diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000000000..d1261f04b8255 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,781 @@ +############################################################# +# WARNING: automatically generated file, DO NOT CHANGE! # +############################################################# + +# This file was automatically generated by the expand-yaml-anchors tool. The +# source file that generated this one is: +# +# src/ci/github-actions/ci.yml +# +# Once you make changes to that file you need to run: +# +# ./x.py run src/tools/expand-yaml-anchors/ +# +# The CI build will fail if the tool is not run after changes to this file. + +--- +name: CI +"on": + push: + branches: + - auto + - try + - master + pull_request: + branches: + - "**" +jobs: + pr: + name: PR + env: + CI_JOB_NAME: "${{ matrix.name }}" + SCCACHE_BUCKET: rust-lang-gha-caches + TOOLSTATE_REPO: "https://github.com/pietroalbini/rust-toolstate" + if: "github.event_name == 'pull_request'" + strategy: + matrix: + name: + - mingw-check + - x86_64-gnu-llvm-7 + - x86_64-gnu-tools + include: + - name: mingw-check + os: ubuntu-latest-xl + env: {} + - name: x86_64-gnu-llvm-7 + os: ubuntu-latest-xl + env: {} + - name: x86_64-gnu-tools + env: + CI_ONLY_WHEN_SUBMODULES_CHANGED: 1 + os: ubuntu-latest-xl + timeout-minutes: 600 + runs-on: "${{ matrix.os }}" + steps: + - name: disable git crlf conversion + run: git config --global core.autocrlf false + shell: bash + - name: checkout the source code + uses: actions/checkout@v1 + with: + fetch-depth: 2 + - name: configure GitHub Actions to kill the build when outdated + uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master + with: + github_token: "${{ secrets.github_token }}" + if: success() && !env.SKIP_JOB + - name: add extra environment variables + run: src/ci/scripts/setup-environment.sh + env: + EXTRA_VARIABLES: "${{ toJson(matrix.env) }}" + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: decide whether to skip this job + run: src/ci/scripts/should-skip-this.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: collect CPU statistics + run: src/ci/scripts/collect-cpu-stats.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: show the current environment + run: src/ci/scripts/dump-environment.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install awscli + run: src/ci/scripts/install-awscli.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install sccache + run: src/ci/scripts/install-sccache.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install clang + run: src/ci/scripts/install-clang.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install WIX + run: src/ci/scripts/install-wix.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install InnoSetup + run: src/ci/scripts/install-innosetup.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: ensure the build happens on a partition with enough space + run: src/ci/scripts/symlink-build-dir.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: disable git crlf conversion + run: src/ci/scripts/disable-git-crlf-conversion.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install MSYS2 + run: src/ci/scripts/install-msys2.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install MSYS2 packages + run: src/ci/scripts/install-msys2-packages.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install MinGW + run: src/ci/scripts/install-mingw.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install ninja + run: src/ci/scripts/install-ninja.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: enable ipv6 on Docker + run: src/ci/scripts/enable-docker-ipv6.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: disable git crlf conversion + run: src/ci/scripts/disable-git-crlf-conversion.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: checkout submodules + run: src/ci/scripts/checkout-submodules.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: ensure line endings are correct + run: src/ci/scripts/verify-line-endings.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: run the build + run: src/ci/scripts/run-build-from-ci.sh + env: + AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}" + AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}" + TOOLSTATE_REPO_ACCESS_TOKEN: "${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}" + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: upload artifacts to S3 + run: src/ci/scripts/upload-artifacts.sh + env: + AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}" + AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}" + if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')" + shell: "python src/ci/exec-with-shell.py {0}" + try: + name: try + env: + CI_JOB_NAME: "${{ matrix.name }}" + SCCACHE_BUCKET: rust-lang-gha-caches + DEPLOY_BUCKET: rust-lang-gha + TOOLSTATE_REPO: "https://github.com/pietroalbini/rust-toolstate" + TOOLSTATE_ISSUES_API_URL: "https://api.github.com/repos/pietroalbini/rust-toolstate/issues" + TOOLSTATE_PUBLISH: 1 + CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZOMUQATD5 + ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZH5AYXDVF + if: "github.event_name == 'push' && github.ref == 'refs/heads/try' && github.repository == 'rust-lang-ci/rust'" + strategy: + matrix: + name: + - dist-x86_64-linux + - dist-x86_64-linux-alt + include: + - name: dist-x86_64-linux + os: ubuntu-latest-xl + env: {} + - name: dist-x86_64-linux-alt + env: + IMAGE: dist-x86_64-linux + os: ubuntu-latest-xl + timeout-minutes: 600 + runs-on: "${{ matrix.os }}" + steps: + - name: disable git crlf conversion + run: git config --global core.autocrlf false + shell: bash + - name: checkout the source code + uses: actions/checkout@v1 + with: + fetch-depth: 2 + - name: configure GitHub Actions to kill the build when outdated + uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master + with: + github_token: "${{ secrets.github_token }}" + if: success() && !env.SKIP_JOB + - name: add extra environment variables + run: src/ci/scripts/setup-environment.sh + env: + EXTRA_VARIABLES: "${{ toJson(matrix.env) }}" + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: decide whether to skip this job + run: src/ci/scripts/should-skip-this.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: collect CPU statistics + run: src/ci/scripts/collect-cpu-stats.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: show the current environment + run: src/ci/scripts/dump-environment.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install awscli + run: src/ci/scripts/install-awscli.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install sccache + run: src/ci/scripts/install-sccache.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install clang + run: src/ci/scripts/install-clang.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install WIX + run: src/ci/scripts/install-wix.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install InnoSetup + run: src/ci/scripts/install-innosetup.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: ensure the build happens on a partition with enough space + run: src/ci/scripts/symlink-build-dir.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: disable git crlf conversion + run: src/ci/scripts/disable-git-crlf-conversion.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install MSYS2 + run: src/ci/scripts/install-msys2.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install MSYS2 packages + run: src/ci/scripts/install-msys2-packages.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install MinGW + run: src/ci/scripts/install-mingw.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install ninja + run: src/ci/scripts/install-ninja.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: enable ipv6 on Docker + run: src/ci/scripts/enable-docker-ipv6.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: disable git crlf conversion + run: src/ci/scripts/disable-git-crlf-conversion.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: checkout submodules + run: src/ci/scripts/checkout-submodules.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: ensure line endings are correct + run: src/ci/scripts/verify-line-endings.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: run the build + run: src/ci/scripts/run-build-from-ci.sh + env: + AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}" + AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}" + TOOLSTATE_REPO_ACCESS_TOKEN: "${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}" + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: upload artifacts to S3 + run: src/ci/scripts/upload-artifacts.sh + env: + AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}" + AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}" + if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')" + shell: "python src/ci/exec-with-shell.py {0}" + auto: + name: auto + env: + CI_JOB_NAME: "${{ matrix.name }}" + SCCACHE_BUCKET: rust-lang-gha-caches + DEPLOY_BUCKET: rust-lang-gha + TOOLSTATE_REPO: "https://github.com/pietroalbini/rust-toolstate" + TOOLSTATE_ISSUES_API_URL: "https://api.github.com/repos/pietroalbini/rust-toolstate/issues" + TOOLSTATE_PUBLISH: 1 + CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZOMUQATD5 + ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZH5AYXDVF + if: "github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'" + strategy: + matrix: + name: + - arm-android + - armhf-gnu + - dist-aarch64-linux + - dist-android + - dist-arm-linux + - dist-armhf-linux + - dist-armv7-linux + - dist-i586-gnu-i586-i686-musl + - dist-i686-freebsd + - dist-i686-linux + - dist-i686-mingw + - dist-i686-msvc + - dist-mips-linux + - dist-mips64-linux + - dist-mips64el-linux + - dist-mipsel-linux + - dist-powerpc-linux + - dist-powerpc64-linux + - dist-powerpc64le-linux + - dist-s390x-linux + - dist-various-1 + - dist-various-2 + - dist-x86_64-apple + - dist-x86_64-apple-alt + - dist-x86_64-freebsd + - dist-x86_64-linux + - dist-x86_64-linux-alt + - dist-x86_64-mingw + - dist-x86_64-msvc + - dist-x86_64-msvc-alt + - dist-x86_64-musl + - dist-x86_64-netbsd + - i686-gnu + - i686-gnu-nopt + - i686-mingw-1 + - i686-mingw-2 + - i686-msvc-1 + - i686-msvc-2 + - mingw-check + - test-various + - wasm32 + - x86_64-apple + - x86_64-gnu + - x86_64-gnu-aux + - x86_64-gnu-debug + - x86_64-gnu-distcheck + - x86_64-gnu-full-bootstrap + - x86_64-gnu-llvm-7 + - x86_64-gnu-nopt + - x86_64-gnu-tools + - x86_64-mingw-1 + - x86_64-mingw-2 + - x86_64-msvc-1 + - x86_64-msvc-2 + - x86_64-msvc-aux + - x86_64-msvc-cargo + - x86_64-msvc-tools + include: + - name: arm-android + os: ubuntu-latest-xl + env: {} + - name: armhf-gnu + os: ubuntu-latest-xl + env: {} + - name: dist-aarch64-linux + os: ubuntu-latest-xl + env: {} + - name: dist-android + os: ubuntu-latest-xl + env: {} + - name: dist-arm-linux + os: ubuntu-latest-xl + env: {} + - name: dist-armhf-linux + os: ubuntu-latest-xl + env: {} + - name: dist-armv7-linux + os: ubuntu-latest-xl + env: {} + - name: dist-i586-gnu-i586-i686-musl + os: ubuntu-latest-xl + env: {} + - name: dist-i686-freebsd + os: ubuntu-latest-xl + env: {} + - name: dist-i686-linux + os: ubuntu-latest-xl + env: {} + - name: dist-mips-linux + os: ubuntu-latest-xl + env: {} + - name: dist-mips64-linux + os: ubuntu-latest-xl + env: {} + - name: dist-mips64el-linux + os: ubuntu-latest-xl + env: {} + - name: dist-mipsel-linux + os: ubuntu-latest-xl + env: {} + - name: dist-powerpc-linux + os: ubuntu-latest-xl + env: {} + - name: dist-powerpc64-linux + os: ubuntu-latest-xl + env: {} + - name: dist-powerpc64le-linux + os: ubuntu-latest-xl + env: {} + - name: dist-s390x-linux + os: ubuntu-latest-xl + env: {} + - name: dist-various-1 + os: ubuntu-latest-xl + env: {} + - name: dist-various-2 + os: ubuntu-latest-xl + env: {} + - name: dist-x86_64-freebsd + os: ubuntu-latest-xl + env: {} + - name: dist-x86_64-linux + os: ubuntu-latest-xl + env: {} + - name: dist-x86_64-linux-alt + env: + IMAGE: dist-x86_64-linux + os: ubuntu-latest-xl + - name: dist-x86_64-musl + os: ubuntu-latest-xl + env: {} + - name: dist-x86_64-netbsd + os: ubuntu-latest-xl + env: {} + - name: i686-gnu + os: ubuntu-latest-xl + env: {} + - name: i686-gnu-nopt + os: ubuntu-latest-xl + env: {} + - name: mingw-check + os: ubuntu-latest-xl + env: {} + - name: test-various + os: ubuntu-latest-xl + env: {} + - name: wasm32 + os: ubuntu-latest-xl + env: {} + - name: x86_64-gnu + os: ubuntu-latest-xl + env: {} + - name: x86_64-gnu-aux + os: ubuntu-latest-xl + env: {} + - name: x86_64-gnu-debug + os: ubuntu-latest-xl + env: {} + - name: x86_64-gnu-distcheck + os: ubuntu-latest-xl + env: {} + - name: x86_64-gnu-full-bootstrap + os: ubuntu-latest-xl + env: {} + - name: x86_64-gnu-llvm-7 + env: + RUST_BACKTRACE: 1 + os: ubuntu-latest-xl + - name: x86_64-gnu-nopt + os: ubuntu-latest-xl + env: {} + - name: x86_64-gnu-tools + env: + DEPLOY_TOOLSTATES_JSON: toolstates-linux.json + os: ubuntu-latest-xl + - name: dist-x86_64-apple + env: + SCRIPT: "./x.py dist" + RUST_CONFIGURE_ARGS: "--target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc" + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + DIST_REQUIRE_ALL_TOOLS: 1 + os: macos-latest + - name: dist-x86_64-apple-alt + env: + SCRIPT: "./x.py dist" + RUST_CONFIGURE_ARGS: "--enable-extended --enable-profiler --set rust.jemalloc" + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + os: macos-latest + - name: x86_64-apple + env: + SCRIPT: "./x.py test" + RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc" + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + os: macos-latest + - name: x86_64-msvc-1 + env: + RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler" + SCRIPT: make ci-subset-1 + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + os: windows-latest-xl + - name: x86_64-msvc-2 + env: + RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler" + SCRIPT: make ci-subset-2 + os: windows-latest-xl + - name: i686-msvc-1 + env: + RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-msvc" + SCRIPT: make ci-subset-1 + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + os: windows-latest-xl + - name: i686-msvc-2 + env: + RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-msvc" + SCRIPT: make ci-subset-2 + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + os: windows-latest-xl + - name: x86_64-msvc-aux + env: + RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1 + RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc" + os: windows-latest-xl + - name: x86_64-msvc-cargo + env: + SCRIPT: python x.py test src/tools/cargotest src/tools/cargo + RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc" + VCVARS_BAT: vcvars64.bat + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + os: windows-latest-xl + - name: x86_64-msvc-tools + env: + SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstate/toolstates.json windows + RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstate/toolstates.json" + os: windows-latest-xl + - name: i686-mingw-1 + env: + RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-gnu" + SCRIPT: make ci-mingw-subset-1 + CUSTOM_MINGW: 1 + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + os: windows-latest-xl + - name: i686-mingw-2 + env: + RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-gnu" + SCRIPT: make ci-mingw-subset-2 + CUSTOM_MINGW: 1 + os: windows-latest-xl + - name: x86_64-mingw-1 + env: + SCRIPT: make ci-mingw-subset-1 + RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-gnu" + CUSTOM_MINGW: 1 + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + os: windows-latest-xl + - name: x86_64-mingw-2 + env: + SCRIPT: make ci-mingw-subset-2 + RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-gnu" + CUSTOM_MINGW: 1 + os: windows-latest-xl + - name: dist-x86_64-msvc + env: + RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --target=x86_64-pc-windows-msvc,aarch64-pc-windows-msvc --enable-full-tools --enable-profiler" + SCRIPT: python x.py dist + DIST_REQUIRE_ALL_TOOLS: 1 + os: windows-latest-xl + - name: dist-i686-msvc + env: + RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-msvc --target=i586-pc-windows-msvc --enable-full-tools --enable-profiler" + SCRIPT: python x.py dist + DIST_REQUIRE_ALL_TOOLS: 1 + os: windows-latest-xl + - name: dist-i686-mingw + env: + RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-gnu --enable-full-tools --enable-profiler" + SCRIPT: python x.py dist + CUSTOM_MINGW: 1 + DIST_REQUIRE_ALL_TOOLS: 1 + os: windows-latest-xl + - name: dist-x86_64-mingw + env: + SCRIPT: python x.py dist + RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-gnu --enable-full-tools --enable-profiler" + CUSTOM_MINGW: 1 + DIST_REQUIRE_ALL_TOOLS: 1 + os: windows-latest-xl + - name: dist-x86_64-msvc-alt + env: + RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-extended --enable-profiler" + SCRIPT: python x.py dist + os: windows-latest-xl + timeout-minutes: 600 + runs-on: "${{ matrix.os }}" + steps: + - name: disable git crlf conversion + run: git config --global core.autocrlf false + shell: bash + - name: checkout the source code + uses: actions/checkout@v1 + with: + fetch-depth: 2 + - name: configure GitHub Actions to kill the build when outdated + uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master + with: + github_token: "${{ secrets.github_token }}" + if: success() && !env.SKIP_JOB + - name: add extra environment variables + run: src/ci/scripts/setup-environment.sh + env: + EXTRA_VARIABLES: "${{ toJson(matrix.env) }}" + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: decide whether to skip this job + run: src/ci/scripts/should-skip-this.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: collect CPU statistics + run: src/ci/scripts/collect-cpu-stats.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: show the current environment + run: src/ci/scripts/dump-environment.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install awscli + run: src/ci/scripts/install-awscli.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install sccache + run: src/ci/scripts/install-sccache.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install clang + run: src/ci/scripts/install-clang.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install WIX + run: src/ci/scripts/install-wix.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install InnoSetup + run: src/ci/scripts/install-innosetup.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: ensure the build happens on a partition with enough space + run: src/ci/scripts/symlink-build-dir.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: disable git crlf conversion + run: src/ci/scripts/disable-git-crlf-conversion.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install MSYS2 + run: src/ci/scripts/install-msys2.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install MSYS2 packages + run: src/ci/scripts/install-msys2-packages.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install MinGW + run: src/ci/scripts/install-mingw.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: install ninja + run: src/ci/scripts/install-ninja.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: enable ipv6 on Docker + run: src/ci/scripts/enable-docker-ipv6.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: disable git crlf conversion + run: src/ci/scripts/disable-git-crlf-conversion.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: checkout submodules + run: src/ci/scripts/checkout-submodules.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: ensure line endings are correct + run: src/ci/scripts/verify-line-endings.sh + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: run the build + run: src/ci/scripts/run-build-from-ci.sh + env: + AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}" + AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}" + TOOLSTATE_REPO_ACCESS_TOKEN: "${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}" + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + - name: upload artifacts to S3 + run: src/ci/scripts/upload-artifacts.sh + env: + AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}" + AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}" + if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')" + shell: "python src/ci/exec-with-shell.py {0}" + master: + name: master + runs-on: ubuntu-latest + env: + SCCACHE_BUCKET: rust-lang-gha-caches + DEPLOY_BUCKET: rust-lang-gha + TOOLSTATE_REPO: "https://github.com/pietroalbini/rust-toolstate" + TOOLSTATE_ISSUES_API_URL: "https://api.github.com/repos/pietroalbini/rust-toolstate/issues" + TOOLSTATE_PUBLISH: 1 + CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZOMUQATD5 + ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZH5AYXDVF + if: "github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'rust-lang-ci/rust'" + steps: + - name: checkout the source code + uses: actions/checkout@v1 + with: + fetch-depth: 2 + - name: publish toolstate + run: src/ci/publish_toolstate.sh + env: + TOOLSTATE_REPO_ACCESS_TOKEN: "${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}" + shell: "python src/ci/exec-with-shell.py {0}" + if: success() && !env.SKIP_JOB + try-success: + needs: + - try + if: "success() && github.event_name == 'push' && github.ref == 'refs/heads/try' && github.repository == 'rust-lang-ci/rust'" + steps: + - name: mark the job as a success + run: exit 0 + name: bors build finished + runs-on: ubuntu-latest + try-failure: + needs: + - try + if: "!success() && github.event_name == 'push' && github.ref == 'refs/heads/try' && github.repository == 'rust-lang-ci/rust'" + steps: + - name: mark the job as a failure + run: exit 1 + name: bors build finished + runs-on: ubuntu-latest + auto-success: + needs: + - auto + if: "success() && github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'" + steps: + - name: mark the job as a success + run: exit 0 + name: bors build finished + runs-on: ubuntu-latest + auto-failure: + needs: + - auto + if: "!success() && github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'" + steps: + - name: mark the job as a failure + run: exit 1 + name: bors build finished + runs-on: ubuntu-latest diff --git a/.gitignore b/.gitignore index d9761ce40927c..856ff7dbb0f33 100644 --- a/.gitignore +++ b/.gitignore @@ -35,7 +35,7 @@ __pycache__/ /obj/ /rustllvm/ /unicode-downloads -/target/ +/target # Generated by compiletest for incremental: /tmp/ tags diff --git a/.mailmap b/.mailmap index ea8ef0eebf9a1..78c3c3019af50 100644 --- a/.mailmap +++ b/.mailmap @@ -172,6 +172,9 @@ Mateusz Mikuła Mateusz Mikuła Matt Brubeck Matthew Auld +Matthew Kraai +Matthew Kraai +Matthew Kraai Matthew McPherrin Matthijs Hofstra Melody Horn diff --git a/Cargo.lock b/Cargo.lock index aefd40bfaa59e..854b5478579b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -121,9 +121,9 @@ checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" [[package]] name = "backtrace" -version = "0.3.44" +version = "0.3.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4036b9bf40f3cf16aba72a3d65e8a520fc4bafcdc7079aea8f848c58c5b5536" +checksum = "b1e692897359247cc6bb902933361652380af0f1b7651ae5c5013407f30e109e" dependencies = [ "backtrace-sys", "cfg-if", @@ -135,9 +135,9 @@ dependencies = [ [[package]] name = "backtrace-sys" -version = "0.1.32" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" +checksum = "7de8aba10a69c8e8d7622c5710229485ec32e9d55fdad160ea559c086fdcd118" dependencies = [ "cc", "compiler_builtins", @@ -281,7 +281,7 @@ dependencies = [ [[package]] name = "cargo" -version = "0.44.0" +version = "0.45.0" dependencies = [ "anyhow", "atty", @@ -292,7 +292,6 @@ dependencies = [ "clap", "core-foundation 0.7.0", "crates-io", - "crossbeam-channel", "crossbeam-utils 0.7.0", "crypto-hash", "curl", @@ -300,7 +299,7 @@ dependencies = [ "env_logger 0.7.1", "filetime", "flate2", - "fs2", + "fs3", "fwdansi", "git2", "git2-curl", @@ -338,6 +337,7 @@ dependencies = [ "termcolor", "toml", "unicode-width", + "unicode-xid 0.2.0", "url 2.1.0", "walkdir", "winapi 0.3.8", @@ -386,9 +386,9 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d2d1617e838936c0d2323a65cc151e03ae19a7678dd24f72bccf27119b90a5d" +checksum = "46e3374c604fb39d1a2f35ed5e4a4e30e60d01fab49446e08f1b3e9a90aef202" dependencies = [ "semver", "serde", @@ -443,19 +443,18 @@ dependencies = [ "textwrap", "unicode-width", "vec_map", - "yaml-rust", + "yaml-rust 0.3.5", ] [[package]] name = "clippy" version = "0.0.212" dependencies = [ - "cargo_metadata 0.9.0", + "cargo_metadata 0.9.1", "clippy-mini-macro-test", "clippy_lints", "compiletest_rs", "derive-new", - "git2", "lazy_static 1.4.0", "regex", "rustc-workspace-hack", @@ -474,9 +473,9 @@ version = "0.2.0" name = "clippy_lints" version = "0.0.212" dependencies = [ - "cargo_metadata 0.9.0", + "cargo_metadata 0.9.1", "if_chain", - "itertools 0.8.0", + "itertools 0.9.0", "lazy_static 1.4.0", "matches", "pulldown-cmark 0.7.0", @@ -1027,6 +1026,14 @@ dependencies = [ "walkdir", ] +[[package]] +name = "expand-yaml-anchors" +version = "0.1.0" +dependencies = [ + "yaml-merge-keys", + "yaml-rust 0.4.3", +] + [[package]] name = "failure" version = "0.1.5" @@ -1058,8 +1065,7 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "filetime" version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ff6d4dab0aa0c8e6346d46052e93b13a16cf847b54ed357087c35011048cc7d" +source = "git+https://github.com/alexcrichton/filetime.git?rev=937aa81f320078ba76021ec112df2e01671f58d8#937aa81f320078ba76021ec112df2e01671f58d8" dependencies = [ "cfg-if", "libc", @@ -1120,10 +1126,10 @@ dependencies = [ ] [[package]] -name = "fs2" -version = "0.4.3" +name = "fs3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +checksum = "e1414bd2d0abf7a529ec14e262441fb58b436fb4eac619b151086a338e3f2514" dependencies = [ "libc", "winapi 0.3.8", @@ -1235,9 +1241,9 @@ dependencies = [ [[package]] name = "git2" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26e07ef27260a78f7e8d218ebac2c72f2c4db50493741b190b6e8eade1da7c68" +checksum = "b7da16ceafe24cedd9ba02c4463a2b506b6493baf4317c79c5acb553134a3c15" dependencies = [ "bitflags", "libc", @@ -1250,9 +1256,9 @@ dependencies = [ [[package]] name = "git2-curl" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1754ec4170e7dcaf9bb43743bb16eddb8d827b2e0291deb6f220a6e16fe46a" +checksum = "502d532a2d06184beb3bc869d4d90236e60934e3382c921b203fa3c33e212bd7" dependencies = [ "curl", "git2", @@ -1604,6 +1610,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "0.4.4" @@ -1761,18 +1776,16 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" [[package]] name = "libc" -version = "0.2.66" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" +checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" dependencies = [ "rustc-std-workspace-core", ] [[package]] name = "libgit2-sys" -version = "0.11.0+0.99.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d5d1459353d397a029fb18862166338de938e6be976606bd056cf8f1a912ecf" +version = "0.12.0+0.99.0" dependencies = [ "cc", "libc", @@ -1822,6 +1835,12 @@ dependencies = [ name = "linkchecker" version = "0.1.0" +[[package]] +name = "linked-hash-map" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" + [[package]] name = "lock_api" version = "0.3.1" @@ -2124,7 +2143,7 @@ name = "miri" version = "0.1.0" dependencies = [ "byteorder", - "cargo_metadata 0.9.0", + "cargo_metadata 0.9.1", "colored", "compiletest_rs", "directories", @@ -2250,9 +2269,7 @@ checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" [[package]] name = "openssl-src" -version = "111.6.1+1.1.1d" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91b04cb43c1a8a90e934e0cd612e2a5715d976d2d6cff4490278a0cddf35005" +version = "111.7.0+1.1.1e" dependencies = [ "cc", ] @@ -3108,6 +3125,7 @@ dependencies = [ "rustc_hir", "rustc_index", "rustc_macros", + "rustc_query_system", "rustc_session", "rustc_span", "rustc_target", @@ -3469,8 +3487,8 @@ dependencies = [ name = "rustc_ast_lowering" version = "0.0.0" dependencies = [ + "arena", "log", - "rustc", "rustc_ast", "rustc_ast_pretty", "rustc_data_structures", @@ -3559,7 +3577,6 @@ dependencies = [ "rustc_ast", "rustc_attr", "rustc_codegen_ssa", - "rustc_codegen_utils", "rustc_data_structures", "rustc_errors", "rustc_feature", @@ -3590,36 +3607,21 @@ dependencies = [ "rustc_apfloat", "rustc_ast", "rustc_attr", - "rustc_codegen_utils", "rustc_data_structures", "rustc_errors", "rustc_fs_util", "rustc_hir", "rustc_incremental", "rustc_index", + "rustc_metadata", "rustc_session", "rustc_span", + "rustc_symbol_mangling", "rustc_target", "serialize", "tempfile", ] -[[package]] -name = "rustc_codegen_utils" -version = "0.0.0" -dependencies = [ - "log", - "punycode", - "rustc", - "rustc-demangle", - "rustc_ast", - "rustc_data_structures", - "rustc_hir", - "rustc_metadata", - "rustc_span", - "rustc_target", -] - [[package]] name = "rustc_data_structures" version = "0.0.0" @@ -3656,7 +3658,6 @@ dependencies = [ "rustc_ast", "rustc_ast_pretty", "rustc_codegen_ssa", - "rustc_codegen_utils", "rustc_data_structures", "rustc_error_codes", "rustc_errors", @@ -3669,6 +3670,7 @@ dependencies = [ "rustc_parse", "rustc_plugin_impl", "rustc_save_analysis", + "rustc_session", "rustc_span", "rustc_target", "serialize", @@ -3733,6 +3735,7 @@ name = "rustc_hir" version = "0.0.0" dependencies = [ "lazy_static 1.4.0", + "log", "rustc_ast", "rustc_ast_pretty", "rustc_data_structures", @@ -3774,14 +3777,11 @@ dependencies = [ name = "rustc_infer" version = "0.0.0" dependencies = [ - "fmt_macros", "graphviz", "log", "rustc", "rustc_ast", - "rustc_attr", "rustc_data_structures", - "rustc_error_codes", "rustc_errors", "rustc_hir", "rustc_index", @@ -3807,7 +3807,6 @@ dependencies = [ "rustc_builtin_macros", "rustc_codegen_llvm", "rustc_codegen_ssa", - "rustc_codegen_utils", "rustc_data_structures", "rustc_errors", "rustc_expand", @@ -3825,7 +3824,9 @@ dependencies = [ "rustc_resolve", "rustc_session", "rustc_span", + "rustc_symbol_mangling", "rustc_target", + "rustc_trait_selection", "rustc_traits", "rustc_ty", "rustc_typeck", @@ -3860,6 +3861,7 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", + "rustc_trait_selection", "unicode-security", ] @@ -3897,6 +3899,7 @@ dependencies = [ "rustc_expand", "rustc_hir", "rustc_index", + "rustc_session", "rustc_span", "rustc_target", "serialize", @@ -3927,8 +3930,10 @@ dependencies = [ "rustc_infer", "rustc_lexer", "rustc_macros", + "rustc_session", "rustc_span", "rustc_target", + "rustc_trait_selection", "serialize", "smallvec 1.0.0", ] @@ -3952,6 +3957,7 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", + "rustc_trait_selection", "serialize", "smallvec 1.0.0", ] @@ -3992,6 +3998,7 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", + "rustc_trait_selection", ] [[package]] @@ -4004,6 +4011,7 @@ dependencies = [ "rustc_hir", "rustc_lint", "rustc_metadata", + "rustc_session", "rustc_span", ] @@ -4018,10 +4026,27 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_hir", + "rustc_session", "rustc_span", "rustc_typeck", ] +[[package]] +name = "rustc_query_system" +version = "0.0.0" +dependencies = [ + "log", + "parking_lot 0.9.0", + "rustc_ast", + "rustc_data_structures", + "rustc_errors", + "rustc_hir", + "rustc_index", + "rustc_macros", + "serialize", + "smallvec 1.0.0", +] + [[package]] name = "rustc_resolve" version = "0.0.0" @@ -4039,7 +4064,6 @@ dependencies = [ "rustc_expand", "rustc_feature", "rustc_hir", - "rustc_infer", "rustc_metadata", "rustc_session", "rustc_span", @@ -4056,10 +4080,10 @@ dependencies = [ "rustc", "rustc_ast", "rustc_ast_pretty", - "rustc_codegen_utils", "rustc_data_structures", "rustc_hir", "rustc_parse", + "rustc_session", "rustc_span", "serde_json", ] @@ -4096,6 +4120,23 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "rustc_symbol_mangling" +version = "0.0.0" +dependencies = [ + "log", + "punycode", + "rustc", + "rustc-demangle", + "rustc_ast", + "rustc_data_structures", + "rustc_hir", + "rustc_metadata", + "rustc_session", + "rustc_span", + "rustc_target", +] + [[package]] name = "rustc_target" version = "0.0.0" @@ -4119,6 +4160,27 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b725dadae9fabc488df69a287f5a99c5eaf5d10853842a8a3dfac52476f544ee" +[[package]] +name = "rustc_trait_selection" +version = "0.0.0" +dependencies = [ + "fmt_macros", + "log", + "rustc", + "rustc_ast", + "rustc_attr", + "rustc_data_structures", + "rustc_errors", + "rustc_hir", + "rustc_index", + "rustc_infer", + "rustc_macros", + "rustc_session", + "rustc_span", + "rustc_target", + "smallvec 1.0.0", +] + [[package]] name = "rustc_traits" version = "0.0.0" @@ -4132,6 +4194,7 @@ dependencies = [ "rustc_macros", "rustc_span", "rustc_target", + "rustc_trait_selection", "smallvec 1.0.0", ] @@ -4144,8 +4207,10 @@ dependencies = [ "rustc_data_structures", "rustc_hir", "rustc_infer", + "rustc_session", "rustc_span", "rustc_target", + "rustc_trait_selection", ] [[package]] @@ -4162,8 +4227,10 @@ dependencies = [ "rustc_hir", "rustc_index", "rustc_infer", + "rustc_session", "rustc_span", "rustc_target", + "rustc_trait_selection", "smallvec 1.0.0", ] @@ -4494,8 +4561,7 @@ checksum = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86" [[package]] name = "socket2" version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85" +source = "git+https://github.com/alexcrichton/socket2-rs.git?rev=230d413459911812bb9647b697b681217aae008d#230d413459911812bb9647b697b681217aae008d" dependencies = [ "cfg-if", "libc", @@ -4796,6 +4862,26 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "thiserror" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fb62ff737e573b1e677459bea6fd023cd5d6e868c3242d3cdf3ef2f0554824" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24069c0ba08aab54289d6a25f5036d94afc61e1538bbc42ae5501df141c9027d" +dependencies = [ + "proc-macro2 1.0.3", + "quote 1.0.2", + "syn 1.0.11", +] + [[package]] name = "thread_local" version = "0.3.6" @@ -4818,10 +4904,9 @@ dependencies = [ name = "tidy" version = "0.1.0" dependencies = [ + "cargo_metadata 0.9.1", "lazy_static 1.4.0", "regex", - "serde", - "serde_json", "walkdir", ] @@ -5479,8 +5564,28 @@ dependencies = [ "lzma-sys", ] +[[package]] +name = "yaml-merge-keys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59893318ba3ad2b704498c7761214a10eaf42c5f838bce9fc0145bf2ba658cfa" +dependencies = [ + "lazy_static 1.4.0", + "thiserror", + "yaml-rust 0.4.3", +] + [[package]] name = "yaml-rust" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" + +[[package]] +name = "yaml-rust" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" +dependencies = [ + "linked-hash-map", +] diff --git a/Cargo.toml b/Cargo.toml index 2f5a708e8dc6c..818455e1d834e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ members = [ "src/tools/miri", "src/tools/rustdoc-themes", "src/tools/unicode-table-generator", + "src/tools/expand-yaml-anchors", ] exclude = [ "build", @@ -54,6 +55,15 @@ cargo = { path = "src/tools/cargo" } # `rustfmt` executable are the same exact version). rustfmt-nightly = { path = "src/tools/rustfmt" } +# Temporary cargo fixes +#fs3 = { git = "https://github.com/oxidecomputer/fs3-rs.git", branch = "master" } +socket2 = { git = "https://github.com/alexcrichton/socket2-rs.git", rev = "230d413459911812bb9647b697b681217aae008d" } +filetime = { git = "https://github.com/alexcrichton/filetime.git", rev = "937aa81f320078ba76021ec112df2e01671f58d8" } +#git2 = { git = "https://github.com/pfmooney/git2-rs.git", branch = "illumos-target" } +libgit2-sys = { path = "git2-rs/libgit2-sys" } +#openssl-src = { git = "https://github.com/pfmooney/openssl-src-rs", branch = "illumos-target" } +openssl-src = { path = "openssl-src" } + # See comments in `src/tools/rustc-workspace-hack/README.md` for what's going on # here rustc-workspace-hack = { path = 'src/tools/rustc-workspace-hack' } diff --git a/RELEASES.md b/RELEASES.md index 7e18f1befddec..9ff0d14b353cd 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -4838,7 +4838,6 @@ Version 1.11.0 (2016-08-18) Language -------- -* [`cfg_attr` works on `path` attributes](https://github.com/rust-lang/rust/pull/34546) * [Support nested `cfg_attr` attributes](https://github.com/rust-lang/rust/pull/34216) * [Allow statement-generating braced macro invocations at the end of blocks](https://github.com/rust-lang/rust/pull/34436) * [Macros can be expanded inside of trait definitions](https://github.com/rust-lang/rust/pull/34213) @@ -4957,8 +4956,6 @@ Version 1.10.0 (2016-07-07) Language -------- -* [Allow `concat_idents!` in type positions as well as in expression - positions](https://github.com/rust-lang/rust/pull/33735). * [`Copy` types are required to have a trivial implementation of `Clone`](https://github.com/rust-lang/rust/pull/33420). [RFC 1521](https://github.com/rust-lang/rfcs/blob/master/text/1521-copy-clone-semantics.md). * [Single-variant enums support the `#[repr(..)]` attribute](https://github.com/rust-lang/rust/pull/33355). diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs index 04345867bf5c1..ba644e6111827 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/bin/rustdoc.rs @@ -52,12 +52,7 @@ fn main() { // Bootstrap's Cargo-command builder sets this variable to the current Rust version; let's pick // it up so we can make rustdoc print this into the docs if let Some(version) = env::var_os("RUSTDOC_CRATE_VERSION") { - // This "unstable-options" can be removed when `--crate-version` is stabilized - if !has_unstable { - cmd.arg("-Z").arg("unstable-options"); - } cmd.arg("--crate-version").arg(version); - has_unstable = true; } // Needed to be able to run all rustdoc tests. diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 50e1726240fff..d5efed61b541e 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -664,6 +664,10 @@ def build_bootstrap(self): if self.clean and os.path.exists(build_dir): shutil.rmtree(build_dir) env = os.environ.copy() + # `CARGO_BUILD_TARGET` breaks bootstrap build. + # See also: . + if "CARGO_BUILD_TARGET" in env: + del env["CARGO_BUILD_TARGET"] env["RUSTC_BOOTSTRAP"] = '1' env["CARGO_TARGET_DIR"] = build_dir env["RUSTC"] = self.rustc() diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index e4b57cddfb891..243cd3fa19998 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -11,7 +11,7 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::time::{Duration, Instant}; -use build_helper::t; +use build_helper::{output, t}; use crate::cache::{Cache, Interned, INTERNER}; use crate::check; @@ -21,9 +21,10 @@ use crate::doc; use crate::flags::Subcommand; use crate::install; use crate::native; +use crate::run; use crate::test; use crate::tool; -use crate::util::{self, add_lib_path, exe, libdir}; +use crate::util::{self, add_dylib_path, add_link_lib_path, exe, libdir}; use crate::{Build, DocTests, GitRepo, Mode}; pub use crate::Compiler; @@ -313,6 +314,7 @@ pub enum Kind { Dist, Doc, Install, + Run, } impl<'a> Builder<'a> { @@ -353,6 +355,7 @@ impl<'a> Builder<'a> { } Kind::Test => describe!( crate::toolstate::ToolStateCheck, + test::ExpandYamlAnchors, test::Tidy, test::Ui, test::CompileFail, @@ -454,6 +457,7 @@ impl<'a> Builder<'a> { install::Src, install::Rustc ), + Kind::Run => describe!(run::ExpandYamlAnchors,), } } @@ -507,6 +511,7 @@ impl<'a> Builder<'a> { Subcommand::Bench { ref paths, .. } => (Kind::Bench, &paths[..]), Subcommand::Dist { ref paths } => (Kind::Dist, &paths[..]), Subcommand::Install { ref paths } => (Kind::Install, &paths[..]), + Subcommand::Run { ref paths } => (Kind::Run, &paths[..]), Subcommand::Format { .. } | Subcommand::Clean { .. } => panic!(), }; @@ -660,7 +665,7 @@ impl<'a> Builder<'a> { return; } - add_lib_path(vec![self.rustc_libdir(compiler)], &mut cmd.command); + add_dylib_path(vec![self.rustc_libdir(compiler)], &mut cmd.command); } /// Gets a path to the compiler specified. @@ -698,6 +703,20 @@ impl<'a> Builder<'a> { cmd } + /// Return the path to `llvm-config` for the target, if it exists. + /// + /// Note that this returns `None` if LLVM is disabled, or if we're in a + /// check build or dry-run, where there's no need to build all of LLVM. + fn llvm_config(&self, target: Interned) -> Option { + if self.config.llvm_enabled() && self.kind != Kind::Check && !self.config.dry_run { + let llvm_config = self.ensure(native::Llvm { target }); + if llvm_config.is_file() { + return Some(llvm_config); + } + } + None + } + /// Prepares an invocation of `cargo` to be run. /// /// This will create a `Command` that represents a pending execution of @@ -725,7 +744,7 @@ impl<'a> Builder<'a> { self.clear_if_dirty(&my_out, &rustdoc); } - cargo.env("CARGO_TARGET_DIR", &out_dir).arg(cmd).arg("-Zconfig-profile"); + cargo.env("CARGO_TARGET_DIR", &out_dir).arg(cmd); let profile_var = |name: &str| { let profile = if self.config.rust_optimize { "RELEASE" } else { "DEV" }; @@ -847,13 +866,7 @@ impl<'a> Builder<'a> { rustflags.arg("-Zforce-unstable-if-unmarked"); } - // cfg(bootstrap): the flag was renamed from `-Zexternal-macro-backtrace` - // to `-Zmacro-backtrace`, keep only the latter after beta promotion. - if stage == 0 { - rustflags.arg("-Zexternal-macro-backtrace"); - } else { - rustflags.arg("-Zmacro-backtrace"); - } + rustflags.arg("-Zmacro-backtrace"); let want_rustdoc = self.doc_tests != DocTests::No; @@ -1040,6 +1053,17 @@ impl<'a> Builder<'a> { .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_libdir(compiler)); } + // Tools that use compiler libraries may inherit the `-lLLVM` link + // requirement, but the `-L` library path is not propagated across + // separate Cargo projects. We can add LLVM's library path to the + // platform-specific environment variable as a workaround. + if mode == Mode::ToolRustc { + if let Some(llvm_config) = self.llvm_config(target) { + let llvm_libdir = output(Command::new(&llvm_config).arg("--libdir")); + add_link_lib_path(vec![llvm_libdir.trim().into()], &mut cargo); + } + } + if self.config.incremental { cargo.env("CARGO_INCREMENTAL", "1"); } else { diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs index 504cba45570c1..be2b0f36d14a7 100644 --- a/src/bootstrap/channel.rs +++ b/src/bootstrap/channel.rs @@ -13,7 +13,7 @@ use build_helper::output; use crate::Build; // The version number -pub const CFG_RELEASE_NUM: &str = "1.43.0"; +pub const CFG_RELEASE_NUM: &str = "1.44.0"; pub struct GitInfo { inner: Option, diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 65a00db33949e..ad494b88b3af2 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -451,44 +451,6 @@ impl Step for Rustc { false, ); - // We used to build librustc_codegen_llvm as a separate step, - // which produced a dylib that the compiler would dlopen() at runtime. - // This meant that we only needed to make sure that libLLVM.so was - // installed by the time we went to run a tool using it - since - // librustc_codegen_llvm was effectively a standalone artifact, - // other crates were completely oblivious to its dependency - // on `libLLVM.so` during build time. - // - // However, librustc_codegen_llvm is now built as an ordinary - // crate during the same step as the rest of the compiler crates. - // This means that any crates depending on it will see the fact - // that it uses `libLLVM.so` as a native library, and will - // cause us to pass `-llibLLVM.so` to the linker when we link - // a binary. - // - // For `rustc` itself, this works out fine. - // During the `Assemble` step, we call `dist::maybe_install_llvm_dylib` - // to copy libLLVM.so into the `stage` directory. We then link - // the compiler binary, which will find `libLLVM.so` in the correct place. - // - // However, this is insufficient for tools that are build against stage0 - // (e.g. stage1 rustdoc). Since `Assemble` for stage0 doesn't actually do anything, - // we won't have `libLLVM.so` in the stage0 sysroot. In the past, this wasn't - // a problem - we would copy the tool binary into its correct stage directory - // (e.g. stage1 for a stage1 rustdoc built against a stage0 compiler). - // Since libLLVM.so wasn't resolved until runtime, it was fine for it to - // not exist while we were building it. - // - // To ensure that we can still build stage1 tools against a stage0 compiler, - // we explicitly copy libLLVM.so into the stage0 sysroot when building - // the stage0 compiler. This ensures that tools built against stage0 - // will see libLLVM.so at build time, making the linker happy. - if compiler.stage == 0 { - builder.info(&format!("Installing libLLVM.so to stage 0 ({})", compiler.host)); - let sysroot = builder.sysroot(compiler); - dist::maybe_install_llvm_dylib(builder, compiler.host, &sysroot); - } - builder.ensure(RustcLink { compiler: builder.compiler(compiler.stage, builder.config.build), target_compiler: compiler, diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index b0d9a5b94641c..04da3cc1015b8 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -313,6 +313,9 @@ impl Step for Standalone { } let mut cmd = builder.rustdoc_cmd(compiler); + // Needed for --index-page flag + cmd.arg("-Z").arg("unstable-options"); + cmd.arg("--html-after-content") .arg(&footer) .arg("--html-before-content") @@ -395,7 +398,7 @@ impl Step for Std { // Keep a whitelist so we do not build internal stdlib crates, these will be // build by the rustc step later if enabled. - cargo.arg("-Z").arg("unstable-options").arg("-p").arg(package); + cargo.arg("-p").arg(package); // Create all crate output directories first to make sure rustdoc uses // relative links. // FIXME: Cargo should probably do this itself. @@ -406,6 +409,8 @@ impl Step for Std { .arg("rust.css") .arg("--markdown-no-toc") .arg("--generate-redirect-pages") + .arg("-Z") + .arg("unstable-options") .arg("--resource-suffix") .arg(crate::channel::CFG_RELEASE_NUM) .arg("--index-page") diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index d8831c6d9e566..eda26f7df1f1c 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -86,6 +86,9 @@ pub enum Subcommand { Install { paths: Vec, }, + Run { + paths: Vec, + }, } impl Default for Subcommand { @@ -113,6 +116,7 @@ Subcommands: clean Clean out build directories dist Build distribution artifacts install Install distribution artifacts + run Run tools contained in this repository To learn more about a subcommand, run `./x.py -h`", ); @@ -188,6 +192,7 @@ To learn more about a subcommand, run `./x.py -h`", || (s == "clean") || (s == "dist") || (s == "install") + || (s == "run") }); let subcommand = match subcommand { Some(s) => s, @@ -400,6 +405,18 @@ Arguments: ./x.py doc --stage 1", ); } + "run" => { + subcommand_help.push_str( + "\n +Arguments: + This subcommand accepts a number of paths to tools to build and run. For + example: + + ./x.py run src/tool/expand-yaml-anchors + + At least a tool needs to be called.", + ); + } _ => {} }; // Get any optional paths which occur after the subcommand @@ -468,6 +485,13 @@ Arguments: "fmt" => Subcommand::Format { check: matches.opt_present("check") }, "dist" => Subcommand::Dist { paths }, "install" => Subcommand::Install { paths }, + "run" => { + if paths.is_empty() { + println!("\nrun requires at least a path!\n"); + usage(1, &opts, &subcommand_help, &extra_help); + } + Subcommand::Run { paths } + } _ => { usage(1, &opts, &subcommand_help, &extra_help); } diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs index a4acb14ee4b14..1616ae15d31d6 100644 --- a/src/bootstrap/format.rs +++ b/src/bootstrap/format.rs @@ -37,6 +37,9 @@ struct RustfmtConfig { } pub fn format(build: &Build, check: bool) { + if build.config.dry_run { + return; + } let mut builder = ignore::types::TypesBuilder::new(); builder.add_defaults(); builder.select("rust"); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index a476d25f10214..6436fa756558b 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -140,6 +140,7 @@ mod format; mod install; mod metadata; mod native; +mod run; mod sanity; mod test; mod tool; diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index c22c2a336f124..d4d66abd520a1 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -11,6 +11,7 @@ use std::env; use std::ffi::OsString; use std::fs::{self, File}; +use std::io; use std::path::{Path, PathBuf}; use std::process::Command; @@ -54,7 +55,6 @@ impl Step for Llvm { } } - let llvm_info = &builder.in_tree_llvm_info; let root = "src/llvm-project/llvm"; let out_dir = builder.llvm_out(target); let mut llvm_config_ret_dir = builder.llvm_out(builder.config.build); @@ -65,40 +65,35 @@ impl Step for Llvm { let build_llvm_config = llvm_config_ret_dir.join(exe("llvm-config", &*builder.config.build)); - let done_stamp = out_dir.join("llvm-finished-building"); - if done_stamp.exists() { - if builder.config.llvm_skip_rebuild { - builder.info( - "Warning: \ - Using a potentially stale build of LLVM; \ - This may not behave well.", - ); - return build_llvm_config; - } + let stamp = out_dir.join("llvm-finished-building"); + let stamp = HashStamp::new(stamp, builder.in_tree_llvm_info.sha()); - if let Some(llvm_commit) = llvm_info.sha() { - let done_contents = t!(fs::read(&done_stamp)); + if builder.config.llvm_skip_rebuild && stamp.path.exists() { + builder.info( + "Warning: \ + Using a potentially stale build of LLVM; \ + This may not behave well.", + ); + return build_llvm_config; + } - // If LLVM was already built previously and the submodule's commit didn't change - // from the previous build, then no action is required. - if done_contents == llvm_commit.as_bytes() { - return build_llvm_config; - } - } else { + if stamp.is_done() { + if stamp.hash.is_none() { builder.info( "Could not determine the LLVM submodule commit hash. \ Assuming that an LLVM rebuild is not necessary.", ); builder.info(&format!( "To force LLVM to rebuild, remove the file `{}`", - done_stamp.display() + stamp.path.display() )); - return build_llvm_config; } + return build_llvm_config; } builder.info(&format!("Building LLVM for {}", target)); + t!(stamp.remove()); let _time = util::timeit(&builder); t!(fs::create_dir_all(&out_dir)); @@ -271,7 +266,7 @@ impl Step for Llvm { cfg.build(); - t!(fs::write(&done_stamp, llvm_info.sha().unwrap_or(""))); + t!(stamp.write()); build_llvm_config } @@ -584,17 +579,21 @@ impl Step for Sanitizers { return runtimes; } - let done_stamp = out_dir.join("sanitizers-finished-building"); - if done_stamp.exists() { - builder.info(&format!( - "Assuming that sanitizers rebuild is not necessary. \ - To force a rebuild, remove the file `{}`", - done_stamp.display() - )); + let stamp = out_dir.join("sanitizers-finished-building"); + let stamp = HashStamp::new(stamp, builder.in_tree_llvm_info.sha()); + + if stamp.is_done() { + if stamp.hash.is_none() { + builder.info(&format!( + "Rebuild sanitizers by removing the file `{}`", + stamp.path.display() + )); + } return runtimes; } builder.info(&format!("Building sanitizers for {}", self.target)); + t!(stamp.remove()); let _time = util::timeit(&builder); let mut cfg = cmake::Config::new(&compiler_rt_dir); @@ -623,8 +622,7 @@ impl Step for Sanitizers { cfg.build_target(&runtime.cmake_target); cfg.build(); } - - t!(fs::write(&done_stamp, b"")); + t!(stamp.write()); runtimes } @@ -689,3 +687,41 @@ fn supported_sanitizers( } result } + +struct HashStamp { + path: PathBuf, + hash: Option>, +} + +impl HashStamp { + fn new(path: PathBuf, hash: Option<&str>) -> Self { + HashStamp { path, hash: hash.map(|s| s.as_bytes().to_owned()) } + } + + fn is_done(&self) -> bool { + match fs::read(&self.path) { + Ok(h) => self.hash.as_deref().unwrap_or(b"") == h.as_slice(), + Err(e) if e.kind() == io::ErrorKind::NotFound => false, + Err(e) => { + panic!("failed to read stamp file `{}`: {}", self.path.display(), e); + } + } + } + + fn remove(&self) -> io::Result<()> { + match fs::remove_file(&self.path) { + Ok(()) => Ok(()), + Err(e) => { + if e.kind() == io::ErrorKind::NotFound { + Ok(()) + } else { + Err(e) + } + } + } + } + + fn write(&self) -> io::Result<()> { + fs::write(&self.path, self.hash.as_deref().unwrap_or(b"")) + } +} diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs new file mode 100644 index 0000000000000..900534714277c --- /dev/null +++ b/src/bootstrap/run.rs @@ -0,0 +1,43 @@ +use crate::builder::{Builder, RunConfig, ShouldRun, Step}; +use crate::tool::Tool; +use std::process::Command; + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct ExpandYamlAnchors; + +impl Step for ExpandYamlAnchors { + type Output = (); + + /// Runs the `expand-yaml_anchors` tool. + /// + /// This tool in `src/tools` read the CI configuration files written in YAML and expands the + /// anchors in them, since GitHub Actions doesn't support them. + fn run(self, builder: &Builder<'_>) { + builder.info("Expanding YAML anchors in the GitHub Actions configuration"); + try_run( + builder, + &mut builder.tool_cmd(Tool::ExpandYamlAnchors).arg("generate").arg(&builder.src), + ); + } + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/tools/expand-yaml-anchors") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(ExpandYamlAnchors); + } +} + +fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> bool { + if !builder.fail_fast { + if !builder.try_run(cmd) { + let mut failures = builder.delayed_failures.borrow_mut(); + failures.push(format!("{:?}", cmd)); + return false; + } + } else { + builder.run(cmd); + } + true +} diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 1b9e9a889483c..5b946b05735d8 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -607,7 +607,6 @@ impl Step for RustdocTheme { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct RustdocJSStd { - pub host: Interned, pub target: Interned, } @@ -621,13 +620,16 @@ impl Step for RustdocJSStd { } fn make_run(run: RunConfig<'_>) { - run.builder.ensure(RustdocJSStd { host: run.host, target: run.target }); + run.builder.ensure(RustdocJSStd { target: run.target }); } fn run(self, builder: &Builder<'_>) { if let Some(ref nodejs) = builder.config.nodejs { let mut command = Command::new(nodejs); - command.args(&["src/tools/rustdoc-js-std/tester.js", &*self.host]); + command + .arg(builder.src.join("src/tools/rustdoc-js-std/tester.js")) + .arg(builder.doc_out(self.target)) + .arg(builder.src.join("src/test/rustdoc-js-std")); builder.ensure(crate::doc::Std { target: self.target, stage: builder.top_stage }); builder.run(&mut command); } else { @@ -726,9 +728,6 @@ impl Step for Tidy { let mut cmd = builder.tool_cmd(Tool::Tidy); cmd.arg(builder.src.join("src")); cmd.arg(&builder.initial_cargo); - if !builder.config.vendor { - cmd.arg("--no-vendor"); - } if builder.is_verbose() { cmd.arg("--verbose"); } @@ -751,6 +750,35 @@ impl Step for Tidy { } } +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct ExpandYamlAnchors; + +impl Step for ExpandYamlAnchors { + type Output = (); + const ONLY_HOSTS: bool = true; + + /// Ensure the `generate-ci-config` tool was run locally. + /// + /// The tool in `src/tools` reads the CI definition in `src/ci/builders.yml` and generates the + /// appropriate configuration for all our CI providers. This step ensures the tool was called + /// by the user before committing CI changes. + fn run(self, builder: &Builder<'_>) { + builder.info("Ensuring the YAML anchors in the GitHub Actions config were expanded"); + try_run( + builder, + &mut builder.tool_cmd(Tool::ExpandYamlAnchors).arg("check").arg(&builder.src), + ); + } + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/tools/expand-yaml-anchors") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(ExpandYamlAnchors); + } +} + fn testdir(builder: &Builder<'_>, host: Interned) -> PathBuf { builder.out.join(host).join("test") } @@ -1142,6 +1170,8 @@ impl Step for Compiletest { let llvm_config = builder.ensure(native::Llvm { target: builder.config.build }); if !builder.config.dry_run { let llvm_version = output(Command::new(&llvm_config).arg("--version")); + // Remove trailing newline from llvm-config output. + let llvm_version = llvm_version.trim_end(); cmd.arg("--llvm-version").arg(llvm_version); } if !builder.is_rust_llvm(target) { diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 67e0ed5c58029..52f750f448e20 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -12,7 +12,7 @@ use crate::channel; use crate::channel::GitInfo; use crate::compile; use crate::toolstate::ToolState; -use crate::util::{add_lib_path, exe, CiEnv}; +use crate::util::{add_dylib_path, exe, CiEnv}; use crate::Compiler; use crate::Mode; @@ -378,6 +378,7 @@ bootstrap_tool!( RemoteTestClient, "src/tools/remote-test-client", "remote-test-client"; RustInstaller, "src/tools/rust-installer", "fabricate", is_external_tool = true; RustdocTheme, "src/tools/rustdoc-themes", "rustdoc-themes"; + ExpandYamlAnchors, "src/tools/expand-yaml-anchors", "expand-yaml-anchors"; ); #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] @@ -388,7 +389,7 @@ pub struct ErrorIndex { impl ErrorIndex { pub fn command(builder: &Builder<'_>, compiler: Compiler) -> Command { let mut cmd = Command::new(builder.ensure(ErrorIndex { compiler })); - add_lib_path( + add_dylib_path( vec![PathBuf::from(&builder.sysroot_libdir(compiler, compiler.host))], &mut cmd, ); @@ -689,7 +690,7 @@ impl<'a> Builder<'a> { } } - add_lib_path(lib_paths, &mut cmd); + add_dylib_path(lib_paths, &mut cmd); cmd } } diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index eac790fe504b8..2bc6f1939d97b 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -40,7 +40,7 @@ pub fn libdir(target: &str) -> &'static str { } /// Adds a list of lookup paths to `cmd`'s dynamic library lookup path. -pub fn add_lib_path(path: Vec, cmd: &mut Command) { +pub fn add_dylib_path(path: Vec, cmd: &mut Command) { let mut list = dylib_path(); for path in path { list.insert(0, path); @@ -72,6 +72,31 @@ pub fn dylib_path() -> Vec { env::split_paths(&var).collect() } +/// Adds a list of lookup paths to `cmd`'s link library lookup path. +pub fn add_link_lib_path(path: Vec, cmd: &mut Command) { + let mut list = link_lib_path(); + for path in path { + list.insert(0, path); + } + cmd.env(link_lib_path_var(), t!(env::join_paths(list))); +} + +/// Returns the environment variable which the link library lookup path +/// resides in for this platform. +fn link_lib_path_var() -> &'static str { + if cfg!(target_env = "msvc") { "LIB" } else { "LIBRARY_PATH" } +} + +/// Parses the `link_lib_path_var()` environment variable, returning a list of +/// paths that are members of this lookup path. +fn link_lib_path() -> Vec { + let var = match env::var_os(link_lib_path_var()) { + Some(v) => v, + None => return vec![], + }; + env::split_paths(&var).collect() +} + /// `push` all components to `buf`. On windows, append `.exe` to the last component. pub fn push_exe_path(mut buf: PathBuf, components: &[&str]) -> PathBuf { let (&file, components) = components.split_last().expect("at least one component required"); diff --git a/src/ci/azure-pipelines/auto.yml b/src/ci/azure-pipelines/auto.yml index 74b7469ea27b7..56fe3864204c6 100644 --- a/src/ci/azure-pipelines/auto.yml +++ b/src/ci/azure-pipelines/auto.yml @@ -1,3 +1,14 @@ +##################################### +## READ BEFORE CHANGING THIS ## +##################################### + +# We're in the process of evaluating GitHub Actions as a possible replacement +# for Azure Pipelines, and at the moment the configuration is duplicated +# between the two CI providers. Be sure to also change the configuration in +# src/ci/github-actions when changing this file. + +##################################### + # # Azure Pipelines "auto" branch build for Rust on Linux, macOS, and Windows. # @@ -76,7 +87,7 @@ jobs: # version that we're using, 8.2, cannot compile LLVM for OSX 10.7. x86_64-apple: SCRIPT: ./x.py test - RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc + INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.8 MACOSX_STD_DEPLOYMENT_TARGET: 10.7 @@ -85,7 +96,7 @@ jobs: dist-x86_64-apple: SCRIPT: ./x.py dist - RUST_CONFIGURE_ARGS: --target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc + INITIAL_RUST_CONFIGURE_ARGS: --target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.7 NO_LLVM_ASSERTIONS: 1 @@ -94,7 +105,7 @@ jobs: dist-x86_64-apple-alt: SCRIPT: ./x.py dist - RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --set rust.jemalloc + INITIAL_RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --set rust.jemalloc RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.7 NO_LLVM_ASSERTIONS: 1 @@ -111,22 +122,22 @@ jobs: matrix: # 32/64 bit MSVC tests x86_64-msvc-1: - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler SCRIPT: make ci-subset-1 # FIXME(#59637) NO_DEBUG_ASSERTIONS: 1 NO_LLVM_ASSERTIONS: 1 x86_64-msvc-2: - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler SCRIPT: make ci-subset-2 i686-msvc-1: - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc + INITIAL_RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc SCRIPT: make ci-subset-1 # FIXME(#59637) NO_DEBUG_ASSERTIONS: 1 NO_LLVM_ASSERTIONS: 1 i686-msvc-2: - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc + INITIAL_RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc SCRIPT: make ci-subset-2 # FIXME(#59637) NO_DEBUG_ASSERTIONS: 1 @@ -134,10 +145,10 @@ jobs: # MSVC aux tests x86_64-msvc-aux: RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc + INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc x86_64-msvc-cargo: SCRIPT: python x.py test src/tools/cargotest src/tools/cargo - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc + INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc VCVARS_BAT: vcvars64.bat # FIXME(#59637) NO_DEBUG_ASSERTIONS: 1 @@ -145,7 +156,7 @@ jobs: # MSVC tools tests x86_64-msvc-tools: SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstate/toolstates.json + INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstate/toolstates.json # 32/64-bit MinGW builds. # @@ -161,31 +172,31 @@ jobs: # came from the mingw-w64 SourceForge download site. Unfortunately # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. i686-mingw-1: - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu + INITIAL_RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu SCRIPT: make ci-mingw-subset-1 CUSTOM_MINGW: 1 # FIXME(#59637) NO_DEBUG_ASSERTIONS: 1 NO_LLVM_ASSERTIONS: 1 i686-mingw-2: - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu + INITIAL_RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu SCRIPT: make ci-mingw-subset-2 CUSTOM_MINGW: 1 x86_64-mingw-1: SCRIPT: make ci-mingw-subset-1 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu + INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu CUSTOM_MINGW: 1 # FIXME(#59637) NO_DEBUG_ASSERTIONS: 1 NO_LLVM_ASSERTIONS: 1 x86_64-mingw-2: SCRIPT: make ci-mingw-subset-2 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu + INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu CUSTOM_MINGW: 1 # 32/64 bit MSVC and GNU deployment dist-x86_64-msvc: - RUST_CONFIGURE_ARGS: >- + INITIAL_RUST_CONFIGURE_ARGS: >- --build=x86_64-pc-windows-msvc --target=x86_64-pc-windows-msvc,aarch64-pc-windows-msvc --enable-full-tools @@ -193,7 +204,7 @@ jobs: SCRIPT: python x.py dist DIST_REQUIRE_ALL_TOOLS: 1 dist-i686-msvc: - RUST_CONFIGURE_ARGS: >- + INITIAL_RUST_CONFIGURE_ARGS: >- --build=i686-pc-windows-msvc --target=i586-pc-windows-msvc --enable-full-tools @@ -201,17 +212,17 @@ jobs: SCRIPT: python x.py dist DIST_REQUIRE_ALL_TOOLS: 1 dist-i686-mingw: - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools --enable-profiler + INITIAL_RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools --enable-profiler SCRIPT: python x.py dist CUSTOM_MINGW: 1 DIST_REQUIRE_ALL_TOOLS: 1 dist-x86_64-mingw: SCRIPT: python x.py dist - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools --enable-profiler + INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools --enable-profiler CUSTOM_MINGW: 1 DIST_REQUIRE_ALL_TOOLS: 1 # "alternate" deployment, see .travis.yml for more info dist-x86_64-msvc-alt: - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler + INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler SCRIPT: python x.py dist diff --git a/src/ci/azure-pipelines/master.yml b/src/ci/azure-pipelines/master.yml index 9c5a15a3cf4ed..485b80398c8e4 100644 --- a/src/ci/azure-pipelines/master.yml +++ b/src/ci/azure-pipelines/master.yml @@ -1,3 +1,14 @@ +##################################### +## READ BEFORE CHANGING THIS ## +##################################### + +# We're in the process of evaluating GitHub Actions as a possible replacement +# for Azure Pipelines, and at the moment the configuration is duplicated +# between the two CI providers. Be sure to also change the configuration in +# src/ci/github-actions when changing this file. + +##################################### + # # Azure Pipelines job to publish toolstate. Only triggers on pushes to master. # diff --git a/src/ci/azure-pipelines/pr.yml b/src/ci/azure-pipelines/pr.yml index 1f0be53677de2..37c1779b7995b 100644 --- a/src/ci/azure-pipelines/pr.yml +++ b/src/ci/azure-pipelines/pr.yml @@ -1,3 +1,14 @@ +##################################### +## READ BEFORE CHANGING THIS ## +##################################### + +# We're in the process of evaluating GitHub Actions as a possible replacement +# for Azure Pipelines, and at the moment the configuration is duplicated +# between the two CI providers. Be sure to also change the configuration in +# src/ci/github-actions when changing this file. + +##################################### + # # Azure Pipelines pull request build for Rust # diff --git a/src/ci/azure-pipelines/steps/run.yml b/src/ci/azure-pipelines/steps/run.yml index ee9425aa1c51f..85ff3e52a841d 100644 --- a/src/ci/azure-pipelines/steps/run.yml +++ b/src/ci/azure-pipelines/steps/run.yml @@ -1,3 +1,14 @@ +##################################### +## READ BEFORE CHANGING THIS ## +##################################### + +# We're in the process of evaluating GitHub Actions as a possible replacement +# for Azure Pipelines, and at the moment the configuration is duplicated +# between the two CI providers. Be sure to also change the configuration in +# src/ci/github-actions when changing this file. + +##################################### + # FIXME(linux): need to configure core dumps, enable them, and then dump # backtraces on failure from all core dumps: # @@ -59,8 +70,8 @@ steps: displayName: Install InnoSetup condition: and(succeeded(), not(variables.SKIP_JOB)) -- bash: src/ci/scripts/windows-symlink-build-dir.sh - displayName: Ensure the build happens on C:\ instead of D:\ +- bash: src/ci/scripts/symlink-build-dir.sh + displayName: Ensure the build happens on a partition with enough space condition: and(succeeded(), not(variables.SKIP_JOB)) - bash: src/ci/scripts/disable-git-crlf-conversion.sh diff --git a/src/ci/azure-pipelines/try.yml b/src/ci/azure-pipelines/try.yml index a29d6f9ae1ec6..38a0685e0f75a 100644 --- a/src/ci/azure-pipelines/try.yml +++ b/src/ci/azure-pipelines/try.yml @@ -1,3 +1,14 @@ +##################################### +## READ BEFORE CHANGING THIS ## +##################################### + +# We're in the process of evaluating GitHub Actions as a possible replacement +# for Azure Pipelines, and at the moment the configuration is duplicated +# between the two CI providers. Be sure to also change the configuration in +# src/ci/github-actions when changing this file. + +##################################### + pr: none trigger: - try @@ -32,7 +43,7 @@ jobs: # matrix: # dist-x86_64-apple: # SCRIPT: ./x.py dist -# RUST_CONFIGURE_ARGS: --target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc +# INITIAL_RUST_CONFIGURE_ARGS: --target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc # DEPLOY: 1 # RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 # MACOSX_DEPLOYMENT_TARGET: 10.7 @@ -42,7 +53,7 @@ jobs: # # dist-x86_64-apple-alt: # SCRIPT: ./x.py dist -# RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --set rust.jemalloc +# INITIAL_RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --set rust.jemalloc # DEPLOY_ALT: 1 # RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 # MACOSX_DEPLOYMENT_TARGET: 10.7 @@ -58,7 +69,7 @@ jobs: # strategy: # matrix: # dist-x86_64-msvc: -# RUST_CONFIGURE_ARGS: > +# INITIAL_RUST_CONFIGURE_ARGS: > # --build=x86_64-pc-windows-msvc # --target=x86_64-pc-windows-msvc,aarch64-pc-windows-msvc # --enable-full-tools @@ -68,6 +79,6 @@ jobs: # DEPLOY: 1 # # dist-x86_64-msvc-alt: -# RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler +# INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler # SCRIPT: python x.py dist # DEPLOY_ALT: 1 diff --git a/src/ci/docker/dist-android/Dockerfile b/src/ci/docker/dist-android/Dockerfile index a54a2d003b649..64f31750dd7b6 100644 --- a/src/ci/docker/dist-android/Dockerfile +++ b/src/ci/docker/dist-android/Dockerfile @@ -23,6 +23,7 @@ ENV TARGETS=$TARGETS,x86_64-linux-android ENV RUST_CONFIGURE_ARGS \ --enable-extended \ + --enable-profiler \ --arm-linux-androideabi-ndk=/android/ndk/arm-14 \ --armv7-linux-androideabi-ndk=/android/ndk/arm-14 \ --thumbv7neon-linux-androideabi-ndk=/android/ndk/arm-14 \ diff --git a/src/ci/docker/dist-various-2/build-wasi-toolchain.sh b/src/ci/docker/dist-various-2/build-wasi-toolchain.sh index b868677564298..c82031690ab6a 100755 --- a/src/ci/docker/dist-various-2/build-wasi-toolchain.sh +++ b/src/ci/docker/dist-various-2/build-wasi-toolchain.sh @@ -12,7 +12,7 @@ export PATH=`pwd`/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-14.04/bin:$PATH git clone https://github.com/CraneStation/wasi-libc cd wasi-libc -git reset --hard 1fad33890a5e299027ce0eab7b6ad5260585e347 +git reset --hard 9efc2f428358564fe64c374d762d0bfce1d92507 make -j$(nproc) INSTALL_DIR=/wasm32-wasi install cd .. diff --git a/src/ci/docker/dist-x86_64-sun-solaris/Dockerfile b/src/ci/docker/dist-x86_64-sun-solaris/Dockerfile new file mode 100644 index 0000000000000..9de078451fd84 --- /dev/null +++ b/src/ci/docker/dist-x86_64-sun-solaris/Dockerfile @@ -0,0 +1,33 @@ +FROM ubuntu:18.04 + +# Enable source repositories, which are disabled by default on Ubuntu >= 18.04 +RUN sed -i 's/^# deb-src/deb-src/' /etc/apt/sources.list + +COPY scripts/cross-apt-packages.sh /tmp/ +RUN bash /tmp/cross-apt-packages.sh + +# Required for cross-build gcc +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + libgmp-dev \ + libmpfr-dev \ + libmpc-dev + +COPY scripts/illumos-toolchain.sh /tmp/ + +RUN bash /tmp/illumos-toolchain.sh sysroot +RUN bash /tmp/illumos-toolchain.sh binutils +RUN bash /tmp/illumos-toolchain.sh gcc + +#COPY scripts/sccache.sh /scripts/ +#RUN sh /scripts/sccache.sh + +ENV \ + AR_x86_64_sun_solaris=x86_64-sun-solaris2.10-ar \ + CC_x86_64_sun_solaris=x86_64-sun-solaris2.10-gcc \ + CXX_x86_64_sun_solaris=x86_64-sun-solaris2.10-g++ + +ENV HOSTS=x86_64-sun-solaris + +ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs +ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/mingw-check/Dockerfile b/src/ci/docker/mingw-check/Dockerfile index b2d96aed2a9e8..1293717f975aa 100644 --- a/src/ci/docker/mingw-check/Dockerfile +++ b/src/ci/docker/mingw-check/Dockerfile @@ -22,7 +22,9 @@ RUN sh /scripts/sccache.sh COPY mingw-check/validate-toolstate.sh /scripts/ ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1 -ENV SCRIPT python2.7 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \ +ENV SCRIPT python2.7 ../x.py test src/tools/expand-yaml-anchors && \ + python2.7 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \ python2.7 ../x.py build --stage 0 src/tools/build-manifest && \ python2.7 ../x.py test --stage 0 src/tools/compiletest && \ + python2.7 ../x.py test src/tools/tidy && \ /scripts/validate-toolstate.sh diff --git a/src/ci/docker/scripts/illumos-toolchain.sh b/src/ci/docker/scripts/illumos-toolchain.sh new file mode 100644 index 0000000000000..4b0c48848672a --- /dev/null +++ b/src/ci/docker/scripts/illumos-toolchain.sh @@ -0,0 +1,84 @@ +#!/bin/bash + +set -o errexit +set -o pipefail +set -o xtrace + +JOBS="$(getconf _NPROCESSORS_ONLN)" + +BINUTILS_VERSION=2.25.1 +GCC_VERSION=7.5.0 +BUILD_TARGET=x86_64-sun-solaris2.10 + +SYSROOT_VER=amd64-20200312-161829 +SYSROOT_URL=https://illumos.org/downloads/sysroot-illumos-$SYSROOT_VER.tar.gz +SYSROOT_DIR=/ws/sysroot + +BINUTILS_BASE=binutils-${BINUTILS_VERSION} +BINUTILS_URL=https://ftp.gnu.org/gnu/binutils/${BINUTILS_BASE}.tar.bz2 + +GCC_BASE=gcc-${GCC_VERSION} +GCC_URL=https://ftp.gnu.org/gnu/gcc/${GCC_BASE}/${GCC_BASE}.tar.xz + +case "$1" in +sysroot) + mkdir -p ${SYSROOT_DIR} + cd ${SYSROOT_DIR} + curl -L "$SYSROOT_URL" | tar xzf - + ;; + +binutils) + mkdir -p /ws/src/binutils + cd /ws/src/binutils + curl -L "$BINUTILS_URL" | tar xjf - + + mkdir -p /ws/build/binutils + cd /ws/build/binutils + /ws/src/binutils/${BINUTILS_BASE}/configure \ + --target="${BUILD_TARGET}" \ + --with-sysroot="${SYSROOT_DIR}" + + make -j "$JOBS" + make install + cd /ws + rm -r /ws/src/binutils /ws/build/binutils + ;; + +gcc) + mkdir -p /ws/src/gcc + cd /ws/src/gcc + curl -L "${GCC_URL}" | tar xJf - + + mkdir /ws/build/gcc && \ + cd /ws/build/gcc && \ + export CFLAGS="-fPIC" + export CXXFLAGS="-fPIC" + export CXXFLAGS_FOR_TARGET="-fPIC" + export CFLAGS_FOR_TARGET="-fPIC" + /ws/src/gcc/${GCC_BASE}/configure \ + --target=${BUILD_TARGET} \ + --with-sysroot=${SYSROOT_DIR} \ + --with-gnu-as \ + --with-gnu-ld \ + --disable-nls \ + --disable-libgomp \ + --disable-libquadmath \ + --disable-libssp \ + --disable-libvtv \ + --disable-libcilkrts \ + --disable-libada \ + --disable-libsanitizer \ + --disable-libquadmath-support \ + --disable-shared \ + --enable-tls + make -j "$JOBS" + make install + cd /ws + rm -r /ws/src/gcc /ws/build/gcc + ;; + +*) + printf 'ERROR: unknown phase "%s"\n' "$1" >&2 + exit 100 + +esac diff --git a/src/ci/docker/x86_64-gnu-llvm-7/Dockerfile b/src/ci/docker/x86_64-gnu-llvm-7/Dockerfile index dc90c286f5cd1..4b5d5cac5163c 100644 --- a/src/ci/docker/x86_64-gnu-llvm-7/Dockerfile +++ b/src/ci/docker/x86_64-gnu-llvm-7/Dockerfile @@ -16,7 +16,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libssl-dev \ pkg-config \ zlib1g-dev \ - xz-utils + xz-utils \ + nodejs COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh @@ -28,7 +29,7 @@ ENV RUST_CONFIGURE_ARGS \ --enable-llvm-link-shared \ --set rust.thin-lto-import-instr-limit=10 -ENV SCRIPT python2.7 ../x.py test src/tools/tidy && python2.7 ../x.py test +ENV SCRIPT python2.7 ../x.py test --exclude src/tools/tidy && python2.7 ../x.py test src/tools/tidy # The purpose of this container isn't to test with debug assertions and # this is run on all PRs, so let's get speedier builds by disabling these extra diff --git a/src/ci/exec-with-shell.py b/src/ci/exec-with-shell.py new file mode 100755 index 0000000000000..26ce69e33d9c3 --- /dev/null +++ b/src/ci/exec-with-shell.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python +# A simple wrapper that forwards the arguments to bash, unless the +# CI_OVERRIDE_SHELL environment variable is present: in that case the content +# of that environment variable is used as the shell path. + +import os +import sys +import subprocess + +try: + shell = os.environ["CI_OVERRIDE_SHELL"] +except KeyError: + shell = "bash" + +res = subprocess.call([shell] + sys.argv[1:]) +sys.exit(res) diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml new file mode 100644 index 0000000000000..81a334cd487c6 --- /dev/null +++ b/src/ci/github-actions/ci.yml @@ -0,0 +1,709 @@ +###################################################### +# WARNING! Action needed when changing this file # +###################################################### + +# Due to GitHub Actions limitations, we can't use YAML Anchors directly in the +# CI configuration stored on the repository. To work around that this file is +# expanded by a tool in the repository, and the expansion is committed as well. +# +# After you make any change to the file you'll need to run this command: +# +# ./x.py run src/tools/expand-yaml-anchors +# +# ...and commit the file it updated in addition to this one. If you forget this +# step CI will fail. + +--- + +############################### +# YAML Anchors Definition # +############################### + +# This key contains most of the YAML anchors that will be used later in the +# document. YAML anchors allows us to greatly reduce duplication inside the CI +# configuration by reusing parts of the configuration. +# +# YAML anchors work by defining an anchor with `&anchor-name` and reusing its +# content in another place with `*anchor-name`. The special `<<` map key merges +# the content of the map with the content of the anchor (or list of anchors). +# +# The expand-yaml-anchors tool will automatically remove this block from the +# output YAML file. +x--expand-yaml-anchors--remove: + + - &shared-ci-variables + CI_JOB_NAME: ${{ matrix.name }} + + - &public-variables + SCCACHE_BUCKET: rust-lang-gha-caches + TOOLSTATE_REPO: https://github.com/pietroalbini/rust-toolstate + + - &prod-variables + SCCACHE_BUCKET: rust-lang-gha-caches + DEPLOY_BUCKET: rust-lang-gha + TOOLSTATE_REPO: https://github.com/pietroalbini/rust-toolstate + TOOLSTATE_ISSUES_API_URL: https://api.github.com/repos/pietroalbini/rust-toolstate/issues + TOOLSTATE_PUBLISH: 1 + # AWS_SECRET_ACCESS_KEYs are stored in GitHub's secrets storage, named + # AWS_SECRET_ACCESS_KEY_. Including the key id in the name allows to + # rotate them in a single branch while keeping the old key in another + # branch, which wouldn't be possible if the key was named with the kind + # (caches, artifacts...). + CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZOMUQATD5 + ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZH5AYXDVF + + - &base-job + env: {} + + - &job-linux-xl + os: ubuntu-latest-xl + <<: *base-job + + - &job-macos-xl + os: macos-latest # We don't have an XL builder for this + <<: *base-job + + - &job-windows-xl + os: windows-latest-xl + <<: *base-job + + - &step + if: success() && !env.SKIP_JOB + + - &step-run + <<: *step + # While on Linux and macOS builders it just forwards the arguments to the + # system bash, this wrapper allows switching from the host's bash.exe to + # the one we install along with MSYS2 mid-build on Windows. + # + # Once the step to install MSYS2 is executed, the CI_OVERRIDE_SHELL + # environment variable is set pointing to our MSYS2's bash.exe. From that + # moment the host's bash.exe will not be called anymore. + # + # This is needed because we can't launch our own bash.exe from the host + # bash.exe, as that would load two different cygwin1.dll in memory, causing + # "cygwin heap mismatch" errors. + shell: python src/ci/exec-with-shell.py {0} + + - &base-ci-job + timeout-minutes: 600 + runs-on: "${{ matrix.os }}" + env: *shared-ci-variables + steps: + - name: disable git crlf conversion + run: git config --global core.autocrlf false + shell: bash + + - name: checkout the source code + uses: actions/checkout@v1 + with: + fetch-depth: 2 + + - name: configure GitHub Actions to kill the build when outdated + uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master + with: + github_token: "${{ secrets.github_token }}" + <<: *step + + - name: add extra environment variables + run: src/ci/scripts/setup-environment.sh + env: + # Since it's not possible to merge `${{ matrix.env }}` with the other + # variables in `job..env`, the variables defined in the matrix + # are passed to the `setup-environment.sh` script encoded in JSON, + # which then uses log commands to actually set them. + EXTRA_VARIABLES: ${{ toJson(matrix.env) }} + <<: *step-run + + - name: decide whether to skip this job + run: src/ci/scripts/should-skip-this.sh + <<: *step-run + + - name: collect CPU statistics + run: src/ci/scripts/collect-cpu-stats.sh + <<: *step-run + + - name: show the current environment + run: src/ci/scripts/dump-environment.sh + <<: *step-run + + - name: install awscli + run: src/ci/scripts/install-awscli.sh + <<: *step-run + + - name: install sccache + run: src/ci/scripts/install-sccache.sh + <<: *step-run + + - name: install clang + run: src/ci/scripts/install-clang.sh + <<: *step-run + + - name: install WIX + run: src/ci/scripts/install-wix.sh + <<: *step-run + + - name: install InnoSetup + run: src/ci/scripts/install-innosetup.sh + <<: *step-run + + - name: ensure the build happens on a partition with enough space + run: src/ci/scripts/symlink-build-dir.sh + <<: *step-run + + - name: disable git crlf conversion + run: src/ci/scripts/disable-git-crlf-conversion.sh + <<: *step-run + + - name: install MSYS2 + run: src/ci/scripts/install-msys2.sh + <<: *step-run + + - name: install MSYS2 packages + run: src/ci/scripts/install-msys2-packages.sh + <<: *step-run + + - name: install MinGW + run: src/ci/scripts/install-mingw.sh + <<: *step-run + + - name: install ninja + run: src/ci/scripts/install-ninja.sh + <<: *step-run + + - name: enable ipv6 on Docker + run: src/ci/scripts/enable-docker-ipv6.sh + <<: *step-run + + # Disable automatic line ending conversion (again). On Windows, when we're + # installing dependencies, something switches the git configuration directory or + # re-enables autocrlf. We've not tracked down the exact cause -- and there may + # be multiple -- but this should ensure submodules are checked out with the + # appropriate line endings. + - name: disable git crlf conversion + run: src/ci/scripts/disable-git-crlf-conversion.sh + <<: *step-run + + - name: checkout submodules + run: src/ci/scripts/checkout-submodules.sh + <<: *step-run + + - name: ensure line endings are correct + run: src/ci/scripts/verify-line-endings.sh + <<: *step-run + + - name: run the build + run: src/ci/scripts/run-build-from-ci.sh + env: + AWS_ACCESS_KEY_ID: ${{ env.CACHES_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }} + TOOLSTATE_REPO_ACCESS_TOKEN: ${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }} + <<: *step-run + + - name: upload artifacts to S3 + run: src/ci/scripts/upload-artifacts.sh + env: + AWS_ACCESS_KEY_ID: ${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }} + # Adding a condition on DEPLOY=1 or DEPLOY_ALT=1 is not needed as all deploy + # builders *should* have the AWS credentials available. Still, explicitly + # adding the condition is helpful as this way CI will not silently skip + # deploying artifacts from a dist builder if the variables are misconfigured, + # erroring about invalid credentials instead. + if: success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1') + <<: *step-run + + # These snippets are used by the try-success, try-failure, auto-success and auto-failure jobs. + # Check out their documentation for more information on why they're needed. + + - &base-outcome-job + name: bors build finished + runs-on: ubuntu-latest + + - &base-success-job + steps: + - name: mark the job as a success + run: exit 0 + <<: *base-outcome-job + + - &base-failure-job + steps: + - name: mark the job as a failure + run: exit 1 + <<: *base-outcome-job + +########################### +# Builders definition # +########################### + +name: CI +on: + push: + branches: + - auto + - try + - master + pull_request: + branches: + - "**" + +jobs: + pr: + <<: *base-ci-job + name: PR + env: + <<: [*shared-ci-variables, *public-variables] + if: github.event_name == 'pull_request' + strategy: + matrix: + name: + - mingw-check + - x86_64-gnu-llvm-7 + - x86_64-gnu-tools + include: + - name: mingw-check + <<: *job-linux-xl + + - name: x86_64-gnu-llvm-7 + <<: *job-linux-xl + + - name: x86_64-gnu-tools + env: + CI_ONLY_WHEN_SUBMODULES_CHANGED: 1 + <<: *job-linux-xl + + try: + <<: *base-ci-job + name: try + env: + <<: [*shared-ci-variables, *prod-variables] + if: github.event_name == 'push' && github.ref == 'refs/heads/try' && github.repository == 'rust-lang-ci/rust' + strategy: + matrix: + name: + - dist-x86_64-linux + - dist-x86_64-linux-alt + include: + - name: dist-x86_64-linux + <<: *job-linux-xl + + - name: dist-x86_64-linux-alt + env: + IMAGE: dist-x86_64-linux + <<: *job-linux-xl + + auto: + <<: *base-ci-job + name: auto + env: + <<: [*shared-ci-variables, *prod-variables] + if: github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust' + strategy: + matrix: + name: + - arm-android + - armhf-gnu + - dist-aarch64-linux + - dist-android + - dist-arm-linux + - dist-armhf-linux + - dist-armv7-linux + - dist-i586-gnu-i586-i686-musl + - dist-i686-freebsd + - dist-i686-linux + - dist-i686-mingw + - dist-i686-msvc + - dist-mips-linux + - dist-mips64-linux + - dist-mips64el-linux + - dist-mipsel-linux + - dist-powerpc-linux + - dist-powerpc64-linux + - dist-powerpc64le-linux + - dist-s390x-linux + - dist-various-1 + - dist-various-2 + - dist-x86_64-apple + - dist-x86_64-apple-alt + - dist-x86_64-freebsd + - dist-x86_64-linux + - dist-x86_64-linux-alt + - dist-x86_64-mingw + - dist-x86_64-msvc + - dist-x86_64-msvc-alt + - dist-x86_64-musl + - dist-x86_64-netbsd + - i686-gnu + - i686-gnu-nopt + - i686-mingw-1 + - i686-mingw-2 + - i686-msvc-1 + - i686-msvc-2 + - mingw-check + - test-various + - wasm32 + - x86_64-apple + - x86_64-gnu + - x86_64-gnu-aux + - x86_64-gnu-debug + - x86_64-gnu-distcheck + - x86_64-gnu-full-bootstrap + - x86_64-gnu-llvm-7 + - x86_64-gnu-nopt + - x86_64-gnu-tools + - x86_64-mingw-1 + - x86_64-mingw-2 + - x86_64-msvc-1 + - x86_64-msvc-2 + - x86_64-msvc-aux + - x86_64-msvc-cargo + - x86_64-msvc-tools + include: + ############################# + # Linux/Docker builders # + ############################# + + - name: arm-android + <<: *job-linux-xl + + - name: armhf-gnu + <<: *job-linux-xl + + - name: dist-aarch64-linux + <<: *job-linux-xl + + - name: dist-android + <<: *job-linux-xl + + - name: dist-arm-linux + <<: *job-linux-xl + + - name: dist-armhf-linux + <<: *job-linux-xl + + - name: dist-armv7-linux + <<: *job-linux-xl + + - name: dist-i586-gnu-i586-i686-musl + <<: *job-linux-xl + + - name: dist-i686-freebsd + <<: *job-linux-xl + + - name: dist-i686-linux + <<: *job-linux-xl + + - name: dist-mips-linux + <<: *job-linux-xl + + - name: dist-mips64-linux + <<: *job-linux-xl + + - name: dist-mips64el-linux + <<: *job-linux-xl + + - name: dist-mipsel-linux + <<: *job-linux-xl + + - name: dist-powerpc-linux + <<: *job-linux-xl + + - name: dist-powerpc64-linux + <<: *job-linux-xl + + - name: dist-powerpc64le-linux + <<: *job-linux-xl + + - name: dist-s390x-linux + <<: *job-linux-xl + + - name: dist-various-1 + <<: *job-linux-xl + + - name: dist-various-2 + <<: *job-linux-xl + + - name: dist-x86_64-freebsd + <<: *job-linux-xl + + - name: dist-x86_64-linux + <<: *job-linux-xl + + - name: dist-x86_64-linux-alt + env: + IMAGE: dist-x86_64-linux + <<: *job-linux-xl + + - name: dist-x86_64-musl + <<: *job-linux-xl + + - name: dist-x86_64-netbsd + <<: *job-linux-xl + + - name: i686-gnu + <<: *job-linux-xl + + - name: i686-gnu-nopt + <<: *job-linux-xl + + - name: mingw-check + <<: *job-linux-xl + + - name: test-various + <<: *job-linux-xl + + - name: wasm32 + <<: *job-linux-xl + + - name: x86_64-gnu + <<: *job-linux-xl + + - name: x86_64-gnu-aux + <<: *job-linux-xl + + - name: x86_64-gnu-debug + <<: *job-linux-xl + + - name: x86_64-gnu-distcheck + <<: *job-linux-xl + + - name: x86_64-gnu-full-bootstrap + <<: *job-linux-xl + + - name: x86_64-gnu-llvm-7 + env: + RUST_BACKTRACE: 1 + <<: *job-linux-xl + + - name: x86_64-gnu-nopt + <<: *job-linux-xl + + - name: x86_64-gnu-tools + env: + DEPLOY_TOOLSTATES_JSON: toolstates-linux.json + <<: *job-linux-xl + + #################### + # macOS Builders # + #################### + + - name: dist-x86_64-apple + env: + SCRIPT: ./x.py dist + RUST_CONFIGURE_ARGS: --target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + DIST_REQUIRE_ALL_TOOLS: 1 + <<: *job-macos-xl + + - name: dist-x86_64-apple-alt + env: + SCRIPT: ./x.py dist + RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + <<: *job-macos-xl + + - name: x86_64-apple + env: + SCRIPT: ./x.py test + RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + <<: *job-macos-xl + + ###################### + # Windows Builders # + ###################### + + - name: x86_64-msvc-1 + env: + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + SCRIPT: make ci-subset-1 + # FIXME(#59637) + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + <<: *job-windows-xl + + - name: x86_64-msvc-2 + env: + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + SCRIPT: make ci-subset-2 + <<: *job-windows-xl + + - name: i686-msvc-1 + env: + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc + SCRIPT: make ci-subset-1 + # FIXME(#59637) + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + <<: *job-windows-xl + + - name: i686-msvc-2 + env: + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc + SCRIPT: make ci-subset-2 + # FIXME(#59637) + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + <<: *job-windows-xl + + - name: x86_64-msvc-aux + env: + RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc + <<: *job-windows-xl + + - name: x86_64-msvc-cargo + env: + SCRIPT: python x.py test src/tools/cargotest src/tools/cargo + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc + VCVARS_BAT: vcvars64.bat + # FIXME(#59637) + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + <<: *job-windows-xl + + - name: x86_64-msvc-tools + env: + SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstate/toolstates.json windows + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstate/toolstates.json + <<: *job-windows-xl + + # 32/64-bit MinGW builds. + # + # We are using MinGW with posix threads since LLVM does not compile with + # the win32 threads version due to missing support for C++'s std::thread. + # + # Instead of relying on the MinGW version installed on appveryor we download + # and install one ourselves so we won't be surprised by changes to appveyor's + # build image. + # + # Finally, note that the downloads below are all in the `rust-lang-ci` S3 + # bucket, but they cleraly didn't originate there! The downloads originally + # came from the mingw-w64 SourceForge download site. Unfortunately + # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. + + - name: i686-mingw-1 + env: + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu + SCRIPT: make ci-mingw-subset-1 + CUSTOM_MINGW: 1 + # FIXME(#59637) + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + <<: *job-windows-xl + + - name: i686-mingw-2 + env: + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu + SCRIPT: make ci-mingw-subset-2 + CUSTOM_MINGW: 1 + <<: *job-windows-xl + + - name: x86_64-mingw-1 + env: + SCRIPT: make ci-mingw-subset-1 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu + CUSTOM_MINGW: 1 + # FIXME(#59637) + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + <<: *job-windows-xl + + - name: x86_64-mingw-2 + env: + SCRIPT: make ci-mingw-subset-2 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu + CUSTOM_MINGW: 1 + <<: *job-windows-xl + + - name: dist-x86_64-msvc + env: + RUST_CONFIGURE_ARGS: >- + --build=x86_64-pc-windows-msvc + --target=x86_64-pc-windows-msvc,aarch64-pc-windows-msvc + --enable-full-tools + --enable-profiler + SCRIPT: python x.py dist + DIST_REQUIRE_ALL_TOOLS: 1 + <<: *job-windows-xl + + - name: dist-i686-msvc + env: + RUST_CONFIGURE_ARGS: >- + --build=i686-pc-windows-msvc + --target=i586-pc-windows-msvc + --enable-full-tools + --enable-profiler + SCRIPT: python x.py dist + DIST_REQUIRE_ALL_TOOLS: 1 + <<: *job-windows-xl + + - name: dist-i686-mingw + env: + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools --enable-profiler + SCRIPT: python x.py dist + CUSTOM_MINGW: 1 + DIST_REQUIRE_ALL_TOOLS: 1 + <<: *job-windows-xl + + - name: dist-x86_64-mingw + env: + SCRIPT: python x.py dist + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools --enable-profiler + CUSTOM_MINGW: 1 + DIST_REQUIRE_ALL_TOOLS: 1 + <<: *job-windows-xl + + - name: dist-x86_64-msvc-alt + env: + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler + SCRIPT: python x.py dist + <<: *job-windows-xl + + master: + name: master + runs-on: ubuntu-latest + env: + <<: [*prod-variables] + if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'rust-lang-ci/rust' + steps: + - name: checkout the source code + uses: actions/checkout@v1 + with: + fetch-depth: 2 + + - name: publish toolstate + run: src/ci/publish_toolstate.sh + env: + TOOLSTATE_REPO_ACCESS_TOKEN: ${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }} + <<: *step-run + + # These jobs don't actually test anything, but they're used to tell bors the + # build completed, as there is no practical way to detect when a workflow is + # successful listening to webhooks only. + try-success: + needs: [try] + if: "success() && github.event_name == 'push' && github.ref == 'refs/heads/try' && github.repository == 'rust-lang-ci/rust'" + <<: *base-success-job + try-failure: + needs: [try] + if: "!success() && github.event_name == 'push' && github.ref == 'refs/heads/try' && github.repository == 'rust-lang-ci/rust'" + <<: *base-failure-job + auto-success: + needs: [auto] + if: "success() && github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'" + <<: *base-success-job + auto-failure: + needs: [auto] + if: "!success() && github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'" + <<: *base-failure-job diff --git a/src/ci/scripts/install-awscli.sh b/src/ci/scripts/install-awscli.sh index e21187938504c..f9b759fe343f0 100755 --- a/src/ci/scripts/install-awscli.sh +++ b/src/ci/scripts/install-awscli.sh @@ -28,7 +28,7 @@ if isLinux; then pipflags="--user" sudo apt-get install -y python3-setuptools - echo "##vso[task.prependpath]$HOME/.local/bin" + ciCommandAddPath "${HOME}/.local/bin" fi mkdir -p "${DEPS_DIR}" diff --git a/src/ci/scripts/install-mingw.sh b/src/ci/scripts/install-mingw.sh index 98373df7fce50..78728dd7d005c 100755 --- a/src/ci/scripts/install-mingw.sh +++ b/src/ci/scripts/install-mingw.sh @@ -50,8 +50,8 @@ if isWindows; then esac if [[ "${CUSTOM_MINGW-0}" -ne 1 ]]; then - pacman -S --noconfirm --needed mingw-w64-$arch-toolchain mingw-w64-$arch-cmake \ - mingw-w64-$arch-gcc mingw-w64-$arch-python2 + pacman -S --noconfirm --needed mingw-w64-$arch-toolchain \ + mingw-w64-$arch-cmake mingw-w64-$arch-gcc mingw-w64-$arch-python2 ciCommandAddPath "$(ciCheckoutPath)/msys2/mingw${bits}/bin" else mingw_dir="mingw${bits}" diff --git a/src/ci/scripts/install-msys2-packages.sh b/src/ci/scripts/install-msys2-packages.sh index 843a2bf2d5e55..22b9854ad5eb4 100755 --- a/src/ci/scripts/install-msys2-packages.sh +++ b/src/ci/scripts/install-msys2-packages.sh @@ -13,6 +13,7 @@ if isWindows; then # one way or another. The msys interpreters seem to have weird path conversions # baked in which break LLVM's build system one way or another, so let's use the # native version which keeps everything as native as possible. - cp C:/Python27amd64/python.exe C:/Python27amd64/python2.7.exe - ciCommandAddPath "C:\\Python27amd64" + python_home="C:/hostedtoolcache/windows/Python/2.7.17/x64" + cp "${python_home}/python.exe" "${python_home}/python2.7.exe" + ciCommandAddPath "C:\\hostedtoolcache\\windows\\Python\\2.7.17\\x64" fi diff --git a/src/ci/scripts/install-msys2.sh b/src/ci/scripts/install-msys2.sh index 9e899ba9d8947..3c3b5007f8697 100755 --- a/src/ci/scripts/install-msys2.sh +++ b/src/ci/scripts/install-msys2.sh @@ -22,4 +22,7 @@ if isWindows; then rm msys2.nupkg chocolatey-core.extension.nupkg mkdir -p "$(ciCheckoutPath)/msys2/home/${USERNAME}" ciCommandAddPath "$(ciCheckoutPath)/msys2/usr/bin" + + echo "switching shell to use our own bash" + ciCommandSetEnv CI_OVERRIDE_SHELL "$(ciCheckoutPath)/msys2/usr/bin/bash.exe" fi diff --git a/src/ci/scripts/setup-environment.sh b/src/ci/scripts/setup-environment.sh index e126a06edab73..411ef6f9b2822 100755 --- a/src/ci/scripts/setup-environment.sh +++ b/src/ci/scripts/setup-environment.sh @@ -8,6 +8,37 @@ IFS=$'\n\t' source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" +# Since matrix variables are readonly in Azure Pipelines, we take +# INITIAL_RUST_CONFIGURE_ARGS and establish RUST_CONFIGURE_ARGS +# which downstream steps can alter +if isAzurePipelines; then + # macOS ships with Bash 3.16, so we cannot use [[ -v FOO ]], + # which was introduced in Bash 4.2 + if [[ -z "${INITIAL_RUST_CONFIGURE_ARGS+x}" ]]; then + INITIAL_RUST_CONFIG="" + echo "No initial Rust configure args set" + else + INITIAL_RUST_CONFIG="${INITIAL_RUST_CONFIGURE_ARGS}" + ciCommandSetEnv RUST_CONFIGURE_ARGS "${INITIAL_RUST_CONFIG}" + fi +fi + +# Load extra environment variables +vars="${EXTRA_VARIABLES-}" +echo "${vars}" | jq '' >/dev/null # Validate JSON and exit on errors +for key in $(echo "${vars}" | jq "keys[]" -r); do + # On Windows, for whatever reason, $key contains the BOM character in it, + # and that messes up `jq ".${key}"`. This line strips the BOM from the key. + # + # https://unix.stackexchange.com/a/381263 + key="$(echo "${key}" | sed '1s/^\xEF\xBB\xBF//')" + + echo "adding extra environment variable ${key}" + value="$(echo "${vars}" | jq ".${key}" -r)" + export "${key}"="${value}" + ciCommandSetEnv "${key}" "${value}" +done + # Builders starting with `dist-` are dist builders, but if they also end with # `-alt` they are alternate dist builders. if [[ "${CI_JOB_NAME}" = dist-* ]]; then diff --git a/src/ci/scripts/symlink-build-dir.sh b/src/ci/scripts/symlink-build-dir.sh new file mode 100755 index 0000000000000..c77059c00ac2a --- /dev/null +++ b/src/ci/scripts/symlink-build-dir.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# We've had multiple issues with the default disk running out of disk space +# during builds, and it looks like other disks mounted in the VMs have more +# space available. This script synlinks the build directory to those other +# disks, in the CI providers and OSes affected by this. + +set -euo pipefail +IFS=$'\n\t' + +source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" + +if isWindows && isAzurePipelines; then + cmd //c "mkdir c:\\MORE_SPACE" + cmd //c "mklink /J build c:\\MORE_SPACE" +elif isLinux && isGitHubActions; then + sudo mkdir -p /mnt/more-space + sudo chown -R "$(whoami):" /mnt/more-space + + # Switch the whole workspace to the /mnt partition, which has more space. + # We don't just symlink the `obj` directory as doing that creates problems + # with the docker container. + current_dir="$(readlink -f "$(pwd)")" + cd /tmp + mv "${current_dir}" /mnt/more-space/workspace + ln -s /mnt/more-space/workspace "${current_dir}" + cd "${current_dir}" +fi diff --git a/src/ci/scripts/windows-symlink-build-dir.sh b/src/ci/scripts/windows-symlink-build-dir.sh deleted file mode 100755 index e57128c70f5f1..0000000000000 --- a/src/ci/scripts/windows-symlink-build-dir.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash -# We've had issues with the default drive in use running out of space during a -# build, and it looks like the `C:` drive has more space than the default `D:` -# drive. We should probably confirm this with the azure pipelines team at some -# point, but this seems to fix our "disk space full" problems. - -set -euo pipefail -IFS=$'\n\t' - -source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" - -if isWindows; then - cmd //c "mkdir c:\\MORE_SPACE" - cmd //c "mklink /J build c:\\MORE_SPACE" -fi diff --git a/src/doc/embedded-book b/src/doc/embedded-book index b81ffb7a6f4c5..d22a9c487c780 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit b81ffb7a6f4c5aaed92786e770e99db116aa4ebd +Subproject commit d22a9c487c78095afc4584f1d9b4ec43529d713c diff --git a/src/doc/reference b/src/doc/reference index 559e09caa9661..e2f11fe4d6a5e 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 559e09caa9661043744cf7af7bd88432d966f743 +Subproject commit e2f11fe4d6a5ecb471c70323197da43c70cb96b6 diff --git a/src/doc/robots.txt b/src/doc/robots.txt index d119cc464731b..3a2552e9a159b 100644 --- a/src/doc/robots.txt +++ b/src/doc/robots.txt @@ -1,21 +1,6 @@ User-agent: * -Disallow: /0.3/ -Disallow: /0.4/ -Disallow: /0.5/ -Disallow: /0.6/ -Disallow: /0.7/ -Disallow: /0.8/ -Disallow: /0.9/ -Disallow: /0.10/ -Disallow: /0.11.0/ -Disallow: /0.12.0/ -Disallow: /1.0.0-alpha/ -Disallow: /1.0.0-alpha.2/ -Disallow: /1.0.0-beta/ -Disallow: /1.0.0-beta.2/ -Disallow: /1.0.0-beta.3/ -Disallow: /1.0.0-beta.4/ -Disallow: /1.0.0-beta.5/ +Disallow: /1. +Disallow: /0. Disallow: /book/first-edition/ Disallow: /book/second-edition/ Disallow: /stable/book/first-edition/ diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index db57f899ea2a5..cb369ae95ca36 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit db57f899ea2a56a544c8d280cbf033438666273d +Subproject commit cb369ae95ca36b841960182d26f6d5d9b2e3cc18 diff --git a/src/doc/rustc/src/json.md b/src/doc/rustc/src/json.md index b737849516310..c46380f1505df 100644 --- a/src/doc/rustc/src/json.md +++ b/src/doc/rustc/src/json.md @@ -168,7 +168,7 @@ Diagnostics have the following format: "rendered": null }, { - "message": "consider prefixing with an underscore", + "message": "if this is intentional, prefix it with an underscore", "code": null, "level": "help", "spans": [ @@ -201,7 +201,7 @@ Diagnostics have the following format: /* Optional string of the rendered version of the diagnostic as displayed by rustc. Note that this may be influenced by the `--json` flag. */ - "rendered": "warning: unused variable: `x`\n --> lib.rs:2:9\n |\n2 | let x = 123;\n | ^ help: consider prefixing with an underscore: `_x`\n |\n = note: `#[warn(unused_variables)]` on by default\n\n" + "rendered": "warning: unused variable: `x`\n --> lib.rs:2:9\n |\n2 | let x = 123;\n | ^ help: if this is intentional, prefix it with an underscore: `_x`\n |\n = note: `#[warn(unused_variables)]` on by default\n\n" } ``` diff --git a/src/doc/rustdoc/src/advanced-features.md b/src/doc/rustdoc/src/advanced-features.md index 47bef3cdde187..7c12d23e6495c 100644 --- a/src/doc/rustdoc/src/advanced-features.md +++ b/src/doc/rustdoc/src/advanced-features.md @@ -4,7 +4,7 @@ The features listed on this page fall outside the rest of the main categories. ## `#[cfg(doc)]`: Documenting platform-/feature-specific information -For conditional compilation, Rustdoc treats your crate the same way the compiler does: Only things +For conditional compilation, Rustdoc treats your crate the same way the compiler does. Only things from the host target are available (or from the given `--target` if present), and everything else is "filtered out" from the crate. This can cause problems if your crate is providing different things on different targets and you want your documentation to reflect all the available items you diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index 2e32ce31ecae0..31e002810ce4b 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -79,8 +79,8 @@ Rustdoc only supports HTML output, and so this flag is redundant today. Using this flag looks like this: ```bash -$ rustdoc src/lib.rs -o target\\doc -$ rustdoc src/lib.rs --output target\\doc +$ rustdoc src/lib.rs -o target/doc +$ rustdoc src/lib.rs --output target/doc ``` By default, `rustdoc`'s output appears in a directory named `doc` in @@ -390,3 +390,15 @@ the same CSS rules as the official `light` theme. `--check-theme` is a separate mode in `rustdoc`. When `rustdoc` sees the `--check-theme` flag, it discards all other flags and only performs the CSS rule comparison operation. + +### `--crate-version`: control the crate version + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs --crate-version 1.3.37 +``` + +When `rustdoc` receives this flag, it will print an extra "Version (version)" into the sidebar of +the crate root's docs. You can use this flag to differentiate between different versions of your +library's documentation. diff --git a/src/doc/rustdoc/src/documentation-tests.md b/src/doc/rustdoc/src/documentation-tests.md index 96fa4344b04b7..78181156e250f 100644 --- a/src/doc/rustdoc/src/documentation-tests.md +++ b/src/doc/rustdoc/src/documentation-tests.md @@ -314,7 +314,7 @@ only shows the part you care about. `should_panic` tells `rustdoc` that the code should compile correctly, but not actually pass as a test. -```text +```rust /// ```no_run /// loop { /// println!("Hello, world"); diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index f704fe8e099b8..84e1ebe5e01f5 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -248,18 +248,6 @@ Markdown file, the URL given to `--markdown-playground-url` will take precedence `--playground-url` and `#![doc(html_playground_url = "url")]` are present when rendering crate docs, the attribute will take precedence. -### `--crate-version`: control the crate version - -Using this flag looks like this: - -```bash -$ rustdoc src/lib.rs -Z unstable-options --crate-version 1.3.37 -``` - -When `rustdoc` receives this flag, it will print an extra "Version (version)" into the sidebar of -the crate root's docs. You can use this flag to differentiate between different versions of your -library's documentation. - ### `--sort-modules-by-appearance`: control how items on module pages are sorted Using this flag looks like this: diff --git a/src/doc/rustdoc/src/what-is-rustdoc.md b/src/doc/rustdoc/src/what-is-rustdoc.md index bbcacb7f3d5d9..adcebc832bc0b 100644 --- a/src/doc/rustdoc/src/what-is-rustdoc.md +++ b/src/doc/rustdoc/src/what-is-rustdoc.md @@ -78,8 +78,8 @@ $ cargo doc Internally, this calls out to `rustdoc` like this: ```bash -$ rustdoc --crate-name docs srclib.rs -o \docs\target\doc -L -dependency=docs\target\debug\deps +$ rustdoc --crate-name docs src/lib.rs -o /docs/target/doc -L +dependency=/docs/target/debug/deps ``` You can see this with `cargo doc --verbose`. @@ -128,4 +128,4 @@ Cargo currently does not understand standalone Markdown files, unfortunately. ## Summary This covers the simplest use-cases of `rustdoc`. The rest of this book will -explain all of the options that `rustdoc` has, and how to use them. \ No newline at end of file +explain all of the options that `rustdoc` has, and how to use them. diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md index 6f096e582f575..250824321920d 100644 --- a/src/doc/unstable-book/src/language-features/lang-items.md +++ b/src/doc/unstable-book/src/language-features/lang-items.md @@ -52,7 +52,6 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize { #[lang = "eh_personality"] extern fn rust_eh_personality() {} #[lang = "panic_impl"] extern fn rust_begin_panic(info: &PanicInfo) -> ! { unsafe { intrinsics::abort() } } -#[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {} #[no_mangle] pub extern fn rust_eh_register_frames () {} #[no_mangle] pub extern fn rust_eh_unregister_frames () {} ``` @@ -67,7 +66,7 @@ Other features provided by lang items include: marked with lang items; those specific four are `eq`, `ord`, `deref`, and `add` respectively. - stack unwinding and general failure; the `eh_personality`, - `eh_unwind_resume`, `fail` and `fail_bounds_checks` lang items. + `panic` and `panic_bounds_checks` lang items. - the traits in `std::marker` used to indicate types of various kinds; lang items `send`, `sync` and `copy`. - the marker types and variance indicators found in @@ -130,12 +129,6 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize { pub extern fn rust_eh_personality() { } -// This function may be needed based on the compilation target. -#[lang = "eh_unwind_resume"] -#[no_mangle] -pub extern fn rust_eh_unwind_resume() { -} - #[lang = "panic_impl"] #[no_mangle] pub extern fn rust_begin_panic(info: &PanicInfo) -> ! { @@ -173,12 +166,6 @@ pub extern fn main(_argc: i32, _argv: *const *const u8) -> i32 { pub extern fn rust_eh_personality() { } -// This function may be needed based on the compilation target. -#[lang = "eh_unwind_resume"] -#[no_mangle] -pub extern fn rust_eh_unwind_resume() { -} - #[lang = "panic_impl"] #[no_mangle] pub extern fn rust_begin_panic(info: &PanicInfo) -> ! { @@ -211,10 +198,8 @@ compiler. When a panic happens, this controls the message that's displayed on the screen. While the language item's name is `panic_impl`, the symbol name is `rust_begin_panic`. -A third function, `rust_eh_unwind_resume`, is also needed if the `custom_unwind_resume` -flag is set in the options of the compilation target. It allows customizing the -process of resuming unwind at the end of the landing pads. The language item's name -is `eh_unwind_resume`. +Finally, a `eh_catch_typeinfo` static is needed for certain targets which +implement Rust panics on top of C++ exceptions. ## List of all language items @@ -247,8 +232,6 @@ the source code. - `eh_personality`: `libpanic_unwind/emcc.rs` (EMCC) - `eh_personality`: `libpanic_unwind/gcc.rs` (GNU) - `eh_personality`: `libpanic_unwind/seh.rs` (SEH) - - `eh_unwind_resume`: `libpanic_unwind/gcc.rs` (GCC) - - `eh_catch_typeinfo`: `libpanic_unwind/seh.rs` (SEH) - `eh_catch_typeinfo`: `libpanic_unwind/emcc.rs` (EMCC) - `panic`: `libcore/panicking.rs` - `panic_bounds_check`: `libcore/panicking.rs` diff --git a/src/doc/unstable-book/src/language-features/negative-impls.md b/src/doc/unstable-book/src/language-features/negative-impls.md new file mode 100644 index 0000000000000..151520f0e4abc --- /dev/null +++ b/src/doc/unstable-book/src/language-features/negative-impls.md @@ -0,0 +1,57 @@ +# `negative_impls` + +The tracking issue for this feature is [#68318]. + +[#68318]: https://github.com/rust-lang/rust/issues/68318 + +---- + +With the feature gate `negative_impls`, you can write negative impls as well as positive ones: + +```rust +#![feature(negative_impls)] +trait DerefMut { } +impl !DerefMut for &T { } +``` + +Negative impls indicate a semver guarantee that the given trait will not be implemented for the given types. Negative impls play an additional purpose for auto traits, described below. + +Negative impls have the following characteristics: + +* They do not have any items. +* They must obey the orphan rules as if they were a positive impl. +* They cannot "overlap" with any positive impls. + +## Semver interaction + +It is a breaking change to remove a negative impl. Negative impls are a commitment not to implement the given trait for the named types. + +## Orphan and overlap rules + +Negative impls must obey the same orphan rules as a positive impl. This implies you cannot add a negative impl for types defined in upstream crates and so forth. + +Similarly, negative impls cannot overlap with positive impls, again using the same "overlap" check that we ordinarily use to determine if two impls overlap. (Note that positive impls typically cannot overlap with one another either, except as permitted by specialization.) + +## Interaction with auto traits + +Declaring a negative impl `impl !SomeAutoTrait for SomeType` for an +auto-trait serves two purposes: + +* as with any trait, it declares that `SomeType` will never implement `SomeAutoTrait`; +* it disables the automatic `SomeType: SomeAutoTrait` impl that would otherwise have been generated. + +Note that, at present, there is no way to indicate that a given type +does not implement an auto trait *but that it may do so in the +future*. For ordinary types, this is done by simply not declaring any +impl at all, but that is not an option for auto traits. A workaround +is that one could embed a marker type as one of the fields, where the +marker type is `!AutoTrait`. + +## Immediate uses + +Negative impls are used to declare that `&T: !DerefMut` and `&mut T: !Clone`, as required to fix the soundness of `Pin` described in [#66544](https://github.com/rust-lang/rust/issues/66544). + +This serves two purposes: + +* For proving the correctness of unsafe code, we can use that impl as evidence that no `DerefMut` or `Clone` impl exists. +* It prevents downstream crates from creating such impls. diff --git a/src/doc/unstable-book/src/language-features/optin-builtin-traits.md b/src/doc/unstable-book/src/language-features/optin-builtin-traits.md index 5c8124c9c6b7d..6f0f0cfd33e4d 100644 --- a/src/doc/unstable-book/src/language-features/optin-builtin-traits.md +++ b/src/doc/unstable-book/src/language-features/optin-builtin-traits.md @@ -10,18 +10,20 @@ The `optin_builtin_traits` feature gate allows you to define auto traits. Auto traits, like [`Send`] or [`Sync`] in the standard library, are marker traits that are automatically implemented for every type, unless the type, or a type it contains, -has explicitly opted out via a negative impl. +has explicitly opted out via a negative impl. (Negative impls are separately controlled +by the `negative_impls` feature.) [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html ```rust,ignore -impl !Type for Trait +impl !Trait for Type ``` Example: ```rust +#![feature(negative_impls)] #![feature(optin_builtin_traits)] auto trait Valid {} @@ -43,3 +45,63 @@ fn main() { // must_be_valid( MaybeValid(False) ); } ``` + +## Automatic trait implementations + +When a type is declared as an `auto trait`, we will automatically +create impls for every struct/enum/union, unless an explicit impl is +provided. These automatic impls contain a where clause for each field +of the form `T: AutoTrait`, where `T` is the type of the field and +`AutoTrait` is the auto trait in question. As an example, consider the +struct `List` and the auto trait `Send`: + +```rust +struct List { + data: T, + next: Option>>, +} +``` + +Presuming that there is no explicit impl of `Send` for `List`, the +compiler will supply an automatic impl of the form: + +```rust +struct List { + data: T, + next: Option>>, +} + +unsafe impl Send for List +where + T: Send, // from the field `data` + Option>>: Send, // from the field `next` +{ } +``` + +Explicit impls may be either positive or negative. They take the form: + +```rust,ignore +impl<...> AutoTrait for StructName<..> { } +impl<...> !AutoTrait for StructName<..> { } +``` + +## Coinduction: Auto traits permit cyclic matching + +Unlike ordinary trait matching, auto traits are **coinductive**. This +means, in short, that cycles which occur in trait matching are +considered ok. As an example, consider the recursive struct `List` +introduced in the previous section. In attempting to determine whether +`List: Send`, we would wind up in a cycle: to apply the impl, we must +show that `Option>: Send`, which will in turn require +`Box: Send` and then finally `List: Send` again. Under ordinary +trait matching, this cycle would be an error, but for an auto trait it +is considered a successful match. + +## Items + +Auto traits cannot have any trait items, such as methods or associated types. This ensures that we can generate default implementations. + +## Supertraits + +Auto traits cannot have supertraits. This is for soundness reasons, as the interaction of coinduction with implied bounds is difficult to reconcile. + diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py index 0914c22eb13f0..51dfc3fff3f92 100755 --- a/src/etc/gdb_rust_pretty_printing.py +++ b/src/etc/gdb_rust_pretty_printing.py @@ -335,7 +335,7 @@ def children(self): def children_of_node(boxed_node, height, want_values): node_ptr = boxed_node['ptr']['pointer'] if height > 0: - type_name = str(node_ptr.type.target()).replace('LeafNode', 'InternalNode') + type_name = str(node_ptr.type.target()).replace('LeafNode', 'InternalNode', 1) node_type = gdb.lookup_type(type_name) node_ptr = node_ptr.cast(node_type.pointer()) leaf = node_ptr['data'] @@ -370,12 +370,17 @@ def to_string(self): ("(len: %i)" % self.__val.get_wrapped_value()['map']['length'])) def children(self): - root = self.__val.get_wrapped_value()['map']['root'] - node_ptr = root['node'] - i = 0 - for child in children_of_node(node_ptr, root['height'], False): - yield (str(i), child) - i = i + 1 + prev_idx = None + innermap = GdbValue(self.__val.get_wrapped_value()['map']) + if innermap.get_wrapped_value()['length'] > 0: + root = GdbValue(innermap.get_wrapped_value()['root']) + type_name = str(root.type.ty.name).replace('core::option::Option<', '')[:-1] + root = root.get_wrapped_value().cast(gdb.lookup_type(type_name)) + node_ptr = root['node'] + i = 0 + for child in children_of_node(node_ptr, root['height'], False): + yield (str(i), child) + i = i + 1 class RustStdBTreeMapPrinter(object): @@ -391,13 +396,16 @@ def to_string(self): ("(len: %i)" % self.__val.get_wrapped_value()['length'])) def children(self): - root = self.__val.get_wrapped_value()['root'] - node_ptr = root['node'] - i = 0 - for child in children_of_node(node_ptr, root['height'], True): - yield (str(i), child[0]) - yield (str(i), child[1]) - i = i + 1 + if self.__val.get_wrapped_value()['length'] > 0: + root = GdbValue(self.__val.get_wrapped_value()['root']) + type_name = str(root.type.ty.name).replace('core::option::Option<', '')[:-1] + root = root.get_wrapped_value().cast(gdb.lookup_type(type_name)) + node_ptr = root['node'] + i = 0 + for child in children_of_node(node_ptr, root['height'], True): + yield (str(i), child[0]) + yield (str(i), child[1]) + i = i + 1 class RustStdStringPrinter(object): diff --git a/src/etc/lldb_batchmode.py b/src/etc/lldb_batchmode.py index d9c4bc5562f00..629c8e04ec533 100644 --- a/src/etc/lldb_batchmode.py +++ b/src/etc/lldb_batchmode.py @@ -139,11 +139,17 @@ def listen(): def start_watchdog(): """Starts a watchdog thread that will terminate the process after a certain period of time""" - watchdog_start_time = time.clock() + + try: + from time import clock + except ImportError: + from time import perf_counter as clock + + watchdog_start_time = clock() watchdog_max_time = watchdog_start_time + 30 def watchdog(): - while time.clock() < watchdog_max_time: + while clock() < watchdog_max_time: time.sleep(1) print("TIMEOUT: lldb_batchmode.py has been running for too long. Aborting!") thread.interrupt_main() diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 9a7d0d9aebaaf..36641284a769b 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -1105,29 +1105,6 @@ impl AsMut for Box { #[stable(feature = "pin", since = "1.33.0")] impl Unpin for Box {} -#[cfg(bootstrap)] -#[unstable(feature = "generator_trait", issue = "43122")] -impl Generator for Box { - type Yield = G::Yield; - type Return = G::Return; - - fn resume(mut self: Pin<&mut Self>) -> GeneratorState { - G::resume(Pin::new(&mut *self)) - } -} - -#[cfg(bootstrap)] -#[unstable(feature = "generator_trait", issue = "43122")] -impl Generator for Pin> { - type Yield = G::Yield; - type Return = G::Return; - - fn resume(mut self: Pin<&mut Self>) -> GeneratorState { - G::resume((*self).as_mut()) - } -} - -#[cfg(not(bootstrap))] #[unstable(feature = "generator_trait", issue = "43122")] impl + Unpin, R> Generator for Box { type Yield = G::Yield; @@ -1138,7 +1115,6 @@ impl + Unpin, R> Generator for Box { } } -#[cfg(not(bootstrap))] #[unstable(feature = "generator_trait", issue = "43122")] impl, R> Generator for Pin> { type Yield = G::Yield; diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index 9da324ba2d4f1..bde66c406af7f 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -122,7 +122,7 @@ use UnderflowResult::*; /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub struct BTreeMap { - root: node::Root, + root: Option>, length: usize, } @@ -147,10 +147,11 @@ impl Clone for BTreeMap { { match node.force() { Leaf(leaf) => { - let mut out_tree = BTreeMap { root: node::Root::new_leaf(), length: 0 }; + let mut out_tree = BTreeMap { root: Some(node::Root::new_leaf()), length: 0 }; { - let mut out_node = match out_tree.root.as_mut().force() { + let root = out_tree.root.as_mut().unwrap(); + let mut out_node = match root.as_mut().force() { Leaf(leaf) => leaf, Internal(_) => unreachable!(), }; @@ -169,9 +170,14 @@ impl Clone for BTreeMap { } Internal(internal) => { let mut out_tree = clone_subtree(internal.first_edge().descend()); + out_tree.ensure_root_is_owned(); { - let mut out_node = out_tree.root.push_level(); + // Ideally we'd use the return of ensure_root_is_owned + // instead of re-unwrapping here but unfortunately that + // borrows all of out_tree and we need access to the + // length below. + let mut out_node = out_tree.root.as_mut().unwrap().push_level(); let mut in_edge = internal.first_edge(); while let Ok(kv) = in_edge.right_kv() { let (k, v) = kv.into_kv(); @@ -190,7 +196,7 @@ impl Clone for BTreeMap { (root, length) }; - out_node.push(k, v, subroot); + out_node.push(k, v, subroot.unwrap_or_else(node::Root::new_leaf)); out_tree.length += 1 + sublength; } } @@ -203,9 +209,9 @@ impl Clone for BTreeMap { if self.is_empty() { // Ideally we'd call `BTreeMap::new` here, but that has the `K: // Ord` constraint, which this method lacks. - BTreeMap { root: node::Root::shared_empty_root(), length: 0 } + BTreeMap { root: None, length: 0 } } else { - clone_subtree(self.root.as_ref()) + clone_subtree(self.root.as_ref().unwrap().as_ref()) } } @@ -271,14 +277,14 @@ where type Key = K; fn get(&self, key: &Q) -> Option<&K> { - match search::search_tree(self.root.as_ref(), key) { + match search::search_tree(self.root.as_ref()?.as_ref(), key) { Found(handle) => Some(handle.into_kv().0), GoDown(_) => None, } } fn take(&mut self, key: &Q) -> Option { - match search::search_tree(self.root.as_mut(), key) { + match search::search_tree(self.root.as_mut()?.as_mut(), key) { Found(handle) => Some( OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData } .remove_kv() @@ -290,7 +296,7 @@ where fn replace(&mut self, key: K) -> Option { self.ensure_root_is_owned(); - match search::search_tree::, K, (), K>(self.root.as_mut(), &key) { + match search::search_tree::, K, (), K>(self.root.as_mut()?.as_mut(), &key) { Found(handle) => Some(mem::replace(handle.into_kv_mut().0, key)), GoDown(handle) => { VacantEntry { key, handle, length: &mut self.length, _marker: PhantomData } @@ -344,15 +350,18 @@ pub struct IterMut<'a, K: 'a, V: 'a> { /// [`BTreeMap`]: struct.BTreeMap.html #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter { - front: Handle, marker::Edge>, - back: Handle, marker::Edge>, + front: Option, marker::Edge>>, + back: Option, marker::Edge>>, length: usize, } #[stable(feature = "collection_debug", since = "1.17.0")] impl fmt::Debug for IntoIter { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let range = Range { front: self.front.reborrow(), back: self.back.reborrow() }; + let range = Range { + front: self.front.as_ref().map(|f| f.reborrow()), + back: self.back.as_ref().map(|b| b.reborrow()), + }; f.debug_list().entries(range).finish() } } @@ -417,8 +426,8 @@ pub struct ValuesMut<'a, K: 'a, V: 'a> { /// [`BTreeMap`]: struct.BTreeMap.html #[stable(feature = "btree_range", since = "1.17.0")] pub struct Range<'a, K: 'a, V: 'a> { - front: Handle, K, V, marker::Leaf>, marker::Edge>, - back: Handle, K, V, marker::Leaf>, marker::Edge>, + front: Option, K, V, marker::Leaf>, marker::Edge>>, + back: Option, K, V, marker::Leaf>, marker::Edge>>, } #[stable(feature = "collection_debug", since = "1.17.0")] @@ -437,8 +446,8 @@ impl fmt::Debug for Range<'_, K, V> { /// [`BTreeMap`]: struct.BTreeMap.html #[stable(feature = "btree_range", since = "1.17.0")] pub struct RangeMut<'a, K: 'a, V: 'a> { - front: Handle, K, V, marker::Leaf>, marker::Edge>, - back: Handle, K, V, marker::Leaf>, marker::Edge>, + front: Option, K, V, marker::Leaf>, marker::Edge>>, + back: Option, K, V, marker::Leaf>, marker::Edge>>, // Be invariant in `K` and `V` _marker: PhantomData<&'a mut (K, V)>, @@ -447,7 +456,10 @@ pub struct RangeMut<'a, K: 'a, V: 'a> { #[stable(feature = "collection_debug", since = "1.17.0")] impl fmt::Debug for RangeMut<'_, K, V> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let range = Range { front: self.front.reborrow(), back: self.back.reborrow() }; + let range = Range { + front: self.front.as_ref().map(|f| f.reborrow()), + back: self.back.as_ref().map(|b| b.reborrow()), + }; f.debug_list().entries(range).finish() } } @@ -544,7 +556,7 @@ impl BTreeMap { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new() -> BTreeMap { - BTreeMap { root: node::Root::shared_empty_root(), length: 0 } + BTreeMap { root: None, length: 0 } } /// Clears the map, removing all elements. @@ -589,7 +601,7 @@ impl BTreeMap { K: Borrow, Q: Ord, { - match search::search_tree(self.root.as_ref(), key) { + match search::search_tree(self.root.as_ref()?.as_ref(), key) { Found(handle) => Some(handle.into_kv().1), GoDown(_) => None, } @@ -616,7 +628,7 @@ impl BTreeMap { K: Borrow, Q: Ord, { - match search::search_tree(self.root.as_ref(), k) { + match search::search_tree(self.root.as_ref()?.as_ref(), k) { Found(handle) => Some(handle.into_kv()), GoDown(_) => None, } @@ -645,7 +657,7 @@ impl BTreeMap { T: Ord, K: Borrow, { - let front = self.root.as_ref().first_leaf_edge(); + let front = self.root.as_ref()?.as_ref().first_leaf_edge(); front.right_kv().ok().map(Handle::into_kv) } @@ -674,7 +686,7 @@ impl BTreeMap { T: Ord, K: Borrow, { - let front = self.root.as_mut().first_leaf_edge(); + let front = self.root.as_mut()?.as_mut().first_leaf_edge(); if let Ok(kv) = front.right_kv() { Some(OccupiedEntry { handle: kv.forget_node_type(), @@ -708,7 +720,7 @@ impl BTreeMap { T: Ord, K: Borrow, { - let back = self.root.as_ref().last_leaf_edge(); + let back = self.root.as_ref()?.as_ref().last_leaf_edge(); back.left_kv().ok().map(Handle::into_kv) } @@ -737,7 +749,7 @@ impl BTreeMap { T: Ord, K: Borrow, { - let back = self.root.as_mut().last_leaf_edge(); + let back = self.root.as_mut()?.as_mut().last_leaf_edge(); if let Ok(kv) = back.left_kv() { Some(OccupiedEntry { handle: kv.forget_node_type(), @@ -801,7 +813,7 @@ impl BTreeMap { K: Borrow, Q: Ord, { - match search::search_tree(self.root.as_mut(), key) { + match search::search_tree(self.root.as_mut()?.as_mut(), key) { Found(handle) => Some(handle.into_kv_mut().1), GoDown(_) => None, } @@ -896,7 +908,7 @@ impl BTreeMap { K: Borrow, Q: Ord, { - match search::search_tree(self.root.as_mut(), key) { + match search::search_tree(self.root.as_mut()?.as_mut(), key) { Found(handle) => Some( OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData } .remove_entry(), @@ -992,11 +1004,15 @@ impl BTreeMap { K: Borrow, R: RangeBounds, { - let root1 = self.root.as_ref(); - let root2 = self.root.as_ref(); - let (f, b) = range_search(root1, root2, range); + if let Some(root) = &self.root { + let root1 = root.as_ref(); + let root2 = root.as_ref(); + let (f, b) = range_search(root1, root2, range); - Range { front: f, back: b } + Range { front: Some(f), back: Some(b) } + } else { + Range { front: None, back: None } + } } /// Constructs a mutable double-ended iterator over a sub-range of elements in the map. @@ -1036,11 +1052,15 @@ impl BTreeMap { K: Borrow, R: RangeBounds, { - let root1 = self.root.as_mut(); - let root2 = unsafe { ptr::read(&root1) }; - let (f, b) = range_search(root1, root2, range); + if let Some(root) = &mut self.root { + let root1 = root.as_mut(); + let root2 = unsafe { ptr::read(&root1) }; + let (f, b) = range_search(root1, root2, range); - RangeMut { front: f, back: b, _marker: PhantomData } + RangeMut { front: Some(f), back: Some(b), _marker: PhantomData } + } else { + RangeMut { front: None, back: None, _marker: PhantomData } + } } /// Gets the given key's corresponding entry in the map for in-place manipulation. @@ -1065,7 +1085,7 @@ impl BTreeMap { pub fn entry(&mut self, key: K) -> Entry<'_, K, V> { // FIXME(@porglezomp) Avoid allocating if we don't insert self.ensure_root_is_owned(); - match search::search_tree(self.root.as_mut(), &key) { + match search::search_tree(self.root.as_mut().unwrap().as_mut(), &key) { Found(handle) => { Occupied(OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData }) } @@ -1077,7 +1097,7 @@ impl BTreeMap { fn from_sorted_iter>(&mut self, iter: I) { self.ensure_root_is_owned(); - let mut cur_node = self.root.as_mut().last_leaf_edge().into_node(); + let mut cur_node = self.root.as_mut().unwrap().as_mut().last_leaf_edge().into_node(); // Iterate through all key-value pairs, pushing them into nodes at the right level. for (key, value) in iter { // Try to push key-value pair into the current leaf node. @@ -1126,7 +1146,7 @@ impl BTreeMap { fn fix_right_edge(&mut self) { // Handle underfull nodes, start from the top. - let mut cur_node = self.root.as_mut(); + let mut cur_node = self.root.as_mut().unwrap().as_mut(); while let Internal(internal) = cur_node.force() { // Check if right-most child is underfull. let mut last_edge = internal.last_edge(); @@ -1187,14 +1207,14 @@ impl BTreeMap { let total_num = self.len(); let mut right = Self::new(); - right.root = node::Root::new_leaf(); - for _ in 0..(self.root.as_ref().height()) { - right.root.push_level(); + let right_root = right.ensure_root_is_owned(); + for _ in 0..(self.root.as_ref().unwrap().as_ref().height()) { + right_root.push_level(); } { - let mut left_node = self.root.as_mut(); - let mut right_node = right.root.as_mut(); + let mut left_node = self.root.as_mut().unwrap().as_mut(); + let mut right_node = right.root.as_mut().unwrap().as_mut(); loop { let mut split_edge = match search::search_node(left_node, key) { @@ -1223,7 +1243,9 @@ impl BTreeMap { self.fix_right_border(); right.fix_left_border(); - if self.root.as_ref().height() < right.root.as_ref().height() { + if self.root.as_ref().unwrap().as_ref().height() + < right.root.as_ref().unwrap().as_ref().height() + { self.recalc_length(); right.length = total_num - self.len(); } else { @@ -1261,19 +1283,19 @@ impl BTreeMap { res } - self.length = dfs(self.root.as_ref()); + self.length = dfs(self.root.as_ref().unwrap().as_ref()); } /// Removes empty levels on the top. fn fix_top(&mut self) { loop { { - let node = self.root.as_ref(); + let node = self.root.as_ref().unwrap().as_ref(); if node.height() == 0 || node.len() > 0 { break; } } - self.root.pop_level(); + self.root.as_mut().unwrap().pop_level(); } } @@ -1281,7 +1303,7 @@ impl BTreeMap { self.fix_top(); { - let mut cur_node = self.root.as_mut(); + let mut cur_node = self.root.as_mut().unwrap().as_mut(); while let Internal(node) = cur_node.force() { let mut last_kv = node.last_kv(); @@ -1307,7 +1329,7 @@ impl BTreeMap { self.fix_top(); { - let mut cur_node = self.root.as_mut(); + let mut cur_node = self.root.as_mut().unwrap().as_mut(); while let Internal(node) = cur_node.force() { let mut first_kv = node.first_kv(); @@ -1326,13 +1348,6 @@ impl BTreeMap { self.fix_top(); } - - /// If the root node is the shared root node, allocate our own node. - fn ensure_root_is_owned(&mut self) { - if self.root.is_shared_root() { - self.root = node::Root::new_leaf(); - } - } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1458,12 +1473,21 @@ impl IntoIterator for BTreeMap { type IntoIter = IntoIter; fn into_iter(self) -> IntoIter { - let root1 = unsafe { ptr::read(&self.root).into_ref() }; - let root2 = unsafe { ptr::read(&self.root).into_ref() }; + if self.root.is_none() { + mem::forget(self); + return IntoIter { front: None, back: None, length: 0 }; + } + + let root1 = unsafe { unwrap_unchecked(ptr::read(&self.root)).into_ref() }; + let root2 = unsafe { unwrap_unchecked(ptr::read(&self.root)).into_ref() }; let len = self.length; mem::forget(self); - IntoIter { front: root1.first_leaf_edge(), back: root2.last_leaf_edge(), length: len } + IntoIter { + front: Some(root1.first_leaf_edge()), + back: Some(root2.last_leaf_edge()), + length: len, + } } } @@ -1478,9 +1502,9 @@ impl Drop for IntoIter { // don't have to care about panics this time (they'll abort). while let Some(_) = self.0.next() {} - // No need to avoid the shared root, because the tree was definitely not empty. unsafe { - let mut node = ptr::read(&self.0.front).into_node().forget_type(); + let mut node = + unwrap_unchecked(ptr::read(&self.0.front)).into_node().forget_type(); while let Some(parent) = node.deallocate_and_ascend() { node = parent.into_node().forget_type(); } @@ -1495,14 +1519,13 @@ impl Drop for IntoIter { } unsafe { - let mut node = ptr::read(&self.front).into_node().forget_type(); - if node.is_shared_root() { - return; - } - // Most of the nodes have been deallocated while traversing - // but one pile from a leaf up to the root is left standing. - while let Some(parent) = node.deallocate_and_ascend() { - node = parent.into_node().forget_type(); + if let Some(front) = ptr::read(&self.front) { + let mut node = front.into_node().forget_type(); + // Most of the nodes have been deallocated while traversing + // but one pile from a leaf up to the root is left standing. + while let Some(parent) = node.deallocate_and_ascend() { + node = parent.into_node().forget_type(); + } } } } @@ -1517,7 +1540,7 @@ impl Iterator for IntoIter { None } else { self.length -= 1; - Some(unsafe { self.front.next_unchecked() }) + Some(unsafe { self.front.as_mut().unwrap().next_unchecked() }) } } @@ -1533,7 +1556,7 @@ impl DoubleEndedIterator for IntoIter { None } else { self.length -= 1; - Some(unsafe { self.back.next_back_unchecked() }) + Some(unsafe { self.back.as_mut().unwrap().next_back_unchecked() }) } } } @@ -1683,7 +1706,7 @@ impl<'a, K, V> Range<'a, K, V> { } unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) { - self.front.next_unchecked() + unwrap_unchecked(self.front.as_mut()).next_unchecked() } } @@ -1696,7 +1719,7 @@ impl<'a, K, V> DoubleEndedIterator for Range<'a, K, V> { impl<'a, K, V> Range<'a, K, V> { unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) { - self.back.next_back_unchecked() + unwrap_unchecked(self.back.as_mut()).next_back_unchecked() } } @@ -1734,7 +1757,7 @@ impl<'a, K, V> RangeMut<'a, K, V> { } unsafe fn next_unchecked(&mut self) -> (&'a mut K, &'a mut V) { - self.front.next_unchecked() + unwrap_unchecked(self.front.as_mut()).next_unchecked() } } @@ -1755,7 +1778,7 @@ impl FusedIterator for RangeMut<'_, K, V> {} impl<'a, K, V> RangeMut<'a, K, V> { unsafe fn next_back_unchecked(&mut self) -> (&'a mut K, &'a mut V) { - self.back.next_back_unchecked() + unwrap_unchecked(self.back.as_mut()).next_back_unchecked() } } @@ -1969,8 +1992,8 @@ impl BTreeMap { pub fn iter(&self) -> Iter<'_, K, V> { Iter { range: Range { - front: self.root.as_ref().first_leaf_edge(), - back: self.root.as_ref().last_leaf_edge(), + front: self.root.as_ref().map(|r| r.as_ref().first_leaf_edge()), + back: self.root.as_ref().map(|r| r.as_ref().last_leaf_edge()), }, length: self.length, } @@ -1999,13 +2022,17 @@ impl BTreeMap { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn iter_mut(&mut self) -> IterMut<'_, K, V> { - let root1 = self.root.as_mut(); - let root2 = unsafe { ptr::read(&root1) }; IterMut { - range: RangeMut { - front: root1.first_leaf_edge(), - back: root2.last_leaf_edge(), - _marker: PhantomData, + range: if let Some(root) = &mut self.root { + let root1 = root.as_mut(); + let root2 = unsafe { ptr::read(&root1) }; + RangeMut { + front: Some(root1.first_leaf_edge()), + back: Some(root2.last_leaf_edge()), + _marker: PhantomData, + } + } else { + RangeMut { front: None, back: None, _marker: PhantomData } }, length: self.length, } @@ -2116,6 +2143,12 @@ impl BTreeMap { pub fn is_empty(&self) -> bool { self.len() == 0 } + + /// If the root node is the empty (non-allocated) root node, allocate our + /// own node. + fn ensure_root_is_owned(&mut self) -> &mut node::Root { + self.root.get_or_insert_with(node::Root::new_leaf) + } } impl<'a, K: Ord, V> Entry<'a, K, V> { diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs index 1132ffdaf8005..6ebb98c42cd4f 100644 --- a/src/liballoc/collections/btree/node.rs +++ b/src/liballoc/collections/btree/node.rs @@ -44,34 +44,7 @@ const B: usize = 6; pub const MIN_LEN: usize = B - 1; pub const CAPACITY: usize = 2 * B - 1; -/// The underlying representation of leaf nodes. Note that it is often unsafe to actually store -/// these, since only the first `len` keys and values are assumed to be initialized. As such, -/// these should always be put behind pointers, and specifically behind `BoxedNode` in the owned -/// case. -/// -/// We have a separate type for the header and rely on it matching the prefix of `LeafNode`, in -/// order to statically allocate a single dummy node to avoid allocations. This struct is -/// `repr(C)` to prevent them from being reordered. `LeafNode` does not just contain a -/// `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`.) -#[repr(C)] -struct NodeHeader { - /// 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, - - /// This node's index into the parent node's `edges` array. - /// `*node.parent.edges[node.parent_idx]` should be the same thing as `node`. - /// This is only guaranteed to be initialized when `parent` is non-null. - parent_idx: MaybeUninit, - - /// The number of keys and values this node stores. - /// - /// 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, -} +/// The underlying representation of leaf nodes. #[repr(C)] struct LeafNode { /// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`. @@ -111,21 +84,6 @@ impl LeafNode { } } -impl NodeHeader { - fn is_shared_root(&self) -> bool { - ptr::eq(self, &EMPTY_ROOT_NODE as *const _ as *const _) - } -} - -// We need to implement Sync here in order to make a static instance. -unsafe impl Sync for NodeHeader<(), ()> {} - -// An empty node used as a placeholder for the root node, to avoid allocations. -// 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 }; - /// 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 /// `InternalNode` can be directly casted to a pointer to the underlying `LeafNode` portion of the @@ -154,12 +112,9 @@ impl InternalNode { } /// A managed, non-null pointer to a node. This is either an owned pointer to -/// `LeafNode`, an owned pointer to `InternalNode`, or a (not owned) -/// pointer to `NodeHeader<(), ()` (more specifically, the pointer to EMPTY_ROOT_NODE). -/// All of these types have a `NodeHeader` prefix, meaning that they have at -/// least the same size as `NodeHeader` and store the same kinds of data at the same -/// offsets; and they have a pointer alignment at least as large as `NodeHeader`'s. -/// However, `BoxedNode` contains no information as to which of the three types +/// `LeafNode` or an owned pointer to `InternalNode`. +/// +/// However, `BoxedNode` contains no information as to which of the two types /// of nodes it actually contains, and, partially due to this lack of information, /// has no destructor. struct BoxedNode { @@ -184,8 +139,9 @@ impl BoxedNode { } } -/// Either an owned tree or a shared, empty tree. Note that this does not have a destructor, -/// and must be cleaned up manually if it is an owned tree. +/// An owned tree. +/// +/// Note that this does not have a destructor, and must be cleaned up manually. pub struct Root { node: BoxedNode, /// The number of levels below the root node. @@ -196,20 +152,6 @@ unsafe impl Sync for Root {} unsafe impl Send for Root {} impl Root { - /// Whether the instance of `Root` wraps a shared, empty root node. If not, - /// the entire tree is uniquely owned by the owner of the `Root` instance. - pub fn is_shared_root(&self) -> bool { - self.as_ref().is_shared_root() - } - - /// Returns a shared tree, wrapping a shared root node that is eternally empty. - pub fn shared_empty_root() -> Self { - Root { - node: unsafe { BoxedNode::from_ptr(NonNull::from(&EMPTY_ROOT_NODE).cast()) }, - height: 0, - } - } - /// Returns a new owned tree, with its own root node that is initially empty. pub fn new_leaf() -> Self { Root { node: BoxedNode::from_leaf(Box::new(unsafe { LeafNode::new() })), height: 0 } @@ -245,7 +187,6 @@ impl Root { /// Adds a new internal node with a single edge, pointing to the previous root, and make that /// new node the root. This increases the height by 1 and is the opposite of `pop_level`. pub fn push_level(&mut self) -> NodeRef, K, V, marker::Internal> { - debug_assert!(!self.is_shared_root()); let mut new_node = Box::new(unsafe { InternalNode::new() }); new_node.edges[0].write(unsafe { BoxedNode::from_ptr(self.node.as_ptr()) }); @@ -308,11 +249,6 @@ impl Root { /// `Leaf`, the `NodeRef` points to a leaf node, when this is `Internal` the /// `NodeRef` points to an internal node, and when this is `LeafOrInternal` the /// `NodeRef` could be pointing to either type of node. -/// Note that in case of a leaf node, this might still be the shared root! -/// Only turn this into a `LeafNode` reference if you know it is not the shared root! -/// Shared references must be dereferenceable *for the entire size of their pointee*, -/// so '&LeafNode` or `&InternalNode` pointing to the shared root is undefined behavior. -/// Turning this into a `NodeHeader` reference is always safe. pub struct NodeRef { /// The number of levels below the node. height: usize, @@ -354,7 +290,7 @@ impl NodeRef { /// Note that, despite being safe, calling this function can have the side effect /// of invalidating mutable references that unsafe code has created. pub fn len(&self) -> usize { - self.as_header().len as usize + self.as_leaf().len as usize } /// Returns the height of this node in the whole tree. Zero height denotes the @@ -374,35 +310,24 @@ impl NodeRef { NodeRef { height: self.height, node: self.node, root: self.root, _marker: PhantomData } } - /// Exposes the leaf "portion" of any leaf or internal node that is not the shared root. + /// Exposes the leaf "portion" of any leaf or internal node. /// If the node is a leaf, this function simply opens up its data. /// If the node is an internal node, so not a leaf, it does have all the data a leaf has /// (header, keys and values), and this function exposes that. - /// Unsafe because the node must not be the shared root. For more information, - /// see the `NodeRef` comments. - unsafe fn as_leaf(&self) -> &LeafNode { - debug_assert!(!self.is_shared_root()); - self.node.as_ref() - } - - fn as_header(&self) -> &NodeHeader { - unsafe { &*(self.node.as_ptr() as *const NodeHeader) } - } - - /// Returns whether the node is the shared, empty root. - pub fn is_shared_root(&self) -> bool { - self.as_header().is_shared_root() + fn as_leaf(&self) -> &LeafNode { + // The node must be valid for at least the LeafNode portion. + // This is not a reference in the NodeRef type because we don't know if + // it should be unique or shared. + unsafe { self.node.as_ref() } } /// Borrows a view into the keys stored in the node. - /// Unsafe because the caller must ensure that the node is not the shared root. - pub unsafe fn keys(&self) -> &[K] { + pub fn keys(&self) -> &[K] { self.reborrow().into_key_slice() } /// Borrows a view into the values stored in the node. - /// Unsafe because the caller must ensure that the node is not the shared root. - unsafe fn vals(&self) -> &[V] { + fn vals(&self) -> &[V] { self.reborrow().into_val_slice() } @@ -416,7 +341,7 @@ impl NodeRef { pub fn ascend( self, ) -> Result, marker::Edge>, Self> { - let parent_as_leaf = self.as_header().parent as *const LeafNode; + let parent_as_leaf = self.as_leaf().parent as *const LeafNode; if let Some(non_zero) = NonNull::new(parent_as_leaf as *mut _) { Ok(Handle { node: NodeRef { @@ -425,7 +350,7 @@ impl NodeRef { root: self.root, _marker: PhantomData, }, - idx: unsafe { usize::from(*self.as_header().parent_idx.as_ptr()) }, + idx: unsafe { usize::from(*self.as_leaf().parent_idx.as_ptr()) }, _marker: PhantomData, }) } else { @@ -464,7 +389,6 @@ impl NodeRef { pub unsafe fn deallocate_and_ascend( self, ) -> Option, marker::Edge>> { - assert!(!self.is_shared_root()); let height = self.height; let node = self.node; let ret = self.ascend().ok(); @@ -507,41 +431,37 @@ impl<'a, K, V, Type> NodeRef, K, V, Type> { /// (header, keys and values), and this function exposes that. /// /// Returns a raw ptr to avoid asserting exclusive access to the entire node. - /// This also implies you can invoke this member on the shared root, but the resulting pointer - /// might not be properly aligned and definitely would not allow accessing keys and values. fn as_leaf_mut(&mut self) -> *mut LeafNode { self.node.as_ptr() } - /// Unsafe because the caller must ensure that the node is not the shared root. - unsafe fn keys_mut(&mut self) -> &mut [K] { - self.reborrow_mut().into_key_slice_mut() + fn keys_mut(&mut self) -> &mut [K] { + // SAFETY: the caller will not be able to call further methods on self + // until the key slice reference is dropped, as we have unique access + // for the lifetime of the borrow. + unsafe { self.reborrow_mut().into_key_slice_mut() } } - /// Unsafe because the caller must ensure that the node is not the shared root. - unsafe fn vals_mut(&mut self) -> &mut [V] { - self.reborrow_mut().into_val_slice_mut() + fn vals_mut(&mut self) -> &mut [V] { + // SAFETY: the caller will not be able to call further methods on self + // until the value slice reference is dropped, as we have unique access + // for the lifetime of the borrow. + unsafe { self.reborrow_mut().into_val_slice_mut() } } } impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { - /// Unsafe because 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()) + fn into_key_slice(self) -> &'a [K] { + unsafe { slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().keys), self.len()) } } - /// Unsafe because the caller must ensure that the node is not the shared root. - unsafe fn into_val_slice(self) -> &'a [V] { - 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().vals), self.len()) + fn into_val_slice(self) -> &'a [V] { + unsafe { slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().vals), self.len()) } } - /// Unsafe because the caller must ensure that the node is not the shared root. - unsafe fn into_slices(self) -> (&'a [K], &'a [V]) { - let k = ptr::read(&self); + fn into_slices(self) -> (&'a [K], &'a [V]) { + // SAFETY: equivalent to reborrow() except not requiring Type: 'a + let k = unsafe { ptr::read(&self) }; (k.into_key_slice(), self.into_val_slice()) } } @@ -553,28 +473,27 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { unsafe { &mut *(self.root as *mut Root) } } - /// Unsafe because the caller must ensure that the node is not the shared root. - unsafe fn into_key_slice_mut(mut self) -> &'a mut [K] { - debug_assert!(!self.is_shared_root()); - // We cannot be the shared root, so `as_leaf_mut` is okay. - slice::from_raw_parts_mut( - MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).keys), - self.len(), - ) + fn into_key_slice_mut(mut self) -> &'a mut [K] { + // SAFETY: The keys of a node must always be initialized up to length. + unsafe { + slice::from_raw_parts_mut( + MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).keys), + self.len(), + ) + } } - /// Unsafe because the caller must ensure that the node is not the shared root. - unsafe fn into_val_slice_mut(mut self) -> &'a mut [V] { - debug_assert!(!self.is_shared_root()); - slice::from_raw_parts_mut( - MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).vals), - self.len(), - ) + fn into_val_slice_mut(mut self) -> &'a mut [V] { + // SAFETY: The values of a node must always be initialized up to length. + unsafe { + slice::from_raw_parts_mut( + MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).vals), + self.len(), + ) + } } - /// Unsafe because the caller must ensure that the node is not the shared root. - unsafe fn into_slices_mut(mut self) -> (&'a mut [K], &'a mut [V]) { - debug_assert!(!self.is_shared_root()); + fn into_slices_mut(mut self) -> (&'a mut [K], &'a mut [V]) { // We cannot use the getters here, because calling the second one // invalidates the reference returned by the first. // More precisely, it is the call to `len` that is the culprit, @@ -582,8 +501,13 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { // overlap with the keys (and even the values, for ZST keys). let len = self.len(); let leaf = self.as_leaf_mut(); - let keys = slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).keys), len); - let vals = slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).vals), len); + // SAFETY: The keys and values of a node must always be initialized up to length. + let keys = unsafe { + slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).keys), len) + }; + let vals = unsafe { + slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).vals), len) + }; (keys, vals) } } @@ -592,7 +516,6 @@ impl<'a, K, V> NodeRef, K, V, marker::Leaf> { /// Adds a key/value pair the end of the node. pub fn push(&mut self, key: K, val: V) { assert!(self.len() < CAPACITY); - debug_assert!(!self.is_shared_root()); let idx = self.len(); @@ -607,7 +530,6 @@ impl<'a, K, V> NodeRef, K, V, marker::Leaf> { /// Adds a key/value pair to the beginning of the node. pub fn push_front(&mut self, key: K, val: V) { assert!(self.len() < CAPACITY); - debug_assert!(!self.is_shared_root()); unsafe { slice_insert(self.keys_mut(), 0, key); @@ -624,7 +546,6 @@ impl<'a, K, V> NodeRef, K, V, marker::Internal> { pub fn push(&mut self, key: K, val: V, edge: Root) { assert!(edge.height == self.height - 1); assert!(self.len() < CAPACITY); - debug_assert!(!self.is_shared_root()); let idx = self.len(); @@ -658,7 +579,6 @@ impl<'a, K, V> NodeRef, K, V, marker::Internal> { pub fn push_front(&mut self, key: K, val: V, edge: Root) { assert!(edge.height == self.height - 1); assert!(self.len() < CAPACITY); - debug_assert!(!self.is_shared_root()); unsafe { slice_insert(self.keys_mut(), 0, key); @@ -744,8 +664,7 @@ impl<'a, K, V> NodeRef, K, V, marker::LeafOrInternal> { } } - /// Unsafe because the caller must ensure that the node is not the shared root. - unsafe fn into_kv_pointers_mut(mut self) -> (*mut K, *mut V) { + fn into_kv_pointers_mut(mut self) -> (*mut K, *mut V) { (self.keys_mut().as_mut_ptr(), self.vals_mut().as_mut_ptr()) } } @@ -904,7 +823,6 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::Edge fn insert_fit(&mut self, key: K, val: V) -> *mut V { // Necessary for correctness, but in a private module debug_assert!(self.node.len() < CAPACITY); - debug_assert!(!self.node.is_shared_root()); unsafe { slice_insert(self.node.keys_mut(), self.idx, key); @@ -1081,7 +999,6 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::KV> /// - All the key/value pairs to the right of this handle are put into a newly /// allocated node. pub fn split(mut self) -> (NodeRef, K, V, marker::Leaf>, K, V, Root) { - assert!(!self.node.is_shared_root()); unsafe { let mut new_node = Box::new(LeafNode::new()); @@ -1113,7 +1030,6 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::KV> pub fn remove( mut self, ) -> (Handle, K, V, marker::Leaf>, marker::Edge>, K, V) { - assert!(!self.node.is_shared_root()); unsafe { let k = slice_remove(self.node.keys_mut(), self.idx); let v = slice_remove(self.node.vals_mut(), self.idx); diff --git a/src/liballoc/collections/btree/search.rs b/src/liballoc/collections/btree/search.rs index 2ba5cebbdee74..4e80f7f21ebff 100644 --- a/src/liballoc/collections/btree/search.rs +++ b/src/liballoc/collections/btree/search.rs @@ -67,19 +67,16 @@ where Q: Ord, K: Borrow, { - // This function is defined over all borrow types (immutable, mutable, owned), - // and may be called on the shared root in each case. + // This function is defined over all borrow types (immutable, mutable, owned). // Using `keys()` is fine here even if BorrowType is mutable, as all we return // is an index -- not a reference. 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), - } + let keys = node.keys(); + for (i, k) in keys.iter().enumerate() { + match key.cmp(k.borrow()) { + Ordering::Greater => {} + Ordering::Equal => return (i, true), + Ordering::Less => return (i, false), } } (len, false) diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs index 73ae267ddab7f..53d4f7239b76e 100644 --- a/src/liballoc/collections/linked_list.rs +++ b/src/liballoc/collections/linked_list.rs @@ -1427,7 +1427,7 @@ impl<'a, T> CursorMut<'a, T> { /// `CursorMut`, which means it cannot outlive the `CursorMut` and that the /// `CursorMut` is frozen for the lifetime of the `Cursor`. #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn as_cursor<'cm>(&'cm self) -> Cursor<'cm, T> { + pub fn as_cursor(&self) -> Cursor<'_, T> { Cursor { list: self.list, current: self.current, index: self.index } } } diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 9d56f17700a85..69284fbf1b37d 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -1876,6 +1876,7 @@ impl VecDeque { /// assert_eq!(buf2, [2, 3]); /// ``` #[inline] + #[must_use = "use `.truncate()` if you don't need the other half"] #[stable(feature = "split_off", since = "1.4.0")] pub fn split_off(&mut self, at: usize) -> Self { let len = self.len(); diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index ffa4176cc7969..5857b79d5eeeb 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -80,6 +80,7 @@ #![feature(box_into_raw_non_null)] #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(cfg_sanitize)] #![feature(cfg_target_has_atomic)] #![feature(coerce_unsized)] #![feature(const_generic_impls_guard)] @@ -98,6 +99,7 @@ #![feature(internal_uninit_const)] #![feature(lang_items)] #![feature(libc)] +#![cfg_attr(not(bootstrap), feature(negative_impls))] #![feature(nll)] #![feature(optin_builtin_traits)] #![feature(pattern)] @@ -160,6 +162,8 @@ pub mod str; pub mod string; #[cfg(target_has_atomic = "ptr")] pub mod sync; +#[cfg(target_has_atomic = "ptr")] +pub mod task; #[cfg(test)] mod tests; pub mod vec; diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 9c286298aa65c..e7f7608e676a2 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -259,6 +259,10 @@ use crate::vec::Vec; #[cfg(test)] mod tests; +// This is repr(C) to future-proof against possible field-reordering, which +// would interfere with otherwise safe [into|from]_raw() of transmutable +// inner types. +#[repr(C)] struct RcBox { strong: Cell, weak: Cell, @@ -580,15 +584,24 @@ impl Rc { } } - /// Constructs an `Rc` from a raw pointer. + /// Constructs an `Rc` from a raw pointer. /// - /// The raw pointer must have been previously returned by a call to a - /// [`Rc::into_raw`][into_raw]. + /// The raw pointer must have been previously returned by a call to + /// [`Rc::into_raw`][into_raw] where `U` must have the same size + /// and alignment as `T`. This is trivially true if `U` is `T`. + /// Note that if `U` is not `T` but has the same size and alignment, this is + /// basically like transmuting references of different types. See + /// [`mem::transmute`][transmute] for more information on what + /// restrictions apply in this case. /// - /// This function is unsafe because improper use may lead to memory problems. For example, a - /// double-free may occur if the function is called twice on the same raw pointer. + /// The user of `from_raw` has to make sure a specific value of `T` is only + /// dropped once. + /// + /// This function is unsafe because improper use may lead to memory unsafety, + /// even if the returned `Rc` is never accessed. /// /// [into_raw]: struct.Rc.html#method.into_raw + /// [transmute]: ../../std/mem/fn.transmute.html /// /// # Examples /// diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 7b83658fca60d..d8fc1faca3a39 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -145,8 +145,7 @@ mod hack { unsafe { let len = b.len(); let b = Box::into_raw(b); - let xs = Vec::from_raw_parts(b as *mut T, len, len); - xs + Vec::from_raw_parts(b as *mut T, len, len) } } diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index c95f79472fe57..7c89d38caa4e6 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -1461,6 +1461,7 @@ impl String { /// ``` #[inline] #[stable(feature = "string_split_off", since = "1.16.0")] + #[must_use = "use `.truncate()` if you don't need the other half"] pub fn split_off(&mut self, at: usize) -> String { assert!(self.is_char_boundary(at)); let other = self.vec.split_off(at); @@ -2225,6 +2226,17 @@ impl From<&str> for String { } } +#[stable(feature = "from_mut_str_for_string", since = "1.44.0")] +impl From<&mut str> for String { + /// Converts a `&mut str` into a `String`. + /// + /// The result is allocated on the heap. + #[inline] + fn from(s: &mut str) -> String { + s.to_owned() + } +} + #[stable(feature = "from_ref_string", since = "1.35.0")] impl From<&String> for String { #[inline] diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 4a0cf2984edd9..e8985e202567b 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -40,6 +40,23 @@ mod tests; /// necessarily) at _exactly_ `MAX_REFCOUNT + 1` references. const MAX_REFCOUNT: usize = (isize::MAX) as usize; +#[cfg(not(sanitize = "thread"))] +macro_rules! acquire { + ($x:expr) => { + atomic::fence(Acquire) + }; +} + +// ThreadSanitizer does not support memory fences. To avoid false positive +// reports in Arc / Weak implementation use atomic loads for synchronization +// instead. +#[cfg(sanitize = "thread")] +macro_rules! acquire { + ($x:expr) => { + $x.load(Acquire) + }; +} + /// A thread-safe reference-counting pointer. 'Arc' stands for 'Atomically /// Reference Counted'. /// @@ -270,6 +287,10 @@ impl fmt::Debug for Weak { } } +// This is repr(C) to future-proof against possible field-reordering, which +// would interfere with otherwise safe [into|from]_raw() of transmutable +// inner types. +#[repr(C)] struct ArcInner { strong: atomic::AtomicUsize, @@ -402,7 +423,7 @@ impl Arc { return Err(this); } - atomic::fence(Acquire); + acquire!(this.inner().strong); unsafe { let elem = ptr::read(&this.ptr.as_ref().data); @@ -560,15 +581,24 @@ impl Arc { } } - /// Constructs an `Arc` from a raw pointer. + /// Constructs an `Arc` from a raw pointer. + /// + /// The raw pointer must have been previously returned by a call to + /// [`Arc::into_raw`][into_raw] where `U` must have the same size and + /// alignment as `T`. This is trivially true if `U` is `T`. + /// Note that if `U` is not `T` but has the same size and alignment, this is + /// basically like transmuting references of different types. See + /// [`mem::transmute`][transmute] for more information on what + /// restrictions apply in this case. /// - /// The raw pointer must have been previously returned by a call to a - /// [`Arc::into_raw`][into_raw]. + /// The user of `from_raw` has to make sure a specific value of `T` is only + /// dropped once. /// - /// This function is unsafe because improper use may lead to memory problems. For example, a - /// double-free may occur if the function is called twice on the same raw pointer. + /// This function is unsafe because improper use may lead to memory unsafety, + /// even if the returned `Arc` is never accessed. /// /// [into_raw]: struct.Arc.html#method.into_raw + /// [transmute]: ../../std/mem/fn.transmute.html /// /// # Examples /// @@ -739,7 +769,7 @@ impl Arc { ptr::drop_in_place(&mut self.ptr.as_mut().data); if self.inner().weak.fetch_sub(1, Release) == 1 { - atomic::fence(Acquire); + acquire!(self.inner().weak); Global.dealloc(self.ptr.cast(), Layout::for_value(self.ptr.as_ref())) } } @@ -1243,7 +1273,7 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc { // // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) // [2]: (https://github.com/rust-lang/rust/pull/41714) - atomic::fence(Acquire); + acquire!(self.inner().strong); unsafe { self.drop_slow(); @@ -1701,7 +1731,7 @@ impl Drop for Weak { let inner = if let Some(inner) = self.inner() { inner } else { return }; if inner.weak.fetch_sub(1, Release) == 1 { - atomic::fence(Acquire); + acquire!(inner.weak); unsafe { Global.dealloc(self.ptr.cast(), Layout::for_value(self.ptr.as_ref())) } } } diff --git a/src/liballoc/task.rs b/src/liballoc/task.rs new file mode 100644 index 0000000000000..981095302c730 --- /dev/null +++ b/src/liballoc/task.rs @@ -0,0 +1,87 @@ +#![unstable(feature = "wake_trait", issue = "69912")] +//! Types and Traits for working with asynchronous tasks. +use core::mem::{self, ManuallyDrop}; +use core::task::{RawWaker, RawWakerVTable, Waker}; + +use crate::sync::Arc; + +/// The implementation of waking a task on an executor. +/// +/// This trait can be used to create a [`Waker`]. An executor can define an +/// implementation of this trait, and use that to construct a Waker to pass +/// to the tasks that are executed on that executor. +/// +/// This trait is a memory-safe and ergonomic alternative to constructing a +/// [`RawWaker`]. It supports the common executor design in which the data +/// used to wake up a task is stored in an [`Arc`]. Some executors (especially +/// those for embedded systems) cannot use this API, which is why [`RawWaker`] +/// exists as an alternative for those systems. +#[unstable(feature = "wake_trait", issue = "69912")] +pub trait Wake { + /// Wake this task. + #[unstable(feature = "wake_trait", issue = "69912")] + fn wake(self: Arc); + + /// Wake this task without consuming the waker. + /// + /// If an executor supports a cheaper way to wake without consuming the + /// waker, it should override this method. By default, it clones the + /// [`Arc`] and calls `wake` on the clone. + #[unstable(feature = "wake_trait", issue = "69912")] + fn wake_by_ref(self: &Arc) { + self.clone().wake(); + } +} + +#[unstable(feature = "wake_trait", issue = "69912")] +impl From> for Waker { + fn from(waker: Arc) -> Waker { + // SAFETY: This is safe because raw_waker safely constructs + // a RawWaker from Arc. + unsafe { Waker::from_raw(raw_waker(waker)) } + } +} + +#[unstable(feature = "wake_trait", issue = "69912")] +impl From> for RawWaker { + fn from(waker: Arc) -> RawWaker { + raw_waker(waker) + } +} + +// NB: This private function for constructing a RawWaker is used, rather than +// inlining this into the `From> for RawWaker` impl, to ensure that +// the safety of `From> for Waker` does not depend on the correct +// trait dispatch - instead both impls call this function directly and +// explicitly. +#[inline(always)] +fn raw_waker(waker: Arc) -> RawWaker { + // Increment the reference count of the arc to clone it. + unsafe fn clone_waker(waker: *const ()) -> RawWaker { + let waker: Arc = Arc::from_raw(waker as *const W); + mem::forget(Arc::clone(&waker)); + raw_waker(waker) + } + + // Wake by value, moving the Arc into the Wake::wake function + unsafe fn wake(waker: *const ()) { + let waker: Arc = Arc::from_raw(waker as *const W); + ::wake(waker); + } + + // Wake by reference, wrap the waker in ManuallyDrop to avoid dropping it + unsafe fn wake_by_ref(waker: *const ()) { + let waker: ManuallyDrop> = ManuallyDrop::new(Arc::from_raw(waker as *const W)); + ::wake_by_ref(&waker); + } + + // Decrement the reference count of the Arc on drop + unsafe fn drop_waker(waker: *const ()) { + mem::drop(Arc::from_raw(waker as *const W)); + } + + RawWaker::new( + Arc::into_raw(waker) as *const (), + &RawWakerVTable::new(clone_waker::, wake::, wake_by_ref::, drop_waker::), + ) +} diff --git a/src/liballoc/tests/btree/map.rs b/src/liballoc/tests/btree/map.rs index d05eec19346de..3a3462d546f7a 100644 --- a/src/liballoc/tests/btree/map.rs +++ b/src/liballoc/tests/btree/map.rs @@ -67,7 +67,7 @@ fn test_basic_large() { #[test] fn test_basic_small() { let mut map = BTreeMap::new(); - // Empty, shared root: + // Empty, root is absent (None): assert_eq!(map.remove(&1), None); assert_eq!(map.len(), 0); assert_eq!(map.get(&1), None); @@ -123,7 +123,7 @@ fn test_basic_small() { assert_eq!(map.values().collect::>(), vec![&4]); assert_eq!(map.remove(&2), Some(4)); - // Empty but private root: + // Empty but root is owned (Some(...)): assert_eq!(map.len(), 0); assert_eq!(map.get(&1), None); assert_eq!(map.get_mut(&1), None); @@ -263,13 +263,6 @@ fn test_iter_mut_mutation() { do_test_iter_mut_mutation::(144); } -#[test] -fn test_into_key_slice_with_shared_root_past_bounds() { - let mut map: BTreeMap = BTreeMap::new(); - assert_eq!(map.get(&Align32(1)), None); - assert_eq!(map.get_mut(&Align32(1)), None); -} - #[test] fn test_values_mut() { let mut a = BTreeMap::new(); diff --git a/src/liballoc/tests/string.rs b/src/liballoc/tests/string.rs index 08859b2b24bde..d2f09eb4a7568 100644 --- a/src/liballoc/tests/string.rs +++ b/src/liballoc/tests/string.rs @@ -266,14 +266,14 @@ fn test_split_off_empty() { fn test_split_off_past_end() { let orig = "Hello, world!"; let mut split = String::from(orig); - split.split_off(orig.len() + 1); + let _ = split.split_off(orig.len() + 1); } #[test] #[should_panic] fn test_split_off_mid_char() { let mut orig = String::from("山"); - orig.split_off(1); + let _ = orig.split_off(1); } #[test] diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index d1956270f135f..4769091183a37 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1377,6 +1377,7 @@ impl Vec { /// assert_eq!(vec2, [2, 3]); /// ``` #[inline] + #[must_use = "use `.truncate()` if you don't need the other half"] #[stable(feature = "split_off", since = "1.4.0")] pub fn split_off(&mut self, at: usize) -> Self { assert!(at <= self.len(), "`at` out of bounds"); diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 2a3d92edc4956..0f0bd617f439c 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -488,5 +488,187 @@ impl DroplessArena { } } +/// Calls the destructor for an object when dropped. +struct DropType { + drop_fn: unsafe fn(*mut u8), + obj: *mut u8, +} + +unsafe fn drop_for_type(to_drop: *mut u8) { + std::ptr::drop_in_place(to_drop as *mut T) +} + +impl Drop for DropType { + fn drop(&mut self) { + unsafe { (self.drop_fn)(self.obj) } + } +} + +/// An arena which can be used to allocate any type. +/// Allocating in this arena is unsafe since the type system +/// doesn't know which types it contains. In order to +/// allocate safely, you must store a PhantomData +/// alongside this arena for each type T you allocate. +#[derive(Default)] +pub struct DropArena { + /// A list of destructors to run when the arena drops. + /// Ordered so `destructors` gets dropped before the arena + /// since its destructor can reference memory in the arena. + destructors: RefCell>, + arena: DroplessArena, +} + +impl DropArena { + #[inline] + pub unsafe fn alloc(&self, object: T) -> &mut T { + let mem = + self.arena.alloc_raw(mem::size_of::(), mem::align_of::()) as *mut _ as *mut T; + // Write into uninitialized memory. + ptr::write(mem, object); + let result = &mut *mem; + // Record the destructor after doing the allocation as that may panic + // and would cause `object`'s destuctor to run twice if it was recorded before + self.destructors + .borrow_mut() + .push(DropType { drop_fn: drop_for_type::, obj: result as *mut T as *mut u8 }); + result + } + + #[inline] + pub unsafe fn alloc_from_iter>(&self, iter: I) -> &mut [T] { + let mut vec: SmallVec<[_; 8]> = iter.into_iter().collect(); + if vec.is_empty() { + return &mut []; + } + let len = vec.len(); + + let start_ptr = self + .arena + .alloc_raw(len.checked_mul(mem::size_of::()).unwrap(), mem::align_of::()) + as *mut _ as *mut T; + + let mut destructors = self.destructors.borrow_mut(); + // Reserve space for the destructors so we can't panic while adding them + destructors.reserve(len); + + // Move the content to the arena by copying it and then forgetting + // the content of the SmallVec + vec.as_ptr().copy_to_nonoverlapping(start_ptr, len); + mem::forget(vec.drain(..)); + + // Record the destructors after doing the allocation as that may panic + // and would cause `object`'s destuctor to run twice if it was recorded before + for i in 0..len { + destructors.push(DropType { + drop_fn: drop_for_type::, + obj: start_ptr.offset(i as isize) as *mut u8, + }); + } + + slice::from_raw_parts_mut(start_ptr, len) + } +} + +#[macro_export] +macro_rules! arena_for_type { + ([][$ty:ty]) => { + $crate::TypedArena<$ty> + }; + ([few $(, $attrs:ident)*][$ty:ty]) => { + ::std::marker::PhantomData<$ty> + }; + ([$ignore:ident $(, $attrs:ident)*]$args:tt) => { + $crate::arena_for_type!([$($attrs),*]$args) + }; +} + +#[macro_export] +macro_rules! which_arena_for_type { + ([][$arena:expr]) => { + ::std::option::Option::Some($arena) + }; + ([few$(, $attrs:ident)*][$arena:expr]) => { + ::std::option::Option::None + }; + ([$ignore:ident$(, $attrs:ident)*]$args:tt) => { + $crate::which_arena_for_type!([$($attrs),*]$args) + }; +} + +#[macro_export] +macro_rules! declare_arena { + ([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => { + #[derive(Default)] + pub struct Arena<$tcx> { + pub dropless: $crate::DroplessArena, + drop: $crate::DropArena, + $($name: $crate::arena_for_type!($a[$ty]),)* + } + + #[marker] + pub trait ArenaAllocatable {} + + impl ArenaAllocatable for T {} + + unsafe trait ArenaField<'tcx>: Sized { + /// Returns a specific arena to allocate from. + /// If `None` is returned, the `DropArena` will be used. + fn arena<'a>(arena: &'a Arena<'tcx>) -> Option<&'a $crate::TypedArena>; + } + + unsafe impl<'tcx, T> ArenaField<'tcx> for T { + #[inline] + default fn arena<'a>(_: &'a Arena<'tcx>) -> Option<&'a $crate::TypedArena> { + panic!() + } + } + + $( + #[allow(unused_lifetimes)] + impl<$tcx> ArenaAllocatable for $ty {} + unsafe impl<$tcx> ArenaField<$tcx> for $ty { + #[inline] + fn arena<'a>(_arena: &'a Arena<$tcx>) -> Option<&'a $crate::TypedArena> { + $crate::which_arena_for_type!($a[&_arena.$name]) + } + } + )* + + impl<'tcx> Arena<'tcx> { + #[inline] + pub fn alloc(&self, value: T) -> &mut T { + if !::std::mem::needs_drop::() { + return self.dropless.alloc(value); + } + match >::arena(self) { + ::std::option::Option::Some(arena) => arena.alloc(value), + ::std::option::Option::None => unsafe { self.drop.alloc(value) }, + } + } + + #[inline] + pub fn alloc_slice(&self, value: &[T]) -> &mut [T] { + if value.is_empty() { + return &mut []; + } + self.dropless.alloc_slice(value) + } + + pub fn alloc_from_iter<'a, T: ArenaAllocatable>( + &'a self, + iter: impl ::std::iter::IntoIterator, + ) -> &'a mut [T] { + if !::std::mem::needs_drop::() { + return self.dropless.alloc_from_iter(iter); + } + match >::arena(self) { + ::std::option::Option::Some(arena) => arena.alloc_from_iter(iter), + ::std::option::Option::None => unsafe { self.drop.alloc_from_iter(iter) }, + } + } + } + } +} + #[cfg(test)] mod tests; diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index d2a513451ccb6..be20a1cde3694 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -140,6 +140,42 @@ impl Layout { unsafe { Layout::from_size_align_unchecked(size, align) } } + /// Produces layout describing a record that could be used to + /// allocate backing structure for `T` (which could be a trait + /// or other unsized type like a slice). + /// + /// # Safety + /// + /// This function is only safe to call if the following conditions hold: + /// + /// - If `T` is `Sized`, this function is always safe to call. + /// - If the unsized tail of `T` is: + /// - a [slice], then the length of the slice tail must be an intialized + /// integer, and the size of the *entire value* + /// (dynamic tail length + statically sized prefix) must fit in `isize`. + /// - a [trait object], then the vtable part of the pointer must point + /// to a valid vtable acquired by an unsizing coersion, and the size + /// of the *entire value* (dynamic tail length + statically sized prefix) + /// must fit in `isize`. + /// - an (unstable) [extern type], then this function is always safe to + /// call, but may panic or otherwise return the wrong value, as the + /// extern type's layout is not known. This is the same behavior as + /// [`Layout::for_value`] on a reference to an extern type tail. + /// - otherwise, it is conservatively not allowed to call this function. + /// + /// [slice]: ../../std/primitive.slice.html + /// [trait object]: ../../book/ch17-02-trait-objects.html + /// [extern type]: ../../unstable-book/language-features/extern-types.html + #[inline] + #[cfg(not(bootstrap))] + #[unstable(feature = "layout_for_ptr", issue = "69835")] + pub unsafe fn for_value_raw(t: *const T) -> Self { + let (size, align) = (mem::size_of_val_raw(t), mem::align_of_val_raw(t)); + // See rationale in `new` for why this is using an unsafe variant below + debug_assert!(Layout::from_size_align(size, align).is_ok()); + Layout::from_size_align_unchecked(size, align) + } + /// Creates a `NonNull` that is dangling, but well-aligned for this Layout. /// /// Note that the pointer value may potentially represent a valid pointer, diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 97ef513cbcc63..39df803bbea30 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -164,7 +164,7 @@ impl dyn Any { // Get `TypeId` of the type this function is instantiated with. let t = TypeId::of::(); - // Get `TypeId` of the type in the trait object. + // Get `TypeId` of the type in the trait object (`self`). let concrete = self.type_id(); // Compare both `TypeId`s on equality. diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 9ebb317641875..a922d4f118b5a 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -958,6 +958,33 @@ impl RefCell { unsafe { &mut *self.value.get() } } + /// Undo the effect of leaked guards on the borrow state of the `RefCell`. + /// + /// This call is similar to [`get_mut`] but more specialized. It borrows `RefCell` mutably to + /// ensure no borrows exist and then resets the state tracking shared borrows. This is relevant + /// if some `Ref` or `RefMut` borrows have been leaked. + /// + /// [`get_mut`]: #method.get_mut + /// + /// # Examples + /// + /// ``` + /// #![feature(cell_leak)] + /// use std::cell::RefCell; + /// + /// let mut c = RefCell::new(0); + /// std::mem::forget(c.borrow_mut()); + /// + /// assert!(c.try_borrow().is_err()); + /// c.undo_leak(); + /// assert!(c.try_borrow().is_ok()); + /// ``` + #[unstable(feature = "cell_leak", issue = "69099")] + pub fn undo_leak(&mut self) -> &mut T { + *self.borrow.get_mut() = UNUSED; + self.get_mut() + } + /// Immutably borrows the wrapped value, returning an error if the value is /// currently mutably borrowed. /// @@ -1272,8 +1299,10 @@ impl<'b, T: ?Sized> Ref<'b, T> { /// ``` #[unstable(feature = "cell_leak", issue = "69099")] pub fn leak(orig: Ref<'b, T>) -> &'b T { - // By forgetting this Ref we ensure that the borrow counter in the RefCell never goes back - // to UNUSED again. No further mutable references can be created from the original cell. + // By forgetting this Ref we ensure that the borrow counter in the RefCell can't go back to + // UNUSED within the lifetime `'b`. Resetting the reference tracking state would require a + // unique reference to the borrowed RefCell. No further mutable references can be created + // from the original cell. mem::forget(orig.borrow); orig.value } @@ -1387,9 +1416,11 @@ impl<'b, T: ?Sized> RefMut<'b, T> { /// ``` #[unstable(feature = "cell_leak", issue = "69099")] pub fn leak(orig: RefMut<'b, T>) -> &'b mut T { - // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell never - // goes back to UNUSED again. No further references can be created from the original cell, - // making the current borrow the only reference for the remaining lifetime. + // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell can't + // go back to UNUSED within the lifetime `'b`. Resetting the reference tracking state would + // require a unique reference to the borrowed RefCell. No further references can be created + // from the original cell within that lifetime, making the current borrow the only + // reference for the remaining lifetime. mem::forget(orig.borrow); orig.value } @@ -1538,7 +1569,7 @@ impl fmt::Display for RefMut<'_, T> { #[lang = "unsafe_cell"] #[stable(feature = "rust1", since = "1.0.0")] #[repr(transparent)] -#[cfg_attr(not(bootstrap), repr(no_niche))] // rust-lang/rust#68303. +#[repr(no_niche)] // rust-lang/rust#68303. pub struct UnsafeCell { value: T, } diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 9a412e5729427..eb101fc72fd9e 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -219,7 +219,7 @@ mod impls { } } - // Shared references can be cloned, but mutable references *cannot*! + /// Shared references can be cloned, but mutable references *cannot*! #[stable(feature = "rust1", since = "1.0.0")] impl Clone for &T { #[inline] @@ -227,4 +227,9 @@ mod impls { *self } } + + /// Shared references can be cloned, but mutable references *cannot*! + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(not(bootstrap))] + impl !Clone for &mut T {} } diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index a93b34fc46cb9..fe728d42c76f7 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -282,10 +282,10 @@ impl<'a> ArgumentV1<'a> { // SAFETY: `mem::transmute(x)` is safe because // 1. `&'b T` keeps the lifetime it originated with `'b` // (so as to not have an unbounded lifetime) - // 2. `&'b T` and `&'b Void` have the same memory layout + // 2. `&'b T` and `&'b Opaque` have the same memory layout // (when `T` is `Sized`, as it is here) // `mem::transmute(f)` is safe since `fn(&T, &mut Formatter<'_>) -> Result` - // and `fn(&Void, &mut Formatter<'_>) -> Result` have the same ABI + // and `fn(&Opaque, &mut Formatter<'_>) -> Result` have the same ABI // (as long as `T` is `Sized`) unsafe { ArgumentV1 { formatter: mem::transmute(f), value: mem::transmute(x) } } } diff --git a/src/libcore/future/mod.rs b/src/libcore/future/mod.rs index 89ea4713cfdaa..8dfda7a4a3236 100644 --- a/src/libcore/future/mod.rs +++ b/src/libcore/future/mod.rs @@ -2,6 +2,84 @@ //! Asynchronous values. +#[cfg(not(bootstrap))] +use crate::{ + ops::{Generator, GeneratorState}, + pin::Pin, + ptr::NonNull, + task::{Context, Poll}, +}; + mod future; #[stable(feature = "futures_api", since = "1.36.0")] pub use self::future::Future; + +/// This type is needed because: +/// +/// a) Generators cannot implement `for<'a, 'b> Generator<&'a mut Context<'b>>`, so we need to pass +/// a raw pointer (see https://github.com/rust-lang/rust/issues/68923). +/// b) Raw pointers and `NonNull` aren't `Send` or `Sync`, so that would make every single future +/// non-Send/Sync as well, and we don't want that. +/// +/// It also simplifies the HIR lowering of `.await`. +#[doc(hidden)] +#[unstable(feature = "gen_future", issue = "50547")] +#[cfg(not(bootstrap))] +#[derive(Debug, Copy, Clone)] +pub struct ResumeTy(NonNull>); + +#[unstable(feature = "gen_future", issue = "50547")] +#[cfg(not(bootstrap))] +unsafe impl Send for ResumeTy {} + +#[unstable(feature = "gen_future", issue = "50547")] +#[cfg(not(bootstrap))] +unsafe impl Sync for ResumeTy {} + +/// Wrap a generator in a future. +/// +/// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give +/// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`). +// This is `const` to avoid extra errors after we recover from `const async fn` +#[doc(hidden)] +#[unstable(feature = "gen_future", issue = "50547")] +#[cfg(not(bootstrap))] +#[inline] +pub const fn from_generator(gen: T) -> impl Future +where + T: Generator, +{ + struct GenFuture>(T); + + // We rely on the fact that async/await futures are immovable in order to create + // self-referential borrows in the underlying generator. + impl> !Unpin for GenFuture {} + + impl> Future for GenFuture { + type Output = T::Return; + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + // Safety: Safe because we're !Unpin + !Drop, and this is just a field projection. + let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) }; + + // Resume the generator, turning the `&mut Context` into a `NonNull` raw pointer. The + // `.await` lowering will safely cast that back to a `&mut Context`. + match gen.resume(ResumeTy(NonNull::from(cx).cast::>())) { + GeneratorState::Yielded(()) => Poll::Pending, + GeneratorState::Complete(x) => Poll::Ready(x), + } + } + } + + GenFuture(gen) +} + +#[doc(hidden)] +#[unstable(feature = "gen_future", issue = "50547")] +#[cfg(not(bootstrap))] +#[inline] +pub unsafe fn poll_with_context(f: Pin<&mut F>, mut cx: ResumeTy) -> Poll +where + F: Future, +{ + F::poll(f, cx.0.as_mut()) +} diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index aa50e7cdf578d..adfbe243512bd 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -220,37 +220,6 @@ impl Hasher { self.state.v3 = self.k1 ^ 0x7465646279746573; self.ntail = 0; } - - // Specialized write function that is only valid for buffers with len <= 8. - // It's used to force inlining of write_u8 and write_usize, those would normally be inlined - // except for composite types (that includes slices and str hashing because of delimiter). - // Without this extra push the compiler is very reluctant to inline delimiter writes, - // degrading performance substantially for the most common use cases. - #[inline] - fn short_write(&mut self, msg: &[u8]) { - debug_assert!(msg.len() <= 8); - let length = msg.len(); - self.length += length; - - let needed = 8 - self.ntail; - let fill = cmp::min(length, needed); - if fill == 8 { - self.tail = unsafe { load_int_le!(msg, 0, u64) }; - } else { - self.tail |= unsafe { u8to64_le(msg, 0, fill) } << (8 * self.ntail); - if length < needed { - self.ntail += length; - return; - } - } - self.state.v3 ^= self.tail; - S::c_rounds(&mut self.state); - self.state.v0 ^= self.tail; - - // Buffered tail is now flushed, process new input. - self.ntail = length - needed; - self.tail = unsafe { u8to64_le(msg, needed, self.ntail) }; - } } #[stable(feature = "rust1", since = "1.0.0")] @@ -280,21 +249,13 @@ impl super::Hasher for SipHasher13 { } impl super::Hasher for Hasher { - // see short_write comment for explanation - #[inline] - fn write_usize(&mut self, i: usize) { - let bytes = unsafe { - crate::slice::from_raw_parts(&i as *const usize as *const u8, mem::size_of::()) - }; - self.short_write(bytes); - } - - // see short_write comment for explanation - #[inline] - fn write_u8(&mut self, i: u8) { - self.short_write(&[i]); - } - + // Note: no integer hashing methods (`write_u*`, `write_i*`) are defined + // for this type. We could add them, copy the `short_write` implementation + // in librustc_data_structures/sip128.rs, and add `write_u*`/`write_i*` + // methods to `SipHasher`, `SipHasher13`, and `DefaultHasher`. This would + // greatly speed up integer hashing by those hashers, at the cost of + // slightly slowing down compile speeds on some benchmarks. See #69152 for + // details. #[inline] fn write(&mut self, msg: &[u8]) { let length = msg.len(); diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs index f4fb9ab1757cd..6cbd26a78de72 100644 --- a/src/libcore/hint.rs +++ b/src/libcore/hint.rs @@ -114,6 +114,6 @@ pub fn black_box(dummy: T) -> T { // more than we want, but it's so far good enough. unsafe { asm!("" : : "r"(&dummy)); - return dummy; + dummy } } diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 3c060cc6e840b..eb71497cc4782 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -980,13 +980,24 @@ extern "rust-intrinsic" { /// /// The stabilized version of this intrinsic is /// [`std::mem::size_of_val`](../../std/mem/fn.size_of_val.html). + #[cfg(bootstrap)] pub fn size_of_val(_: &T) -> usize; /// The minimum alignment of the type of the value that `val` points to. /// /// The stabilized version of this intrinsic is /// [`std::mem::min_align_of_val`](../../std/mem/fn.min_align_of_val.html). + #[cfg(bootstrap)] pub fn min_align_of_val(_: &T) -> usize; + /// The size of the referenced value in bytes. + /// + /// The stabilized version of this intrinsic is + /// [`std::mem::size_of_val`](../../std/mem/fn.size_of_val.html). + #[cfg(not(bootstrap))] + pub fn size_of_val(_: *const T) -> usize; + #[cfg(not(bootstrap))] + pub fn min_align_of_val(_: *const T) -> usize; + /// Gets a static string slice containing the name of a type. /// /// The stabilized version of this intrinsic is @@ -1005,62 +1016,30 @@ extern "rust-intrinsic" { /// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited: /// This will statically either panic, or do nothing. + #[cfg(bootstrap)] pub fn panic_if_uninhabited(); + /// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited: + /// This will statically either panic, or do nothing. + #[cfg(not(bootstrap))] + pub fn assert_inhabited(); + /// A guard for unsafe functions that cannot ever be executed if `T` does not permit /// zero-initialization: This will statically either panic, or do nothing. #[cfg(not(bootstrap))] - pub fn panic_if_zero_invalid(); + pub fn assert_zero_valid(); /// A guard for unsafe functions that cannot ever be executed if `T` has invalid /// bit patterns: This will statically either panic, or do nothing. #[cfg(not(bootstrap))] - pub fn panic_if_any_invalid(); + pub fn assert_uninit_valid(); /// Gets a reference to a static `Location` indicating where it was called. #[rustc_const_unstable(feature = "const_caller_location", issue = "47809")] pub fn caller_location() -> &'static crate::panic::Location<'static>; - /// Creates a value initialized to zero. - /// - /// `init` is unsafe because it returns a zeroed-out datum, - /// which is unsafe unless `T` is `Copy`. Also, even if T is - /// `Copy`, an all-zero value may not correspond to any legitimate - /// state for the type in question. - /// - /// The stabilized version of this intrinsic is - /// [`std::mem::zeroed`](../../std/mem/fn.zeroed.html). - #[unstable( - feature = "core_intrinsics", - reason = "intrinsics are unlikely to ever be stabilized, instead \ - they should be used through stabilized interfaces \ - in the rest of the standard library", - issue = "none" - )] - #[rustc_deprecated(reason = "superseded by MaybeUninit, removal planned", since = "1.38.0")] - pub fn init() -> T; - - /// Creates an uninitialized value. - /// - /// `uninit` is unsafe because there is no guarantee of what its - /// contents are. In particular its drop-flag may be set to any - /// state, which means it may claim either dropped or - /// undropped. In the general case one must use `ptr::write` to - /// initialize memory previous set to the result of `uninit`. - /// - /// The stabilized version of this intrinsic is - /// [`std::mem::MaybeUninit`](../../std/mem/union.MaybeUninit.html). - #[unstable( - feature = "core_intrinsics", - reason = "intrinsics are unlikely to ever be stabilized, instead \ - they should be used through stabilized interfaces \ - in the rest of the standard library", - issue = "none" - )] - #[rustc_deprecated(reason = "superseded by MaybeUninit, removal planned", since = "1.38.0")] - pub fn uninit() -> T; - /// Moves a value out of scope without running drop glue. + /// This exists solely for `mem::forget_unsized`; normal `forget` uses `ManuallyDrop` instead. pub fn forget(_: T); /// Reinterprets the bits of a value of one type as another type. @@ -1865,14 +1844,16 @@ extern "rust-intrinsic" { #[rustc_const_unstable(feature = "const_discriminant", issue = "69821")] pub fn discriminant_value(v: &T) -> u64; - /// Rust's "try catch" construct which invokes the function pointer `f` with - /// the data pointer `data`. + /// Rust's "try catch" construct which invokes the function pointer `try_fn` + /// with the data pointer `data`. /// - /// The third pointer is a target-specific data pointer which is filled in - /// with the specifics of the exception that occurred. For examples on Unix - /// platforms this is a `*mut *mut T` which is filled in by the compiler and - /// on MSVC it's `*mut [usize; 2]`. For more information see the compiler's + /// The third argument is a function called if a panic occurs. This function + /// takes the data pointer and a pointer to the target-specific exception + /// object that was caught. For more information see the compiler's /// source as well as std's catch implementation. + #[cfg(not(bootstrap))] + pub fn r#try(try_fn: fn(*mut u8), data: *mut u8, catch_fn: fn(*mut u8, *mut u8)) -> i32; + #[cfg(bootstrap)] pub fn r#try(f: fn(*mut u8), data: *mut u8, local_ptr: *mut u8) -> i32; /// Emits a `!nontemporal` store according to LLVM (see their docs). @@ -1884,10 +1865,12 @@ extern "rust-intrinsic" { pub fn ptr_offset_from(ptr: *const T, base: *const T) -> isize; /// Internal hook used by Miri to implement unwinding. - /// Compiles to a NOP during non-Miri codegen. + /// ICEs when encountered during non-Miri codegen. + /// + /// The `payload` ptr here will be exactly the one `do_catch` gets passed by `try`. /// - /// Perma-unstable: do not use - pub fn miri_start_panic(data: *mut (dyn crate::any::Any + crate::marker::Send)) -> (); + /// Perma-unstable: do not use. + pub fn miri_start_panic(payload: *mut u8) -> !; } // Some functions are defined here because they accidentally got made diff --git a/src/libcore/iter/adapters/flatten.rs b/src/libcore/iter/adapters/flatten.rs index 0a7a9f26f8912..4202e52448dcf 100644 --- a/src/libcore/iter/adapters/flatten.rs +++ b/src/libcore/iter/adapters/flatten.rs @@ -1,7 +1,7 @@ use crate::fmt; use crate::ops::Try; -use super::super::{DoubleEndedIterator, FusedIterator, Iterator}; +use super::super::{DoubleEndedIterator, Fuse, FusedIterator, Iterator}; use super::Map; /// An iterator that maps each element to an iterator, and yields the elements @@ -239,14 +239,17 @@ where /// this type. #[derive(Clone, Debug)] struct FlattenCompat { - iter: I, + iter: Fuse, frontiter: Option, backiter: Option, } -impl FlattenCompat { +impl FlattenCompat +where + I: Iterator, +{ /// Adapts an iterator by flattening it, for use in `flatten()` and `flat_map()`. fn new(iter: I) -> FlattenCompat { - FlattenCompat { iter, frontiter: None, backiter: None } + FlattenCompat { iter: iter.fuse(), frontiter: None, backiter: None } } } @@ -261,8 +264,9 @@ where fn next(&mut self) -> Option { loop { if let Some(ref mut inner) = self.frontiter { - if let elt @ Some(_) = inner.next() { - return elt; + match inner.next() { + None => self.frontiter = None, + elt @ Some(_) => return elt, } } match self.iter.next() { @@ -348,8 +352,9 @@ where fn next_back(&mut self) -> Option { loop { if let Some(ref mut inner) = self.backiter { - if let elt @ Some(_) = inner.next_back() { - return elt; + match inner.next_back() { + None => self.backiter = None, + elt @ Some(_) => return elt, } } match self.iter.next_back() { diff --git a/src/libcore/iter/adapters/fuse.rs b/src/libcore/iter/adapters/fuse.rs new file mode 100644 index 0000000000000..a60ca64ec87c8 --- /dev/null +++ b/src/libcore/iter/adapters/fuse.rs @@ -0,0 +1,342 @@ +use crate::intrinsics; +use crate::iter::{ + DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator, TrustedRandomAccess, +}; +use crate::ops::Try; + +/// An iterator that yields `None` forever after the underlying iterator +/// yields `None` once. +/// +/// This `struct` is created by the [`fuse`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`fuse`]: trait.Iterator.html#method.fuse +/// [`Iterator`]: trait.Iterator.html +#[derive(Clone, Debug)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Fuse { + // NOTE: for `I: FusedIterator`, this is always assumed `Some`! + iter: Option, +} +impl Fuse { + pub(in crate::iter) fn new(iter: I) -> Fuse { + Fuse { iter: Some(iter) } + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Fuse where I: Iterator {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for Fuse +where + I: Iterator, +{ + type Item = ::Item; + + #[inline] + default fn next(&mut self) -> Option<::Item> { + let next = self.iter.as_mut()?.next(); + if next.is_none() { + self.iter = None; + } + next + } + + #[inline] + default fn nth(&mut self, n: usize) -> Option { + let nth = self.iter.as_mut()?.nth(n); + if nth.is_none() { + self.iter = None; + } + nth + } + + #[inline] + default fn last(self) -> Option { + self.iter?.last() + } + + #[inline] + default fn count(self) -> usize { + self.iter.map_or(0, I::count) + } + + #[inline] + default fn size_hint(&self) -> (usize, Option) { + self.iter.as_ref().map_or((0, Some(0)), I::size_hint) + } + + #[inline] + default fn try_fold(&mut self, mut acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + if let Some(ref mut iter) = self.iter { + acc = iter.try_fold(acc, fold)?; + self.iter = None; + } + Try::from_ok(acc) + } + + #[inline] + default fn fold(self, mut acc: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + if let Some(iter) = self.iter { + acc = iter.fold(acc, fold); + } + acc + } + + #[inline] + default fn find

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + let found = self.iter.as_mut()?.find(predicate); + if found.is_none() { + self.iter = None; + } + found + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for Fuse +where + I: DoubleEndedIterator, +{ + #[inline] + default fn next_back(&mut self) -> Option<::Item> { + let next = self.iter.as_mut()?.next_back(); + if next.is_none() { + self.iter = None; + } + next + } + + #[inline] + default fn nth_back(&mut self, n: usize) -> Option<::Item> { + let nth = self.iter.as_mut()?.nth_back(n); + if nth.is_none() { + self.iter = None; + } + nth + } + + #[inline] + default fn try_rfold(&mut self, mut acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + if let Some(ref mut iter) = self.iter { + acc = iter.try_rfold(acc, fold)?; + self.iter = None; + } + Try::from_ok(acc) + } + + #[inline] + default fn rfold(self, mut acc: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + if let Some(iter) = self.iter { + acc = iter.rfold(acc, fold); + } + acc + } + + #[inline] + default fn rfind

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + let found = self.iter.as_mut()?.rfind(predicate); + if found.is_none() { + self.iter = None; + } + found + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Fuse +where + I: ExactSizeIterator, +{ + default fn len(&self) -> usize { + self.iter.as_ref().map_or(0, I::len) + } + + default fn is_empty(&self) -> bool { + self.iter.as_ref().map_or(true, I::is_empty) + } +} + +// NOTE: for `I: FusedIterator`, we assume that the iterator is always `Some` +impl Fuse { + #[inline(always)] + fn as_inner(&self) -> &I { + match self.iter { + Some(ref iter) => iter, + // SAFETY: the specialized iterator never sets `None` + None => unsafe { intrinsics::unreachable() }, + } + } + + #[inline(always)] + fn as_inner_mut(&mut self) -> &mut I { + match self.iter { + Some(ref mut iter) => iter, + // SAFETY: the specialized iterator never sets `None` + None => unsafe { intrinsics::unreachable() }, + } + } + + #[inline(always)] + fn into_inner(self) -> I { + match self.iter { + Some(iter) => iter, + // SAFETY: the specialized iterator never sets `None` + None => unsafe { intrinsics::unreachable() }, + } + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl Iterator for Fuse +where + I: FusedIterator, +{ + #[inline] + fn next(&mut self) -> Option<::Item> { + self.as_inner_mut().next() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + self.as_inner_mut().nth(n) + } + + #[inline] + fn last(self) -> Option { + self.into_inner().last() + } + + #[inline] + fn count(self) -> usize { + self.into_inner().count() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.as_inner().size_hint() + } + + #[inline] + fn try_fold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + self.as_inner_mut().try_fold(init, fold) + } + + #[inline] + fn fold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.into_inner().fold(init, fold) + } + + #[inline] + fn find

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + self.as_inner_mut().find(predicate) + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl DoubleEndedIterator for Fuse +where + I: DoubleEndedIterator + FusedIterator, +{ + #[inline] + fn next_back(&mut self) -> Option<::Item> { + self.as_inner_mut().next_back() + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option<::Item> { + self.as_inner_mut().nth_back(n) + } + + #[inline] + fn try_rfold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + self.as_inner_mut().try_rfold(init, fold) + } + + #[inline] + fn rfold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.into_inner().rfold(init, fold) + } + + #[inline] + fn rfind

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + self.as_inner_mut().rfind(predicate) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Fuse +where + I: ExactSizeIterator + FusedIterator, +{ + fn len(&self) -> usize { + self.as_inner().len() + } + + fn is_empty(&self) -> bool { + self.as_inner().is_empty() + } +} + +unsafe impl TrustedRandomAccess for Fuse +where + I: TrustedRandomAccess, +{ + unsafe fn get_unchecked(&mut self, i: usize) -> I::Item { + match self.iter { + Some(ref mut iter) => iter.get_unchecked(i), + // SAFETY: the caller asserts there is an item at `i`, so we're not exhausted. + None => intrinsics::unreachable(), + } + } + + fn may_have_side_effect() -> bool { + I::may_have_side_effect() + } +} diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index 26132e36c9750..16738543eb3af 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -9,11 +9,13 @@ use super::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator, Tru mod chain; mod flatten; +mod fuse; mod zip; pub use self::chain::Chain; #[stable(feature = "rust1", since = "1.0.0")] pub use self::flatten::{FlatMap, Flatten}; +pub use self::fuse::Fuse; pub(crate) use self::zip::TrustedRandomAccess; pub use self::zip::Zip; @@ -1480,7 +1482,11 @@ where { #[inline] fn next_back(&mut self) -> Option { - self.iter.next_back().or_else(|| self.peeked.take().and_then(|x| x)) + match self.peeked.as_mut() { + Some(v @ Some(_)) => self.iter.next_back().or_else(|| v.take()), + Some(None) => None, + None => self.iter.next_back(), + } } #[inline] @@ -1764,6 +1770,14 @@ where } } +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for TakeWhile +where + I: FusedIterator, + P: FnMut(&I::Item) -> bool, +{ +} + /// An iterator that only accepts elements while `predicate` returns `Some(_)`. /// /// This `struct` is created by the [`map_while`] method on [`Iterator`]. See its @@ -1776,20 +1790,19 @@ where #[derive(Clone)] pub struct MapWhile { iter: I, - finished: bool, predicate: P, } impl MapWhile { pub(super) fn new(iter: I, predicate: P) -> MapWhile { - MapWhile { iter, finished: false, predicate } + MapWhile { iter, predicate } } } #[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")] impl fmt::Debug for MapWhile { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("MapWhile").field("iter", &self.iter).field("flag", &self.finished).finish() + f.debug_struct("MapWhile").field("iter", &self.iter).finish() } } @@ -1802,65 +1815,32 @@ where #[inline] fn next(&mut self) -> Option { - if self.finished { - None - } else { - let x = self.iter.next()?; - let ret = (self.predicate)(x); - self.finished = ret.is_none(); - ret - } + let x = self.iter.next()?; + (self.predicate)(x) } #[inline] fn size_hint(&self) -> (usize, Option) { - if self.finished { - (0, Some(0)) - } else { - let (_, upper) = self.iter.size_hint(); - (0, upper) // can't know a lower bound, due to the predicate - } + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the predicate } #[inline] - fn try_fold(&mut self, init: Acc, fold: Fold) -> R + fn try_fold(&mut self, init: Acc, mut fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, { - fn check<'a, B, T, Acc, R: Try>( - flag: &'a mut bool, - p: &'a mut impl FnMut(T) -> Option, - mut fold: impl FnMut(Acc, B) -> R + 'a, - ) -> impl FnMut(Acc, T) -> LoopState + 'a { - move |acc, x| match p(x) { - Some(item) => LoopState::from_try(fold(acc, item)), - None => { - *flag = true; - LoopState::Break(Try::from_ok(acc)) - } - } - } - - if self.finished { - Try::from_ok(init) - } else { - let flag = &mut self.finished; - let p = &mut self.predicate; - self.iter.try_fold(init, check(flag, p, fold)).into_try() - } + let Self { iter, predicate } = self; + iter.try_fold(init, |acc, x| match predicate(x) { + Some(item) => LoopState::from_try(fold(acc, item)), + None => LoopState::Break(Try::from_ok(acc)), + }) + .into_try() } } -#[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for TakeWhile -where - I: FusedIterator, - P: FnMut(&I::Item) -> bool, -{ -} - /// An iterator that skips over `n` elements of `iter`. /// /// This `struct` is created by the [`skip`] method on [`Iterator`]. See its @@ -2260,261 +2240,6 @@ where } } -/// An iterator that yields `None` forever after the underlying iterator -/// yields `None` once. -/// -/// This `struct` is created by the [`fuse`] method on [`Iterator`]. See its -/// documentation for more. -/// -/// [`fuse`]: trait.Iterator.html#method.fuse -/// [`Iterator`]: trait.Iterator.html -#[derive(Clone, Debug)] -#[must_use = "iterators are lazy and do nothing unless consumed"] -#[stable(feature = "rust1", since = "1.0.0")] -pub struct Fuse { - iter: I, - done: bool, -} -impl Fuse { - pub(super) fn new(iter: I) -> Fuse { - Fuse { iter, done: false } - } -} - -#[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for Fuse where I: Iterator {} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for Fuse -where - I: Iterator, -{ - type Item = ::Item; - - #[inline] - default fn next(&mut self) -> Option<::Item> { - if self.done { - None - } else { - let next = self.iter.next(); - self.done = next.is_none(); - next - } - } - - #[inline] - default fn nth(&mut self, n: usize) -> Option { - if self.done { - None - } else { - let nth = self.iter.nth(n); - self.done = nth.is_none(); - nth - } - } - - #[inline] - default fn last(self) -> Option { - if self.done { None } else { self.iter.last() } - } - - #[inline] - default fn count(self) -> usize { - if self.done { 0 } else { self.iter.count() } - } - - #[inline] - default fn size_hint(&self) -> (usize, Option) { - if self.done { (0, Some(0)) } else { self.iter.size_hint() } - } - - #[inline] - default fn try_fold(&mut self, init: Acc, fold: Fold) -> R - where - Self: Sized, - Fold: FnMut(Acc, Self::Item) -> R, - R: Try, - { - if self.done { - Try::from_ok(init) - } else { - let acc = self.iter.try_fold(init, fold)?; - self.done = true; - Try::from_ok(acc) - } - } - - #[inline] - default fn fold(self, init: Acc, fold: Fold) -> Acc - where - Fold: FnMut(Acc, Self::Item) -> Acc, - { - if self.done { init } else { self.iter.fold(init, fold) } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for Fuse -where - I: DoubleEndedIterator, -{ - #[inline] - default fn next_back(&mut self) -> Option<::Item> { - if self.done { - None - } else { - let next = self.iter.next_back(); - self.done = next.is_none(); - next - } - } - - #[inline] - default fn nth_back(&mut self, n: usize) -> Option<::Item> { - if self.done { - None - } else { - let nth = self.iter.nth_back(n); - self.done = nth.is_none(); - nth - } - } - - #[inline] - default fn try_rfold(&mut self, init: Acc, fold: Fold) -> R - where - Self: Sized, - Fold: FnMut(Acc, Self::Item) -> R, - R: Try, - { - if self.done { - Try::from_ok(init) - } else { - let acc = self.iter.try_rfold(init, fold)?; - self.done = true; - Try::from_ok(acc) - } - } - - #[inline] - default fn rfold(self, init: Acc, fold: Fold) -> Acc - where - Fold: FnMut(Acc, Self::Item) -> Acc, - { - if self.done { init } else { self.iter.rfold(init, fold) } - } -} - -unsafe impl TrustedRandomAccess for Fuse -where - I: TrustedRandomAccess, -{ - unsafe fn get_unchecked(&mut self, i: usize) -> I::Item { - self.iter.get_unchecked(i) - } - - fn may_have_side_effect() -> bool { - I::may_have_side_effect() - } -} - -#[stable(feature = "fused", since = "1.26.0")] -impl Iterator for Fuse -where - I: FusedIterator, -{ - #[inline] - fn next(&mut self) -> Option<::Item> { - self.iter.next() - } - - #[inline] - fn nth(&mut self, n: usize) -> Option { - self.iter.nth(n) - } - - #[inline] - fn last(self) -> Option { - self.iter.last() - } - - #[inline] - fn count(self) -> usize { - self.iter.count() - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } - - #[inline] - fn try_fold(&mut self, init: Acc, fold: Fold) -> R - where - Self: Sized, - Fold: FnMut(Acc, Self::Item) -> R, - R: Try, - { - self.iter.try_fold(init, fold) - } - - #[inline] - fn fold(self, init: Acc, fold: Fold) -> Acc - where - Fold: FnMut(Acc, Self::Item) -> Acc, - { - self.iter.fold(init, fold) - } -} - -#[stable(feature = "fused", since = "1.26.0")] -impl DoubleEndedIterator for Fuse -where - I: DoubleEndedIterator + FusedIterator, -{ - #[inline] - fn next_back(&mut self) -> Option<::Item> { - self.iter.next_back() - } - - #[inline] - fn nth_back(&mut self, n: usize) -> Option<::Item> { - self.iter.nth_back(n) - } - - #[inline] - fn try_rfold(&mut self, init: Acc, fold: Fold) -> R - where - Self: Sized, - Fold: FnMut(Acc, Self::Item) -> R, - R: Try, - { - self.iter.try_rfold(init, fold) - } - - #[inline] - fn rfold(self, init: Acc, fold: Fold) -> Acc - where - Fold: FnMut(Acc, Self::Item) -> Acc, - { - self.iter.rfold(init, fold) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Fuse -where - I: ExactSizeIterator, -{ - fn len(&self) -> usize { - self.iter.len() - } - - fn is_empty(&self) -> bool { - self.iter.is_empty() - } -} - /// An iterator that calls a function with a reference to each element before /// yielding it. /// diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index e2ebef9c6ce2f..39bd270da8680 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -1037,9 +1037,6 @@ pub trait Iterator { /// closure on each element of the iterator, and yield elements /// while it returns [`Some(_)`][`Some`]. /// - /// After [`None`] is returned, `map_while()`'s job is over, and the - /// rest of the elements are ignored. - /// /// # Examples /// /// Basic usage: @@ -1079,15 +1076,14 @@ pub trait Iterator { /// #![feature(iter_map_while)] /// use std::convert::TryFrom; /// - /// let a = [0, -1, 1, -2]; - /// - /// let mut iter = a.iter().map_while(|x| u32::try_from(*x).ok()); + /// let a = [0, 1, 2, -3, 4, 5, -6]; /// - /// assert_eq!(iter.next(), Some(0u32)); + /// let iter = a.iter().map_while(|x| u32::try_from(*x).ok()); + /// let vec = iter.collect::>(); /// - /// // We have more elements that are fit in u32, but since we already - /// // got a None, map_while() isn't used any more - /// assert_eq!(iter.next(), None); + /// // We have more elements which could fit in u32 (4, 5), but `map_while` returned `None` for `-3` + /// // (as the `predicate` returned `None`) and `collect` stops at the first `None` entcountered. + /// assert_eq!(vec, vec![0, 1, 2]); /// ``` /// /// Because `map_while()` needs to look at the value in order to see if it @@ -1115,8 +1111,13 @@ pub trait Iterator { /// The `-3` is no longer there, because it was consumed in order to see if /// the iteration should stop, but wasn't placed back into the iterator. /// + /// Note that unlike [`take_while`] this iterator is **not** fused. + /// It is also not specified what this iterator returns after the first` None` is returned. + /// If you need fused iterator, use [`fuse`]. + /// /// [`Some`]: ../../std/option/enum.Option.html#variant.Some /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`fuse`]: #method.fuse #[inline] #[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")] fn map_while(self, predicate: P) -> MapWhile diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index a1dde1d51ef80..0bee16f98bd5e 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -98,6 +98,7 @@ #![feature(is_sorted)] #![feature(lang_items)] #![feature(link_llvm_intrinsics)] +#![cfg_attr(not(bootstrap), feature(negative_impls))] #![feature(never_type)] #![feature(nll)] #![feature(exhaustive_patterns)] @@ -140,7 +141,8 @@ #![feature(associated_type_bounds)] #![feature(const_type_id)] #![feature(const_caller_location)] -#![cfg_attr(not(bootstrap), feature(no_niche))] // rust-lang/rust#68303 +#![feature(option_zip)] +#![feature(no_niche)] // rust-lang/rust#68303 #[prelude_import] #[allow(unused)] diff --git a/src/libcore/macros/mod.rs b/src/libcore/macros/mod.rs index 04af5b5f76828..a0873fe6b625d 100644 --- a/src/libcore/macros/mod.rs +++ b/src/libcore/macros/mod.rs @@ -1404,6 +1404,18 @@ pub(crate) mod builtin { /* compiler built-in */ } + /// Keeps the item it's applied to if the passed path is accessible, and removes it otherwise. + #[cfg(not(bootstrap))] + #[unstable( + feature = "cfg_accessible", + issue = "64797", + reason = "`cfg_accessible` is not fully implemented" + )] + #[rustc_builtin_macro] + pub macro cfg_accessible($item:item) { + /* compiler built-in */ + } + /// Unstable implementation detail of the `rustc` compiler, do not use. #[rustc_builtin_macro] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 2800f11cc01b1..549f80de36aa5 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -87,9 +87,10 @@ impl !Send for *mut T {} message = "the size for values of type `{Self}` cannot be known at compilation time", label = "doesn't have a size known at compile-time", note = "to learn more, visit " + ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>" )] #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable +#[cfg_attr(not(bootstrap), rustc_specialization_trait)] pub trait Sized { // Empty. } @@ -789,7 +790,7 @@ mod copy_impls { #[stable(feature = "rust1", since = "1.0.0")] impl Copy for *mut T {} - // Shared references can be copied, but mutable references *cannot*! + /// Shared references can be copied, but mutable references *cannot*! #[stable(feature = "rust1", since = "1.0.0")] impl Copy for &T {} } diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs index 58aaac21ad751..bf39d56fc115c 100644 --- a/src/libcore/mem/maybe_uninit.rs +++ b/src/libcore/mem/maybe_uninit.rs @@ -495,7 +495,10 @@ impl MaybeUninit { #[inline(always)] #[rustc_diagnostic_item = "assume_init"] pub unsafe fn assume_init(self) -> T { + #[cfg(bootstrap)] intrinsics::panic_if_uninhabited::(); + #[cfg(not(bootstrap))] + intrinsics::assert_inhabited::(); ManuallyDrop::into_inner(self.value) } @@ -559,7 +562,10 @@ impl MaybeUninit { #[unstable(feature = "maybe_uninit_extra", issue = "63567")] #[inline(always)] pub unsafe fn read(&self) -> T { + #[cfg(bootstrap)] intrinsics::panic_if_uninhabited::(); + #[cfg(not(bootstrap))] + intrinsics::assert_inhabited::(); self.as_ptr().read() } @@ -621,7 +627,10 @@ impl MaybeUninit { #[unstable(feature = "maybe_uninit_ref", issue = "63568")] #[inline(always)] pub unsafe fn get_ref(&self) -> &T { + #[cfg(bootstrap)] intrinsics::panic_if_uninhabited::(); + #[cfg(not(bootstrap))] + intrinsics::assert_inhabited::(); &*self.value } @@ -739,7 +748,10 @@ impl MaybeUninit { #[unstable(feature = "maybe_uninit_ref", issue = "63568")] #[inline(always)] pub unsafe fn get_mut(&mut self) -> &mut T { + #[cfg(bootstrap)] intrinsics::panic_if_uninhabited::(); + #[cfg(not(bootstrap))] + intrinsics::assert_inhabited::(); &mut *self.value } diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index 7d9a8bcd05b1c..07f7d28bb7546 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -58,7 +58,9 @@ pub use crate::intrinsics::transmute; /// /// # Examples /// -/// Leak an I/O object, never closing the file: +/// The canonical safe use of `mem::forget` is to circumvent a value's destructor +/// implemented by the `Drop` trait. For example, this will leak a `File`, i.e. reclaim +/// the space taken by the variable but never close the underlying system resource: /// /// ```no_run /// use std::mem; @@ -68,9 +70,40 @@ pub use crate::intrinsics::transmute; /// mem::forget(file); /// ``` /// -/// The practical use cases for `forget` are rather specialized and mainly come -/// up in unsafe or FFI code. However, [`ManuallyDrop`] is usually preferred -/// for such cases, e.g.: +/// This is useful when the ownership of the underlying resource was previously +/// transferred to code outside of Rust, for example by transmitting the raw +/// file descriptor to C code. +/// +/// # Relationship with `ManuallyDrop` +/// +/// While `mem::forget` can also be used to transfer *memory* ownership, doing so is error-prone. +/// [`ManuallyDrop`] should be used instead. Consider, for example, this code: +/// +/// ``` +/// use std::mem; +/// +/// let mut v = vec![65, 122]; +/// // Build a `String` using the contents of `v` +/// let s = unsafe { String::from_raw_parts(v.as_mut_ptr(), v.len(), v.capacity()) }; +/// // leak `v` because its memory is now managed by `s` +/// mem::forget(v); // ERROR - v is invalid and must not be passed to a function +/// assert_eq!(s, "Az"); +/// // `s` is implicitly dropped and its memory deallocated. +/// ``` +/// +/// There are two issues with the above example: +/// +/// * If more code were added between the construction of `String` and the invocation of +/// `mem::forget()`, a panic within it would cause a double free because the same memory +/// is handled by both `v` and `s`. +/// * After calling `v.as_mut_ptr()` and transmitting the ownership of the data to `s`, +/// the `v` value is invalid. Even when a value is just moved to `mem::forget` (which won't +/// inspect it), some types have strict requirements on their values that +/// make them invalid when dangling or no longer owned. Using invalid values in any +/// way, including passing them to or returning them from functions, constitutes +/// undefined behavior and may break the assumptions made by the compiler. +/// +/// Switching to `ManuallyDrop` avoids both issues: /// /// ``` /// use std::mem::ManuallyDrop; @@ -80,24 +113,24 @@ pub use crate::intrinsics::transmute; /// // does not get dropped! /// let mut v = ManuallyDrop::new(v); /// // Now disassemble `v`. These operations cannot panic, so there cannot be a leak. -/// let ptr = v.as_mut_ptr(); -/// let cap = v.capacity(); +/// let (ptr, len, cap) = (v.as_mut_ptr(), v.len(), v.capacity()); /// // Finally, build a `String`. -/// let s = unsafe { String::from_raw_parts(ptr, 2, cap) }; +/// let s = unsafe { String::from_raw_parts(ptr, len, cap) }; /// assert_eq!(s, "Az"); /// // `s` is implicitly dropped and its memory deallocated. /// ``` /// -/// Using `ManuallyDrop` here has two advantages: +/// `ManuallyDrop` robustly prevents double-free because we disable `v`'s destructor +/// before doing anything else. `mem::forget()` doesn't allow this because it consumes its +/// argument, forcing us to call it only after extracting anything we need from `v`. Even +/// if a panic were introduced between construction of `ManuallyDrop` and building the +/// string (which cannot happen in the code as shown), it would result in a leak and not a +/// double free. In other words, `ManuallyDrop` errs on the side of leaking instead of +/// erring on the side of (double-)dropping. /// -/// * We do not "touch" `v` after disassembling it. For some types, operations -/// such as passing ownership (to a function like `mem::forget`) requires them to actually -/// be fully owned right now; that is a promise we do not want to make here as we are -/// in the process of transferring ownership to the new `String` we are building. -/// * In case of an unexpected panic, `ManuallyDrop` is not dropped, but if the panic -/// occurs before `mem::forget` was called we might end up dropping invalid data, -/// or double-dropping. In other words, `ManuallyDrop` errs on the side of leaking -/// instead of erring on the side of dropping. +/// Also, `ManuallyDrop` prevents us from having to "touch" `v` after transferring the +/// ownership to `s` - the final step of interacting with `v` to dispoe of it without +/// running its destructor is entirely avoided. /// /// [drop]: fn.drop.html /// [uninit]: fn.uninitialized.html @@ -303,6 +336,54 @@ pub fn size_of_val(val: &T) -> usize { intrinsics::size_of_val(val) } +/// Returns the size of the pointed-to value in bytes. +/// +/// This is usually the same as `size_of::()`. However, when `T` *has* no +/// statically-known size, e.g., a slice [`[T]`][slice] or a [trait object], +/// then `size_of_val_raw` can be used to get the dynamically-known size. +/// +/// # Safety +/// +/// This function is only safe to call if the following conditions hold: +/// +/// - If `T` is `Sized`, this function is always safe to call. +/// - If the unsized tail of `T` is: +/// - a [slice], then the length of the slice tail must be an intialized +/// integer, and the size of the *entire value* +/// (dynamic tail length + statically sized prefix) must fit in `isize`. +/// - a [trait object], then the vtable part of the pointer must point +/// to a valid vtable acquired by an unsizing coersion, and the size +/// of the *entire value* (dynamic tail length + statically sized prefix) +/// must fit in `isize`. +/// - an (unstable) [extern type], then this function is always safe to +/// call, but may panic or otherwise return the wrong value, as the +/// extern type's layout is not known. This is the same behavior as +/// [`size_of_val`] on a reference to an extern type tail. +/// - otherwise, it is conservatively not allowed to call this function. +/// +/// [slice]: ../../std/primitive.slice.html +/// [trait object]: ../../book/ch17-02-trait-objects.html +/// [extern type]: ../../unstable-book/language-features/extern-types.html +/// +/// # Examples +/// +/// ``` +/// #![feature(layout_for_ptr)] +/// use std::mem; +/// +/// assert_eq!(4, mem::size_of_val(&5i32)); +/// +/// let x: [u8; 13] = [0; 13]; +/// let y: &[u8] = &x; +/// assert_eq!(13, unsafe { mem::size_of_val_raw(y) }); +/// ``` +#[inline] +#[cfg(not(bootstrap))] +#[unstable(feature = "layout_for_ptr", issue = "69835")] +pub unsafe fn size_of_val_raw(val: *const T) -> usize { + intrinsics::size_of_val(val) +} + /// Returns the [ABI]-required minimum alignment of a type. /// /// Every reference to a value of the type `T` must be a multiple of this number. @@ -390,6 +471,50 @@ pub fn align_of_val(val: &T) -> usize { min_align_of_val(val) } +/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to. +/// +/// Every reference to a value of the type `T` must be a multiple of this number. +/// +/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface +/// +/// # Safety +/// +/// This function is only safe to call if the following conditions hold: +/// +/// - If `T` is `Sized`, this function is always safe to call. +/// - If the unsized tail of `T` is: +/// - a [slice], then the length of the slice tail must be an intialized +/// integer, and the size of the *entire value* +/// (dynamic tail length + statically sized prefix) must fit in `isize`. +/// - a [trait object], then the vtable part of the pointer must point +/// to a valid vtable acquired by an unsizing coersion, and the size +/// of the *entire value* (dynamic tail length + statically sized prefix) +/// must fit in `isize`. +/// - an (unstable) [extern type], then this function is always safe to +/// call, but may panic or otherwise return the wrong value, as the +/// extern type's layout is not known. This is the same behavior as +/// [`align_of_val`] on a reference to an extern type tail. +/// - otherwise, it is conservatively not allowed to call this function. +/// +/// [slice]: ../../std/primitive.slice.html +/// [trait object]: ../../book/ch17-02-trait-objects.html +/// [extern type]: ../../unstable-book/language-features/extern-types.html +/// +/// # Examples +/// +/// ``` +/// #![feature(layout_for_ptr)] +/// use std::mem; +/// +/// assert_eq!(4, unsafe { mem::align_of_val_raw(&5i32) }); +/// ``` +#[inline] +#[cfg(not(bootstrap))] +#[unstable(feature = "layout_for_ptr", issue = "69835")] +pub unsafe fn align_of_val_raw(val: *const T) -> usize { + intrinsics::min_align_of_val(val) +} + /// Returns `true` if dropping values of type `T` matters. /// /// This is purely an optimization hint, and may be implemented conservatively: @@ -490,17 +615,17 @@ pub const fn needs_drop() -> bool { /// /// let _x: &i32 = unsafe { mem::zeroed() }; // Undefined behavior! /// ``` -#[inline] +#[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated_in_future)] #[allow(deprecated)] #[rustc_diagnostic_item = "mem_zeroed"] pub unsafe fn zeroed() -> T { #[cfg(not(bootstrap))] - intrinsics::panic_if_zero_invalid::(); + intrinsics::assert_zero_valid::(); #[cfg(bootstrap)] intrinsics::panic_if_uninhabited::(); - intrinsics::init() + MaybeUninit::zeroed().assume_init() } /// Bypasses Rust's normal memory-initialization checks by pretending to @@ -525,7 +650,7 @@ pub unsafe fn zeroed() -> T { /// [uninit]: union.MaybeUninit.html#method.uninit /// [assume_init]: union.MaybeUninit.html#method.assume_init /// [inv]: union.MaybeUninit.html#initialization-invariant -#[inline] +#[inline(always)] #[rustc_deprecated(since = "1.39.0", reason = "use `mem::MaybeUninit` instead")] #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated_in_future)] @@ -533,10 +658,10 @@ pub unsafe fn zeroed() -> T { #[rustc_diagnostic_item = "mem_uninitialized"] pub unsafe fn uninitialized() -> T { #[cfg(not(bootstrap))] - intrinsics::panic_if_any_invalid::(); + intrinsics::assert_uninit_valid::(); #[cfg(bootstrap)] intrinsics::panic_if_uninhabited::(); - intrinsics::uninit() + MaybeUninit::uninit().assume_init() } /// Swaps the values at two mutable locations, without deinitializing either one. diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index caffa6c509aaa..853092dd85ee9 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -2154,7 +2154,7 @@ let bytes = ", $swap_op, stringify!($SelfT), ".to_be_bytes(); assert_eq!(bytes, ", $be_bytes, "); ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] #[inline] pub const fn to_be_bytes(self) -> [u8; mem::size_of::()] { self.to_be().to_ne_bytes() @@ -2174,7 +2174,7 @@ let bytes = ", $swap_op, stringify!($SelfT), ".to_le_bytes(); assert_eq!(bytes, ", $le_bytes, "); ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] #[inline] pub const fn to_le_bytes(self) -> [u8; mem::size_of::()] { self.to_le().to_ne_bytes() @@ -2209,7 +2209,7 @@ assert_eq!( ); ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] // SAFETY: const sound because integers are plain old datatypes so we can always // transmute them to arrays of bytes #[allow_internal_unstable(const_fn_union)] @@ -2251,7 +2251,7 @@ fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), } ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] #[inline] pub const fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { Self::from_be(Self::from_ne_bytes(bytes)) @@ -2284,7 +2284,7 @@ fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), } ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] #[inline] pub const fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { Self::from_le(Self::from_ne_bytes(bytes)) @@ -2327,7 +2327,7 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), } ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] // SAFETY: const sound because integers are plain old datatypes so we can always // transmute to them #[allow_internal_unstable(const_fn_union)] @@ -4115,7 +4115,7 @@ let bytes = ", $swap_op, stringify!($SelfT), ".to_be_bytes(); assert_eq!(bytes, ", $be_bytes, "); ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] #[inline] pub const fn to_be_bytes(self) -> [u8; mem::size_of::()] { self.to_be().to_ne_bytes() @@ -4135,7 +4135,7 @@ let bytes = ", $swap_op, stringify!($SelfT), ".to_le_bytes(); assert_eq!(bytes, ", $le_bytes, "); ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] #[inline] pub const fn to_le_bytes(self) -> [u8; mem::size_of::()] { self.to_le().to_ne_bytes() @@ -4170,7 +4170,7 @@ assert_eq!( ); ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] // SAFETY: const sound because integers are plain old datatypes so we can always // transmute them to arrays of bytes #[allow_internal_unstable(const_fn_union)] @@ -4212,7 +4212,7 @@ fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), } ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] #[inline] pub const fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { Self::from_be(Self::from_ne_bytes(bytes)) @@ -4245,7 +4245,7 @@ fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), } ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] #[inline] pub const fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { Self::from_le(Self::from_ne_bytes(bytes)) @@ -4288,7 +4288,7 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), } ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] // SAFETY: const sound because integers are plain old datatypes so we can always // transmute to them #[allow_internal_unstable(const_fn_union)] diff --git a/src/libcore/ops/deref.rs b/src/libcore/ops/deref.rs index 68244fdb38114..e2deeb556610c 100644 --- a/src/libcore/ops/deref.rs +++ b/src/libcore/ops/deref.rs @@ -81,6 +81,10 @@ impl Deref for &T { } } +#[cfg(not(bootstrap))] +#[stable(feature = "rust1", since = "1.0.0")] +impl !DerefMut for &T {} + #[stable(feature = "rust1", since = "1.0.0")] impl Deref for &mut T { type Target = T; diff --git a/src/libcore/ops/generator.rs b/src/libcore/ops/generator.rs index 4e43561996c37..4f23620b92b80 100644 --- a/src/libcore/ops/generator.rs +++ b/src/libcore/ops/generator.rs @@ -67,7 +67,7 @@ pub enum GeneratorState { #[lang = "generator"] #[unstable(feature = "generator_trait", issue = "43122")] #[fundamental] -pub trait Generator<#[cfg(not(bootstrap))] R = ()> { +pub trait Generator { /// The type of value this generator yields. /// /// This associated type corresponds to the `yield` expression and the @@ -110,35 +110,9 @@ pub trait Generator<#[cfg(not(bootstrap))] R = ()> { /// been returned previously. While generator literals in the language are /// guaranteed to panic on resuming after `Complete`, this is not guaranteed /// for all implementations of the `Generator` trait. - fn resume( - self: Pin<&mut Self>, - #[cfg(not(bootstrap))] arg: R, - ) -> GeneratorState; + fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState; } -#[cfg(bootstrap)] -#[unstable(feature = "generator_trait", issue = "43122")] -impl Generator for Pin<&mut G> { - type Yield = G::Yield; - type Return = G::Return; - - fn resume(mut self: Pin<&mut Self>) -> GeneratorState { - G::resume((*self).as_mut()) - } -} - -#[cfg(bootstrap)] -#[unstable(feature = "generator_trait", issue = "43122")] -impl Generator for &mut G { - type Yield = G::Yield; - type Return = G::Return; - - fn resume(mut self: Pin<&mut Self>) -> GeneratorState { - G::resume(Pin::new(&mut *self)) - } -} - -#[cfg(not(bootstrap))] #[unstable(feature = "generator_trait", issue = "43122")] impl, R> Generator for Pin<&mut G> { type Yield = G::Yield; @@ -149,7 +123,6 @@ impl, R> Generator for Pin<&mut G> { } } -#[cfg(not(bootstrap))] #[unstable(feature = "generator_trait", issue = "43122")] impl + Unpin, R> Generator for &mut G { type Yield = G::Yield; diff --git a/src/libcore/ops/index.rs b/src/libcore/ops/index.rs index aae0691122415..64dd633f75d2b 100644 --- a/src/libcore/ops/index.rs +++ b/src/libcore/ops/index.rs @@ -65,6 +65,7 @@ pub trait Index { /// Performs the indexing (`container[index]`) operation. #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(bootstrap), track_caller)] fn index(&self, index: Idx) -> &Self::Output; } @@ -166,5 +167,6 @@ see chapter in The Book : Index { /// Performs the mutable indexing (`container[index]`) operation. #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(bootstrap), track_caller)] fn index_mut(&mut self, index: Idx) -> &mut Self::Output; } diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index 8ffad82b69d7c..adee8cea442b4 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -1,5 +1,5 @@ use crate::fmt; -use crate::hash::{Hash, Hasher}; +use crate::hash::Hash; /// An unbounded range (`..`). /// @@ -330,7 +330,7 @@ impl> RangeTo { /// assert_eq!(arr[1..=3], [ 1,2,3 ]); // RangeInclusive /// ``` #[doc(alias = "..=")] -#[derive(Clone)] // not Copy -- see #27186 +#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 #[stable(feature = "inclusive_range", since = "1.26.0")] pub struct RangeInclusive { // Note that the fields here are not public to allow changing the @@ -350,26 +350,6 @@ pub struct RangeInclusive { pub(crate) exhausted: bool, } -#[stable(feature = "inclusive_range", since = "1.26.0")] -impl PartialEq for RangeInclusive { - #[inline] - fn eq(&self, other: &Self) -> bool { - self.start == other.start && self.end == other.end && self.exhausted == other.exhausted - } -} - -#[stable(feature = "inclusive_range", since = "1.26.0")] -impl Eq for RangeInclusive {} - -#[stable(feature = "inclusive_range", since = "1.26.0")] -impl Hash for RangeInclusive { - fn hash(&self, state: &mut H) { - self.start.hash(state); - self.end.hash(state); - self.exhausted.hash(state); - } -} - impl RangeInclusive { /// Creates a new inclusive range. Equivalent to writing `start..=end`. /// diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 9b32442371c37..3aab8b1b3337c 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -913,6 +913,63 @@ impl Option { pub fn replace(&mut self, value: T) -> Option { mem::replace(self, Some(value)) } + + /// Zips `self` with another `Option`. + /// + /// If `self` is `Some(s)` and `other` is `Some(o)`, this method returns `Some((s, o))`. + /// Otherwise, `None` is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(option_zip)] + /// let x = Some(1); + /// let y = Some("hi"); + /// let z = None::; + /// + /// assert_eq!(x.zip(y), Some((1, "hi"))); + /// assert_eq!(x.zip(z), None); + /// ``` + #[unstable(feature = "option_zip", issue = "70086")] + pub fn zip(self, other: Option) -> Option<(T, U)> { + self.zip_with(other, |a, b| (a, b)) + } + + /// Zips `self` and another `Option` with function `f`. + /// + /// If `self` is `Some(s)` and `other` is `Some(o)`, this method returns `Some(f(s, o))`. + /// Otherwise, `None` is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(option_zip)] + /// + /// #[derive(Debug, PartialEq)] + /// struct Point { + /// x: f64, + /// y: f64, + /// } + /// + /// impl Point { + /// fn new(x: f64, y: f64) -> Self { + /// Self { x, y } + /// } + /// } + /// + /// let x = Some(17.5); + /// let y = Some(42.7); + /// + /// assert_eq!(x.zip_with(y, Point::new), Some(Point { x: 17.5, y: 42.7 })); + /// assert_eq!(x.zip_with(None, Point::new), None); + /// ``` + #[unstable(feature = "option_zip", issue = "70086")] + pub fn zip_with(self, other: Option, f: F) -> Option + where + F: FnOnce(T, U) -> R, + { + Some(f(self?, other?)) + } } impl Option<&T> { diff --git a/src/libcore/prelude/v1.rs b/src/libcore/prelude/v1.rs index 66b5a90b77b91..c91370b271992 100644 --- a/src/libcore/prelude/v1.rs +++ b/src/libcore/prelude/v1.rs @@ -67,3 +67,12 @@ pub use crate::{ pub use crate::macros::builtin::{ bench, global_allocator, test, test_case, RustcDecodable, RustcEncodable, }; + +#[cfg(not(bootstrap))] +#[unstable( + feature = "cfg_accessible", + issue = "64797", + reason = "`cfg_accessible` is not fully implemented" +)] +#[doc(no_inline)] +pub use crate::macros::builtin::cfg_accessible; diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs index 72c46f58fcc7b..4913cd73a2a9a 100644 --- a/src/libcore/ptr/mod.rs +++ b/src/libcore/ptr/mod.rs @@ -810,9 +810,7 @@ pub unsafe fn read_unaligned(src: *const T) -> T { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn write(dst: *mut T, src: T) { - // FIXME: the debug assertion here causes codegen test failures on some architectures. - // See . - // debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer"); + debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer"); intrinsics::move_val_init(&mut *dst, src) } diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 0e12e6360da95..2140a7be9efe8 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -2306,6 +2306,7 @@ impl [T] { /// assert_eq!(&bytes, b"Hello, Wello!"); /// ``` #[stable(feature = "copy_within", since = "1.37.0")] + #[track_caller] pub fn copy_within>(&mut self, src: R, dest: usize) where T: Copy, @@ -2721,18 +2722,21 @@ where #[inline(never)] #[cold] +#[track_caller] fn slice_index_len_fail(index: usize, len: usize) -> ! { panic!("index {} out of range for slice of length {}", index, len); } #[inline(never)] #[cold] +#[track_caller] fn slice_index_order_fail(index: usize, end: usize) -> ! { panic!("slice index starts at {} but ends at {}", index, end); } #[inline(never)] #[cold] +#[track_caller] fn slice_index_overflow_fail() -> ! { panic!("attempted to index slice up to maximum usize"); } @@ -2804,11 +2808,13 @@ pub trait SliceIndex: private_slice_index::Sealed { /// Returns a shared reference to the output at this location, panicking /// if out of bounds. #[unstable(feature = "slice_index_methods", issue = "none")] + #[cfg_attr(not(bootstrap), track_caller)] fn index(self, slice: &T) -> &Self::Output; /// Returns a mutable reference to the output at this location, panicking /// if out of bounds. #[unstable(feature = "slice_index_methods", issue = "none")] + #[cfg_attr(not(bootstrap), track_caller)] fn index_mut(self, slice: &mut T) -> &mut Self::Output; } diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 6ad0e68a88f3b..013ca182c13cd 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1794,6 +1794,7 @@ mod traits { #[inline(never)] #[cold] + #[track_caller] fn str_index_overflow_fail() -> ! { panic!("attempted to index str up to maximum usize"); } @@ -2185,6 +2186,7 @@ fn truncate_to_char_boundary(s: &str, mut max: usize) -> (bool, &str) { #[inline(never)] #[cold] +#[track_caller] fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! { const MAX_DISPLAY_LENGTH: usize = 256; let (truncated, s_trunc) = truncate_to_char_boundary(s, MAX_DISPLAY_LENGTH); diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs index 6c826e5dcdec0..ffa418cba6c99 100644 --- a/src/libcore/str/pattern.rs +++ b/src/libcore/str/pattern.rs @@ -365,11 +365,7 @@ unsafe impl<'a> ReverseSearcher<'a> for CharSearcher<'a> { let haystack = self.haystack.as_bytes(); loop { // get the haystack up to but not including the last character searched - let bytes = if let Some(slice) = haystack.get(self.finger..self.finger_back) { - slice - } else { - return None; - }; + let bytes = haystack.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) }; @@ -575,11 +571,12 @@ macro_rules! pattern_methods { #[inline] fn is_suffix_of(self, haystack: &'a str) -> bool - where $t: ReverseSearcher<'a> + where + $t: ReverseSearcher<'a>, { ($pmap)(self).is_suffix_of(haystack) } - } + }; } macro_rules! searcher_methods { @@ -614,7 +611,7 @@ macro_rules! searcher_methods { fn next_reject_back(&mut self) -> Option<(usize, usize)> { self.0.next_reject_back() } - } + }; } ///////////////////////////////////////////////////////////////////////////// diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 3ba15968f8933..220f221cdd36d 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -2259,7 +2259,7 @@ fn strongest_failure_ordering(order: Ordering) -> Ordering { } #[inline] -unsafe fn atomic_store(dst: *mut T, val: T, order: Ordering) { +unsafe fn atomic_store(dst: *mut T, val: T, order: Ordering) { match order { Release => intrinsics::atomic_store_rel(dst, val), Relaxed => intrinsics::atomic_store_relaxed(dst, val), @@ -2270,7 +2270,7 @@ unsafe fn atomic_store(dst: *mut T, val: T, order: Ordering) { } #[inline] -unsafe fn atomic_load(dst: *const T, order: Ordering) -> T { +unsafe fn atomic_load(dst: *const T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_load_acq(dst), Relaxed => intrinsics::atomic_load_relaxed(dst), @@ -2282,7 +2282,7 @@ unsafe fn atomic_load(dst: *const T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_swap(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_swap(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xchg_acq(dst, val), Release => intrinsics::atomic_xchg_rel(dst, val), @@ -2295,7 +2295,7 @@ unsafe fn atomic_swap(dst: *mut T, val: T, order: Ordering) -> T { /// Returns the previous value (like __sync_fetch_and_add). #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_add(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_add(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xadd_acq(dst, val), Release => intrinsics::atomic_xadd_rel(dst, val), @@ -2308,7 +2308,7 @@ unsafe fn atomic_add(dst: *mut T, val: T, order: Ordering) -> T { /// Returns the previous value (like __sync_fetch_and_sub). #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_sub(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_sub(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xsub_acq(dst, val), Release => intrinsics::atomic_xsub_rel(dst, val), @@ -2320,7 +2320,7 @@ unsafe fn atomic_sub(dst: *mut T, val: T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_compare_exchange( +unsafe fn atomic_compare_exchange( dst: *mut T, old: T, new: T, @@ -2346,7 +2346,7 @@ unsafe fn atomic_compare_exchange( #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_compare_exchange_weak( +unsafe fn atomic_compare_exchange_weak( dst: *mut T, old: T, new: T, @@ -2372,7 +2372,7 @@ unsafe fn atomic_compare_exchange_weak( #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_and(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_and(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_and_acq(dst, val), Release => intrinsics::atomic_and_rel(dst, val), @@ -2384,7 +2384,7 @@ unsafe fn atomic_and(dst: *mut T, val: T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_nand(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_nand(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_nand_acq(dst, val), Release => intrinsics::atomic_nand_rel(dst, val), @@ -2396,7 +2396,7 @@ unsafe fn atomic_nand(dst: *mut T, val: T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_or(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_or(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_or_acq(dst, val), Release => intrinsics::atomic_or_rel(dst, val), @@ -2408,7 +2408,7 @@ unsafe fn atomic_or(dst: *mut T, val: T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_xor(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_xor(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xor_acq(dst, val), Release => intrinsics::atomic_xor_rel(dst, val), @@ -2421,7 +2421,7 @@ unsafe fn atomic_xor(dst: *mut T, val: T, order: Ordering) -> T { /// returns the max value (signed comparison) #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_max(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_max(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_max_acq(dst, val), Release => intrinsics::atomic_max_rel(dst, val), @@ -2434,7 +2434,7 @@ unsafe fn atomic_max(dst: *mut T, val: T, order: Ordering) -> T { /// returns the min value (signed comparison) #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_min(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_min(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_min_acq(dst, val), Release => intrinsics::atomic_min_rel(dst, val), @@ -2447,7 +2447,7 @@ unsafe fn atomic_min(dst: *mut T, val: T, order: Ordering) -> T { /// returns the max value (unsigned comparison) #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_umax(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_umax(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_umax_acq(dst, val), Release => intrinsics::atomic_umax_rel(dst, val), @@ -2460,7 +2460,7 @@ unsafe fn atomic_umax(dst: *mut T, val: T, order: Ordering) -> T { /// returns the min value (unsigned comparison) #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_umin(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_umin(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_umin_acq(dst, val), Release => intrinsics::atomic_umin_rel(dst, val), diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 5b41ef350657f..98e3eeb982bde 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1,3 +1,5 @@ +// ignore-tidy-filelength + use core::cell::Cell; use core::convert::TryFrom; use core::iter::*; @@ -2940,3 +2942,73 @@ fn test_partition() { check(xs, |&x| x < 3, 3); // small check(xs, |&x| x > 6, 3); // large } + +/// An iterator that panics whenever `next` or next_back` is called +/// after `None` has already been returned. This does not violate +/// `Iterator`'s contract. Used to test that iterator adaptors don't +/// poll their inner iterators after exhausting them. +struct NonFused { + iter: I, + done: bool, +} + +impl NonFused { + fn new(iter: I) -> Self { + Self { iter, done: false } + } +} + +impl Iterator for NonFused +where + I: Iterator, +{ + type Item = I::Item; + + fn next(&mut self) -> Option { + assert!(!self.done, "this iterator has already returned None"); + self.iter.next().or_else(|| { + self.done = true; + None + }) + } +} + +impl DoubleEndedIterator for NonFused +where + I: DoubleEndedIterator, +{ + fn next_back(&mut self) -> Option { + assert!(!self.done, "this iterator has already returned None"); + self.iter.next_back().or_else(|| { + self.done = true; + None + }) + } +} + +#[test] +fn test_peekable_non_fused() { + let mut iter = NonFused::new(empty::()).peekable(); + + assert_eq!(iter.peek(), None); + assert_eq!(iter.next_back(), None); +} + +#[test] +fn test_flatten_non_fused_outer() { + let mut iter = NonFused::new(once(0..2)).flatten(); + + assert_eq!(iter.next_back(), Some(1)); + assert_eq!(iter.next(), Some(0)); + assert_eq!(iter.next(), None); +} + +#[test] +fn test_flatten_non_fused_inner() { + let mut iter = once(0..1).chain(once(1..3)).flat_map(NonFused::new); + + assert_eq!(iter.next_back(), Some(2)); + assert_eq!(iter.next(), Some(0)); + assert_eq!(iter.next(), Some(1)); + assert_eq!(iter.next(), None); +} diff --git a/src/libcore/tests/mem.rs b/src/libcore/tests/mem.rs index 8337ab103419f..59588d97787b7 100644 --- a/src/libcore/tests/mem.rs +++ b/src/libcore/tests/mem.rs @@ -129,21 +129,3 @@ fn test_discriminant_send_sync() { is_send_sync::>(); is_send_sync::>(); } - -#[test] -fn test_const_forget() { - const _: () = forget(0i32); - const _: () = forget(Vec::>>::new()); - - // Writing this function signature without const-forget - // triggers compiler errors: - // 1) That we use a non-const fn inside a const fn - // 2) without the forget, it complains about the destructor of Box - const fn const_forget_box(x: Box) { - forget(x); - } - - // Call the forget_box at runtime, - // as we can't const-construct a box yet. - const_forget_box(Box::new(0i32)); -} diff --git a/src/libcore/unicode/printable.rs b/src/libcore/unicode/printable.rs index eee9ea52ef0d2..9680aa14d3b54 100644 --- a/src/libcore/unicode/printable.rs +++ b/src/libcore/unicode/printable.rs @@ -44,7 +44,7 @@ pub(crate) fn is_printable(x: char) -> bool { } else if x < 0x20000 { check(lower, SINGLETONS1U, SINGLETONS1L, NORMAL1) } else { - if 0x2a6d7 <= x && x < 0x2a700 { + if 0x2a6de <= x && x < 0x2a700 { return false; } if 0x2b735 <= x && x < 0x2b740 { @@ -59,7 +59,10 @@ pub(crate) fn is_printable(x: char) -> bool { if 0x2ebe1 <= x && x < 0x2f800 { return false; } - if 0x2fa1e <= x && x < 0xe0100 { + if 0x2fa1e <= x && x < 0x30000 { + return false; + } + if 0x3134b <= x && x < 0xe0100 { return false; } if 0xe01f0 <= x && x < 0x110000 { @@ -81,7 +84,7 @@ const SINGLETONS0U: &[(u8, u8)] = &[ (0x0a, 28), (0x0b, 25), (0x0c, 20), - (0x0d, 18), + (0x0d, 16), (0x0e, 13), (0x0f, 4), (0x10, 3), @@ -96,7 +99,7 @@ const SINGLETONS0U: &[(u8, u8)] = &[ (0x1d, 1), (0x1f, 22), (0x20, 3), - (0x2b, 4), + (0x2b, 3), (0x2c, 2), (0x2d, 11), (0x2e, 1), @@ -129,29 +132,29 @@ const SINGLETONS0L: &[u8] = &[ 0x4a, 0x5e, 0x64, 0x65, 0x84, 0x91, 0x9b, 0x9d, 0xc9, 0xce, 0xcf, 0x0d, 0x11, 0x29, 0x45, 0x49, 0x57, 0x64, 0x65, 0x8d, 0x91, 0xa9, 0xb4, 0xba, - 0xbb, 0xc5, 0xc9, 0xdf, 0xe4, 0xe5, 0xf0, 0x04, - 0x0d, 0x11, 0x45, 0x49, 0x64, 0x65, 0x80, 0x81, - 0x84, 0xb2, 0xbc, 0xbe, 0xbf, 0xd5, 0xd7, 0xf0, - 0xf1, 0x83, 0x85, 0x8b, 0xa4, 0xa6, 0xbe, 0xbf, - 0xc5, 0xc7, 0xce, 0xcf, 0xda, 0xdb, 0x48, 0x98, - 0xbd, 0xcd, 0xc6, 0xce, 0xcf, 0x49, 0x4e, 0x4f, - 0x57, 0x59, 0x5e, 0x5f, 0x89, 0x8e, 0x8f, 0xb1, - 0xb6, 0xb7, 0xbf, 0xc1, 0xc6, 0xc7, 0xd7, 0x11, - 0x16, 0x17, 0x5b, 0x5c, 0xf6, 0xf7, 0xfe, 0xff, - 0x80, 0x0d, 0x6d, 0x71, 0xde, 0xdf, 0x0e, 0x0f, - 0x1f, 0x6e, 0x6f, 0x1c, 0x1d, 0x5f, 0x7d, 0x7e, - 0xae, 0xaf, 0xbb, 0xbc, 0xfa, 0x16, 0x17, 0x1e, - 0x1f, 0x46, 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, - 0x5e, 0x7e, 0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, - 0xf0, 0xf1, 0xf5, 0x72, 0x73, 0x8f, 0x74, 0x75, - 0x96, 0x97, 0x2f, 0x5f, 0x26, 0x2e, 0x2f, 0xa7, - 0xaf, 0xb7, 0xbf, 0xc7, 0xcf, 0xd7, 0xdf, 0x9a, - 0x40, 0x97, 0x98, 0x30, 0x8f, 0x1f, 0xc0, 0xc1, - 0xce, 0xff, 0x4e, 0x4f, 0x5a, 0x5b, 0x07, 0x08, - 0x0f, 0x10, 0x27, 0x2f, 0xee, 0xef, 0x6e, 0x6f, - 0x37, 0x3d, 0x3f, 0x42, 0x45, 0x90, 0x91, 0xfe, - 0xff, 0x53, 0x67, 0x75, 0xc8, 0xc9, 0xd0, 0xd1, - 0xd8, 0xd9, 0xe7, 0xfe, 0xff, + 0xbb, 0xc5, 0xc9, 0xdf, 0xe4, 0xe5, 0xf0, 0x0d, + 0x11, 0x45, 0x49, 0x64, 0x65, 0x80, 0x84, 0xb2, + 0xbc, 0xbe, 0xbf, 0xd5, 0xd7, 0xf0, 0xf1, 0x83, + 0x85, 0x8b, 0xa4, 0xa6, 0xbe, 0xbf, 0xc5, 0xc7, + 0xce, 0xcf, 0xda, 0xdb, 0x48, 0x98, 0xbd, 0xcd, + 0xc6, 0xce, 0xcf, 0x49, 0x4e, 0x4f, 0x57, 0x59, + 0x5e, 0x5f, 0x89, 0x8e, 0x8f, 0xb1, 0xb6, 0xb7, + 0xbf, 0xc1, 0xc6, 0xc7, 0xd7, 0x11, 0x16, 0x17, + 0x5b, 0x5c, 0xf6, 0xf7, 0xfe, 0xff, 0x80, 0x0d, + 0x6d, 0x71, 0xde, 0xdf, 0x0e, 0x0f, 0x1f, 0x6e, + 0x6f, 0x1c, 0x1d, 0x5f, 0x7d, 0x7e, 0xae, 0xaf, + 0xbb, 0xbc, 0xfa, 0x16, 0x17, 0x1e, 0x1f, 0x46, + 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, 0x5e, 0x7e, + 0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, 0xf0, 0xf1, + 0xf5, 0x72, 0x73, 0x8f, 0x74, 0x75, 0x96, 0x2f, + 0x5f, 0x26, 0x2e, 0x2f, 0xa7, 0xaf, 0xb7, 0xbf, + 0xc7, 0xcf, 0xd7, 0xdf, 0x9a, 0x40, 0x97, 0x98, + 0x30, 0x8f, 0x1f, 0xc0, 0xc1, 0xce, 0xff, 0x4e, + 0x4f, 0x5a, 0x5b, 0x07, 0x08, 0x0f, 0x10, 0x27, + 0x2f, 0xee, 0xef, 0x6e, 0x6f, 0x37, 0x3d, 0x3f, + 0x42, 0x45, 0x90, 0x91, 0xfe, 0xff, 0x53, 0x67, + 0x75, 0xc8, 0xc9, 0xd0, 0xd1, 0xd8, 0xd9, 0xe7, + 0xfe, 0xff, ]; #[rustfmt::skip] const SINGLETONS1U: &[(u8, u8)] = &[ @@ -163,14 +166,15 @@ const SINGLETONS1U: &[(u8, u8)] = &[ (0x09, 2), (0x0a, 5), (0x0b, 2), + (0x0e, 4), (0x10, 1), - (0x11, 4), + (0x11, 2), (0x12, 5), (0x13, 17), - (0x14, 2), + (0x14, 1), (0x15, 2), (0x17, 2), - (0x19, 4), + (0x19, 13), (0x1c, 5), (0x1d, 8), (0x24, 1), @@ -188,32 +192,35 @@ const SINGLETONS1U: &[(u8, u8)] = &[ (0xe8, 2), (0xee, 32), (0xf0, 4), - (0xf9, 6), + (0xf8, 2), + (0xf9, 2), (0xfa, 2), + (0xfb, 1), ]; #[rustfmt::skip] const SINGLETONS1L: &[u8] = &[ 0x0c, 0x27, 0x3b, 0x3e, 0x4e, 0x4f, 0x8f, 0x9e, 0x9e, 0x9f, 0x06, 0x07, 0x09, 0x36, 0x3d, 0x3e, 0x56, 0xf3, 0xd0, 0xd1, 0x04, 0x14, 0x18, 0x36, - 0x37, 0x56, 0x57, 0xbd, 0x35, 0xce, 0xcf, 0xe0, - 0x12, 0x87, 0x89, 0x8e, 0x9e, 0x04, 0x0d, 0x0e, - 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a, 0x45, 0x46, - 0x49, 0x4a, 0x4e, 0x4f, 0x64, 0x65, 0x5a, 0x5c, - 0xb6, 0xb7, 0x1b, 0x1c, 0xa8, 0xa9, 0xd8, 0xd9, - 0x09, 0x37, 0x90, 0x91, 0xa8, 0x07, 0x0a, 0x3b, - 0x3e, 0x66, 0x69, 0x8f, 0x92, 0x6f, 0x5f, 0xee, - 0xef, 0x5a, 0x62, 0x9a, 0x9b, 0x27, 0x28, 0x55, - 0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8, 0xad, - 0xba, 0xbc, 0xc4, 0x06, 0x0b, 0x0c, 0x15, 0x1d, - 0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7, 0xcc, 0xcd, - 0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, 0x3e, 0x3f, - 0xc5, 0xc6, 0x04, 0x20, 0x23, 0x25, 0x26, 0x28, - 0x33, 0x38, 0x3a, 0x48, 0x4a, 0x4c, 0x50, 0x53, - 0x55, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x63, - 0x65, 0x66, 0x6b, 0x73, 0x78, 0x7d, 0x7f, 0x8a, - 0xa4, 0xaa, 0xaf, 0xb0, 0xc0, 0xd0, 0x0c, 0x72, - 0xa3, 0xa4, 0xcb, 0xcc, 0x6e, 0x6f, + 0x37, 0x56, 0x57, 0x7f, 0xaa, 0xae, 0xaf, 0xbd, + 0x35, 0xe0, 0x12, 0x87, 0x89, 0x8e, 0x9e, 0x04, + 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a, + 0x45, 0x46, 0x49, 0x4a, 0x4e, 0x4f, 0x64, 0x65, + 0x5c, 0xb6, 0xb7, 0x1b, 0x1c, 0x07, 0x08, 0x0a, + 0x0b, 0x14, 0x17, 0x36, 0x39, 0x3a, 0xa8, 0xa9, + 0xd8, 0xd9, 0x09, 0x37, 0x90, 0x91, 0xa8, 0x07, + 0x0a, 0x3b, 0x3e, 0x66, 0x69, 0x8f, 0x92, 0x6f, + 0x5f, 0xee, 0xef, 0x5a, 0x62, 0x9a, 0x9b, 0x27, + 0x28, 0x55, 0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, + 0xa8, 0xad, 0xba, 0xbc, 0xc4, 0x06, 0x0b, 0x0c, + 0x15, 0x1d, 0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7, + 0xcc, 0xcd, 0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, + 0x3e, 0x3f, 0xc5, 0xc6, 0x04, 0x20, 0x23, 0x25, + 0x26, 0x28, 0x33, 0x38, 0x3a, 0x48, 0x4a, 0x4c, + 0x50, 0x53, 0x55, 0x56, 0x58, 0x5a, 0x5c, 0x5e, + 0x60, 0x63, 0x65, 0x66, 0x6b, 0x73, 0x78, 0x7d, + 0x7f, 0x8a, 0xa4, 0xaa, 0xaf, 0xb0, 0xc0, 0xd0, + 0xae, 0xaf, 0x79, 0xcc, 0x6e, 0x6f, 0x93, ]; #[rustfmt::skip] const NORMAL0: &[u8] = &[ @@ -225,7 +232,7 @@ const NORMAL0: &[u8] = &[ 0x06, 0x11, 0x81, 0xac, 0x0e, 0x80, 0xab, 0x35, - 0x1e, 0x15, + 0x28, 0x0b, 0x80, 0xe0, 0x03, 0x19, 0x08, 0x01, 0x04, @@ -237,8 +244,8 @@ const NORMAL0: &[u8] = &[ 0x11, 0x0a, 0x50, 0x0f, 0x12, 0x07, - 0x55, 0x08, - 0x02, 0x04, + 0x55, 0x07, + 0x03, 0x04, 0x1c, 0x0a, 0x09, 0x03, 0x08, 0x03, @@ -292,7 +299,7 @@ const NORMAL0: &[u8] = &[ 0x0b, 0x03, 0x80, 0xac, 0x06, 0x0a, 0x06, - 0x1f, 0x41, + 0x21, 0x3f, 0x4c, 0x04, 0x2d, 0x03, 0x74, 0x08, @@ -315,21 +322,19 @@ const NORMAL0: &[u8] = &[ 0x3b, 0x07, 0x02, 0x0e, 0x18, 0x09, - 0x80, 0xb0, 0x30, + 0x80, 0xb3, 0x2d, 0x74, 0x0c, 0x80, 0xd6, 0x1a, 0x0c, 0x05, 0x80, 0xff, 0x05, - 0x80, 0xb6, 0x05, - 0x24, 0x0c, - 0x9b, 0xc6, 0x0a, - 0xd2, 0x30, 0x10, + 0x80, 0xdf, 0x0c, + 0xee, 0x0d, 0x03, 0x84, 0x8d, 0x03, 0x37, 0x09, 0x81, 0x5c, 0x14, 0x80, 0xb8, 0x08, - 0x80, 0xc7, 0x30, - 0x35, 0x04, + 0x80, 0xcb, 0x2a, + 0x38, 0x03, 0x0a, 0x06, 0x38, 0x08, 0x46, 0x08, @@ -341,7 +346,7 @@ const NORMAL0: &[u8] = &[ 0x80, 0x83, 0x18, 0x1c, 0x0a, 0x16, 0x09, - 0x48, 0x08, + 0x4c, 0x04, 0x80, 0x8a, 0x06, 0xab, 0xa4, 0x0c, 0x17, 0x04, @@ -365,7 +370,7 @@ const NORMAL1: &[u8] = &[ 0x7b, 0x05, 0x03, 0x04, 0x2d, 0x03, - 0x65, 0x04, + 0x66, 0x03, 0x01, 0x2f, 0x2e, 0x80, 0x82, 0x1d, 0x03, @@ -410,16 +415,17 @@ const NORMAL1: &[u8] = &[ 0x33, 0x07, 0x2e, 0x08, 0x0a, 0x81, 0x26, - 0x1f, 0x80, 0x81, + 0x52, 0x4e, 0x28, 0x08, - 0x2a, 0x80, 0x86, + 0x2a, 0x56, + 0x1c, 0x14, 0x17, 0x09, 0x4e, 0x04, 0x1e, 0x0f, 0x43, 0x0e, 0x19, 0x07, 0x0a, 0x06, - 0x47, 0x09, + 0x48, 0x08, 0x27, 0x09, 0x75, 0x0b, 0x3f, 0x41, @@ -430,7 +436,7 @@ const NORMAL1: &[u8] = &[ 0x01, 0x05, 0x10, 0x03, 0x05, 0x80, 0x8b, - 0x60, 0x20, + 0x62, 0x1e, 0x48, 0x08, 0x0a, 0x80, 0xa6, 0x5e, 0x22, @@ -443,7 +449,8 @@ const NORMAL1: &[u8] = &[ 0x10, 0x80, 0xc0, 0x3c, 0x64, 0x53, 0x0c, - 0x01, 0x80, 0xa0, + 0x48, 0x09, + 0x0a, 0x46, 0x45, 0x1b, 0x48, 0x08, 0x53, 0x1d, @@ -456,7 +463,8 @@ const NORMAL1: &[u8] = &[ 0x0a, 0x06, 0x39, 0x07, 0x0a, 0x81, 0x36, - 0x19, 0x80, 0xc7, + 0x19, 0x80, 0xb7, + 0x01, 0x0f, 0x32, 0x0d, 0x83, 0x9b, 0x66, 0x75, 0x0b, @@ -474,9 +482,11 @@ const NORMAL1: &[u8] = &[ 0x4b, 0x04, 0x39, 0x07, 0x11, 0x40, - 0x04, 0x1c, + 0x05, 0x0b, + 0x02, 0x0e, 0x97, 0xf8, 0x08, - 0x82, 0xf3, 0xa5, 0x0d, + 0x84, 0xd6, 0x2a, + 0x09, 0xa2, 0xf7, 0x81, 0x1f, 0x31, 0x03, 0x11, 0x04, 0x08, @@ -515,17 +525,15 @@ const NORMAL1: &[u8] = &[ 0x2c, 0x04, 0x64, 0x0c, 0x56, 0x0a, - 0x0d, 0x03, - 0x5d, 0x03, - 0x3d, 0x39, + 0x80, 0xae, 0x38, 0x1d, 0x0d, 0x2c, 0x04, 0x09, 0x07, 0x02, 0x0e, 0x06, 0x80, 0x9a, - 0x83, 0xd6, 0x0a, + 0x83, 0xd8, 0x08, + 0x0d, 0x03, 0x0d, 0x03, - 0x0b, 0x05, 0x74, 0x0c, 0x59, 0x07, 0x0c, 0x14, @@ -533,12 +541,15 @@ const NORMAL1: &[u8] = &[ 0x38, 0x08, 0x0a, 0x06, 0x28, 0x08, - 0x1e, 0x52, - 0x77, 0x03, - 0x31, 0x03, - 0x80, 0xa6, 0x0c, - 0x14, 0x04, + 0x22, 0x4e, + 0x81, 0x54, 0x0c, + 0x15, 0x03, 0x03, 0x05, + 0x07, 0x09, + 0x19, 0x07, + 0x07, 0x09, 0x03, 0x0d, - 0x06, 0x85, 0x6a, + 0x07, 0x29, + 0x80, 0xcb, 0x25, + 0x0a, 0x84, 0x06, ]; diff --git a/src/libcore/unicode/unicode_data.rs b/src/libcore/unicode/unicode_data.rs index da4cd4e9b1da1..3e90028613ce1 100644 --- a/src/libcore/unicode/unicode_data.rs +++ b/src/libcore/unicode/unicode_data.rs @@ -1,128 +1,130 @@ ///! This file is generated by src/tools/unicode-table-generator; do not edit manually! use super::range_search; -pub const UNICODE_VERSION: (u32, u32, u32) = (12, 1, 0); +pub const UNICODE_VERSION: (u32, u32, u32) = (13, 0, 0); #[rustfmt::skip] pub mod alphabetic { - static BITSET_LAST_CHUNK_MAP: (u16, u8) = (190, 37); - static BITSET_CHUNKS_MAP: [u8; 187] = [ - 6, 32, 10, 18, 19, 23, 21, 12, 7, 5, 0, 20, 14, 49, 49, 49, 49, 49, 49, 36, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 47, 49, 30, 8, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 45, 0, 0, 0, 0, 0, 0, 0, 0, 4, 35, 17, 31, 16, 25, 24, 26, 13, 15, - 44, 27, 0, 0, 49, 11, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 38, 1, 49, 49, 49, 49, 49, 48, - 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 28, 0, 0, 0, 0, 0, 29, 0, 0, 9, 0, 33, 2, 3, 0, 0, - 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 41, 49, 49, 49, - 43, 22, 49, 49, 49, 49, 40, 49, 49, 49, 49, 49, 49, 46, + static BITSET_LAST_CHUNK_MAP: (u16, u8) = (196, 44); + static BITSET_CHUNKS_MAP: [u8; 196] = [ + 6, 32, 10, 18, 19, 23, 21, 12, 7, 5, 0, 20, 14, 50, 50, 50, 50, 50, 50, 37, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 49, 50, 30, 8, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 46, 0, 0, 0, 0, 0, 0, 0, 0, 4, 36, 17, 31, 16, 25, 24, 26, 13, 15, + 45, 27, 0, 0, 50, 11, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 39, 1, 50, 50, 50, 50, 50, 48, + 50, 34, 0, 0, 0, 0, 0, 0, 0, 0, 35, 0, 0, 28, 0, 0, 0, 0, 0, 29, 0, 0, 9, 0, 33, 2, 3, 0, 0, + 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 42, 50, 50, 50, + 43, 22, 50, 50, 50, 50, 41, 50, 50, 50, 50, 50, 50, 47, 0, 0, 0, 38, 0, 50, 50, 50, 50, ]; - static BITSET_INDEX_CHUNKS: [[u8; 16]; 50] = [ + static BITSET_INDEX_CHUNKS: [[u8; 16]; 51] = [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 0, 0, 248, 241, 38, 40], - [0, 0, 0, 0, 0, 0, 0, 0, 108, 133, 110, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 190, 200, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 248, 248, 248, 248, 248, 205, 248, 23, 134, 245, 68, 237], - [0, 0, 179, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 103, 99, 176, 248, 248, 248, 248, 248, 248, 248, 61, 0, 151, 217, 178], - [0, 145, 28, 0, 168, 221, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [48, 77, 248, 165, 201, 120, 184, 137, 91, 175, 143, 83, 206, 196, 248, 56], - [53, 0, 0, 0, 126, 15, 0, 0, 0, 0, 0, 58, 0, 0, 0, 0], - [59, 54, 127, 199, 167, 186, 157, 114, 154, 84, 160, 115, 158, 66, 155, 21], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 0, 0, 254, 247, 39, 68], + [0, 0, 0, 0, 0, 0, 0, 0, 111, 135, 113, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 195, 205, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 254, 254, 254, 254, 254, 210, 254, 25, 136, 251, 71, 243], + [0, 0, 182, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 107, 103, 180, 254, 254, 254, 254, 254, 254, 254, 61, 0, 155, 222, 181], + [0, 148, 30, 0, 172, 226, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [48, 80, 254, 169, 206, 123, 189, 139, 95, 179, 145, 86, 211, 204, 254, 56], + [53, 0, 0, 0, 129, 17, 0, 0, 0, 0, 0, 58, 0, 0, 0, 0], + [59, 54, 185, 203, 171, 191, 161, 117, 158, 87, 164, 118, 162, 67, 159, 23], [62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [91, 129, 164, 101, 248, 248, 248, 79, 248, 248, 248, 248, 230, 128, 135, 117], - [97, 0, 220, 144, 0, 0, 212, 44, 142, 240, 30, 97, 0, 0, 0, 0], - [116, 247, 219, 171, 188, 248, 104, 190, 0, 0, 0, 0, 0, 0, 0, 0], - [141, 185, 88, 0, 149, 213, 22, 0, 0, 0, 0, 89, 0, 0, 0, 0], - [147, 90, 35, 82, 98, 0, 153, 0, 85, 119, 29, 45, 86, 71, 18, 0], - [150, 32, 248, 107, 0, 81, 0, 0, 0, 0, 227, 17, 211, 105, 231, 19], - [162, 41, 161, 69, 163, 173, 123, 73, 106, 14, 124, 37, 1, 187, 121, 0], - [172, 240, 228, 170, 248, 248, 248, 248, 248, 229, 138, 235, 234, 24, 222, 125], - [208, 233, 248, 74, 204, 64, 140, 232, 63, 0, 0, 0, 0, 0, 0, 0], - [220, 97, 202, 86, 94, 78, 203, 9, 226, 80, 46, 0, 183, 11, 174, 67], - [231, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248], - [247, 248, 248, 248, 248, 248, 248, 248, 248, 209, 225, 95, 76, 75, 180, 25], - [248, 5, 96, 50, 72, 87, 248, 26, 132, 0, 198, 51, 159, 42, 0, 0], - [248, 8, 72, 72, 49, 0, 0, 0, 0, 0, 0, 0, 194, 5, 0, 89], - [248, 36, 248, 7, 0, 0, 139, 31, 143, 3, 93, 0, 55, 0, 0, 0], - [248, 62, 248, 248, 248, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [248, 118, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [248, 236, 166, 246, 136, 239, 248, 248, 248, 248, 215, 169, 182, 207, 214, 12], - [248, 248, 13, 130, 248, 248, 248, 248, 57, 146, 248, 65, 218, 248, 243, 177], - [248, 248, 191, 111, 197, 43, 0, 0, 248, 248, 248, 248, 91, 47, 0, 0], - [248, 248, 244, 248, 189, 223, 152, 70, 224, 210, 248, 148, 240, 242, 68, 100], - [248, 248, 248, 4, 248, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [248, 248, 248, 248, 35, 195, 248, 248, 248, 248, 248, 113, 0, 0, 0, 0], - [248, 248, 248, 248, 131, 240, 238, 109, 0, 181, 248, 122, 102, 216, 143, 27], - [248, 248, 248, 248, 248, 248, 86, 0, 248, 248, 248, 248, 248, 248, 248, 248], - [248, 248, 248, 248, 248, 248, 248, 248, 33, 0, 0, 0, 0, 0, 0, 0], - [248, 248, 248, 248, 248, 248, 248, 248, 97, 35, 0, 60, 65, 156, 16, 0], - [248, 248, 248, 248, 248, 248, 248, 248, 248, 6, 0, 0, 0, 0, 0, 0], - [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 192, 248, 248, 248, 248, 248], - [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 20, 248, 248, 248, 248], - [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 72, 0, 0, 0, 0], - [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 81, 248, 248, 248], - [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 23, 0], - [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 193, 112], - [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 39], - [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 65], - [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 92], - [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248], + [95, 131, 168, 105, 254, 254, 254, 82, 254, 254, 254, 254, 236, 130, 137, 120], + [101, 0, 225, 146, 151, 2, 217, 45, 144, 246, 32, 101, 0, 0, 0, 0], + [119, 253, 224, 175, 193, 254, 227, 195, 0, 0, 0, 0, 0, 0, 0, 0], + [143, 190, 91, 0, 153, 218, 24, 0, 0, 0, 0, 92, 0, 0, 66, 0], + [150, 94, 37, 85, 102, 0, 157, 0, 88, 122, 31, 46, 89, 74, 20, 0], + [154, 34, 254, 110, 0, 84, 0, 0, 0, 0, 233, 19, 216, 108, 237, 21], + [166, 42, 165, 72, 167, 177, 126, 76, 109, 16, 127, 38, 1, 192, 124, 0], + [176, 246, 234, 174, 254, 254, 254, 254, 254, 235, 140, 241, 240, 26, 228, 128], + [213, 239, 254, 77, 209, 64, 142, 238, 63, 0, 0, 0, 0, 0, 0, 0], + [225, 101, 207, 89, 98, 81, 208, 10, 232, 83, 147, 1, 188, 13, 178, 70], + [237, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254], + [253, 254, 254, 254, 254, 254, 254, 254, 254, 214, 231, 99, 79, 78, 183, 27], + [254, 6, 100, 50, 75, 90, 254, 28, 134, 0, 202, 51, 163, 43, 0, 0], + [254, 9, 75, 75, 49, 0, 0, 0, 0, 0, 69, 0, 199, 6, 195, 93], + [254, 41, 254, 8, 0, 0, 141, 33, 145, 4, 97, 0, 55, 0, 0, 0], + [254, 62, 254, 254, 254, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [254, 121, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [254, 242, 170, 252, 138, 245, 254, 254, 254, 254, 220, 173, 186, 212, 219, 14], + [254, 254, 15, 132, 254, 254, 254, 254, 57, 149, 254, 65, 223, 254, 249, 187], + [254, 254, 196, 114, 201, 44, 0, 0, 254, 254, 254, 254, 95, 47, 0, 0], + [254, 254, 250, 254, 194, 229, 156, 73, 230, 215, 254, 152, 246, 248, 71, 104], + [254, 254, 254, 5, 254, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [254, 254, 254, 22, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [254, 254, 254, 254, 37, 200, 254, 254, 254, 254, 254, 116, 0, 0, 0, 0], + [254, 254, 254, 254, 133, 246, 244, 112, 0, 184, 254, 125, 106, 221, 145, 29], + [254, 254, 254, 254, 254, 254, 254, 0, 254, 254, 254, 254, 254, 254, 254, 254], + [254, 254, 254, 254, 254, 254, 254, 254, 35, 0, 0, 0, 0, 0, 0, 0], + [254, 254, 254, 254, 254, 254, 254, 254, 101, 37, 0, 60, 65, 160, 18, 0], + [254, 254, 254, 254, 254, 254, 254, 254, 254, 7, 0, 0, 0, 0, 0, 0], + [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 197, 254, 254, 254, 254, 254], + [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 35, 254, 254, 254, 254], + [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 84, 254, 254, 254], + [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 11, 0, 0], + [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 25, 0], + [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 198, 115], + [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 40], + [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 96], + [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 125], + [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254], ]; - static BITSET: [u64; 249] = [ - 0, 1, 15, 17, 31, 63, 127, 179, 511, 1023, 2191, 4079, 4087, 8191, 8319, 16384, 65535, - 131071, 262143, 4128527, 8388607, 8461767, 24870911, 67108863, 134217727, 276824575, - 335544350, 486341884, 536805376, 536870911, 553648127, 1056964608, 1073692671, 1073741823, - 1140785663, 2147483647, 2147485627, 4026540127, 4294934783, 8589934591, 47244640256, - 64548249055, 68191066527, 68719476735, 115913785343, 137438953215, 549755813888, - 1095220854783, 1099511627711, 1099511627775, 2199023190016, 2199023255551, 4398046511103, - 8641373536127, 8791831609343, 8795690369023, 8796093022207, 13198434443263, 17592186044415, - 35184321757183, 70368744112128, 88094074470339, 140737488355327, 140737488355328, - 141836999983103, 281474976710655, 563017343310239, 1125625028935679, 1125899906842623, - 1688915364814303, 2119858418286774, 2251795522912255, 2251799813685247, 3377704004976767, - 3509778554814463, 3905461007941631, 4503595333443583, 4503599627370495, 8796093022142464, - 9006649498927104, 9007192812290047, 9007199254740991, 15762594400829440, 17169970223906821, - 17732925109967239, 18014398491652207, 18014398509481983, 20266198323101808, - 36027697507139583, 36028792723996672, 36028792728190975, 36028797018963967, - 72057594037927935, 90071992547409919, 143851303137705983, 144053615424700415, - 144115188075855868, 144115188075855871, 288230371860938751, 297241973452963840, - 301749971126844416, 319718190147960832, 576460743713488896, 576460743847706622, - 576460748008488959, 576460752303359999, 576460752303423486, 576460752303423487, - 790380184120328175, 1152640029630136575, 1152917029519358975, 1152921504591118335, - 1152921504606845055, 1152921504606846975, 1153765996922689951, 2161727885562420159, - 2251241253188403424, 2295745090394464220, 2305570330330005503, 2305843004918726656, - 2305843004919250943, 2305843009196916483, 2305843009213693951, 3457638613854978028, - 4323455298678290390, 4557642822898941951, 4575692405780512767, 4602678814877679616, - 4611686017001275199, 4611686018360336384, 4611686018427322368, 4611686018427387903, - 4656722014700830719, 6843210385291930244, 6881498031078244479, 6908521828386340863, - 8935141660164089791, 8935423131384840192, 9168765891372858879, 9169328841326329855, - 9187201948305063935, 9187343239835811327, 9216616637413720063, 9223372036854775807, - 9223372041149743103, 9223934986808197120, 10371930679322607615, 10502394331027995967, - 11241233151490523135, 13006395723845991295, 13258596753222922239, 13609596598936928288, - 13834776580305453567, 13907115649320091647, 14082190885810440174, 14123225865944680428, - 16212958624174047247, 16412803692974677999, 16424062692043104238, 16424062692043104239, - 16424062692043243502, 16424625641996804079, 16429129241624174575, 16717361816799141871, - 16717361816799216127, 16788293510930366511, 17005555242810474495, 17293822569102704639, - 17581979622616071300, 17870283321271910397, 17870283321406070975, 17870283321406128127, - 17978369712463020031, 18158513764145585631, 18158781978395017215, 18194542490281852927, - 18410715276682199039, 18410715276690587772, 18428729675200069631, 18428729675200069632, - 18433233274827440127, 18437455399478099968, 18437736874452713471, 18442240474082181119, + static BITSET: [u64; 255] = [ + 0, 1, 7, 15, 17, 31, 63, 127, 179, 511, 1023, 2047, 2191, 4079, 4087, 8191, 8319, 16384, + 65535, 131071, 262143, 4128527, 4194303, 8461767, 24870911, 67108863, 134217727, 276824575, + 335593502, 486341884, 536805376, 536870911, 553648127, 1056964608, 1073692671, 1073741823, + 1140785663, 2147483647, 4026540127, 4294934783, 8589934591, 15032387515, 64548249055, + 68191066527, 68719476735, 115913785343, 137438953215, 1095220854783, 1099511627711, + 1099511627775, 2199023190016, 2199023255551, 4398046511103, 8641373536127, 8791831609343, + 8795690369023, 8796093022207, 13198434443263, 17592186044415, 35184321757183, + 70368744112128, 88094074470339, 140737488355327, 140737488355328, 141836999983103, + 281474976710655, 281474976710656, 563017343310239, 844472174772224, 875211255709695, + 1125625028935679, 1125899906842623, 1688915364814303, 2119858418286774, 2251795522912255, + 2251799813685247, 3377704004976767, 3509778554814463, 3905461007941631, 4503595333443583, + 4503599627370495, 8796093022142464, 9006649498927104, 9007192812290047, 9007199254740991, + 15762594400829440, 17169970223906821, 17732925109967239, 18014398491652207, + 18014398509481983, 20266198323101936, 36027697507139583, 36028792723996672, + 36028792723996703, 36028792728190975, 36028797018963967, 72057594037927935, + 90071992547409919, 143851303137705983, 144053615424700415, 144115188075855868, + 144115188075855871, 288230371860938751, 297241973452963840, 301749971126844416, + 319718190147960832, 576460743713488896, 576460743847706622, 576460752303359999, + 576460752303423486, 576460752303423487, 790380184120328175, 1152640029630136575, + 1152917029519358975, 1152921504591118335, 1152921504606845055, 1152921504606846975, + 1153765996922689951, 2161727885562420159, 2251241253188403424, 2295745090394464220, + 2305570330330005503, 2305843004918726656, 2305843004919250943, 2305843009196916483, + 2305843009213693951, 3457638613854978030, 4323455298678290390, 4557642822898941951, + 4575692405780512767, 4611686017001275199, 4611686018360336384, 4611686018427322368, + 4611686018427387903, 4656722014700830719, 6843210385291930244, 6881498031078244479, + 6908521828386340863, 8935141660164089791, 8935423131384840192, 9168765891372858879, + 9169328841326329855, 9187201948305063935, 9187343239835811327, 9216616637413720063, + 9223372036854775807, 9223372041149743103, 9223372586610589696, 9223934986808197120, + 10371930679322607615, 10502394331027995967, 11078855083321979519, 11241233151490523135, + 13006395723845991295, 13258596753222922239, 13609596598936928288, 13834776580305453567, + 13907115649320091647, 14082190885810440174, 14123225865944680428, 16212958624174047247, + 16412803692974677999, 16424062692043104238, 16424062692043104239, 16424062692043243502, + 16424625641996804079, 16429129241624174575, 16717361816799141887, 16717361816799216127, + 16788293510930366511, 17005555242810474495, 17293822569102704639, 17581979622616071300, + 17870283321271910397, 17870283321406070975, 17870283321406128127, 17978369712463020031, + 18158513764145585631, 18158781978395017215, 18194542490281852927, 18410715276682199039, + 18428729675200069631, 18428729675200069632, 18433233274827440127, 18437455399478099968, + 18437736870159843328, 18437736874452713471, 18437736874454812668, 18442240474082181119, 18444492273895866367, 18445618173802708993, 18446181192473632767, 18446216308128218879, 18446462598732840928, 18446462598732840959, 18446462598732840960, 18446462599806582783, 18446462615912710143, 18446462667452317695, 18446463149025525759, 18446463629525450752, - 18446463698110251007, 18446463698244468735, 18446464796682337663, 18446466966713532416, + 18446463698244468735, 18446464796682337663, 18446466966713532671, 18446466996645134335, 18446466996779287551, 18446471394825862144, 18446471394825863167, 18446480190918885375, 18446498607738650623, 18446532967477018623, 18446602782178705022, 18446603336221163519, 18446603336221196287, 18446638520593285119, 18446673709243564031, 18446708893632430079, 18446740770879700992, 18446741595513422027, 18446741874686295551, 18446743249075830783, 18446743798965862398, 18446744056529672000, 18446744060816261120, 18446744068886102015, - 18446744069414584320, 18446744069414601696, 18446744069414649855, 18446744069456527359, - 18446744069548736512, 18446744069548802046, 18446744069683019775, 18446744069951455231, - 18446744070421282815, 18446744070446333439, 18446744070475743231, 18446744070488326143, - 18446744071553646463, 18446744071562067967, 18446744073696837631, 18446744073701162813, - 18446744073707454463, 18446744073709027328, 18446744073709355007, 18446744073709419615, - 18446744073709486080, 18446744073709520895, 18446744073709543424, 18446744073709550079, - 18446744073709550595, 18446744073709551579, 18446744073709551599, 18446744073709551614, - 18446744073709551615, + 18446744069414584320, 18446744069414601696, 18446744069414617087, 18446744069414649855, + 18446744069456527359, 18446744069548736512, 18446744069548802046, 18446744069683019775, + 18446744069951455231, 18446744070421282815, 18446744070446333439, 18446744070475743231, + 18446744070488326143, 18446744071553646463, 18446744071562067967, 18446744073696837631, + 18446744073701162813, 18446744073707454463, 18446744073709027328, 18446744073709355007, + 18446744073709419615, 18446744073709486080, 18446744073709520895, 18446744073709543424, + 18446744073709550079, 18446744073709550595, 18446744073709551579, 18446744073709551599, + 18446744073709551614, 18446744073709551615, ]; pub fn lookup(c: char) -> bool { @@ -141,82 +143,83 @@ pub mod case_ignorable { static BITSET_LAST_CHUNK_MAP: (u16, u8) = (896, 33); static BITSET_CHUNKS_MAP: [u8; 125] = [ 25, 14, 21, 30, 28, 4, 17, 23, 22, 0, 0, 16, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 13, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 13, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6, 9, 0, 7, 11, 32, 31, 26, 29, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, - 10, 0, 8, 0, 20, 0, 12, 0, 1, + 10, 0, 8, 0, 19, 0, 12, 0, 1, ]; static BITSET_INDEX_CHUNKS: [[u8; 16]; 34] = [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 47, 52], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 171, 2], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 88, 134, 38], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 102, 6, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 76, 26, 0, 146, 136, 79, 43, 117], - [0, 0, 0, 0, 0, 0, 0, 0, 152, 0, 0, 58, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 165, 97, 75, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 48, 0, 114, 0, 0], - [0, 0, 0, 0, 0, 170, 68, 0, 0, 7, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0], - [0, 0, 0, 28, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 133, 0, 0, 0, 0, 15, 160, 45, 84, 51, 78, 12, 109], - [0, 0, 11, 0, 0, 30, 161, 90, 35, 80, 0, 69, 173, 13, 81, 129], - [0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 131, 0, 85, 0, 148, 0, 175, 73, 0, 0, 0, 0, 0, 0, 0], - [20, 4, 62, 0, 118, 0, 0, 0, 32, 154, 145, 0, 124, 89, 67, 86], - [25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [59, 0, 0, 150, 70, 24, 132, 60, 100, 122, 163, 99, 0, 46, 0, 66], - [63, 0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0], - [71, 33, 0, 178, 123, 83, 120, 137, 121, 98, 121, 167, 153, 55, 3, 18], - [72, 149, 36, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [104, 133, 0, 110, 174, 105, 177, 166, 0, 0, 0, 0, 0, 0, 155, 139], - [107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [111, 50, 106, 0, 0, 0, 0, 0, 0, 0, 172, 179, 179, 112, 9, 0], - [113, 0, 0, 0, 0, 0, 0, 49, 142, 34, 31, 0, 0, 0, 0, 0], - [116, 0, 42, 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [140, 93, 37, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0], - [159, 0, 101, 0, 158, 10, 29, 0, 0, 0, 0, 91, 0, 0, 0, 0], - [162, 56, 153, 54, 125, 53, 0, 27, 115, 21, 126, 19, 108, 144, 127, 8], - [168, 41, 151, 5, 0, 0, 157, 39, 156, 1, 103, 0, 65, 0, 0, 0], - [169, 147, 130, 17, 96, 87, 143, 16, 138, 0, 0, 64, 125, 95, 0, 0], - [176, 179, 0, 0, 179, 179, 179, 77, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 47, 57], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 173, 3], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 90, 136, 38], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 104, 7, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 78, 27, 0, 148, 138, 81, 44, 119], + [0, 0, 0, 0, 0, 0, 0, 0, 154, 0, 0, 58, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 167, 99, 77, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 130, 0, 0, 0, 48, 0, 116, 0, 0], + [0, 0, 0, 0, 0, 172, 70, 0, 0, 8, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 67, 0, 0, 24, 0, 0], + [0, 0, 0, 29, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 135, 0, 0, 0, 0, 16, 162, 46, 86, 51, 80, 13, 111], + [0, 0, 12, 0, 0, 43, 163, 92, 35, 82, 0, 71, 175, 14, 83, 131], + [0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 133, 0, 87, 0, 150, 0, 178, 75, 0, 0, 0, 0, 0, 0, 0], + [20, 5, 61, 0, 120, 0, 0, 0, 32, 156, 176, 1, 126, 91, 69, 88], + [26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [62, 0, 0, 0, 137, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 0], + [66, 0, 0, 152, 72, 25, 134, 59, 102, 124, 165, 101, 0, 64, 0, 68], + [73, 33, 0, 181, 125, 85, 122, 139, 123, 100, 123, 169, 155, 54, 4, 18], + [74, 151, 36, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [106, 135, 0, 112, 177, 107, 180, 168, 0, 0, 0, 0, 0, 0, 157, 142], + [109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [113, 50, 108, 0, 0, 0, 0, 0, 0, 0, 174, 182, 182, 114, 10, 0], + [115, 0, 0, 0, 141, 5, 0, 49, 145, 34, 31, 0, 0, 0, 0, 0], + [118, 0, 42, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [143, 95, 37, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0], + [161, 0, 103, 0, 160, 11, 30, 0, 0, 0, 0, 93, 0, 0, 0, 0], + [164, 55, 155, 53, 127, 52, 2, 28, 117, 21, 128, 19, 110, 147, 129, 9], + [170, 41, 153, 6, 0, 0, 159, 39, 158, 1, 105, 0, 65, 0, 0, 0], + [171, 149, 132, 17, 98, 89, 146, 23, 140, 0, 0, 63, 127, 97, 0, 0], + [179, 182, 0, 0, 182, 182, 182, 79, 0, 0, 0, 0, 0, 0, 0, 0], ]; - static BITSET: [u64; 180] = [ - 0, 1, 3, 4, 8, 13, 15, 28, 64, 176, 191, 1016, 1792, 2047, 4080, 4096, 7680, 8192, 8193, - 16192, 30720, 32704, 32768, 131008, 262016, 2097152, 2359296, 6030336, 8323072, 10682368, - 33554432, 58719232, 159383552, 234881024, 243138688, 402587711, 536805376, 536879204, - 546307648, 805306369, 1073741824, 1073741916, 2113929216, 3221225472, 3758096384, - 4026531840, 4160749568, 4294934528, 4294967296, 4512022528, 5368709120, 17179869183, - 47244640256, 51539615774, 51539619904, 51543810078, 51545914817, 66035122176, 412316860416, - 412316862532, 412316893184, 1030792151040, 2199023255648, 8641373536127, 8763880767488, - 17303886364672, 36421322670080, 65128884076547, 65970697670631, 68168642985984, - 70093866270720, 70368739983360, 136957967529984, 140737488355328, 263882790666240, - 281470547525648, 281470682333183, 281474976710655, 281474976710656, 281474976710657, - 281479271675905, 562675075514368, 562949953355776, 563001509683710, 844424930131968, - 985162418487296, 1023920203366400, 2251799813685248, 3377699721314304, 4494803534348292, - 4503599627370678, 6755399441055744, 7881299349733376, 8444256867844096, 8725724278030336, - 8760633772212225, 8989057312882695, 9042383626829823, 9851624185018758, 24822575045541890, - 28848986089586688, 30958948903026688, 35747322042253312, 53805701016846336, - 58529202969772032, 72066390130950143, 112767012056334336, 143833713099145216, - 189151184399892480, 216172782113783808, 220713756545974272, 288301294651703296, - 302022650010533887, 504262420777140224, 558446353793941504, 572520102629474304, - 593978171557150752, 1008806350890729472, 1009933895770046464, 1152921504606846976, - 1152921504606846978, 1152921504606846982, 1153202979583561736, 1441151880758558727, - 1715871458028158991, 1729382256910270467, 2301902359539744768, 2305843009196908767, - 2305843009213693952, 2612078987781865472, 2771965570646540291, 3458764513820540928, - 3731232291276455943, 4539628424389459968, 4589168020290535424, 4611404543450677248, - 4611686018494513280, 4611686069967003678, 4671217976001691648, 6917775322003857411, - 7421334051581067264, 8070450532247928832, 8788774672813524990, 9205357638345293827, - 9222809086901354496, 9223091111633879040, 9223372036854775808, 9223372036854775935, - 9223512774343131136, 9224216320050987008, 9224497932466651184, 9653465801268658176, - 9727775195120332910, 10376293541461622786, 11526998316797657088, 11529215046068469760, - 12103423998558208000, 12699025049277956096, 13005832773892571136, 13798747783286489088, - 13832665517980123136, 13835058055282032640, 13835058055282163729, 13951307220663664640, - 17870283321406128128, 17906312118425092095, 18158513697557839871, 18158513749097456062, - 18374686479671623680, 18374686479671623682, 18444496122186563584, 18445618173802708992, - 18446462598732840960, 18446462598733004800, 18446726481523507200, 18446744069414584320, - 18446744069414584322, 18446744073575333888, 18446744073709027328, 18446744073709551615, + static BITSET: [u64; 183] = [ + 0, 1, 2, 3, 4, 8, 13, 15, 28, 64, 176, 191, 1016, 1792, 2047, 4080, 4096, 8192, 8193, + 16192, 30720, 32704, 32768, 40448, 131008, 262016, 2097152, 2359296, 6030336, 8323072, + 10682368, 58719232, 159383552, 234881024, 243138688, 402587711, 536805376, 536879204, + 546307648, 805306369, 1073741824, 1073741916, 2113929216, 2181038080, 3221225472, + 3758096384, 4026531840, 4294934528, 4294967296, 4512022528, 5368709120, 17179869183, + 51539615774, 51539619904, 51545907230, 51545914817, 66035122176, 115964116992, 412316860416, + 412316893184, 1030792151040, 2199023255648, 8641373536127, 8763880767488, 15397323538432, + 17303886364672, 18004502906948, 26388279066624, 36421322670080, 65128884076547, + 65970697670631, 68168642985984, 70093866270720, 70368739983360, 136957967529984, + 140737488355328, 263882790666240, 281470547525648, 281470682333183, 281474976710655, + 281474976710656, 281474976710657, 281479271675905, 562675075514368, 562949953355776, + 563001509683710, 844424930131968, 985162418487296, 1023920203366400, 2251799813685248, + 3377699721314304, 4494803534348292, 4503599627370678, 6755399441055744, 7881299349733376, + 8444256867844096, 8725724278030336, 8760633772212225, 8989057312882695, 9042383626829823, + 9851624185018758, 24822575045541890, 28848986089586688, 30958948903026688, + 35747322042253312, 53805701016846336, 58529202969772032, 72066390130950143, + 112767012056334336, 143833713099145216, 189151184399892480, 216172782113783808, + 220713756545974272, 288301294651703296, 302022650010533887, 504262420777140224, + 558446353793941504, 572520102629474304, 593978171557150752, 1008806350890729472, + 1009933895770046464, 1152921504606846976, 1152921504606846978, 1152921504606846982, + 1153202979583561736, 1441151880758558727, 1715871458028158991, 1729382256910270467, + 2301902359539744768, 2305843009196908767, 2305843009213693952, 2612078987781865472, + 2771965570646540291, 3458764513820540928, 3731232291276455943, 4539628424389459968, + 4589168020290535424, 4611404543450677248, 4611686018494513280, 4611686069967003678, + 4671217976001691648, 6341068275337658368, 6917775322003857411, 7421334051581067264, + 8070450532247928832, 8788774672813524990, 9205357638345293827, 9222809086901354496, + 9223372036854775808, 9223372036854775935, 9223512774343131136, 9224216320050987008, + 9224497932466651184, 9653465801268658176, 9727775195120332910, 10376293541461622786, + 11526998316797657088, 11529215046068469760, 12103423998558208000, 12699025049277956096, + 13005832773892571136, 13798747783286489088, 13832665517980123136, 13835058055282032640, + 13835058055282163729, 13951307220663664640, 17870283321406128128, 17906312118425092095, + 18158513697557839871, 18158513749097456062, 18374686479671623680, 18374686479671623682, + 18444496122186563584, 18445618173802708992, 18446462598732840960, 18446462598733004800, + 18446463148488654848, 18446726481523507200, 18446744069414584320, 18446744069414584322, + 18446744073575333888, 18446744073709027328, 18446744073709551615, ]; pub fn lookup(c: char) -> bool { @@ -264,13 +267,13 @@ pub mod cased { static BITSET: [u64; 63] = [ 0, 15, 24, 511, 1023, 4087, 65535, 16253055, 134217726, 536805376, 1073741823, 4294967295, 133143986179, 4398046511103, 36009005809663, 70368744177663, 2251799813685247, - 3509778554814463, 144115188074807295, 297241973452963840, 504403158265495676, + 3509778554814463, 144115188074807295, 297241973452963840, 531424756029720572, 576460743713488896, 576460743847706622, 1152921504591118335, 2295745090394464220, 4557642822898941951, 4611686017001275199, 6908521828386340863, 8935141660164089791, 9223934986808197120, 13605092999309557792, 16717361816799216127, 16717361816799223999, 17005555242810474495, 17446871633794956420, 17870283321271910397, 17870283321406128127, 18410715276682199039, 18428729675200069631, 18428729675200069632, 18437736874452713471, - 18446462598732840959, 18446462598732840960, 18446463698110251007, 18446466996779287551, + 18446462598732840959, 18446462598732840960, 18446464797621878783, 18446466996779287551, 18446603336221163519, 18446603336221196287, 18446741874686295551, 18446743249075830783, 18446744056529672000, 18446744056529682432, 18446744069414584320, 18446744069414601696, 18446744069422972927, 18446744070475743231, 18446744071562067967, 18446744073707454463, @@ -317,72 +320,72 @@ pub mod grapheme_extend { static BITSET_LAST_CHUNK_MAP: (u16, u8) = (896, 30); static BITSET_CHUNKS_MAP: [u8; 123] = [ 4, 15, 21, 27, 25, 3, 18, 23, 17, 0, 0, 14, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 7, 10, 0, 8, 12, 29, 28, 24, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, - 11, 0, 9, 0, 20, 0, 13, + 11, 0, 9, 0, 19, 0, 13, ]; static BITSET_INDEX_CHUNKS: [[u8; 16]; 31] = [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 18, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 70, 102, 29], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 62, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 83, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 35, 66, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 0, 0, 35, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 117, 0, 0, 45, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 130, 78, 60, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 99, 0, 0, 0, 37, 0, 90, 0, 0], - [0, 0, 0, 0, 0, 129, 54, 0, 0, 3, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0], - [0, 0, 0, 19, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 67, 0, 114, 0, 137, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 7, 0, 0, 0, 125, 5, 24, 63, 0, 55, 135, 9, 64, 100], - [0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [10, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [12, 0, 48, 0, 92, 0, 0, 0, 25, 119, 113, 0, 96, 71, 53, 68], - [46, 0, 0, 116, 57, 17, 101, 44, 81, 94, 127, 80, 0, 0, 0, 52], - [49, 0, 0, 0, 83, 0, 0, 0, 0, 0, 0, 58, 0, 0, 0, 0], - [56, 26, 0, 136, 95, 43, 107, 105, 93, 79, 93, 132, 128, 42, 104, 20], - [59, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [85, 0, 0, 87, 0, 0, 0, 131, 0, 0, 0, 0, 0, 0, 0, 0], - [89, 0, 0, 0, 0, 0, 0, 38, 110, 27, 22, 0, 0, 0, 0, 0], - [109, 74, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0], - [124, 0, 82, 0, 123, 6, 21, 0, 0, 0, 0, 72, 0, 0, 0, 0], - [126, 40, 118, 39, 108, 41, 0, 34, 91, 14, 97, 13, 86, 112, 98, 4], - [133, 32, 120, 2, 0, 0, 122, 30, 121, 1, 84, 0, 51, 0, 0, 0], - [134, 115, 88, 0, 77, 69, 111, 11, 106, 0, 0, 50, 108, 76, 0, 0], - [137, 138, 0, 0, 138, 138, 138, 62, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 20, 46], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 74, 106, 31], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 66, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 87, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 37, 70, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, 0, 37, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 121, 0, 0, 48, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 134, 82, 64, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 39, 0, 94, 0, 0], + [0, 0, 0, 0, 0, 133, 58, 0, 0, 5, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 55, 0, 0, 18, 0, 0], + [0, 0, 0, 21, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 71, 0, 118, 0, 142, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 9, 0, 0, 0, 129, 7, 26, 67, 0, 59, 140, 11, 68, 104], + [0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [12, 0, 0, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [13, 0, 50, 0, 96, 0, 0, 0, 27, 123, 139, 1, 100, 75, 57, 72], + [51, 0, 0, 0, 87, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0], + [54, 0, 0, 120, 61, 19, 105, 47, 85, 98, 131, 84, 0, 0, 0, 56], + [60, 28, 0, 141, 99, 45, 111, 109, 97, 83, 97, 136, 132, 44, 108, 22], + [63, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [89, 0, 0, 91, 0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 0, 0], + [93, 0, 0, 0, 113, 3, 0, 40, 115, 29, 24, 0, 0, 0, 0, 0], + [114, 78, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0], + [128, 0, 86, 0, 127, 8, 23, 0, 0, 0, 0, 76, 0, 0, 0, 0], + [130, 42, 122, 41, 112, 43, 2, 36, 95, 15, 101, 14, 90, 117, 102, 6], + [137, 34, 124, 4, 0, 0, 126, 32, 125, 1, 88, 0, 53, 0, 0, 0], + [138, 119, 92, 0, 81, 73, 116, 17, 110, 0, 0, 52, 112, 80, 0, 0], + [142, 143, 0, 0, 143, 143, 143, 66, 0, 0, 0, 0, 0, 0, 0, 0], ]; - static BITSET: [u64; 139] = [ - 0, 1, 13, 28, 64, 182, 191, 1016, 2032, 2047, 4096, 7680, 14336, 16128, 32640, 32768, - 131008, 262016, 491520, 8323072, 8396801, 10682368, 58719232, 100663296, 134152192, + static BITSET: [u64; 144] = [ + 0, 1, 2, 8, 13, 28, 64, 182, 191, 1016, 2032, 2047, 4096, 14336, 16128, 32640, 32768, + 40448, 131008, 262016, 491520, 8323072, 8396801, 10682368, 58719232, 100663296, 134152192, 159383552, 234881024, 243138688, 536879204, 537919040, 805306369, 1073741824, 1073741916, 1610612736, 2153546752, 3221225472, 3758096384, 4294967296, 4512022528, 51545911364, - 51545914817, 51548004382, 51552198686, 51556262398, 137438953472, 412316860416, - 412316862532, 1030792151040, 2199023255648, 8641373536127, 8763880767488, 17303886364672, - 36421322670080, 65128884076547, 65970697670631, 67755789254656, 69200441769984, - 70093866270720, 263882790666240, 277076930199552, 281470547525648, 281470681808895, - 281474976710655, 281479271675904, 562675075514368, 562949953355776, 844424930131968, - 985162418487296, 1023920203366400, 2251799813685248, 3377699721314304, 4494803534348292, - 6755399441055744, 7881299349733376, 8444256867844096, 8725724278030336, 8760633780600833, - 8989057312882695, 9042383626829823, 9851624185018758, 18067175067615234, 28848986089586688, - 30958948903026688, 35747322042253312, 53805701016846336, 58529202969772032, - 189151184399892480, 220713756545974272, 466122561432846339, 504262420777140224, - 558446353793941504, 572520102629474304, 1009933895770046464, 1152921504606846982, - 1152921504606851080, 1441151880758558727, 1724878657282899983, 2301902359539744768, - 2305843009196908767, 2305843009213693952, 2310337812748042240, 3731232291276455943, - 4589168020290535424, 4609293481125347328, 4611686018427387908, 4611686069975392286, - 4671217976001691648, 5764607523034234882, 6341068275337658371, 7421334051581067264, - 8788774672813524990, 9205357638345293827, 9222809086901354496, 9223090561878065152, - 9223372036854775808, 9223372036854775935, 9224497932466651184, 9727775195120332910, - 10376293541461622786, 11526998316797657088, 11959590285459062784, 12103423998558208000, - 12699165786766311424, 13005832773892571136, 13798747783286489088, 13835058055282032640, - 13835058055282163729, 13951307220663664640, 14987979559889010690, 17872468738205286400, - 17906312118425092095, 18158513697557839871, 18158513749097456062, 18374686479671623680, - 18374686479671623682, 18446462598732972032, 18446744056529158144, 18446744069414584320, - 18446744073709551615, + 51545914817, 51548004382, 51554295838, 51556262398, 68719476736, 137438953472, 412316860416, + 1030792151040, 2199023255648, 8641373536127, 8763880767488, 17303886364672, 18004502906948, + 26388279066624, 36421322670080, 65128884076547, 65970697670631, 67755789254656, + 69200441769984, 70093866270720, 263882790666240, 277076930199552, 281470547525648, + 281470681808895, 281474976710655, 281479271675904, 562675075514368, 562949953355776, + 844424930131968, 985162418487296, 1023920203366400, 2251799813685248, 3377699721314304, + 4494803534348292, 6755399441055744, 7881299349733376, 8444256867844096, 8725724278030336, + 8760633780600833, 8989057312882695, 9042383626829823, 9851624185018758, 18067175067615234, + 28848986089586688, 30958948903026688, 35747322042253312, 53805701016846336, + 58529202969772032, 189151184399892480, 220713756545974272, 466122561432846339, + 504262420777140224, 558446353793941504, 572520102629474304, 1009933895770046464, + 1152921504606846982, 1152921504606851080, 1441151880758558727, 1724878657282899983, + 2301902359539744768, 2305843009196908767, 2305843009213693952, 2310337812748042240, + 3731232291276455943, 4589168020290535424, 4609293481125347328, 4611686018427387908, + 4611686069975392286, 4671217976001691648, 5764607523034234882, 6341068275337658371, + 6341349750314369024, 7421334051581067264, 8788774672813524990, 9205357638345293827, + 9222809086901354496, 9223372036854775808, 9223372036854775935, 9224497932466651184, + 9727775195120332910, 10376293541461622786, 11526998316797657088, 11959590285459062784, + 12103423998558208000, 12699165786766311424, 13005832773892571136, 13798747783286489088, + 13835058055282032640, 13835058055282163729, 13951307220663664640, 14987979559889010690, + 17872468738205286400, 17906312118425092095, 18158513697557839871, 18158513749097456062, + 18374686479671623680, 18374686479671623682, 18446462598732840960, 18446462598732972032, + 18446744056529158144, 18446744069414584320, 18446744073709551615, ]; pub fn lookup(c: char) -> bool { @@ -430,7 +433,7 @@ pub mod lowercase { 133143986179, 274877905920, 1099509514240, 4398046445568, 17592185782272, 36009005809663, 46912496118442, 187649984473770, 281474972516352, 2251799813685247, 2339875276368554, 4503599560261632, 61925590106570972, 71777214282006783, 72057592964186127, - 144115188074807295, 297241973452963840, 504403158265495560, 576460743713488896, + 144115188074807295, 297241973452963840, 522417556774978824, 576460743713488896, 1152921487426978047, 1152921504590069760, 1814856824841797631, 3607524039012697088, 4362299189061746720, 4539628424389459968, 4601013482110844927, 4611405638684049471, 4674456033467236607, 6172933889249159850, 9223934986808197120, 10663022717737544362, @@ -439,7 +442,7 @@ pub mod lowercase { 12298110845996498944, 15324248332066007893, 16596095761559859497, 16717361816799215616, 16987577794709946364, 17293822586148356092, 18158513701852807104, 18410715274543104000, 18428729675466407935, 18446462598732840960, 18446462598732858304, 18446462598737002495, - 18446463698110251007, 18446673704966422527, 18446726481523572736, 18446739675663105535, + 18446464797621878783, 18446673704966422527, 18446726481523572736, 18446739675663105535, 18446739675663106031, 18446742974197923840, 18446744056529682432, 18446744069414584320, 18446744073709529733, 18446744073709551615, ]; @@ -457,56 +460,57 @@ pub mod lowercase { #[rustfmt::skip] pub mod n { - static BITSET_LAST_CHUNK_MAP: (u16, u8) = (124, 11); - static BITSET_CHUNKS_MAP: [u8; 124] = [ - 30, 7, 10, 24, 18, 3, 28, 20, 23, 27, 0, 15, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 2, 12, 17, 25, 16, 22, 19, 14, 21, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 6, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 4, 1, 0, 0, 9, 0, 13, 26, + static BITSET_LAST_CHUNK_MAP: (u16, u8) = (127, 0); + static BITSET_CHUNKS_MAP: [u8; 127] = [ + 31, 8, 11, 25, 19, 4, 29, 21, 24, 28, 0, 16, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3, 13, 18, 26, 17, 23, 20, 15, 22, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 2, 0, 0, 10, 0, 14, 27, 12, 0, 1, ]; - static BITSET_INDEX_CHUNKS: [[u8; 16]; 33] = [ + static BITSET_INDEX_CHUNKS: [[u8; 16]; 34] = [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 48], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 0, 42, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 21, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 46, 0, 0, 0, 2], - [0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 30, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 46, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 30, 0, 44, 0, 30, 0, 30, 0, 40, 0, 33], - [0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 36, 43, 4, 0, 0, 0, 0, 51, 22, 3, 0, 12], - [0, 0, 0, 6, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 61, 46, 0, 0, 0, 0, 59, 0, 0, 23, 9, 0, 0], - [0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 2, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0], - [0, 14, 0, 14, 0, 0, 0, 0, 0, 14, 0, 2, 50, 0, 0, 0], - [0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 25, 0, 0, 0, 14, 24, 0, 0, 0, 0, 0, 0, 0, 0, 10], - [0, 31, 0, 46, 64, 0, 0, 38, 0, 0, 0, 46, 0, 0, 0, 0], - [0, 45, 2, 0, 0, 70, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 58, 0, 30, 0, 41, 0, 30, 0, 14, 0, 14, 35, 0, 0, 0], - [0, 62, 29, 60, 17, 0, 54, 69, 0, 56, 19, 27, 0, 63, 28, 0], - [0, 65, 37, 0, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 68, 18, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 8, 0], - [14, 0, 0, 0, 0, 7, 0, 16, 0, 0, 15, 0, 0, 14, 46, 0], - [39, 0, 0, 14, 2, 0, 0, 47, 0, 14, 0, 0, 0, 0, 0, 46], - [46, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [49, 0, 0, 0, 0, 0, 11, 0, 24, 20, 66, 0, 0, 0, 0, 0], - [72, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 49], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 43, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 22, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 47, 0, 0, 0, 2], + [0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 31, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 31, 0, 45, 0, 31, 0, 31, 0, 41, 0, 34], + [0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 37, 44, 4, 0, 0, 0, 0, 52, 23, 3, 0, 13], + [0, 0, 0, 7, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 35, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 62, 47, 0, 0, 0, 0, 60, 0, 0, 24, 10, 0, 5], + [0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 2, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 0], + [0, 15, 0, 15, 0, 0, 0, 0, 0, 15, 0, 2, 51, 0, 0, 0], + [0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 26, 0, 0, 0, 15, 25, 0, 0, 0, 0, 0, 0, 0, 0, 11], + [0, 32, 0, 47, 65, 0, 0, 39, 0, 0, 0, 47, 0, 0, 0, 0], + [0, 46, 2, 0, 0, 71, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 59, 0, 31, 0, 42, 0, 31, 0, 15, 0, 15, 36, 0, 0, 0], + [0, 63, 30, 61, 18, 0, 55, 70, 0, 57, 20, 28, 0, 64, 29, 0], + [0, 66, 38, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 69, 19, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 9, 0], + [15, 0, 0, 0, 0, 8, 0, 17, 0, 0, 16, 0, 0, 15, 47, 0], + [40, 0, 0, 15, 2, 0, 0, 48, 0, 15, 0, 0, 0, 0, 0, 47], + [47, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [50, 0, 0, 0, 0, 0, 12, 0, 25, 21, 67, 0, 0, 0, 0, 0], + [73, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], ]; - static BITSET: [u64; 73] = [ - 0, 999, 1023, 1026, 3072, 8191, 65408, 65472, 1048575, 1966080, 2097151, 3932160, 4063232, - 8388607, 67043328, 67044351, 134152192, 264241152, 268435455, 3758096384, 4294901504, - 17112694784, 64424509440, 549218942976, 4393751543808, 35184372023296, 140737488355327, - 272678883688448, 279275953455104, 280925220896768, 281200098803712, 281474976448512, - 492581209243648, 2251524935778304, 2251795518717952, 4503595332403200, 4503599627370368, - 8708132091985919, 9007190731849728, 17732923532771328, 71212894229889024, + static BITSET: [u64; 74] = [ + 0, 999, 1023, 1026, 3072, 4064, 8191, 65408, 65472, 1048575, 1966080, 2097151, 3932160, + 4063232, 8388607, 67043328, 67044351, 134152192, 264241152, 268435455, 3758096384, + 4294901504, 17112694784, 64424509440, 549218942976, 4393751543808, 35184372023296, + 140737488355327, 272678883688448, 279275953455104, 280925220896768, 281200098803712, + 281474976448512, 492581209243648, 2251524935778304, 2251795518717952, 4503595332403200, + 4503599627370368, 8708132091985919, 9007190731849728, 17732923532771328, 71212894229889024, 144114915328655360, 144115183780888576, 144115188075855871, 284007976623144960, 284008251501051904, 287948901175001088, 287948901242044416, 287953294926544896, 504407547722072192, 1152640029630136320, 1152921496016912384, 2305840810190438400, @@ -541,28 +545,28 @@ pub mod uppercase { static BITSET_INDEX_CHUNKS: [[u8; 16]; 17] = [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 10, 0, 38, 46, 44, 2], - [0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 51, 24, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 60, 62, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 54, 0, 0, 0, 0, 0, 43, 43, 40, 43, 56, 23, 34, 35], - [0, 0, 57, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 9, 0, 38, 46, 44, 28], + [0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 51, 23, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 60, 62, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 54, 0, 0, 0, 0, 0, 43, 43, 40, 43, 56, 22, 34, 35], + [0, 0, 57, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 66, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 30], - [0, 11, 0, 12, 50, 37, 36, 45, 47, 6, 0, 0, 0, 49, 18, 53], - [15, 0, 60, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [22, 52, 43, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [25, 39, 42, 41, 59, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [58, 65, 29, 17, 48, 63, 31, 20, 55, 61, 64, 32, 28, 21, 16, 4], + [0, 0, 66, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 30], + [0, 10, 0, 11, 50, 37, 36, 45, 47, 5, 0, 0, 0, 49, 17, 53], + [14, 0, 60, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [21, 52, 43, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [24, 39, 42, 41, 59, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [58, 65, 29, 16, 48, 63, 31, 19, 55, 61, 64, 32, 27, 20, 15, 3], ]; static BITSET: [u64; 67] = [ - 0, 8, 116, 1023, 1024, 8383, 21882, 65535, 1048575, 8388607, 89478485, 134217726, - 2139095039, 4294967295, 17179869183, 1099511627775, 2199023190016, 4398046445568, - 17575006099264, 23456248059221, 70368743129088, 140737484161024, 140737488355327, - 280378317225728, 281470681743392, 281474976710655, 1169903278445909, 2251799813685247, - 9007198986305536, 17977448100528131, 18014398509481983, 288230371856744511, + 0, 8, 1023, 1024, 8383, 21882, 65535, 1048575, 8388607, 89478485, 134217726, 2139095039, + 4294967295, 17179869183, 1099511627775, 2199023190016, 4398046445568, 17575006099264, + 23456248059221, 70368743129088, 140737484161024, 140737488355327, 280378317225728, + 281470681743392, 281474976710655, 1169903278445909, 2251799813685247, 9007198986305536, + 9007199254741748, 17977448100528131, 18014398509481983, 288230371856744511, 576460735123554305, 576460743713488896, 1080863910568919040, 1080897995681042176, 1274187559846268630, 3122495741643543722, 6148633210533183488, 6148914689804861440, 6148914690880001365, 6148914691236506283, 6148914691236516865, 6148914691236517205, @@ -1202,20 +1206,21 @@ pub mod conversions { ('\u{a7ba}', ['\u{a7bb}', '\u{0}', '\u{0}']), ('\u{a7bc}', ['\u{a7bd}', '\u{0}', '\u{0}']), ('\u{a7be}', ['\u{a7bf}', '\u{0}', '\u{0}']), ('\u{a7c2}', ['\u{a7c3}', '\u{0}', '\u{0}']), ('\u{a7c4}', ['\u{a794}', '\u{0}', '\u{0}']), ('\u{a7c5}', ['\u{282}', '\u{0}', '\u{0}']), - ('\u{a7c6}', ['\u{1d8e}', '\u{0}', '\u{0}']), ('\u{ff21}', ['\u{ff41}', '\u{0}', '\u{0}']), - ('\u{ff22}', ['\u{ff42}', '\u{0}', '\u{0}']), ('\u{ff23}', ['\u{ff43}', '\u{0}', '\u{0}']), - ('\u{ff24}', ['\u{ff44}', '\u{0}', '\u{0}']), ('\u{ff25}', ['\u{ff45}', '\u{0}', '\u{0}']), - ('\u{ff26}', ['\u{ff46}', '\u{0}', '\u{0}']), ('\u{ff27}', ['\u{ff47}', '\u{0}', '\u{0}']), - ('\u{ff28}', ['\u{ff48}', '\u{0}', '\u{0}']), ('\u{ff29}', ['\u{ff49}', '\u{0}', '\u{0}']), - ('\u{ff2a}', ['\u{ff4a}', '\u{0}', '\u{0}']), ('\u{ff2b}', ['\u{ff4b}', '\u{0}', '\u{0}']), - ('\u{ff2c}', ['\u{ff4c}', '\u{0}', '\u{0}']), ('\u{ff2d}', ['\u{ff4d}', '\u{0}', '\u{0}']), - ('\u{ff2e}', ['\u{ff4e}', '\u{0}', '\u{0}']), ('\u{ff2f}', ['\u{ff4f}', '\u{0}', '\u{0}']), - ('\u{ff30}', ['\u{ff50}', '\u{0}', '\u{0}']), ('\u{ff31}', ['\u{ff51}', '\u{0}', '\u{0}']), - ('\u{ff32}', ['\u{ff52}', '\u{0}', '\u{0}']), ('\u{ff33}', ['\u{ff53}', '\u{0}', '\u{0}']), - ('\u{ff34}', ['\u{ff54}', '\u{0}', '\u{0}']), ('\u{ff35}', ['\u{ff55}', '\u{0}', '\u{0}']), - ('\u{ff36}', ['\u{ff56}', '\u{0}', '\u{0}']), ('\u{ff37}', ['\u{ff57}', '\u{0}', '\u{0}']), - ('\u{ff38}', ['\u{ff58}', '\u{0}', '\u{0}']), ('\u{ff39}', ['\u{ff59}', '\u{0}', '\u{0}']), - ('\u{ff3a}', ['\u{ff5a}', '\u{0}', '\u{0}']), + ('\u{a7c6}', ['\u{1d8e}', '\u{0}', '\u{0}']), ('\u{a7c7}', ['\u{a7c8}', '\u{0}', '\u{0}']), + ('\u{a7c9}', ['\u{a7ca}', '\u{0}', '\u{0}']), ('\u{a7f5}', ['\u{a7f6}', '\u{0}', '\u{0}']), + ('\u{ff21}', ['\u{ff41}', '\u{0}', '\u{0}']), ('\u{ff22}', ['\u{ff42}', '\u{0}', '\u{0}']), + ('\u{ff23}', ['\u{ff43}', '\u{0}', '\u{0}']), ('\u{ff24}', ['\u{ff44}', '\u{0}', '\u{0}']), + ('\u{ff25}', ['\u{ff45}', '\u{0}', '\u{0}']), ('\u{ff26}', ['\u{ff46}', '\u{0}', '\u{0}']), + ('\u{ff27}', ['\u{ff47}', '\u{0}', '\u{0}']), ('\u{ff28}', ['\u{ff48}', '\u{0}', '\u{0}']), + ('\u{ff29}', ['\u{ff49}', '\u{0}', '\u{0}']), ('\u{ff2a}', ['\u{ff4a}', '\u{0}', '\u{0}']), + ('\u{ff2b}', ['\u{ff4b}', '\u{0}', '\u{0}']), ('\u{ff2c}', ['\u{ff4c}', '\u{0}', '\u{0}']), + ('\u{ff2d}', ['\u{ff4d}', '\u{0}', '\u{0}']), ('\u{ff2e}', ['\u{ff4e}', '\u{0}', '\u{0}']), + ('\u{ff2f}', ['\u{ff4f}', '\u{0}', '\u{0}']), ('\u{ff30}', ['\u{ff50}', '\u{0}', '\u{0}']), + ('\u{ff31}', ['\u{ff51}', '\u{0}', '\u{0}']), ('\u{ff32}', ['\u{ff52}', '\u{0}', '\u{0}']), + ('\u{ff33}', ['\u{ff53}', '\u{0}', '\u{0}']), ('\u{ff34}', ['\u{ff54}', '\u{0}', '\u{0}']), + ('\u{ff35}', ['\u{ff55}', '\u{0}', '\u{0}']), ('\u{ff36}', ['\u{ff56}', '\u{0}', '\u{0}']), + ('\u{ff37}', ['\u{ff57}', '\u{0}', '\u{0}']), ('\u{ff38}', ['\u{ff58}', '\u{0}', '\u{0}']), + ('\u{ff39}', ['\u{ff59}', '\u{0}', '\u{0}']), ('\u{ff3a}', ['\u{ff5a}', '\u{0}', '\u{0}']), ('\u{10400}', ['\u{10428}', '\u{0}', '\u{0}']), ('\u{10401}', ['\u{10429}', '\u{0}', '\u{0}']), ('\u{10402}', ['\u{1042a}', '\u{0}', '\u{0}']), @@ -2052,51 +2057,52 @@ pub mod conversions { ('\u{a7b7}', ['\u{a7b6}', '\u{0}', '\u{0}']), ('\u{a7b9}', ['\u{a7b8}', '\u{0}', '\u{0}']), ('\u{a7bb}', ['\u{a7ba}', '\u{0}', '\u{0}']), ('\u{a7bd}', ['\u{a7bc}', '\u{0}', '\u{0}']), ('\u{a7bf}', ['\u{a7be}', '\u{0}', '\u{0}']), ('\u{a7c3}', ['\u{a7c2}', '\u{0}', '\u{0}']), - ('\u{ab53}', ['\u{a7b3}', '\u{0}', '\u{0}']), ('\u{ab70}', ['\u{13a0}', '\u{0}', '\u{0}']), - ('\u{ab71}', ['\u{13a1}', '\u{0}', '\u{0}']), ('\u{ab72}', ['\u{13a2}', '\u{0}', '\u{0}']), - ('\u{ab73}', ['\u{13a3}', '\u{0}', '\u{0}']), ('\u{ab74}', ['\u{13a4}', '\u{0}', '\u{0}']), - ('\u{ab75}', ['\u{13a5}', '\u{0}', '\u{0}']), ('\u{ab76}', ['\u{13a6}', '\u{0}', '\u{0}']), - ('\u{ab77}', ['\u{13a7}', '\u{0}', '\u{0}']), ('\u{ab78}', ['\u{13a8}', '\u{0}', '\u{0}']), - ('\u{ab79}', ['\u{13a9}', '\u{0}', '\u{0}']), ('\u{ab7a}', ['\u{13aa}', '\u{0}', '\u{0}']), - ('\u{ab7b}', ['\u{13ab}', '\u{0}', '\u{0}']), ('\u{ab7c}', ['\u{13ac}', '\u{0}', '\u{0}']), - ('\u{ab7d}', ['\u{13ad}', '\u{0}', '\u{0}']), ('\u{ab7e}', ['\u{13ae}', '\u{0}', '\u{0}']), - ('\u{ab7f}', ['\u{13af}', '\u{0}', '\u{0}']), ('\u{ab80}', ['\u{13b0}', '\u{0}', '\u{0}']), - ('\u{ab81}', ['\u{13b1}', '\u{0}', '\u{0}']), ('\u{ab82}', ['\u{13b2}', '\u{0}', '\u{0}']), - ('\u{ab83}', ['\u{13b3}', '\u{0}', '\u{0}']), ('\u{ab84}', ['\u{13b4}', '\u{0}', '\u{0}']), - ('\u{ab85}', ['\u{13b5}', '\u{0}', '\u{0}']), ('\u{ab86}', ['\u{13b6}', '\u{0}', '\u{0}']), - ('\u{ab87}', ['\u{13b7}', '\u{0}', '\u{0}']), ('\u{ab88}', ['\u{13b8}', '\u{0}', '\u{0}']), - ('\u{ab89}', ['\u{13b9}', '\u{0}', '\u{0}']), ('\u{ab8a}', ['\u{13ba}', '\u{0}', '\u{0}']), - ('\u{ab8b}', ['\u{13bb}', '\u{0}', '\u{0}']), ('\u{ab8c}', ['\u{13bc}', '\u{0}', '\u{0}']), - ('\u{ab8d}', ['\u{13bd}', '\u{0}', '\u{0}']), ('\u{ab8e}', ['\u{13be}', '\u{0}', '\u{0}']), - ('\u{ab8f}', ['\u{13bf}', '\u{0}', '\u{0}']), ('\u{ab90}', ['\u{13c0}', '\u{0}', '\u{0}']), - ('\u{ab91}', ['\u{13c1}', '\u{0}', '\u{0}']), ('\u{ab92}', ['\u{13c2}', '\u{0}', '\u{0}']), - ('\u{ab93}', ['\u{13c3}', '\u{0}', '\u{0}']), ('\u{ab94}', ['\u{13c4}', '\u{0}', '\u{0}']), - ('\u{ab95}', ['\u{13c5}', '\u{0}', '\u{0}']), ('\u{ab96}', ['\u{13c6}', '\u{0}', '\u{0}']), - ('\u{ab97}', ['\u{13c7}', '\u{0}', '\u{0}']), ('\u{ab98}', ['\u{13c8}', '\u{0}', '\u{0}']), - ('\u{ab99}', ['\u{13c9}', '\u{0}', '\u{0}']), ('\u{ab9a}', ['\u{13ca}', '\u{0}', '\u{0}']), - ('\u{ab9b}', ['\u{13cb}', '\u{0}', '\u{0}']), ('\u{ab9c}', ['\u{13cc}', '\u{0}', '\u{0}']), - ('\u{ab9d}', ['\u{13cd}', '\u{0}', '\u{0}']), ('\u{ab9e}', ['\u{13ce}', '\u{0}', '\u{0}']), - ('\u{ab9f}', ['\u{13cf}', '\u{0}', '\u{0}']), ('\u{aba0}', ['\u{13d0}', '\u{0}', '\u{0}']), - ('\u{aba1}', ['\u{13d1}', '\u{0}', '\u{0}']), ('\u{aba2}', ['\u{13d2}', '\u{0}', '\u{0}']), - ('\u{aba3}', ['\u{13d3}', '\u{0}', '\u{0}']), ('\u{aba4}', ['\u{13d4}', '\u{0}', '\u{0}']), - ('\u{aba5}', ['\u{13d5}', '\u{0}', '\u{0}']), ('\u{aba6}', ['\u{13d6}', '\u{0}', '\u{0}']), - ('\u{aba7}', ['\u{13d7}', '\u{0}', '\u{0}']), ('\u{aba8}', ['\u{13d8}', '\u{0}', '\u{0}']), - ('\u{aba9}', ['\u{13d9}', '\u{0}', '\u{0}']), ('\u{abaa}', ['\u{13da}', '\u{0}', '\u{0}']), - ('\u{abab}', ['\u{13db}', '\u{0}', '\u{0}']), ('\u{abac}', ['\u{13dc}', '\u{0}', '\u{0}']), - ('\u{abad}', ['\u{13dd}', '\u{0}', '\u{0}']), ('\u{abae}', ['\u{13de}', '\u{0}', '\u{0}']), - ('\u{abaf}', ['\u{13df}', '\u{0}', '\u{0}']), ('\u{abb0}', ['\u{13e0}', '\u{0}', '\u{0}']), - ('\u{abb1}', ['\u{13e1}', '\u{0}', '\u{0}']), ('\u{abb2}', ['\u{13e2}', '\u{0}', '\u{0}']), - ('\u{abb3}', ['\u{13e3}', '\u{0}', '\u{0}']), ('\u{abb4}', ['\u{13e4}', '\u{0}', '\u{0}']), - ('\u{abb5}', ['\u{13e5}', '\u{0}', '\u{0}']), ('\u{abb6}', ['\u{13e6}', '\u{0}', '\u{0}']), - ('\u{abb7}', ['\u{13e7}', '\u{0}', '\u{0}']), ('\u{abb8}', ['\u{13e8}', '\u{0}', '\u{0}']), - ('\u{abb9}', ['\u{13e9}', '\u{0}', '\u{0}']), ('\u{abba}', ['\u{13ea}', '\u{0}', '\u{0}']), - ('\u{abbb}', ['\u{13eb}', '\u{0}', '\u{0}']), ('\u{abbc}', ['\u{13ec}', '\u{0}', '\u{0}']), - ('\u{abbd}', ['\u{13ed}', '\u{0}', '\u{0}']), ('\u{abbe}', ['\u{13ee}', '\u{0}', '\u{0}']), - ('\u{abbf}', ['\u{13ef}', '\u{0}', '\u{0}']), ('\u{fb00}', ['F', 'F', '\u{0}']), - ('\u{fb01}', ['F', 'I', '\u{0}']), ('\u{fb02}', ['F', 'L', '\u{0}']), - ('\u{fb03}', ['F', 'F', 'I']), ('\u{fb04}', ['F', 'F', 'L']), - ('\u{fb05}', ['S', 'T', '\u{0}']), ('\u{fb06}', ['S', 'T', '\u{0}']), - ('\u{fb13}', ['\u{544}', '\u{546}', '\u{0}']), + ('\u{a7c8}', ['\u{a7c7}', '\u{0}', '\u{0}']), ('\u{a7ca}', ['\u{a7c9}', '\u{0}', '\u{0}']), + ('\u{a7f6}', ['\u{a7f5}', '\u{0}', '\u{0}']), ('\u{ab53}', ['\u{a7b3}', '\u{0}', '\u{0}']), + ('\u{ab70}', ['\u{13a0}', '\u{0}', '\u{0}']), ('\u{ab71}', ['\u{13a1}', '\u{0}', '\u{0}']), + ('\u{ab72}', ['\u{13a2}', '\u{0}', '\u{0}']), ('\u{ab73}', ['\u{13a3}', '\u{0}', '\u{0}']), + ('\u{ab74}', ['\u{13a4}', '\u{0}', '\u{0}']), ('\u{ab75}', ['\u{13a5}', '\u{0}', '\u{0}']), + ('\u{ab76}', ['\u{13a6}', '\u{0}', '\u{0}']), ('\u{ab77}', ['\u{13a7}', '\u{0}', '\u{0}']), + ('\u{ab78}', ['\u{13a8}', '\u{0}', '\u{0}']), ('\u{ab79}', ['\u{13a9}', '\u{0}', '\u{0}']), + ('\u{ab7a}', ['\u{13aa}', '\u{0}', '\u{0}']), ('\u{ab7b}', ['\u{13ab}', '\u{0}', '\u{0}']), + ('\u{ab7c}', ['\u{13ac}', '\u{0}', '\u{0}']), ('\u{ab7d}', ['\u{13ad}', '\u{0}', '\u{0}']), + ('\u{ab7e}', ['\u{13ae}', '\u{0}', '\u{0}']), ('\u{ab7f}', ['\u{13af}', '\u{0}', '\u{0}']), + ('\u{ab80}', ['\u{13b0}', '\u{0}', '\u{0}']), ('\u{ab81}', ['\u{13b1}', '\u{0}', '\u{0}']), + ('\u{ab82}', ['\u{13b2}', '\u{0}', '\u{0}']), ('\u{ab83}', ['\u{13b3}', '\u{0}', '\u{0}']), + ('\u{ab84}', ['\u{13b4}', '\u{0}', '\u{0}']), ('\u{ab85}', ['\u{13b5}', '\u{0}', '\u{0}']), + ('\u{ab86}', ['\u{13b6}', '\u{0}', '\u{0}']), ('\u{ab87}', ['\u{13b7}', '\u{0}', '\u{0}']), + ('\u{ab88}', ['\u{13b8}', '\u{0}', '\u{0}']), ('\u{ab89}', ['\u{13b9}', '\u{0}', '\u{0}']), + ('\u{ab8a}', ['\u{13ba}', '\u{0}', '\u{0}']), ('\u{ab8b}', ['\u{13bb}', '\u{0}', '\u{0}']), + ('\u{ab8c}', ['\u{13bc}', '\u{0}', '\u{0}']), ('\u{ab8d}', ['\u{13bd}', '\u{0}', '\u{0}']), + ('\u{ab8e}', ['\u{13be}', '\u{0}', '\u{0}']), ('\u{ab8f}', ['\u{13bf}', '\u{0}', '\u{0}']), + ('\u{ab90}', ['\u{13c0}', '\u{0}', '\u{0}']), ('\u{ab91}', ['\u{13c1}', '\u{0}', '\u{0}']), + ('\u{ab92}', ['\u{13c2}', '\u{0}', '\u{0}']), ('\u{ab93}', ['\u{13c3}', '\u{0}', '\u{0}']), + ('\u{ab94}', ['\u{13c4}', '\u{0}', '\u{0}']), ('\u{ab95}', ['\u{13c5}', '\u{0}', '\u{0}']), + ('\u{ab96}', ['\u{13c6}', '\u{0}', '\u{0}']), ('\u{ab97}', ['\u{13c7}', '\u{0}', '\u{0}']), + ('\u{ab98}', ['\u{13c8}', '\u{0}', '\u{0}']), ('\u{ab99}', ['\u{13c9}', '\u{0}', '\u{0}']), + ('\u{ab9a}', ['\u{13ca}', '\u{0}', '\u{0}']), ('\u{ab9b}', ['\u{13cb}', '\u{0}', '\u{0}']), + ('\u{ab9c}', ['\u{13cc}', '\u{0}', '\u{0}']), ('\u{ab9d}', ['\u{13cd}', '\u{0}', '\u{0}']), + ('\u{ab9e}', ['\u{13ce}', '\u{0}', '\u{0}']), ('\u{ab9f}', ['\u{13cf}', '\u{0}', '\u{0}']), + ('\u{aba0}', ['\u{13d0}', '\u{0}', '\u{0}']), ('\u{aba1}', ['\u{13d1}', '\u{0}', '\u{0}']), + ('\u{aba2}', ['\u{13d2}', '\u{0}', '\u{0}']), ('\u{aba3}', ['\u{13d3}', '\u{0}', '\u{0}']), + ('\u{aba4}', ['\u{13d4}', '\u{0}', '\u{0}']), ('\u{aba5}', ['\u{13d5}', '\u{0}', '\u{0}']), + ('\u{aba6}', ['\u{13d6}', '\u{0}', '\u{0}']), ('\u{aba7}', ['\u{13d7}', '\u{0}', '\u{0}']), + ('\u{aba8}', ['\u{13d8}', '\u{0}', '\u{0}']), ('\u{aba9}', ['\u{13d9}', '\u{0}', '\u{0}']), + ('\u{abaa}', ['\u{13da}', '\u{0}', '\u{0}']), ('\u{abab}', ['\u{13db}', '\u{0}', '\u{0}']), + ('\u{abac}', ['\u{13dc}', '\u{0}', '\u{0}']), ('\u{abad}', ['\u{13dd}', '\u{0}', '\u{0}']), + ('\u{abae}', ['\u{13de}', '\u{0}', '\u{0}']), ('\u{abaf}', ['\u{13df}', '\u{0}', '\u{0}']), + ('\u{abb0}', ['\u{13e0}', '\u{0}', '\u{0}']), ('\u{abb1}', ['\u{13e1}', '\u{0}', '\u{0}']), + ('\u{abb2}', ['\u{13e2}', '\u{0}', '\u{0}']), ('\u{abb3}', ['\u{13e3}', '\u{0}', '\u{0}']), + ('\u{abb4}', ['\u{13e4}', '\u{0}', '\u{0}']), ('\u{abb5}', ['\u{13e5}', '\u{0}', '\u{0}']), + ('\u{abb6}', ['\u{13e6}', '\u{0}', '\u{0}']), ('\u{abb7}', ['\u{13e7}', '\u{0}', '\u{0}']), + ('\u{abb8}', ['\u{13e8}', '\u{0}', '\u{0}']), ('\u{abb9}', ['\u{13e9}', '\u{0}', '\u{0}']), + ('\u{abba}', ['\u{13ea}', '\u{0}', '\u{0}']), ('\u{abbb}', ['\u{13eb}', '\u{0}', '\u{0}']), + ('\u{abbc}', ['\u{13ec}', '\u{0}', '\u{0}']), ('\u{abbd}', ['\u{13ed}', '\u{0}', '\u{0}']), + ('\u{abbe}', ['\u{13ee}', '\u{0}', '\u{0}']), ('\u{abbf}', ['\u{13ef}', '\u{0}', '\u{0}']), + ('\u{fb00}', ['F', 'F', '\u{0}']), ('\u{fb01}', ['F', 'I', '\u{0}']), + ('\u{fb02}', ['F', 'L', '\u{0}']), ('\u{fb03}', ['F', 'F', 'I']), + ('\u{fb04}', ['F', 'F', 'L']), ('\u{fb05}', ['S', 'T', '\u{0}']), + ('\u{fb06}', ['S', 'T', '\u{0}']), ('\u{fb13}', ['\u{544}', '\u{546}', '\u{0}']), ('\u{fb14}', ['\u{544}', '\u{535}', '\u{0}']), ('\u{fb15}', ['\u{544}', '\u{53b}', '\u{0}']), ('\u{fb16}', ['\u{54e}', '\u{546}', '\u{0}']), diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index db7c250e21157..f44a875c9d0d5 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -18,17 +18,11 @@ #![feature(staged_api)] #![feature(rustc_attrs)] -// Rust's "try" function, but if we're aborting on panics we just call the -// function as there's nothing else we need to do here. +use core::any::Any; + #[rustc_std_internal_symbol] -pub unsafe extern "C" fn __rust_maybe_catch_panic( - f: fn(*mut u8), - data: *mut u8, - _data_ptr: *mut usize, - _vtable_ptr: *mut usize, -) -> u32 { - f(data); - 0 +pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Send + 'static) { + unreachable!() } // "Leak" the payload and shim to the relevant abort on the platform in @@ -92,7 +86,7 @@ pub unsafe extern "C" fn __rust_start_panic(_payload: usize) -> u32 { // binaries, but it should never be called as we don't link in an unwinding // runtime at all. pub mod personalities { - #[no_mangle] + #[rustc_std_internal_symbol] #[cfg(not(any( all(target_arch = "wasm32", not(target_os = "emscripten"),), all(target_os = "windows", target_env = "gnu", target_arch = "x86_64",), @@ -101,7 +95,7 @@ pub mod personalities { // On x86_64-pc-windows-gnu we use our own personality function that needs // to return `ExceptionContinueSearch` as we're passing on all our frames. - #[no_mangle] + #[rustc_std_internal_symbol] #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86_64"))] pub extern "C" fn rust_eh_personality( _record: usize, @@ -117,16 +111,16 @@ pub mod personalities { // // Note that we don't execute landing pads, so this is never called, so it's // body is empty. - #[no_mangle] - #[cfg(all(target_os = "windows", target_env = "gnu"))] + #[rustc_std_internal_symbol] + #[cfg(all(bootstrap, target_os = "windows", target_env = "gnu"))] pub extern "C" fn rust_eh_unwind_resume() {} // These two are called by our startup objects on i686-pc-windows-gnu, but // they don't need to do anything so the bodies are nops. - #[no_mangle] + #[rustc_std_internal_symbol] #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86"))] pub extern "C" fn rust_eh_register_frames() {} - #[no_mangle] + #[rustc_std_internal_symbol] #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86"))] pub extern "C" fn rust_eh_unregister_frames() {} } diff --git a/src/libpanic_unwind/dummy.rs b/src/libpanic_unwind/dummy.rs index 8675632638712..4667ede2baad5 100644 --- a/src/libpanic_unwind/dummy.rs +++ b/src/libpanic_unwind/dummy.rs @@ -6,10 +6,6 @@ use alloc::boxed::Box; use core::any::Any; use core::intrinsics; -pub fn payload() -> *mut u8 { - core::ptr::null_mut() -} - pub unsafe fn cleanup(_ptr: *mut u8) -> Box { intrinsics::abort() } diff --git a/src/libpanic_unwind/emcc.rs b/src/libpanic_unwind/emcc.rs index 9161d49959cf5..a0bdb1481c6b2 100644 --- a/src/libpanic_unwind/emcc.rs +++ b/src/libpanic_unwind/emcc.rs @@ -6,8 +6,6 @@ //! Emscripten's runtime always implements those APIs and does not //! implement libunwind. -#![allow(private_no_mangle_fns)] - use alloc::boxed::Box; use core::any::Any; use core::mem; @@ -48,15 +46,11 @@ static EXCEPTION_TYPE_INFO: TypeInfo = TypeInfo { name: b"rust_panic\0".as_ptr(), }; -pub fn payload() -> *mut u8 { - ptr::null_mut() -} - struct Exception { // This needs to be an Option because the object's lifetime follows C++ // semantics: when catch_unwind moves the Box out of the exception it must // still leave the exception object in a valid state because its destructor - // is still going to be called by __cxa_end_catch.. + // is still going to be called by __cxa_end_catch. data: Option>, } @@ -98,7 +92,6 @@ extern "C" fn exception_cleanup(ptr: *mut libc::c_void) -> DestructorRet { } #[lang = "eh_personality"] -#[no_mangle] unsafe extern "C" fn rust_eh_personality( version: c_int, actions: uw::_Unwind_Action, diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs index 591ff9d7fdcaa..1622442a5eb45 100644 --- a/src/libpanic_unwind/gcc.rs +++ b/src/libpanic_unwind/gcc.rs @@ -35,20 +35,9 @@ //! //! Once stack has been unwound down to the handler frame level, unwinding stops //! and the last personality routine transfers control to the catch block. -//! -//! ## `eh_personality` and `eh_unwind_resume` -//! -//! These language items are used by the compiler when generating unwind info. -//! The first one is the personality routine described above. The second one -//! allows compilation target to customize the process of resuming unwind at the -//! end of the landing pads. `eh_unwind_resume` is used only if -//! `custom_unwind_resume` flag in the target options is set. - -#![allow(private_no_mangle_fns)] use alloc::boxed::Box; use core::any::Any; -use core::ptr; use crate::dwarf::eh::{self, EHAction, EHContext}; use libc::{c_int, uintptr_t}; @@ -83,10 +72,6 @@ pub unsafe fn panic(data: Box) -> u32 { } } -pub fn payload() -> *mut u8 { - ptr::null_mut() -} - pub unsafe fn cleanup(ptr: *mut u8) -> Box { let exception = Box::from_raw(ptr as *mut Exception); exception.cause @@ -143,7 +128,6 @@ cfg_if::cfg_if! { // // iOS uses the default routine instead since it uses SjLj unwinding. #[lang = "eh_personality"] - #[no_mangle] unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State, exception_object: *mut uw::_Unwind_Exception, context: *mut uw::_Unwind_Context) @@ -277,7 +261,6 @@ cfg_if::cfg_if! { // On x86_64 MinGW targets, the unwinding mechanism is SEH however the unwind // handler data (aka LSDA) uses GCC-compatible encoding. #[lang = "eh_personality"] - #[no_mangle] #[allow(nonstandard_style)] unsafe extern "C" fn rust_eh_personality(exceptionRecord: *mut uw::EXCEPTION_RECORD, establisherFrame: uw::LPVOID, @@ -293,7 +276,6 @@ cfg_if::cfg_if! { } else { // The personality routine for most of our targets. #[lang = "eh_personality"] - #[no_mangle] unsafe extern "C" fn rust_eh_personality(version: c_int, actions: uw::_Unwind_Action, exception_class: uw::_Unwind_Exception_Class, @@ -329,8 +311,8 @@ unsafe fn find_eh_action( eh::find_eh_action(lsda, &eh_context, foreign_exception) } -// See docs in the `unwind` module. #[cfg(all( + bootstrap, target_os = "windows", any(target_arch = "x86", target_arch = "x86_64"), target_env = "gnu" @@ -364,12 +346,12 @@ pub mod eh_frame_registry { fn __deregister_frame_info(eh_frame_begin: *const u8, object: *mut u8); } - #[no_mangle] + #[rustc_std_internal_symbol] pub unsafe extern "C" fn rust_eh_register_frames(eh_frame_begin: *const u8, object: *mut u8) { __register_frame_info(eh_frame_begin, object); } - #[no_mangle] + #[rustc_std_internal_symbol] pub unsafe extern "C" fn rust_eh_unregister_frames(eh_frame_begin: *const u8, object: *mut u8) { __deregister_frame_info(eh_frame_begin, object); } diff --git a/src/libpanic_unwind/hermit.rs b/src/libpanic_unwind/hermit.rs index 2f53df2861d44..69b9edb77c564 100644 --- a/src/libpanic_unwind/hermit.rs +++ b/src/libpanic_unwind/hermit.rs @@ -4,11 +4,6 @@ use alloc::boxed::Box; use core::any::Any; -use core::ptr; - -pub fn payload() -> *mut u8 { - ptr::null_mut() -} pub unsafe fn cleanup(_ptr: *mut u8) -> Box { extern "C" { diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index 6383ae39fb6db..0a2a0e9e045c6 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -22,42 +22,56 @@ #![feature(libc)] #![feature(nll)] #![feature(panic_unwind)] -#![feature(raw)] #![feature(staged_api)] #![feature(std_internals)] #![feature(unwind_attributes)] #![feature(abi_thiscall)] +#![feature(rustc_attrs)] +#![feature(raw)] #![panic_runtime] #![feature(panic_runtime)] +// `real_imp` is unused with Miri, so silence warnings. +#![cfg_attr(miri, allow(dead_code))] use alloc::boxed::Box; -use core::intrinsics; -use core::mem; +use core::any::Any; use core::panic::BoxMeUp; -use core::raw; cfg_if::cfg_if! { if #[cfg(target_os = "emscripten")] { #[path = "emcc.rs"] - mod imp; + mod real_imp; } else if #[cfg(target_arch = "wasm32")] { #[path = "dummy.rs"] - mod imp; + mod real_imp; } else if #[cfg(target_os = "hermit")] { #[path = "hermit.rs"] - mod imp; + mod real_imp; } else if #[cfg(all(target_env = "msvc", target_arch = "aarch64"))] { #[path = "dummy.rs"] - mod imp; + mod real_imp; } else if #[cfg(target_env = "msvc")] { #[path = "seh.rs"] - mod imp; + mod real_imp; } else { // Rust runtime's startup objects depend on these symbols, so make them public. #[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))] - pub use imp::eh_frame_registry::*; + pub use real_imp::eh_frame_registry::*; #[path = "gcc.rs"] + mod real_imp; + } +} + +cfg_if::cfg_if! { + if #[cfg(miri)] { + // Use the Miri runtime. + // We still need to also load the normal runtime above, as rustc expects certain lang + // items from there to be defined. + #[path = "miri.rs"] mod imp; + } else { + // Use the real runtime. + use real_imp as imp; } } @@ -69,44 +83,18 @@ extern "C" { mod dwarf; -// Entry point for catching an exception, implemented using the `try` intrinsic -// in the compiler. -// -// The interaction between the `payload` function and the compiler is pretty -// hairy and tightly coupled, for more information see the compiler's -// implementation of this. -#[no_mangle] -pub unsafe extern "C" fn __rust_maybe_catch_panic( - f: fn(*mut u8), - data: *mut u8, - data_ptr: *mut usize, - vtable_ptr: *mut usize, -) -> u32 { - let mut payload = imp::payload(); - if intrinsics::r#try(f, data, &mut payload as *mut _ as *mut _) == 0 { - 0 - } else { - let obj = mem::transmute::<_, raw::TraitObject>(imp::cleanup(payload)); - *data_ptr = obj.data as usize; - *vtable_ptr = obj.vtable as usize; - 1 - } +#[rustc_std_internal_symbol] +pub unsafe extern "C" fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static) { + Box::into_raw(imp::cleanup(payload)) } // Entry point for raising an exception, just delegates to the platform-specific // implementation. -#[no_mangle] +#[rustc_std_internal_symbol] #[unwind(allowed)] pub unsafe extern "C" fn __rust_start_panic(payload: usize) -> u32 { let payload = payload as *mut &mut dyn BoxMeUp; let payload = (*payload).take_box(); - // Miri panic support: cfg'd out of normal builds just to be sure. - // When going through normal codegen, `miri_start_panic` is a NOP, so the - // Miri-enabled sysroot still supports normal unwinding. But when executed in - // Miri, this line initiates unwinding. - #[cfg(miri)] - core::intrinsics::miri_start_panic(payload); - imp::panic(Box::from_raw(payload)) } diff --git a/src/libpanic_unwind/miri.rs b/src/libpanic_unwind/miri.rs new file mode 100644 index 0000000000000..9d92b2b2f3207 --- /dev/null +++ b/src/libpanic_unwind/miri.rs @@ -0,0 +1,20 @@ +//! Unwinding panics for Miri. +use alloc::boxed::Box; +use core::any::Any; + +// The type of the payload that the Miri engine propagates through unwinding for us. +// Must be pointer-sized. +type Payload = Box>; + +pub unsafe fn panic(payload: Box) -> u32 { + // The payload we pass to `miri_start_panic` will be exactly the argument we get + // in `cleanup` below. So we just box it up once, to get something pointer-sized. + let payload_box: Payload = Box::new(payload); + core::intrinsics::miri_start_panic(Box::into_raw(payload_box) as *mut u8) +} + +pub unsafe fn cleanup(payload_box: *mut u8) -> Box { + // Recover the underlying `Box`. + let payload_box: Payload = Box::from_raw(payload_box as *mut _); + *payload_box +} diff --git a/src/libpanic_unwind/seh.rs b/src/libpanic_unwind/seh.rs index 6f507e85e742c..10b765a5b411b 100644 --- a/src/libpanic_unwind/seh.rs +++ b/src/libpanic_unwind/seh.rs @@ -45,14 +45,20 @@ //! [llvm]: http://llvm.org/docs/ExceptionHandling.html#background-on-windows-exceptions #![allow(nonstandard_style)] -#![allow(private_no_mangle_fns)] use alloc::boxed::Box; use core::any::Any; -use core::mem; -use core::raw; +use core::mem::{self, ManuallyDrop}; use libc::{c_int, c_uint, c_void}; +struct Exception { + // This needs to be an Option because we catch the exception by reference + // and its destructor is executed by the C++ runtime. When we take the Box + // out of the exception, we need to leave the exception in a valid state + // for its destructor to run without double-dropping the Box. + data: Option>, +} + // First up, a whole bunch of type definitions. There's a few platform-specific // oddities here, and a lot that's just blatantly copied from LLVM. The purpose // of all this is to implement the `panic` function below through a call to @@ -167,6 +173,9 @@ pub struct _TypeDescriptor { // Note that we intentionally ignore name mangling rules here: we don't want C++ // to be able to catch Rust panics by simply declaring a `struct rust_panic`. +// +// When modifying, make sure that the type name string exactly matches +// the one used in src/librustc_codegen_llvm/intrinsic.rs. const TYPE_NAME: [u8; 11] = *b"rust_panic\0"; static mut THROW_INFO: _ThrowInfo = _ThrowInfo { @@ -183,7 +192,7 @@ static mut CATCHABLE_TYPE: _CatchableType = _CatchableType { properties: 0, pType: ptr!(0), thisDisplacement: _PMD { mdisp: 0, pdisp: -1, vdisp: 0 }, - sizeOrOffset: mem::size_of::<[u64; 2]>() as c_int, + sizeOrOffset: mem::size_of::() as c_int, copyFunction: ptr!(0), }; @@ -199,12 +208,12 @@ extern "C" { static TYPE_INFO_VTABLE: *const u8; } -// We use #[lang = "eh_catch_typeinfo"] here as this is the type descriptor which -// we'll use in LLVM's `catchpad` instruction which ends up also being passed as -// an argument to the C++ personality function. +// This type descriptor is only used when throwing an exception. The catch part +// is handled by the try intrinsic, which generates its own TypeDescriptor. // -// Again, I'm not entirely sure what this is describing, it just seems to work. -#[cfg_attr(not(test), lang = "eh_catch_typeinfo")] +// This is fine since the MSVC runtime uses string comparison on the type name +// to match TypeDescriptors rather than pointer equality. +#[cfg_attr(bootstrap, lang = "eh_catch_typeinfo")] static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor { pVFTable: unsafe { &TYPE_INFO_VTABLE } as *const _ as *const _, spare: core::ptr::null_mut(), @@ -226,16 +235,16 @@ static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor { // because Box isn't clonable. macro_rules! define_cleanup { ($abi:tt) => { - unsafe extern $abi fn exception_cleanup(e: *mut [u64; 2]) { - if (*e)[0] != 0 { - cleanup(*e); + unsafe extern $abi fn exception_cleanup(e: *mut Exception) { + if let Exception { data: Some(b) } = e.read() { + drop(b); super::__rust_drop_panic(); } } #[unwind(allowed)] - unsafe extern $abi fn exception_copy(_dest: *mut [u64; 2], - _src: *mut [u64; 2]) - -> *mut [u64; 2] { + unsafe extern $abi fn exception_copy(_dest: *mut Exception, + _src: *mut Exception) + -> *mut Exception { panic!("Rust panics cannot be copied"); } } @@ -255,12 +264,11 @@ pub unsafe fn panic(data: Box) -> u32 { // need to otherwise transfer `data` to the heap. We just pass a stack // pointer to this function. // - // The first argument is the payload being thrown (our two pointers), and - // the second argument is the type information object describing the - // exception (constructed above). - let ptrs = mem::transmute::<_, raw::TraitObject>(data); - let mut ptrs = [ptrs.data as u64, ptrs.vtable as u64]; - let throw_ptr = ptrs.as_mut_ptr() as *mut _; + // The ManuallyDrop is needed here since we don't want Exception to be + // dropped when unwinding. Instead it will be dropped by exception_cleanup + // which is invoked by the C++ runtime. + let mut exception = ManuallyDrop::new(Exception { data: Some(data) }); + let throw_ptr = &mut exception as *mut _ as *mut _; // This... may seems surprising, and justifiably so. On 32-bit MSVC the // pointers between these structure are just that, pointers. On 64-bit MSVC, @@ -308,12 +316,9 @@ pub unsafe fn panic(data: Box) -> u32 { _CxxThrowException(throw_ptr, &mut THROW_INFO as *mut _ as *mut _); } -pub fn payload() -> [u64; 2] { - [0; 2] -} - -pub unsafe fn cleanup(payload: [u64; 2]) -> Box { - mem::transmute(raw::TraitObject { data: payload[0] as *mut _, vtable: payload[1] as *mut _ }) +pub unsafe fn cleanup(payload: *mut u8) -> Box { + let exception = &mut *(payload as *mut Exception); + exception.data.take().unwrap() } // This is required by the compiler to exist (e.g., it's a lang item), but diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 59ce14c97c0e6..a975ce93bb1a3 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -24,9 +24,11 @@ #![feature(decl_macro)] #![feature(extern_types)] #![feature(in_band_lifetimes)] +#![cfg_attr(not(bootstrap), feature(negative_impls))] #![feature(optin_builtin_traits)] #![feature(rustc_attrs)] -#![feature(specialization)] +#![cfg_attr(bootstrap, feature(specialization))] +#![cfg_attr(not(bootstrap), feature(min_specialization))] #![recursion_limit = "256"] #[unstable(feature = "proc_macro_internals", issue = "27812")] diff --git a/src/libprofiler_builtins/build.rs b/src/libprofiler_builtins/build.rs index 8adcff67800fe..c990b28933504 100644 --- a/src/libprofiler_builtins/build.rs +++ b/src/libprofiler_builtins/build.rs @@ -41,7 +41,6 @@ fn main() { cfg.flag("-fno-builtin"); cfg.flag("-fvisibility=hidden"); cfg.flag("-fomit-frame-pointer"); - cfg.flag("-ffreestanding"); cfg.define("VISIBILITY_HIDDEN", None); if !target.contains("windows") { cfg.define("COMPILER_RT_HAS_UNAME", Some("1")); diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 481d691b8e9b2..47b94a2f1a4b4 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -25,6 +25,7 @@ rustc_hir = { path = "../librustc_hir" } rustc_target = { path = "../librustc_target" } rustc_macros = { path = "../librustc_macros" } rustc_data_structures = { path = "../librustc_data_structures" } +rustc_query_system = { path = "../librustc_query_system" } rustc_errors = { path = "../librustc_errors" } rustc_index = { path = "../librustc_index" } rustc_serialize = { path = "../libserialize", package = "serialize" } diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index 0384a9f781578..ae542cec170a3 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -1,11 +1,3 @@ -use arena::{DroplessArena, TypedArena}; -use smallvec::SmallVec; -use std::cell::RefCell; -use std::marker::PhantomData; -use std::mem; -use std::ptr; -use std::slice; - /// This declares a list of types which can be allocated by `Arena`. /// /// The `few` modifier will cause allocation to use the shared arena and recording the destructor. @@ -19,7 +11,7 @@ use std::slice; macro_rules! arena_types { ($macro:path, $args:tt, $tcx:lifetime) => ( $macro!($args, [ - [] layouts: rustc::ty::layout::LayoutDetails, + [] layouts: rustc::ty::layout::Layout, [] generics: rustc::ty::Generics, [] trait_def: rustc::ty::TraitDef, [] adt_def: rustc::ty::AdtDef, @@ -128,225 +120,13 @@ macro_rules! arena_types { // Interned types [] tys: rustc::ty::TyS<$tcx>, - // HIR types - [few] hir_krate: rustc_hir::Crate<$tcx>, - [] arm: rustc_hir::Arm<$tcx>, - [] attribute: rustc_ast::ast::Attribute, - [] block: rustc_hir::Block<$tcx>, - [] bare_fn_ty: rustc_hir::BareFnTy<$tcx>, - [few] global_asm: rustc_hir::GlobalAsm, - [] generic_arg: rustc_hir::GenericArg<$tcx>, - [] generic_args: rustc_hir::GenericArgs<$tcx>, - [] generic_bound: rustc_hir::GenericBound<$tcx>, - [] generic_param: rustc_hir::GenericParam<$tcx>, - [] expr: rustc_hir::Expr<$tcx>, - [] field: rustc_hir::Field<$tcx>, - [] field_pat: rustc_hir::FieldPat<$tcx>, - [] fn_decl: rustc_hir::FnDecl<$tcx>, - [] foreign_item: rustc_hir::ForeignItem<$tcx>, - [] impl_item_ref: rustc_hir::ImplItemRef<$tcx>, - [] inline_asm: rustc_hir::InlineAsm<$tcx>, - [] local: rustc_hir::Local<$tcx>, - [few] macro_def: rustc_hir::MacroDef<$tcx>, - [] param: rustc_hir::Param<$tcx>, - [] pat: rustc_hir::Pat<$tcx>, - [] path: rustc_hir::Path<$tcx>, - [] path_segment: rustc_hir::PathSegment<$tcx>, - [] poly_trait_ref: rustc_hir::PolyTraitRef<$tcx>, - [] qpath: rustc_hir::QPath<$tcx>, - [] stmt: rustc_hir::Stmt<$tcx>, - [] struct_field: rustc_hir::StructField<$tcx>, - [] trait_item_ref: rustc_hir::TraitItemRef, - [] ty: rustc_hir::Ty<$tcx>, - [] type_binding: rustc_hir::TypeBinding<$tcx>, - [] variant: rustc_hir::Variant<$tcx>, - [] where_predicate: rustc_hir::WherePredicate<$tcx>, + // HIR query types + [few] indexed_hir: rustc::hir::map::IndexedHir<$tcx>, + [few] hir_definitions: rustc_hir::definitions::Definitions, + [] hir_owner: rustc::hir::Owner<$tcx>, + [] hir_owner_nodes: rustc::hir::OwnerNodes<$tcx>, ], $tcx); ) } -macro_rules! arena_for_type { - ([][$ty:ty]) => { - TypedArena<$ty> - }; - ([few $(, $attrs:ident)*][$ty:ty]) => { - PhantomData<$ty> - }; - ([$ignore:ident $(, $attrs:ident)*]$args:tt) => { - arena_for_type!([$($attrs),*]$args) - }; -} - -macro_rules! declare_arena { - ([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => { - #[derive(Default)] - pub struct Arena<$tcx> { - pub dropless: DroplessArena, - drop: DropArena, - $($name: arena_for_type!($a[$ty]),)* - } - } -} - -macro_rules! which_arena_for_type { - ([][$arena:expr]) => { - Some($arena) - }; - ([few$(, $attrs:ident)*][$arena:expr]) => { - None - }; - ([$ignore:ident$(, $attrs:ident)*]$args:tt) => { - which_arena_for_type!([$($attrs),*]$args) - }; -} - -macro_rules! impl_arena_allocatable { - ([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => { - $( - impl ArenaAllocatable for $ty {} - unsafe impl<$tcx> ArenaField<$tcx> for $ty { - #[inline] - fn arena<'a>(_arena: &'a Arena<$tcx>) -> Option<&'a TypedArena> { - which_arena_for_type!($a[&_arena.$name]) - } - } - )* - } -} - -arena_types!(declare_arena, [], 'tcx); - -arena_types!(impl_arena_allocatable, [], 'tcx); - -#[marker] -pub trait ArenaAllocatable {} - -impl ArenaAllocatable for T {} - -unsafe trait ArenaField<'tcx>: Sized { - /// Returns a specific arena to allocate from. - /// If `None` is returned, the `DropArena` will be used. - fn arena<'a>(arena: &'a Arena<'tcx>) -> Option<&'a TypedArena>; -} - -unsafe impl<'tcx, T> ArenaField<'tcx> for T { - #[inline] - default fn arena<'a>(_: &'a Arena<'tcx>) -> Option<&'a TypedArena> { - panic!() - } -} - -impl<'tcx> Arena<'tcx> { - #[inline] - pub fn alloc(&self, value: T) -> &mut T { - if !mem::needs_drop::() { - return self.dropless.alloc(value); - } - match >::arena(self) { - Some(arena) => arena.alloc(value), - None => unsafe { self.drop.alloc(value) }, - } - } - - #[inline] - pub fn alloc_slice(&self, value: &[T]) -> &mut [T] { - if value.is_empty() { - return &mut []; - } - self.dropless.alloc_slice(value) - } - - pub fn alloc_from_iter>( - &'a self, - iter: I, - ) -> &'a mut [T] { - if !mem::needs_drop::() { - return self.dropless.alloc_from_iter(iter); - } - match >::arena(self) { - Some(arena) => arena.alloc_from_iter(iter), - None => unsafe { self.drop.alloc_from_iter(iter) }, - } - } -} - -/// Calls the destructor for an object when dropped. -struct DropType { - drop_fn: unsafe fn(*mut u8), - obj: *mut u8, -} - -unsafe fn drop_for_type(to_drop: *mut u8) { - std::ptr::drop_in_place(to_drop as *mut T) -} - -impl Drop for DropType { - fn drop(&mut self) { - unsafe { (self.drop_fn)(self.obj) } - } -} - -/// An arena which can be used to allocate any type. -/// Allocating in this arena is unsafe since the type system -/// doesn't know which types it contains. In order to -/// allocate safely, you must store a PhantomData -/// alongside this arena for each type T you allocate. -#[derive(Default)] -struct DropArena { - /// A list of destructors to run when the arena drops. - /// Ordered so `destructors` gets dropped before the arena - /// since its destructor can reference memory in the arena. - destructors: RefCell>, - arena: DroplessArena, -} - -impl DropArena { - #[inline] - unsafe fn alloc(&self, object: T) -> &mut T { - let mem = - self.arena.alloc_raw(mem::size_of::(), mem::align_of::()) as *mut _ as *mut T; - // Write into uninitialized memory. - ptr::write(mem, object); - let result = &mut *mem; - // Record the destructor after doing the allocation as that may panic - // and would cause `object`'s destuctor to run twice if it was recorded before - self.destructors - .borrow_mut() - .push(DropType { drop_fn: drop_for_type::, obj: result as *mut T as *mut u8 }); - result - } - - #[inline] - unsafe fn alloc_from_iter>(&self, iter: I) -> &mut [T] { - let mut vec: SmallVec<[_; 8]> = iter.into_iter().collect(); - if vec.is_empty() { - return &mut []; - } - let len = vec.len(); - - let start_ptr = self - .arena - .alloc_raw(len.checked_mul(mem::size_of::()).unwrap(), mem::align_of::()) - as *mut _ as *mut T; - - let mut destructors = self.destructors.borrow_mut(); - // Reserve space for the destructors so we can't panic while adding them - destructors.reserve(len); - - // Move the content to the arena by copying it and then forgetting - // the content of the SmallVec - vec.as_ptr().copy_to_nonoverlapping(start_ptr, len); - mem::forget(vec.drain(..)); - - // Record the destructors after doing the allocation as that may panic - // and would cause `object`'s destuctor to run twice if it was recorded before - for i in 0..len { - destructors.push(DropType { - drop_fn: drop_for_type::, - obj: start_ptr.offset(i as isize) as *mut u8, - }); - } - - slice::from_raw_parts_mut(start_ptr, len) - } -} +arena_types!(arena::declare_arena, [], 'tcx); diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 5cbaa5a42f678..f4a4aab844c14 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -35,7 +35,7 @@ //! "infer" some properties for each kind of `DepNode`: //! //! * Whether a `DepNode` of a given kind has any parameters at all. Some -//! `DepNode`s, like `AllLocalTraitImpls`, represent global concepts with only one value. +//! `DepNode`s could represent global concepts with only one value. //! * Whether it is possible, in principle, to reconstruct a query key from a //! given `DepNode`. Many `DepKind`s only require a single `DefId` parameter, //! in which case it is possible to map the node's fingerprint back to the @@ -49,8 +49,6 @@ //! user of the `DepNode` API of having to know how to compute the expected //! fingerprint for a given set of node parameters. -use crate::hir::map::DefPathHash; -use crate::ich::{Fingerprint, StableHashingContext}; use crate::mir; use crate::mir::interpret::{GlobalId, LitToConstInput}; use crate::traits; @@ -59,16 +57,18 @@ use crate::traits::query::{ CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, }; -use crate::ty::subst::SubstsRef; +use crate::ty::subst::{GenericArg, SubstsRef}; use crate::ty::{self, ParamEnvAnd, Ty, TyCtxt}; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX}; +use rustc_data_structures::fingerprint::Fingerprint; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX}; +use rustc_hir::definitions::DefPathHash; use rustc_hir::HirId; use rustc_span::symbol::Symbol; -use std::fmt; use std::hash::Hash; +pub use rustc_query_system::dep_graph::{DepContext, DepNodeParams}; + // erase!() just makes tokens go away. It's used to specify which macro argument // is repeated (i.e., which sub-expression of the macro we are in) but don't need // to actually use any of the arguments. @@ -128,7 +128,7 @@ macro_rules! define_dep_nodes { // tuple args $({ - return <$tuple_arg_ty as DepNodeParams> + return <$tuple_arg_ty as DepNodeParams>> ::CAN_RECONSTRUCT_QUERY_KEY; })* @@ -179,7 +179,7 @@ macro_rules! define_dep_nodes { $( #[inline(always)] #[allow(unreachable_code, non_snake_case)] - pub fn $variant<'tcx>(_tcx: TyCtxt<'tcx>, $(arg: $tuple_arg_ty)*) -> DepNode { + pub fn $variant(_tcx: TyCtxt<'_>, $(arg: $tuple_arg_ty)*) -> DepNode { // tuple args $({ erase!($tuple_arg_ty); @@ -212,20 +212,39 @@ macro_rules! define_dep_nodes { )* } - #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, - RustcEncodable, RustcDecodable)] - pub struct DepNode { - pub kind: DepKind, - pub hash: Fingerprint, + pub type DepNode = rustc_query_system::dep_graph::DepNode; + + pub trait DepNodeExt: Sized { + /// Construct a DepNode from the given DepKind and DefPathHash. This + /// method will assert that the given DepKind actually requires a + /// single DefId/DefPathHash parameter. + fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> Self; + + /// Extracts the DefId corresponding to this DepNode. This will work + /// if two conditions are met: + /// + /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and + /// 2. the item that the DefPath refers to exists in the current tcx. + /// + /// Condition (1) is determined by the DepKind variant of the + /// DepNode. Condition (2) might not be fulfilled if a DepNode + /// refers to something from the previous compilation session that + /// has been removed. + fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option; + + /// Used in testing + fn from_label_string(label: &str, def_path_hash: DefPathHash) + -> Result; + + /// Used in testing + fn has_label_string(label: &str) -> bool; } - impl DepNode { + impl DepNodeExt for DepNode { /// Construct a DepNode from the given DepKind and DefPathHash. This /// method will assert that the given DepKind actually requires a /// single DefId/DefPathHash parameter. - pub fn from_def_path_hash(kind: DepKind, - def_path_hash: DefPathHash) - -> DepNode { + fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> DepNode { debug_assert!(kind.can_reconstruct_query_key() && kind.has_params()); DepNode { kind, @@ -233,17 +252,6 @@ macro_rules! define_dep_nodes { } } - /// Creates a new, parameterless DepNode. This method will assert - /// that the DepNode corresponding to the given DepKind actually - /// does not require any parameters. - pub fn new_no_params(kind: DepKind) -> DepNode { - debug_assert!(!kind.has_params()); - DepNode { - kind, - hash: Fingerprint::ZERO, - } - } - /// Extracts the DefId corresponding to this DepNode. This will work /// if two conditions are met: /// @@ -254,20 +262,17 @@ macro_rules! define_dep_nodes { /// DepNode. Condition (2) might not be fulfilled if a DepNode /// refers to something from the previous compilation session that /// has been removed. - pub fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option { + fn extract_def_id(&self, tcx: TyCtxt<'tcx>) -> Option { if self.kind.can_reconstruct_query_key() { let def_path_hash = DefPathHash(self.hash); - tcx.def_path_hash_to_def_id.as_ref()? - .get(&def_path_hash).cloned() + tcx.def_path_hash_to_def_id.as_ref()?.get(&def_path_hash).cloned() } else { None } } /// Used in testing - pub fn from_label_string(label: &str, - def_path_hash: DefPathHash) - -> Result { + fn from_label_string(label: &str, def_path_hash: DefPathHash) -> Result { let kind = match label { $( stringify!($variant) => DepKind::$variant, @@ -280,14 +285,14 @@ macro_rules! define_dep_nodes { } if kind.has_params() { - Ok(def_path_hash.to_dep_node(kind)) + Ok(DepNode::from_def_path_hash(def_path_hash, kind)) } else { Ok(DepNode::new_no_params(kind)) } } /// Used in testing - pub fn has_label_string(label: &str) -> bool { + fn has_label_string(label: &str) -> bool { match label { $( stringify!($variant) => true, @@ -308,114 +313,22 @@ macro_rules! define_dep_nodes { ); } -impl fmt::Debug for DepNode { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:?}", self.kind)?; - - if !self.kind.has_params() && !self.kind.is_anon() { - return Ok(()); - } - - write!(f, "(")?; - - crate::ty::tls::with_opt(|opt_tcx| { - if let Some(tcx) = opt_tcx { - if let Some(def_id) = self.extract_def_id(tcx) { - write!(f, "{}", tcx.def_path_debug_str(def_id))?; - } else if let Some(ref s) = tcx.dep_graph.dep_node_debug_str(*self) { - write!(f, "{}", s)?; - } else { - write!(f, "{}", self.hash)?; - } - } else { - write!(f, "{}", self.hash)?; - } - Ok(()) - })?; - - write!(f, ")") - } -} - -impl DefPathHash { - pub fn to_dep_node(self, kind: DepKind) -> DepNode { - DepNode::from_def_path_hash(kind, self) - } -} - rustc_dep_node_append!([define_dep_nodes!][ <'tcx> // We use this for most things when incr. comp. is turned off. [] Null, - // Represents the body of a function or method. The def-id is that of the - // function/method. - [eval_always] HirBody(DefId), - - // Represents the HIR node with the given node-id - [eval_always] Hir(DefId), - // Represents metadata from an extern crate. [eval_always] CrateMetadata(CrateNum), - [eval_always] AllLocalTraitImpls, - [anon] TraitSelect, [] CompileCodegenUnit(Symbol), ]); -pub(crate) trait DepNodeParams<'tcx>: fmt::Debug + Sized { - const CAN_RECONSTRUCT_QUERY_KEY: bool; - - /// This method turns the parameters of a DepNodeConstructor into an opaque - /// Fingerprint to be used in DepNode. - /// Not all DepNodeParams support being turned into a Fingerprint (they - /// don't need to if the corresponding DepNode is anonymous). - fn to_fingerprint(&self, _: TyCtxt<'tcx>) -> Fingerprint { - panic!("Not implemented. Accidentally called on anonymous node?") - } - - fn to_debug_str(&self, _: TyCtxt<'tcx>) -> String { - format!("{:?}", self) - } - - /// This method tries to recover the query key from the given `DepNode`, - /// something which is needed when forcing `DepNode`s during red-green - /// evaluation. The query system will only call this method if - /// `CAN_RECONSTRUCT_QUERY_KEY` is `true`. - /// It is always valid to return `None` here, in which case incremental - /// compilation will treat the query as having changed instead of forcing it. - fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option; -} - -impl<'tcx, T> DepNodeParams<'tcx> for T -where - T: HashStable> + fmt::Debug, -{ - default const CAN_RECONSTRUCT_QUERY_KEY: bool = false; - - default fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { - let mut hcx = tcx.create_stable_hashing_context(); - let mut hasher = StableHasher::new(); - - self.hash_stable(&mut hcx, &mut hasher); - - hasher.finish() - } - - default fn to_debug_str(&self, _: TyCtxt<'tcx>) -> String { - format!("{:?}", *self) - } - - default fn recover(_: TyCtxt<'tcx>, _: &DepNode) -> Option { - None - } -} - -impl<'tcx> DepNodeParams<'tcx> for DefId { +impl<'tcx> DepNodeParams> for DefId { const CAN_RECONSTRUCT_QUERY_KEY: bool = true; - fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint { + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { tcx.def_path_hash(*self).0 } @@ -428,26 +341,26 @@ impl<'tcx> DepNodeParams<'tcx> for DefId { } } -impl<'tcx> DepNodeParams<'tcx> for DefIndex { +impl<'tcx> DepNodeParams> for LocalDefId { const CAN_RECONSTRUCT_QUERY_KEY: bool = true; - fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint { - tcx.hir().definitions().def_path_hash(*self).0 + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + self.to_def_id().to_fingerprint(tcx) } fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { - tcx.def_path_str(DefId::local(*self)) + self.to_def_id().to_debug_str(tcx) } fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { - dep_node.extract_def_id(tcx).map(|id| id.index) + dep_node.extract_def_id(tcx).map(|id| id.expect_local()) } } -impl<'tcx> DepNodeParams<'tcx> for CrateNum { +impl<'tcx> DepNodeParams> for CrateNum { const CAN_RECONSTRUCT_QUERY_KEY: bool = true; - fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint { + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { let def_id = DefId { krate: *self, index: CRATE_DEF_INDEX }; tcx.def_path_hash(def_id).0 } @@ -461,13 +374,13 @@ impl<'tcx> DepNodeParams<'tcx> for CrateNum { } } -impl<'tcx> DepNodeParams<'tcx> for (DefId, DefId) { +impl<'tcx> DepNodeParams> for (DefId, DefId) { const CAN_RECONSTRUCT_QUERY_KEY: bool = false; // We actually would not need to specialize the implementation of this // method but it's faster to combine the hashes than to instantiate a full // hashing context and stable-hashing state. - fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint { + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { let (def_id_0, def_id_1) = *self; let def_path_hash_0 = tcx.def_path_hash(def_id_0); @@ -483,53 +396,18 @@ impl<'tcx> DepNodeParams<'tcx> for (DefId, DefId) { } } -impl<'tcx> DepNodeParams<'tcx> for HirId { +impl<'tcx> DepNodeParams> for HirId { const CAN_RECONSTRUCT_QUERY_KEY: bool = false; // We actually would not need to specialize the implementation of this // method but it's faster to combine the hashes than to instantiate a full // hashing context and stable-hashing state. - fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint { + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { let HirId { owner, local_id } = *self; - let def_path_hash = tcx.def_path_hash(DefId::local(owner)); + let def_path_hash = tcx.def_path_hash(owner.to_def_id()); let local_id = Fingerprint::from_smaller_hash(local_id.as_u32().into()); def_path_hash.0.combine(local_id) } } - -/// A "work product" corresponds to a `.o` (or other) file that we -/// save in between runs. These IDs do not have a `DefId` but rather -/// some independent path or string that persists between runs without -/// the need to be mapped or unmapped. (This ensures we can serialize -/// them even in the absence of a tcx.) -#[derive( - Clone, - Copy, - Debug, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - RustcEncodable, - RustcDecodable, - HashStable -)] -pub struct WorkProductId { - hash: Fingerprint, -} - -impl WorkProductId { - pub fn from_cgu_name(cgu_name: &str) -> WorkProductId { - let mut hasher = StableHasher::new(); - cgu_name.len().hash(&mut hasher); - cgu_name.hash(&mut hasher); - WorkProductId { hash: hasher.finish() } - } - - pub fn from_fingerprint(fingerprint: Fingerprint) -> WorkProductId { - WorkProductId { hash: fingerprint } - } -} diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs index 1fbd90743f402..3c39597584df5 100644 --- a/src/librustc/dep_graph/mod.rs +++ b/src/librustc/dep_graph/mod.rs @@ -1,17 +1,191 @@ -pub mod debug; +use crate::ich::StableHashingContext; +use crate::ty::query::try_load_from_on_disk_cache; +use crate::ty::{self, TyCtxt}; +use rustc_data_structures::profiling::SelfProfilerRef; +use rustc_data_structures::sync::Lock; +use rustc_data_structures::thin_vec::ThinVec; +use rustc_errors::Diagnostic; +use rustc_hir::def_id::DefId; + mod dep_node; -mod graph; -mod prev; -mod query; mod safe; -mod serialized; - -pub(crate) use self::dep_node::DepNodeParams; -pub use self::dep_node::{label_strs, DepConstructor, DepKind, DepNode, WorkProductId}; -pub use self::graph::WorkProductFileKind; -pub use self::graph::{hash_result, DepGraph, DepNodeColor, DepNodeIndex, TaskDeps, WorkProduct}; -pub use self::prev::PreviousDepGraph; -pub use self::query::DepGraphQuery; -pub use self::safe::AssertDepGraphSafe; -pub use self::safe::DepGraphSafe; -pub use self::serialized::{SerializedDepGraph, SerializedDepNodeIndex}; + +pub(crate) use rustc_query_system::dep_graph::DepNodeParams; +pub use rustc_query_system::dep_graph::{ + debug, hash_result, DepContext, DepNodeColor, DepNodeIndex, SerializedDepNodeIndex, + WorkProduct, WorkProductFileKind, WorkProductId, +}; + +pub use dep_node::{label_strs, DepConstructor, DepKind, DepNode, DepNodeExt}; +pub use safe::AssertDepGraphSafe; +pub use safe::DepGraphSafe; + +pub type DepGraph = rustc_query_system::dep_graph::DepGraph; +pub type TaskDeps = rustc_query_system::dep_graph::TaskDeps; +pub type DepGraphQuery = rustc_query_system::dep_graph::DepGraphQuery; +pub type PreviousDepGraph = rustc_query_system::dep_graph::PreviousDepGraph; +pub type SerializedDepGraph = rustc_query_system::dep_graph::SerializedDepGraph; + +impl rustc_query_system::dep_graph::DepKind for DepKind { + fn is_eval_always(&self) -> bool { + DepKind::is_eval_always(self) + } + + fn has_params(&self) -> bool { + DepKind::has_params(self) + } + + fn debug_node(node: &DepNode, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", node.kind)?; + + if !node.kind.has_params() && !node.kind.is_anon() { + return Ok(()); + } + + write!(f, "(")?; + + ty::tls::with_opt(|opt_tcx| { + if let Some(tcx) = opt_tcx { + if let Some(def_id) = node.extract_def_id(tcx) { + write!(f, "{}", tcx.def_path_debug_str(def_id))?; + } else if let Some(ref s) = tcx.dep_graph.dep_node_debug_str(*node) { + write!(f, "{}", s)?; + } else { + write!(f, "{}", node.hash)?; + } + } else { + write!(f, "{}", node.hash)?; + } + Ok(()) + })?; + + write!(f, ")") + } + + fn with_deps(task_deps: Option<&Lock>, op: OP) -> R + where + OP: FnOnce() -> R, + { + ty::tls::with_context(|icx| { + let icx = ty::tls::ImplicitCtxt { task_deps, ..icx.clone() }; + + ty::tls::enter_context(&icx, |_| op()) + }) + } + + fn read_deps(op: OP) -> () + where + OP: for<'a> FnOnce(Option<&'a Lock>) -> (), + { + ty::tls::with_context_opt(|icx| { + let icx = if let Some(icx) = icx { icx } else { return }; + op(icx.task_deps) + }) + } +} + +impl<'tcx> DepContext for TyCtxt<'tcx> { + type DepKind = DepKind; + type StableHashingContext = StableHashingContext<'tcx>; + + fn create_stable_hashing_context(&self) -> Self::StableHashingContext { + TyCtxt::create_stable_hashing_context(*self) + } + + fn try_force_from_dep_node(&self, dep_node: &DepNode) -> bool { + // FIXME: This match is just a workaround for incremental bugs and should + // be removed. https://github.com/rust-lang/rust/issues/62649 is one such + // bug that must be fixed before removing this. + match dep_node.kind { + DepKind::hir_owner | DepKind::hir_owner_nodes | DepKind::CrateMetadata => { + if let Some(def_id) = dep_node.extract_def_id(*self) { + if def_id_corresponds_to_hir_dep_node(*self, def_id) { + if dep_node.kind == DepKind::CrateMetadata { + // The `DefPath` has corresponding node, + // and that node should have been marked + // either red or green in `data.colors`. + bug!( + "DepNode {:?} should have been \ + pre-marked as red or green but wasn't.", + dep_node + ); + } + } else { + // This `DefPath` does not have a + // corresponding `DepNode` (e.g. a + // struct field), and the ` DefPath` + // collided with the `DefPath` of a + // proper item that existed in the + // previous compilation session. + // + // Since the given `DefPath` does not + // denote the item that previously + // existed, we just fail to mark green. + return false; + } + } else { + // If the node does not exist anymore, we + // just fail to mark green. + return false; + } + } + _ => { + // For other kinds of nodes it's OK to be + // forced. + } + } + + debug!("try_force_from_dep_node({:?}) --- trying to force", dep_node); + ty::query::force_from_dep_node(*self, dep_node) + } + + fn has_errors_or_delayed_span_bugs(&self) -> bool { + self.sess.has_errors_or_delayed_span_bugs() + } + + fn diagnostic(&self) -> &rustc_errors::Handler { + self.sess.diagnostic() + } + + // Interactions with on_disk_cache + fn try_load_from_on_disk_cache(&self, dep_node: &DepNode) { + try_load_from_on_disk_cache(*self, dep_node) + } + + fn load_diagnostics(&self, prev_dep_node_index: SerializedDepNodeIndex) -> Vec { + self.queries.on_disk_cache.load_diagnostics(*self, prev_dep_node_index) + } + + fn store_diagnostics(&self, dep_node_index: DepNodeIndex, diagnostics: ThinVec) { + self.queries.on_disk_cache.store_diagnostics(dep_node_index, diagnostics) + } + + fn profiler(&self) -> &SelfProfilerRef { + &self.prof + } +} + +fn def_id_corresponds_to_hir_dep_node(tcx: TyCtxt<'_>, def_id: DefId) -> bool { + let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); + def_id.index == hir_id.owner.local_def_index +} + +impl rustc_query_system::HashStableContext for StableHashingContext<'_> { + fn debug_dep_tasks(&self) -> bool { + self.sess().opts.debugging_opts.dep_tasks + } +} + +impl rustc_query_system::HashStableContextProvider> for TyCtxt<'tcx> { + fn get_stable_hashing_context(&self) -> StableHashingContext<'tcx> { + self.create_stable_hashing_context() + } +} + +impl rustc_query_system::HashStableContextProvider> + for StableHashingContext<'a> +{ + fn get_stable_hashing_context(&self) -> Self { + self.clone() + } +} diff --git a/src/librustc/dep_graph/safe.rs b/src/librustc/dep_graph/safe.rs index 74e32867cdec1..47a1c09672ff6 100644 --- a/src/librustc/dep_graph/safe.rs +++ b/src/librustc/dep_graph/safe.rs @@ -2,56 +2,8 @@ use crate::ty::TyCtxt; -use rustc_ast::ast::NodeId; -use rustc_hir::def_id::DefId; -use rustc_hir::BodyId; - -/// The `DepGraphSafe` trait is used to specify what kinds of values -/// are safe to "leak" into a task. The idea is that this should be -/// only be implemented for things like the tcx as well as various id -/// types, which will create reads in the dep-graph whenever the trait -/// loads anything that might depend on the input program. -pub trait DepGraphSafe {} - -/// A `BodyId` on its own doesn't give access to any particular state. -/// You must fetch the state from the various maps or generate -/// on-demand queries, all of which create reads. -impl DepGraphSafe for BodyId {} - -/// A `NodeId` on its own doesn't give access to any particular state. -/// You must fetch the state from the various maps or generate -/// on-demand queries, all of which create reads. -impl DepGraphSafe for NodeId {} - -/// A `DefId` on its own doesn't give access to any particular state. -/// You must fetch the state from the various maps or generate -/// on-demand queries, all of which create reads. -impl DepGraphSafe for DefId {} +pub use rustc_query_system::dep_graph::{AssertDepGraphSafe, DepGraphSafe}; /// The type context itself can be used to access all kinds of tracked /// state, but those accesses should always generate read events. impl<'tcx> DepGraphSafe for TyCtxt<'tcx> {} - -/// Tuples make it easy to build up state. -impl DepGraphSafe for (A, B) -where - A: DepGraphSafe, - B: DepGraphSafe, -{ -} - -/// Shared ref to dep-graph-safe stuff should still be dep-graph-safe. -impl<'a, A> DepGraphSafe for &'a A where A: DepGraphSafe {} - -/// Mut ref to dep-graph-safe stuff should still be dep-graph-safe. -impl<'a, A> DepGraphSafe for &'a mut A where A: DepGraphSafe {} - -/// No data here! :) -impl DepGraphSafe for () {} - -/// A convenient override that lets you pass arbitrary state into a -/// task. Every use should be accompanied by a comment explaining why -/// it makes sense (or how it could be refactored away in the future). -pub struct AssertDepGraphSafe(pub T); - -impl DepGraphSafe for AssertDepGraphSafe {} diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs index d9ffe4582e7d7..7024e86f95d06 100644 --- a/src/librustc/hir/map/blocks.rs +++ b/src/librustc/hir/map/blocks.rs @@ -51,7 +51,7 @@ impl MaybeFnLike for hir::Item<'_> { impl MaybeFnLike for hir::ImplItem<'_> { fn is_fn_like(&self) -> bool { match self.kind { - hir::ImplItemKind::Method(..) => true, + hir::ImplItemKind::Fn(..) => true, _ => false, } } @@ -60,7 +60,7 @@ impl MaybeFnLike for hir::ImplItem<'_> { impl MaybeFnLike for hir::TraitItem<'_> { fn is_fn_like(&self) -> bool { match self.kind { - hir::TraitItemKind::Fn(_, hir::TraitMethod::Provided(_)) => true, + hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => true, _ => false, } } @@ -239,13 +239,13 @@ impl<'a> FnLikeNode<'a> { _ => bug!("item FnLikeNode that is not fn-like"), }, Node::TraitItem(ti) => match ti.kind { - hir::TraitItemKind::Fn(ref sig, hir::TraitMethod::Provided(body)) => { + hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { method(ti.hir_id, ti.ident, sig, None, body, ti.span, &ti.attrs) } _ => bug!("trait method FnLikeNode that is not fn-like"), }, Node::ImplItem(ii) => match ii.kind { - hir::ImplItemKind::Method(ref sig, body) => { + hir::ImplItemKind::Fn(ref sig, body) => { method(ii.hir_id, ii.ident, sig, Some(&ii.vis), body, ii.span, &ii.attrs) } _ => bug!("impl method FnLikeNode that is not fn-like"), diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index ebd335ab35504..725238f1d1a85 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -1,19 +1,19 @@ -use crate::dep_graph::{DepGraph, DepKind, DepNode, DepNodeIndex}; -use crate::hir::map::definitions::{self, DefPathHash}; -use crate::hir::map::{Entry, HirEntryMap, Map}; +use crate::arena::Arena; +use crate::hir::map::{Entry, HirOwnerData, Map}; +use crate::hir::{Owner, OwnerNodes, ParentedNode}; use crate::ich::StableHashingContext; use crate::middle::cstore::CrateStore; -use rustc_ast::ast::NodeId; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::svh::Svh; use rustc_hir as hir; use rustc_hir::def_id::CRATE_DEF_INDEX; -use rustc_hir::def_id::{CrateNum, DefIndex, LOCAL_CRATE}; +use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE}; +use rustc_hir::definitions::{self, DefPathHash}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::*; -use rustc_index::vec::IndexVec; +use rustc_index::vec::{Idx, IndexVec}; use rustc_session::{CrateDisambiguator, Session}; use rustc_span::source_map::SourceMap; use rustc_span::{Span, Symbol, DUMMY_SP}; @@ -22,76 +22,57 @@ use std::iter::repeat; /// A visitor that walks over the HIR and collects `Node`s into a HIR map. pub(super) struct NodeCollector<'a, 'hir> { + arena: &'hir Arena<'hir>, + /// The crate krate: &'hir Crate<'hir>, /// Source map source_map: &'a SourceMap, - /// The node map - map: HirEntryMap<'hir>, + map: IndexVec>, + /// The parent of this node parent_node: hir::HirId, - // These fields keep track of the currently relevant DepNodes during - // the visitor's traversal. - current_dep_node_owner: DefIndex, - current_signature_dep_index: DepNodeIndex, - current_full_dep_index: DepNodeIndex, - currently_in_body: bool, + current_dep_node_owner: LocalDefId, - dep_graph: &'a DepGraph, definitions: &'a definitions::Definitions, - hir_to_node_id: &'a FxHashMap, hcx: StableHashingContext<'a>, - // We are collecting `DepNode::HirBody` hashes here so we can compute the - // crate hash from then later on. + // We are collecting HIR hashes here so we can compute the + // crate hash from them later on. hir_body_nodes: Vec<(DefPathHash, Fingerprint)>, } -fn input_dep_node_and_hash( - dep_graph: &DepGraph, +fn insert_vec_map(map: &mut IndexVec>, k: K, v: V) { + let i = k.index(); + let len = map.len(); + if i >= len { + map.extend(repeat(None).take(i - len + 1)); + } + map[k] = Some(v); +} + +fn hash( hcx: &mut StableHashingContext<'_>, - dep_node: DepNode, input: impl for<'a> HashStable>, -) -> (DepNodeIndex, Fingerprint) { - let dep_node_index = dep_graph.input_task(dep_node, &mut *hcx, &input).1; - - let hash = if dep_graph.is_fully_enabled() { - dep_graph.fingerprint_of(dep_node_index) - } else { - let mut stable_hasher = StableHasher::new(); - input.hash_stable(hcx, &mut stable_hasher); - stable_hasher.finish() - }; - - (dep_node_index, hash) +) -> Fingerprint { + let mut stable_hasher = StableHasher::new(); + input.hash_stable(hcx, &mut stable_hasher); + stable_hasher.finish() } -fn alloc_hir_dep_nodes( - dep_graph: &DepGraph, +fn hash_body( hcx: &mut StableHashingContext<'_>, def_path_hash: DefPathHash, item_like: impl for<'a> HashStable>, hir_body_nodes: &mut Vec<(DefPathHash, Fingerprint)>, -) -> (DepNodeIndex, DepNodeIndex) { - let sig = dep_graph - .input_task( - def_path_hash.to_dep_node(DepKind::Hir), - &mut *hcx, - HirItemLike { item_like: &item_like, hash_bodies: false }, - ) - .1; - let (full, hash) = input_dep_node_and_hash( - dep_graph, - hcx, - def_path_hash.to_dep_node(DepKind::HirBody), - HirItemLike { item_like: &item_like, hash_bodies: true }, - ); +) -> Fingerprint { + let hash = hash(hcx, HirItemLike { item_like: &item_like }); hir_body_nodes.push((def_path_hash, hash)); - (sig, full) + hash } fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(Symbol, Fingerprint, Svh)> { @@ -112,24 +93,19 @@ fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(Symbol, Fingerprint, Svh)> { impl<'a, 'hir> NodeCollector<'a, 'hir> { pub(super) fn root( sess: &'a Session, + arena: &'hir Arena<'hir>, krate: &'hir Crate<'hir>, - dep_graph: &'a DepGraph, definitions: &'a definitions::Definitions, - hir_to_node_id: &'a FxHashMap, mut hcx: StableHashingContext<'a>, ) -> NodeCollector<'a, 'hir> { - let root_mod_def_path_hash = definitions.def_path_hash(CRATE_DEF_INDEX); + let root_mod_def_path_hash = + definitions.def_path_hash(LocalDefId { local_def_index: CRATE_DEF_INDEX }); let mut hir_body_nodes = Vec::new(); - // Allocate `DepNode`s for the root module. - let (root_mod_sig_dep_index, root_mod_full_dep_index) = { + let hash = { let Crate { - ref module, - // Crate attributes are not copied over to the root `Mod`, so hash - // them explicitly here. - ref attrs, - span, + ref item, // These fields are handled separately: exported_macros: _, non_exported_macro_attrs: _, @@ -143,45 +119,26 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { proc_macros: _, } = *krate; - alloc_hir_dep_nodes( - dep_graph, - &mut hcx, - root_mod_def_path_hash, - (module, attrs, span), - &mut hir_body_nodes, - ) + hash_body(&mut hcx, root_mod_def_path_hash, item, &mut hir_body_nodes) }; - { - dep_graph.input_task( - DepNode::new_no_params(DepKind::AllLocalTraitImpls), - &mut hcx, - &krate.trait_impls, - ); - } - let mut collector = NodeCollector { + arena, krate, source_map: sess.source_map(), - map: IndexVec::from_elem_n(IndexVec::new(), definitions.def_index_count()), parent_node: hir::CRATE_HIR_ID, - current_signature_dep_index: root_mod_sig_dep_index, - current_full_dep_index: root_mod_full_dep_index, - current_dep_node_owner: CRATE_DEF_INDEX, - currently_in_body: false, - dep_graph, + current_dep_node_owner: LocalDefId { local_def_index: CRATE_DEF_INDEX }, definitions, - hir_to_node_id, hcx, hir_body_nodes, + map: (0..definitions.def_index_count()) + .map(|_| HirOwnerData { signature: None, with_bodies: None }) + .collect(), }; collector.insert_entry( hir::CRATE_HIR_ID, - Entry { - parent: hir::CRATE_HIR_ID, - dep_node: root_mod_sig_dep_index, - node: Node::Crate, - }, + Entry { parent: hir::CRATE_HIR_ID, node: Node::Crate(&krate.item) }, + hash, ); collector @@ -192,7 +149,13 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { crate_disambiguator: CrateDisambiguator, cstore: &dyn CrateStore, commandline_args_hash: u64, - ) -> (HirEntryMap<'hir>, Svh) { + ) -> (IndexVec>, Svh) { + // Insert bodies into the map + for (id, body) in self.krate.bodies.iter() { + let bodies = &mut self.map[id.hir_id.owner].with_bodies.as_mut().unwrap().bodies; + assert!(bodies.insert(id.hir_id.local_id, body).is_none()); + } + self.hir_body_nodes.sort_unstable_by_key(|bn| bn.0); let node_hashes = self.hir_body_nodes.iter().fold( @@ -213,7 +176,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { .source_map .files() .iter() - .filter(|source_file| CrateNum::from_u32(source_file.crate_of_origin) == LOCAL_CRATE) + .filter(|source_file| source_file.cnum == LOCAL_CRATE) .map(|source_file| source_file.name_hash) .collect(); @@ -232,37 +195,58 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { (self.map, svh) } - fn insert_entry(&mut self, id: HirId, entry: Entry<'hir>) { - debug!("hir_map: {:?} => {:?}", id, entry); - let local_map = &mut self.map[id.owner]; + fn insert_entry(&mut self, id: HirId, entry: Entry<'hir>, hash: Fingerprint) { let i = id.local_id.as_u32() as usize; - let len = local_map.len(); - if i >= len { - local_map.extend(repeat(None).take(i - len + 1)); + + let arena = self.arena; + + let data = &mut self.map[id.owner]; + + if data.with_bodies.is_none() { + data.with_bodies = Some(arena.alloc(OwnerNodes { + hash, + nodes: IndexVec::new(), + bodies: FxHashMap::default(), + })); + } + + let nodes = data.with_bodies.as_mut().unwrap(); + + if i == 0 { + // Overwrite the dummy hash with the real HIR owner hash. + nodes.hash = hash; + + // FIXME: feature(impl_trait_in_bindings) broken and trigger this assert + //assert!(data.signature.is_none()); + + data.signature = + Some(self.arena.alloc(Owner { parent: entry.parent, node: entry.node })); + } else { + assert_eq!(entry.parent.owner, id.owner); + insert_vec_map( + &mut nodes.nodes, + id.local_id, + ParentedNode { parent: entry.parent.local_id, node: entry.node }, + ); } - local_map[id.local_id] = Some(entry); } fn insert(&mut self, span: Span, hir_id: HirId, node: Node<'hir>) { - let entry = Entry { - parent: self.parent_node, - dep_node: if self.currently_in_body { - self.current_full_dep_index - } else { - self.current_signature_dep_index - }, - node, - }; + self.insert_with_hash(span, hir_id, node, Fingerprint::ZERO) + } + + fn insert_with_hash(&mut self, span: Span, hir_id: HirId, node: Node<'hir>, hash: Fingerprint) { + let entry = Entry { parent: self.parent_node, node }; // Make sure that the DepNode of some node coincides with the HirId // owner of that node. if cfg!(debug_assertions) { - let node_id = self.hir_to_node_id[&hir_id]; + let node_id = self.definitions.hir_to_node_id(hir_id); assert_eq!(self.definitions.node_to_hir_id(node_id), hir_id); if hir_id.owner != self.current_dep_node_owner { - let node_str = match self.definitions.opt_def_index(node_id) { - Some(def_index) => self.definitions.def_path(def_index).to_string_no_crate(), + let node_str = match self.definitions.opt_local_def_id(node_id) { + Some(def_id) => self.definitions.def_path(def_id).to_string_no_crate(), None => format!("{:?}", node), }; @@ -287,7 +271,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { } } - self.insert_entry(hir_id, entry); + self.insert_entry(hir_id, entry, hash); } fn with_parent(&mut self, parent_node_id: HirId, f: F) { @@ -299,37 +283,22 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { fn with_dep_node_owner< T: for<'b> HashStable>, - F: FnOnce(&mut Self), + F: FnOnce(&mut Self, Fingerprint), >( &mut self, - dep_node_owner: DefIndex, + dep_node_owner: LocalDefId, item_like: &T, f: F, ) { let prev_owner = self.current_dep_node_owner; - let prev_signature_dep_index = self.current_signature_dep_index; - let prev_full_dep_index = self.current_full_dep_index; - let prev_in_body = self.currently_in_body; let def_path_hash = self.definitions.def_path_hash(dep_node_owner); - let (signature_dep_index, full_dep_index) = alloc_hir_dep_nodes( - self.dep_graph, - &mut self.hcx, - def_path_hash, - item_like, - &mut self.hir_body_nodes, - ); - self.current_signature_dep_index = signature_dep_index; - self.current_full_dep_index = full_dep_index; + let hash = hash_body(&mut self.hcx, def_path_hash, item_like, &mut self.hir_body_nodes); self.current_dep_node_owner = dep_node_owner; - self.currently_in_body = false; - f(self); - self.currently_in_body = prev_in_body; + f(self, hash); self.current_dep_node_owner = prev_owner; - self.current_full_dep_index = prev_full_dep_index; - self.current_signature_dep_index = prev_signature_dep_index; } } @@ -340,7 +309,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { /// deep walking so that we walk nested items in the context of /// their outer items. - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { panic!("`visit_nested_xxx` must be manually implemented in this visitor"); } @@ -358,10 +327,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_nested_body(&mut self, id: BodyId) { - let prev_in_body = self.currently_in_body; - self.currently_in_body = true; self.visit_body(self.krate.body(id)); - self.currently_in_body = prev_in_body; } fn visit_param(&mut self, param: &'hir Param<'hir>) { @@ -376,10 +342,10 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { debug!("visit_item: {:?}", i); debug_assert_eq!( i.hir_id.owner, - self.definitions.opt_def_index(self.hir_to_node_id[&i.hir_id]).unwrap() + self.definitions.opt_local_def_id(self.definitions.hir_to_node_id(i.hir_id)).unwrap() ); - self.with_dep_node_owner(i.hir_id.owner, i, |this| { - this.insert(i.span, i.hir_id, Node::Item(i)); + self.with_dep_node_owner(i.hir_id.owner, i, |this, hash| { + this.insert_with_hash(i.span, i.hir_id, Node::Item(i), hash); this.with_parent(i.hir_id, |this| { if let ItemKind::Struct(ref struct_def, _) = i.kind { // If this is a tuple or unit-like struct, register the constructor. @@ -408,10 +374,10 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) { debug_assert_eq!( ti.hir_id.owner, - self.definitions.opt_def_index(self.hir_to_node_id[&ti.hir_id]).unwrap() + self.definitions.opt_local_def_id(self.definitions.hir_to_node_id(ti.hir_id)).unwrap() ); - self.with_dep_node_owner(ti.hir_id.owner, ti, |this| { - this.insert(ti.span, ti.hir_id, Node::TraitItem(ti)); + self.with_dep_node_owner(ti.hir_id.owner, ti, |this, hash| { + this.insert_with_hash(ti.span, ti.hir_id, Node::TraitItem(ti), hash); this.with_parent(ti.hir_id, |this| { intravisit::walk_trait_item(this, ti); @@ -422,10 +388,10 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) { debug_assert_eq!( ii.hir_id.owner, - self.definitions.opt_def_index(self.hir_to_node_id[&ii.hir_id]).unwrap() + self.definitions.opt_local_def_id(self.definitions.hir_to_node_id(ii.hir_id)).unwrap() ); - self.with_dep_node_owner(ii.hir_id.owner, ii, |this| { - this.insert(ii.span, ii.hir_id, Node::ImplItem(ii)); + self.with_dep_node_owner(ii.hir_id.owner, ii, |this, hash| { + this.insert_with_hash(ii.span, ii.hir_id, Node::ImplItem(ii), hash); this.with_parent(ii.hir_id, |this| { intravisit::walk_impl_item(this, ii); @@ -541,11 +507,13 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_macro_def(&mut self, macro_def: &'hir MacroDef<'hir>) { - let node_id = self.hir_to_node_id[¯o_def.hir_id]; - let def_index = self.definitions.opt_def_index(node_id).unwrap(); - - self.with_dep_node_owner(def_index, macro_def, |this| { - this.insert(macro_def.span, macro_def.hir_id, Node::MacroDef(macro_def)); + self.with_dep_node_owner(macro_def.hir_id.owner, macro_def, |this, hash| { + this.insert_with_hash( + macro_def.span, + macro_def.hir_id, + Node::MacroDef(macro_def), + hash, + ); }); } @@ -584,11 +552,8 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } } -// This is a wrapper structure that allows determining if span values within -// the wrapped item should be hashed or not. struct HirItemLike { item_like: T, - hash_bodies: bool, } impl<'hir, T> HashStable> for HirItemLike @@ -596,7 +561,7 @@ where T: HashStable>, { fn hash_stable(&self, hcx: &mut StableHashingContext<'hir>, hasher: &mut StableHasher) { - hcx.while_hashing_hir_bodies(self.hash_bodies, |hcx| { + hcx.while_hashing_hir_bodies(true, |hcx| { self.item_like.hash_stable(hcx, hasher); }); } diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index cacb76c286191..6290f5bb9b418 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -1,16 +1,13 @@ use self::collector::NodeCollector; -pub use self::definitions::{ - DefKey, DefPath, DefPathData, DefPathHash, Definitions, DisambiguatedDefPathData, -}; -use crate::dep_graph::{DepGraph, DepKind, DepNode, DepNodeIndex}; -use crate::middle::cstore::CrateStoreDyn; +use crate::hir::{Owner, OwnerNodes}; use crate::ty::query::Providers; +use crate::ty::TyCtxt; use rustc_ast::ast::{self, Name, NodeId}; -use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; +use rustc_hir::definitions::{DefKey, DefPath, Definitions}; use rustc_hir::intravisit; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::print::Nested; @@ -24,133 +21,87 @@ use rustc_target::spec::abi::Abi; pub mod blocks; mod collector; -pub mod definitions; -mod hir_id_validator; /// Represents an entry and its parent `HirId`. #[derive(Copy, Clone, Debug)] pub struct Entry<'hir> { parent: HirId, - dep_node: DepNodeIndex, node: Node<'hir>, } impl<'hir> Entry<'hir> { fn parent_node(self) -> Option { match self.node { - Node::Crate | Node::MacroDef(_) => None, + Node::Crate(_) | Node::MacroDef(_) => None, _ => Some(self.parent), } } +} - fn fn_decl(&self) -> Option<&'hir FnDecl<'hir>> { - match self.node { - Node::Item(ref item) => match item.kind { - ItemKind::Fn(ref sig, _, _) => Some(&sig.decl), - _ => None, - }, - - Node::TraitItem(ref item) => match item.kind { - TraitItemKind::Fn(ref sig, _) => Some(&sig.decl), - _ => None, - }, - - Node::ImplItem(ref item) => match item.kind { - ImplItemKind::Method(ref sig, _) => Some(&sig.decl), - _ => None, - }, - - Node::Expr(ref expr) => match expr.kind { - ExprKind::Closure(_, ref fn_decl, ..) => Some(fn_decl), - _ => None, - }, - - _ => None, - } +fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> { + match node { + Node::Item(Item { kind: ItemKind::Fn(sig, _, _), .. }) + | Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(sig, _), .. }) + | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(sig, _), .. }) => Some(&sig.decl), + Node::Expr(Expr { kind: ExprKind::Closure(_, fn_decl, ..), .. }) => Some(fn_decl), + _ => None, } +} - fn fn_sig(&self) -> Option<&'hir FnSig<'hir>> { - match &self.node { - Node::Item(item) => match &item.kind { - ItemKind::Fn(sig, _, _) => Some(sig), - _ => None, - }, - - Node::TraitItem(item) => match &item.kind { - TraitItemKind::Fn(sig, _) => Some(sig), - _ => None, - }, - - Node::ImplItem(item) => match &item.kind { - ImplItemKind::Method(sig, _) => Some(sig), - _ => None, - }, - - _ => None, - } +fn fn_sig<'hir>(node: Node<'hir>) -> Option<&'hir FnSig<'hir>> { + match &node { + Node::Item(Item { kind: ItemKind::Fn(sig, _, _), .. }) + | Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(sig, _), .. }) + | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(sig, _), .. }) => Some(sig), + _ => None, } +} - fn associated_body(self) -> Option { - match self.node { - Node::Item(item) => match item.kind { - ItemKind::Const(_, body) | ItemKind::Static(.., body) | ItemKind::Fn(.., body) => { - Some(body) - } - _ => None, - }, - - Node::TraitItem(item) => match item.kind { - TraitItemKind::Const(_, Some(body)) - | TraitItemKind::Fn(_, TraitMethod::Provided(body)) => Some(body), - _ => None, - }, - - Node::ImplItem(item) => match item.kind { - ImplItemKind::Const(_, body) | ImplItemKind::Method(_, body) => Some(body), - _ => None, - }, - - Node::AnonConst(constant) => Some(constant.body), +fn associated_body<'hir>(node: Node<'hir>) -> Option { + match node { + Node::Item(Item { + kind: ItemKind::Const(_, body) | ItemKind::Static(.., body) | ItemKind::Fn(.., body), + .. + }) + | Node::TraitItem(TraitItem { + kind: + TraitItemKind::Const(_, Some(body)) | TraitItemKind::Fn(_, TraitFn::Provided(body)), + .. + }) + | Node::ImplItem(ImplItem { + kind: ImplItemKind::Const(_, body) | ImplItemKind::Fn(_, body), + .. + }) + | Node::Expr(Expr { kind: ExprKind::Closure(.., body, _, _), .. }) => Some(*body), - Node::Expr(expr) => match expr.kind { - ExprKind::Closure(.., body, _, _) => Some(body), - _ => None, - }, + Node::AnonConst(constant) => Some(constant.body), - _ => None, - } + _ => None, } +} - fn is_body_owner(self, hir_id: HirId) -> bool { - match self.associated_body() { - Some(b) => b.hir_id == hir_id, - None => false, - } +fn is_body_owner<'hir>(node: Node<'hir>, hir_id: HirId) -> bool { + match associated_body(node) { + Some(b) => b.hir_id == hir_id, + None => false, } } -/// This type is effectively a `HashMap>`, -/// but it is implemented as 2 layers of arrays. -/// - first we have `A = IndexVec` mapping `DefIndex`s to an inner value -/// - which is `B = IndexVec>` which gives you the `Entry`. -pub(super) type HirEntryMap<'hir> = IndexVec>>>; - -/// Represents a mapping from `NodeId`s to AST elements and their parent `NodeId`s. -#[derive(Clone)] -pub struct Map<'hir> { - krate: &'hir Crate<'hir>, - - pub dep_graph: DepGraph, +pub(super) struct HirOwnerData<'hir> { + pub(super) signature: Option<&'hir Owner<'hir>>, + pub(super) with_bodies: Option<&'hir mut OwnerNodes<'hir>>, +} +pub struct IndexedHir<'hir> { /// The SVH of the local crate. pub crate_hash: Svh, - map: HirEntryMap<'hir>, - - definitions: Definitions, + pub(super) map: IndexVec>, +} - /// The reverse mapping of `node_to_hir_id`. - hir_to_node_id: FxHashMap, +#[derive(Copy, Clone)] +pub struct Map<'hir> { + pub(super) tcx: TyCtxt<'hir>, } /// An iterator that walks up the ancestor tree of a given `HirId`. @@ -186,53 +137,28 @@ impl<'hir> Iterator for ParentHirIterator<'_, 'hir> { } impl<'hir> Map<'hir> { - /// This is used internally in the dependency tracking system. - /// Use the `krate` method to ensure your dependency on the - /// crate is tracked. - pub fn untracked_krate(&self) -> &Crate<'hir> { - &self.krate - } - - #[inline] - fn lookup(&self, id: HirId) -> Option<&Entry<'hir>> { - let local_map = self.map.get(id.owner)?; - local_map.get(id.local_id)?.as_ref() - } - - /// Registers a read in the dependency graph of the AST node with - /// the given `id`. This needs to be called each time a public - /// function returns the HIR for a node -- in other words, when it - /// "reveals" the content of a node to the caller (who might not - /// otherwise have had access to those contents, and hence needs a - /// read recorded). If the function just returns a DefId or - /// HirId, no actual content was returned, so no read is needed. - pub fn read(&self, hir_id: HirId) { - if let Some(entry) = self.lookup(hir_id) { - self.dep_graph.read_index(entry.dep_node); - } else { - bug!("called `HirMap::read()` with invalid `HirId`: {:?}", hir_id) - } + pub fn krate(&self) -> &'hir Crate<'hir> { + self.tcx.hir_crate(LOCAL_CRATE) } #[inline] - pub fn definitions(&self) -> &Definitions { - &self.definitions + pub fn definitions(&self) -> &'hir Definitions { + &self.tcx.definitions } - pub fn def_key(&self, def_id: DefId) -> DefKey { - assert!(def_id.is_local()); - self.definitions.def_key(def_id.index) + pub fn def_key(&self, def_id: LocalDefId) -> DefKey { + self.tcx.definitions.def_key(def_id) } pub fn def_path_from_hir_id(&self, id: HirId) -> Option { - self.opt_local_def_id(id).map(|def_id| self.def_path(def_id)) + self.opt_local_def_id(id).map(|def_id| self.def_path(def_id.expect_local())) } - pub fn def_path(&self, def_id: DefId) -> DefPath { - assert!(def_id.is_local()); - self.definitions.def_path(def_id.index) + pub fn def_path(&self, def_id: LocalDefId) -> DefPath { + self.tcx.definitions.def_path(def_id) } + // FIXME(eddyb) this function can and should return `LocalDefId`. #[inline] pub fn local_def_id_from_node_id(&self, node: NodeId) -> DefId { self.opt_local_def_id_from_node_id(node).unwrap_or_else(|| { @@ -245,6 +171,7 @@ impl<'hir> Map<'hir> { }) } + // FIXME(eddyb) this function can and should return `LocalDefId`. #[inline] pub fn local_def_id(&self, hir_id: HirId) -> DefId { self.opt_local_def_id(hir_id).unwrap_or_else(|| { @@ -259,46 +186,41 @@ impl<'hir> Map<'hir> { #[inline] pub fn opt_local_def_id(&self, hir_id: HirId) -> Option { let node_id = self.hir_to_node_id(hir_id); - self.definitions.opt_local_def_id(node_id) + self.opt_local_def_id_from_node_id(node_id) } #[inline] pub fn opt_local_def_id_from_node_id(&self, node: NodeId) -> Option { - self.definitions.opt_local_def_id(node) + Some(self.tcx.definitions.opt_local_def_id(node)?.to_def_id()) } #[inline] pub fn as_local_node_id(&self, def_id: DefId) -> Option { - self.definitions.as_local_node_id(def_id) + self.tcx.definitions.as_local_node_id(def_id) } #[inline] pub fn as_local_hir_id(&self, def_id: DefId) -> Option { - self.definitions.as_local_hir_id(def_id) + self.tcx.definitions.as_local_hir_id(def_id) } #[inline] pub fn hir_to_node_id(&self, hir_id: HirId) -> NodeId { - self.hir_to_node_id[&hir_id] + self.tcx.definitions.hir_to_node_id(hir_id) } #[inline] pub fn node_to_hir_id(&self, node_id: NodeId) -> HirId { - self.definitions.node_to_hir_id(node_id) - } - - #[inline] - pub fn def_index_to_hir_id(&self, def_index: DefIndex) -> HirId { - self.definitions.def_index_to_hir_id(def_index) + self.tcx.definitions.node_to_hir_id(node_id) } #[inline] pub fn local_def_id_to_hir_id(&self, def_id: LocalDefId) -> HirId { - self.definitions.def_index_to_hir_id(def_id.to_def_id().index) + self.tcx.definitions.local_def_id_to_hir_id(def_id) } pub fn def_kind(&self, hir_id: HirId) -> Option { - let node = if let Some(node) = self.find(hir_id) { node } else { return None }; + let node = self.find(hir_id)?; Some(match node { Node::Item(item) => match item.kind { @@ -331,7 +253,7 @@ impl<'hir> Map<'hir> { }, Node::ImplItem(item) => match item.kind { ImplItemKind::Const(..) => DefKind::AssocConst, - ImplItemKind::Method(..) => DefKind::AssocFn, + ImplItemKind::Fn(..) => DefKind::AssocFn, ImplItemKind::TyAlias(..) => DefKind::AssocTy, ImplItemKind::OpaqueTy(..) => DefKind::AssocOpaqueTy, }, @@ -362,7 +284,7 @@ impl<'hir> Map<'hir> { | Node::Lifetime(_) | Node::Visibility(_) | Node::Block(_) - | Node::Crate => return None, + | Node::Crate(_) => return None, Node::MacroDef(_) => DefKind::Macro(MacroKind::Bang), Node::GenericParam(param) => match param.kind { GenericParamKind::Lifetime { .. } => return None, @@ -373,54 +295,66 @@ impl<'hir> Map<'hir> { } fn find_entry(&self, id: HirId) -> Option> { - self.lookup(id).cloned() + if id.local_id == ItemLocalId::from_u32(0) { + let owner = self.tcx.hir_owner(id.owner); + owner.map(|owner| Entry { parent: owner.parent, node: owner.node }) + } else { + let owner = self.tcx.hir_owner_nodes(id.owner); + owner.and_then(|owner| { + let node = owner.nodes[id.local_id].as_ref(); + // FIXME(eddyb) use a single generic type insted of having both + // `Entry` and `ParentedNode`, which are effectively the same. + // Alternatively, rewrite code using `Entry` to use `ParentedNode`. + node.map(|node| Entry { + parent: HirId { owner: id.owner, local_id: node.parent }, + node: node.node, + }) + }) + } } - pub fn item(&self, id: HirId) -> &'hir Item<'hir> { - self.read(id); + fn get_entry(&self, id: HirId) -> Entry<'hir> { + self.find_entry(id).unwrap() + } - // N.B., intentionally bypass `self.krate()` so that we - // do not trigger a read of the whole krate here - self.krate.item(id) + pub fn item(&self, id: HirId) -> &'hir Item<'hir> { + match self.find(id).unwrap() { + Node::Item(item) => item, + _ => bug!(), + } } pub fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> { - self.read(id.hir_id); - - // N.B., intentionally bypass `self.krate()` so that we - // do not trigger a read of the whole krate here - self.krate.trait_item(id) + match self.find(id.hir_id).unwrap() { + Node::TraitItem(item) => item, + _ => bug!(), + } } pub fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> { - self.read(id.hir_id); - - // N.B., intentionally bypass `self.krate()` so that we - // do not trigger a read of the whole krate here - self.krate.impl_item(id) + match self.find(id.hir_id).unwrap() { + Node::ImplItem(item) => item, + _ => bug!(), + } } pub fn body(&self, id: BodyId) -> &'hir Body<'hir> { - self.read(id.hir_id); - - // N.B., intentionally bypass `self.krate()` so that we - // do not trigger a read of the whole krate here - self.krate.body(id) + self.tcx.hir_owner_nodes(id.hir_id.owner).unwrap().bodies.get(&id.hir_id.local_id).unwrap() } pub fn fn_decl_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> { - if let Some(entry) = self.find_entry(hir_id) { - entry.fn_decl() + if let Some(node) = self.find(hir_id) { + fn_decl(node) } else { - bug!("no entry for hir_id `{}`", hir_id) + bug!("no node for hir_id `{}`", hir_id) } } pub fn fn_sig_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnSig<'hir>> { - if let Some(entry) = self.find_entry(hir_id) { - entry.fn_sig() + if let Some(node) = self.find(hir_id) { + fn_sig(node) } else { - bug!("no entry for hir_id `{}`", hir_id) + bug!("no node for hir_id `{}`", hir_id) } } @@ -429,10 +363,11 @@ impl<'hir> Map<'hir> { /// item (possibly associated), a closure, or a `hir::AnonConst`. pub fn body_owner(&self, BodyId { hir_id }: BodyId) -> HirId { let parent = self.get_parent_node(hir_id); - assert!(self.lookup(parent).map_or(false, |e| e.is_body_owner(hir_id))); + assert!(self.find(parent).map_or(false, |n| is_body_owner(n, hir_id))); parent } + // FIXME(eddyb) this function can and should return `LocalDefId`. pub fn body_owner_def_id(&self, id: BodyId) -> DefId { self.local_def_id(self.body_owner(id)) } @@ -440,14 +375,8 @@ impl<'hir> Map<'hir> { /// Given a `HirId`, returns the `BodyId` associated with it, /// if the node is a body owner, otherwise returns `None`. pub fn maybe_body_owned_by(&self, hir_id: HirId) -> Option { - if let Some(entry) = self.find_entry(hir_id) { - if self.dep_graph.is_fully_enabled() { - let hir_id_owner = hir_id.owner; - let def_path_hash = self.definitions.def_path_hash(hir_id_owner); - self.dep_graph.read(def_path_hash.to_dep_node(DepKind::HirBody)); - } - - entry.associated_body() + if let Some(node) = self.find(hir_id) { + associated_body(node) } else { bug!("no entry for id `{}`", hir_id) } @@ -473,7 +402,7 @@ impl<'hir> Map<'hir> { Node::Ctor(..) | Node::Item(&Item { kind: ItemKind::Fn(..), .. }) | Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(..), .. }) - | Node::ImplItem(&ImplItem { kind: ImplItemKind::Method(..), .. }) => BodyOwnerKind::Fn, + | Node::ImplItem(&ImplItem { kind: ImplItemKind::Fn(..), .. }) => BodyOwnerKind::Fn, Node::Item(&Item { kind: ItemKind::Static(_, m, _), .. }) => BodyOwnerKind::Static(m), Node::Expr(&Expr { kind: ExprKind::Closure(..), .. }) => BodyOwnerKind::Closure, node => bug!("{:#?} is not a body node", node), @@ -499,29 +428,24 @@ impl<'hir> Map<'hir> { } pub fn trait_impls(&self, trait_did: DefId) -> &'hir [HirId] { - self.dep_graph.read(DepNode::new_no_params(DepKind::AllLocalTraitImpls)); - - // N.B., intentionally bypass `self.krate()` so that we - // do not trigger a read of the whole krate here - self.krate.trait_impls.get(&trait_did).map_or(&[], |xs| &xs[..]) + self.tcx.all_local_trait_impls(LOCAL_CRATE).get(&trait_did).map_or(&[], |xs| &xs[..]) } /// Gets the attributes on the crate. This is preferable to /// invoking `krate.attrs` because it registers a tighter /// dep-graph access. pub fn krate_attrs(&self) -> &'hir [ast::Attribute] { - let def_path_hash = self.definitions.def_path_hash(CRATE_DEF_INDEX); - - self.dep_graph.read(def_path_hash.to_dep_node(DepKind::Hir)); - &self.krate.attrs + match self.get_entry(CRATE_HIR_ID).node { + Node::Crate(item) => item.attrs, + _ => bug!(), + } } pub fn get_module(&self, module: DefId) -> (&'hir Mod<'hir>, Span, HirId) { let hir_id = self.as_local_hir_id(module).unwrap(); - self.read(hir_id); - match self.find_entry(hir_id).unwrap().node { + match self.get_entry(hir_id).node { Node::Item(&Item { span, kind: ItemKind::Mod(ref m), .. }) => (m, span, hir_id), - Node::Crate => (&self.krate.module, self.krate.span, hir_id), + Node::Crate(item) => (&item.module, item.span, hir_id), node => panic!("not a module: {:?}", node), } } @@ -530,15 +454,7 @@ impl<'hir> Map<'hir> { where V: ItemLikeVisitor<'hir>, { - let hir_id = self.as_local_hir_id(module).unwrap(); - - // Read the module so we'll be re-executed if new items - // appear immediately under in the module. If some new item appears - // in some nested item in the module, we'll be re-executed due to reads - // in the expect_* calls the loops below - self.read(hir_id); - - let module = &self.krate.modules[&hir_id]; + let module = self.tcx.hir_module_items(module.expect_local()); for id in &module.items { visitor.visit_item(self.expect_item(*id)); @@ -555,42 +471,38 @@ impl<'hir> Map<'hir> { /// Retrieves the `Node` corresponding to `id`, panicking if it cannot be found. pub fn get(&self, id: HirId) -> Node<'hir> { - // read recorded by `find` self.find(id).unwrap_or_else(|| bug!("couldn't find hir id {} in the HIR map", id)) } pub fn get_if_local(&self, id: DefId) -> Option> { - self.as_local_hir_id(id).map(|id| self.get(id)) // read recorded by `get` + self.as_local_hir_id(id).map(|id| self.get(id)) } pub fn get_generics(&self, id: DefId) -> Option<&'hir Generics<'hir>> { - self.get_if_local(id).and_then(|node| match node { - Node::ImplItem(ref impl_item) => Some(&impl_item.generics), - Node::TraitItem(ref trait_item) => Some(&trait_item.generics), - Node::Item(ref item) => match item.kind { - ItemKind::Fn(_, ref generics, _) - | ItemKind::TyAlias(_, ref generics) - | ItemKind::Enum(_, ref generics) - | ItemKind::Struct(_, ref generics) - | ItemKind::Union(_, ref generics) - | ItemKind::Trait(_, _, ref generics, ..) - | ItemKind::TraitAlias(ref generics, _) - | ItemKind::Impl { ref generics, .. } => Some(generics), - _ => None, - }, + self.get_if_local(id).and_then(|node| match &node { + Node::ImplItem(impl_item) => Some(&impl_item.generics), + Node::TraitItem(trait_item) => Some(&trait_item.generics), + Node::Item(Item { + kind: + ItemKind::Fn(_, generics, _) + | ItemKind::TyAlias(_, generics) + | ItemKind::Enum(_, generics) + | ItemKind::Struct(_, generics) + | ItemKind::Union(_, generics) + | ItemKind::Trait(_, _, generics, ..) + | ItemKind::TraitAlias(generics, _) + | ItemKind::Impl { generics, .. }, + .. + }) => Some(generics), _ => None, }) } /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found. pub fn find(&self, hir_id: HirId) -> Option> { - let result = self - .find_entry(hir_id) - .and_then(|entry| if let Node::Crate = entry.node { None } else { Some(entry.node) }); - if result.is_some() { - self.read(hir_id); - } - result + self.find_entry(hir_id).and_then(|entry| { + if let Node::Crate(..) = entry.node { None } else { Some(entry.node) } + }) } /// Similar to `get_parent`; returns the parent HIR Id, or just `hir_id` if there @@ -604,13 +516,7 @@ impl<'hir> Map<'hir> { /// from a node to the root of the HIR (unless you get back the same ID here, /// which can happen if the ID is not in the map itself or is just weird). pub fn get_parent_node(&self, hir_id: HirId) -> HirId { - if self.dep_graph.is_fully_enabled() { - let hir_id_owner = hir_id.owner; - let def_path_hash = self.definitions.def_path_hash(hir_id_owner); - self.dep_graph.read(def_path_hash.to_dep_node(DepKind::HirBody)); - } - - self.find_entry(hir_id).and_then(|x| x.parent_node()).unwrap_or(hir_id) + self.get_entry(hir_id).parent_node().unwrap_or(hir_id) } /// Returns an iterator for the nodes in the ancestor tree of the `current_id` @@ -627,11 +533,12 @@ impl<'hir> Map<'hir> { _ => return false, } match self.find(self.get_parent_node(id)) { - Some(Node::Item(_)) | Some(Node::TraitItem(_)) | Some(Node::ImplItem(_)) => true, - Some(Node::Expr(e)) => match e.kind { - ExprKind::Closure(..) => true, - _ => false, - }, + Some( + Node::Item(_) + | Node::TraitItem(_) + | Node::ImplItem(_) + | Node::Expr(Expr { kind: ExprKind::Closure(..), .. }), + ) => true, _ => false, } } @@ -655,9 +562,9 @@ impl<'hir> Map<'hir> { /// Whether `hir_id` corresponds to a `mod` or a crate. pub fn is_hir_id_module(&self, hir_id: HirId) -> bool { - match self.lookup(hir_id) { - Some(Entry { node: Node::Item(Item { kind: ItemKind::Mod(_), .. }), .. }) - | Some(Entry { node: Node::Crate, .. }) => true, + match self.get_entry(hir_id) { + Entry { node: Node::Item(Item { kind: ItemKind::Mod(_), .. }), .. } + | Entry { node: Node::Crate(..), .. } => true, _ => false, } } @@ -698,12 +605,8 @@ impl<'hir> Map<'hir> { if let (Some((_, next_node)), false) = (iter.peek(), ignore_tail) { match next_node { Node::Block(Block { expr: None, .. }) => return None, - Node::Block(Block { expr: Some(expr), .. }) => { - if hir_id != expr.hir_id { - // The current node is not the tail expression of its parent. - return None; - } - } + // The current node is not the tail expression of its parent. + Node::Block(Block { expr: Some(e), .. }) if hir_id != e.hir_id => return None, _ => {} } } @@ -713,14 +616,11 @@ impl<'hir> Map<'hir> { | Node::TraitItem(_) | Node::Expr(Expr { kind: ExprKind::Closure(..), .. }) | Node::ImplItem(_) => return Some(hir_id), - Node::Expr(ref expr) => { - match expr.kind { - // Ignore `return`s on the first iteration - ExprKind::Loop(..) | ExprKind::Ret(..) => return None, - _ => {} - } + // Ignore `return`s on the first iteration + Node::Expr(Expr { kind: ExprKind::Loop(..) | ExprKind::Ret(..), .. }) + | Node::Local(_) => { + return None; } - Node::Local(_) => return None, _ => {} } } @@ -734,7 +634,7 @@ impl<'hir> Map<'hir> { pub fn get_parent_item(&self, hir_id: HirId) -> HirId { for (hir_id, node) in self.parent_iter(hir_id) { match node { - Node::Crate + Node::Crate(_) | Node::Item(_) | Node::ForeignItem(_) | Node::TraitItem(_) @@ -764,17 +664,12 @@ impl<'hir> Map<'hir> { pub fn get_match_if_cause(&self, hir_id: HirId) -> Option<&'hir Expr<'hir>> { for (_, node) in self.parent_iter(hir_id) { match node { - Node::Item(_) | Node::ForeignItem(_) | Node::TraitItem(_) | Node::ImplItem(_) => { - break; - } - Node::Expr(expr) => match expr.kind { - ExprKind::Match(_, _, _) => return Some(expr), - _ => {} - }, - Node::Stmt(stmt) => match stmt.kind { - StmtKind::Local(_) => break, - _ => {} - }, + Node::Item(_) + | Node::ForeignItem(_) + | Node::TraitItem(_) + | Node::ImplItem(_) + | Node::Stmt(Stmt { kind: StmtKind::Local(_), .. }) => break, + Node::Expr(expr @ Expr { kind: ExprKind::Match(..), .. }) => return Some(expr), _ => {} } } @@ -784,32 +679,22 @@ impl<'hir> Map<'hir> { /// Returns the nearest enclosing scope. A scope is roughly an item or block. pub fn get_enclosing_scope(&self, hir_id: HirId) -> Option { for (hir_id, node) in self.parent_iter(hir_id) { - if match node { - Node::Item(i) => match i.kind { + if let Node::Item(Item { + kind: ItemKind::Fn(..) | ItemKind::Mod(..) | ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::Trait(..) - | ItemKind::Impl { .. } => true, - _ => false, - }, - Node::ForeignItem(fi) => match fi.kind { - ForeignItemKind::Fn(..) => true, - _ => false, - }, - Node::TraitItem(ti) => match ti.kind { - TraitItemKind::Fn(..) => true, - _ => false, - }, - Node::ImplItem(ii) => match ii.kind { - ImplItemKind::Method(..) => true, - _ => false, - }, - Node::Block(_) => true, - _ => false, - } { + | ItemKind::Impl { .. }, + .. + }) + | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(..), .. }) + | Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(..), .. }) + | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(..), .. }) + | Node::Block(_) = node + { return Some(hir_id); } } @@ -825,17 +710,18 @@ impl<'hir> Map<'hir> { return CRATE_HIR_ID; } match self.get(scope) { - Node::Item(i) => match i.kind { - ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: None, .. }) => {} - _ => break, - }, - Node::Block(_) => {} + Node::Item(Item { + kind: ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: None, .. }), + .. + }) + | Node::Block(_) => {} _ => break, } } scope } + // FIXME(eddyb) this function can and should return `LocalDefId`. pub fn get_parent_did(&self, id: HirId) -> DefId { self.local_def_id(self.get_parent_item(id)) } @@ -847,7 +733,6 @@ impl<'hir> Map<'hir> { node: Node::Item(Item { kind: ItemKind::ForeignMod(ref nm), .. }), .. } = entry { - self.read(hir_id); // reveals some of the content of a node return nm.abi; } } @@ -856,7 +741,6 @@ impl<'hir> Map<'hir> { pub fn expect_item(&self, id: HirId) -> &'hir Item<'hir> { match self.find(id) { - // read recorded by `find` Some(Node::Item(item)) => item, _ => bug!("expected item, found {}", self.node_to_string(id)), } @@ -878,14 +762,11 @@ impl<'hir> Map<'hir> { pub fn expect_variant_data(&self, id: HirId) -> &'hir VariantData<'hir> { match self.find(id) { - Some(Node::Item(i)) => match i.kind { - ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => { - struct_def - } - _ => bug!("struct ID bound to non-struct {}", self.node_to_string(id)), - }, + Some( + Node::Ctor(vd) + | Node::Item(Item { kind: ItemKind::Struct(vd, _) | ItemKind::Union(vd, _), .. }), + ) => vd, Some(Node::Variant(variant)) => &variant.data, - Some(Node::Ctor(data)) => data, _ => bug!("expected struct or variant, found {}", self.node_to_string(id)), } } @@ -906,7 +787,6 @@ impl<'hir> Map<'hir> { pub fn expect_expr(&self, id: HirId) -> &'hir Expr<'hir> { match self.find(id) { - // read recorded by find Some(Node::Expr(expr)) => expr, _ => bug!("expected expr, found {}", self.node_to_string(id)), } @@ -938,7 +818,6 @@ impl<'hir> Map<'hir> { /// Given a node ID, gets a list of attributes associated with the AST /// corresponding to the node-ID. pub fn attrs(&self, id: HirId) -> &'hir [ast::Attribute] { - self.read(id); // reveals attributes on the node let attrs = match self.find_entry(id).map(|entry| entry.node) { Some(Node::Param(a)) => Some(&a.attrs[..]), Some(Node::Local(l)) => Some(&l.attrs[..]), @@ -955,53 +834,13 @@ impl<'hir> Map<'hir> { // Unit/tuple structs/variants take the attributes straight from // the struct/variant definition. Some(Node::Ctor(..)) => return self.attrs(self.get_parent_item(id)), - Some(Node::Crate) => Some(&self.krate.attrs[..]), + Some(Node::Crate(item)) => Some(&item.attrs[..]), _ => None, }; attrs.unwrap_or(&[]) } - /// Returns an iterator that yields all the hir ids in the map. - fn all_ids<'a>(&'a self) -> impl Iterator + 'a { - // This code is a bit awkward because the map is implemented as 2 levels of arrays, - // see the comment on `HirEntryMap`. - // Iterate over all the indices and return a reference to - // local maps and their index given that they exist. - self.map.iter_enumerated().flat_map(move |(owner, local_map)| { - // Iterate over each valid entry in the local map. - local_map.iter_enumerated().filter_map(move |(i, entry)| { - entry.map(move |_| { - // Reconstruct the `HirId` based on the 3 indices we used to find it. - HirId { owner, local_id: i } - }) - }) - }) - } - - /// Returns an iterator that yields the node id's with paths that - /// match `parts`. (Requires `parts` is non-empty.) - /// - /// For example, if given `parts` equal to `["bar", "quux"]`, then - /// the iterator will produce node id's for items with paths - /// such as `foo::bar::quux`, `bar::quux`, `other::bar::quux`, and - /// any other such items it can find in the map. - pub fn nodes_matching_suffix<'a>( - &'a self, - parts: &'a [String], - ) -> impl Iterator + 'a { - let nodes = NodesMatchingSuffix { - map: self, - item_name: parts.last().unwrap(), - in_which: &parts[..parts.len() - 1], - }; - - self.all_ids() - .filter(move |hir| nodes.matches_suffix(*hir)) - .map(move |hir| self.hir_to_node_id(hir)) - } - pub fn span(&self, hir_id: HirId) -> Span { - self.read(hir_id); // reveals span from node match self.find_entry(hir_id).map(|entry| entry.node) { Some(Node::Param(param)) => param.span, Some(Node::Item(item)) => item.span, @@ -1034,7 +873,7 @@ impl<'hir> Map<'hir> { Some(Node::Visibility(v)) => bug!("unexpected Visibility {:?}", v), Some(Node::Local(local)) => local.span, Some(Node::MacroDef(macro_def)) => macro_def.span, - Some(Node::Crate) => self.krate.span, + Some(Node::Crate(item)) => item.span, None => bug!("hir::map::Map::span: id not in map: {:?}", hir_id), } } @@ -1082,82 +921,6 @@ impl<'hir> intravisit::Map<'hir> for Map<'hir> { } } -pub struct NodesMatchingSuffix<'a> { - map: &'a Map<'a>, - item_name: &'a String, - in_which: &'a [String], -} - -impl<'a> NodesMatchingSuffix<'a> { - /// Returns `true` only if some suffix of the module path for parent - /// matches `self.in_which`. - /// - /// In other words: let `[x_0,x_1,...,x_k]` be `self.in_which`; - /// returns true if parent's path ends with the suffix - /// `x_0::x_1::...::x_k`. - fn suffix_matches(&self, parent: HirId) -> bool { - let mut cursor = parent; - for part in self.in_which.iter().rev() { - let (mod_id, mod_name) = match find_first_mod_parent(self.map, cursor) { - None => return false, - Some((node_id, name)) => (node_id, name), - }; - if mod_name.as_str() != *part { - return false; - } - cursor = self.map.get_parent_item(mod_id); - } - return true; - - // Finds the first mod in parent chain for `id`, along with - // that mod's name. - // - // If `id` itself is a mod named `m` with parent `p`, then - // returns `Some(id, m, p)`. If `id` has no mod in its parent - // chain, then returns `None`. - fn find_first_mod_parent(map: &Map<'_>, mut id: HirId) -> Option<(HirId, Name)> { - loop { - if let Node::Item(item) = map.find(id)? { - if item_is_mod(&item) { - return Some((id, item.ident.name)); - } - } - let parent = map.get_parent_item(id); - if parent == id { - return None; - } - id = parent; - } - - fn item_is_mod(item: &Item<'_>) -> bool { - match item.kind { - ItemKind::Mod(_) => true, - _ => false, - } - } - } - } - - // We are looking at some node `n` with a given name and parent - // id; do their names match what I am seeking? - fn matches_names(&self, parent_of_n: HirId, name: Name) -> bool { - name.as_str() == *self.item_name && self.suffix_matches(parent_of_n) - } - - fn matches_suffix(&self, hir: HirId) -> bool { - let name = match self.map.find_entry(hir).map(|entry| entry.node) { - Some(Node::Item(n)) => n.name(), - Some(Node::ForeignItem(n)) => n.name(), - Some(Node::TraitItem(n)) => n.name(), - Some(Node::ImplItem(n)) => n.name(), - Some(Node::Variant(n)) => n.name(), - Some(Node::Field(n)) => n.name(), - _ => return false, - }; - self.matches_names(self.map.get_parent_item(hir), name) - } -} - trait Named { fn name(&self) -> Name; } @@ -1199,41 +962,24 @@ impl Named for ImplItem<'_> { } } -pub fn map_crate<'hir>( - sess: &rustc_session::Session, - cstore: &CrateStoreDyn, - krate: &'hir Crate<'hir>, - dep_graph: DepGraph, - definitions: Definitions, -) -> Map<'hir> { - let _prof_timer = sess.prof.generic_activity("build_hir_map"); - - // Build the reverse mapping of `node_to_hir_id`. - let hir_to_node_id = definitions - .node_to_hir_id - .iter_enumerated() - .map(|(node_id, &hir_id)| (hir_id, node_id)) - .collect(); +pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> &'tcx IndexedHir<'tcx> { + assert_eq!(cnum, LOCAL_CRATE); + + let _prof_timer = tcx.sess.prof.generic_activity("build_hir_map"); let (map, crate_hash) = { - let hcx = crate::ich::StableHashingContext::new(sess, krate, &definitions, cstore); + let hcx = tcx.create_stable_hashing_context(); let mut collector = - NodeCollector::root(sess, krate, &dep_graph, &definitions, &hir_to_node_id, hcx); - intravisit::walk_crate(&mut collector, krate); + NodeCollector::root(tcx.sess, &**tcx.arena, tcx.untracked_crate, &tcx.definitions, hcx); + intravisit::walk_crate(&mut collector, tcx.untracked_crate); - let crate_disambiguator = sess.local_crate_disambiguator(); - let cmdline_args = sess.opts.dep_tracking_hash(); - collector.finalize_and_compute_crate_hash(crate_disambiguator, cstore, cmdline_args) + let crate_disambiguator = tcx.sess.local_crate_disambiguator(); + let cmdline_args = tcx.sess.opts.dep_tracking_hash(); + collector.finalize_and_compute_crate_hash(crate_disambiguator, &*tcx.cstore, cmdline_args) }; - let map = Map { krate, dep_graph, crate_hash, map, hir_to_node_id, definitions }; - - sess.time("validate_HIR_map", || { - hir_id_validator::check_crate(&map, sess); - }); - - map + tcx.arena.alloc(IndexedHir { crate_hash, map }) } /// Identical to the `PpAnn` implementation for `hir::Crate`, @@ -1300,7 +1046,7 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { ImplItemKind::Const(..) => { format!("assoc const {} in {}{}", ii.ident, path_str(), id_str) } - ImplItemKind::Method(..) => format!("method {} in {}{}", ii.ident, path_str(), id_str), + ImplItemKind::Fn(..) => format!("method {} in {}{}", ii.ident, path_str(), id_str), ImplItemKind::TyAlias(_) => { format!("assoc type {} in {}{}", ii.ident, path_str(), id_str) } @@ -1342,7 +1088,7 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { Some(Node::GenericParam(ref param)) => format!("generic_param {:?}{}", param, id_str), Some(Node::Visibility(ref vis)) => format!("visibility {:?}{}", vis, id_str), Some(Node::MacroDef(_)) => format!("macro {}{}", path_str(), id_str), - Some(Node::Crate) => String::from("root_crate"), + Some(Node::Crate(..)) => String::from("root_crate"), None => format!("unknown node{}", id_str), } } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 30c9a2ee769fb..ce8e1f48daa77 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -5,58 +5,81 @@ pub mod exports; pub mod map; +use crate::ich::StableHashingContext; use crate::ty::query::Providers; use crate::ty::TyCtxt; -use rustc_hir::def_id::{DefId, LOCAL_CRATE}; -use rustc_hir::print; -use rustc_hir::Crate; +use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE}; +use rustc_hir::Body; use rustc_hir::HirId; -use std::ops::Deref; +use rustc_hir::ItemLocalId; +use rustc_hir::Node; +use rustc_index::vec::IndexVec; -/// A wrapper type which allows you to access HIR. -#[derive(Clone)] -pub struct Hir<'tcx> { - tcx: TyCtxt<'tcx>, - map: &'tcx map::Map<'tcx>, +pub struct Owner<'tcx> { + parent: HirId, + node: Node<'tcx>, } -impl<'tcx> Hir<'tcx> { - pub fn krate(&self) -> &'tcx Crate<'tcx> { - self.tcx.hir_crate(LOCAL_CRATE) +impl<'a, 'tcx> HashStable> for Owner<'tcx> { + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + let Owner { parent, node } = self; + hcx.while_hashing_hir_bodies(false, |hcx| { + parent.hash_stable(hcx, hasher); + node.hash_stable(hcx, hasher); + }); } } -impl<'tcx> Deref for Hir<'tcx> { - type Target = &'tcx map::Map<'tcx>; +#[derive(Clone)] +pub struct ParentedNode<'tcx> { + parent: ItemLocalId, + node: Node<'tcx>, +} - #[inline(always)] - fn deref(&self) -> &Self::Target { - &self.map - } +pub struct OwnerNodes<'tcx> { + hash: Fingerprint, + nodes: IndexVec>>, + bodies: FxHashMap>, } -impl<'hir> print::PpAnn for Hir<'hir> { - fn nested(&self, state: &mut print::State<'_>, nested: print::Nested) { - self.map.nested(state, nested) +impl<'a, 'tcx> HashStable> for OwnerNodes<'tcx> { + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + // We ignore the `nodes` and `bodies` fields since these refer to information included in + // `hash` which is hashed in the collector and used for the crate hash. + let OwnerNodes { hash, nodes: _, bodies: _ } = *self; + hash.hash_stable(hcx, hasher); } } impl<'tcx> TyCtxt<'tcx> { #[inline(always)] - pub fn hir(self) -> Hir<'tcx> { - Hir { tcx: self, map: &self.hir_map } + pub fn hir(self) -> map::Map<'tcx> { + map::Map { tcx: self } } - pub fn parent_module(self, id: HirId) -> DefId { - self.parent_module_from_def_id(DefId::local(id.owner)) + pub fn parent_module(self, id: HirId) -> LocalDefId { + self.parent_module_from_def_id(id.owner) } } pub fn provide(providers: &mut Providers<'_>) { providers.parent_module_from_def_id = |tcx, id| { let hir = tcx.hir(); - hir.local_def_id(hir.get_module_parent_node(hir.as_local_hir_id(id).unwrap())) + hir.local_def_id(hir.get_module_parent_node(hir.as_local_hir_id(id.to_def_id()).unwrap())) + .expect_local() + }; + providers.hir_crate = |tcx, _| tcx.untracked_crate; + providers.index_hir = map::index_hir; + providers.hir_module_items = |tcx, id| { + let hir = tcx.hir(); + let module = hir.as_local_hir_id(id.to_def_id()).unwrap(); + &tcx.untracked_crate.modules[&module] }; - providers.hir_crate = |tcx, _| tcx.hir_map.untracked_krate(); + providers.hir_owner = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].signature; + providers.hir_owner_nodes = + |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].with_bodies.as_ref().map(|nodes| &**nodes); map::provide(providers); } diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index f28e26ef2c396..a9466e8252de7 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -1,19 +1,18 @@ -use crate::hir::map::definitions::Definitions; -use crate::hir::map::DefPathHash; -use crate::ich::{self, CachingSourceMapView}; +use crate::ich; use crate::middle::cstore::CrateStore; -use crate::session::Session; use crate::ty::{fast_reject, TyCtxt}; use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, DefIndex}; +use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::definitions::{DefPathHash, Definitions}; +use rustc_session::Session; use rustc_span::source_map::SourceMap; use rustc_span::symbol::Symbol; -use rustc_span::{BytePos, SourceFile}; +use rustc_span::{BytePos, CachingSourceMapView, SourceFile}; use smallvec::SmallVec; use std::cmp::Ord; @@ -124,16 +123,16 @@ impl<'a> StableHashingContext<'a> { #[inline] pub fn def_path_hash(&self, def_id: DefId) -> DefPathHash { - if def_id.is_local() { - self.definitions.def_path_hash(def_id.index) + if let Some(def_id) = def_id.as_local() { + self.local_def_path_hash(def_id) } else { self.cstore.def_path_hash(def_id) } } #[inline] - pub fn local_def_path_hash(&self, def_index: DefIndex) -> DefPathHash { - self.definitions.def_path_hash(def_index) + pub fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash { + self.definitions.def_path_hash(def_id) } #[inline] @@ -164,15 +163,6 @@ impl<'a> StableHashingContext<'a> { } IGNORED_ATTRIBUTES.with(|attrs| attrs.contains(&name)) } - - pub fn hash_hir_item_like(&mut self, f: F) { - let prev_hash_node_ids = self.node_id_hashing_mode; - self.node_id_hashing_mode = NodeIdHashingMode::Ignore; - - f(self); - - self.node_id_hashing_mode = prev_hash_node_ids; - } } /// Something that can provide a stable hashing context. @@ -206,19 +196,6 @@ impl<'a> StableHashingContextProvider<'a> for StableHashingContext<'a> { impl<'a> crate::dep_graph::DepGraphSafe for StableHashingContext<'a> {} -impl<'a> ToStableHashKey> for hir::HirId { - type KeyType = (DefPathHash, hir::ItemLocalId); - - #[inline] - fn to_stable_hash_key( - &self, - hcx: &StableHashingContext<'a>, - ) -> (DefPathHash, hir::ItemLocalId) { - let def_path_hash = hcx.local_def_path_hash(self.owner); - (def_path_hash, self.local_id) - } -} - impl<'a> HashStable> for ast::NodeId { fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) { panic!("Node IDs should not appear in incremental state"); diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index eadc9ddeee6fc..f668cc99754f4 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -1,12 +1,13 @@ //! This module contains `HashStable` implementations for various HIR data //! types in no particular order. -use crate::hir::map::DefPathHash; -use crate::ich::{Fingerprint, NodeIdHashingMode, StableHashingContext}; +use crate::ich::{NodeIdHashingMode, StableHashingContext}; use rustc_attr as attr; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX}; +use rustc_hir::definitions::DefPathHash; use smallvec::SmallVec; use std::mem; @@ -105,6 +106,20 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { } } } + + fn hash_hir_item_like(&mut self, f: F) { + let prev_hash_node_ids = self.node_id_hashing_mode; + self.node_id_hashing_mode = NodeIdHashingMode::Ignore; + + f(self); + + self.node_id_hashing_mode = prev_hash_node_ids; + } + + #[inline] + fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash { + self.local_def_path_hash(def_id) + } } impl<'a> ToStableHashKey> for DefId { @@ -158,59 +173,6 @@ impl<'a> ToStableHashKey> for hir::ItemLocalId { } } -impl<'a> HashStable> for hir::TraitItem<'_> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let hir::TraitItem { hir_id: _, ident, ref attrs, ref generics, ref kind, span } = *self; - - hcx.hash_hir_item_like(|hcx| { - ident.name.hash_stable(hcx, hasher); - attrs.hash_stable(hcx, hasher); - generics.hash_stable(hcx, hasher); - kind.hash_stable(hcx, hasher); - span.hash_stable(hcx, hasher); - }); - } -} - -impl<'a> HashStable> for hir::ImplItem<'_> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let hir::ImplItem { - hir_id: _, - ident, - ref vis, - defaultness, - ref attrs, - ref generics, - ref kind, - span, - } = *self; - - hcx.hash_hir_item_like(|hcx| { - ident.name.hash_stable(hcx, hasher); - vis.hash_stable(hcx, hasher); - defaultness.hash_stable(hcx, hasher); - attrs.hash_stable(hcx, hasher); - generics.hash_stable(hcx, hasher); - kind.hash_stable(hcx, hasher); - span.hash_stable(hcx, hasher); - }); - } -} - -impl<'a> HashStable> for hir::Item<'_> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let hir::Item { ident, ref attrs, hir_id: _, ref kind, ref vis, span } = *self; - - hcx.hash_hir_item_like(|hcx| { - ident.name.hash_stable(hcx, hasher); - attrs.hash_stable(hcx, hasher); - kind.hash_stable(hcx, hasher); - vis.hash_stable(hcx, hasher); - span.hash_stable(hcx, hasher); - }); - } -} - impl<'a> HashStable> for hir::Body<'_> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let hir::Body { params, value, generator_kind } = self; @@ -236,21 +198,6 @@ impl<'a> ToStableHashKey> for hir::BodyId { } } -impl<'a> HashStable> for hir::def_id::DefIndex { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - hcx.local_def_path_hash(*self).hash_stable(hcx, hasher); - } -} - -impl<'a> ToStableHashKey> for hir::def_id::DefIndex { - type KeyType = DefPathHash; - - #[inline] - fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash { - hcx.local_def_path_hash(*self) - } -} - impl<'a> HashStable> for hir::TraitCandidate { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index daff8a0f1825e..c5a4b53b10df8 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -5,7 +5,6 @@ use crate::ich::StableHashingContext; use rustc_ast::ast; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX}; use rustc_span::SourceFile; use smallvec::SmallVec; @@ -59,7 +58,7 @@ impl<'a> HashStable> for SourceFile { name_hash, name_was_remapped, unmapped_path: _, - crate_of_origin, + cnum, // Do not hash the source as it is not encoded src: _, src_hash, @@ -75,9 +74,6 @@ impl<'a> HashStable> for SourceFile { (name_hash as u64).hash_stable(hcx, hasher); name_was_remapped.hash_stable(hcx, hasher); - DefId { krate: CrateNum::from_u32(crate_of_origin), index: CRATE_DEF_INDEX } - .hash_stable(hcx, hasher); - src_hash.hash_stable(hcx, hasher); // We only hash the relative position within this source_file @@ -101,6 +97,8 @@ impl<'a> HashStable> for SourceFile { for &char_pos in normalized_pos.iter() { stable_normalized_pos(char_pos, start_pos).hash_stable(hcx, hasher); } + + cnum.hash_stable(hcx, hasher); } } diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 844250f51a099..41cc8cbaebb6e 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -1,10 +1,11 @@ //! This module contains `HashStable` implementations for various data types //! from rustc::ty in no particular order. -use crate::ich::{Fingerprint, NodeIdHashingMode, StableHashingContext}; +use crate::ich::{NodeIdHashingMode, StableHashingContext}; use crate::middle::region; use crate::mir; use crate::ty; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; use std::cell::RefCell; @@ -92,9 +93,6 @@ impl<'a> HashStable> for ty::RegionKind { ty::ReFree(ref free_region) => { free_region.hash_stable(hcx, hasher); } - ty::ReClosureBound(vid) => { - vid.hash_stable(hcx, hasher); - } ty::ReVar(..) | ty::RePlaceholder(..) => { bug!("StableHasher: unexpected region {:?}", *self) } diff --git a/src/librustc/ich/mod.rs b/src/librustc/ich/mod.rs index 2c4618dcd42cf..516e3ed979c7c 100644 --- a/src/librustc/ich/mod.rs +++ b/src/librustc/ich/mod.rs @@ -3,7 +3,6 @@ pub use self::hcx::{ hash_stable_trait_impls, NodeIdHashingMode, StableHashingContext, StableHashingContextProvider, }; -crate use rustc_data_structures::fingerprint::Fingerprint; use rustc_span::symbol::{sym, Symbol}; pub use rustc_span::CachingSourceMapView; diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 24237235e0c4a..6f18560a02d7f 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -26,6 +26,9 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(const_if_match)] +#![feature(const_fn)] +#![feature(const_panic)] #![feature(const_transmute)] #![feature(core_intrinsics)] #![feature(drain_filter)] @@ -35,6 +38,7 @@ #![feature(extern_types)] #![feature(nll)] #![feature(option_expect_none)] +#![feature(or_patterns)] #![feature(range_is_empty)] #![feature(specialization)] #![feature(trusted_len)] @@ -80,7 +84,6 @@ pub mod infer; pub mod lint; pub mod middle; pub mod mir; -pub use rustc_session as session; pub mod traits; pub mod ty; diff --git a/src/librustc/lint.rs b/src/librustc/lint.rs index dcc8dcbf21961..53061436de07a 100644 --- a/src/librustc/lint.rs +++ b/src/librustc/lint.rs @@ -3,9 +3,9 @@ use std::cmp; use crate::ich::StableHashingContext; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_errors::{pluralize, Applicability, DiagnosticBuilder, DiagnosticId}; +use rustc_errors::{DiagnosticBuilder, DiagnosticId}; use rustc_hir::HirId; -pub use rustc_session::lint::{builtin, Level, Lint, LintId, LintPass}; +use rustc_session::lint::{builtin, Level, Lint, LintId}; use rustc_session::{DiagnosticMessageId, Session}; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::{DesugaringKind, ExpnKind, MultiSpan}; @@ -85,7 +85,7 @@ impl LintLevelSets { level = cmp::min(*driver_level, level); } - return (level, src); + (level, src) } pub fn get_lint_id_level( @@ -350,45 +350,3 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool { ExpnKind::Macro(..) => true, // definitely a plugin } } - -pub fn add_elided_lifetime_in_path_suggestion( - sess: &Session, - db: &mut DiagnosticBuilder<'_>, - n: usize, - path_span: Span, - incl_angl_brckt: bool, - insertion_span: Span, - anon_lts: String, -) { - let (replace_span, suggestion) = if incl_angl_brckt { - (insertion_span, anon_lts) - } else { - // When possible, prefer a suggestion that replaces the whole - // `Path` expression with `Path<'_, T>`, rather than inserting `'_, ` - // at a point (which makes for an ugly/confusing label) - if let Ok(snippet) = sess.source_map().span_to_snippet(path_span) { - // But our spans can get out of whack due to macros; if the place we think - // we want to insert `'_` isn't even within the path expression's span, we - // should bail out of making any suggestion rather than panicking on a - // subtract-with-overflow or string-slice-out-out-bounds (!) - // FIXME: can we do better? - if insertion_span.lo().0 < path_span.lo().0 { - return; - } - let insertion_index = (insertion_span.lo().0 - path_span.lo().0) as usize; - if insertion_index > snippet.len() { - return; - } - let (before, after) = snippet.split_at(insertion_index); - (path_span, format!("{}{}{}", before, anon_lts, after)) - } else { - (insertion_span, anon_lts) - } - }; - db.span_suggestion( - replace_span, - &format!("indicate the anonymous lifetime{}", pluralize!(n)), - suggestion, - Applicability::MachineApplicable, - ); -} diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 42d56c654627a..012390e8f74b8 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -2,10 +2,8 @@ //! are *mostly* used as a part of that interface, but these should //! probably get a better home if someone can find one. -use crate::hir::map as hir_map; -use crate::hir::map::definitions::{DefKey, DefPathTable}; -use crate::session::search_paths::PathKind; -use crate::session::CrateDisambiguator; +pub use self::NativeLibraryKind::*; + use crate::ty::TyCtxt; use rustc_ast::ast; @@ -13,16 +11,18 @@ use rustc_ast::expand::allocator::AllocatorKind; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{self, MetadataRef}; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; +use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, DefPathTable}; use rustc_macros::HashStable; +use rustc_session::search_paths::PathKind; +pub use rustc_session::utils::NativeLibraryKind; +use rustc_session::CrateDisambiguator; use rustc_span::symbol::Symbol; use rustc_span::Span; use rustc_target::spec::Target; + use std::any::Any; use std::path::{Path, PathBuf}; -pub use self::NativeLibraryKind::*; -pub use rustc_session::utils::NativeLibraryKind; - // lonely orphan structs and enums looking for a better home /// Where a crate came from on the local filesystem. One of these three options @@ -40,18 +40,8 @@ impl CrateSource { } } -#[derive( - RustcEncodable, - RustcDecodable, - Copy, - Clone, - Ord, - PartialOrd, - Eq, - PartialEq, - Debug, - HashStable -)] +#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)] +#[derive(HashStable)] pub enum DepKind { /// A dependency that is only used for its macros. MacrosOnly, @@ -197,8 +187,8 @@ pub trait CrateStore { // resolve fn def_key(&self, def: DefId) -> DefKey; - fn def_path(&self, def: DefId) -> hir_map::DefPath; - fn def_path_hash(&self, def: DefId) -> hir_map::DefPathHash; + fn def_path(&self, def: DefId) -> DefPath; + fn def_path_hash(&self, def: DefId) -> DefPathHash; fn def_path_table(&self, cnum: CrateNum) -> &DefPathTable; // "queries" used in resolve that aren't tracked for incremental compilation diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index 6ece51fe86674..ee5f822d3134c 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -4,7 +4,7 @@ //! For all the gory details, see the provider of the `dependency_formats` //! query. -use crate::session::config; +use rustc_session::config; /// A list of dependencies for a certain crate type. /// diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index c8e284be6fc09..36560371587a5 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -57,8 +57,7 @@ pub fn whitelisted(tcx: TyCtxt<'_>, lang_item: LangItem) -> bool { // symbols. Other panic runtimes ensure that the relevant symbols are // available to link things together, but they're never exercised. if tcx.sess.panic_strategy() != PanicStrategy::Unwind { - return lang_item == LangItem::EhPersonalityLangItem - || lang_item == LangItem::EhUnwindResumeLangItem; + return lang_item == LangItem::EhPersonalityLangItem; } false diff --git a/src/librustc/middle/limits.rs b/src/librustc/middle/limits.rs index 22e4f5ea22261..6de53c703e165 100644 --- a/src/librustc/middle/limits.rs +++ b/src/librustc/middle/limits.rs @@ -5,13 +5,13 @@ //! this via an attribute on the crate like `#![recursion_limit="22"]`. This pass //! just peeks and looks for that attribute. -use crate::session::Session; -use core::num::IntErrorKind; use rustc::bug; use rustc_ast::ast; +use rustc_data_structures::sync::Once; +use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; -use rustc_data_structures::sync::Once; +use std::num::IntErrorKind; pub fn update_limits(sess: &Session, krate: &ast::Crate) { update_limit(sess, krate, &sess.recursion_limit, sym::recursion_limit, 128); diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 758ba4a1ab013..73251ee2680df 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -9,7 +9,6 @@ use crate::ich::{NodeIdHashingMode, StableHashingContext}; use crate::ty::{self, DefIdTree, TyCtxt}; use rustc_hir as hir; -use rustc_hir::def_id::DefId; use rustc_hir::Node; use rustc_data_structures::fx::FxHashMap; @@ -81,18 +80,8 @@ use std::fmt; // placate the same deriving in `ty::FreeRegion`, but we may want to // actually attach a more meaningful ordering to scopes than the one // generated via deriving here. -#[derive( - Clone, - PartialEq, - PartialOrd, - Eq, - Ord, - Hash, - Copy, - RustcEncodable, - RustcDecodable, - HashStable -)] +#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy, RustcEncodable, RustcDecodable)] +#[derive(HashStable)] pub struct Scope { pub id: hir::ItemLocalId, pub data: ScopeData, @@ -115,19 +104,8 @@ impl fmt::Debug for Scope { } } -#[derive( - Clone, - PartialEq, - PartialOrd, - Eq, - Ord, - Hash, - Debug, - Copy, - RustcEncodable, - RustcDecodable, - HashStable -)] +#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, RustcEncodable, RustcDecodable)] +#[derive(HashStable)] pub enum ScopeData { Node, @@ -468,7 +446,7 @@ impl<'tcx> ScopeTree { } debug!("temporary_scope({:?}) = None", expr_id); - return None; + None } /// Returns the lifetime of the variable `id`. @@ -499,7 +477,7 @@ impl<'tcx> ScopeTree { debug!("is_subscope_of({:?}, {:?})=true", subscope, superscope); - return true; + true } /// Returns the ID of the innermost containing body. @@ -594,7 +572,7 @@ impl<'tcx> ScopeTree { region scope tree for {:?} / {:?}", param_owner, self.root_parent.map(|id| tcx.hir().local_def_id(id)), - self.root_body.map(|hir_id| DefId::local(hir_id.owner)) + self.root_body.map(|hir_id| hir_id.owner) ), ); } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 048e24ce3aa89..46525bdedad35 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -3,7 +3,6 @@ pub use self::StabilityLevel::*; -use crate::session::{DiagnosticMessageId, Session}; use crate::ty::{self, TyCtxt}; use rustc_ast::ast::CRATE_NODE_ID; use rustc_attr::{self as attr, ConstStability, Deprecation, RustcDeprecation, Stability}; @@ -17,6 +16,7 @@ use rustc_hir::{self, HirId}; use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE}; use rustc_session::lint::{BuiltinLintDiagnostics, Lint, LintBuffer}; use rustc_session::parse::feature_err_issue; +use rustc_session::{DiagnosticMessageId, Session}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{MultiSpan, Span}; diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 546ba586d30f9..ada02ceb5cbf3 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -1,32 +1,24 @@ //! The virtual memory representation of the MIR interpreter. +use std::borrow::Cow; +use std::convert::TryFrom; +use std::iter; +use std::ops::{Deref, DerefMut, Range}; + +use rustc_ast::ast::Mutability; +use rustc_data_structures::sorted_map::SortedMap; +use rustc_target::abi::HasDataLayout; + use super::{ read_target_uint, write_target_uint, AllocId, InterpResult, Pointer, Scalar, ScalarMaybeUndef, }; use crate::ty::layout::{Align, Size}; -use rustc_ast::ast::Mutability; -use rustc_data_structures::sorted_map::SortedMap; -use rustc_target::abi::HasDataLayout; -use std::borrow::Cow; -use std::iter; -use std::ops::{Deref, DerefMut, Range}; - // NOTE: When adding new fields, make sure to adjust the `Snapshot` impl in // `src/librustc_mir/interpret/snapshot.rs`. -#[derive( - Clone, - Debug, - Eq, - PartialEq, - PartialOrd, - Ord, - Hash, - RustcEncodable, - RustcDecodable, - HashStable -)] +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] +#[derive(HashStable)] pub struct Allocation { /// The actual bytes of the allocation. /// Note that the bytes of a pointer represent the offset of the pointer. @@ -41,6 +33,7 @@ pub struct Allocation { /// The size of the allocation. Currently, must always equal `bytes.len()`. pub size: Size, /// The alignment of the allocation to detect unaligned reads. + /// (`Align` guarantees that this is a power of two.) pub align: Align, /// `true` if the allocation is mutable. /// Also used by codegen to determine if a static should be put into mutable memory, @@ -99,7 +92,7 @@ impl Allocation { /// Creates a read-only allocation initialized by the given bytes pub fn from_bytes<'a>(slice: impl Into>, align: Align) -> Self { let bytes = slice.into().into_owned(); - let size = Size::from_bytes(bytes.len() as u64); + let size = Size::from_bytes(bytes.len()); Self { bytes, relocations: Relocations::new(), @@ -116,9 +109,8 @@ impl Allocation { } pub fn undef(size: Size, align: Align) -> Self { - assert_eq!(size.bytes() as usize as u64, size.bytes()); Allocation { - bytes: vec![0; size.bytes() as usize], + bytes: vec![0; size.bytes_usize()], relocations: Relocations::new(), undef_mask: UndefMask::new(size, false), size, @@ -161,7 +153,7 @@ impl Allocation<(), ()> { /// Raw accessors. Provide access to otherwise private bytes. impl Allocation { pub fn len(&self) -> usize { - self.size.bytes() as usize + self.size.bytes_usize() } /// Looks at a slice which may describe undefined bytes or describe a relocation. This differs @@ -192,12 +184,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { #[inline] fn check_bounds(&self, offset: Size, size: Size) -> Range { let end = offset + size; // This does overflow checking. - assert_eq!( - end.bytes() as usize as u64, - end.bytes(), - "cannot handle this access on this host architecture" - ); - let end = end.bytes() as usize; + let end = usize::try_from(end.bytes()).expect("access too big for this host architecture"); assert!( end <= self.len(), "Out-of-bounds access at offset {}, size {} in allocation of size {}", @@ -205,7 +192,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { size.bytes(), self.len() ); - (offset.bytes() as usize)..end + offset.bytes_usize()..end } /// The last argument controls whether we error out when there are undefined @@ -303,18 +290,17 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { cx: &impl HasDataLayout, ptr: Pointer, ) -> InterpResult<'tcx, &[u8]> { - assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes()); - let offset = ptr.offset.bytes() as usize; + let offset = ptr.offset.bytes_usize(); Ok(match self.bytes[offset..].iter().position(|&c| c == 0) { Some(size) => { - let size_with_null = Size::from_bytes((size + 1) as u64); + let size_with_null = Size::from_bytes(size) + Size::from_bytes(1); // Go through `get_bytes` for checks and AllocationExtra hooks. // We read the null, so we include it in the request, but we want it removed // from the result, so we do subslicing. &self.get_bytes(cx, ptr, size_with_null)?[..size] } // This includes the case where `offset` is out-of-bounds to begin with. - None => throw_unsup!(UnterminatedCString(ptr.erase_tag())), + None => throw_ub!(UnterminatedCString(ptr.erase_tag())), }) } @@ -352,7 +338,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { let (lower, upper) = src.size_hint(); let len = upper.expect("can only write bounded iterators"); assert_eq!(lower, len, "can only write iterators with a precise length"); - let bytes = self.get_bytes_mut(cx, ptr, Size::from_bytes(len as u64))?; + let bytes = self.get_bytes_mut(cx, ptr, Size::from_bytes(len))?; // `zip` would stop when the first iterator ends; we want to definitely // cover all of `bytes`. for dest in bytes { @@ -381,7 +367,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { let bytes = self.get_bytes_with_undef_and_ptr(cx, ptr, size)?; // Undef check happens *after* we established that the alignment is correct. // We must not return `Ok()` for unaligned pointers! - if self.check_defined(ptr, size).is_err() { + if self.is_defined(ptr, size).is_err() { // This inflates undefined bytes to the entire scalar, even if only a few // bytes are undefined. return Ok(ScalarMaybeUndef::Undef); @@ -395,7 +381,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { } else { match self.relocations.get(&ptr.offset) { Some(&(tag, alloc_id)) => { - let ptr = Pointer::new_with_tag(alloc_id, Size::from_bytes(bits as u64), tag); + let ptr = Pointer::new_with_tag(alloc_id, Size::from_bytes(bits), tag); return Ok(ScalarMaybeUndef::Scalar(ptr.into())); } None => {} @@ -442,7 +428,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { }; let bytes = match val.to_bits_or_ptr(type_size, cx) { - Err(val) => val.offset.bytes() as u128, + Err(val) => u128::from(val.offset.bytes()), Ok(data) => data, }; @@ -533,7 +519,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { ) }; let start = ptr.offset; - let end = start + size; + let end = start + size; // `Size` addition // Mark parts of the outermost relocations as undefined if they partially fall outside the // given range. @@ -566,14 +552,20 @@ impl<'tcx, Tag: Copy, Extra> Allocation { } /// Undefined bytes. -impl<'tcx, Tag, Extra> Allocation { +impl<'tcx, Tag: Copy, Extra> Allocation { + /// Checks whether the given range is entirely defined. + /// + /// Returns `Ok(())` if it's defined. Otherwise returns the index of the byte + /// at which the first undefined access begins. + fn is_defined(&self, ptr: Pointer, size: Size) -> Result<(), Size> { + self.undef_mask.is_range_defined(ptr.offset, ptr.offset + size) // `Size` addition + } + /// Checks that a range of bytes is defined. If not, returns the `ReadUndefBytes` /// error which will report the first byte which is undefined. - #[inline] fn check_defined(&self, ptr: Pointer, size: Size) -> InterpResult<'tcx> { - self.undef_mask - .is_range_defined(ptr.offset, ptr.offset + size) - .or_else(|idx| throw_unsup!(ReadUndefBytes(idx))) + self.is_defined(ptr, size) + .or_else(|idx| throw_ub!(InvalidUndefBytes(Some(Pointer::new(ptr.alloc_id, idx))))) } pub fn mark_definedness(&mut self, ptr: Pointer, size: Size, new_state: bool) { @@ -652,7 +644,7 @@ impl Allocation { if defined.ranges.len() <= 1 { self.undef_mask.set_range_inbounds( dest.offset, - dest.offset + size * repeat, + dest.offset + size * repeat, // `Size` operations defined.initial, ); return; @@ -730,10 +722,10 @@ impl Allocation { for i in 0..length { new_relocations.extend(relocations.iter().map(|&(offset, reloc)| { // compute offset for current repetition - let dest_offset = dest.offset + (i * size); + let dest_offset = dest.offset + size * i; // `Size` operations ( // shift offsets from source allocation to destination allocation - offset + dest_offset - src.offset, + (offset + dest_offset) - src.offset, // `Size` operations reloc, ) })); @@ -758,18 +750,8 @@ type Block = u64; /// A bitmask where each bit refers to the byte with the same index. If the bit is `true`, the byte /// is defined. If it is `false` the byte is undefined. -#[derive( - Clone, - Debug, - Eq, - PartialEq, - PartialOrd, - Ord, - Hash, - RustcEncodable, - RustcDecodable, - HashStable -)] +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] +#[derive(HashStable)] pub struct UndefMask { blocks: Vec, len: Size, @@ -795,7 +777,7 @@ impl UndefMask { } // FIXME(oli-obk): optimize this for allocations larger than a block. - let idx = (start.bytes()..end.bytes()).map(|i| Size::from_bytes(i)).find(|&i| !self.get(i)); + let idx = (start.bytes()..end.bytes()).map(Size::from_bytes).find(|&i| !self.get(i)); match idx { Some(idx) => Err(idx), @@ -880,18 +862,18 @@ impl UndefMask { if amount.bytes() == 0 { return; } - let unused_trailing_bits = self.blocks.len() as u64 * Self::BLOCK_SIZE - self.len.bytes(); + let unused_trailing_bits = + u64::try_from(self.blocks.len()).unwrap() * Self::BLOCK_SIZE - self.len.bytes(); if amount.bytes() > unused_trailing_bits { let additional_blocks = amount.bytes() / Self::BLOCK_SIZE + 1; - assert_eq!(additional_blocks as usize as u64, additional_blocks); self.blocks.extend( // FIXME(oli-obk): optimize this by repeating `new_state as Block`. - iter::repeat(0).take(additional_blocks as usize), + iter::repeat(0).take(usize::try_from(additional_blocks).unwrap()), ); } let start = self.len; self.len += amount; - self.set_range_inbounds(start, start + amount, new_state); + self.set_range_inbounds(start, start + amount, new_state); // `Size` operation } } @@ -900,7 +882,5 @@ fn bit_index(bits: Size) -> (usize, usize) { let bits = bits.bytes(); let a = bits / UndefMask::BLOCK_SIZE; let b = bits % UndefMask::BLOCK_SIZE; - assert_eq!(a as usize as u64, a); - assert_eq!(b as usize as u64, b); - (a as usize, b as usize) + (usize::try_from(a).unwrap(), usize::try_from(b).unwrap()) } diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 0b33408edf02d..c46ab89d0049c 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -1,7 +1,5 @@ -use super::{CheckInAllocMsg, Pointer, RawConst, ScalarMaybeUndef}; +use super::{AllocId, CheckInAllocMsg, Pointer, RawConst, ScalarMaybeUndef}; -use crate::hir::map::definitions::DefPathData; -use crate::mir; use crate::mir::interpret::ConstValue; use crate::ty::layout::{Align, LayoutError, Size}; use crate::ty::query::TyCtxtAt; @@ -12,11 +10,11 @@ use backtrace::Backtrace; use rustc_data_structures::sync::Lock; use rustc_errors::{struct_span_err, DiagnosticBuilder}; use rustc_hir as hir; +use rustc_hir::definitions::DefPathData; use rustc_macros::HashStable; use rustc_session::CtfeBacktrace; -use rustc_span::{Pos, Span}; -use rustc_target::spec::abi::Abi; -use std::{any::Any, fmt}; +use rustc_span::{def_id::DefId, Pos, Span}; +use std::{any::Any, fmt, mem}; #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable)] pub enum ErrorHandled { @@ -296,6 +294,8 @@ pub enum InvalidProgramInfo<'tcx> { TypeckError, /// An error occurred during layout computation. Layout(layout::LayoutError<'tcx>), + /// An invalid transmute happened. + TransmuteSizeDiff(Ty<'tcx>, Ty<'tcx>), } impl fmt::Debug for InvalidProgramInfo<'_> { @@ -306,6 +306,11 @@ impl fmt::Debug for InvalidProgramInfo<'_> { ReferencedConstant => write!(f, "referenced constant has errors"), TypeckError => write!(f, "encountered constants with type errors, stopping evaluation"), Layout(ref err) => write!(f, "{}", err), + TransmuteSizeDiff(from_ty, to_ty) => write!( + f, + "tried to transmute from {:?} to {:?}, but their sizes differed", + from_ty, to_ty + ), } } } @@ -314,14 +319,15 @@ impl fmt::Debug for InvalidProgramInfo<'_> { pub enum UndefinedBehaviorInfo { /// Free-form case. Only for errors that are never caught! Ub(String), - /// Free-form case for experimental UB. Only for errors that are never caught! - UbExperimental(String), /// Unreachable code was executed. Unreachable, /// An enum discriminant was set to a value which was outside the range of valid values. InvalidDiscriminant(ScalarMaybeUndef), /// A slice/array index projection went out-of-bounds. - BoundsCheckFailed { len: u64, index: u64 }, + BoundsCheckFailed { + len: u64, + index: u64, + }, /// Something was divided by 0 (x / 0). DivisionByZero, /// Something was "remainded" by 0 (x % 0). @@ -330,13 +336,50 @@ pub enum UndefinedBehaviorInfo { PointerArithOverflow, /// Invalid metadata in a wide pointer (using `str` to avoid allocations). InvalidMeta(&'static str), + /// Reading a C string that does not end within its allocation. + UnterminatedCString(Pointer), + /// Dereferencing a dangling pointer after it got freed. + PointerUseAfterFree(AllocId), + /// Used a pointer outside the bounds it is valid for. + PointerOutOfBounds { + ptr: Pointer, + msg: CheckInAllocMsg, + allocation_size: Size, + }, + /// Used a pointer with bad alignment. + AlignmentCheckFailed { + required: Align, + has: Align, + }, + /// Using an integer as a pointer in the wrong way. + InvalidIntPointerUsage(u64), + /// Writing to read-only memory. + WriteToReadOnly(AllocId), + /// Using a pointer-not-to-a-function as function pointer. + InvalidFunctionPointer(Pointer), + // Trying to access the data behind a function pointer. + DerefFunctionPointer(AllocId), + /// The value validity check found a problem. + /// Should only be thrown by `validity.rs` and always point out which part of the value + /// is the problem. + ValidationFailure(String), + /// Using a non-boolean `u8` as bool. + InvalidBool(u8), + /// Using a non-character `u32` as character. + InvalidChar(u32), + /// Using uninitialized data where it is not allowed. + InvalidUndefBytes(Option), + /// Working with a local that is not currently live. + DeadLocal, + /// Trying to read from the return place of a function. + ReadFromReturnPlace, } impl fmt::Debug for UndefinedBehaviorInfo { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use UndefinedBehaviorInfo::*; match self { - Ub(msg) | UbExperimental(msg) => write!(f, "{}", msg), + Ub(msg) => write!(f, "{}", msg), Unreachable => write!(f, "entering unreachable code"), InvalidDiscriminant(val) => write!(f, "encountering invalid enum discriminant {}", val), BoundsCheckFailed { ref len, ref index } => write!( @@ -348,6 +391,50 @@ impl fmt::Debug for UndefinedBehaviorInfo { RemainderByZero => write!(f, "calculating the remainder with a divisor of zero"), PointerArithOverflow => write!(f, "overflowing in-bounds pointer arithmetic"), InvalidMeta(msg) => write!(f, "invalid metadata in wide pointer: {}", msg), + UnterminatedCString(p) => write!( + f, + "reading a null-terminated string starting at {:?} with no null found before end of allocation", + p, + ), + PointerUseAfterFree(a) => { + write!(f, "pointer to {:?} was dereferenced after this allocation got freed", a) + } + PointerOutOfBounds { ptr, msg, allocation_size } => write!( + f, + "{} failed: pointer must be in-bounds at offset {}, \ + but is outside bounds of {} which has size {}", + msg, + ptr.offset.bytes(), + ptr.alloc_id, + allocation_size.bytes() + ), + InvalidIntPointerUsage(0) => write!(f, "invalid use of NULL pointer"), + InvalidIntPointerUsage(i) => write!(f, "invalid use of {} as a pointer", i), + AlignmentCheckFailed { required, has } => write!( + f, + "accessing memory with alignment {}, but alignment {} is required", + has.bytes(), + required.bytes() + ), + WriteToReadOnly(a) => write!(f, "writing to {:?} which is read-only", a), + InvalidFunctionPointer(p) => { + write!(f, "using {:?} as function pointer but it does not point to a function", p) + } + DerefFunctionPointer(a) => write!(f, "accessing {:?} which contains a function", a), + ValidationFailure(ref err) => write!(f, "type validation failed: {}", err), + InvalidBool(b) => write!(f, "interpreting an invalid 8-bit value as a bool: {}", b), + InvalidChar(c) => write!(f, "interpreting an invalid 32-bit value as a char: {}", c), + InvalidUndefBytes(Some(p)) => write!( + f, + "reading uninitialized memory at {:?}, but this operation requires initialized memory", + p + ), + InvalidUndefBytes(None) => write!( + f, + "using uninitialized data, but this operation requires initialized memory" + ), + DeadLocal => write!(f, "accessing a dead local variable"), + ReadFromReturnPlace => write!(f, "tried to read from the return place"), } } } @@ -359,203 +446,30 @@ impl fmt::Debug for UndefinedBehaviorInfo { /// /// Currently, we also use this as fall-back error kind for errors that have not been /// categorized yet. -pub enum UnsupportedOpInfo<'tcx> { +pub enum UnsupportedOpInfo { /// Free-form case. Only for errors that are never caught! Unsupported(String), - - /// When const-prop encounters a situation it does not support, it raises this error. - /// This must not allocate for performance reasons (hence `str`, not `String`). - ConstPropUnsupported(&'static str), - - // -- Everything below is not categorized yet -- - FunctionAbiMismatch(Abi, Abi), - FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>), - FunctionRetMismatch(Ty<'tcx>, Ty<'tcx>), - FunctionArgCountMismatch, - UnterminatedCString(Pointer), - DanglingPointerDeref, - DoubleFree, - InvalidMemoryAccess, - InvalidFunctionPointer, - InvalidBool, - PointerOutOfBounds { - ptr: Pointer, - msg: CheckInAllocMsg, - allocation_size: Size, - }, - InvalidNullPointerUsage, + /// Accessing an unsupported foreign static. + ReadForeignStatic(DefId), + /// Could not find MIR for a function. + NoMirFor(DefId), + /// Encountered a pointer where we needed raw bytes. ReadPointerAsBytes, + /// Encountered raw bytes where we needed a pointer. ReadBytesAsPointer, - ReadForeignStatic, - InvalidPointerMath, - ReadUndefBytes(Size), - DeadLocal, - InvalidBoolOp(mir::BinOp), - UnimplementedTraitSelection, - CalledClosureAsFunction, - NoMirFor(String), - DerefFunctionPointer, - ExecuteMemory, - InvalidChar(u128), - OutOfTls, - TlsOutOfBounds, - AlignmentCheckFailed { - required: Align, - has: Align, - }, - ValidationFailure(String), - VtableForArgumentlessMethod, - ModifiedConstantMemory, - ModifiedStatic, - TypeNotPrimitive(Ty<'tcx>), - ReallocatedWrongMemoryKind(String, String), - DeallocatedWrongMemoryKind(String, String), - ReallocateNonBasePtr, - DeallocateNonBasePtr, - IncorrectAllocationInformation(Size, Size, Align, Align), - HeapAllocZeroBytes, - HeapAllocNonPowerOfTwoAlignment(u64), - ReadFromReturnPointer, - PathNotFound(Vec), - TransmuteSizeDiff(Ty<'tcx>, Ty<'tcx>), } -impl fmt::Debug for UnsupportedOpInfo<'tcx> { +impl fmt::Debug for UnsupportedOpInfo { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use UnsupportedOpInfo::*; match self { - PointerOutOfBounds { ptr, msg, allocation_size } => write!( - f, - "{} failed: pointer must be in-bounds at offset {}, \ - but is outside bounds of allocation {} which has size {}", - msg, - ptr.offset.bytes(), - ptr.alloc_id, - allocation_size.bytes() - ), - ValidationFailure(ref err) => write!(f, "type validation failed: {}", err), - NoMirFor(ref func) => write!(f, "no MIR for `{}`", func), - FunctionAbiMismatch(caller_abi, callee_abi) => write!( - f, - "tried to call a function with ABI {:?} using caller ABI {:?}", - callee_abi, caller_abi - ), - FunctionArgMismatch(caller_ty, callee_ty) => write!( - f, - "tried to call a function with argument of type {:?} \ - passing data of type {:?}", - callee_ty, caller_ty - ), - TransmuteSizeDiff(from_ty, to_ty) => write!( - f, - "tried to transmute from {:?} to {:?}, but their sizes differed", - from_ty, to_ty - ), - FunctionRetMismatch(caller_ty, callee_ty) => write!( - f, - "tried to call a function with return type {:?} \ - passing return place of type {:?}", - callee_ty, caller_ty - ), - FunctionArgCountMismatch => { - write!(f, "tried to call a function with incorrect number of arguments") - } - ReallocatedWrongMemoryKind(ref old, ref new) => { - write!(f, "tried to reallocate memory from `{}` to `{}`", old, new) - } - DeallocatedWrongMemoryKind(ref old, ref new) => { - write!(f, "tried to deallocate `{}` memory but gave `{}` as the kind", old, new) - } - InvalidChar(c) => { - write!(f, "tried to interpret an invalid 32-bit value as a char: {}", c) - } - AlignmentCheckFailed { required, has } => write!( - f, - "tried to access memory with alignment {}, but alignment {} is required", - has.bytes(), - required.bytes() - ), - TypeNotPrimitive(ty) => write!(f, "expected primitive type, got {}", ty), - PathNotFound(ref path) => write!(f, "cannot find path {:?}", path), - IncorrectAllocationInformation(size, size2, align, align2) => write!( - f, - "incorrect alloc info: expected size {} and align {}, \ - got size {} and align {}", - size.bytes(), - align.bytes(), - size2.bytes(), - align2.bytes() - ), - InvalidMemoryAccess => write!(f, "tried to access memory through an invalid pointer"), - DanglingPointerDeref => write!(f, "dangling pointer was dereferenced"), - DoubleFree => write!(f, "tried to deallocate dangling pointer"), - InvalidFunctionPointer => { - write!(f, "tried to use a function pointer after offsetting it") - } - InvalidBool => write!(f, "invalid boolean value read"), - InvalidNullPointerUsage => write!(f, "invalid use of NULL pointer"), - ReadPointerAsBytes => write!( - f, - "a raw memory access tried to access part of a pointer value as raw \ - bytes" - ), - ReadBytesAsPointer => { - write!(f, "a memory access tried to interpret some bytes as a pointer") - } - ReadForeignStatic => write!(f, "tried to read from foreign (extern) static"), - InvalidPointerMath => write!( - f, - "attempted to do invalid arithmetic on pointers that would leak base \ - addresses, e.g., comparing pointers into different allocations" - ), - DeadLocal => write!(f, "tried to access a dead local variable"), - DerefFunctionPointer => write!(f, "tried to dereference a function pointer"), - ExecuteMemory => write!(f, "tried to treat a memory pointer as a function pointer"), - OutOfTls => write!(f, "reached the maximum number of representable TLS keys"), - TlsOutOfBounds => write!(f, "accessed an invalid (unallocated) TLS key"), - CalledClosureAsFunction => { - write!(f, "tried to call a closure through a function pointer") - } - VtableForArgumentlessMethod => { - write!(f, "tried to call a vtable function without arguments") - } - ModifiedConstantMemory => write!(f, "tried to modify constant memory"), - ModifiedStatic => write!( - f, - "tried to modify a static's initial value from another static's \ - initializer" - ), - ReallocateNonBasePtr => write!( - f, - "tried to reallocate with a pointer not to the beginning of an \ - existing object" - ), - DeallocateNonBasePtr => write!( - f, - "tried to deallocate with a pointer not to the beginning of an \ - existing object" - ), - HeapAllocZeroBytes => write!(f, "tried to re-, de- or allocate zero bytes on the heap"), - ReadFromReturnPointer => write!(f, "tried to read from the return pointer"), - UnimplementedTraitSelection => { - write!(f, "there were unresolved type arguments during trait selection") - } - InvalidBoolOp(_) => write!(f, "invalid boolean operation"), - UnterminatedCString(_) => write!( - f, - "attempted to get length of a null-terminated string, but no null \ - found before end of allocation" - ), - ReadUndefBytes(_) => write!(f, "attempted to read undefined bytes"), - HeapAllocNonPowerOfTwoAlignment(_) => write!( - f, - "tried to re-, de-, or allocate heap memory with alignment that is \ - not a power of two" - ), Unsupported(ref msg) => write!(f, "{}", msg), - ConstPropUnsupported(ref msg) => { - write!(f, "Constant propagation encountered an unsupported situation: {}", msg) + ReadForeignStatic(did) => { + write!(f, "tried to read from foreign (extern) static {:?}", did) } + NoMirFor(did) => write!(f, "could not load MIR for {:?}", did), + ReadPointerAsBytes => write!(f, "unable to turn pointer into raw bytes",), + ReadBytesAsPointer => write!(f, "unable to turn bytes into a pointer"), } } } @@ -565,8 +479,10 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> { pub enum ResourceExhaustionInfo { /// The stack grew too big. StackFrameLimitReached, - /// The program ran into an infinite loop. - InfiniteLoop, + /// The program ran for too long. + /// + /// The exact limit is set by the `const_eval_limit` attribute. + StepLimitReached, } impl fmt::Debug for ResourceExhaustionInfo { @@ -576,21 +492,42 @@ impl fmt::Debug for ResourceExhaustionInfo { StackFrameLimitReached => { write!(f, "reached the configured maximum number of stack frames") } - InfiniteLoop => write!( - f, - "duplicate interpreter state observed here, const evaluation will never \ - terminate" - ), + StepLimitReached => { + write!(f, "exceeded interpreter step limit (see `#[const_eval_limit]`)") + } } } } +/// A trait to work around not having trait object upcasting. +pub trait AsAny: Any { + fn as_any(&self) -> &dyn Any; +} + +impl AsAny for T { + #[inline(always)] + fn as_any(&self) -> &dyn Any { + self + } +} + +/// A trait for machine-specific errors (or other "machine stop" conditions). +pub trait MachineStopType: AsAny + fmt::Debug + Send {} +impl MachineStopType for String {} + +impl dyn MachineStopType { + #[inline(always)] + pub fn downcast_ref(&self) -> Option<&T> { + self.as_any().downcast_ref() + } +} + pub enum InterpError<'tcx> { /// The program caused undefined behavior. UndefinedBehavior(UndefinedBehaviorInfo), /// The program did something the interpreter does not support (some of these *might* be UB /// but the interpreter is not sure). - Unsupported(UnsupportedOpInfo<'tcx>), + Unsupported(UnsupportedOpInfo), /// The program was invalid (ill-typed, bad MIR, not sufficiently monomorphized, ...). InvalidProgram(InvalidProgramInfo<'tcx>), /// The program exhausted the interpreter's resources (stack/heap too big, @@ -598,7 +535,7 @@ pub enum InterpError<'tcx> { ResourceExhaustion(ResourceExhaustionInfo), /// Stop execution for a machine-controlled reason. This is never raised by /// the core engine itself. - MachineStop(Box), + MachineStop(Box), } pub type InterpResult<'tcx, T = ()> = Result>; @@ -606,7 +543,7 @@ pub type InterpResult<'tcx, T = ()> = Result>; impl fmt::Display for InterpError<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // Forward `Display` to `Debug`. - write!(f, "{:?}", self) + fmt::Debug::fmt(self, f) } } @@ -618,7 +555,7 @@ impl fmt::Debug for InterpError<'_> { InvalidProgram(ref msg) => write!(f, "{:?}", msg), UndefinedBehavior(ref msg) => write!(f, "{:?}", msg), ResourceExhaustion(ref msg) => write!(f, "{:?}", msg), - MachineStop(_) => bug!("unhandled MachineStop"), + MachineStop(ref msg) => write!(f, "{:?}", msg), } } } @@ -629,11 +566,11 @@ impl InterpError<'_> { /// waste of resources. pub fn allocates(&self) -> bool { match self { - InterpError::MachineStop(_) - | InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_)) - | InterpError::Unsupported(UnsupportedOpInfo::ValidationFailure(_)) - | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_)) - | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::UbExperimental(_)) => true, + // Zero-sized boxes do not allocate. + InterpError::MachineStop(b) => mem::size_of_val::(&**b) > 0, + InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_)) + | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure(_)) + | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_)) => true, _ => false, } } diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index 64c07b431db38..10c3a06da0810 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -46,9 +46,17 @@ macro_rules! err_exhaust { }; } +#[macro_export] +macro_rules! err_machine_stop { + ($($tt:tt)*) => { + $crate::mir::interpret::InterpError::MachineStop(Box::new($($tt)*)) + }; +} + +// In the `throw_*` macros, avoid `return` to make them work with `try {}`. #[macro_export] macro_rules! throw_unsup { - ($($tt:tt)*) => { return Err(err_unsup!($($tt)*).into()) }; + ($($tt:tt)*) => { Err::(err_unsup!($($tt)*))? }; } #[macro_export] @@ -58,12 +66,12 @@ macro_rules! throw_unsup_format { #[macro_export] macro_rules! throw_inval { - ($($tt:tt)*) => { return Err(err_inval!($($tt)*).into()) }; + ($($tt:tt)*) => { Err::(err_inval!($($tt)*))? }; } #[macro_export] macro_rules! throw_ub { - ($($tt:tt)*) => { return Err(err_ub!($($tt)*).into()) }; + ($($tt:tt)*) => { Err::(err_ub!($($tt)*))? }; } #[macro_export] @@ -73,14 +81,12 @@ macro_rules! throw_ub_format { #[macro_export] macro_rules! throw_exhaust { - ($($tt:tt)*) => { return Err(err_exhaust!($($tt)*).into()) }; + ($($tt:tt)*) => { Err::(err_exhaust!($($tt)*))? }; } #[macro_export] macro_rules! throw_machine_stop { - ($($tt:tt)*) => { - return Err($crate::mir::interpret::InterpError::MachineStop(Box::new($($tt)*)).into()) - }; + ($($tt:tt)*) => { Err::(err_machine_stop!($($tt)*))? }; } mod allocation; @@ -89,23 +95,12 @@ mod pointer; mod queries; mod value; -pub use self::error::{ - struct_error, ConstEvalErr, ConstEvalRawResult, ConstEvalResult, ErrorHandled, FrameInfo, - InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo, ResourceExhaustionInfo, - UndefinedBehaviorInfo, UnsupportedOpInfo, -}; - -pub use self::value::{get_slice_bytes, ConstValue, RawConst, Scalar, ScalarMaybeUndef}; - -pub use self::allocation::{Allocation, AllocationExtra, Relocations, UndefMask}; - -pub use self::pointer::{CheckInAllocMsg, Pointer, PointerArithmetic}; +use std::convert::TryFrom; +use std::fmt; +use std::io; +use std::num::NonZeroU32; +use std::sync::atomic::{AtomicU32, Ordering}; -use crate::mir; -use crate::ty::codec::TyDecoder; -use crate::ty::layout::{self, Size}; -use crate::ty::subst::GenericArgKind; -use crate::ty::{self, Instance, Ty, TyCtxt}; use byteorder::{BigEndian, LittleEndian, ReadBytesExt, WriteBytesExt}; use rustc_ast::ast::LitKind; use rustc_data_structures::fx::FxHashMap; @@ -114,10 +109,24 @@ use rustc_data_structures::tiny_list::TinyList; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; use rustc_serialize::{Decodable, Encodable, Encoder}; -use std::fmt; -use std::io; -use std::num::NonZeroU32; -use std::sync::atomic::{AtomicU32, Ordering}; + +use crate::mir; +use crate::ty::codec::TyDecoder; +use crate::ty::layout::{self, Size}; +use crate::ty::subst::GenericArgKind; +use crate::ty::{self, Instance, Ty, TyCtxt}; + +pub use self::error::{ + struct_error, ConstEvalErr, ConstEvalRawResult, ConstEvalResult, ErrorHandled, FrameInfo, + InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo, MachineStopType, + ResourceExhaustionInfo, UndefinedBehaviorInfo, UnsupportedOpInfo, +}; + +pub use self::value::{get_slice_bytes, ConstValue, RawConst, Scalar, ScalarMaybeUndef}; + +pub use self::allocation::{Allocation, AllocationExtra, Relocations, UndefMask}; + +pub use self::pointer::{CheckInAllocMsg, Pointer, PointerArithmetic}; /// Uniquely identifies one of the following: /// - A constant @@ -150,7 +159,7 @@ pub struct LitToConstInput<'tcx> { pub enum LitToConstError { /// The literal's inferred type did not match the expected `ty` in the input. /// This is used for graceful error handling (`delay_span_bug`) in - /// type checking (`AstConv::ast_const_to_const`). + /// type checking (`Const::from_anon_const`). TypeError, UnparseableFloat, Reported, @@ -161,7 +170,13 @@ pub struct AllocId(pub u64); impl fmt::Debug for AllocId { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(fmt, "alloc{}", self.0) + fmt::Display::fmt(self, fmt) + } +} + +impl fmt::Display for AllocId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "alloc{}", self.0) } } @@ -252,8 +267,8 @@ impl<'s> AllocDecodingSession<'s> { D: TyDecoder<'tcx>, { // Read the index of the allocation. - let idx = decoder.read_u32()? as usize; - let pos = self.state.data_offsets[idx] as usize; + let idx = usize::try_from(decoder.read_u32()?).unwrap(); + let pos = usize::try_from(self.state.data_offsets[idx]).unwrap(); // Decode the `AllocDiscriminant` now so that we know if we have to reserve an // `AllocId`. @@ -351,12 +366,6 @@ impl<'s> AllocDecodingSession<'s> { } } -impl fmt::Display for AllocId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - /// An allocation in the global (tcx-managed) memory can be either a function pointer, /// a static, or a "real" allocation with some data in it. #[derive(Debug, Clone, Eq, PartialEq, Hash, RustcDecodable, RustcEncodable, HashStable)] diff --git a/src/librustc/mir/interpret/pointer.rs b/src/librustc/mir/interpret/pointer.rs index cc3c50b7899f3..3f841cfb33003 100644 --- a/src/librustc/mir/interpret/pointer.rs +++ b/src/librustc/mir/interpret/pointer.rs @@ -62,9 +62,9 @@ pub trait PointerArithmetic: layout::HasDataLayout { /// This should be called by all the other methods before returning! #[inline] fn truncate_to_ptr(&self, (val, over): (u64, bool)) -> (u64, bool) { - let val = val as u128; + let val = u128::from(val); let max_ptr_plus_1 = 1u128 << self.pointer_size().bits(); - ((val % max_ptr_plus_1) as u64, over || val >= max_ptr_plus_1) + (u64::try_from(val % max_ptr_plus_1).unwrap(), over || val >= max_ptr_plus_1) } #[inline] @@ -73,10 +73,8 @@ pub trait PointerArithmetic: layout::HasDataLayout { self.truncate_to_ptr(res) } - // Overflow checking only works properly on the range from -u64 to +u64. #[inline] - fn overflowing_signed_offset(&self, val: u64, i: i128) -> (u64, bool) { - // FIXME: is it possible to over/underflow here? + fn overflowing_signed_offset(&self, val: u64, i: i64) -> (u64, bool) { if i < 0 { // Trickery to ensure that `i64::MIN` works fine: compute `n = -i`. // This formula only works for true negative values; it overflows for zero! @@ -84,6 +82,7 @@ pub trait PointerArithmetic: layout::HasDataLayout { let res = val.overflowing_sub(n); self.truncate_to_ptr(res) } else { + // `i >= 0`, so the cast is safe. self.overflowing_offset(val, i as u64) } } @@ -96,7 +95,7 @@ pub trait PointerArithmetic: layout::HasDataLayout { #[inline] fn signed_offset<'tcx>(&self, val: u64, i: i64) -> InterpResult<'tcx, u64> { - let (res, over) = self.overflowing_signed_offset(val, i128::from(i)); + let (res, over) = self.overflowing_signed_offset(val, i); if over { throw_ub!(PointerArithOverflow) } else { Ok(res) } } } @@ -111,18 +110,8 @@ impl PointerArithmetic for T {} /// /// `Pointer` is also generic over the `Tag` associated with each pointer, /// which is used to do provenance tracking during execution. -#[derive( - Copy, - Clone, - Eq, - PartialEq, - Ord, - PartialOrd, - RustcEncodable, - RustcDecodable, - Hash, - HashStable -)] +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)] +#[derive(HashStable)] pub struct Pointer { pub alloc_id: Id, pub offset: Size, @@ -199,34 +188,18 @@ impl<'tcx, Tag> Pointer { } #[inline] - pub fn overflowing_signed_offset(self, i: i128, cx: &impl HasDataLayout) -> (Self, bool) { + pub fn overflowing_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> (Self, bool) { let (res, over) = cx.data_layout().overflowing_signed_offset(self.offset.bytes(), i); (Pointer::new_with_tag(self.alloc_id, Size::from_bytes(res), self.tag), over) } #[inline(always)] pub fn wrapping_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> Self { - self.overflowing_signed_offset(i128::from(i), cx).0 + self.overflowing_signed_offset(i, cx).0 } #[inline(always)] pub fn erase_tag(self) -> Pointer { Pointer { alloc_id: self.alloc_id, offset: self.offset, tag: () } } - - /// Test if the pointer is "inbounds" of an allocation of the given size. - /// A pointer is "inbounds" even if its offset is equal to the size; this is - /// a "one-past-the-end" pointer. - #[inline(always)] - pub fn check_inbounds_alloc( - self, - allocation_size: Size, - msg: CheckInAllocMsg, - ) -> InterpResult<'tcx, ()> { - if self.offset > allocation_size { - throw_unsup!(PointerOutOfBounds { ptr: self.erase_tag(), msg, allocation_size }) - } else { - Ok(()) - } - } } diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 9dc0b24cd2f3f..706cf1cd09a79 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -1,9 +1,12 @@ +use std::convert::TryFrom; +use std::fmt; + use rustc_apfloat::{ ieee::{Double, Single}, Float, }; use rustc_macros::HashStable; -use std::fmt; +use rustc_target::abi::TargetDataLayout; use crate::ty::{ layout::{HasDataLayout, Size}, @@ -23,19 +26,8 @@ pub struct RawConst<'tcx> { /// Represents a constant value in Rust. `Scalar` and `Slice` are optimizations for /// array length computations, enum discriminants and the pattern matching logic. -#[derive( - Copy, - Clone, - Debug, - Eq, - PartialEq, - PartialOrd, - Ord, - RustcEncodable, - RustcDecodable, - Hash, - HashStable -)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)] +#[derive(HashStable)] pub enum ConstValue<'tcx> { /// Used only for types with `layout::abi::Scalar` ABI and ZSTs. /// @@ -98,18 +90,8 @@ impl<'tcx> ConstValue<'tcx> { /// `memory::Allocation`. It is in many ways like a small chunk of a `Allocation`, up to 8 bytes in /// size. Like a range of bytes in an `Allocation`, a `Scalar` can either represent the raw bytes /// of a simple value or a pointer into another `Allocation` -#[derive( - Clone, - Copy, - Eq, - PartialEq, - Ord, - PartialOrd, - RustcEncodable, - RustcDecodable, - Hash, - HashStable -)] +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)] +#[derive(HashStable)] pub enum Scalar { /// The raw bytes of a simple value. Raw { @@ -177,7 +159,7 @@ impl Scalar<()> { #[inline(always)] fn check_data(data: u128, size: u8) { debug_assert_eq!( - truncate(data, Size::from_bytes(size as u64)), + truncate(data, Size::from_bytes(u64::from(size))), data, "Scalar value {:#x} exceeds size of {} bytes", data, @@ -219,64 +201,65 @@ impl<'tcx, Tag> Scalar { Scalar::Raw { data: 0, size: 0 } } - #[inline] - pub fn ptr_offset(self, i: Size, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> { - let dl = cx.data_layout(); + #[inline(always)] + fn ptr_op( + self, + dl: &TargetDataLayout, + f_int: impl FnOnce(u64) -> InterpResult<'tcx, u64>, + f_ptr: impl FnOnce(Pointer) -> InterpResult<'tcx, Pointer>, + ) -> InterpResult<'tcx, Self> { match self { Scalar::Raw { data, size } => { - assert_eq!(size as u64, dl.pointer_size.bytes()); - Ok(Scalar::Raw { data: dl.offset(data as u64, i.bytes())? as u128, size }) + assert_eq!(u64::from(size), dl.pointer_size.bytes()); + Ok(Scalar::Raw { data: u128::from(f_int(u64::try_from(data).unwrap())?), size }) } - Scalar::Ptr(ptr) => ptr.offset(i, dl).map(Scalar::Ptr), + Scalar::Ptr(ptr) => Ok(Scalar::Ptr(f_ptr(ptr)?)), } } + #[inline] + pub fn ptr_offset(self, i: Size, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> { + let dl = cx.data_layout(); + self.ptr_op(dl, |int| dl.offset(int, i.bytes()), |ptr| ptr.offset(i, dl)) + } + #[inline] pub fn ptr_wrapping_offset(self, i: Size, cx: &impl HasDataLayout) -> Self { let dl = cx.data_layout(); - match self { - Scalar::Raw { data, size } => { - assert_eq!(size as u64, dl.pointer_size.bytes()); - Scalar::Raw { data: dl.overflowing_offset(data as u64, i.bytes()).0 as u128, size } - } - Scalar::Ptr(ptr) => Scalar::Ptr(ptr.wrapping_offset(i, dl)), - } + self.ptr_op( + dl, + |int| Ok(dl.overflowing_offset(int, i.bytes()).0), + |ptr| Ok(ptr.wrapping_offset(i, dl)), + ) + .unwrap() } #[inline] pub fn ptr_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> { let dl = cx.data_layout(); - match self { - Scalar::Raw { data, size } => { - assert_eq!(size as u64, dl.pointer_size().bytes()); - Ok(Scalar::Raw { data: dl.signed_offset(data as u64, i)? as u128, size }) - } - Scalar::Ptr(ptr) => ptr.signed_offset(i, dl).map(Scalar::Ptr), - } + self.ptr_op(dl, |int| dl.signed_offset(int, i), |ptr| ptr.signed_offset(i, dl)) } #[inline] pub fn ptr_wrapping_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> Self { let dl = cx.data_layout(); - match self { - Scalar::Raw { data, size } => { - assert_eq!(size as u64, dl.pointer_size.bytes()); - Scalar::Raw { - data: dl.overflowing_signed_offset(data as u64, i128::from(i)).0 as u128, - size, - } - } - Scalar::Ptr(ptr) => Scalar::Ptr(ptr.wrapping_signed_offset(i, dl)), - } + self.ptr_op( + dl, + |int| Ok(dl.overflowing_signed_offset(int, i).0), + |ptr| Ok(ptr.wrapping_signed_offset(i, dl)), + ) + .unwrap() } #[inline] pub fn from_bool(b: bool) -> Self { + // Guaranteed to be truncated and does not need sign extension. Scalar::Raw { data: b as u128, size: 1 } } #[inline] pub fn from_char(c: char) -> Self { + // Guaranteed to be truncated and does not need sign extension. Scalar::Raw { data: c as u128, size: 4 } } @@ -299,22 +282,26 @@ impl<'tcx, Tag> Scalar { #[inline] pub fn from_u8(i: u8) -> Self { - Scalar::Raw { data: i as u128, size: 1 } + // Guaranteed to be truncated and does not need sign extension. + Scalar::Raw { data: i.into(), size: 1 } } #[inline] pub fn from_u16(i: u16) -> Self { - Scalar::Raw { data: i as u128, size: 2 } + // Guaranteed to be truncated and does not need sign extension. + Scalar::Raw { data: i.into(), size: 2 } } #[inline] pub fn from_u32(i: u32) -> Self { - Scalar::Raw { data: i as u128, size: 4 } + // Guaranteed to be truncated and does not need sign extension. + Scalar::Raw { data: i.into(), size: 4 } } #[inline] pub fn from_u64(i: u64) -> Self { - Scalar::Raw { data: i as u128, size: 8 } + // Guaranteed to be truncated and does not need sign extension. + Scalar::Raw { data: i.into(), size: 8 } } #[inline] @@ -341,6 +328,26 @@ impl<'tcx, Tag> Scalar { .unwrap_or_else(|| bug!("Signed value {:#x} does not fit in {} bits", i, size.bits())) } + #[inline] + pub fn from_i8(i: i8) -> Self { + Self::from_int(i, Size::from_bits(8)) + } + + #[inline] + pub fn from_i16(i: i16) -> Self { + Self::from_int(i, Size::from_bits(16)) + } + + #[inline] + pub fn from_i32(i: i32) -> Self { + Self::from_int(i, Size::from_bits(32)) + } + + #[inline] + pub fn from_i64(i: i64) -> Self { + Self::from_int(i, Size::from_bits(64)) + } + #[inline] pub fn from_machine_isize(i: i64, cx: &impl HasDataLayout) -> Self { Self::from_int(i, cx.data_layout().pointer_size) @@ -371,7 +378,7 @@ impl<'tcx, Tag> Scalar { assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST"); match self { Scalar::Raw { data, size } => { - assert_eq!(target_size.bytes(), size as u64); + assert_eq!(target_size.bytes(), u64::from(size)); Scalar::check_data(data, size); Ok(data) } @@ -389,7 +396,7 @@ impl<'tcx, Tag> Scalar { assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST"); match self { Scalar::Raw { data, size } => { - assert_eq!(target_size.bytes(), size as u64); + assert_eq!(target_size.bytes(), u64::from(size)); Scalar::check_data(data, size); Ok(data) } @@ -429,10 +436,11 @@ impl<'tcx, Tag> Scalar { } pub fn to_bool(self) -> InterpResult<'tcx, bool> { - match self { - Scalar::Raw { data: 0, size: 1 } => Ok(false), - Scalar::Raw { data: 1, size: 1 } => Ok(true), - _ => throw_unsup!(InvalidBool), + let val = self.to_u8()?; + match val { + 0 => Ok(false), + 1 => Ok(true), + _ => throw_ub!(InvalidBool(val)), } } @@ -440,7 +448,7 @@ impl<'tcx, Tag> Scalar { let val = self.to_u32()?; match ::std::char::from_u32(val) { Some(c) => Ok(c), - None => throw_unsup!(InvalidChar(val as u128)), + None => throw_ub!(InvalidChar(val)), } } @@ -452,27 +460,27 @@ impl<'tcx, Tag> Scalar { /// Converts the scalar to produce an `u8`. Fails if the scalar is a pointer. pub fn to_u8(self) -> InterpResult<'static, u8> { - self.to_unsigned_with_bit_width(8).map(|v| v as u8) + self.to_unsigned_with_bit_width(8).map(|v| u8::try_from(v).unwrap()) } /// Converts the scalar to produce an `u16`. Fails if the scalar is a pointer. pub fn to_u16(self) -> InterpResult<'static, u16> { - self.to_unsigned_with_bit_width(16).map(|v| v as u16) + self.to_unsigned_with_bit_width(16).map(|v| u16::try_from(v).unwrap()) } /// Converts the scalar to produce an `u32`. Fails if the scalar is a pointer. pub fn to_u32(self) -> InterpResult<'static, u32> { - self.to_unsigned_with_bit_width(32).map(|v| v as u32) + self.to_unsigned_with_bit_width(32).map(|v| u32::try_from(v).unwrap()) } /// Converts the scalar to produce an `u64`. Fails if the scalar is a pointer. pub fn to_u64(self) -> InterpResult<'static, u64> { - self.to_unsigned_with_bit_width(64).map(|v| v as u64) + self.to_unsigned_with_bit_width(64).map(|v| u64::try_from(v).unwrap()) } pub fn to_machine_usize(self, cx: &impl HasDataLayout) -> InterpResult<'static, u64> { let b = self.to_bits(cx.data_layout().pointer_size)?; - Ok(b as u64) + Ok(u64::try_from(b).unwrap()) } #[inline] @@ -484,41 +492,41 @@ impl<'tcx, Tag> Scalar { /// Converts the scalar to produce an `i8`. Fails if the scalar is a pointer. pub fn to_i8(self) -> InterpResult<'static, i8> { - self.to_signed_with_bit_width(8).map(|v| v as i8) + self.to_signed_with_bit_width(8).map(|v| i8::try_from(v).unwrap()) } /// Converts the scalar to produce an `i16`. Fails if the scalar is a pointer. pub fn to_i16(self) -> InterpResult<'static, i16> { - self.to_signed_with_bit_width(16).map(|v| v as i16) + self.to_signed_with_bit_width(16).map(|v| i16::try_from(v).unwrap()) } /// Converts the scalar to produce an `i32`. Fails if the scalar is a pointer. pub fn to_i32(self) -> InterpResult<'static, i32> { - self.to_signed_with_bit_width(32).map(|v| v as i32) + self.to_signed_with_bit_width(32).map(|v| i32::try_from(v).unwrap()) } /// Converts the scalar to produce an `i64`. Fails if the scalar is a pointer. pub fn to_i64(self) -> InterpResult<'static, i64> { - self.to_signed_with_bit_width(64).map(|v| v as i64) + self.to_signed_with_bit_width(64).map(|v| i64::try_from(v).unwrap()) } pub fn to_machine_isize(self, cx: &impl HasDataLayout) -> InterpResult<'static, i64> { let sz = cx.data_layout().pointer_size; let b = self.to_bits(sz)?; let b = sign_extend(b, sz) as i128; - Ok(b as i64) + Ok(i64::try_from(b).unwrap()) } #[inline] pub fn to_f32(self) -> InterpResult<'static, Single> { // Going through `u32` to check size and truncation. - Ok(Single::from_bits(self.to_u32()? as u128)) + Ok(Single::from_bits(self.to_u32()?.into())) } #[inline] pub fn to_f64(self) -> InterpResult<'static, Double> { // Going through `u64` to check size and truncation. - Ok(Double::from_bits(self.to_u64()? as u128)) + Ok(Double::from_bits(self.to_u64()?.into())) } } @@ -583,7 +591,7 @@ impl<'tcx, Tag> ScalarMaybeUndef { pub fn not_undef(self) -> InterpResult<'static, Scalar> { match self { ScalarMaybeUndef::Scalar(scalar) => Ok(scalar), - ScalarMaybeUndef::Undef => throw_unsup!(ReadUndefBytes(Size::ZERO)), + ScalarMaybeUndef::Undef => throw_ub!(InvalidUndefBytes(None)), } } @@ -665,8 +673,8 @@ pub fn get_slice_bytes<'tcx>(cx: &impl HasDataLayout, val: ConstValue<'tcx>) -> data.get_bytes( cx, // invent a pointer, only the offset is relevant anyway - Pointer::new(AllocId(0), Size::from_bytes(start as u64)), - Size::from_bytes(len as u64), + Pointer::new(AllocId(0), Size::from_bytes(start)), + Size::from_bytes(len), ) .unwrap_or_else(|err| bug!("const slice is invalid: {:?}", err)) } else { diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index afb585c4aa339..1e47317cf1ace 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -45,6 +45,7 @@ pub mod mono; mod query; pub mod tcx; pub mod traversal; +mod type_foldable; pub mod visit; /// Types for locals @@ -69,18 +70,8 @@ impl<'tcx> HasLocalDecls<'tcx> for Body<'tcx> { /// The various "big phases" that MIR goes through. /// /// Warning: ordering of variants is significant. -#[derive( - Copy, - Clone, - RustcEncodable, - RustcDecodable, - HashStable, - Debug, - PartialEq, - Eq, - PartialOrd, - Ord -)] +#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(HashStable)] pub enum MirPhase { Build = 0, Const = 1, @@ -403,7 +394,7 @@ pub enum ClearCrossCrate { } impl ClearCrossCrate { - pub fn as_ref(&'a self) -> ClearCrossCrate<&'a T> { + pub fn as_ref(&self) -> ClearCrossCrate<&T> { match self { ClearCrossCrate::Clear => ClearCrossCrate::Clear, ClearCrossCrate::Set(v) => ClearCrossCrate::Set(v), @@ -439,18 +430,8 @@ pub struct SourceInfo { /////////////////////////////////////////////////////////////////////////// // Borrow kinds -#[derive( - Copy, - Clone, - Debug, - PartialEq, - Eq, - PartialOrd, - Ord, - RustcEncodable, - RustcDecodable, - HashStable -)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable)] +#[derive(HashStable)] pub enum BorrowKind { /// Data must be immutable and is aliasable. Shared, @@ -2066,7 +2047,7 @@ pub enum Rvalue<'tcx> { Use(Operand<'tcx>), /// [x; 32] - Repeat(Operand<'tcx>, u64), + Repeat(Operand<'tcx>, &'tcx ty::Const<'tcx>), /// &x or &mut x Ref(Region<'tcx>, BorrowKind, Place<'tcx>), @@ -2194,7 +2175,11 @@ impl<'tcx> Debug for Rvalue<'tcx> { match *self { Use(ref place) => write!(fmt, "{:?}", place), - Repeat(ref a, ref b) => write!(fmt, "[{:?}; {:?}]", a, b), + Repeat(ref a, ref b) => { + write!(fmt, "[{:?}; ", a)?; + pretty_print_const(b, fmt, false)?; + write!(fmt, "]") + } Len(ref a) => write!(fmt, "Len({:?})", a), Cast(ref kind, ref place, ref ty) => { write!(fmt, "{:?} as {:?} ({:?})", place, ty, kind) @@ -2503,7 +2488,7 @@ impl UserTypeProjection { pub(crate) fn variant( mut self, - adt_def: &'tcx AdtDef, + adt_def: &AdtDef, variant_index: VariantIdx, field: Field, ) -> Self { @@ -2563,17 +2548,25 @@ impl<'tcx> Debug for Constant<'tcx> { impl<'tcx> Display for Constant<'tcx> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { write!(fmt, "const ")?; - // FIXME make the default pretty printing of raw pointers more detailed. Here we output the - // debug representation of raw pointers, so that the raw pointers in the mir dump output are - // detailed and just not '{pointer}'. - if let ty::RawPtr(_) = self.literal.ty.kind { - write!(fmt, "{:?} : {}", self.literal.val, self.literal.ty) - } else { - write!(fmt, "{}", self.literal) - } + pretty_print_const(self.literal, fmt, true) } } +fn pretty_print_const( + c: &ty::Const<'tcx>, + fmt: &mut Formatter<'_>, + print_types: bool, +) -> fmt::Result { + use crate::ty::print::PrettyPrinter; + ty::tls::with(|tcx| { + let literal = tcx.lift(&c).unwrap(); + let mut cx = FmtPrinter::new(tcx, fmt, Namespace::ValueNS); + cx.print_alloc_ids = true; + cx.pretty_print_const(literal, print_types)?; + Ok(()) + }) +} + impl<'tcx> graph::DirectedGraph for Body<'tcx> { type Node = BasicBlock; } @@ -2671,325 +2664,3 @@ impl Location { } } } - -/* - * `TypeFoldable` implementations for MIR types -*/ - -CloneTypeFoldableAndLiftImpls! { - BlockTailInfo, - MirPhase, - SourceInfo, - FakeReadCause, - RetagKind, - SourceScope, - SourceScopeData, - SourceScopeLocalData, - UserTypeAnnotationIndex, -} - -impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { - fn super_fold_with>(&self, folder: &mut F) -> Self { - use crate::mir::TerminatorKind::*; - - let kind = match self.kind { - Goto { target } => Goto { target }, - SwitchInt { ref discr, switch_ty, ref values, ref targets } => SwitchInt { - discr: discr.fold_with(folder), - switch_ty: switch_ty.fold_with(folder), - values: values.clone(), - targets: targets.clone(), - }, - Drop { ref location, target, unwind } => { - Drop { location: location.fold_with(folder), target, unwind } - } - DropAndReplace { ref location, ref value, target, unwind } => DropAndReplace { - location: location.fold_with(folder), - value: value.fold_with(folder), - target, - unwind, - }, - Yield { ref value, resume, ref resume_arg, drop } => Yield { - value: value.fold_with(folder), - resume, - resume_arg: resume_arg.fold_with(folder), - drop, - }, - Call { ref func, ref args, ref destination, cleanup, from_hir_call } => { - let dest = - destination.as_ref().map(|&(ref loc, dest)| (loc.fold_with(folder), dest)); - - Call { - func: func.fold_with(folder), - args: args.fold_with(folder), - destination: dest, - cleanup, - from_hir_call, - } - } - Assert { ref cond, expected, ref msg, target, cleanup } => { - use AssertKind::*; - let msg = match msg { - BoundsCheck { ref len, ref index } => { - BoundsCheck { len: len.fold_with(folder), index: index.fold_with(folder) } - } - Overflow(_) - | OverflowNeg - | DivisionByZero - | RemainderByZero - | ResumedAfterReturn(_) - | ResumedAfterPanic(_) => msg.clone(), - }; - Assert { cond: cond.fold_with(folder), expected, msg, target, cleanup } - } - GeneratorDrop => GeneratorDrop, - Resume => Resume, - Abort => Abort, - Return => Return, - Unreachable => Unreachable, - FalseEdges { real_target, imaginary_target } => { - FalseEdges { real_target, imaginary_target } - } - FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind }, - }; - Terminator { source_info: self.source_info, kind } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - use crate::mir::TerminatorKind::*; - - match self.kind { - SwitchInt { ref discr, switch_ty, .. } => { - discr.visit_with(visitor) || switch_ty.visit_with(visitor) - } - Drop { ref location, .. } => location.visit_with(visitor), - DropAndReplace { ref location, ref value, .. } => { - location.visit_with(visitor) || value.visit_with(visitor) - } - Yield { ref value, .. } => value.visit_with(visitor), - Call { ref func, ref args, ref destination, .. } => { - let dest = if let Some((ref loc, _)) = *destination { - loc.visit_with(visitor) - } else { - false - }; - dest || func.visit_with(visitor) || args.visit_with(visitor) - } - Assert { ref cond, ref msg, .. } => { - if cond.visit_with(visitor) { - use AssertKind::*; - match msg { - BoundsCheck { ref len, ref index } => { - len.visit_with(visitor) || index.visit_with(visitor) - } - Overflow(_) - | OverflowNeg - | DivisionByZero - | RemainderByZero - | ResumedAfterReturn(_) - | ResumedAfterPanic(_) => false, - } - } else { - false - } - } - Goto { .. } - | Resume - | Abort - | Return - | GeneratorDrop - | Unreachable - | FalseEdges { .. } - | FalseUnwind { .. } => false, - } - } -} - -impl<'tcx> TypeFoldable<'tcx> for GeneratorKind { - fn super_fold_with>(&self, _: &mut F) -> Self { - *self - } - - fn super_visit_with>(&self, _: &mut V) -> bool { - false - } -} - -impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> { - fn super_fold_with>(&self, folder: &mut F) -> Self { - Place { local: self.local.fold_with(folder), projection: self.projection.fold_with(folder) } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.local.visit_with(visitor) || self.projection.visit_with(visitor) - } -} - -impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { - fn super_fold_with>(&self, folder: &mut F) -> Self { - let v = self.iter().map(|t| t.fold_with(folder)).collect::>(); - folder.tcx().intern_place_elems(&v) - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|t| t.visit_with(visitor)) - } -} - -impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { - fn super_fold_with>(&self, folder: &mut F) -> Self { - use crate::mir::Rvalue::*; - match *self { - Use(ref op) => Use(op.fold_with(folder)), - Repeat(ref op, len) => Repeat(op.fold_with(folder), len), - Ref(region, bk, ref place) => { - Ref(region.fold_with(folder), bk, place.fold_with(folder)) - } - AddressOf(mutability, ref place) => AddressOf(mutability, place.fold_with(folder)), - Len(ref place) => Len(place.fold_with(folder)), - Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)), - BinaryOp(op, ref rhs, ref lhs) => { - BinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)) - } - CheckedBinaryOp(op, ref rhs, ref lhs) => { - CheckedBinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)) - } - UnaryOp(op, ref val) => UnaryOp(op, val.fold_with(folder)), - Discriminant(ref place) => Discriminant(place.fold_with(folder)), - NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)), - Aggregate(ref kind, ref fields) => { - let kind = box match **kind { - AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)), - AggregateKind::Tuple => AggregateKind::Tuple, - AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt( - def, - v, - substs.fold_with(folder), - user_ty.fold_with(folder), - n, - ), - AggregateKind::Closure(id, substs) => { - AggregateKind::Closure(id, substs.fold_with(folder)) - } - AggregateKind::Generator(id, substs, movablity) => { - AggregateKind::Generator(id, substs.fold_with(folder), movablity) - } - }; - Aggregate(kind, fields.fold_with(folder)) - } - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - use crate::mir::Rvalue::*; - match *self { - Use(ref op) => op.visit_with(visitor), - Repeat(ref op, _) => op.visit_with(visitor), - Ref(region, _, ref place) => region.visit_with(visitor) || place.visit_with(visitor), - AddressOf(_, ref place) => place.visit_with(visitor), - Len(ref place) => place.visit_with(visitor), - Cast(_, ref op, ty) => op.visit_with(visitor) || ty.visit_with(visitor), - BinaryOp(_, ref rhs, ref lhs) | CheckedBinaryOp(_, ref rhs, ref lhs) => { - rhs.visit_with(visitor) || lhs.visit_with(visitor) - } - UnaryOp(_, ref val) => val.visit_with(visitor), - Discriminant(ref place) => place.visit_with(visitor), - NullaryOp(_, ty) => ty.visit_with(visitor), - Aggregate(ref kind, ref fields) => { - (match **kind { - AggregateKind::Array(ty) => ty.visit_with(visitor), - AggregateKind::Tuple => false, - AggregateKind::Adt(_, _, substs, user_ty, _) => { - substs.visit_with(visitor) || user_ty.visit_with(visitor) - } - AggregateKind::Closure(_, substs) => substs.visit_with(visitor), - AggregateKind::Generator(_, substs, _) => substs.visit_with(visitor), - }) || fields.visit_with(visitor) - } - } - } -} - -impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> { - fn super_fold_with>(&self, folder: &mut F) -> Self { - match *self { - Operand::Copy(ref place) => Operand::Copy(place.fold_with(folder)), - Operand::Move(ref place) => Operand::Move(place.fold_with(folder)), - Operand::Constant(ref c) => Operand::Constant(c.fold_with(folder)), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - match *self { - Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor), - Operand::Constant(ref c) => c.visit_with(visitor), - } - } -} - -impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> { - fn super_fold_with>(&self, folder: &mut F) -> Self { - use crate::mir::ProjectionElem::*; - - match *self { - Deref => Deref, - Field(f, ty) => Field(f, ty.fold_with(folder)), - Index(v) => Index(v.fold_with(folder)), - Downcast(symbol, variantidx) => Downcast(symbol, variantidx), - ConstantIndex { offset, min_length, from_end } => { - ConstantIndex { offset, min_length, from_end } - } - Subslice { from, to, from_end } => Subslice { from, to, from_end }, - } - } - - fn super_visit_with>(&self, visitor: &mut Vs) -> bool { - use crate::mir::ProjectionElem::*; - - match self { - Field(_, ty) => ty.visit_with(visitor), - Index(v) => v.visit_with(visitor), - _ => false, - } - } -} - -impl<'tcx> TypeFoldable<'tcx> for Field { - fn super_fold_with>(&self, _: &mut F) -> Self { - *self - } - fn super_visit_with>(&self, _: &mut V) -> bool { - false - } -} - -impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal { - fn super_fold_with>(&self, _: &mut F) -> Self { - *self - } - fn super_visit_with>(&self, _: &mut V) -> bool { - false - } -} - -impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix { - fn super_fold_with>(&self, _: &mut F) -> Self { - self.clone() - } - fn super_visit_with>(&self, _: &mut V) -> bool { - false - } -} - -impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { - fn super_fold_with>(&self, folder: &mut F) -> Self { - Constant { - span: self.span, - user_ty: self.user_ty.fold_with(folder), - literal: self.literal.fold_with(folder), - } - } - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.literal.visit_with(visitor) - } -} diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs index 4f8efc1607eaa..0b64cb479d559 100644 --- a/src/librustc/mir/mono.rs +++ b/src/librustc/mir/mono.rs @@ -1,14 +1,15 @@ use crate::dep_graph::{DepConstructor, DepNode, WorkProduct, WorkProductId}; -use crate::ich::{Fingerprint, NodeIdHashingMode, StableHashingContext}; -use crate::session::config::OptLevel; +use crate::ich::{NodeIdHashingMode, StableHashingContext}; use crate::ty::print::obsolete::DefPathBasedNames; use crate::ty::{subst::InternalSubsts, Instance, InstanceDef, SymbolName, TyCtxt}; use rustc_attr::InlineAttr; use rustc_data_structures::base_n; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_hir::HirId; +use rustc_session::config::OptLevel; use rustc_span::source_map::Span; use rustc_span::symbol::Symbol; use std::fmt; diff --git a/src/librustc/mir/query.rs b/src/librustc/mir/query.rs index 824cdfe55bfb6..8c81f5227d260 100644 --- a/src/librustc/mir/query.rs +++ b/src/librustc/mir/query.rs @@ -88,34 +88,35 @@ pub struct ConstQualifs { /// requirements are then verified and proved by the closure's /// creating function. This struct encodes those requirements. /// -/// The requirements are listed as being between various -/// `RegionVid`. The 0th region refers to `'static`; subsequent region -/// vids refer to the free regions that appear in the closure (or -/// generator's) type, in order of appearance. (This numbering is -/// actually defined by the `UniversalRegions` struct in the NLL -/// region checker. See for example -/// `UniversalRegions::closure_mapping`.) Note that we treat the free -/// regions in the closure's type "as if" they were erased, so their -/// precise identity is not important, only their position. +/// The requirements are listed as being between various `RegionVid`. The 0th +/// region refers to `'static`; subsequent region vids refer to the free +/// regions that appear in the closure (or generator's) type, in order of +/// appearance. (This numbering is actually defined by the `UniversalRegions` +/// struct in the NLL region checker. See for example +/// `UniversalRegions::closure_mapping`.) Note the free regions in the +/// closure's signature and captures are erased. /// /// Example: If type check produces a closure with the closure substs: /// /// ```text /// ClosureSubsts = [ -/// i8, // the "closure kind" -/// for<'x> fn(&'a &'x u32) -> &'x u32, // the "closure signature" -/// &'a String, // some upvar +/// 'a, // From the parent. +/// 'b, +/// i8, // the "closure kind" +/// for<'x> fn(&' &'x u32) -> &'x u32, // the "closure signature" +/// &' String, // some upvar /// ] /// ``` /// -/// here, there is one unique free region (`'a`) but it appears -/// twice. We would "renumber" each occurrence to a unique vid, as follows: +/// We would "renumber" each free region to a unique vid, as follows: /// /// ```text /// ClosureSubsts = [ -/// i8, // the "closure kind" -/// for<'x> fn(&'1 &'x u32) -> &'x u32, // the "closure signature" -/// &'2 String, // some upvar +/// '1, // From the parent. +/// '2, +/// i8, // the "closure kind" +/// for<'x> fn(&'3 &'x u32) -> &'x u32, // the "closure signature" +/// &'4 String, // some upvar /// ] /// ``` /// @@ -124,14 +125,12 @@ pub struct ConstQualifs { /// can be extracted from its type and constrained to have the given /// outlives relationship. /// -/// In some cases, we have to record outlives requirements between -/// types and regions as well. In that case, if those types include -/// any regions, those regions are recorded as `ReClosureBound` -/// instances assigned one of these same indices. Those regions will -/// be substituted away by the creator. We use `ReClosureBound` in -/// that case because the regions must be allocated in the global -/// `TyCtxt`, and hence we cannot use `ReVar` (which is what we use -/// internally within the rest of the NLL code). +/// In some cases, we have to record outlives requirements between types and +/// regions as well. In that case, if those types include any regions, those +/// regions are recorded using their external names (`ReStatic`, +/// `ReEarlyBound`, `ReFree`). We use these because in a query response we +/// cannot use `ReVar` (which is what we use internally within the rest of the +/// NLL code). #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct ClosureRegionRequirements<'tcx> { /// The number of external regions defined on the closure. In our diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 13996a74acb35..feb6631926712 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -149,7 +149,9 @@ impl<'tcx> Rvalue<'tcx> { { match *self { Rvalue::Use(ref operand) => operand.ty(local_decls, tcx), - Rvalue::Repeat(ref operand, count) => tcx.mk_array(operand.ty(local_decls, tcx), count), + Rvalue::Repeat(ref operand, count) => { + tcx.mk_ty(ty::Array(operand.ty(local_decls, tcx), count)) + } Rvalue::Ref(reg, bk, ref place) => { let place_ty = place.ty(local_decls, tcx).ty; tcx.mk_ref(reg, ty::TypeAndMut { ty: place_ty, mutbl: bk.to_mutbl_lossy() }) diff --git a/src/librustc/mir/type_foldable.rs b/src/librustc/mir/type_foldable.rs new file mode 100644 index 0000000000000..9520f081b6bfb --- /dev/null +++ b/src/librustc/mir/type_foldable.rs @@ -0,0 +1,322 @@ +//! `TypeFoldable` implementations for MIR types + +use super::*; +use crate::ty; + +CloneTypeFoldableAndLiftImpls! { + BlockTailInfo, + MirPhase, + SourceInfo, + FakeReadCause, + RetagKind, + SourceScope, + SourceScopeData, + SourceScopeLocalData, + UserTypeAnnotationIndex, +} + +impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + use crate::mir::TerminatorKind::*; + + let kind = match self.kind { + Goto { target } => Goto { target }, + SwitchInt { ref discr, switch_ty, ref values, ref targets } => SwitchInt { + discr: discr.fold_with(folder), + switch_ty: switch_ty.fold_with(folder), + values: values.clone(), + targets: targets.clone(), + }, + Drop { ref location, target, unwind } => { + Drop { location: location.fold_with(folder), target, unwind } + } + DropAndReplace { ref location, ref value, target, unwind } => DropAndReplace { + location: location.fold_with(folder), + value: value.fold_with(folder), + target, + unwind, + }, + Yield { ref value, resume, ref resume_arg, drop } => Yield { + value: value.fold_with(folder), + resume, + resume_arg: resume_arg.fold_with(folder), + drop, + }, + Call { ref func, ref args, ref destination, cleanup, from_hir_call } => { + let dest = + destination.as_ref().map(|&(ref loc, dest)| (loc.fold_with(folder), dest)); + + Call { + func: func.fold_with(folder), + args: args.fold_with(folder), + destination: dest, + cleanup, + from_hir_call, + } + } + Assert { ref cond, expected, ref msg, target, cleanup } => { + use AssertKind::*; + let msg = match msg { + BoundsCheck { ref len, ref index } => { + BoundsCheck { len: len.fold_with(folder), index: index.fold_with(folder) } + } + Overflow(_) + | OverflowNeg + | DivisionByZero + | RemainderByZero + | ResumedAfterReturn(_) + | ResumedAfterPanic(_) => msg.clone(), + }; + Assert { cond: cond.fold_with(folder), expected, msg, target, cleanup } + } + GeneratorDrop => GeneratorDrop, + Resume => Resume, + Abort => Abort, + Return => Return, + Unreachable => Unreachable, + FalseEdges { real_target, imaginary_target } => { + FalseEdges { real_target, imaginary_target } + } + FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind }, + }; + Terminator { source_info: self.source_info, kind } + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + use crate::mir::TerminatorKind::*; + + match self.kind { + SwitchInt { ref discr, switch_ty, .. } => { + discr.visit_with(visitor) || switch_ty.visit_with(visitor) + } + Drop { ref location, .. } => location.visit_with(visitor), + DropAndReplace { ref location, ref value, .. } => { + location.visit_with(visitor) || value.visit_with(visitor) + } + Yield { ref value, .. } => value.visit_with(visitor), + Call { ref func, ref args, ref destination, .. } => { + let dest = if let Some((ref loc, _)) = *destination { + loc.visit_with(visitor) + } else { + false + }; + dest || func.visit_with(visitor) || args.visit_with(visitor) + } + Assert { ref cond, ref msg, .. } => { + if cond.visit_with(visitor) { + use AssertKind::*; + match msg { + BoundsCheck { ref len, ref index } => { + len.visit_with(visitor) || index.visit_with(visitor) + } + Overflow(_) + | OverflowNeg + | DivisionByZero + | RemainderByZero + | ResumedAfterReturn(_) + | ResumedAfterPanic(_) => false, + } + } else { + false + } + } + Goto { .. } + | Resume + | Abort + | Return + | GeneratorDrop + | Unreachable + | FalseEdges { .. } + | FalseUnwind { .. } => false, + } + } +} + +impl<'tcx> TypeFoldable<'tcx> for GeneratorKind { + fn super_fold_with>(&self, _: &mut F) -> Self { + *self + } + + fn super_visit_with>(&self, _: &mut V) -> bool { + false + } +} + +impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + Place { local: self.local.fold_with(folder), projection: self.projection.fold_with(folder) } + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + self.local.visit_with(visitor) || self.projection.visit_with(visitor) + } +} + +impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + let v = self.iter().map(|t| t.fold_with(folder)).collect::>(); + folder.tcx().intern_place_elems(&v) + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + self.iter().any(|t| t.visit_with(visitor)) + } +} + +impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + use crate::mir::Rvalue::*; + match *self { + Use(ref op) => Use(op.fold_with(folder)), + Repeat(ref op, len) => Repeat(op.fold_with(folder), len), + Ref(region, bk, ref place) => { + Ref(region.fold_with(folder), bk, place.fold_with(folder)) + } + AddressOf(mutability, ref place) => AddressOf(mutability, place.fold_with(folder)), + Len(ref place) => Len(place.fold_with(folder)), + Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)), + BinaryOp(op, ref rhs, ref lhs) => { + BinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)) + } + CheckedBinaryOp(op, ref rhs, ref lhs) => { + CheckedBinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)) + } + UnaryOp(op, ref val) => UnaryOp(op, val.fold_with(folder)), + Discriminant(ref place) => Discriminant(place.fold_with(folder)), + NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)), + Aggregate(ref kind, ref fields) => { + let kind = box match **kind { + AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)), + AggregateKind::Tuple => AggregateKind::Tuple, + AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt( + def, + v, + substs.fold_with(folder), + user_ty.fold_with(folder), + n, + ), + AggregateKind::Closure(id, substs) => { + AggregateKind::Closure(id, substs.fold_with(folder)) + } + AggregateKind::Generator(id, substs, movablity) => { + AggregateKind::Generator(id, substs.fold_with(folder), movablity) + } + }; + Aggregate(kind, fields.fold_with(folder)) + } + } + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + use crate::mir::Rvalue::*; + match *self { + Use(ref op) => op.visit_with(visitor), + Repeat(ref op, _) => op.visit_with(visitor), + Ref(region, _, ref place) => region.visit_with(visitor) || place.visit_with(visitor), + AddressOf(_, ref place) => place.visit_with(visitor), + Len(ref place) => place.visit_with(visitor), + Cast(_, ref op, ty) => op.visit_with(visitor) || ty.visit_with(visitor), + BinaryOp(_, ref rhs, ref lhs) | CheckedBinaryOp(_, ref rhs, ref lhs) => { + rhs.visit_with(visitor) || lhs.visit_with(visitor) + } + UnaryOp(_, ref val) => val.visit_with(visitor), + Discriminant(ref place) => place.visit_with(visitor), + NullaryOp(_, ty) => ty.visit_with(visitor), + Aggregate(ref kind, ref fields) => { + (match **kind { + AggregateKind::Array(ty) => ty.visit_with(visitor), + AggregateKind::Tuple => false, + AggregateKind::Adt(_, _, substs, user_ty, _) => { + substs.visit_with(visitor) || user_ty.visit_with(visitor) + } + AggregateKind::Closure(_, substs) => substs.visit_with(visitor), + AggregateKind::Generator(_, substs, _) => substs.visit_with(visitor), + }) || fields.visit_with(visitor) + } + } + } +} + +impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + match *self { + Operand::Copy(ref place) => Operand::Copy(place.fold_with(folder)), + Operand::Move(ref place) => Operand::Move(place.fold_with(folder)), + Operand::Constant(ref c) => Operand::Constant(c.fold_with(folder)), + } + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + match *self { + Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor), + Operand::Constant(ref c) => c.visit_with(visitor), + } + } +} + +impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + use crate::mir::ProjectionElem::*; + + match *self { + Deref => Deref, + Field(f, ty) => Field(f, ty.fold_with(folder)), + Index(v) => Index(v.fold_with(folder)), + Downcast(symbol, variantidx) => Downcast(symbol, variantidx), + ConstantIndex { offset, min_length, from_end } => { + ConstantIndex { offset, min_length, from_end } + } + Subslice { from, to, from_end } => Subslice { from, to, from_end }, + } + } + + fn super_visit_with>(&self, visitor: &mut Vs) -> bool { + use crate::mir::ProjectionElem::*; + + match self { + Field(_, ty) => ty.visit_with(visitor), + Index(v) => v.visit_with(visitor), + _ => false, + } + } +} + +impl<'tcx> TypeFoldable<'tcx> for Field { + fn super_fold_with>(&self, _: &mut F) -> Self { + *self + } + fn super_visit_with>(&self, _: &mut V) -> bool { + false + } +} + +impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal { + fn super_fold_with>(&self, _: &mut F) -> Self { + *self + } + fn super_visit_with>(&self, _: &mut V) -> bool { + false + } +} + +impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix { + fn super_fold_with>(&self, _: &mut F) -> Self { + self.clone() + } + fn super_visit_with>(&self, _: &mut V) -> bool { + false + } +} + +impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + Constant { + span: self.span, + user_ty: self.user_ty.fold_with(folder), + literal: self.literal.fold_with(folder), + } + } + fn super_visit_with>(&self, visitor: &mut V) -> bool { + self.literal.visit_with(visitor) + } +} diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 11e9acf3a3912..c1ece6275092d 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -9,9 +9,9 @@ use crate::traits::query::{ }; use crate::ty::query::queries; use crate::ty::query::QueryDescription; -use crate::ty::subst::SubstsRef; +use crate::ty::subst::{GenericArg, SubstsRef}; use crate::ty::{self, ParamEnvAnd, Ty, TyCtxt}; -use rustc_hir::def_id::{CrateNum, DefId, DefIndex}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_span::symbol::Symbol; use std::borrow::Cow; @@ -55,6 +55,41 @@ rustc_queries! { desc { "get the crate HIR" } } + // The indexed HIR. This can be conveniently accessed by `tcx.hir()`. + // Avoid calling this query directly. + query index_hir(_: CrateNum) -> &'tcx map::IndexedHir<'tcx> { + eval_always + no_hash + desc { "index HIR" } + } + + // The items in a module. + // + // This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`. + // Avoid calling this query directly. + query hir_module_items(key: LocalDefId) -> &'tcx hir::ModuleItems { + eval_always + desc { |tcx| "HIR module items in `{}`", tcx.def_path_str(key.to_def_id()) } + } + + // Gives access to the HIR node for the HIR owner `key`. + // + // This can be conveniently accessed by methods on `tcx.hir()`. + // Avoid calling this query directly. + query hir_owner(key: LocalDefId) -> Option<&'tcx crate::hir::Owner<'tcx>> { + eval_always + desc { |tcx| "HIR owner of `{}`", tcx.def_path_str(key.to_def_id()) } + } + + // Gives access to the HIR nodes and bodies inside the HIR owner `key`. + // + // This can be conveniently accessed by methods on `tcx.hir()`. + // Avoid calling this query directly. + query hir_owner_nodes(key: LocalDefId) -> Option<&'tcx crate::hir::OwnerNodes<'tcx>> { + eval_always + desc { |tcx| "HIR owner items in `{}`", tcx.def_path_str(key.to_def_id()) } + } + /// Records the type of every item. query type_of(key: DefId) -> Ty<'tcx> { cache_on_disk_if { key.is_local() } @@ -104,8 +139,9 @@ rustc_queries! { desc { "computing the lint levels for items in this crate" } } - query parent_module_from_def_id(_: DefId) -> DefId { + query parent_module_from_def_id(key: LocalDefId) -> LocalDefId { eval_always + desc { |tcx| "parent module of `{}`", tcx.def_path_str(key.to_def_id()) } } } @@ -653,6 +689,9 @@ rustc_queries! { } TypeChecking { + query all_local_trait_impls(key: CrateNum) -> &'tcx BTreeMap> { + desc { "local trait impls" } + } query trait_impls_of(key: DefId) -> &'tcx ty::trait_def::TraitImpls { desc { |tcx| "trait impls of `{}`", tcx.def_path_str(key) } } @@ -699,7 +738,7 @@ rustc_queries! { query layout_raw( env: ty::ParamEnvAnd<'tcx, Ty<'tcx>> - ) -> Result<&'tcx ty::layout::LayoutDetails, ty::layout::LayoutError<'tcx>> { + ) -> Result<&'tcx ty::layout::Layout, ty::layout::LayoutError<'tcx>> { desc { "computing layout of `{}`", env.value } } } @@ -757,7 +796,7 @@ rustc_queries! { query specializes(_: (DefId, DefId)) -> bool { desc { "computing whether impls specialize one another" } } - query in_scope_traits_map(_: DefIndex) + query in_scope_traits_map(_: LocalDefId) -> Option<&'tcx FxHashMap>> { eval_always desc { "traits in scope at a block" } @@ -914,15 +953,15 @@ rustc_queries! { query resolve_lifetimes(_: CrateNum) -> &'tcx ResolveLifetimes { desc { "resolving lifetimes" } } - query named_region_map(_: DefIndex) -> + query named_region_map(_: LocalDefId) -> Option<&'tcx FxHashMap> { desc { "looking up a named region" } } - query is_late_bound_map(_: DefIndex) -> + query is_late_bound_map(_: LocalDefId) -> Option<&'tcx FxHashSet> { desc { "testing if a region is late bound" } } - query object_lifetime_defaults_map(_: DefIndex) + query object_lifetime_defaults_map(_: LocalDefId) -> Option<&'tcx FxHashMap>> { desc { "looking up lifetime defaults for a region" } } @@ -1075,10 +1114,10 @@ rustc_queries! { } /// Do not call this query directly: invoke `normalize_erasing_regions` instead. - query normalize_ty_after_erasing_regions( - goal: ParamEnvAnd<'tcx, Ty<'tcx>> - ) -> Ty<'tcx> { - desc { "normalizing `{:?}`", goal } + query normalize_generic_arg_after_erasing_regions( + goal: ParamEnvAnd<'tcx, GenericArg<'tcx>> + ) -> GenericArg<'tcx> { + desc { "normalizing `{}`", goal.value } } query implied_outlives_bounds( diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 6ebcc8b075462..c129b574fd38a 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -108,7 +108,9 @@ impl<'tcx> ObligationCause<'tcx> { match self.code { ObligationCauseCode::CompareImplMethodObligation { .. } | ObligationCauseCode::MainFunctionType - | ObligationCauseCode::StartFunctionType => tcx.sess.source_map().def_span(self.span), + | ObligationCauseCode::StartFunctionType => { + tcx.sess.source_map().guess_head_span(self.span) + } ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { arm_span, .. diff --git a/src/librustc/traits/query.rs b/src/librustc/traits/query.rs index c90551826202e..67f4b15f9194d 100644 --- a/src/librustc/traits/query.rs +++ b/src/librustc/traits/query.rs @@ -229,8 +229,8 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { // (T1..Tn) and closures have same properties as T1..Tn -- // check if *any* of those are trivial. ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t.expect_ty())), - ty::Closure(def_id, ref substs) => { - substs.as_closure().upvar_tys(def_id, tcx).all(|t| trivial_dropck_outlives(tcx, t)) + ty::Closure(_, ref substs) => { + substs.as_closure().upvar_tys().all(|t| trivial_dropck_outlives(tcx, t)) } ty::Adt(def, _) => { diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 08d78b3a0b24b..d316d7659e222 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -288,3 +288,44 @@ impl WithDepNode { self.cached_value.clone() } } + +#[derive(Clone, Debug)] +pub enum IntercrateAmbiguityCause { + DownstreamCrate { trait_desc: String, self_desc: Option }, + UpstreamCrateUpdate { trait_desc: String, self_desc: Option }, + ReservationImpl { message: String }, +} + +impl IntercrateAmbiguityCause { + /// Emits notes when the overlap is caused by complex intercrate ambiguities. + /// See #23980 for details. + pub fn add_intercrate_ambiguity_hint(&self, err: &mut rustc_errors::DiagnosticBuilder<'_>) { + err.note(&self.intercrate_ambiguity_hint()); + } + + pub fn intercrate_ambiguity_hint(&self) -> String { + match self { + &IntercrateAmbiguityCause::DownstreamCrate { ref trait_desc, ref self_desc } => { + let self_desc = if let &Some(ref ty) = self_desc { + format!(" for type `{}`", ty) + } else { + String::new() + }; + format!("downstream crates may implement trait `{}`{}", trait_desc, self_desc) + } + &IntercrateAmbiguityCause::UpstreamCrateUpdate { ref trait_desc, ref self_desc } => { + let self_desc = if let &Some(ref ty) = self_desc { + format!(" for type `{}`", ty) + } else { + String::new() + }; + format!( + "upstream crates may add a new impl of trait `{}`{} \ + in future versions", + trait_desc, self_desc + ) + } + &IntercrateAmbiguityCause::ReservationImpl { ref message } => message.clone(), + } + } +} diff --git a/src/librustc/traits/specialization_graph.rs b/src/librustc/traits/specialization_graph.rs index d481e578fc1dd..1847326a742eb 100644 --- a/src/librustc/traits/specialization_graph.rs +++ b/src/librustc/traits/specialization_graph.rs @@ -4,6 +4,7 @@ use crate::ty::{self, TyCtxt}; use rustc_ast::ast::Ident; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_errors::ErrorReported; use rustc_hir::def_id::{DefId, DefIdMap}; /// A per-trait graph of impls in specialization order. At the moment, this @@ -23,17 +24,20 @@ use rustc_hir::def_id::{DefId, DefIdMap}; /// has at most one parent. #[derive(RustcEncodable, RustcDecodable, HashStable)] pub struct Graph { - // All impls have a parent; the "root" impls have as their parent the `def_id` - // of the trait. + /// All impls have a parent; the "root" impls have as their parent the `def_id` + /// of the trait. pub parent: DefIdMap, - // The "root" impls are found by looking up the trait's def_id. + /// The "root" impls are found by looking up the trait's def_id. pub children: DefIdMap, + + /// Whether an error was emitted while constructing the graph. + pub has_errored: bool, } impl Graph { pub fn new() -> Graph { - Graph { parent: Default::default(), children: Default::default() } + Graph { parent: Default::default(), children: Default::default(), has_errored: false } } /// The parent of a given impl, which is the `DefId` of the trait when the @@ -179,17 +183,22 @@ impl<'tcx> Ancestors<'tcx> { } /// Walk up the specialization ancestors of a given impl, starting with that -/// impl itself. +/// impl itself. Returns `None` if an error was reported while building the +/// specialization graph. pub fn ancestors( tcx: TyCtxt<'tcx>, trait_def_id: DefId, start_from_impl: DefId, -) -> Ancestors<'tcx> { +) -> Result, ErrorReported> { let specialization_graph = tcx.specialization_graph_of(trait_def_id); - Ancestors { - trait_def_id, - specialization_graph, - current_source: Some(Node::Impl(start_from_impl)), + if specialization_graph.has_errored { + Err(ErrorReported) + } else { + Ok(Ancestors { + trait_def_id, + specialization_graph, + current_source: Some(Node::Impl(start_from_impl)), + }) } } diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index a5efea9e5fa4d..b1fb02a67b3ff 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -273,6 +273,20 @@ impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector { t.super_visit_with(self) } + fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool { + match c.val { + ty::ConstKind::Bound(debruijn, bound_var) if debruijn == self.binder_index => { + self.types.insert( + bound_var.as_u32(), + Symbol::intern(&format!("^{}", bound_var.as_u32())), + ); + } + _ => (), + } + + c.super_visit_with(self) + } + fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { match r { ty::ReLateBound(index, br) if *index == self.binder_index => match br { diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs index c305999a64ba7..cbbc937ed7d31 100644 --- a/src/librustc/ty/codec.rs +++ b/src/librustc/ty/codec.rs @@ -396,6 +396,7 @@ macro_rules! implement_ty_decoder { // the caller to pick any lifetime for `'tcx`, including `'static`, // by using the unspecialized proxies to them. + rustc_hir::arena_types!(impl_arena_allocatable_decoders, [$DecoderName [$($typaram),*]], 'tcx); arena_types!(impl_arena_allocatable_decoders, [$DecoderName [$($typaram),*]], 'tcx); impl<$($typaram),*> SpecializedDecoder diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 6fab55e9fd935..c1d13b0353ebb 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -4,8 +4,6 @@ use crate::arena::Arena; use crate::dep_graph::DepGraph; use crate::dep_graph::{self, DepConstructor}; use crate::hir::exports::Export; -use crate::hir::map as hir_map; -use crate::hir::map::{DefPathData, DefPathHash}; use crate::ich::{NodeIdHashingMode, StableHashingContext}; use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos}; use crate::lint::{struct_lint_level, LintSource}; @@ -22,8 +20,7 @@ use crate::mir::{ }; use crate::traits; use crate::traits::{Clause, Clauses, Goal, GoalKind, Goals}; -use crate::ty::free_region_map::FreeRegionMap; -use crate::ty::layout::{LayoutDetails, TargetDataLayout, VariantIdx}; +use crate::ty::layout::{Layout, TargetDataLayout, VariantIdx}; use crate::ty::query; use crate::ty::steal::Steal; use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; @@ -55,7 +52,8 @@ use rustc_data_structures::stable_hasher::{ use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, DefIndex, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE}; +use rustc_hir::definitions::{DefPathData, DefPathHash, Definitions}; use rustc_hir::{HirId, Node, TraitCandidate}; use rustc_hir::{ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet}; use rustc_index::vec::{Idx, IndexVec}; @@ -188,37 +186,37 @@ pub struct CommonConsts<'tcx> { } pub struct LocalTableInContext<'a, V> { - local_id_root: Option, + hir_owner: Option, data: &'a ItemLocalMap, } /// Validate that the given HirId (respectively its `local_id` part) can be /// safely used as a key in the tables of a TypeckTable. For that to be /// the case, the HirId must have the same `owner` as all the other IDs in -/// this table (signified by `local_id_root`). Otherwise the HirId +/// this table (signified by `hir_owner`). Otherwise the HirId /// would be in a different frame of reference and using its `local_id` /// would result in lookup errors, or worse, in silently wrong data being /// stored/returned. fn validate_hir_id_for_typeck_tables( - local_id_root: Option, + hir_owner: Option, hir_id: hir::HirId, mut_access: bool, ) { - if let Some(local_id_root) = local_id_root { - if hir_id.owner != local_id_root.index { + if let Some(hir_owner) = hir_owner { + if hir_id.owner != hir_owner { ty::tls::with(|tcx| { bug!( "node {} with HirId::owner {:?} cannot be placed in \ - TypeckTables with local_id_root {:?}", + TypeckTables with hir_owner {:?}", tcx.hir().node_to_string(hir_id), - DefId::local(hir_id.owner), - local_id_root + hir_id.owner, + hir_owner ) }); } } else { // We use "Null Object" TypeckTables in some of the analysis passes. - // These are just expected to be empty and their `local_id_root` is + // These are just expected to be empty and their `hir_owner` is // `None`. Therefore we cannot verify whether a given `HirId` would // be a valid key for the given table. Instead we make sure that // nobody tries to write to such a Null Object table. @@ -230,12 +228,12 @@ fn validate_hir_id_for_typeck_tables( impl<'a, V> LocalTableInContext<'a, V> { pub fn contains_key(&self, id: hir::HirId) -> bool { - validate_hir_id_for_typeck_tables(self.local_id_root, id, false); + validate_hir_id_for_typeck_tables(self.hir_owner, id, false); self.data.contains_key(&id.local_id) } pub fn get(&self, id: hir::HirId) -> Option<&V> { - validate_hir_id_for_typeck_tables(self.local_id_root, id, false); + validate_hir_id_for_typeck_tables(self.hir_owner, id, false); self.data.get(&id.local_id) } @@ -253,28 +251,28 @@ impl<'a, V> ::std::ops::Index for LocalTableInContext<'a, V> { } pub struct LocalTableInContextMut<'a, V> { - local_id_root: Option, + hir_owner: Option, data: &'a mut ItemLocalMap, } impl<'a, V> LocalTableInContextMut<'a, V> { pub fn get_mut(&mut self, id: hir::HirId) -> Option<&mut V> { - validate_hir_id_for_typeck_tables(self.local_id_root, id, true); + validate_hir_id_for_typeck_tables(self.hir_owner, id, true); self.data.get_mut(&id.local_id) } pub fn entry(&mut self, id: hir::HirId) -> Entry<'_, hir::ItemLocalId, V> { - validate_hir_id_for_typeck_tables(self.local_id_root, id, true); + validate_hir_id_for_typeck_tables(self.hir_owner, id, true); self.data.entry(id.local_id) } pub fn insert(&mut self, id: hir::HirId, val: V) -> Option { - validate_hir_id_for_typeck_tables(self.local_id_root, id, true); + validate_hir_id_for_typeck_tables(self.hir_owner, id, true); self.data.insert(id.local_id, val) } pub fn remove(&mut self, id: hir::HirId) -> Option { - validate_hir_id_for_typeck_tables(self.local_id_root, id, true); + validate_hir_id_for_typeck_tables(self.hir_owner, id, true); self.data.remove(&id.local_id) } } @@ -322,8 +320,8 @@ pub struct GeneratorInteriorTypeCause<'tcx> { #[derive(RustcEncodable, RustcDecodable, Debug)] pub struct TypeckTables<'tcx> { - /// The HirId::owner all ItemLocalIds in this table are relative to. - pub local_id_root: Option, + /// The `HirId::owner` all `ItemLocalId`s in this table are relative to. + pub hir_owner: Option, /// Resolved definitions for `::X` associated paths and /// method calls, including those of overloaded operators. @@ -415,11 +413,6 @@ pub struct TypeckTables<'tcx> { /// this field will be set to `true`. pub tainted_by_errors: bool, - /// Stores the free-region relationships that were deduced from - /// its where-clauses and parameter types. These are then - /// read-again by borrowck. - pub free_region_map: FreeRegionMap<'tcx>, - /// All the opaque types that are restricted to concrete types /// by this function. pub concrete_opaque_types: FxHashMap>, @@ -436,9 +429,9 @@ pub struct TypeckTables<'tcx> { } impl<'tcx> TypeckTables<'tcx> { - pub fn empty(local_id_root: Option) -> TypeckTables<'tcx> { + pub fn empty(hir_owner: Option) -> TypeckTables<'tcx> { TypeckTables { - local_id_root, + hir_owner, type_dependent_defs: Default::default(), field_indices: Default::default(), user_provided_types: Default::default(), @@ -455,7 +448,6 @@ impl<'tcx> TypeckTables<'tcx> { coercion_casts: Default::default(), used_trait_imports: Lrc::new(Default::default()), tainted_by_errors: false, - free_region_map: Default::default(), concrete_opaque_types: Default::default(), upvar_list: Default::default(), generator_interior_types: Default::default(), @@ -475,11 +467,11 @@ impl<'tcx> TypeckTables<'tcx> { pub fn type_dependent_defs( &self, ) -> LocalTableInContext<'_, Result<(DefKind, DefId), ErrorReported>> { - LocalTableInContext { local_id_root: self.local_id_root, data: &self.type_dependent_defs } + LocalTableInContext { hir_owner: self.hir_owner, data: &self.type_dependent_defs } } pub fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> { - validate_hir_id_for_typeck_tables(self.local_id_root, id, false); + validate_hir_id_for_typeck_tables(self.hir_owner, id, false); self.type_dependent_defs.get(&id.local_id).cloned().and_then(|r| r.ok()) } @@ -490,39 +482,33 @@ impl<'tcx> TypeckTables<'tcx> { pub fn type_dependent_defs_mut( &mut self, ) -> LocalTableInContextMut<'_, Result<(DefKind, DefId), ErrorReported>> { - LocalTableInContextMut { - local_id_root: self.local_id_root, - data: &mut self.type_dependent_defs, - } + LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.type_dependent_defs } } pub fn field_indices(&self) -> LocalTableInContext<'_, usize> { - LocalTableInContext { local_id_root: self.local_id_root, data: &self.field_indices } + LocalTableInContext { hir_owner: self.hir_owner, data: &self.field_indices } } pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<'_, usize> { - LocalTableInContextMut { local_id_root: self.local_id_root, data: &mut self.field_indices } + LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.field_indices } } pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> { - LocalTableInContext { local_id_root: self.local_id_root, data: &self.user_provided_types } + LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types } } pub fn user_provided_types_mut( &mut self, ) -> LocalTableInContextMut<'_, CanonicalUserType<'tcx>> { - LocalTableInContextMut { - local_id_root: self.local_id_root, - data: &mut self.user_provided_types, - } + LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.user_provided_types } } pub fn node_types(&self) -> LocalTableInContext<'_, Ty<'tcx>> { - LocalTableInContext { local_id_root: self.local_id_root, data: &self.node_types } + LocalTableInContext { hir_owner: self.hir_owner, data: &self.node_types } } pub fn node_types_mut(&mut self) -> LocalTableInContextMut<'_, Ty<'tcx>> { - LocalTableInContextMut { local_id_root: self.local_id_root, data: &mut self.node_types } + LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_types } } pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> { @@ -532,21 +518,21 @@ impl<'tcx> TypeckTables<'tcx> { } pub fn node_type_opt(&self, id: hir::HirId) -> Option> { - validate_hir_id_for_typeck_tables(self.local_id_root, id, false); + validate_hir_id_for_typeck_tables(self.hir_owner, id, false); self.node_types.get(&id.local_id).cloned() } pub fn node_substs_mut(&mut self) -> LocalTableInContextMut<'_, SubstsRef<'tcx>> { - LocalTableInContextMut { local_id_root: self.local_id_root, data: &mut self.node_substs } + LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_substs } } pub fn node_substs(&self, id: hir::HirId) -> SubstsRef<'tcx> { - validate_hir_id_for_typeck_tables(self.local_id_root, id, false); + validate_hir_id_for_typeck_tables(self.hir_owner, id, false); self.node_substs.get(&id.local_id).cloned().unwrap_or_else(|| InternalSubsts::empty()) } pub fn node_substs_opt(&self, id: hir::HirId) -> Option> { - validate_hir_id_for_typeck_tables(self.local_id_root, id, false); + validate_hir_id_for_typeck_tables(self.hir_owner, id, false); self.node_substs.get(&id.local_id).cloned() } @@ -579,17 +565,17 @@ impl<'tcx> TypeckTables<'tcx> { } pub fn adjustments(&self) -> LocalTableInContext<'_, Vec>> { - LocalTableInContext { local_id_root: self.local_id_root, data: &self.adjustments } + LocalTableInContext { hir_owner: self.hir_owner, data: &self.adjustments } } pub fn adjustments_mut( &mut self, ) -> LocalTableInContextMut<'_, Vec>> { - LocalTableInContextMut { local_id_root: self.local_id_root, data: &mut self.adjustments } + LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.adjustments } } pub fn expr_adjustments(&self, expr: &hir::Expr<'_>) -> &[ty::adjustment::Adjustment<'tcx>] { - validate_hir_id_for_typeck_tables(self.local_id_root, expr.hir_id, false); + validate_hir_id_for_typeck_tables(self.hir_owner, expr.hir_id, false); self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..]) } @@ -624,25 +610,19 @@ impl<'tcx> TypeckTables<'tcx> { } pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingMode> { - LocalTableInContext { local_id_root: self.local_id_root, data: &self.pat_binding_modes } + LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_binding_modes } } pub fn pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingMode> { - LocalTableInContextMut { - local_id_root: self.local_id_root, - data: &mut self.pat_binding_modes, - } + LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_binding_modes } } pub fn pat_adjustments(&self) -> LocalTableInContext<'_, Vec>> { - LocalTableInContext { local_id_root: self.local_id_root, data: &self.pat_adjustments } + LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_adjustments } } pub fn pat_adjustments_mut(&mut self) -> LocalTableInContextMut<'_, Vec>> { - LocalTableInContextMut { - local_id_root: self.local_id_root, - data: &mut self.pat_adjustments, - } + LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments } } pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> ty::UpvarCapture<'tcx> { @@ -650,40 +630,31 @@ impl<'tcx> TypeckTables<'tcx> { } pub fn closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, ast::Name)> { - LocalTableInContext { local_id_root: self.local_id_root, data: &self.closure_kind_origins } + LocalTableInContext { hir_owner: self.hir_owner, data: &self.closure_kind_origins } } pub fn closure_kind_origins_mut(&mut self) -> LocalTableInContextMut<'_, (Span, ast::Name)> { - LocalTableInContextMut { - local_id_root: self.local_id_root, - data: &mut self.closure_kind_origins, - } + LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.closure_kind_origins } } pub fn liberated_fn_sigs(&self) -> LocalTableInContext<'_, ty::FnSig<'tcx>> { - LocalTableInContext { local_id_root: self.local_id_root, data: &self.liberated_fn_sigs } + LocalTableInContext { hir_owner: self.hir_owner, data: &self.liberated_fn_sigs } } pub fn liberated_fn_sigs_mut(&mut self) -> LocalTableInContextMut<'_, ty::FnSig<'tcx>> { - LocalTableInContextMut { - local_id_root: self.local_id_root, - data: &mut self.liberated_fn_sigs, - } + LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.liberated_fn_sigs } } pub fn fru_field_types(&self) -> LocalTableInContext<'_, Vec>> { - LocalTableInContext { local_id_root: self.local_id_root, data: &self.fru_field_types } + LocalTableInContext { hir_owner: self.hir_owner, data: &self.fru_field_types } } pub fn fru_field_types_mut(&mut self) -> LocalTableInContextMut<'_, Vec>> { - LocalTableInContextMut { - local_id_root: self.local_id_root, - data: &mut self.fru_field_types, - } + LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.fru_field_types } } pub fn is_coercion_cast(&self, hir_id: hir::HirId) -> bool { - validate_hir_id_for_typeck_tables(self.local_id_root, hir_id, true); + validate_hir_id_for_typeck_tables(self.hir_owner, hir_id, true); self.coercion_casts.contains(&hir_id.local_id) } @@ -699,7 +670,7 @@ impl<'tcx> TypeckTables<'tcx> { impl<'a, 'tcx> HashStable> for TypeckTables<'tcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let ty::TypeckTables { - local_id_root, + hir_owner, ref type_dependent_defs, ref field_indices, ref user_provided_types, @@ -718,7 +689,6 @@ impl<'a, 'tcx> HashStable> for TypeckTables<'tcx> { ref used_trait_imports, tainted_by_errors, - ref free_region_map, ref concrete_opaque_types, ref upvar_list, ref generator_interior_types, @@ -737,16 +707,12 @@ impl<'a, 'tcx> HashStable> for TypeckTables<'tcx> { hash_stable_hashmap(hcx, hasher, upvar_capture_map, |up_var_id, hcx| { let ty::UpvarId { var_path, closure_expr_id } = *up_var_id; - let local_id_root = local_id_root.expect("trying to hash invalid TypeckTables"); + assert_eq!(Some(var_path.hir_id.owner), hir_owner); - let var_owner_def_id = - DefId { krate: local_id_root.krate, index: var_path.hir_id.owner }; - let closure_def_id = - DefId { krate: local_id_root.krate, index: closure_expr_id.to_def_id().index }; ( - hcx.def_path_hash(var_owner_def_id), + hcx.local_def_path_hash(var_path.hir_id.owner), var_path.hir_id.local_id, - hcx.def_path_hash(closure_def_id), + hcx.local_def_path_hash(closure_expr_id), ) }); @@ -756,7 +722,6 @@ impl<'a, 'tcx> HashStable> for TypeckTables<'tcx> { coercion_casts.hash_stable(hcx, hasher); used_trait_imports.hash_stable(hcx, hasher); tainted_by_errors.hash_stable(hcx, hasher); - free_region_map.hash_stable(hcx, hasher); concrete_opaque_types.hash_stable(hcx, hasher); upvar_list.hash_stable(hcx, hasher); generator_interior_types.hash_stable(hcx, hasher); @@ -938,7 +903,7 @@ pub struct GlobalCtxt<'tcx> { interners: CtxtInterners<'tcx>, - cstore: Box, + pub(crate) cstore: Box, pub sess: &'tcx Session, @@ -966,13 +931,13 @@ pub struct GlobalCtxt<'tcx> { /// Map indicating what traits are in scope for places where this /// is relevant; generated by resolve. - trait_map: FxHashMap>>, + trait_map: FxHashMap>>, /// Export map produced by name resolution. export_map: FxHashMap>>, - /// This should usually be accessed with the `tcx.hir()` method. - pub(crate) hir_map: hir_map::Map<'tcx>, + pub(crate) untracked_crate: &'tcx hir::Crate<'tcx>, + pub(crate) definitions: &'tcx Definitions, /// A map from `DefPathHash` -> `DefId`. Includes `DefId`s from the local crate /// as well as all upstream crates. Only populated in incremental mode. @@ -1017,9 +982,10 @@ pub struct GlobalCtxt<'tcx> { /// Stores the value of constants (and deduplicates the actual memory) allocation_interner: ShardedHashMap<&'tcx Allocation, ()>, + /// Stores memory for globals (statics/consts). pub alloc_map: Lock>, - layout_interner: ShardedHashMap<&'tcx LayoutDetails, ()>, + layout_interner: ShardedHashMap<&'tcx Layout, ()>, output_filenames: Arc, } @@ -1074,7 +1040,7 @@ impl<'tcx> TyCtxt<'tcx> { self.const_stability_interner.intern(stab, |stab| self.arena.alloc(stab)) } - pub fn intern_layout(self, layout: LayoutDetails) -> &'tcx LayoutDetails { + pub fn intern_layout(self, layout: Layout) -> &'tcx Layout { self.layout_interner.intern(layout, |layout| self.arena.alloc(layout)) } @@ -1116,7 +1082,9 @@ impl<'tcx> TyCtxt<'tcx> { extern_providers: ty::query::Providers<'tcx>, arena: &'tcx WorkerLocal>, resolutions: ty::ResolverOutputs, - hir: hir_map::Map<'tcx>, + krate: &'tcx hir::Crate<'tcx>, + definitions: &'tcx Definitions, + dep_graph: DepGraph, on_disk_query_result_cache: query::OnDiskCache<'tcx>, crate_name: &str, output_filenames: &OutputFilenames, @@ -1128,7 +1096,6 @@ impl<'tcx> TyCtxt<'tcx> { let common_types = CommonTypes::new(&interners); let common_lifetimes = CommonLifetimes::new(&interners); let common_consts = CommonConsts::new(&interners, &common_types); - let dep_graph = hir.dep_graph.clone(); let cstore = resolutions.cstore; let crates = cstore.crates_untracked(); let max_cnum = crates.iter().map(|c| c.as_usize()).max().unwrap_or(0); @@ -1139,7 +1106,7 @@ impl<'tcx> TyCtxt<'tcx> { let def_path_tables = crates .iter() .map(|&cnum| (cnum, cstore.def_path_table(cnum))) - .chain(iter::once((LOCAL_CRATE, hir.definitions().def_path_table()))); + .chain(iter::once((LOCAL_CRATE, definitions.def_path_table()))); // Precompute the capacity of the hashmap so we don't have to // re-allocate when populating it. @@ -1159,11 +1126,11 @@ impl<'tcx> TyCtxt<'tcx> { let mut trait_map: FxHashMap<_, FxHashMap<_, _>> = FxHashMap::default(); for (k, v) in resolutions.trait_map { - let hir_id = hir.node_to_hir_id(k); + let hir_id = definitions.node_to_hir_id(k); let map = trait_map.entry(hir_id.owner).or_default(); let v = v .into_iter() - .map(|tc| tc.map_import_ids(|id| hir.definitions().node_to_hir_id(id))) + .map(|tc| tc.map_import_ids(|id| definitions.node_to_hir_id(id))) .collect(); map.insert(hir_id.local_id, StableVec::new(v)); } @@ -1185,28 +1152,31 @@ impl<'tcx> TyCtxt<'tcx> { .export_map .into_iter() .map(|(k, v)| { - let exports: Vec<_> = - v.into_iter().map(|e| e.map_id(|id| hir.node_to_hir_id(id))).collect(); + let exports: Vec<_> = v + .into_iter() + .map(|e| e.map_id(|id| definitions.node_to_hir_id(id))) + .collect(); (k, exports) }) .collect(), maybe_unused_trait_imports: resolutions .maybe_unused_trait_imports .into_iter() - .map(|id| hir.local_def_id_from_node_id(id)) + .map(|id| definitions.local_def_id(id)) .collect(), maybe_unused_extern_crates: resolutions .maybe_unused_extern_crates .into_iter() - .map(|(id, sp)| (hir.local_def_id_from_node_id(id), sp)) + .map(|(id, sp)| (definitions.local_def_id(id), sp)) .collect(), glob_map: resolutions .glob_map .into_iter() - .map(|(id, names)| (hir.local_def_id_from_node_id(id), names)) + .map(|(id, names)| (definitions.local_def_id(id), names)) .collect(), extern_prelude: resolutions.extern_prelude, - hir_map: hir, + untracked_crate: krate, + definitions, def_path_hash_to_def_id, queries: query::Queries::new(providers, extern_providers, on_disk_query_result_cache), rcache: Default::default(), @@ -1264,8 +1234,8 @@ impl<'tcx> TyCtxt<'tcx> { self.features_query(LOCAL_CRATE) } - pub fn def_key(self, id: DefId) -> hir_map::DefKey { - if id.is_local() { self.hir().def_key(id) } else { self.cstore.def_key(id) } + pub fn def_key(self, id: DefId) -> rustc_hir::definitions::DefKey { + if let Some(id) = id.as_local() { self.hir().def_key(id) } else { self.cstore.def_key(id) } } /// Converts a `DefId` into its fully expanded `DefPath` (every @@ -1273,8 +1243,12 @@ impl<'tcx> TyCtxt<'tcx> { /// /// Note that if `id` is not local to this crate, the result will /// be a non-local `DefPath`. - pub fn def_path(self, id: DefId) -> hir_map::DefPath { - if id.is_local() { self.hir().def_path(id) } else { self.cstore.def_path(id) } + pub fn def_path(self, id: DefId) -> rustc_hir::definitions::DefPath { + if let Some(id) = id.as_local() { + self.hir().def_path(id) + } else { + self.cstore.def_path(id) + } } /// Returns whether or not the crate with CrateNum 'cnum' @@ -1284,9 +1258,9 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline] - pub fn def_path_hash(self, def_id: DefId) -> hir_map::DefPathHash { - if def_id.is_local() { - self.hir().definitions().def_path_hash(def_id.index) + pub fn def_path_hash(self, def_id: DefId) -> rustc_hir::definitions::DefPathHash { + if let Some(def_id) = def_id.as_local() { + self.definitions.def_path_hash(def_id) } else { self.cstore.def_path_hash(def_id) } @@ -1321,7 +1295,7 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn encode_metadata(self) -> EncodedMetadata { - let _prof_timer = self.prof.generic_activity("generate_crate_metadata"); + let _prof_timer = self.prof.verbose_generic_activity("generate_crate_metadata"); self.cstore.encode_metadata(self) } @@ -1333,9 +1307,9 @@ impl<'tcx> TyCtxt<'tcx> { #[inline(always)] pub fn create_stable_hashing_context(self) -> StableHashingContext<'tcx> { - let krate = self.gcx.hir_map.untracked_krate(); + let krate = self.gcx.untracked_crate; - StableHashingContext::new(self.sess, krate, self.hir().definitions(), &*self.cstore) + StableHashingContext::new(self.sess, krate, self.definitions, &*self.cstore) } // This method makes sure that we have a DepNode and a Fingerprint for @@ -1445,11 +1419,11 @@ impl<'tcx> TyCtxt<'tcx> { _ => return None, }; - return Some(FreeRegionInfo { + Some(FreeRegionInfo { def_id: suitable_region_binding_scope, boundregion: bound_region, is_impl_item, - }); + }) } pub fn return_type_impl_trait(&self, scope_def_id: DefId) -> Option<(Ty<'tcx>, Span)> { @@ -1515,20 +1489,21 @@ impl<'tcx> TyCtxt<'tcx> { /// Returns a displayable description and article for the given `def_id` (e.g. `("a", "struct")`). pub fn article_and_description(&self, def_id: DefId) -> (&'static str, &'static str) { - match self.def_key(def_id).disambiguated_data.data { - DefPathData::TypeNs(..) | DefPathData::ValueNs(..) | DefPathData::MacroNs(..) => { - let kind = self.def_kind(def_id).unwrap(); - (kind.article(), kind.descr(def_id)) - } - DefPathData::ClosureExpr => match self.generator_kind(def_id) { - None => ("a", "closure"), - Some(rustc_hir::GeneratorKind::Async(..)) => ("an", "async closure"), - Some(rustc_hir::GeneratorKind::Gen) => ("a", "generator"), - }, - DefPathData::LifetimeNs(..) => ("a", "lifetime"), - DefPathData::Impl => ("an", "implementation"), - _ => bug!("article_and_description called on def_id {:?}", def_id), - } + self.def_kind(def_id) + .map(|def_kind| (def_kind.article(), def_kind.descr(def_id))) + .unwrap_or_else(|| match self.def_key(def_id).disambiguated_data.data { + DefPathData::ClosureExpr => match self.generator_kind(def_id) { + None => ("a", "closure"), + Some(rustc_hir::GeneratorKind::Async(..)) => ("an", "async closure"), + Some(rustc_hir::GeneratorKind::Gen) => ("a", "generator"), + }, + DefPathData::LifetimeNs(..) => ("a", "lifetime"), + DefPathData::Impl => ("an", "implementation"), + DefPathData::TypeNs(..) | DefPathData::ValueNs(..) | DefPathData::MacroNs(..) => { + unreachable!() + } + _ => bug!("article_and_description called on def_id {:?}", def_id), + }) } } @@ -2750,18 +2725,15 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { }; providers.lookup_stability = |tcx, id| { - assert_eq!(id.krate, LOCAL_CRATE); - let id = tcx.hir().definitions().def_index_to_hir_id(id.index); + let id = tcx.hir().local_def_id_to_hir_id(id.expect_local()); tcx.stability().local_stability(id) }; providers.lookup_const_stability = |tcx, id| { - assert_eq!(id.krate, LOCAL_CRATE); - let id = tcx.hir().definitions().def_index_to_hir_id(id.index); + let id = tcx.hir().local_def_id_to_hir_id(id.expect_local()); tcx.stability().local_const_stability(id) }; providers.lookup_deprecation_entry = |tcx, id| { - assert_eq!(id.krate, LOCAL_CRATE); - let id = tcx.hir().definitions().def_index_to_hir_id(id.index); + let id = tcx.hir().local_def_id_to_hir_id(id.expect_local()); tcx.stability().local_deprecation_entry(id) }; providers.extern_mod_stmt_cnum = |tcx, id| { diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 4adca6c7d9772..3f4f2407f1e6e 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -978,17 +978,27 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector { // ignore the inputs to a projection, as they may not appear // in the normalized form if self.just_constrained { - match t.kind { - ty::Projection(..) | ty::Opaque(..) => { - return false; - } - _ => {} + if let ty::Projection(..) | ty::Opaque(..) = t.kind { + return false; } } t.super_visit_with(self) } + fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool { + // if we are only looking for "constrained" region, we have to + // ignore the inputs of an unevaluated const, as they may not appear + // in the normalized form + if self.just_constrained { + if let ty::ConstKind::Unevaluated(..) = c.val { + return false; + } + } + + c.super_visit_with(self) + } + fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { if let ty::ReLateBound(debruijn, br) = *r { if debruijn == self.current_index { diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs index 144e3bc9c8bc6..b166c4dea0c85 100644 --- a/src/librustc/ty/inhabitedness/mod.rs +++ b/src/librustc/ty/inhabitedness/mod.rs @@ -90,30 +90,46 @@ impl<'tcx> TyCtxt<'tcx> { /// ``` /// This code should only compile in modules where the uninhabitedness of Foo is /// visible. - pub fn is_ty_uninhabited_from(self, module: DefId, ty: Ty<'tcx>) -> bool { + pub fn is_ty_uninhabited_from( + self, + module: DefId, + ty: Ty<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> bool { // To check whether this type is uninhabited at all (not just from the // given node), you could check whether the forest is empty. // ``` // forest.is_empty() // ``` - ty.uninhabited_from(self).contains(self, module) + ty.uninhabited_from(self, param_env).contains(self, module) } - pub fn is_ty_uninhabited_from_any_module(self, ty: Ty<'tcx>) -> bool { - !ty.uninhabited_from(self).is_empty() + pub fn is_ty_uninhabited_from_any_module( + self, + ty: Ty<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> bool { + !ty.uninhabited_from(self, param_env).is_empty() } } impl<'tcx> AdtDef { /// Calculates the forest of `DefId`s from which this ADT is visibly uninhabited. - fn uninhabited_from(&self, tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>) -> DefIdForest { + fn uninhabited_from( + &self, + tcx: TyCtxt<'tcx>, + substs: SubstsRef<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> DefIdForest { // Non-exhaustive ADTs from other crates are always considered inhabited. if self.is_variant_list_non_exhaustive() && !self.did.is_local() { DefIdForest::empty() } else { DefIdForest::intersection( tcx, - self.variants.iter().map(|v| v.uninhabited_from(tcx, substs, self.adt_kind())), + self.variants + .iter() + .map(|v| v.uninhabited_from(tcx, substs, self.adt_kind(), param_env)), ) } } @@ -126,6 +142,7 @@ impl<'tcx> VariantDef { tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, adt_kind: AdtKind, + param_env: ty::ParamEnv<'tcx>, ) -> DefIdForest { let is_enum = match adt_kind { // For now, `union`s are never considered uninhabited. @@ -140,7 +157,7 @@ impl<'tcx> VariantDef { } else { DefIdForest::union( tcx, - self.fields.iter().map(|f| f.uninhabited_from(tcx, substs, is_enum)), + self.fields.iter().map(|f| f.uninhabited_from(tcx, substs, is_enum, param_env)), ) } } @@ -153,8 +170,9 @@ impl<'tcx> FieldDef { tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, is_enum: bool, + param_env: ty::ParamEnv<'tcx>, ) -> DefIdForest { - let data_uninhabitedness = move || self.ty(tcx, substs).uninhabited_from(tcx); + let data_uninhabitedness = move || self.ty(tcx, substs).uninhabited_from(tcx, param_env); // FIXME(canndrew): Currently enum fields are (incorrectly) stored with // `Visibility::Invisible` so we need to override `self.vis` if we're // dealing with an enum. @@ -176,20 +194,21 @@ impl<'tcx> FieldDef { impl<'tcx> TyS<'tcx> { /// Calculates the forest of `DefId`s from which this type is visibly uninhabited. - fn uninhabited_from(&self, tcx: TyCtxt<'tcx>) -> DefIdForest { + fn uninhabited_from(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> DefIdForest { match self.kind { - Adt(def, substs) => def.uninhabited_from(tcx, substs), + Adt(def, substs) => def.uninhabited_from(tcx, substs, param_env), Never => DefIdForest::full(tcx), - Tuple(ref tys) => { - DefIdForest::union(tcx, tys.iter().map(|ty| ty.expect_ty().uninhabited_from(tcx))) - } + Tuple(ref tys) => DefIdForest::union( + tcx, + tys.iter().map(|ty| ty.expect_ty().uninhabited_from(tcx, param_env)), + ), - Array(ty, len) => match len.try_eval_usize(tcx, ty::ParamEnv::empty()) { + Array(ty, len) => match len.try_eval_usize(tcx, param_env) { // If the array is definitely non-empty, it's uninhabited if // the type of its elements is uninhabited. - Some(n) if n != 0 => ty.uninhabited_from(tcx), + Some(n) if n != 0 => ty.uninhabited_from(tcx, param_env), _ => DefIdForest::empty(), }, diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 445df76cd32be..fcfee0fea85af 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -39,6 +39,10 @@ pub enum InstanceDef<'tcx> { /// `::call_*` /// `DefId` is `FnTrait::call_*`. + /// + /// NB: the (`fn` pointer) type must currently be monomorphic to avoid double substitution + /// problems with the MIR shim bodies. `Instance::resolve` enforces this. + // FIXME(#69925) support polymorphic MIR shim bodies properly instead. FnPtrShim(DefId, Ty<'tcx>), /// `::fn`, "direct calls" of which are implicitly @@ -57,9 +61,17 @@ pub enum InstanceDef<'tcx> { /// The `DefId` is for `core::ptr::drop_in_place`. /// The `Option>` is either `Some(T)`, or `None` for empty drop /// glue. + /// + /// NB: the type must currently be monomorphic to avoid double substitution + /// problems with the MIR shim bodies. `Instance::resolve` enforces this. + // FIXME(#69925) support polymorphic MIR shim bodies properly instead. DropGlue(DefId, Option>), ///`::clone` shim. + /// + /// NB: the type must currently be monomorphic to avoid double substitution + /// problems with the MIR shim bodies. `Instance::resolve` enforces this. + // FIXME(#69925) support polymorphic MIR shim bodies properly instead. CloneShim(DefId, Ty<'tcx>), } @@ -154,7 +166,7 @@ impl<'tcx> InstanceDef<'tcx> { /// Note that this is only a hint. See the documentation for /// `generates_cgu_internal_copy` for more information. pub fn requires_inline(&self, tcx: TyCtxt<'tcx>) -> bool { - use crate::hir::map::DefPathData; + use rustc_hir::definitions::DefPathData; let def_id = match *self { ty::InstanceDef::Item(def_id) => def_id, ty::InstanceDef::DropGlue(_, Some(_)) => return false, @@ -329,7 +341,7 @@ impl<'tcx> Instance<'tcx> { substs: ty::SubstsRef<'tcx>, requested_kind: ty::ClosureKind, ) -> Instance<'tcx> { - let actual_kind = substs.as_closure().kind(def_id, tcx); + let actual_kind = substs.as_closure().kind(); match needs_fn_once_adapter_shim(actual_kind, requested_kind) { Ok(true) => Instance::fn_once_adapter_instance(tcx, def_id, substs), @@ -360,7 +372,7 @@ impl<'tcx> Instance<'tcx> { let self_ty = tcx.mk_closure(closure_did, substs); - let sig = substs.as_closure().sig(closure_did, tcx); + let sig = substs.as_closure().sig(); let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); assert_eq!(sig.inputs().len(), 1); let substs = tcx.mk_substs_trait(self_ty, &[sig.inputs()[0].into()]); @@ -369,8 +381,30 @@ impl<'tcx> Instance<'tcx> { Instance { def, substs } } - pub fn is_vtable_shim(&self) -> bool { - if let InstanceDef::VtableShim(..) = self.def { true } else { false } + /// FIXME(#69925) Depending on the kind of `InstanceDef`, the MIR body associated with an + /// instance is expressed in terms of the generic parameters of `self.def_id()`, and in other + /// cases the MIR body is expressed in terms of the types found in the substitution array. + /// In the former case, we want to substitute those generic types and replace them with the + /// values from the substs when monomorphizing the function body. But in the latter case, we + /// don't want to do that substitution, since it has already been done effectively. + /// + /// This function returns `Some(substs)` in the former case and None otherwise -- i.e., if + /// this function returns `None`, then the MIR body does not require substitution during + /// monomorphization. + pub fn substs_for_mir_body(&self) -> Option> { + match self.def { + InstanceDef::CloneShim(..) + | InstanceDef::DropGlue(_, Some(_)) => None, + InstanceDef::ClosureOnceShim { .. } + | InstanceDef::DropGlue(..) + // FIXME(#69925): `FnPtrShim` should be in the other branch. + | InstanceDef::FnPtrShim(..) + | InstanceDef::Item(_) + | InstanceDef::Intrinsic(..) + | InstanceDef::ReifyShim(..) + | InstanceDef::Virtual(..) + | InstanceDef::VtableShim(..) => Some(self.substs), + } } } diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index dedb3035cedb3..ad4352c010572 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1,30 +1,28 @@ -use crate::session::{self, DataTypeKind}; +use crate::ich::StableHashingContext; +use crate::mir::{GeneratorLayout, GeneratorSavedLocal}; +use crate::ty::subst::Subst; use crate::ty::{self, subst::SubstsRef, ReprOptions, Ty, TyCtxt, TypeFoldable}; use rustc_ast::ast::{self, Ident, IntTy, UintTy}; use rustc_attr as attr; -use rustc_span::DUMMY_SP; - -use std::cmp; -use std::fmt; -use std::iter; -use std::mem; -use std::ops::Bound; - -use crate::ich::StableHashingContext; -use crate::mir::{GeneratorLayout, GeneratorSavedLocal}; -use crate::ty::subst::Subst; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir as hir; use rustc_index::bit_set::BitSet; use rustc_index::vec::{Idx, IndexVec}; - +use rustc_session::{DataTypeKind, FieldInfo, SizeKind, VariantInfo}; +use rustc_span::DUMMY_SP; use rustc_target::abi::call::{ ArgAbi, ArgAttribute, ArgAttributes, Conv, FnAbi, PassMode, Reg, RegKind, }; pub use rustc_target::abi::*; use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec}; +use std::cmp; +use std::fmt; +use std::iter; +use std::mem; +use std::ops::Bound; + pub trait IntegerExt { fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx>; fn from_attr(cx: &C, ity: attr::IntType) -> Integer; @@ -183,7 +181,7 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> { fn layout_raw<'tcx>( tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, -) -> Result<&'tcx LayoutDetails, LayoutError<'tcx>> { +) -> Result<&'tcx Layout, LayoutError<'tcx>> { ty::tls::with_related_context(tcx, move |icx| { let rec_limit = *tcx.sess.recursion_limit.get(); let (param_env, ty) = query.into_parts(); @@ -242,7 +240,7 @@ fn invert_mapping(map: &[u32]) -> Vec { } impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { - fn scalar_pair(&self, a: Scalar, b: Scalar) -> LayoutDetails { + fn scalar_pair(&self, a: Scalar, b: Scalar) -> Layout { let dl = self.data_layout(); let b_align = b.value.align(dl); let align = a.value.align(dl).max(b_align).max(dl.aggregate_align); @@ -256,7 +254,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { .chain(Niche::from_scalar(dl, Size::ZERO, a.clone())) .max_by_key(|niche| niche.available(dl)); - LayoutDetails { + Layout { variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldPlacement::Arbitrary { offsets: vec![Size::ZERO, b_offset], @@ -275,7 +273,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { fields: &[TyLayout<'_>], repr: &ReprOptions, kind: StructKind, - ) -> Result> { + ) -> Result> { let dl = self.data_layout(); let pack = repr.pack; if pack.is_some() && repr.align.is_some() { @@ -284,8 +282,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align }; - let mut sized = true; - let mut offsets = vec![Size::ZERO; fields.len()]; let mut inverse_memory_index: Vec = (0..fields.len() as u32).collect(); let mut optimize = !repr.inhibit_struct_field_reordering_opt(); @@ -322,6 +318,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // At the bottom of this function, we invert `inverse_memory_index` to // produce `memory_index` (see `invert_mapping`). + let mut sized = true; + let mut offsets = vec![Size::ZERO; fields.len()]; let mut offset = Size::ZERO; let mut largest_niche = None; let mut largest_niche_available = 0; @@ -383,12 +381,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // Field 5 would be the first element, so memory_index is i: // Note: if we didn't optimize, it's already right. - let memory_index; - if optimize { - memory_index = invert_mapping(&inverse_memory_index); - } else { - memory_index = inverse_memory_index; - } + let memory_index = + if optimize { invert_mapping(&inverse_memory_index) } else { inverse_memory_index }; let size = min_size.align_to(align.abi); let mut abi = Abi::Aggregate { sized }; @@ -428,17 +422,11 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { ( Some(( i, - &TyLayout { - details: &LayoutDetails { abi: Abi::Scalar(ref a), .. }, - .. - }, + &TyLayout { layout: &Layout { abi: Abi::Scalar(ref a), .. }, .. }, )), Some(( j, - &TyLayout { - details: &LayoutDetails { abi: Abi::Scalar(ref b), .. }, - .. - }, + &TyLayout { layout: &Layout { abi: Abi::Scalar(ref b), .. }, .. }, )), None, ) => { @@ -476,7 +464,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { abi = Abi::Uninhabited; } - Ok(LayoutDetails { + Ok(Layout { variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldPlacement::Arbitrary { offsets, memory_index }, abi, @@ -486,7 +474,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { }) } - fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx LayoutDetails, LayoutError<'tcx>> { + fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'tcx>> { let tcx = self.tcx; let param_env = self.param_env; let dl = self.data_layout(); @@ -495,8 +483,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { assert!(bits <= 128); Scalar { value, valid_range: 0..=(!0 >> (128 - bits)) } }; - let scalar = - |value: Primitive| tcx.intern_layout(LayoutDetails::scalar(self, scalar_unit(value))); + let scalar = |value: Primitive| tcx.intern_layout(Layout::scalar(self, scalar_unit(value))); let univariant = |fields: &[TyLayout<'_>], repr: &ReprOptions, kind| { Ok(tcx.intern_layout(self.univariant_uninterned(ty, fields, repr, kind)?)) @@ -505,11 +492,11 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { Ok(match ty.kind { // Basic scalars. - ty::Bool => tcx.intern_layout(LayoutDetails::scalar( + ty::Bool => tcx.intern_layout(Layout::scalar( self, Scalar { value: Int(I8, false), valid_range: 0..=1 }, )), - ty::Char => tcx.intern_layout(LayoutDetails::scalar( + ty::Char => tcx.intern_layout(Layout::scalar( self, Scalar { value: Int(I32, false), valid_range: 0..=0x10FFFF }, )), @@ -522,11 +509,11 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { ty::FnPtr(_) => { let mut ptr = scalar_unit(Pointer); ptr.valid_range = 1..=*ptr.valid_range.end(); - tcx.intern_layout(LayoutDetails::scalar(self, ptr)) + tcx.intern_layout(Layout::scalar(self, ptr)) } // The never type. - ty::Never => tcx.intern_layout(LayoutDetails { + ty::Never => tcx.intern_layout(Layout { variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldPlacement::Union(0), abi: Abi::Uninhabited, @@ -544,13 +531,13 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let pointee = tcx.normalize_erasing_regions(param_env, pointee); if pointee.is_sized(tcx.at(DUMMY_SP), param_env) { - return Ok(tcx.intern_layout(LayoutDetails::scalar(self, data_ptr))); + return Ok(tcx.intern_layout(Layout::scalar(self, data_ptr))); } let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env); let metadata = match unsized_part.kind { ty::Foreign(..) => { - return Ok(tcx.intern_layout(LayoutDetails::scalar(self, data_ptr))); + return Ok(tcx.intern_layout(Layout::scalar(self, data_ptr))); } ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)), ty::Dynamic(..) => { @@ -587,7 +574,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let largest_niche = if count != 0 { element.largest_niche.clone() } else { None }; - tcx.intern_layout(LayoutDetails { + tcx.intern_layout(Layout { variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldPlacement::Array { stride: element.size, count }, abi, @@ -598,7 +585,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } ty::Slice(element) => { let element = self.layout_of(element)?; - tcx.intern_layout(LayoutDetails { + tcx.intern_layout(Layout { variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldPlacement::Array { stride: element.size, count: 0 }, abi: Abi::Aggregate { sized: false }, @@ -607,7 +594,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { size: Size::ZERO, }) } - ty::Str => tcx.intern_layout(LayoutDetails { + ty::Str => tcx.intern_layout(Layout { variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldPlacement::Array { stride: Size::from_bytes(1), count: 0 }, abi: Abi::Aggregate { sized: false }, @@ -634,8 +621,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { ty::Generator(def_id, substs, _) => self.generator_layout(ty, def_id, substs)?, - ty::Closure(def_id, ref substs) => { - let tys = substs.as_closure().upvar_tys(def_id, tcx); + ty::Closure(_, ref substs) => { + let tys = substs.as_closure().upvar_tys(); univariant( &tys.map(|ty| self.layout_of(ty)).collect::, _>>()?, &ReprOptions::default(), @@ -676,7 +663,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let align = dl.vector_align(size); let size = size.align_to(align.abi); - tcx.intern_layout(LayoutDetails { + tcx.intern_layout(Layout { variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldPlacement::Array { stride: element.size, count }, abi: Abi::Vector { element: scalar, count }, @@ -752,7 +739,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { align = align.min(AbiAndPrefAlign::new(pack)); } - return Ok(tcx.intern_layout(LayoutDetails { + return Ok(tcx.intern_layout(Layout { variants: Variants::Single { index }, fields: FieldPlacement::Union(variants[index].len()), abi, @@ -782,8 +769,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { present_first @ Some(_) => present_first, // Uninhabited because it has no variants, or only absent ones. None if def.is_enum() => return tcx.layout_raw(param_env.and(tcx.types.never)), - // if it's a struct, still compute a layout so that we can still compute the - // field offsets + // If it's a struct, still compute a layout so that we can still compute the + // field offsets. None => Some(VariantIdx::new(0)), }; @@ -913,18 +900,19 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let count = (niche_variants.end().as_u32() - niche_variants.start().as_u32() + 1) as u128; - // FIXME(#62691) use the largest niche across all fields, - // not just the first one. - for (field_index, &field) in variants[i].iter().enumerate() { - let niche = match &field.largest_niche { - Some(niche) => niche, - _ => continue, - }; - let (niche_start, niche_scalar) = match niche.reserve(self, count) { - Some(pair) => pair, - None => continue, - }; + // Find the field with the largest niche + let niche_candidate = variants[i] + .iter() + .enumerate() + .filter_map(|(j, &field)| Some((j, field.largest_niche.as_ref()?))) + .max_by_key(|(_, niche)| niche.available(dl)); + + if let Some((field_index, niche, (niche_start, niche_scalar))) = + niche_candidate.and_then(|(field_index, niche)| { + Some((field_index, niche, niche.reserve(self, count)?)) + }) + { let mut align = dl.aggregate_align; let st = variants .iter_enumerated() @@ -946,37 +934,37 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let offset = st[i].fields.offset(field_index) + niche.offset; let size = st[i].size; - let mut abi = match st[i].abi { - Abi::Scalar(_) => Abi::Scalar(niche_scalar.clone()), - Abi::ScalarPair(ref first, ref second) => { - // We need to use scalar_unit to reset the - // valid range to the maximal one for that - // primitive, because only the niche is - // guaranteed to be initialised, not the - // other primitive. - if offset.bytes() == 0 { - Abi::ScalarPair( - niche_scalar.clone(), - scalar_unit(second.value), - ) - } else { - Abi::ScalarPair( - scalar_unit(first.value), - niche_scalar.clone(), - ) + let abi = if st.iter().all(|v| v.abi.is_uninhabited()) { + Abi::Uninhabited + } else { + match st[i].abi { + Abi::Scalar(_) => Abi::Scalar(niche_scalar.clone()), + Abi::ScalarPair(ref first, ref second) => { + // We need to use scalar_unit to reset the + // valid range to the maximal one for that + // primitive, because only the niche is + // guaranteed to be initialised, not the + // other primitive. + if offset.bytes() == 0 { + Abi::ScalarPair( + niche_scalar.clone(), + scalar_unit(second.value), + ) + } else { + Abi::ScalarPair( + scalar_unit(first.value), + niche_scalar.clone(), + ) + } } + _ => Abi::Aggregate { sized: true }, } - _ => Abi::Aggregate { sized: true }, }; - if st.iter().all(|v| v.abi.is_uninhabited()) { - abi = Abi::Uninhabited; - } - let largest_niche = Niche::from_scalar(dl, offset, niche_scalar.clone()); - return Ok(tcx.intern_layout(LayoutDetails { + return Ok(tcx.intern_layout(Layout { variants: Variants::Multiple { discr: niche_scalar, discr_kind: DiscriminantKind::Niche { @@ -1171,7 +1159,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { break; } }; - let prim = match field.details.abi { + let prim = match field.abi { Abi::Scalar(ref scalar) => scalar.value, _ => { common_prim = None; @@ -1218,7 +1206,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag.clone()); - tcx.intern_layout(LayoutDetails { + tcx.intern_layout(Layout { variants: Variants::Multiple { discr: tag, discr_kind: DiscriminantKind::Tag, @@ -1249,7 +1237,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { | ty::Placeholder(..) | ty::UnnormalizedProjection(..) | ty::GeneratorWitness(..) - | ty::Infer(_) => bug!("LayoutDetails::compute: unexpected type `{}`", ty), + | ty::Infer(_) => bug!("Layout::compute: unexpected type `{}`", ty), ty::Param(_) | ty::Error => { return Err(LayoutError::Unknown(ty)); @@ -1396,7 +1384,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { ty: Ty<'tcx>, def_id: hir::def_id::DefId, substs: SubstsRef<'tcx>, - ) -> Result<&'tcx LayoutDetails, LayoutError<'tcx>> { + ) -> Result<&'tcx Layout, LayoutError<'tcx>> { use SavedLocalEligibility::*; let tcx = self.tcx; @@ -1408,13 +1396,16 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // Build a prefix layout, including "promoting" all ineligible // locals as part of the prefix. We compute the layout of all of // these fields at once to get optimal packing. - let discr_index = substs.as_generator().prefix_tys(def_id, tcx).count(); - // FIXME(eddyb) set the correct vaidity range for the discriminant. - let discr_layout = self.layout_of(substs.as_generator().discr_ty(tcx))?; - let discr = match &discr_layout.abi { - Abi::Scalar(s) => s.clone(), - _ => bug!(), - }; + let discr_index = substs.as_generator().prefix_tys().count(); + + // `info.variant_fields` already accounts for the reserved variants, so no need to add them. + let max_discr = (info.variant_fields.len() - 1) as u128; + let discr_int = Integer::fit_unsigned(max_discr); + let discr_int_ty = discr_int.to_ty(tcx, false); + let discr = Scalar { value: Primitive::Int(discr_int, false), valid_range: 0..=max_discr }; + let discr_layout = self.tcx.intern_layout(Layout::scalar(self, discr.clone())); + let discr_layout = TyLayout { ty: discr_int_ty, layout: discr_layout }; + let promoted_layouts = ineligible_locals .iter() .map(|local| subst_field(info.field_tys[local])) @@ -1422,7 +1413,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { .map(|ty| self.layout_of(ty)); let prefix_layouts = substs .as_generator() - .prefix_tys(def_id, tcx) + .prefix_tys() .map(|ty| self.layout_of(ty)) .chain(iter::once(Ok(discr_layout))) .chain(promoted_layouts) @@ -1562,7 +1553,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { Abi::Aggregate { sized: true } }; - let layout = tcx.intern_layout(LayoutDetails { + let layout = tcx.intern_layout(Layout { variants: Variants::Multiple { discr, discr_kind: DiscriminantKind::Tag, @@ -1648,7 +1639,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { if min_size < field_end { min_size = field_end; } - session::FieldInfo { + FieldInfo { name: name.to_string(), offset: offset.bytes(), size: field_layout.size.bytes(), @@ -1658,13 +1649,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { }) .collect(); - session::VariantInfo { + VariantInfo { name: n.map(|n| n.to_string()), - kind: if layout.is_unsized() { - session::SizeKind::Min - } else { - session::SizeKind::Exact - }, + kind: if layout.is_unsized() { SizeKind::Min } else { SizeKind::Exact }, align: layout.align.abi.bytes(), size: if min_size.bytes() == 0 { layout.size.bytes() } else { min_size.bytes() }, fields: field_info, @@ -1915,8 +1902,8 @@ impl<'tcx> LayoutOf for LayoutCx<'tcx, TyCtxt<'tcx>> { fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyLayout { let param_env = self.param_env.with_reveal_all(); let ty = self.tcx.normalize_erasing_regions(param_env, ty); - let details = self.tcx.layout_raw(param_env.and(ty))?; - let layout = TyLayout { ty, details }; + let layout = self.tcx.layout_raw(param_env.and(ty))?; + let layout = TyLayout { ty, layout }; // N.B., this recording is normally disabled; when enabled, it // can however trigger recursive invocations of `layout_of`. @@ -1939,8 +1926,8 @@ impl LayoutOf for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> { fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyLayout { let param_env = self.param_env.with_reveal_all(); let ty = self.tcx.normalize_erasing_regions(param_env, ty); - let details = self.tcx.layout_raw(param_env.and(ty))?; - let layout = TyLayout { ty, details }; + let layout = self.tcx.layout_raw(param_env.and(ty))?; + let layout = TyLayout { ty, layout }; // N.B., this recording is normally disabled; when enabled, it // can however trigger recursive invocations of `layout_of`. @@ -1989,13 +1976,21 @@ where + HasParamEnv<'tcx>, { fn for_variant(this: TyLayout<'tcx>, cx: &C, variant_index: VariantIdx) -> TyLayout<'tcx> { - let details = match this.variants { - Variants::Single { index } if index == variant_index => this.details, + let layout = match this.variants { + Variants::Single { index } + // If all variants but one are uninhabited, the variant layout is the enum layout. + if index == variant_index && + // Don't confuse variants of uninhabited enums with the enum itself. + // For more details see https://github.com/rust-lang/rust/issues/69763. + this.fields != FieldPlacement::Union(0) => + { + this.layout + } Variants::Single { index } => { // Deny calling for_variant more than once for non-Single enums. - if let Ok(layout) = cx.layout_of(this.ty).to_result() { - assert_eq!(layout.variants, Variants::Single { index }); + if let Ok(original_layout) = cx.layout_of(this.ty).to_result() { + assert_eq!(original_layout.variants, Variants::Single { index }); } let fields = match this.ty.kind { @@ -2003,7 +1998,7 @@ where _ => bug!(), }; let tcx = cx.tcx(); - tcx.intern_layout(LayoutDetails { + tcx.intern_layout(Layout { variants: Variants::Single { index: variant_index }, fields: FieldPlacement::Union(fields), abi: Abi::Uninhabited, @@ -2016,17 +2011,17 @@ where Variants::Multiple { ref variants, .. } => &variants[variant_index], }; - assert_eq!(details.variants, Variants::Single { index: variant_index }); + assert_eq!(layout.variants, Variants::Single { index: variant_index }); - TyLayout { ty: this.ty, details } + TyLayout { ty: this.ty, layout } } fn field(this: TyLayout<'tcx>, cx: &C, i: usize) -> C::TyLayout { let tcx = cx.tcx(); let discr_layout = |discr: &Scalar| -> C::TyLayout { - let layout = LayoutDetails::scalar(cx, discr.clone()); + let layout = Layout::scalar(cx, discr.clone()); MaybeResult::from(Ok(TyLayout { - details: tcx.intern_layout(layout), + layout: tcx.intern_layout(layout), ty: discr.value.to_ty(tcx), })) }; @@ -2094,9 +2089,7 @@ where ty::Str => tcx.types.u8, // Tuples, generators and closures. - ty::Closure(def_id, ref substs) => { - substs.as_closure().upvar_tys(def_id, tcx).nth(i).unwrap() - } + ty::Closure(_, ref substs) => substs.as_closure().upvar_tys().nth(i).unwrap(), ty::Generator(def_id, ref substs, _) => match this.variants { Variants::Single { index } => substs @@ -2110,7 +2103,7 @@ where if i == discr_index { return discr_layout(discr); } - substs.as_generator().prefix_tys(def_id, tcx).nth(i).unwrap() + substs.as_generator().prefix_tys().nth(i).unwrap() } }, @@ -2297,7 +2290,7 @@ impl<'tcx> ty::Instance<'tcx> { sig } ty::Closure(def_id, substs) => { - let sig = substs.as_closure().sig(def_id, tcx); + let sig = substs.as_closure().sig(); let env_ty = tcx.closure_env_ty(def_id, substs).unwrap(); sig.map_bound(|sig| tcx.mk_fn_sig( @@ -2308,8 +2301,8 @@ impl<'tcx> ty::Instance<'tcx> { sig.abi )) } - ty::Generator(def_id, substs, _) => { - let sig = substs.as_generator().poly_sig(def_id, tcx); + ty::Generator(_, substs, _) => { + let sig = substs.as_generator().poly_sig(); let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv); let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index c2697570dda27..43982439d47c8 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -8,9 +8,6 @@ pub use self::Variance::*; use crate::arena::Arena; use crate::hir::exports::ExportMap; -use crate::hir::map as hir_map; - -use crate::ich::Fingerprint; use crate::ich::StableHashingContext; use crate::infer::canonical::Canonical; use crate::middle::cstore::CrateStoreDyn; @@ -19,7 +16,6 @@ use crate::middle::resolve_lifetime::ObjectLifetimeDefault; use crate::mir::interpret::ErrorHandled; use crate::mir::GeneratorLayout; use crate::mir::ReadOnlyBodyAndCache; -use crate::session::DataTypeKind; use crate::traits::{self, Reveal}; use crate::ty; use crate::ty::layout::VariantIdx; @@ -30,6 +26,7 @@ use rustc_ast::ast::{self, Ident, Name}; use rustc_ast::node_id::{NodeId, NodeMap, NodeSet}; use rustc_attr as attr; use rustc_data_structures::captures::Captures; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sorted_map::SortedIndexMultiMap; @@ -37,11 +34,12 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{self, par_iter, Lrc, ParallelIterator}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Namespace, Res}; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX}; use rustc_hir::{Constness, GlobMap, Node, TraitMap}; use rustc_index::vec::{Idx, IndexVec}; use rustc_macros::HashStable; use rustc_serialize::{self, Encodable, Encoder}; +use rustc_session::DataTypeKind; use rustc_span::hygiene::ExpnId; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::Span; @@ -125,7 +123,7 @@ mod sty; // Data types pub struct ResolverOutputs { - pub definitions: hir_map::Definitions, + pub definitions: rustc_hir::definitions::Definitions, pub cstore: Box, pub extern_crate_map: NodeMap, pub trait_map: TraitMap, @@ -385,7 +383,9 @@ impl Visibility { Res::Err => Visibility::Public, def => Visibility::Restricted(def.def_id()), }, - hir::VisibilityKind::Inherited => Visibility::Restricted(tcx.parent_module(id)), + hir::VisibilityKind::Inherited => { + Visibility::Restricted(tcx.parent_module(id).to_def_id()) + } } } @@ -554,24 +554,26 @@ bitflags! { /// Does this have [ConstKind::Placeholder]? const HAS_CT_PLACEHOLDER = 1 << 8; + /// `true` if there are "names" of regions and so forth + /// that are local to a particular fn/inferctxt + const HAS_FREE_LOCAL_REGIONS = 1 << 9; + /// `true` if there are "names" of types and regions and so forth /// that are local to a particular fn const HAS_FREE_LOCAL_NAMES = TypeFlags::HAS_TY_PARAM.bits - | TypeFlags::HAS_RE_PARAM.bits | TypeFlags::HAS_CT_PARAM.bits | TypeFlags::HAS_TY_INFER.bits - | TypeFlags::HAS_RE_INFER.bits | TypeFlags::HAS_CT_INFER.bits | TypeFlags::HAS_TY_PLACEHOLDER.bits - | TypeFlags::HAS_RE_PLACEHOLDER.bits - | TypeFlags::HAS_CT_PLACEHOLDER.bits; + | TypeFlags::HAS_CT_PLACEHOLDER.bits + | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits; /// Does this have [Projection] or [UnnormalizedProjection]? - const HAS_TY_PROJECTION = 1 << 9; + const HAS_TY_PROJECTION = 1 << 10; /// Does this have [Opaque]? - const HAS_TY_OPAQUE = 1 << 10; + const HAS_TY_OPAQUE = 1 << 11; /// Does this have [ConstKind::Unevaluated]? - const HAS_CT_PROJECTION = 1 << 11; + const HAS_CT_PROJECTION = 1 << 12; /// Could this type be normalized further? const HAS_PROJECTION = TypeFlags::HAS_TY_PROJECTION.bits @@ -580,21 +582,21 @@ bitflags! { /// Present if the type belongs in a local type context. /// Set for placeholders and inference variables that are not "Fresh". - const KEEP_IN_LOCAL_TCX = 1 << 12; + const KEEP_IN_LOCAL_TCX = 1 << 13; /// Is an error type reachable? - const HAS_TY_ERR = 1 << 13; + const HAS_TY_ERR = 1 << 14; /// Does this have any region that "appears free" in the type? /// Basically anything but [ReLateBound] and [ReErased]. - const HAS_FREE_REGIONS = 1 << 14; + const HAS_FREE_REGIONS = 1 << 15; /// Does this have any [ReLateBound] regions? Used to check /// if a global bound is safe to evaluate. - const HAS_RE_LATE_BOUND = 1 << 15; + const HAS_RE_LATE_BOUND = 1 << 16; /// Does this have any [ReErased] regions? - const HAS_RE_ERASED = 1 << 16; + const HAS_RE_ERASED = 1 << 17; /// Flags representing the nominal content of a type, /// computed by FlagsComputation. If you add a new nominal @@ -608,6 +610,7 @@ bitflags! { | TypeFlags::HAS_TY_PLACEHOLDER.bits | TypeFlags::HAS_RE_PLACEHOLDER.bits | TypeFlags::HAS_CT_PLACEHOLDER.bits + | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits | TypeFlags::HAS_TY_PROJECTION.bits | TypeFlags::HAS_TY_OPAQUE.bits | TypeFlags::HAS_CT_PROJECTION.bits @@ -1697,7 +1700,7 @@ rustc_index::newtype_index! { } impl UniverseIndex { - pub const ROOT: UniverseIndex = UniverseIndex::from_u32_const(0); + pub const ROOT: UniverseIndex = UniverseIndex::from_u32(0); /// Returns the "next" universe index in order -- this new index /// is considered to extend all previous universes. This @@ -2638,19 +2641,8 @@ impl<'tcx> FieldDef { /// /// You can get the environment type of a closure using /// `tcx.closure_env_ty()`. -#[derive( - Clone, - Copy, - PartialOrd, - Ord, - PartialEq, - Eq, - Hash, - Debug, - RustcEncodable, - RustcDecodable, - HashStable -)] +#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] +#[derive(HashStable)] pub enum ClosureKind { // Warning: Ordering is significant here! The ordering is chosen // because the trait Fn is a subtrait of FnMut and so in turn, and @@ -2871,8 +2863,8 @@ impl<'tcx> TyCtxt<'tcx> { _ => false, } } else { - match self.def_kind(def_id).expect("no def for `DefId`") { - DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy => true, + match self.def_kind(def_id) { + Some(DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy) => true, _ => false, } }; @@ -2993,7 +2985,7 @@ impl<'tcx> TyCtxt<'tcx> { let def_key = self.def_key(id); match def_key.disambiguated_data.data { // The name of a constructor is that of its parent. - hir_map::DefPathData::Ctor => { + rustc_hir::definitions::DefPathData::Ctor => { self.item_name(DefId { krate: id.krate, index: def_key.parent.unwrap() }) } _ => def_key.disambiguated_data.data.get_opt_name().unwrap_or_else(|| { @@ -3050,17 +3042,7 @@ impl<'tcx> TyCtxt<'tcx> { /// If the given defid describes a method belonging to an impl, returns the /// `DefId` of the impl that the method belongs to; otherwise, returns `None`. pub fn impl_of_method(self, def_id: DefId) -> Option { - let item = if def_id.krate != LOCAL_CRATE { - if let Some(DefKind::AssocFn) = self.def_kind(def_id) { - Some(self.associated_item(def_id)) - } else { - None - } - } else { - self.opt_associated_item(def_id) - }; - - item.and_then(|trait_item| match trait_item.container { + self.opt_associated_item(def_id).and_then(|trait_item| match trait_item.container { TraitContainer(_) => None, ImplContainer(def_id) => Some(def_id), }) @@ -3083,7 +3065,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn hygienic_eq(self, use_name: Ident, def_name: Ident, def_parent_def_id: DefId) -> bool { // We could use `Ident::eq` here, but we deliberately don't. The name // comparison fails frequently, and we want to avoid the expensive - // `modern()` calls required for the span comparison whenever possible. + // `normalize_to_macros_2_0()` calls required for the span comparison whenever possible. use_name.name == def_name.name && use_name .span @@ -3092,14 +3074,14 @@ impl<'tcx> TyCtxt<'tcx> { } fn expansion_that_defined(self, scope: DefId) -> ExpnId { - match scope.krate { - LOCAL_CRATE => self.hir().definitions().expansion_that_defined(scope.index), - _ => ExpnId::root(), + match scope.as_local() { + Some(scope) => self.hir().definitions().expansion_that_defined(scope), + None => ExpnId::root(), } } pub fn adjust_ident(self, mut ident: Ident, scope: DefId) -> Ident { - ident.span.modernize_and_adjust(self.expansion_that_defined(scope)); + ident.span.normalize_to_macros_2_0_and_adjust(self.expansion_that_defined(scope)); ident } @@ -3109,12 +3091,14 @@ impl<'tcx> TyCtxt<'tcx> { scope: DefId, block: hir::HirId, ) -> (Ident, DefId) { - let scope = match ident.span.modernize_and_adjust(self.expansion_that_defined(scope)) { - Some(actual_expansion) => { - self.hir().definitions().parent_module_of_macro_def(actual_expansion) - } - None => self.parent_module(block), - }; + let scope = + match ident.span.normalize_to_macros_2_0_and_adjust(self.expansion_that_defined(scope)) + { + Some(actual_expansion) => { + self.hir().definitions().parent_module_of_macro_def(actual_expansion) + } + None => self.parent_module(block).to_def_id(), + }; (ident, scope) } @@ -3142,8 +3126,12 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { context::provide(providers); erase_regions::provide(providers); layout::provide(providers); - *providers = - ty::query::Providers { trait_impls_of: trait_def::trait_impls_of_provider, ..*providers }; + super::util::bug::provide(providers); + *providers = ty::query::Providers { + trait_impls_of: trait_def::trait_impls_of_provider, + all_local_trait_impls: trait_def::all_local_trait_impls, + ..*providers + }; } /// A map for the local crate mapping each type to a vector of its diff --git a/src/librustc/ty/normalize_erasing_regions.rs b/src/librustc/ty/normalize_erasing_regions.rs index cbaabd8e1f137..2f0a57c59eb14 100644 --- a/src/librustc/ty/normalize_erasing_regions.rs +++ b/src/librustc/ty/normalize_erasing_regions.rs @@ -4,8 +4,8 @@ //! //! The methods in this file use a `TypeFolder` to recursively process //! contents, invoking the underlying -//! `normalize_ty_after_erasing_regions` query for each type found -//! within. (This underlying query is what is cached.) +//! `normalize_generic_arg_after_erasing_regions` query for each type +//! or constant found within. (This underlying query is what is cached.) use crate::ty::fold::{TypeFoldable, TypeFolder}; use crate::ty::subst::{Subst, SubstsRef}; @@ -94,6 +94,12 @@ impl TypeFolder<'tcx> for NormalizeAfterErasingRegionsFolder<'tcx> { } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.tcx.normalize_ty_after_erasing_regions(self.param_env.and(ty)) + let arg = self.param_env.and(ty.into()); + self.tcx.normalize_generic_arg_after_erasing_regions(arg).expect_ty() + } + + fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + let arg = self.param_env.and(c.into()); + self.tcx.normalize_generic_arg_after_erasing_regions(arg).expect_const() } } diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs index b397a2c80d59b..9dd96f2f2b507 100644 --- a/src/librustc/ty/outlives.rs +++ b/src/librustc/ty/outlives.rs @@ -61,15 +61,15 @@ fn compute_components(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, out: &mut SmallVec<[Compo // in the `subtys` iterator (e.g., when encountering a // projection). match ty.kind { - ty::Closure(def_id, ref substs) => { - for upvar_ty in substs.as_closure().upvar_tys(def_id, tcx) { + ty::Closure(_, ref substs) => { + for upvar_ty in substs.as_closure().upvar_tys() { compute_components(tcx, upvar_ty, out); } } - ty::Generator(def_id, ref substs, _) => { + ty::Generator(_, ref substs, _) => { // Same as the closure case - for upvar_ty in substs.as_generator().upvar_tys(def_id, tcx) { + for upvar_ty in substs.as_generator().upvar_tys() { compute_components(tcx, upvar_ty, out); } diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs index 8d784833bd310..a932f334dde68 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -1,9 +1,9 @@ -use crate::hir::map::{DefPathData, DisambiguatedDefPathData}; use crate::ty::subst::{GenericArg, Subst}; use crate::ty::{self, DefIdTree, Ty, TyCtxt}; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::{CrateNum, DefId}; +use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; // `pretty` is a separate module only for organization. mod pretty; diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 05dcc9e85ac52..b1626d95eb3e8 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1,22 +1,22 @@ -use crate::hir::map::{DefPathData, DisambiguatedDefPathData}; use crate::middle::cstore::{ExternCrate, ExternCrateSource}; use crate::middle::region; -use crate::mir::interpret::{sign_extend, truncate, ConstValue, Scalar}; +use crate::mir::interpret::{sign_extend, truncate, AllocId, ConstValue, Pointer, Scalar}; use crate::ty::layout::{Integer, IntegerExt, Size}; use crate::ty::subst::{GenericArg, GenericArgKind, Subst}; use crate::ty::{self, DefIdTree, ParamConst, Ty, TyCtxt, TypeFoldable}; -use rustc_hir as hir; -use rustc_hir::def::{DefKind, Namespace}; -use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; - use rustc_apfloat::ieee::{Double, Single}; use rustc_apfloat::Float; use rustc_ast::ast; use rustc_attr::{SignedInt, UnsignedInt}; +use rustc_hir as hir; +use rustc_hir::def::{DefKind, Namespace}; +use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; use rustc_span::symbol::{kw, Symbol}; use rustc_target::spec::abi::Abi; use std::cell::Cell; +use std::char; use std::collections::BTreeMap; use std::fmt::{self, Write as _}; use std::ops::{Deref, DerefMut}; @@ -210,6 +210,21 @@ pub trait PrettyPrinter<'tcx>: Ok(self) } + /// Prints `{f: t}` or `{f as t}` depending on the `cast` argument + fn typed_value( + mut self, + f: impl FnOnce(Self) -> Result, + t: impl FnOnce(Self) -> Result, + conversion: &str, + ) -> Result { + self.write_str("{")?; + self = f(self)?; + self.write_str(conversion)?; + self = t(self)?; + self.write_str("}")?; + Ok(self) + } + /// Prints `<...>` around what `f` prints. fn generic_delimiters( self, @@ -517,14 +532,7 @@ pub trait PrettyPrinter<'tcx>: ty::Error => p!(write("[type error]")), ty::Param(ref param_ty) => p!(write("{}", param_ty)), ty::Bound(debruijn, bound_ty) => match bound_ty.kind { - ty::BoundTyKind::Anon => { - if debruijn == ty::INNERMOST { - p!(write("^{}", bound_ty.var.index())) - } else { - p!(write("^{}_{}", debruijn.index(), bound_ty.var.index())) - } - } - + ty::BoundTyKind::Anon => self.pretty_print_bound_var(debruijn, bound_ty.var)?, ty::BoundTyKind::Param(p) => p!(write("{}", p)), }, ty::Adt(def, substs) => { @@ -608,8 +616,6 @@ pub trait PrettyPrinter<'tcx>: } ty::Str => p!(write("str")), ty::Generator(did, substs, movability) => { - let upvar_tys = substs.as_generator().upvar_tys(did, self.tcx()); - let witness = substs.as_generator().witness(did, self.tcx()); match movability { hir::Movability::Movable => p!(write("[generator")), hir::Movability::Static => p!(write("[static generator")), @@ -618,31 +624,47 @@ pub trait PrettyPrinter<'tcx>: // FIXME(eddyb) should use `def_span`. if let Some(hir_id) = self.tcx().hir().as_local_hir_id(did) { p!(write("@{:?}", self.tcx().hir().span(hir_id))); - let mut sep = " "; - for (&var_id, upvar_ty) in - self.tcx().upvars(did).as_ref().iter().flat_map(|v| v.keys()).zip(upvar_tys) - { - p!(write("{}{}:", sep, self.tcx().hir().name(var_id)), print(upvar_ty)); - sep = ", "; + + if substs.as_generator().is_valid() { + let upvar_tys = substs.as_generator().upvar_tys(); + let mut sep = " "; + for (&var_id, upvar_ty) in self + .tcx() + .upvars(did) + .as_ref() + .iter() + .flat_map(|v| v.keys()) + .zip(upvar_tys) + { + p!(write("{}{}:", sep, self.tcx().hir().name(var_id)), print(upvar_ty)); + sep = ", "; + } } } else { // Cross-crate closure types should only be // visible in codegen bug reports, I imagine. p!(write("@{:?}", did)); - let mut sep = " "; - for (index, upvar_ty) in upvar_tys.enumerate() { - p!(write("{}{}:", sep, index), print(upvar_ty)); - sep = ", "; + + if substs.as_generator().is_valid() { + let upvar_tys = substs.as_generator().upvar_tys(); + let mut sep = " "; + for (index, upvar_ty) in upvar_tys.enumerate() { + p!(write("{}{}:", sep, index), print(upvar_ty)); + sep = ", "; + } } } - p!(write(" "), print(witness), write("]")) + if substs.as_generator().is_valid() { + p!(write(" "), print(substs.as_generator().witness())); + } + + p!(write("]")) } ty::GeneratorWitness(types) => { p!(in_binder(&types)); } ty::Closure(did, substs) => { - let upvar_tys = substs.as_closure().upvar_tys(did, self.tcx()); p!(write("[closure")); // FIXME(eddyb) should use `def_span`. @@ -652,30 +674,43 @@ pub trait PrettyPrinter<'tcx>: } else { p!(write("@{:?}", self.tcx().hir().span(hir_id))); } - let mut sep = " "; - for (&var_id, upvar_ty) in - self.tcx().upvars(did).as_ref().iter().flat_map(|v| v.keys()).zip(upvar_tys) - { - p!(write("{}{}:", sep, self.tcx().hir().name(var_id)), print(upvar_ty)); - sep = ", "; + + if substs.as_closure().is_valid() { + let upvar_tys = substs.as_closure().upvar_tys(); + let mut sep = " "; + for (&var_id, upvar_ty) in self + .tcx() + .upvars(did) + .as_ref() + .iter() + .flat_map(|v| v.keys()) + .zip(upvar_tys) + { + p!(write("{}{}:", sep, self.tcx().hir().name(var_id)), print(upvar_ty)); + sep = ", "; + } } } else { // Cross-crate closure types should only be // visible in codegen bug reports, I imagine. p!(write("@{:?}", did)); - let mut sep = " "; - for (index, upvar_ty) in upvar_tys.enumerate() { - p!(write("{}{}:", sep, index), print(upvar_ty)); - sep = ", "; + + if substs.as_closure().is_valid() { + let upvar_tys = substs.as_closure().upvar_tys(); + let mut sep = " "; + for (index, upvar_ty) in upvar_tys.enumerate() { + p!(write("{}{}:", sep, index), print(upvar_ty)); + sep = ", "; + } } } - if self.tcx().sess.verbose() { - p!(write( - " closure_kind_ty={:?} closure_sig_ty={:?}", - substs.as_closure().kind_ty(did, self.tcx()), - substs.as_closure().sig_ty(did, self.tcx()) - )); + if self.tcx().sess.verbose() && substs.as_closure().is_valid() { + p!(write(" closure_kind_ty="), print(substs.as_closure().kind_ty())); + p!( + write(" closure_sig_as_fn_ptr_ty="), + print(substs.as_closure().sig_as_fn_ptr_ty()) + ); } p!(write("]")) @@ -689,7 +724,7 @@ pub trait PrettyPrinter<'tcx>: // array length anon const, rustc will (with debug assertions) print the // constant's path. Which will end up here again. p!(write("_")); - } else if let Some(n) = sz.try_eval_usize(self.tcx(), ty::ParamEnv::empty()) { + } else if let Some(n) = sz.val.try_to_bits(self.tcx().data_layout.pointer_size) { p!(write("{}", n)); } else { p!(write("_")); @@ -702,6 +737,18 @@ pub trait PrettyPrinter<'tcx>: Ok(self) } + fn pretty_print_bound_var( + &mut self, + debruijn: ty::DebruijnIndex, + var: ty::BoundVar, + ) -> Result<(), Self::Error> { + if debruijn == ty::INNERMOST { + write!(self, "^{}", var.index()) + } else { + write!(self, "^{}_{}", debruijn.index(), var.index()) + } + } + fn infer_ty_name(&self, _: ty::TyVid) -> Option { None } @@ -842,16 +889,23 @@ pub trait PrettyPrinter<'tcx>: macro_rules! print_underscore { () => {{ - p!(write("_")); if print_ty { - p!(write(": "), print(ct.ty)); + self = self.typed_value( + |mut this| { + write!(this, "_")?; + Ok(this) + }, + |this| this.print_type(ct.ty), + ": ", + )?; + } else { + write!(self, "_")?; } }}; } - match (ct.val, &ct.ty.kind) { - (_, ty::FnDef(did, substs)) => p!(print_value_path(*did, substs)), - (ty::ConstKind::Unevaluated(did, substs, promoted), _) => { + match ct.val { + ty::ConstKind::Unevaluated(did, substs, promoted) => { if let Some(promoted) = promoted { p!(print_value_path(did, substs)); p!(write("::{:?}", promoted)); @@ -876,49 +930,73 @@ pub trait PrettyPrinter<'tcx>: } } } - (ty::ConstKind::Infer(..), _) => print_underscore!(), - (ty::ConstKind::Param(ParamConst { name, .. }), _) => p!(write("{}", name)), - (ty::ConstKind::Value(value), _) => { + ty::ConstKind::Infer(..) => print_underscore!(), + ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)), + ty::ConstKind::Value(value) => { return self.pretty_print_const_value(value, ct.ty, print_ty); } - _ => { - // fallback - p!(write("{:?}", ct.val)); - if print_ty { - p!(write(": "), print(ct.ty)); - } + ty::ConstKind::Bound(debruijn, bound_var) => { + self.pretty_print_bound_var(debruijn, bound_var)? } + ty::ConstKind::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)), }; Ok(self) } - fn pretty_print_const_value( + fn pretty_print_const_scalar( mut self, - ct: ConstValue<'tcx>, + scalar: Scalar, ty: Ty<'tcx>, print_ty: bool, ) -> Result { define_scoped_cx!(self); - if self.tcx().sess.verbose() { - p!(write("ConstValue({:?}: {:?})", ct, ty)); - return Ok(self); - } - - let u8 = self.tcx().types.u8; - - match (ct, &ty.kind) { - (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Bool) => { - p!(write("{}", if data == 0 { "false" } else { "true" })) - } - (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Float(ast::FloatTy::F32)) => { + match (scalar, &ty.kind) { + // Byte strings (&[u8; N]) + ( + Scalar::Ptr(ptr), + ty::Ref( + _, + ty::TyS { + kind: + ty::Array( + ty::TyS { kind: ty::Uint(ast::UintTy::U8), .. }, + ty::Const { + val: + ty::ConstKind::Value(ConstValue::Scalar(Scalar::Raw { + data, + .. + })), + .. + }, + ), + .. + }, + _, + ), + ) => { + let byte_str = self + .tcx() + .alloc_map + .lock() + .unwrap_memory(ptr.alloc_id) + .get_bytes(&self.tcx(), ptr, Size::from_bytes(*data)) + .unwrap(); + p!(pretty_print_byte_str(byte_str)); + } + // Bool + (Scalar::Raw { data: 0, .. }, ty::Bool) => p!(write("false")), + (Scalar::Raw { data: 1, .. }, ty::Bool) => p!(write("true")), + // Float + (Scalar::Raw { data, .. }, ty::Float(ast::FloatTy::F32)) => { p!(write("{}f32", Single::from_bits(data))) } - (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Float(ast::FloatTy::F64)) => { + (Scalar::Raw { data, .. }, ty::Float(ast::FloatTy::F64)) => { p!(write("{}f64", Double::from_bits(data))) } - (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Uint(ui)) => { + // Int + (Scalar::Raw { data, .. }, ty::Uint(ui)) => { let bit_size = Integer::from_attr(&self.tcx(), UnsignedInt(*ui)).size(); let max = truncate(u128::MAX, bit_size); @@ -926,93 +1004,191 @@ pub trait PrettyPrinter<'tcx>: if data == max { p!(write("std::{}::MAX", ui_str)) } else { - p!(write("{}{}", data, ui_str)) + if print_ty { p!(write("{}{}", data, ui_str)) } else { p!(write("{}", data)) } }; } - (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Int(i)) => { - let bit_size = Integer::from_attr(&self.tcx(), SignedInt(*i)).size().bits() as u128; + (Scalar::Raw { data, .. }, ty::Int(i)) => { + let size = Integer::from_attr(&self.tcx(), SignedInt(*i)).size(); + let bit_size = size.bits() as u128; let min = 1u128 << (bit_size - 1); let max = min - 1; - let ty = self.tcx().lift(&ty).unwrap(); - let size = self.tcx().layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size; let i_str = i.name_str(); match data { d if d == min => p!(write("std::{}::MIN", i_str)), d if d == max => p!(write("std::{}::MAX", i_str)), - _ => p!(write("{}{}", sign_extend(data, size) as i128, i_str)), + _ => { + let data = sign_extend(data, size) as i128; + if print_ty { + p!(write("{}{}", data, i_str)) + } else { + p!(write("{}", data)) + } + } } } - (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Char) => { - p!(write("{:?}", ::std::char::from_u32(data as u32).unwrap())) - } - (ConstValue::Scalar(_), ty::RawPtr(_)) => p!(write("{{pointer}}")), - (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::FnPtr(_)) => { + // Char + (Scalar::Raw { data, .. }, ty::Char) if char::from_u32(data as u32).is_some() => { + p!(write("{:?}", char::from_u32(data as u32).unwrap())) + } + // Raw pointers + (Scalar::Raw { data, .. }, ty::RawPtr(_)) => { + self = self.typed_value( + |mut this| { + write!(this, "0x{:x}", data)?; + Ok(this) + }, + |this| this.print_type(ty), + " as ", + )?; + } + (Scalar::Ptr(ptr), ty::FnPtr(_)) => { let instance = { let alloc_map = self.tcx().alloc_map.lock(); alloc_map.unwrap_fn(ptr.alloc_id) }; - p!(print_value_path(instance.def_id(), instance.substs)); - } - _ => { - let printed = if let ty::Ref(_, ref_ty, _) = ty.kind { - let byte_str = match (ct, &ref_ty.kind) { - (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => { - let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty()); - Some( - self.tcx() - .alloc_map - .lock() - .unwrap_memory(ptr.alloc_id) - .get_bytes(&self.tcx(), ptr, Size::from_bytes(n)) - .unwrap(), - ) - } - (ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => { - // The `inspect` here is okay since we checked the bounds, and there are - // no relocations (we have an active slice reference here). We don't use - // this result to affect interpreter execution. - Some(data.inspect_with_undef_and_ptr_outside_interpreter(start..end)) - } - _ => None, - }; - - if let Some(byte_str) = byte_str { - p!(write("b\"")); - for &c in byte_str { - for e in std::ascii::escape_default(c) { - self.write_char(e as char)?; - } - } - p!(write("\"")); - true - } else if let (ConstValue::Slice { data, start, end }, ty::Str) = - (ct, &ref_ty.kind) - { - // The `inspect` here is okay since we checked the bounds, and there are no - // relocations (we have an active `str` reference here). We don't use this - // result to affect interpreter execution. - let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end); - let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri"); - p!(write("{:?}", s)); - true + self = self.typed_value( + |this| this.print_value_path(instance.def_id(), instance.substs), + |this| this.print_type(ty), + " as ", + )?; + } + // For function type zsts just printing the path is enough + (Scalar::Raw { size: 0, .. }, ty::FnDef(d, s)) => p!(print_value_path(*d, s)), + // Empty tuples are frequently occurring, so don't print the fallback. + (Scalar::Raw { size: 0, .. }, ty::Tuple(ts)) if ts.is_empty() => p!(write("()")), + // Zero element arrays have a trivial representation. + ( + Scalar::Raw { size: 0, .. }, + ty::Array( + _, + ty::Const { + val: ty::ConstKind::Value(ConstValue::Scalar(Scalar::Raw { data: 0, .. })), + .. + }, + ), + ) => p!(write("[]")), + // Nontrivial types with scalar bit representation + (Scalar::Raw { data, size }, _) => { + let print = |mut this: Self| { + if size == 0 { + write!(this, "transmute(())")?; } else { - false + write!(this, "transmute(0x{:01$x})", data, size as usize * 2)?; } + Ok(this) + }; + self = if print_ty { + self.typed_value(print, |this| this.print_type(ty), ": ")? } else { - false + print(self)? }; - if !printed { - // fallback - p!(write("{:?}", ct)); - if print_ty { - p!(write(": "), print(ty)); - } - } } - }; + // Any pointer values not covered by a branch above + (Scalar::Ptr(p), _) => { + self = self.pretty_print_const_pointer(p, ty, print_ty)?; + } + } + Ok(self) + } + + /// This is overridden for MIR printing because we only want to hide alloc ids from users, not + /// from MIR where it is actually useful. + fn pretty_print_const_pointer( + mut self, + _: Pointer, + ty: Ty<'tcx>, + print_ty: bool, + ) -> Result { + if print_ty { + self.typed_value( + |mut this| { + this.write_str("&_")?; + Ok(this) + }, + |this| this.print_type(ty), + ": ", + ) + } else { + self.write_str("&_")?; + Ok(self) + } + } + + fn pretty_print_byte_str(mut self, byte_str: &'tcx [u8]) -> Result { + define_scoped_cx!(self); + p!(write("b\"")); + for &c in byte_str { + for e in std::ascii::escape_default(c) { + self.write_char(e as char)?; + } + } + p!(write("\"")); Ok(self) } + + fn pretty_print_const_value( + mut self, + ct: ConstValue<'tcx>, + ty: Ty<'tcx>, + print_ty: bool, + ) -> Result { + define_scoped_cx!(self); + + if self.tcx().sess.verbose() { + p!(write("ConstValue({:?}: {:?})", ct, ty)); + return Ok(self); + } + + let u8_type = self.tcx().types.u8; + + match (ct, &ty.kind) { + (ConstValue::Scalar(scalar), _) => self.pretty_print_const_scalar(scalar, ty, print_ty), + ( + ConstValue::Slice { data, start, end }, + ty::Ref(_, ty::TyS { kind: ty::Slice(t), .. }, _), + ) if *t == u8_type => { + // The `inspect` here is okay since we checked the bounds, and there are + // no relocations (we have an active slice reference here). We don't use + // this result to affect interpreter execution. + let byte_str = data.inspect_with_undef_and_ptr_outside_interpreter(start..end); + self.pretty_print_byte_str(byte_str) + } + ( + ConstValue::Slice { data, start, end }, + ty::Ref(_, ty::TyS { kind: ty::Str, .. }, _), + ) => { + // The `inspect` here is okay since we checked the bounds, and there are no + // relocations (we have an active `str` reference here). We don't use this + // result to affect interpreter execution. + let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end); + let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri"); + p!(write("{:?}", s)); + Ok(self) + } + (ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => { + let n = n.val.try_to_bits(self.tcx().data_layout.pointer_size).unwrap(); + // cast is ok because we already checked for pointer size (32 or 64 bit) above + let n = Size::from_bytes(n); + let ptr = Pointer::new(AllocId(0), offset); + + let byte_str = alloc.get_bytes(&self.tcx(), ptr, n).unwrap(); + p!(write("*")); + p!(pretty_print_byte_str(byte_str)); + Ok(self) + } + // FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading + // their fields instead of just dumping the memory. + _ => { + // fallback + p!(write("{:?}", ct)); + if print_ty { + p!(write(": "), print(ty)); + } + Ok(self) + } + } + } } // HACK(eddyb) boxed to avoid moving around a large struct by-value. @@ -1024,6 +1200,7 @@ pub struct FmtPrinterData<'a, 'tcx, F> { empty_path: bool, in_value: bool, + pub print_alloc_ids: bool, used_region_names: FxHashSet, region_index: usize, @@ -1054,6 +1231,7 @@ impl FmtPrinter<'a, 'tcx, F> { fmt, empty_path: false, in_value: ns == Namespace::ValueNS, + print_alloc_ids: false, used_region_names: Default::default(), region_index: 0, binder_depth: 0, @@ -1326,6 +1504,22 @@ impl PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { self.pretty_in_binder(value) } + fn typed_value( + mut self, + f: impl FnOnce(Self) -> Result, + t: impl FnOnce(Self) -> Result, + conversion: &str, + ) -> Result { + self.write_str("{")?; + self = f(self)?; + self.write_str(conversion)?; + let was_in_value = std::mem::replace(&mut self.in_value, false); + self = t(self)?; + self.in_value = was_in_value; + self.write_str("}")?; + Ok(self) + } + fn generic_delimiters( mut self, f: impl FnOnce(Self) -> Result, @@ -1379,7 +1573,29 @@ impl PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { ty::ReVar(_) | ty::ReScope(_) | ty::ReErased => false, - ty::ReStatic | ty::ReEmpty(_) | ty::ReClosureBound(_) => true, + ty::ReStatic | ty::ReEmpty(_) => true, + } + } + + fn pretty_print_const_pointer( + self, + p: Pointer, + ty: Ty<'tcx>, + print_ty: bool, + ) -> Result { + let print = |mut this: Self| { + define_scoped_cx!(this); + if this.print_alloc_ids { + p!(write("{:?}", p)); + } else { + p!(write("&_")); + } + Ok(this) + }; + if print_ty { + self.typed_value(print, |this| this.print_type(ty), ": ") + } else { + print(self) } } } @@ -1469,12 +1685,6 @@ impl FmtPrinter<'_, '_, F> { p!(write("'", ui)); return Ok(self); } - - // The user should never encounter these in unsubstituted form. - ty::ReClosureBound(vid) => { - p!(write("{:?}", vid)); - return Ok(self); - } } p!(write("'_")); diff --git a/src/librustc/ty/query/caches.rs b/src/librustc/ty/query/caches.rs index efc2804bd4d59..a11b3bcba3ed3 100644 --- a/src/librustc/ty/query/caches.rs +++ b/src/librustc/ty/query/caches.rs @@ -1,5 +1,4 @@ use crate::dep_graph::DepNodeIndex; -use crate::ty::query::config::QueryAccessors; use crate::ty::query::plumbing::{QueryLookup, QueryState, QueryStateShard}; use crate::ty::TyCtxt; @@ -7,39 +6,43 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sharded::Sharded; use std::default::Default; use std::hash::Hash; +use std::marker::PhantomData; pub(crate) trait CacheSelector { - type Cache: QueryCache; + type Cache: QueryCache; } -pub(crate) trait QueryCache: Default { +pub(crate) trait QueryCache: Default { + type Key; + type Value; type Sharded: Default; /// Checks if the query is already computed and in the cache. /// It returns the shard index and a lock guard to the shard, /// which will be used if the query is not in the cache and we need /// to compute it. - fn lookup<'tcx, R, GetCache, OnHit, OnMiss, Q>( + fn lookup<'tcx, R, GetCache, OnHit, OnMiss>( &self, - state: &'tcx QueryState<'tcx, Q>, + state: &'tcx QueryState<'tcx, Self>, get_cache: GetCache, - key: K, + key: Self::Key, // `on_hit` can be called while holding a lock to the query state shard. on_hit: OnHit, on_miss: OnMiss, ) -> R where - Q: QueryAccessors<'tcx>, - GetCache: for<'a> Fn(&'a mut QueryStateShard<'tcx, Q>) -> &'a mut Self::Sharded, - OnHit: FnOnce(&V, DepNodeIndex) -> R, - OnMiss: FnOnce(K, QueryLookup<'tcx, Q>) -> R; + GetCache: for<'a> Fn( + &'a mut QueryStateShard<'tcx, Self::Key, Self::Sharded>, + ) -> &'a mut Self::Sharded, + OnHit: FnOnce(&Self::Value, DepNodeIndex) -> R, + OnMiss: FnOnce(Self::Key, QueryLookup<'tcx, Self::Key, Self::Sharded>) -> R; fn complete( &self, tcx: TyCtxt<'tcx>, lock_sharded_storage: &mut Self::Sharded, - key: K, - value: V, + key: Self::Key, + value: Self::Value, index: DepNodeIndex, ); @@ -47,36 +50,45 @@ pub(crate) trait QueryCache: Default { &self, shards: &Sharded, get_shard: impl Fn(&mut L) -> &mut Self::Sharded, - f: impl for<'a> FnOnce(Box + 'a>) -> R, + f: impl for<'a> FnOnce( + Box + 'a>, + ) -> R, ) -> R; } pub struct DefaultCacheSelector; impl CacheSelector for DefaultCacheSelector { - type Cache = DefaultCache; + type Cache = DefaultCache; } -#[derive(Default)] -pub struct DefaultCache; +pub struct DefaultCache(PhantomData<(K, V)>); + +impl Default for DefaultCache { + fn default() -> Self { + DefaultCache(PhantomData) + } +} -impl QueryCache for DefaultCache { +impl QueryCache for DefaultCache { + type Key = K; + type Value = V; type Sharded = FxHashMap; #[inline(always)] - fn lookup<'tcx, R, GetCache, OnHit, OnMiss, Q>( + fn lookup<'tcx, R, GetCache, OnHit, OnMiss>( &self, - state: &'tcx QueryState<'tcx, Q>, + state: &'tcx QueryState<'tcx, Self>, get_cache: GetCache, key: K, on_hit: OnHit, on_miss: OnMiss, ) -> R where - Q: QueryAccessors<'tcx>, - GetCache: for<'a> Fn(&'a mut QueryStateShard<'tcx, Q>) -> &'a mut Self::Sharded, + GetCache: + for<'a> Fn(&'a mut QueryStateShard<'tcx, K, Self::Sharded>) -> &'a mut Self::Sharded, OnHit: FnOnce(&V, DepNodeIndex) -> R, - OnMiss: FnOnce(K, QueryLookup<'tcx, Q>) -> R, + OnMiss: FnOnce(K, QueryLookup<'tcx, K, Self::Sharded>) -> R, { let mut lookup = state.get_lookup(&key); let lock = &mut *lookup.lock; diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index 178c2362def6e..72a0fdf156726 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -2,7 +2,7 @@ use crate::dep_graph::SerializedDepNodeIndex; use crate::dep_graph::{DepKind, DepNode}; use crate::ty::query::caches::QueryCache; use crate::ty::query::plumbing::CycleError; -use crate::ty::query::{Query, QueryState}; +use crate::ty::query::QueryState; use crate::ty::TyCtxt; use rustc_data_structures::profiling::ProfileCategory; use rustc_hir::def_id::DefId; @@ -28,18 +28,15 @@ pub trait QueryConfig<'tcx> { pub(crate) trait QueryAccessors<'tcx>: QueryConfig<'tcx> { const ANON: bool; const EVAL_ALWAYS: bool; + const DEP_KIND: DepKind; - type Cache: QueryCache; - - fn query(key: Self::Key) -> Query<'tcx>; + type Cache: QueryCache; // Don't use this method to access query results, instead use the methods on TyCtxt - fn query_state<'a>(tcx: TyCtxt<'tcx>) -> &'a QueryState<'tcx, Self>; + fn query_state<'a>(tcx: TyCtxt<'tcx>) -> &'a QueryState<'tcx, Self::Cache>; fn to_dep_node(tcx: TyCtxt<'tcx>, key: &Self::Key) -> DepNode; - fn dep_kind() -> DepKind; - // Don't use this method to compute query results, instead use the methods on TyCtxt fn compute(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value; @@ -62,10 +59,7 @@ pub(crate) trait QueryDescription<'tcx>: QueryAccessors<'tcx> { } } -impl<'tcx, M: QueryAccessors<'tcx, Key = DefId>> QueryDescription<'tcx> for M -where - >::Cache: QueryCache>::Value>, -{ +impl<'tcx, M: QueryAccessors<'tcx, Key = DefId>> QueryDescription<'tcx> for M { default fn describe(tcx: TyCtxt<'_>, def_id: DefId) -> Cow<'static, str> { if !tcx.sess.verbose() { format!("processing `{}`", tcx.def_path_str(def_id)).into() diff --git a/src/librustc/ty/query/keys.rs b/src/librustc/ty/query/keys.rs index 09fb307a1ceb4..6be1f04efca2b 100644 --- a/src/librustc/ty/query/keys.rs +++ b/src/librustc/ty/query/keys.rs @@ -5,9 +5,9 @@ use crate::mir; use crate::traits; use crate::ty::fast_reject::SimplifiedType; use crate::ty::query::caches::DefaultCacheSelector; -use crate::ty::subst::SubstsRef; +use crate::ty::subst::{GenericArg, SubstsRef}; use crate::ty::{self, Ty, TyCtxt}; -use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; @@ -84,14 +84,14 @@ impl Key for CrateNum { } } -impl Key for DefIndex { +impl Key for LocalDefId { type CacheSelector = DefaultCacheSelector; fn query_crate(&self) -> CrateNum { - LOCAL_CRATE + self.to_def_id().query_crate() } - fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { - DUMMY_SP + fn default_span(&self, tcx: TyCtxt<'_>) -> Span { + self.to_def_id().default_span(tcx) } } @@ -194,6 +194,17 @@ impl<'tcx> Key for ty::PolyTraitRef<'tcx> { } } +impl<'tcx> Key for GenericArg<'tcx> { + type CacheSelector = DefaultCacheSelector; + + fn query_crate(&self) -> CrateNum { + LOCAL_CRATE + } + fn default_span(&self, _: TyCtxt<'_>) -> Span { + DUMMY_SP + } +} + impl<'tcx> Key for &'tcx ty::Const<'tcx> { type CacheSelector = DefaultCacheSelector; diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 8adb828fbebc4..c75e0d95e8fdf 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -1,5 +1,6 @@ use crate::dep_graph::{self, DepConstructor, DepNode, DepNodeParams}; use crate::hir::exports::Export; +use crate::hir::map; use crate::infer::canonical::{self, Canonical}; use crate::lint::LintLevelMap; use crate::middle::codegen_fn_attrs::CodegenFnAttrs; @@ -17,8 +18,6 @@ use crate::mir::interpret::GlobalId; use crate::mir::interpret::{ConstEvalRawResult, ConstEvalResult, ConstValue}; use crate::mir::interpret::{LitToConstError, LitToConstInput}; use crate::mir::mono::CodegenUnit; -use crate::session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; -use crate::session::CrateDisambiguator; use crate::traits::query::{ CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal, @@ -32,7 +31,7 @@ use crate::traits::specialization_graph; use crate::traits::Clauses; use crate::traits::{self, Vtable}; use crate::ty::steal::Steal; -use crate::ty::subst::SubstsRef; +use crate::ty::subst::{GenericArg, SubstsRef}; use crate::ty::util::AlwaysRequiresDrop; use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt}; use crate::util::common::ErrorReported; @@ -44,9 +43,11 @@ use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::Lrc; use rustc_hir as hir; use rustc_hir::def::DefKind; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, DefIndex}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId}; use rustc_hir::{Crate, HirIdSet, ItemLocalId, TraitCandidate}; use rustc_index::vec::IndexVec; +use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; +use rustc_session::CrateDisambiguator; use rustc_target::spec::PanicStrategy; use rustc_ast::ast; @@ -54,13 +55,13 @@ use rustc_attr as attr; use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; use std::borrow::Cow; -use std::convert::TryFrom; +use std::collections::BTreeMap; use std::ops::Deref; use std::sync::Arc; #[macro_use] mod plumbing; -pub use self::plumbing::CycleError; +pub(crate) use self::plumbing::CycleError; use self::plumbing::*; mod stats; @@ -144,13 +145,11 @@ rustc_query_append! { [define_queries!][<'tcx>] } /// /// When you implement a new query, it will likely have a corresponding new /// `DepKind`, and you'll have to support it here in `force_from_dep_node()`. As -/// a rule of thumb, if your query takes a `DefId` or `DefIndex` as sole parameter, +/// a rule of thumb, if your query takes a `DefId` or `LocalDefId` as sole parameter, /// then `force_from_dep_node()` should not fail for it. Otherwise, you can just /// add it to the "We don't have enough information to reconstruct..." group in /// the match below. pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool { - use crate::dep_graph::DepKind; - // We must avoid ever having to call `force_from_dep_node()` for a // `DepNode::codegen_unit`: // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we @@ -165,7 +164,7 @@ pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool // hit the cache instead of having to go through `force_from_dep_node`. // This assertion makes sure, we actually keep applying the solution above. debug_assert!( - dep_node.kind != DepKind::codegen_unit, + dep_node.kind != crate::dep_graph::DepKind::codegen_unit, "calling force_from_dep_node() on DepKind::codegen_unit" ); @@ -176,17 +175,14 @@ pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool rustc_dep_node_force!([dep_node, tcx] // These are inputs that are expected to be pre-allocated and that // should therefore always be red or green already. - DepKind::AllLocalTraitImpls | - DepKind::CrateMetadata | - DepKind::HirBody | - DepKind::Hir | + crate::dep_graph::DepKind::CrateMetadata | // These are anonymous nodes. - DepKind::TraitSelect | + crate::dep_graph::DepKind::TraitSelect | // We don't have enough information to reconstruct the query key of // these. - DepKind::CompileCodegenUnit => { + crate::dep_graph::DepKind::CompileCodegenUnit => { bug!("force_from_dep_node: encountered {:?}", dep_node) } ); @@ -194,15 +190,6 @@ pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool false } -impl DepNode { - /// Check whether the query invocation corresponding to the given - /// DepNode is eligible for on-disk-caching. If so, this is method - /// will execute the query corresponding to the given DepNode. - /// Also, as a sanity check, it expects that the corresponding query - /// invocation has been marked as green already. - pub fn try_load_from_on_disk_cache<'tcx>(&self, tcx: TyCtxt<'tcx>) { - use crate::dep_graph::DepKind; - - rustc_dep_node_try_load_from_on_disk_cache!(self, tcx) - } +pub(crate) fn try_load_from_on_disk_cache<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) { + rustc_dep_node_try_load_from_on_disk_cache!(dep_node, tcx) } diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index 9c1db7c5f2b70..155f792bd9d0a 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -1,26 +1,26 @@ use crate::dep_graph::{DepNodeIndex, SerializedDepNodeIndex}; -use crate::hir::map::definitions::DefPathHash; -use crate::ich::{CachingSourceMapView, Fingerprint}; use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use crate::mir::{self, interpret}; -use crate::session::{CrateDisambiguator, Session}; use crate::ty::codec::{self as ty_codec, TyDecoder, TyEncoder}; use crate::ty::context::TyCtxt; use crate::ty::{self, Ty}; use rustc_ast::ast::Ident; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, Once}; use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::Diagnostic; -use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE}; +use rustc_hir::definitions::DefPathHash; use rustc_index::vec::{Idx, IndexVec}; use rustc_serialize::{ opaque, Decodable, Decoder, Encodable, Encoder, SpecializedDecoder, SpecializedEncoder, UseSpecializedDecodable, UseSpecializedEncodable, }; +use rustc_session::{CrateDisambiguator, Session}; use rustc_span::hygiene::{ExpnId, SyntaxContext}; use rustc_span::source_map::{SourceMap, StableSourceFileId}; +use rustc_span::CachingSourceMapView; use rustc_span::{BytePos, SourceFile, Span, DUMMY_SP}; use std::mem; @@ -657,26 +657,7 @@ impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { #[inline] fn specialized_decode(&mut self) -> Result { - Ok(LocalDefId::from_def_id(DefId::decode(self)?)) - } -} - -impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { - fn specialized_decode(&mut self) -> Result { - // Load the `DefPathHash` which is what we encoded the `DefIndex` as. - let def_path_hash = DefPathHash::decode(self)?; - - // Use the `DefPathHash` to map to the current `DefId`. - let def_id = self.tcx().def_path_hash_to_def_id.as_ref().unwrap()[&def_path_hash]; - - debug_assert!(def_id.is_local()); - - // The `ItemLocalId` needs no remapping. - let local_id = hir::ItemLocalId::decode(self)?; - - // Reconstruct the `HirId` and look up the corresponding `NodeId` in the - // context of the current session. - Ok(hir::HirId { owner: def_id.index, local_id }) + Ok(DefId::decode(self)?.expect_local()) } } @@ -873,21 +854,6 @@ where } } -impl<'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'a, 'tcx, E> -where - E: 'a + TyEncoder, -{ - #[inline] - fn specialized_encode(&mut self, id: &hir::HirId) -> Result<(), Self::Error> { - let hir::HirId { owner, local_id } = *id; - - let def_path_hash = self.tcx.hir().definitions().def_path_hash(owner); - - def_path_hash.encode(self)?; - local_id.encode(self) - } -} - impl<'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'a, 'tcx, E> where E: 'a + TyEncoder, diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index acf67f52dceaa..c0cc119c5a125 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -2,10 +2,10 @@ //! generate the actual methods on tcx which find and execute the provider, //! manage the caches, and so forth. -use crate::dep_graph::{DepNode, DepNodeIndex, SerializedDepNodeIndex}; +use crate::dep_graph::{DepKind, DepNode, DepNodeIndex, SerializedDepNodeIndex}; use crate::ty::query::caches::QueryCache; -use crate::ty::query::config::{QueryAccessors, QueryDescription}; -use crate::ty::query::job::{QueryInfo, QueryJob, QueryJobId, QueryShardJobId}; +use crate::ty::query::config::QueryDescription; +use crate::ty::query::job::{QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryShardJobId}; use crate::ty::query::Query; use crate::ty::tls; use crate::ty::{self, TyCtxt}; @@ -20,6 +20,8 @@ use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, FatalError, H use rustc_span::source_map::DUMMY_SP; use rustc_span::Span; use std::collections::hash_map::Entry; +use std::convert::TryFrom; +use std::fmt::Debug; use std::hash::{Hash, Hasher}; use std::mem; use std::num::NonZeroU32; @@ -27,37 +29,38 @@ use std::ptr; #[cfg(debug_assertions)] use std::sync::atomic::{AtomicUsize, Ordering}; -pub(crate) struct QueryStateShard<'tcx, D: QueryAccessors<'tcx> + ?Sized> { - pub(super) cache: <>::Cache as QueryCache>::Sharded, - pub(super) active: FxHashMap>, +pub(crate) struct QueryStateShard<'tcx, K, C> { + cache: C, + active: FxHashMap>, /// Used to generate unique ids for active jobs. - pub(super) jobs: u32, + jobs: u32, } -impl<'tcx, Q: QueryAccessors<'tcx>> QueryStateShard<'tcx, Q> { - fn get_cache( - &mut self, - ) -> &mut <>::Cache as QueryCache>::Sharded { +impl<'tcx, K, C> QueryStateShard<'tcx, K, C> { + fn get_cache(&mut self) -> &mut C { &mut self.cache } } -impl<'tcx, Q: QueryAccessors<'tcx>> Default for QueryStateShard<'tcx, Q> { - fn default() -> QueryStateShard<'tcx, Q> { +impl<'tcx, K, C: Default> Default for QueryStateShard<'tcx, K, C> { + fn default() -> QueryStateShard<'tcx, K, C> { QueryStateShard { cache: Default::default(), active: Default::default(), jobs: 0 } } } -pub(crate) struct QueryState<'tcx, D: QueryAccessors<'tcx> + ?Sized> { - pub(super) cache: D::Cache, - pub(super) shards: Sharded>, +pub(crate) struct QueryState<'tcx, C: QueryCache> { + cache: C, + shards: Sharded>, #[cfg(debug_assertions)] pub(super) cache_hits: AtomicUsize, } -impl<'tcx, Q: QueryAccessors<'tcx>> QueryState<'tcx, Q> { - pub(super) fn get_lookup(&'tcx self, key: &K) -> QueryLookup<'tcx, Q> { +impl<'tcx, C: QueryCache> QueryState<'tcx, C> { + pub(super) fn get_lookup( + &'tcx self, + key: &K2, + ) -> QueryLookup<'tcx, C::Key, C::Sharded> { // We compute the key's hash once and then use it for both the // shard lookup and the hashmap lookup. This relies on the fact // that both of them use `FxHasher`. @@ -72,7 +75,7 @@ impl<'tcx, Q: QueryAccessors<'tcx>> QueryState<'tcx, Q> { } /// Indicates the state of a query for a given key in a query map. -pub(super) enum QueryResult<'tcx> { +enum QueryResult<'tcx> { /// An already executing query. The query job can be used to await for its completion. Started(QueryJob<'tcx>), @@ -81,25 +84,54 @@ pub(super) enum QueryResult<'tcx> { Poisoned, } -impl<'tcx, M: QueryAccessors<'tcx>> QueryState<'tcx, M> { - pub fn iter_results( +impl<'tcx, C: QueryCache> QueryState<'tcx, C> { + pub(super) fn iter_results( &self, f: impl for<'a> FnOnce( - Box + 'a>, + Box + 'a>, ) -> R, ) -> R { self.cache.iter(&self.shards, |shard| &mut shard.cache, f) } - pub fn all_inactive(&self) -> bool { + pub(super) fn all_inactive(&self) -> bool { let shards = self.shards.lock_shards(); shards.iter().all(|shard| shard.active.is_empty()) } + + pub(super) fn try_collect_active_jobs( + &self, + kind: DepKind, + make_query: fn(C::Key) -> Query<'tcx>, + jobs: &mut FxHashMap>, + ) -> Option<()> + where + C::Key: Clone, + { + // We use try_lock_shards here since we are called from the + // deadlock handler, and this shouldn't be locked. + let shards = self.shards.try_lock_shards()?; + let shards = shards.iter().enumerate(); + jobs.extend(shards.flat_map(|(shard_id, shard)| { + shard.active.iter().filter_map(move |(k, v)| { + if let QueryResult::Started(ref job) = *v { + let id = + QueryJobId { job: job.id, shard: u16::try_from(shard_id).unwrap(), kind }; + let info = QueryInfo { span: job.span, query: make_query(k.clone()) }; + Some((id, QueryJobInfo { info, job: job.clone() })) + } else { + None + } + }) + })); + + Some(()) + } } -impl<'tcx, M: QueryAccessors<'tcx>> Default for QueryState<'tcx, M> { - fn default() -> QueryState<'tcx, M> { +impl<'tcx, C: QueryCache> Default for QueryState<'tcx, C> { + fn default() -> QueryState<'tcx, C> { QueryState { - cache: M::Cache::default(), + cache: C::default(), shards: Default::default(), #[cfg(debug_assertions)] cache_hits: AtomicUsize::new(0), @@ -108,21 +140,31 @@ impl<'tcx, M: QueryAccessors<'tcx>> Default for QueryState<'tcx, M> { } /// Values used when checking a query cache which can be reused on a cache-miss to execute the query. -pub(crate) struct QueryLookup<'tcx, Q: QueryAccessors<'tcx>> { +pub(crate) struct QueryLookup<'tcx, K, C> { pub(super) key_hash: u64, - pub(super) shard: usize, - pub(super) lock: LockGuard<'tcx, QueryStateShard<'tcx, Q>>, + shard: usize, + pub(super) lock: LockGuard<'tcx, QueryStateShard<'tcx, K, C>>, } /// A type representing the responsibility to execute the job in the `job` field. /// This will poison the relevant query if dropped. -pub(super) struct JobOwner<'tcx, Q: QueryDescription<'tcx>> { - tcx: TyCtxt<'tcx>, - key: Q::Key, +struct JobOwner<'tcx, C> +where + C: QueryCache, + C::Key: Eq + Hash + Clone + Debug, + C::Value: Clone, +{ + state: &'tcx QueryState<'tcx, C>, + key: C::Key, id: QueryJobId, } -impl<'tcx, Q: QueryDescription<'tcx>> JobOwner<'tcx, Q> { +impl<'tcx, C: QueryCache> JobOwner<'tcx, C> +where + C: QueryCache, + C::Key: Eq + Hash + Clone + Debug, + C::Value: Clone, +{ /// Either gets a `JobOwner` corresponding the query, allowing us to /// start executing the query, or returns with the result of the query. /// This function assumes that `try_get_cached` is already called and returned `lookup`. @@ -132,12 +174,15 @@ impl<'tcx, Q: QueryDescription<'tcx>> JobOwner<'tcx, Q> { /// This function is inlined because that results in a noticeable speed-up /// for some compile-time benchmarks. #[inline(always)] - pub(super) fn try_start( + fn try_start( tcx: TyCtxt<'tcx>, span: Span, - key: &Q::Key, - mut lookup: QueryLookup<'tcx, Q>, - ) -> TryGetJob<'tcx, Q> { + key: &C::Key, + mut lookup: QueryLookup<'tcx, C::Key, C::Sharded>, + ) -> TryGetJob<'tcx, C> + where + Q: QueryDescription<'tcx, Key = C::Key, Value = C::Value, Cache = C>, + { let lock = &mut *lookup.lock; let (latch, mut _query_blocked_prof_timer) = match lock.active.entry((*key).clone()) { @@ -154,7 +199,7 @@ impl<'tcx, Q: QueryDescription<'tcx>> JobOwner<'tcx, Q> { }; // Create the id of the job we're waiting for - let id = QueryJobId::new(job.id, lookup.shard, Q::dep_kind()); + let id = QueryJobId::new(job.id, lookup.shard, Q::DEP_KIND); (job.latch(id), _query_blocked_prof_timer) } @@ -169,13 +214,14 @@ impl<'tcx, Q: QueryDescription<'tcx>> JobOwner<'tcx, Q> { lock.jobs = id; let id = QueryShardJobId(NonZeroU32::new(id).unwrap()); - let global_id = QueryJobId::new(id, lookup.shard, Q::dep_kind()); + let global_id = QueryJobId::new(id, lookup.shard, Q::DEP_KIND); let job = tls::with_related_context(tcx, |icx| QueryJob::new(id, span, icx.query)); entry.insert(QueryResult::Started(job)); - let owner = JobOwner { tcx, id: global_id, key: (*key).clone() }; + let owner = + JobOwner { state: Q::query_state(tcx), id: global_id, key: (*key).clone() }; return TryGetJob::NotYetStarted(owner); } }; @@ -198,7 +244,8 @@ impl<'tcx, Q: QueryDescription<'tcx>> JobOwner<'tcx, Q> { return TryGetJob::Cycle(Q::handle_cycle_error(tcx, cycle)); } - let cached = tcx.try_get_cached::( + let cached = tcx.try_get_cached( + Q::query_state(tcx), (*key).clone(), |value, index| (value.clone(), index), |_, _| panic!("value must be in cache after waiting"), @@ -215,16 +262,15 @@ impl<'tcx, Q: QueryDescription<'tcx>> JobOwner<'tcx, Q> { /// Completes the query by updating the query cache with the `result`, /// signals the waiter and forgets the JobOwner, so it won't poison the query #[inline(always)] - pub(super) fn complete(self, result: &Q::Value, dep_node_index: DepNodeIndex) { + fn complete(self, tcx: TyCtxt<'tcx>, result: &C::Value, dep_node_index: DepNodeIndex) { // We can move out of `self` here because we `mem::forget` it below let key = unsafe { ptr::read(&self.key) }; - let tcx = self.tcx; + let state = self.state; // Forget ourself so our destructor won't poison the query mem::forget(self); let job = { - let state = Q::query_state(tcx); let result = result.clone(); let mut lock = state.shards.get_shard_by_value(&key).lock(); let job = match lock.active.remove(&key).unwrap() { @@ -249,12 +295,16 @@ where (result, diagnostics.into_inner()) } -impl<'tcx, Q: QueryDescription<'tcx>> Drop for JobOwner<'tcx, Q> { +impl<'tcx, C: QueryCache> Drop for JobOwner<'tcx, C> +where + C::Key: Eq + Hash + Clone + Debug, + C::Value: Clone, +{ #[inline(never)] #[cold] fn drop(&mut self) { // Poison the query so jobs waiting on it panic. - let state = Q::query_state(self.tcx); + let state = self.state; let shard = state.shards.get_shard_by_value(&self.key); let job = { let mut shard = shard.lock(); @@ -272,25 +322,29 @@ impl<'tcx, Q: QueryDescription<'tcx>> Drop for JobOwner<'tcx, Q> { } #[derive(Clone)] -pub struct CycleError<'tcx> { +pub(crate) struct CycleError<'tcx> { /// The query and related span that uses the cycle. pub(super) usage: Option<(Span, Query<'tcx>)>, pub(super) cycle: Vec>, } /// The result of `try_start`. -pub(super) enum TryGetJob<'tcx, D: QueryDescription<'tcx>> { +enum TryGetJob<'tcx, C: QueryCache> +where + C::Key: Eq + Hash + Clone + Debug, + C::Value: Clone, +{ /// The query is not yet started. Contains a guard to the cache eventually used to start it. - NotYetStarted(JobOwner<'tcx, D>), + NotYetStarted(JobOwner<'tcx, C>), /// The query was already completed. /// Returns the result of the query and its dep-node index /// if it succeeded or a cycle error if it failed. #[cfg(parallel_compiler)] - JobCompleted((D::Value, DepNodeIndex)), + JobCompleted((C::Value, DepNodeIndex)), /// Trying to execute the query resulted in a cycle. - Cycle(D::Value), + Cycle(C::Value), } impl<'tcx> TyCtxt<'tcx> { @@ -298,7 +352,7 @@ impl<'tcx> TyCtxt<'tcx> { /// new query job while it executes. It returns the diagnostics /// captured during execution and the actual result. #[inline(always)] - pub(super) fn start_query( + fn start_query( self, token: QueryJobId, diagnostics: Option<&Lock>>, @@ -334,7 +388,7 @@ impl<'tcx> TyCtxt<'tcx> { assert!(!stack.is_empty()); let fix_span = |span: Span, query: &Query<'tcx>| { - self.sess.source_map().def_span(query.default_span(self, span)) + self.sess.source_map().guess_head_span(query.default_span(self, span)) }; // Disable naming impls with types in this path, since that @@ -402,7 +456,8 @@ impl<'tcx> TyCtxt<'tcx> { query_info.info.query.describe(icx.tcx) ), ); - diag.span = icx.tcx.sess.source_map().def_span(query_info.info.span).into(); + diag.span = + icx.tcx.sess.source_map().guess_head_span(query_info.info.span).into(); handler.force_print_diagnostic(diag); current_query = query_info.job.parent; @@ -419,23 +474,22 @@ impl<'tcx> TyCtxt<'tcx> { /// which will be used if the query is not in the cache and we need /// to compute it. #[inline(always)] - fn try_get_cached( + fn try_get_cached( self, - key: Q::Key, + state: &'tcx QueryState<'tcx, C>, + key: C::Key, // `on_hit` can be called while holding a lock to the query cache on_hit: OnHit, on_miss: OnMiss, ) -> R where - Q: QueryDescription<'tcx> + 'tcx, - OnHit: FnOnce(&Q::Value, DepNodeIndex) -> R, - OnMiss: FnOnce(Q::Key, QueryLookup<'tcx, Q>) -> R, + C: QueryCache, + OnHit: FnOnce(&C::Value, DepNodeIndex) -> R, + OnMiss: FnOnce(C::Key, QueryLookup<'tcx, C::Key, C::Sharded>) -> R, { - let state = Q::query_state(self); - state.cache.lookup( state, - QueryStateShard::::get_cache, + QueryStateShard::::get_cache, key, |value, index| { if unlikely!(self.prof.enabled()) { @@ -459,7 +513,8 @@ impl<'tcx> TyCtxt<'tcx> { ) -> Q::Value { debug!("ty::query::get_query<{}>(key={:?}, span={:?})", Q::NAME, key, span); - self.try_get_cached::( + self.try_get_cached( + Q::query_state(self), key, |value, index| { self.dep_graph.read_index(index); @@ -470,13 +525,13 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline(always)] - pub(super) fn try_execute_query>( + fn try_execute_query + 'tcx>( self, span: Span, key: Q::Key, - lookup: QueryLookup<'tcx, Q>, + lookup: QueryLookup<'tcx, Q::Key, ::Sharded>, ) -> Q::Value { - let job = match JobOwner::try_start(self, span, &key, lookup) { + let job = match JobOwner::try_start::(self, span, &key, lookup) { TryGetJob::NotYetStarted(job) => job, TryGetJob::Cycle(result) => return result, #[cfg(parallel_compiler)] @@ -498,7 +553,7 @@ impl<'tcx> TyCtxt<'tcx> { let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| { self.start_query(job.id, diagnostics, |tcx| { - tcx.dep_graph.with_anon_task(Q::dep_kind(), || Q::compute(tcx, key)) + tcx.dep_graph.with_anon_task(Q::DEP_KIND, || Q::compute(tcx, key)) }) }); @@ -512,7 +567,7 @@ impl<'tcx> TyCtxt<'tcx> { .store_diagnostics_for_anon_node(dep_node_index, diagnostics); } - job.complete(&result, dep_node_index); + job.complete(self, &result, dep_node_index); return result; } @@ -538,7 +593,7 @@ impl<'tcx> TyCtxt<'tcx> { }) }); if let Some((result, dep_node_index)) = loaded { - job.complete(&result, dep_node_index); + job.complete(self, &result, dep_node_index); return result; } } @@ -561,9 +616,7 @@ impl<'tcx> TyCtxt<'tcx> { debug_assert!(self.dep_graph.is_green(dep_node)); // First we try to load the result from the on-disk cache. - let result = if Q::cache_on_disk(self, key.clone(), None) - && self.sess.opts.debugging_opts.incremental_queries - { + let result = if Q::cache_on_disk(self, key.clone(), None) { let prof_timer = self.prof.incr_cache_loading(); let result = Q::try_load_from_disk(self, prev_dep_node_index); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); @@ -613,7 +666,7 @@ impl<'tcx> TyCtxt<'tcx> { dep_node: &DepNode, dep_node_index: DepNodeIndex, ) { - use crate::ich::Fingerprint; + use rustc_data_structures::fingerprint::Fingerprint; assert!( Some(self.dep_graph.fingerprint_of(dep_node_index)) @@ -634,10 +687,10 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline(always)] - fn force_query_with_job>( + fn force_query_with_job + 'tcx>( self, key: Q::Key, - job: JobOwner<'tcx, Q>, + job: JobOwner<'tcx, Q::Cache>, dep_node: DepNode, ) -> (Q::Value, DepNodeIndex) { // If the following assertion triggers, it can have two reasons: @@ -680,7 +733,7 @@ impl<'tcx> TyCtxt<'tcx> { } } - job.complete(&result, dep_node_index); + job.complete(self, &result, dep_node_index); (result, dep_node_index) } @@ -692,7 +745,7 @@ impl<'tcx> TyCtxt<'tcx> { /// side-effects -- e.g., in order to report errors for erroneous programs. /// /// Note: The optimization is only available during incr. comp. - pub(super) fn ensure_query + 'tcx>(self, key: Q::Key) -> () { + pub(super) fn ensure_query + 'tcx>(self, key: Q::Key) { if Q::EVAL_ALWAYS { let _ = self.get_query::(DUMMY_SP, key); return; @@ -729,13 +782,14 @@ impl<'tcx> TyCtxt<'tcx> { // We may be concurrently trying both execute and force a query. // Ensure that only one of them runs the query. - self.try_get_cached::( + self.try_get_cached( + Q::query_state(self), key, |_, _| { // Cache hit, do nothing }, |key, lookup| { - let job = match JobOwner::try_start(self, span, &key, lookup) { + let job = match JobOwner::try_start::(self, span, &key, lookup) { TryGetJob::NotYetStarted(job) => job, TryGetJob::Cycle(_) => return, #[cfg(parallel_compiler)] @@ -842,55 +896,6 @@ macro_rules! define_queries_inner { input: ($(([$($modifiers)*] [$($attr)*] [$name]))*) } - impl<$tcx> Queries<$tcx> { - pub fn new( - providers: IndexVec>, - fallback_extern_providers: Providers<$tcx>, - on_disk_cache: OnDiskCache<'tcx>, - ) -> Self { - Queries { - providers, - fallback_extern_providers: Box::new(fallback_extern_providers), - on_disk_cache, - $($name: Default::default()),* - } - } - - pub fn try_collect_active_jobs( - &self - ) -> Option>> { - let mut jobs = FxHashMap::default(); - - $( - // We use try_lock_shards here since we are called from the - // deadlock handler, and this shouldn't be locked. - let shards = self.$name.shards.try_lock_shards()?; - let shards = shards.iter().enumerate(); - jobs.extend(shards.flat_map(|(shard_id, shard)| { - shard.active.iter().filter_map(move |(k, v)| { - if let QueryResult::Started(ref job) = *v { - let id = QueryJobId { - job: job.id, - shard: u16::try_from(shard_id).unwrap(), - kind: - as QueryAccessors<'tcx>>::dep_kind(), - }; - let info = QueryInfo { - span: job.span, - query: queries::$name::query(k.clone()) - }; - Some((id, QueryJobInfo { info, job: job.clone() })) - } else { - None - } - }) - })); - )* - - Some(jobs) - } - } - #[allow(nonstandard_style)] #[derive(Clone, Debug)] pub enum Query<$tcx> { @@ -951,16 +956,6 @@ macro_rules! define_queries_inner { })* } - // This module and the functions in it exist only to provide a - // predictable symbol name prefix for query providers. This is helpful - // for analyzing queries in profilers. - pub(super) mod __query_compute { - $(#[inline(never)] - pub fn $name R, R>(f: F) -> R { - f() - })* - } - $(impl<$tcx> QueryConfig<$tcx> for queries::$name<$tcx> { type Key = $K; type Value = $V; @@ -971,16 +966,12 @@ macro_rules! define_queries_inner { impl<$tcx> QueryAccessors<$tcx> for queries::$name<$tcx> { const ANON: bool = is_anon!([$($modifiers)*]); const EVAL_ALWAYS: bool = is_eval_always!([$($modifiers)*]); + const DEP_KIND: dep_graph::DepKind = dep_graph::DepKind::$node; type Cache = query_storage!([$($modifiers)*][$K, $V]); #[inline(always)] - fn query(key: Self::Key) -> Query<'tcx> { - Query::$name(key) - } - - #[inline(always)] - fn query_state<'a>(tcx: TyCtxt<$tcx>) -> &'a QueryState<$tcx, Self> { + fn query_state<'a>(tcx: TyCtxt<$tcx>) -> &'a QueryState<$tcx, Self::Cache> { &tcx.queries.$name } @@ -990,23 +981,16 @@ macro_rules! define_queries_inner { DepConstructor::$node(tcx, *key) } - #[inline(always)] - fn dep_kind() -> dep_graph::DepKind { - dep_graph::DepKind::$node - } - #[inline] fn compute(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value { - __query_compute::$name(move || { - let provider = tcx.queries.providers.get(key.query_crate()) - // HACK(eddyb) it's possible crates may be loaded after - // the query engine is created, and because crate loading - // is not yet integrated with the query engine, such crates - // would be missing appropriate entries in `providers`. - .unwrap_or(&tcx.queries.fallback_extern_providers) - .$name; - provider(tcx, key) - }) + let provider = tcx.queries.providers.get(key.query_crate()) + // HACK(eddyb) it's possible crates may be loaded after + // the query engine is created, and because crate loading + // is not yet integrated with the query engine, such crates + // would be missing appropriate entries in `providers`. + .unwrap_or(&tcx.queries.fallback_extern_providers) + .$name; + provider(tcx, key) } fn hash_result( @@ -1139,7 +1123,41 @@ macro_rules! define_queries_struct { providers: IndexVec>, fallback_extern_providers: Box>, - $($(#[$attr])* $name: QueryState<$tcx, queries::$name<$tcx>>,)* + $($(#[$attr])* $name: QueryState< + $tcx, + as QueryAccessors<'tcx>>::Cache, + >,)* + } + + impl<$tcx> Queries<$tcx> { + pub(crate) fn new( + providers: IndexVec>, + fallback_extern_providers: Providers<$tcx>, + on_disk_cache: OnDiskCache<'tcx>, + ) -> Self { + Queries { + providers, + fallback_extern_providers: Box::new(fallback_extern_providers), + on_disk_cache, + $($name: Default::default()),* + } + } + + pub(crate) fn try_collect_active_jobs( + &self + ) -> Option>> { + let mut jobs = FxHashMap::default(); + + $( + self.$name.try_collect_active_jobs( + as QueryAccessors<'tcx>>::DEP_KIND, + Query::$name, + &mut jobs, + )?; + )* + + Some(jobs) + } } }; } diff --git a/src/librustc/ty/query/profiling_support.rs b/src/librustc/ty/query/profiling_support.rs index 99ada34d59ebe..0081794051f37 100644 --- a/src/librustc/ty/query/profiling_support.rs +++ b/src/librustc/ty/query/profiling_support.rs @@ -1,11 +1,11 @@ -use crate::hir::map::definitions::DefPathData; use crate::ty::context::TyCtxt; -use crate::ty::query::config::QueryAccessors; +use crate::ty::query::caches::QueryCache; use crate::ty::query::plumbing::QueryState; use measureme::{StringComponent, StringId}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::profiling::SelfProfiler; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::definitions::DefPathData; use std::fmt::Debug; use std::io::Write; @@ -157,13 +157,14 @@ where /// Allocate the self-profiling query strings for a single query cache. This /// method is called from `alloc_self_profile_query_strings` which knows all /// the queries via macro magic. -pub(super) fn alloc_self_profile_query_strings_for_query_cache<'tcx, Q>( +pub(super) fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>( tcx: TyCtxt<'tcx>, query_name: &'static str, - query_state: &QueryState<'tcx, Q>, + query_state: &QueryState<'tcx, C>, string_cache: &mut QueryKeyStringCache, ) where - Q: QueryAccessors<'tcx>, + C: QueryCache, + C::Key: Debug + Clone, { tcx.prof.with_profiler(|profiler| { let event_id_builder = profiler.event_id_builder(); diff --git a/src/librustc/ty/query/stats.rs b/src/librustc/ty/query/stats.rs index d257320d4eaf6..527bb46c90888 100644 --- a/src/librustc/ty/query/stats.rs +++ b/src/librustc/ty/query/stats.rs @@ -1,3 +1,4 @@ +use crate::ty::query::caches::QueryCache; use crate::ty::query::config::QueryAccessors; use crate::ty::query::plumbing::QueryState; use crate::ty::query::queries; @@ -37,20 +38,17 @@ struct QueryStats { local_def_id_keys: Option, } -fn stats<'tcx, Q: QueryAccessors<'tcx>>( - name: &'static str, - map: &QueryState<'tcx, Q>, -) -> QueryStats { +fn stats<'tcx, C: QueryCache>(name: &'static str, map: &QueryState<'tcx, C>) -> QueryStats { let mut stats = QueryStats { name, #[cfg(debug_assertions)] cache_hits: map.cache_hits.load(Ordering::Relaxed), #[cfg(not(debug_assertions))] cache_hits: 0, - key_size: mem::size_of::(), - key_type: type_name::(), - value_size: mem::size_of::(), - value_type: type_name::(), + key_size: mem::size_of::(), + key_type: type_name::(), + value_size: mem::size_of::(), + value_type: type_name::(), entry_count: map.iter_results(|results| results.count()), local_def_id_keys: None, }; @@ -125,7 +123,9 @@ macro_rules! print_stats { let mut queries = Vec::new(); $($( - queries.push(stats::>( + queries.push(stats::< + as QueryAccessors<'_>>::Cache, + >( stringify!($name), &tcx.queries.$name, )); diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index fb4184a9fb347..872e06e1176dc 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -440,7 +440,7 @@ pub fn super_relate_tys>( (Some(sz_a_val), Some(sz_b_val)) => Err(TypeError::FixedArraySize( expected_found(relation, &sz_a_val, &sz_b_val), )), - _ => return Err(err), + _ => Err(err), } } } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index e2fa03139110c..81be5b11143af 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -81,8 +81,6 @@ impl fmt::Debug for ty::RegionKind { match *self { ty::ReEarlyBound(ref data) => write!(f, "ReEarlyBound({}, {})", data.index, data.name), - ty::ReClosureBound(ref vid) => write!(f, "ReClosureBound({:?})", vid), - ty::ReLateBound(binder_id, ref bound_region) => { write!(f, "ReLateBound({:?}, {:?})", binder_id, bound_region) } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 76b9aed831482..d440e84e15c45 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -8,10 +8,10 @@ use self::TyKind::*; use crate::infer::canonical::Canonical; use crate::middle::region; use crate::mir::interpret::ConstValue; -use crate::mir::interpret::Scalar; +use crate::mir::interpret::{LitToConstInput, Scalar}; use crate::mir::Promoted; use crate::ty::layout::VariantIdx; -use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef}; +use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; use crate::ty::{ self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable, WithConstness, }; @@ -20,7 +20,7 @@ use polonius_engine::Atom; use rustc_ast::ast::{self, Ident}; use rustc_data_structures::captures::Captures; use rustc_hir as hir; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_index::vec::Idx; use rustc_macros::HashStable; use rustc_span::symbol::{kw, Symbol}; @@ -31,38 +31,15 @@ use std::cmp::Ordering; use std::marker::PhantomData; use std::ops::Range; -#[derive( - Clone, - Copy, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - Debug, - RustcEncodable, - RustcDecodable, - HashStable, - TypeFoldable, - Lift -)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] +#[derive(HashStable, TypeFoldable, Lift)] pub struct TypeAndMut<'tcx> { pub ty: Ty<'tcx>, pub mutbl: hir::Mutability, } -#[derive( - Clone, - PartialEq, - PartialOrd, - Eq, - Ord, - Hash, - RustcEncodable, - RustcDecodable, - Copy, - HashStable -)] +#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable, RustcDecodable, Copy)] +#[derive(HashStable)] /// A "free" region `fr` can be interpreted as "some region /// at least as big as the scope `fr.scope`". pub struct FreeRegion { @@ -70,18 +47,8 @@ pub struct FreeRegion { pub bound_region: BoundRegion, } -#[derive( - Clone, - PartialEq, - PartialOrd, - Eq, - Ord, - Hash, - RustcEncodable, - RustcDecodable, - Copy, - HashStable -)] +#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable, RustcDecodable, Copy)] +#[derive(HashStable)] pub enum BoundRegion { /// An anonymous region parameter for a given fn (&T) BrAnon(u32), @@ -119,18 +86,8 @@ impl BoundRegion { /// N.B., if you change this, you'll probably want to change the corresponding /// AST structure in `librustc_ast/ast.rs` as well. -#[derive( - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - RustcEncodable, - RustcDecodable, - HashStable, - Debug -)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)] +#[derive(HashStable)] #[rustc_diagnostic_item = "TyKind"] pub enum TyKind<'tcx> { /// The primitive boolean type. Written as `bool`. @@ -260,15 +217,11 @@ static_assert_size!(TyKind<'_>, 24); /// A closure can be modeled as a struct that looks like: /// -/// struct Closure<'l0...'li, T0...Tj, CK, CS, U0...Uk> { -/// upvar0: U0, -/// ... -/// upvark: Uk -/// } +/// struct Closure<'l0...'li, T0...Tj, CK, CS, U>(...U); /// /// where: /// -/// - 'l0...'li and T0...Tj are the lifetime and type parameters +/// - 'l0...'li and T0...Tj are the generic parameters /// in scope on the function that defined the closure, /// - CK represents the *closure kind* (Fn vs FnMut vs FnOnce). This /// is rather hackily encoded via a scalar type. See @@ -277,9 +230,9 @@ static_assert_size!(TyKind<'_>, 24); /// type. For example, `fn(u32, u32) -> u32` would mean that the closure /// implements `CK<(u32, u32), Output = u32>`, where `CK` is the trait /// specified above. -/// - U0...Uk are type parameters representing the types of its upvars -/// (borrowed, if appropriate; that is, if Ui represents a by-ref upvar, -/// and the up-var has the type `Foo`, then `Ui = &Foo`). +/// - U is a type parameter representing the types of its upvars, tupled up +/// (borrowed, if appropriate; that is, if an U field represents a by-ref upvar, +/// and the up-var has the type `Foo`, then that field of U will be `&Foo`). /// /// So, for example, given this function: /// @@ -289,9 +242,7 @@ static_assert_size!(TyKind<'_>, 24); /// /// the type of the closure would be something like: /// -/// struct Closure<'a, T, U0> { -/// data: U0 -/// } +/// struct Closure<'a, T, U>(...U); /// /// Note that the type of the upvar is not specified in the struct. /// You may wonder how the impl would then be able to use the upvar, @@ -299,7 +250,7 @@ static_assert_size!(TyKind<'_>, 24); /// (conceptually) not fully generic over Closure but rather tied to /// instances with the expected upvar types: /// -/// impl<'b, 'a, T> FnMut() for Closure<'a, T, &'b mut &'a mut T> { +/// impl<'b, 'a, T> FnMut() for Closure<'a, T, (&'b mut &'a mut T,)> { /// ... /// } /// @@ -308,7 +259,7 @@ static_assert_size!(TyKind<'_>, 24); /// (Here, I am assuming that `data` is mut-borrowed.) /// /// Now, the last question you may ask is: Why include the upvar types -/// as extra type parameters? The reason for this design is that the +/// in an extra type parameter? The reason for this design is that the /// upvar types can reference lifetimes that are internal to the /// creating function. In my example above, for example, the lifetime /// `'b` represents the scope of the closure itself; this is some @@ -360,7 +311,7 @@ static_assert_size!(TyKind<'_>, 24); #[derive(Copy, Clone, Debug, TypeFoldable)] pub struct ClosureSubsts<'tcx> { /// Lifetime and type parameters from the enclosing function, - /// concatenated with the types of the upvars. + /// concatenated with a tuple containing the types of the upvars. /// /// These are separated out because codegen wants to pass them around /// when monomorphizing. @@ -370,54 +321,52 @@ pub struct ClosureSubsts<'tcx> { /// Struct returned by `split()`. Note that these are subslices of the /// parent slice and not canonical substs themselves. struct SplitClosureSubsts<'tcx> { - closure_kind_ty: Ty<'tcx>, - closure_sig_ty: Ty<'tcx>, - upvar_kinds: &'tcx [GenericArg<'tcx>], + closure_kind_ty: GenericArg<'tcx>, + closure_sig_as_fn_ptr_ty: GenericArg<'tcx>, + tupled_upvars_ty: GenericArg<'tcx>, } impl<'tcx> ClosureSubsts<'tcx> { /// Divides the closure substs into their respective /// components. Single source of truth with respect to the /// ordering. - fn split(self, def_id: DefId, tcx: TyCtxt<'_>) -> SplitClosureSubsts<'tcx> { - let generics = tcx.generics_of(def_id); - let parent_len = generics.parent_count; - SplitClosureSubsts { - closure_kind_ty: self.substs.type_at(parent_len), - closure_sig_ty: self.substs.type_at(parent_len + 1), - upvar_kinds: &self.substs[parent_len + 2..], + fn split(self) -> SplitClosureSubsts<'tcx> { + match self.substs[..] { + [.., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => { + SplitClosureSubsts { closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty } + } + _ => bug!("closure substs missing synthetics"), } } + /// Returns `true` only if enough of the synthetic types are known to + /// allow using all of the methods on `ClosureSubsts` without panicking. + /// + /// Used primarily by `ty::print::pretty` to be able to handle closure + /// types that haven't had their synthetic types substituted in. + pub fn is_valid(self) -> bool { + self.substs.len() >= 3 && matches!(self.split().tupled_upvars_ty.expect_ty().kind, Tuple(_)) + } + #[inline] - pub fn upvar_tys( - self, - def_id: DefId, - tcx: TyCtxt<'_>, - ) -> impl Iterator> + 'tcx { - let SplitClosureSubsts { upvar_kinds, .. } = self.split(def_id, tcx); - upvar_kinds.iter().map(|t| { - if let GenericArgKind::Type(ty) = t.unpack() { - ty - } else { - bug!("upvar should be type") - } - }) + pub fn upvar_tys(self) -> impl Iterator> + 'tcx { + self.split().tupled_upvars_ty.expect_ty().tuple_fields() } /// Returns the closure kind for this closure; may return a type /// variable during inference. To get the closure kind during - /// inference, use `infcx.closure_kind(def_id, substs)`. - pub fn kind_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> { - self.split(def_id, tcx).closure_kind_ty + /// inference, use `infcx.closure_kind(substs)`. + pub fn kind_ty(self) -> Ty<'tcx> { + self.split().closure_kind_ty.expect_ty() } - /// Returns the type representing the closure signature for this - /// closure; may contain type variables during inference. To get - /// the closure signature during inference, use - /// `infcx.fn_sig(def_id)`. - pub fn sig_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> { - self.split(def_id, tcx).closure_sig_ty + /// Returns the `fn` pointer type representing the closure signature for this + /// closure. + // FIXME(eddyb) this should be unnecessary, as the shallowly resolved + // type is known at the time of the creation of `ClosureSubsts`, + // see `rustc_typeck::check::closure`. + pub fn sig_as_fn_ptr_ty(self) -> Ty<'tcx> { + self.split().closure_sig_as_fn_ptr_ty.expect_ty() } /// Returns the closure kind for this closure; only usable outside @@ -425,20 +374,16 @@ impl<'tcx> ClosureSubsts<'tcx> { /// there are no type variables. /// /// If you have an inference context, use `infcx.closure_kind()`. - pub fn kind(self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::ClosureKind { - self.split(def_id, tcx).closure_kind_ty.to_opt_closure_kind().unwrap() + pub fn kind(self) -> ty::ClosureKind { + self.kind_ty().to_opt_closure_kind().unwrap() } - /// Extracts the signature from the closure; only usable outside - /// of an inference context, because in that context we know that - /// there are no type variables. - /// - /// If you have an inference context, use `infcx.closure_sig()`. - pub fn sig(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { - let ty = self.sig_ty(def_id, tcx); + /// Extracts the signature from the closure. + pub fn sig(self) -> ty::PolyFnSig<'tcx> { + let ty = self.sig_as_fn_ptr_ty(); match ty.kind { ty::FnPtr(sig) => sig, - _ => bug!("closure_sig_ty is not a fn-ptr: {:?}", ty.kind), + _ => bug!("closure_sig_as_fn_ptr_ty is not a fn-ptr: {:?}", ty.kind), } } } @@ -450,64 +395,59 @@ pub struct GeneratorSubsts<'tcx> { } struct SplitGeneratorSubsts<'tcx> { - resume_ty: Ty<'tcx>, - yield_ty: Ty<'tcx>, - return_ty: Ty<'tcx>, - witness: Ty<'tcx>, - upvar_kinds: &'tcx [GenericArg<'tcx>], + resume_ty: GenericArg<'tcx>, + yield_ty: GenericArg<'tcx>, + return_ty: GenericArg<'tcx>, + witness: GenericArg<'tcx>, + tupled_upvars_ty: GenericArg<'tcx>, } impl<'tcx> GeneratorSubsts<'tcx> { - fn split(self, def_id: DefId, tcx: TyCtxt<'_>) -> SplitGeneratorSubsts<'tcx> { - let generics = tcx.generics_of(def_id); - let parent_len = generics.parent_count; - SplitGeneratorSubsts { - resume_ty: self.substs.type_at(parent_len), - yield_ty: self.substs.type_at(parent_len + 1), - return_ty: self.substs.type_at(parent_len + 2), - witness: self.substs.type_at(parent_len + 3), - upvar_kinds: &self.substs[parent_len + 4..], + fn split(self) -> SplitGeneratorSubsts<'tcx> { + match self.substs[..] { + [.., resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty] => { + SplitGeneratorSubsts { resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty } + } + _ => bug!("generator substs missing synthetics"), } } + /// Returns `true` only if enough of the synthetic types are known to + /// allow using all of the methods on `GeneratorSubsts` without panicking. + /// + /// Used primarily by `ty::print::pretty` to be able to handle generator + /// types that haven't had their synthetic types substituted in. + pub fn is_valid(self) -> bool { + self.substs.len() >= 5 && matches!(self.split().tupled_upvars_ty.expect_ty().kind, Tuple(_)) + } + /// This describes the types that can be contained in a generator. /// It will be a type variable initially and unified in the last stages of typeck of a body. /// It contains a tuple of all the types that could end up on a generator frame. /// The state transformation MIR pass may only produce layouts which mention types /// in this tuple. Upvars are not counted here. - pub fn witness(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> { - self.split(def_id, tcx).witness + pub fn witness(self) -> Ty<'tcx> { + self.split().witness.expect_ty() } #[inline] - pub fn upvar_tys( - self, - def_id: DefId, - tcx: TyCtxt<'_>, - ) -> impl Iterator> + 'tcx { - let SplitGeneratorSubsts { upvar_kinds, .. } = self.split(def_id, tcx); - upvar_kinds.iter().map(|t| { - if let GenericArgKind::Type(ty) = t.unpack() { - ty - } else { - bug!("upvar should be type") - } - }) + pub fn upvar_tys(self) -> impl Iterator> + 'tcx { + self.split().tupled_upvars_ty.expect_ty().tuple_fields() } /// Returns the type representing the resume type of the generator. - pub fn resume_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> { - self.split(def_id, tcx).resume_ty + pub fn resume_ty(self) -> Ty<'tcx> { + self.split().resume_ty.expect_ty() } /// Returns the type representing the yield type of the generator. - pub fn yield_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> { - self.split(def_id, tcx).yield_ty + pub fn yield_ty(self) -> Ty<'tcx> { + self.split().yield_ty.expect_ty() } /// Returns the type representing the return type of the generator. - pub fn return_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> { - self.split(def_id, tcx).return_ty + pub fn return_ty(self) -> Ty<'tcx> { + self.split().return_ty.expect_ty() } /// Returns the "generator signature", which consists of its yield @@ -516,17 +456,17 @@ impl<'tcx> GeneratorSubsts<'tcx> { /// N.B., some bits of the code prefers to see this wrapped in a /// binder, but it never contains bound regions. Probably this /// function should be removed. - pub fn poly_sig(self, def_id: DefId, tcx: TyCtxt<'_>) -> PolyGenSig<'tcx> { - ty::Binder::dummy(self.sig(def_id, tcx)) + pub fn poly_sig(self) -> PolyGenSig<'tcx> { + ty::Binder::dummy(self.sig()) } /// Returns the "generator signature", which consists of its resume, yield /// and return types. - pub fn sig(self, def_id: DefId, tcx: TyCtxt<'_>) -> GenSig<'tcx> { + pub fn sig(self) -> GenSig<'tcx> { ty::GenSig { - resume_ty: self.resume_ty(def_id, tcx), - yield_ty: self.yield_ty(def_id, tcx), - return_ty: self.return_ty(def_id, tcx), + resume_ty: self.resume_ty(), + yield_ty: self.yield_ty(), + return_ty: self.return_ty(), } } } @@ -618,8 +558,8 @@ impl<'tcx> GeneratorSubsts<'tcx> { /// This is the types of the fields of a generator which are not stored in a /// variant. #[inline] - pub fn prefix_tys(self, def_id: DefId, tcx: TyCtxt<'tcx>) -> impl Iterator> { - self.upvar_tys(def_id, tcx) + pub fn prefix_tys(self) -> impl Iterator> { + self.upvar_tys() } } @@ -631,22 +571,12 @@ pub enum UpvarSubsts<'tcx> { impl<'tcx> UpvarSubsts<'tcx> { #[inline] - pub fn upvar_tys( - self, - def_id: DefId, - tcx: TyCtxt<'tcx>, - ) -> impl Iterator> + 'tcx { - let upvar_kinds = match self { - UpvarSubsts::Closure(substs) => substs.as_closure().split(def_id, tcx).upvar_kinds, - UpvarSubsts::Generator(substs) => substs.as_generator().split(def_id, tcx).upvar_kinds, + pub fn upvar_tys(self) -> impl Iterator> + 'tcx { + let tupled_upvars_ty = match self { + UpvarSubsts::Closure(substs) => substs.as_closure().split().tupled_upvars_ty, + UpvarSubsts::Generator(substs) => substs.as_generator().split().tupled_upvars_ty, }; - upvar_kinds.iter().map(|t| { - if let GenericArgKind::Type(ty) = t.unpack() { - ty - } else { - bug!("upvar should be type") - } - }) + tupled_upvars_ty.expect_ty().tuple_fields() } } @@ -1174,18 +1104,8 @@ impl<'tcx> PolyFnSig<'tcx> { pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder>>; -#[derive( - Clone, - Copy, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - RustcEncodable, - RustcDecodable, - HashStable -)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] +#[derive(HashStable)] pub struct ParamTy { pub index: u32, pub name: Symbol, @@ -1209,18 +1129,8 @@ impl<'tcx> ParamTy { } } -#[derive( - Copy, - Clone, - Hash, - RustcEncodable, - RustcDecodable, - Eq, - PartialEq, - Ord, - PartialOrd, - HashStable -)] +#[derive(Copy, Clone, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq, Ord, PartialOrd)] +#[derive(HashStable)] pub struct ParamConst { pub index: u32, pub name: Symbol, @@ -1442,12 +1352,6 @@ pub enum RegionKind { /// Erased region, used by trait selection, in MIR and during codegen. ReErased, - - /// These are regions bound in the "defining type" for a - /// closure. They are used ONLY as part of the - /// `ClosureRegionRequirements` that are produced by MIR borrowck. - /// See `ClosureRegionRequirements` for more details. - ReClosureBound(RegionVid), } impl<'tcx> rustc_serialize::UseSpecializedDecodable for Region<'tcx> {} @@ -1492,18 +1396,8 @@ impl Atom for RegionVid { } } -#[derive( - Clone, - Copy, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - RustcEncodable, - RustcDecodable, - HashStable -)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] +#[derive(HashStable)] pub enum InferTy { TyVar(TyVid), IntVar(IntVid), @@ -1521,37 +1415,15 @@ rustc_index::newtype_index! { pub struct BoundVar { .. } } -#[derive( - Clone, - Copy, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - Debug, - RustcEncodable, - RustcDecodable, - HashStable -)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] +#[derive(HashStable)] pub struct BoundTy { pub var: BoundVar, pub kind: BoundTyKind, } -#[derive( - Clone, - Copy, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - Debug, - RustcEncodable, - RustcDecodable, - HashStable -)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] +#[derive(HashStable)] pub enum BoundTyKind { Anon, Param(Symbol), @@ -1612,7 +1484,7 @@ impl<'tcx> PolyExistentialProjection<'tcx> { } pub fn item_def_id(&self) -> DefId { - return self.skip_binder().item_def_id; + self.skip_binder().item_def_id } } @@ -1689,7 +1561,6 @@ impl RegionKind { RegionKind::RePlaceholder(placeholder) => placeholder.name.is_named(), RegionKind::ReEmpty(_) => false, RegionKind::ReErased => false, - RegionKind::ReClosureBound(..) => false, } } @@ -1743,42 +1614,39 @@ impl RegionKind { } } - pub fn keep_in_local_tcx(&self) -> bool { - if let ty::ReVar(..) = self { true } else { false } - } - pub fn type_flags(&self) -> TypeFlags { let mut flags = TypeFlags::empty(); - if self.keep_in_local_tcx() { - flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX; - } - match *self { ty::ReVar(..) => { flags = flags | TypeFlags::HAS_FREE_REGIONS; + flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; flags = flags | TypeFlags::HAS_RE_INFER; + flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX; } ty::RePlaceholder(..) => { flags = flags | TypeFlags::HAS_FREE_REGIONS; + flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; flags = flags | TypeFlags::HAS_RE_PLACEHOLDER; } - ty::ReLateBound(..) => { - flags = flags | TypeFlags::HAS_RE_LATE_BOUND; - } ty::ReEarlyBound(..) => { flags = flags | TypeFlags::HAS_FREE_REGIONS; + flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; flags = flags | TypeFlags::HAS_RE_PARAM; } - ty::ReEmpty(_) | ty::ReStatic | ty::ReFree { .. } | ty::ReScope { .. } => { + ty::ReFree { .. } | ty::ReScope { .. } => { flags = flags | TypeFlags::HAS_FREE_REGIONS; + flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; + } + ty::ReEmpty(_) | ty::ReStatic => { + flags = flags | TypeFlags::HAS_FREE_REGIONS; + } + ty::ReLateBound(..) => { + flags = flags | TypeFlags::HAS_RE_LATE_BOUND; } ty::ReErased => { flags = flags | TypeFlags::HAS_RE_ERASED; } - ty::ReClosureBound(..) => { - flags = flags | TypeFlags::HAS_FREE_REGIONS; - } } debug!("type_flags({:?}) = {:?}", self, flags); @@ -2000,8 +1868,8 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_unsafe_ptr(&self) -> bool { match self.kind { - RawPtr(_) => return true, - _ => return false, + RawPtr(_) => true, + _ => false, } } @@ -2200,9 +2068,9 @@ impl<'tcx> TyS<'tcx> { // ignore errors (#54954) ty::Binder::dummy(FnSig::fake()) } - Closure(..) => { - bug!("to get the signature of a closure, use `closure_sig()` not `fn_sig()`",) - } + Closure(..) => bug!( + "to get the signature of a closure, use `substs.as_closure().sig()` not `fn_sig()`", + ), _ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self), } } @@ -2385,19 +2253,8 @@ impl<'tcx> TyS<'tcx> { } /// Typed constant value. -#[derive( - Copy, - Clone, - Debug, - Hash, - RustcEncodable, - RustcDecodable, - Eq, - PartialEq, - Ord, - PartialOrd, - HashStable -)] +#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq, Ord, PartialOrd)] +#[derive(HashStable)] pub struct Const<'tcx> { pub ty: Ty<'tcx>, @@ -2408,17 +2265,92 @@ pub struct Const<'tcx> { static_assert_size!(Const<'_>, 48); impl<'tcx> Const<'tcx> { + /// Literals and const generic parameters are eagerly converted to a constant, everything else + /// becomes `Unevaluated`. + pub fn from_anon_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx Self { + debug!("Const::from_anon_const(id={:?})", def_id); + + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + + let body_id = match tcx.hir().get(hir_id) { + hir::Node::AnonConst(ac) => ac.body, + _ => span_bug!( + tcx.def_span(def_id.to_def_id()), + "from_anon_const can only process anonymous constants" + ), + }; + + let expr = &tcx.hir().body(body_id).value; + + let ty = tcx.type_of(def_id.to_def_id()); + + let lit_input = match expr.kind { + hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }), + hir::ExprKind::Unary(hir::UnOp::UnNeg, ref expr) => match expr.kind { + hir::ExprKind::Lit(ref lit) => { + Some(LitToConstInput { lit: &lit.node, ty, neg: true }) + } + _ => None, + }, + _ => None, + }; + + if let Some(lit_input) = lit_input { + // If an error occurred, ignore that it's a literal and leave reporting the error up to + // mir. + if let Ok(c) = tcx.at(expr.span).lit_to_const(lit_input) { + return c; + } else { + tcx.sess.delay_span_bug(expr.span, "Const::from_anon_const: couldn't lit_to_const"); + } + } + + // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments + // currently have to be wrapped in curly brackets, so it's necessary to special-case. + let expr = match &expr.kind { + hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => { + block.expr.as_ref().unwrap() + } + _ => expr, + }; + + use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath}; + let val = match expr.kind { + ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => { + // Find the name and index of the const parameter by indexing the generics of + // the parent item and construct a `ParamConst`. + let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); + let item_id = tcx.hir().get_parent_node(hir_id); + let item_def_id = tcx.hir().local_def_id(item_id); + let generics = tcx.generics_of(item_def_id); + let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(hir_id)]; + let name = tcx.hir().name(hir_id); + ty::ConstKind::Param(ty::ParamConst::new(index, name)) + } + _ => ty::ConstKind::Unevaluated( + def_id.to_def_id(), + InternalSubsts::identity_for_item(tcx, def_id.to_def_id()), + None, + ), + }; + + tcx.mk_const(ty::Const { val, ty }) + } + #[inline] + /// Interns the given value as a constant. pub fn from_value(tcx: TyCtxt<'tcx>, val: ConstValue<'tcx>, ty: Ty<'tcx>) -> &'tcx Self { tcx.mk_const(Self { val: ConstKind::Value(val), ty }) } #[inline] + /// Interns the given scalar as a constant. pub fn from_scalar(tcx: TyCtxt<'tcx>, val: Scalar, ty: Ty<'tcx>) -> &'tcx Self { Self::from_value(tcx, ConstValue::Scalar(val), ty) } #[inline] + /// Creates a constant with the given integer value and interns it. pub fn from_bits(tcx: TyCtxt<'tcx>, bits: u128, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> &'tcx Self { let size = tcx .layout_of(ty) @@ -2428,21 +2360,27 @@ impl<'tcx> Const<'tcx> { } #[inline] + /// Creates an interned zst constant. pub fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx Self { Self::from_scalar(tcx, Scalar::zst(), ty) } #[inline] + /// Creates an interned bool constant. pub fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> &'tcx Self { Self::from_bits(tcx, v as u128, ParamEnv::empty().and(tcx.types.bool)) } #[inline] + /// Creates an interned usize constant. pub fn from_usize(tcx: TyCtxt<'tcx>, n: u64) -> &'tcx Self { Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize)) } #[inline] + /// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of + /// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it + /// contains const generic parameters or pointers). pub fn try_eval_bits( &self, tcx: TyCtxt<'tcx>, @@ -2456,6 +2394,8 @@ impl<'tcx> Const<'tcx> { } #[inline] + /// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the + /// unevaluated constant. pub fn eval(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> &Const<'tcx> { let try_const_eval = |did, param_env: ParamEnv<'tcx>, substs, promoted| { let param_env_and_substs = param_env.with_reveal_all().and(substs); @@ -2512,12 +2452,14 @@ impl<'tcx> Const<'tcx> { } #[inline] + /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type. pub fn eval_bits(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 { self.try_eval_bits(tcx, param_env, ty) .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", ty, self)) } #[inline] + /// Panics if the value cannot be evaluated or doesn't contain a valid `usize`. pub fn eval_usize(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u64 { self.eval_bits(tcx, param_env, tcx.types.usize) as u64 } @@ -2526,19 +2468,8 @@ impl<'tcx> Const<'tcx> { impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx Const<'tcx> {} /// Represents a constant in Rust. -#[derive( - Copy, - Clone, - Debug, - Eq, - PartialEq, - PartialOrd, - Ord, - RustcEncodable, - RustcDecodable, - Hash, - HashStable -)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)] +#[derive(HashStable)] pub enum ConstKind<'tcx> { /// A const generic parameter. Param(ParamConst), @@ -2576,19 +2507,8 @@ impl<'tcx> ConstKind<'tcx> { } /// An inference variable for a const, for use in const generics. -#[derive( - Copy, - Clone, - Debug, - Eq, - PartialEq, - PartialOrd, - Ord, - RustcEncodable, - RustcDecodable, - Hash, - HashStable -)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)] +#[derive(HashStable)] pub enum InferConst<'tcx> { /// Infer the value of the const. Var(ConstVid<'tcx>), diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index a005581283550..0f4485a705046 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -128,6 +128,14 @@ impl<'tcx> GenericArg<'tcx> { _ => bug!("expected a type, but found another kind"), } } + + /// Unpack the `GenericArg` as a const when it is known certainly to be a const. + pub fn expect_const(self) -> &'tcx ty::Const<'tcx> { + match self.unpack() { + GenericArgKind::Const(c) => c, + _ => bug!("expected a const, but found another kind"), + } + } } impl<'a, 'tcx> Lift<'tcx> for GenericArg<'a> { @@ -524,7 +532,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> { self.root_ty = None; } - return t1; + t1 } fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs index 0cf1c397648ed..ed9054fcffd91 100644 --- a/src/librustc/ty/trait_def.rs +++ b/src/librustc/ty/trait_def.rs @@ -1,15 +1,18 @@ -use crate::hir::map::DefPathHash; use crate::ich::{self, StableHashingContext}; use crate::traits::specialization_graph; use crate::ty::fast_reject; use crate::ty::fold::TypeFoldable; use crate::ty::{Ty, TyCtxt}; use rustc_hir as hir; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{CrateNum, DefId}; +use rustc_hir::definitions::DefPathHash; +use rustc_hir::HirId; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_errors::ErrorReported; use rustc_macros::HashStable; +use std::collections::BTreeMap; /// A trait's definition with type information. #[derive(HashStable)] @@ -33,11 +36,33 @@ pub struct TraitDef { /// and thus `impl`s of it are allowed to overlap. pub is_marker: bool, + /// Used to determine whether the standard library is allowed to specialize + /// on this trait. + pub specialization_kind: TraitSpecializationKind, + /// The ICH of this trait's DefPath, cached here so it doesn't have to be /// recomputed all the time. pub def_path_hash: DefPathHash, } +/// Whether this trait is treated specially by the standard library +/// specialization lint. +#[derive(HashStable, PartialEq, Clone, Copy, RustcEncodable, RustcDecodable)] +pub enum TraitSpecializationKind { + /// The default. Specializing on this trait is not allowed. + None, + /// Specializing on this trait is allowed because it doesn't have any + /// methods. For example `Sized` or `FusedIterator`. + /// Applies to traits with the `rustc_unsafe_specialization_marker` + /// attribute. + Marker, + /// Specializing on this trait is allowed because all of the impls of this + /// trait are "always applicable". Always applicable means that if + /// `X<'x>: T<'y>` for any lifetimes, then `for<'a, 'b> X<'a>: T<'b>`. + /// Applies to traits with the `rustc_specialization_trait` attribute. + AlwaysApplicable, +} + #[derive(Default)] pub struct TraitImpls { blanket_impls: Vec, @@ -52,16 +77,25 @@ impl<'tcx> TraitDef { paren_sugar: bool, has_auto_impl: bool, is_marker: bool, + specialization_kind: TraitSpecializationKind, def_path_hash: DefPathHash, ) -> TraitDef { - TraitDef { def_id, unsafety, paren_sugar, has_auto_impl, is_marker, def_path_hash } + TraitDef { + def_id, + unsafety, + paren_sugar, + has_auto_impl, + is_marker, + specialization_kind, + def_path_hash, + } } pub fn ancestors( &self, tcx: TyCtxt<'tcx>, of_impl: DefId, - ) -> specialization_graph::Ancestors<'tcx> { + ) -> Result, ErrorReported> { specialization_graph::ancestors(tcx, self.def_id, of_impl) } } @@ -146,6 +180,14 @@ impl<'tcx> TyCtxt<'tcx> { } } +// Query provider for `all_local_trait_impls`. +pub(super) fn all_local_trait_impls<'tcx>( + tcx: TyCtxt<'tcx>, + krate: CrateNum, +) -> &'tcx BTreeMap> { + &tcx.hir_crate(krate).trait_impls +} + // Query provider for `trait_impls_of`. pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> &TraitImpls { let mut impls = TraitImpls::default(); diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index fcebedb2601c2..dab367a6639ed 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -1,6 +1,5 @@ //! Miscellaneous type-system utilities that are too small to deserve their own modules. -use crate::hir::map::DefPathData; use crate::ich::NodeIdHashingMode; use crate::mir::interpret::{sign_extend, truncate}; use crate::ty::layout::{Integer, IntegerExt, Size}; @@ -17,6 +16,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; +use rustc_hir::definitions::DefPathData; use rustc_macros::HashStable; use rustc_span::Span; use rustc_target::abi::TargetDataLayout; @@ -346,12 +346,7 @@ impl<'tcx> TyCtxt<'tcx> { adt_did: DefId, validate: &mut dyn FnMut(Self, DefId) -> Result<(), ErrorReported>, ) -> Option { - let drop_trait = if let Some(def_id) = self.lang_items().drop_trait() { - def_id - } else { - return None; - }; - + let drop_trait = self.lang_items().drop_trait()?; self.ensure().coherent_trait(drop_trait); let mut dtor_did = None; @@ -507,7 +502,7 @@ impl<'tcx> TyCtxt<'tcx> { ) -> Option>> { let closure_ty = self.mk_closure(closure_def_id, closure_substs); let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv); - let closure_kind_ty = closure_substs.as_closure().kind_ty(closure_def_id, self); + let closure_kind_ty = closure_substs.as_closure().kind_ty(); let closure_kind = closure_kind_ty.to_opt_closure_kind()?; let env_ty = match closure_kind { ty::ClosureKind::Fn => self.mk_imm_ref(self.mk_region(env_region), closure_ty), diff --git a/src/librustc/util/bug.rs b/src/librustc/util/bug.rs index c12b2859f728e..54cd8a29f9474 100644 --- a/src/librustc/util/bug.rs +++ b/src/librustc/util/bug.rs @@ -1,6 +1,6 @@ // These functions are used by macro expansion for bug! and span_bug! -use crate::ty::tls; +use crate::ty::{tls, TyCtxt}; use rustc_span::{MultiSpan, Span}; use std::fmt; @@ -39,3 +39,17 @@ fn opt_span_bug_fmt>( }); unreachable!(); } + +/// A query to trigger a `delay_span_bug`. Clearly, if one has a `tcx` one can already trigger a +/// `delay_span_bug`, so what is the point of this? It exists to help us test `delay_span_bug`'s +/// interactions with the query system and incremental. +pub fn trigger_delay_span_bug(tcx: TyCtxt<'_>, key: rustc_hir::def_id::DefId) { + tcx.sess.delay_span_bug( + tcx.def_span(key), + "delayed span bug triggered by #[rustc_error(delay_span_bug_from_inside_query)]", + ); +} + +pub fn provide(providers: &mut crate::ty::query::Providers<'_>) { + *providers = crate::ty::query::Providers { trigger_delay_span_bug, ..*providers }; +} diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs index 7faba4600a90a..3e7fb0e73bffe 100644 --- a/src/librustc_ast/ast.rs +++ b/src/librustc_ast/ast.rs @@ -14,7 +14,7 @@ //! - [`Generics`], [`GenericParam`], [`WhereClause`]: Metadata associated with generic parameters. //! - [`EnumDef`] and [`Variant`]: Enum declaration. //! - [`Lit`] and [`LitKind`]: Literal expressions. -//! - [`MacroDef`], [`MacStmtStyle`], [`Mac`], [`MacDelimeter`]: Macro definition and invocation. +//! - [`MacroDef`], [`MacStmtStyle`], [`MacCall`], [`MacDelimeter`]: Macro definition and invocation. //! - [`Attribute`]: Metadata associated with item. //! - [`UnOp`], [`UnOpKind`], [`BinOp`], [`BinOpKind`]: Unary and binary operators. @@ -31,7 +31,6 @@ use crate::tokenstream::{DelimSpan, TokenStream, TokenTree}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::thin_vec::ThinVec; -use rustc_index::vec::Idx; use rustc_macros::HashStable_Generic; use rustc_serialize::{self, Decoder, Encoder}; use rustc_span::source_map::{respan, Spanned}; @@ -251,7 +250,7 @@ impl ParenthesizedArgs { pub fn as_angle_bracketed_args(&self) -> AngleBracketedArgs { AngleBracketedArgs { span: self.span, - args: self.inputs.iter().cloned().map(|input| GenericArg::Type(input)).collect(), + args: self.inputs.iter().cloned().map(GenericArg::Type).collect(), constraints: vec![], } } @@ -513,7 +512,7 @@ impl Pat { TyKind::Path(None, Path::from_ident(*ident)) } PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()), - PatKind::Mac(mac) => TyKind::Mac(mac.clone()), + PatKind::MacCall(mac) => TyKind::MacCall(mac.clone()), // `&mut? P` can be reinterpreted as `&mut? T` where `T` is `P` reparsed as a type. PatKind::Ref(pat, mutbl) => { pat.to_ty().map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))? @@ -567,7 +566,7 @@ impl Pat { | PatKind::Range(..) | PatKind::Ident(..) | PatKind::Path(..) - | PatKind::Mac(_) => {} + | PatKind::MacCall(_) => {} } } @@ -682,22 +681,11 @@ pub enum PatKind { Paren(P), /// A macro pattern; pre-expansion. - Mac(Mac), + MacCall(MacCall), } -#[derive( - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - RustcEncodable, - RustcDecodable, - Debug, - Copy, - HashStable_Generic -)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug, Copy)] +#[derive(HashStable_Generic)] pub enum Mutability { Mut, Not, @@ -881,9 +869,9 @@ impl Stmt { pub fn add_trailing_semicolon(mut self) -> Self { self.kind = match self.kind { StmtKind::Expr(expr) => StmtKind::Semi(expr), - StmtKind::Mac(mac) => { - StmtKind::Mac(mac.map(|(mac, _style, attrs)| (mac, MacStmtStyle::Semicolon, attrs))) - } + StmtKind::MacCall(mac) => StmtKind::MacCall( + mac.map(|(mac, _style, attrs)| (mac, MacStmtStyle::Semicolon, attrs)), + ), kind => kind, }; self @@ -917,7 +905,7 @@ pub enum StmtKind { /// Just a trailing semi-colon. Empty, /// Macro. - Mac(P<(Mac, MacStmtStyle, AttrVec)>), + MacCall(P<(MacCall, MacStmtStyle, AttrVec)>), } #[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)] @@ -1057,7 +1045,7 @@ impl Expr { let kind = match &self.kind { // Trivial conversions. ExprKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()), - ExprKind::Mac(mac) => TyKind::Mac(mac.clone()), + ExprKind::MacCall(mac) => TyKind::MacCall(mac.clone()), ExprKind::Paren(expr) => expr.to_ty().map(TyKind::Paren)?, @@ -1127,7 +1115,7 @@ impl Expr { ExprKind::Continue(..) => ExprPrecedence::Continue, ExprKind::Ret(..) => ExprPrecedence::Ret, ExprKind::InlineAsm(..) => ExprPrecedence::InlineAsm, - ExprKind::Mac(..) => ExprPrecedence::Mac, + ExprKind::MacCall(..) => ExprPrecedence::Mac, ExprKind::Struct(..) => ExprPrecedence::Struct, ExprKind::Repeat(..) => ExprPrecedence::Repeat, ExprKind::Paren(..) => ExprPrecedence::Paren, @@ -1259,7 +1247,7 @@ pub enum ExprKind { InlineAsm(P), /// A macro invocation; pre-expansion. - Mac(Mac), + MacCall(MacCall), /// A struct literal expression. /// @@ -1322,19 +1310,8 @@ pub enum CaptureBy { /// The movability of a generator / closure literal: /// whether a generator contains self-references, causing it to be `!Unpin`. -#[derive( - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - RustcEncodable, - RustcDecodable, - Debug, - Copy, - HashStable_Generic -)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug, Copy)] +#[derive(HashStable_Generic)] pub enum Movability { /// May contain self-references, `!Unpin`. Static, @@ -1345,13 +1322,13 @@ pub enum Movability { /// Represents a macro invocation. The `path` indicates which macro /// is being invoked, and the `args` are arguments passed to it. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct Mac { +pub struct MacCall { pub path: Path, pub args: P, pub prior_type_ascription: Option<(Span, bool)>, } -impl Mac { +impl MacCall { pub fn span(&self) -> Span { self.path.span.to(self.args.span().unwrap_or(self.path.span)) } @@ -1446,11 +1423,11 @@ impl MacDelimiter { } /// Represents a macro definition. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] pub struct MacroDef { pub body: P, /// `true` if macro was defined with `macro_rules`. - pub legacy: bool, + pub macro_rules: bool, } #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, Eq, PartialEq)] @@ -1615,19 +1592,8 @@ pub struct FnSig { pub decl: P, } -#[derive( - Clone, - Copy, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - HashStable_Generic, - RustcEncodable, - RustcDecodable, - Debug -)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)] +#[derive(HashStable_Generic)] pub enum FloatTy { F32, F64, @@ -1648,7 +1614,7 @@ impl FloatTy { } } - pub fn bit_width(self) -> usize { + pub fn bit_width(self) -> u64 { match self { FloatTy::F32 => 32, FloatTy::F64 => 64, @@ -1656,19 +1622,8 @@ impl FloatTy { } } -#[derive( - Clone, - Copy, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - HashStable_Generic, - RustcEncodable, - RustcDecodable, - Debug -)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)] +#[derive(HashStable_Generic)] pub enum IntTy { Isize, I8, @@ -1708,7 +1663,7 @@ impl IntTy { format!("{}{}", val as u128, self.name_str()) } - pub fn bit_width(&self) -> Option { + pub fn bit_width(&self) -> Option { Some(match *self { IntTy::Isize => return None, IntTy::I8 => 8, @@ -1732,19 +1687,8 @@ impl IntTy { } } -#[derive( - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - HashStable_Generic, - RustcEncodable, - RustcDecodable, - Copy, - Debug -)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Copy, Debug)] +#[derive(HashStable_Generic)] pub enum UintTy { Usize, U8, @@ -1781,7 +1725,7 @@ impl UintTy { format!("{}{}", val, self.name_str()) } - pub fn bit_width(&self) -> Option { + pub fn bit_width(&self) -> Option { Some(match *self { UintTy::Usize => return None, UintTy::U8 => 8, @@ -1881,7 +1825,7 @@ pub enum TyKind { /// Inferred type of a `self` or `&self` argument in a method. ImplicitSelf, /// A macro in the type position. - Mac(Mac), + MacCall(MacCall), /// Placeholder for a kind that has failed to be defined. Err, /// Placeholder for a `va_list`. @@ -2153,7 +2097,7 @@ impl FnRetTy { /// Module declaration. /// /// E.g., `mod foo;` or `mod foo { .. }`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Default)] pub struct Mod { /// A span from the first token past `{` to the last token until `}`. /// For `mod foo;`, the inner span ranges from the first token @@ -2251,27 +2195,22 @@ pub enum AttrStyle { Inner, } -#[derive(Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord, Copy)] -pub struct AttrId(pub usize); - -impl Idx for AttrId { - fn new(idx: usize) -> Self { - AttrId(idx) - } - fn index(self) -> usize { - self.0 +rustc_index::newtype_index! { + pub struct AttrId { + ENCODABLE = custom + DEBUG_FORMAT = "AttrId({})" } } impl rustc_serialize::Encodable for AttrId { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_unit() + fn encode(&self, _: &mut S) -> Result<(), S::Error> { + Ok(()) } } impl rustc_serialize::Decodable for AttrId { - fn decode(d: &mut D) -> Result { - d.read_nil().map(|_| crate::attr::mk_attr_id()) + fn decode(_: &mut D) -> Result { + Ok(crate::attr::mk_attr_id()) } } @@ -2574,7 +2513,7 @@ pub enum ItemKind { /// A macro invocation. /// /// E.g., `foo!(..)`. - Mac(Mac), + MacCall(MacCall), /// A macro definition. MacroDef(MacroDef), @@ -2586,7 +2525,7 @@ impl ItemKind { match self { Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..) | Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..) => "a", - ExternCrate(..) | ForeignMod(..) | Mac(..) | Enum(..) | Impl { .. } => "an", + ExternCrate(..) | ForeignMod(..) | MacCall(..) | Enum(..) | Impl { .. } => "an", } } @@ -2606,7 +2545,7 @@ impl ItemKind { ItemKind::Union(..) => "union", ItemKind::Trait(..) => "trait", ItemKind::TraitAlias(..) => "trait alias", - ItemKind::Mac(..) => "item macro invocation", + ItemKind::MacCall(..) => "item macro invocation", ItemKind::MacroDef(..) => "macro definition", ItemKind::Impl { .. } => "implementation", } @@ -2648,14 +2587,14 @@ pub enum AssocItemKind { /// An associated type. TyAlias(Defaultness, Generics, GenericBounds, Option>), /// A macro expanding to associated items. - Macro(Mac), + MacCall(MacCall), } impl AssocItemKind { pub fn defaultness(&self) -> Defaultness { match *self { Self::Const(def, ..) | Self::Fn(def, ..) | Self::TyAlias(def, ..) => def, - Self::Macro(..) => Defaultness::Final, + Self::MacCall(..) => Defaultness::Final, } } } @@ -2666,7 +2605,7 @@ impl From for ItemKind { AssocItemKind::Const(a, b, c) => ItemKind::Const(a, b, c), AssocItemKind::Fn(a, b, c, d) => ItemKind::Fn(a, b, c, d), AssocItemKind::TyAlias(a, b, c, d) => ItemKind::TyAlias(a, b, c, d), - AssocItemKind::Macro(a) => ItemKind::Mac(a), + AssocItemKind::MacCall(a) => ItemKind::MacCall(a), } } } @@ -2679,7 +2618,7 @@ impl TryFrom for AssocItemKind { ItemKind::Const(a, b, c) => AssocItemKind::Const(a, b, c), ItemKind::Fn(a, b, c, d) => AssocItemKind::Fn(a, b, c, d), ItemKind::TyAlias(a, b, c, d) => AssocItemKind::TyAlias(a, b, c, d), - ItemKind::Mac(a) => AssocItemKind::Macro(a), + ItemKind::MacCall(a) => AssocItemKind::MacCall(a), _ => return Err(item_kind), }) } @@ -2695,7 +2634,7 @@ pub enum ForeignItemKind { /// A foreign type. TyAlias(Defaultness, Generics, GenericBounds, Option>), /// A macro expanding to foreign items. - Macro(Mac), + MacCall(MacCall), } impl From for ItemKind { @@ -2704,7 +2643,7 @@ impl From for ItemKind { ForeignItemKind::Static(a, b, c) => ItemKind::Static(a, b, c), ForeignItemKind::Fn(a, b, c, d) => ItemKind::Fn(a, b, c, d), ForeignItemKind::TyAlias(a, b, c, d) => ItemKind::TyAlias(a, b, c, d), - ForeignItemKind::Macro(a) => ItemKind::Mac(a), + ForeignItemKind::MacCall(a) => ItemKind::MacCall(a), } } } @@ -2717,7 +2656,7 @@ impl TryFrom for ForeignItemKind { ItemKind::Static(a, b, c) => ForeignItemKind::Static(a, b, c), ItemKind::Fn(a, b, c, d) => ForeignItemKind::Fn(a, b, c, d), ItemKind::TyAlias(a, b, c, d) => ForeignItemKind::TyAlias(a, b, c, d), - ItemKind::Mac(a) => ForeignItemKind::Macro(a), + ItemKind::MacCall(a) => ForeignItemKind::MacCall(a), _ => return Err(item_kind), }) } diff --git a/src/librustc_ast/attr/mod.rs b/src/librustc_ast/attr/mod.rs index 52a59e82ae23f..d53d776778598 100644 --- a/src/librustc_ast/attr/mod.rs +++ b/src/librustc_ast/attr/mod.rs @@ -366,14 +366,14 @@ pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem { } crate fn mk_attr_id() -> AttrId { - use std::sync::atomic::AtomicUsize; + use std::sync::atomic::AtomicU32; use std::sync::atomic::Ordering; - static NEXT_ATTR_ID: AtomicUsize = AtomicUsize::new(0); + static NEXT_ATTR_ID: AtomicU32 = AtomicU32::new(0); let id = NEXT_ATTR_ID.fetch_add(1, Ordering::SeqCst); - assert!(id != ::std::usize::MAX); - AttrId(id) + assert!(id != u32::MAX); + AttrId::from_u32(id) } pub fn mk_attr(style: AttrStyle, path: Path, args: MacArgs, span: Span) -> Attribute { @@ -679,7 +679,7 @@ impl HasAttrs for StmtKind { StmtKind::Local(ref local) => local.attrs(), StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => expr.attrs(), StmtKind::Empty | StmtKind::Item(..) => &[], - StmtKind::Mac(ref mac) => { + StmtKind::MacCall(ref mac) => { let (_, _, ref attrs) = **mac; attrs.attrs() } @@ -691,7 +691,7 @@ impl HasAttrs for StmtKind { StmtKind::Local(local) => local.visit_attrs(f), StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.visit_attrs(f), StmtKind::Empty | StmtKind::Item(..) => {} - StmtKind::Mac(mac) => { + StmtKind::MacCall(mac) => { let (_mac, _style, attrs) = mac.deref_mut(); attrs.visit_attrs(f); } diff --git a/src/librustc_ast/crate_disambiguator.rs b/src/librustc_ast/crate_disambiguator.rs new file mode 100644 index 0000000000000..95d4c09dac311 --- /dev/null +++ b/src/librustc_ast/crate_disambiguator.rs @@ -0,0 +1,35 @@ +// This is here because `rustc_session` wants to refer to it, +// and so does `rustc_hir`, but `rustc_hir` shouldn't refer to `rustc_session`. + +use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::{base_n, impl_stable_hash_via_hash}; + +use std::fmt; + +/// Hash value constructed out of all the `-C metadata` arguments passed to the +/// compiler. Together with the crate-name forms a unique global identifier for +/// the crate. +#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy, RustcEncodable, RustcDecodable)] +pub struct CrateDisambiguator(Fingerprint); + +impl CrateDisambiguator { + pub fn to_fingerprint(self) -> Fingerprint { + self.0 + } +} + +impl fmt::Display for CrateDisambiguator { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + let (a, b) = self.0.as_value(); + let as_u128 = a as u128 | ((b as u128) << 64); + f.write_str(&base_n::encode(as_u128, base_n::CASE_INSENSITIVE)) + } +} + +impl From for CrateDisambiguator { + fn from(fingerprint: Fingerprint) -> CrateDisambiguator { + CrateDisambiguator(fingerprint) + } +} + +impl_stable_hash_via_hash!(CrateDisambiguator); diff --git a/src/librustc_ast/lib.rs b/src/librustc_ast/lib.rs index adb96356aae7d..a93e0fcbd7193 100644 --- a/src/librustc_ast/lib.rs +++ b/src/librustc_ast/lib.rs @@ -7,7 +7,9 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))] #![feature(bool_to_option)] #![feature(box_syntax)] +#![feature(const_if_match)] #![feature(const_fn)] // For the `transmute` in `P::new` +#![feature(const_panic)] #![feature(const_transmute)] #![feature(crate_visibility_modifier)] #![feature(label_break_value)] @@ -38,6 +40,7 @@ pub mod util { pub mod ast; pub mod attr; pub use attr::{with_default_globals, with_globals, GLOBALS}; +pub mod crate_disambiguator; pub mod entry; pub mod expand; pub mod mut_visit; diff --git a/src/librustc_ast/mut_visit.rs b/src/librustc_ast/mut_visit.rs index dedc74eea9279..aa2968b3cbe44 100644 --- a/src/librustc_ast/mut_visit.rs +++ b/src/librustc_ast/mut_visit.rs @@ -202,7 +202,7 @@ pub trait MutVisitor: Sized { noop_visit_local(l, self); } - fn visit_mac(&mut self, _mac: &mut Mac) { + fn visit_mac(&mut self, _mac: &mut MacCall) { panic!("visit_mac disabled by default"); // N.B., see note about macros above. If you really want a visitor that // works on macros, use this definition in your trait impl: @@ -482,7 +482,7 @@ pub fn noop_visit_ty(ty: &mut P, vis: &mut T) { vis.visit_id(id); visit_vec(bounds, |bound| vis.visit_param_bound(bound)); } - TyKind::Mac(mac) => vis.visit_mac(mac), + TyKind::MacCall(mac) => vis.visit_mac(mac), } vis.visit_span(span); } @@ -584,14 +584,14 @@ pub fn noop_visit_attribute(attr: &mut Attribute, vis: &mut T) { vis.visit_span(span); } -pub fn noop_visit_mac(mac: &mut Mac, vis: &mut T) { - let Mac { path, args, prior_type_ascription: _ } = mac; +pub fn noop_visit_mac(mac: &mut MacCall, vis: &mut T) { + let MacCall { path, args, prior_type_ascription: _ } = mac; vis.visit_path(path); visit_mac_args(args, vis); } pub fn noop_visit_macro_def(macro_def: &mut MacroDef, vis: &mut T) { - let MacroDef { body, legacy: _ } = macro_def; + let MacroDef { body, macro_rules: _ } = macro_def; visit_mac_args(body, vis); } @@ -926,7 +926,7 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) { vis.visit_generics(generics); visit_bounds(bounds, vis); } - ItemKind::Mac(m) => vis.visit_mac(m), + ItemKind::MacCall(m) => vis.visit_mac(m), ItemKind::MacroDef(def) => vis.visit_macro_def(def), } } @@ -955,7 +955,7 @@ pub fn noop_flat_map_assoc_item( visit_bounds(bounds, visitor); visit_opt(ty, |ty| visitor.visit_ty(ty)); } - AssocItemKind::Macro(mac) => visitor.visit_mac(mac), + AssocItemKind::MacCall(mac) => visitor.visit_mac(mac), } visitor.visit_span(span); smallvec![item] @@ -1043,7 +1043,7 @@ pub fn noop_flat_map_foreign_item( visit_bounds(bounds, visitor); visit_opt(ty, |ty| visitor.visit_ty(ty)); } - ForeignItemKind::Macro(mac) => visitor.visit_mac(mac), + ForeignItemKind::MacCall(mac) => visitor.visit_mac(mac), } visitor.visit_span(span); smallvec![item] @@ -1082,7 +1082,7 @@ pub fn noop_visit_pat(pat: &mut P, vis: &mut T) { visit_vec(elems, |elem| vis.visit_pat(elem)) } PatKind::Paren(inner) => vis.visit_pat(inner), - PatKind::Mac(mac) => vis.visit_mac(mac), + PatKind::MacCall(mac) => vis.visit_mac(mac), } vis.visit_span(span); } @@ -1219,7 +1219,7 @@ pub fn noop_visit_expr(Expr { kind, id, span, attrs }: &mut Expr, } visit_vec(inputs, |(_c, expr)| vis.visit_expr(expr)); } - ExprKind::Mac(mac) => vis.visit_mac(mac), + ExprKind::MacCall(mac) => vis.visit_mac(mac), ExprKind::Struct(path, fields, expr) => { vis.visit_path(path); fields.flat_map_in_place(|field| vis.flat_map_field(field)); @@ -1275,11 +1275,11 @@ pub fn noop_flat_map_stmt_kind( StmtKind::Expr(expr) => vis.filter_map_expr(expr).into_iter().map(StmtKind::Expr).collect(), StmtKind::Semi(expr) => vis.filter_map_expr(expr).into_iter().map(StmtKind::Semi).collect(), StmtKind::Empty => smallvec![StmtKind::Empty], - StmtKind::Mac(mut mac) => { + StmtKind::MacCall(mut mac) => { let (mac_, _semi, attrs) = mac.deref_mut(); vis.visit_mac(mac_); visit_thin_attrs(attrs, vis); - smallvec![StmtKind::Mac(mac)] + smallvec![StmtKind::MacCall(mac)] } } } diff --git a/src/librustc_ast/node_id.rs b/src/librustc_ast/node_id.rs index 58d2334a7b148..cd562c48e9115 100644 --- a/src/librustc_ast/node_id.rs +++ b/src/librustc_ast/node_id.rs @@ -12,7 +12,7 @@ rustc_index::newtype_index! { rustc_data_structures::define_id_collections!(NodeMap, NodeSet, NodeId); /// `NodeId` used to represent the root of the crate. -pub const CRATE_NODE_ID: NodeId = NodeId::from_u32_const(0); +pub const CRATE_NODE_ID: NodeId = NodeId::from_u32(0); /// When parsing and doing expansions, we initially give all AST nodes this AST /// node value. Then later, in the renumber pass, we renumber them to have diff --git a/src/librustc_ast/token.rs b/src/librustc_ast/token.rs index 3fc6444168e24..be5d322ba1677 100644 --- a/src/librustc_ast/token.rs +++ b/src/librustc_ast/token.rs @@ -424,7 +424,7 @@ impl Token { NtExpr(..) | NtBlock(..) | NtLiteral(..) => true, _ => false, }, - _ => self.can_begin_literal_or_bool(), + _ => self.can_begin_literal_maybe_minus(), } } @@ -448,13 +448,22 @@ impl Token { /// Returns `true` if the token is any literal, a minus (which can prefix a literal, /// for example a '-42', or one of the boolean idents). /// - /// Keep this in sync with `Lit::from_token`. - pub fn can_begin_literal_or_bool(&self) -> bool { + /// In other words, would this token be a valid start of `parse_literal_maybe_minus`? + /// + /// Keep this in sync with and `Lit::from_token`, excluding unary negation. + pub fn can_begin_literal_maybe_minus(&self) -> bool { match self.uninterpolate().kind { Literal(..) | BinOp(Minus) => true, Ident(name, false) if name.is_bool_lit() => true, Interpolated(ref nt) => match &**nt { - NtExpr(e) | NtLiteral(e) => matches!(e.kind, ast::ExprKind::Lit(_)), + NtLiteral(_) => true, + NtExpr(e) => match &e.kind { + ast::ExprKind::Lit(_) => true, + ast::ExprKind::Unary(ast::UnOp::Neg, e) => { + matches!(&e.kind, ast::ExprKind::Lit(_)) + } + _ => false, + }, _ => false, }, _ => false, diff --git a/src/librustc_ast/util/literal.rs b/src/librustc_ast/util/literal.rs index d1757394f3a1d..1b17f343a6d67 100644 --- a/src/librustc_ast/util/literal.rs +++ b/src/librustc_ast/util/literal.rs @@ -189,7 +189,7 @@ impl Lit { /// Converts arbitrary token into an AST literal. /// - /// Keep this in sync with `Token::can_begin_literal_or_bool`. + /// Keep this in sync with `Token::can_begin_literal_or_bool` excluding unary negation. pub fn from_token(token: &Token) -> Result { let lit = match token.uninterpolate().kind { token::Ident(name, false) if name.is_bool_lit() => { diff --git a/src/librustc_ast/visit.rs b/src/librustc_ast/visit.rs index 1436c84b9c1f3..39028b7583c63 100644 --- a/src/librustc_ast/visit.rs +++ b/src/librustc_ast/visit.rs @@ -168,7 +168,7 @@ pub trait Visitor<'ast>: Sized { fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) { walk_lifetime(self, lifetime) } - fn visit_mac(&mut self, _mac: &'ast Mac) { + fn visit_mac(&mut self, _mac: &'ast MacCall) { panic!("visit_mac disabled by default"); // N.B., see note about macros above. // if you really want a visitor that @@ -350,7 +350,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { visitor.visit_generics(generics); walk_list!(visitor, visit_param_bound, bounds); } - ItemKind::Mac(ref mac) => visitor.visit_mac(mac), + ItemKind::MacCall(ref mac) => visitor.visit_mac(mac), ItemKind::MacroDef(ref ts) => visitor.visit_mac_def(ts, item.id), } walk_list!(visitor, visit_attribute, &item.attrs); @@ -418,7 +418,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { } TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression), TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {} - TyKind::Mac(ref mac) => visitor.visit_mac(mac), + TyKind::MacCall(ref mac) => visitor.visit_mac(mac), TyKind::Never | TyKind::CVarArgs => {} } } @@ -521,7 +521,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { PatKind::Tuple(ref elems) | PatKind::Slice(ref elems) | PatKind::Or(ref elems) => { walk_list!(visitor, visit_pat, elems); } - PatKind::Mac(ref mac) => visitor.visit_mac(mac), + PatKind::MacCall(ref mac) => visitor.visit_mac(mac), } } @@ -545,7 +545,7 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignI walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_ty, ty); } - ForeignItemKind::Macro(mac) => { + ForeignItemKind::MacCall(mac) => { visitor.visit_mac(mac); } } @@ -650,7 +650,7 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem, walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_ty, ty); } - AssocItemKind::Macro(mac) => { + AssocItemKind::MacCall(mac) => { visitor.visit_mac(mac); } } @@ -679,7 +679,7 @@ pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) { StmtKind::Item(ref item) => visitor.visit_item(item), StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => visitor.visit_expr(expr), StmtKind::Empty => {} - StmtKind::Mac(ref mac) => { + StmtKind::MacCall(ref mac) => { let (ref mac, _, ref attrs) = **mac; visitor.visit_mac(mac); for attr in attrs.iter() { @@ -689,7 +689,7 @@ pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) { } } -pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a Mac) { +pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a MacCall) { visitor.visit_path(&mac.path, DUMMY_NODE_ID); } @@ -811,7 +811,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { ExprKind::Ret(ref optional_expression) => { walk_list!(visitor, visit_expr, optional_expression); } - ExprKind::Mac(ref mac) => visitor.visit_mac(mac), + ExprKind::MacCall(ref mac) => visitor.visit_mac(mac), ExprKind::Paren(ref subexpression) => visitor.visit_expr(subexpression), ExprKind::InlineAsm(ref ia) => { for &(_, ref input) in &ia.inputs { diff --git a/src/librustc_ast_lowering/Cargo.toml b/src/librustc_ast_lowering/Cargo.toml index 23dc80facae1d..b477b75db5adc 100644 --- a/src/librustc_ast_lowering/Cargo.toml +++ b/src/librustc_ast_lowering/Cargo.toml @@ -10,8 +10,8 @@ path = "lib.rs" doctest = false [dependencies] +arena = { path = "../libarena" } log = { version = "0.4", features = ["release_max_level_info", "std"] } -rustc = { path = "../librustc" } rustc_ast_pretty = { path = "../librustc_ast_pretty" } rustc_hir = { path = "../librustc_hir" } rustc_target = { path = "../librustc_target" } diff --git a/src/librustc_ast_lowering/expr.rs b/src/librustc_ast_lowering/expr.rs index 7038387caa9bf..239dec9e9746b 100644 --- a/src/librustc_ast_lowering/expr.rs +++ b/src/librustc_ast_lowering/expr.rs @@ -1,6 +1,5 @@ use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs}; -use rustc::bug; use rustc_ast::ast::*; use rustc_ast::attr; use rustc_ast::ptr::P as AstP; @@ -198,7 +197,7 @@ impl<'hir> LoweringContext<'_, 'hir> { return self.lower_expr_for(e, pat, head, body, opt_label); } ExprKind::Try(ref sub_expr) => self.lower_expr_try(e.span, sub_expr), - ExprKind::Mac(_) => panic!("Shouldn't exist here"), + ExprKind::MacCall(_) => panic!("Shouldn't exist here"), }; hir::Expr { @@ -470,6 +469,15 @@ impl<'hir> LoweringContext<'_, 'hir> { } } + /// Lower an `async` construct to a generator that is then wrapped so it implements `Future`. + /// + /// This results in: + /// + /// ```text + /// std::future::from_generator(static move? |_task_context| -> { + /// + /// }) + /// ``` pub(super) fn make_async_expr( &mut self, capture_clause: CaptureBy, @@ -480,17 +488,42 @@ impl<'hir> LoweringContext<'_, 'hir> { body: impl FnOnce(&mut Self) -> hir::Expr<'hir>, ) -> hir::ExprKind<'hir> { let output = match ret_ty { - Some(ty) => FnRetTy::Ty(ty), - None => FnRetTy::Default(span), + Some(ty) => hir::FnRetTy::Return(self.lower_ty(&ty, ImplTraitContext::disallowed())), + None => hir::FnRetTy::DefaultReturn(span), }; - let ast_decl = FnDecl { inputs: vec![], output }; - let decl = self.lower_fn_decl(&ast_decl, None, /* impl trait allowed */ false, None); - let body_id = self.lower_fn_body(&ast_decl, |this| { + + // Resume argument type. We let the compiler infer this to simplify the lowering. It is + // fully constrained by `future::from_generator`. + let input_ty = hir::Ty { hir_id: self.next_id(), kind: hir::TyKind::Infer, span }; + + // The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`. + let decl = self.arena.alloc(hir::FnDecl { + inputs: arena_vec![self; input_ty], + output, + c_variadic: false, + implicit_self: hir::ImplicitSelfKind::None, + }); + + // Lower the argument pattern/ident. The ident is used again in the `.await` lowering. + let (pat, task_context_hid) = self.pat_ident_binding_mode( + span, + Ident::with_dummy_span(sym::_task_context), + hir::BindingAnnotation::Mutable, + ); + let param = hir::Param { attrs: &[], hir_id: self.next_id(), pat, span }; + let params = arena_vec![self; param]; + + let body_id = self.lower_body(move |this| { this.generator_kind = Some(hir::GeneratorKind::Async(async_gen_kind)); - body(this) + + let old_ctx = this.task_context; + this.task_context = Some(task_context_hid); + let res = body(this); + this.task_context = old_ctx; + (params, res) }); - // `static || -> { body }`: + // `static |_task_context| -> { body }`: let generator_kind = hir::ExprKind::Closure( capture_clause, decl, @@ -523,13 +556,14 @@ impl<'hir> LoweringContext<'_, 'hir> { /// ```rust /// match { /// mut pinned => loop { - /// match ::std::future::poll_with_tls_context(unsafe { - /// <::std::pin::Pin>::new_unchecked(&mut pinned) - /// }) { + /// match unsafe { ::std::future::poll_with_context( + /// <::std::pin::Pin>::new_unchecked(&mut pinned), + /// task_context, + /// ) } { /// ::std::task::Poll::Ready(result) => break result, /// ::std::task::Poll::Pending => {} /// } - /// yield (); + /// task_context = yield (); /// } /// } /// ``` @@ -561,12 +595,23 @@ impl<'hir> LoweringContext<'_, 'hir> { let (pinned_pat, pinned_pat_hid) = self.pat_ident_binding_mode(span, pinned_ident, hir::BindingAnnotation::Mutable); - // ::std::future::poll_with_tls_context(unsafe { - // ::std::pin::Pin::new_unchecked(&mut pinned) - // })` + let task_context_ident = Ident::with_dummy_span(sym::_task_context); + + // unsafe { + // ::std::future::poll_with_context( + // ::std::pin::Pin::new_unchecked(&mut pinned), + // task_context, + // ) + // } let poll_expr = { let pinned = self.expr_ident(span, pinned_ident, pinned_pat_hid); let ref_mut_pinned = self.expr_mut_addr_of(span, pinned); + let task_context = if let Some(task_context_hid) = self.task_context { + self.expr_ident_mut(span, task_context_ident, task_context_hid) + } else { + // Use of `await` outside of an async context, we cannot use `task_context` here. + self.expr_err(span) + }; let pin_ty_id = self.next_id(); let new_unchecked_expr_kind = self.expr_call_std_assoc_fn( pin_ty_id, @@ -575,14 +620,13 @@ impl<'hir> LoweringContext<'_, 'hir> { "new_unchecked", arena_vec![self; ref_mut_pinned], ); - let new_unchecked = - self.arena.alloc(self.expr(span, new_unchecked_expr_kind, ThinVec::new())); - let unsafe_expr = self.expr_unsafe(new_unchecked); - self.expr_call_std_path( + let new_unchecked = self.expr(span, new_unchecked_expr_kind, ThinVec::new()); + let call = self.expr_call_std_path( gen_future_span, - &[sym::future, sym::poll_with_tls_context], - arena_vec![self; unsafe_expr], - ) + &[sym::future, sym::poll_with_context], + arena_vec![self; new_unchecked, task_context], + ); + self.arena.alloc(self.expr_unsafe(call)) }; // `::std::task::Poll::Ready(result) => break result` @@ -622,6 +666,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.stmt_expr(span, match_expr) }; + // task_context = yield (); let yield_stmt = { let unit = self.expr_unit(span); let yield_expr = self.expr( @@ -629,7 +674,18 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ExprKind::Yield(unit, hir::YieldSource::Await), ThinVec::new(), ); - self.stmt_expr(span, yield_expr) + let yield_expr = self.arena.alloc(yield_expr); + + if let Some(task_context_hid) = self.task_context { + let lhs = self.expr_ident(span, task_context_ident, task_context_hid); + let assign = + self.expr(span, hir::ExprKind::Assign(lhs, yield_expr, span), AttrVec::new()); + self.stmt_expr(span, assign) + } else { + // Use of `await` outside of an async context. Return `yield_expr` so that we can + // proceed with type checking. + self.stmt(span, hir::StmtKind::Semi(yield_expr)) + } }; let loop_block = self.block_all(span, arena_vec![self; inner_match_stmt, yield_stmt], None); @@ -700,7 +756,7 @@ impl<'hir> LoweringContext<'_, 'hir> { Some(movability) } Some(hir::GeneratorKind::Async(_)) => { - bug!("non-`async` closure body turned `async` during lowering"); + panic!("non-`async` closure body turned `async` during lowering"); } None => { if movability == Movability::Static { diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs index fcc859e3b6d19..740f62b41a584 100644 --- a/src/librustc_ast_lowering/item.rs +++ b/src/librustc_ast_lowering/item.rs @@ -1,16 +1,16 @@ use super::{AnonymousLifetimeMode, LoweringContext, ParamMode}; use super::{ImplTraitContext, ImplTraitPosition, ImplTraitTypeIdVisitor}; +use crate::Arena; -use rustc::arena::Arena; -use rustc::bug; use rustc_ast::ast::*; use rustc_ast::attr; use rustc_ast::node_id::NodeMap; +use rustc_ast::ptr::P; use rustc_ast::visit::{self, AssocCtxt, Visitor}; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::LocalDefId; use rustc_span::source_map::{respan, DesugaringKind}; use rustc_span::symbol::{kw, sym}; use rustc_span::Span; @@ -114,7 +114,7 @@ impl<'hir> LoweringContext<'_, 'hir> { _ => &[], }; let lt_def_names = parent_generics.iter().filter_map(|param| match param.kind { - hir::GenericParamKind::Lifetime { .. } => Some(param.name.modern()), + hir::GenericParamKind::Lifetime { .. } => Some(param.name.normalize_to_macros_2_0()), _ => None, }); self.in_scope_lifetimes.extend(lt_def_names); @@ -219,18 +219,17 @@ impl<'hir> LoweringContext<'_, 'hir> { let mut vis = self.lower_visibility(&i.vis, None); let attrs = self.lower_attrs(&i.attrs); - if let ItemKind::MacroDef(ref def) = i.kind { - if !def.legacy || attr::contains_name(&i.attrs, sym::macro_export) { - let body = self.lower_token_stream(def.body.inner_tokens()); + if let ItemKind::MacroDef(MacroDef { ref body, macro_rules }) = i.kind { + if !macro_rules || attr::contains_name(&i.attrs, sym::macro_export) { let hir_id = self.lower_node_id(i.id); + let body = P(self.lower_mac_args(body)); self.exported_macros.push(hir::MacroDef { - name: ident.name, + ident, vis, attrs, hir_id, span: i.span, - body, - legacy: def.legacy, + ast: MacroDef { body, macro_rules }, }); } else { self.non_exported_macro_attrs.extend(attrs.iter().cloned()); @@ -269,7 +268,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ItemKind::Const(ty, body_id) } ItemKind::Fn(_, FnSig { ref decl, header }, ref generics, ref body) => { - let fn_def_id = self.resolver.definitions().local_def_id(id); + let fn_def_id = self.resolver.definitions().local_def_id(id).expect_local(); self.with_new_scopes(|this| { this.current_item = Some(ident.span); @@ -287,7 +286,12 @@ impl<'hir> LoweringContext<'_, 'hir> { AnonymousLifetimeMode::PassThrough, |this, idty| { let ret_id = asyncness.opt_return_id(); - this.lower_fn_decl(&decl, Some((fn_def_id, idty)), true, ret_id) + this.lower_fn_decl( + &decl, + Some((fn_def_id.to_def_id(), idty)), + true, + ret_id, + ) }, ); let sig = hir::FnSig { decl, header: this.lower_fn_header(header) }; @@ -351,7 +355,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self_ty: ref ty, items: ref impl_items, } => { - let def_id = self.resolver.definitions().local_def_id(id); + let def_id = self.resolver.definitions().local_def_id(id).expect_local(); // Lower the "impl header" first. This ordering is important // for in-band lifetimes! Consider `'a` here: @@ -398,10 +402,15 @@ impl<'hir> LoweringContext<'_, 'hir> { ) }); + // `defaultness.has_value()` is never called for an `impl`, always `true` in order + // to not cause an assertion failure inside the `lower_defaultness` function. + let has_val = true; + let (defaultness, defaultness_span) = self.lower_defaultness(defaultness, has_val); hir::ItemKind::Impl { unsafety: self.lower_unsafety(unsafety), polarity, - defaultness: self.lower_defaultness(defaultness, true /* [1] */), + defaultness, + defaultness_span, constness: self.lower_constness(constness), generics, of_trait: trait_ref, @@ -426,13 +435,10 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_generics(generics, ImplTraitContext::disallowed()), self.lower_param_bounds(bounds, ImplTraitContext::disallowed()), ), - ItemKind::MacroDef(..) | ItemKind::Mac(..) => { - bug!("`TyMac` should have been expanded by now") + ItemKind::MacroDef(..) | ItemKind::MacCall(..) => { + panic!("`TyMac` should have been expanded by now") } } - - // [1] `defaultness.has_value()` is never called for an `impl`, always `true` in order to - // not cause an assertion failure inside the `lower_defaultness` function. } fn lower_const_item( @@ -648,7 +654,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem<'hir> { - let def_id = self.resolver.definitions().local_def_id(i.id); + let def_id = self.resolver.definitions().local_def_id(i.id).expect_local(); hir::ForeignItem { hir_id: self.lower_node_id(i.id), ident: i.ident, @@ -676,7 +682,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ForeignItemKind::Static(ty, m) } ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, - ForeignItemKind::Macro(_) => panic!("macro shouldn't exist here"), + ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"), }, vis: self.lower_visibility(&i.vis, None), span: i.span, @@ -749,7 +755,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_trait_item(&mut self, i: &AssocItem) -> hir::TraitItem<'hir> { - let trait_item_def_id = self.resolver.definitions().local_def_id(i.id); + let trait_item_def_id = self.resolver.definitions().local_def_id(i.id).expect_local(); let (generics, kind) = match i.kind { AssocItemKind::Const(_, ref ty, ref default) => { @@ -761,13 +767,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let names = self.lower_fn_params_to_names(&sig.decl); let (generics, sig) = self.lower_method_sig(generics, sig, trait_item_def_id, false, None); - (generics, hir::TraitItemKind::Fn(sig, hir::TraitMethod::Required(names))) + (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names))) } AssocItemKind::Fn(_, ref sig, ref generics, Some(ref body)) => { let body_id = self.lower_fn_body_block(i.span, &sig.decl, Some(body)); let (generics, sig) = self.lower_method_sig(generics, sig, trait_item_def_id, false, None); - (generics, hir::TraitItemKind::Fn(sig, hir::TraitMethod::Provided(body_id))) + (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id))) } AssocItemKind::TyAlias(_, ref generics, ref bounds, ref default) => { let ty = default.as_ref().map(|x| self.lower_ty(x, ImplTraitContext::disallowed())); @@ -779,7 +785,7 @@ impl<'hir> LoweringContext<'_, 'hir> { (generics, kind) } - AssocItemKind::Macro(..) => bug!("macro item shouldn't exist at this point"), + AssocItemKind::MacCall(..) => panic!("macro item shouldn't exist at this point"), }; hir::TraitItem { @@ -801,7 +807,7 @@ impl<'hir> LoweringContext<'_, 'hir> { AssocItemKind::Fn(_, sig, _, default) => { (hir::AssocItemKind::Method { has_self: sig.decl.has_self() }, default.is_some()) } - AssocItemKind::Macro(..) => unimplemented!(), + AssocItemKind::MacCall(..) => unimplemented!(), }; let id = hir::TraitItemId { hir_id: self.lower_node_id(i.id) }; let defaultness = hir::Defaultness::Default { has_value: has_default }; @@ -809,12 +815,12 @@ impl<'hir> LoweringContext<'_, 'hir> { } /// Construct `ExprKind::Err` for the given `span`. - fn expr_err(&mut self, span: Span) -> hir::Expr<'hir> { + crate fn expr_err(&mut self, span: Span) -> hir::Expr<'hir> { self.expr(span, hir::ExprKind::Err, AttrVec::new()) } fn lower_impl_item(&mut self, i: &AssocItem) -> hir::ImplItem<'hir> { - let impl_item_def_id = self.resolver.definitions().local_def_id(i.id); + let impl_item_def_id = self.resolver.definitions().local_def_id(i.id).expect_local(); let (generics, kind) = match &i.kind { AssocItemKind::Const(_, ty, expr) => { @@ -838,7 +844,7 @@ impl<'hir> LoweringContext<'_, 'hir> { asyncness.opt_return_id(), ); - (generics, hir::ImplItemKind::Method(sig, body_id)) + (generics, hir::ImplItemKind::Fn(sig, body_id)) } AssocItemKind::TyAlias(_, generics, _, ty) => { let generics = self.lower_generics(generics, ImplTraitContext::disallowed()); @@ -860,30 +866,34 @@ impl<'hir> LoweringContext<'_, 'hir> { }; (generics, kind) } - AssocItemKind::Macro(..) => bug!("`TyMac` should have been expanded by now"), + AssocItemKind::MacCall(..) => panic!("`TyMac` should have been expanded by now"), }; + // Since `default impl` is not yet implemented, this is always true in impls. + let has_value = true; + let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); hir::ImplItem { hir_id: self.lower_node_id(i.id), ident: i.ident, attrs: self.lower_attrs(&i.attrs), generics, vis: self.lower_visibility(&i.vis, None), - defaultness: self.lower_defaultness(i.kind.defaultness(), true /* [1] */), + defaultness, kind, span: i.span, } - - // [1] since `default impl` is not yet implemented, this is always true in impls } fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef<'hir> { + // Since `default impl` is not yet implemented, this is always true in impls. + let has_value = true; + let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); hir::ImplItemRef { id: hir::ImplItemId { hir_id: self.lower_node_id(i.id) }, ident: i.ident, span: i.span, vis: self.lower_visibility(&i.vis, Some(i.id)), - defaultness: self.lower_defaultness(i.kind.defaultness(), true /* [1] */), + defaultness, kind: match &i.kind { AssocItemKind::Const(..) => hir::AssocItemKind::Const, AssocItemKind::TyAlias(.., ty) => { @@ -895,11 +905,9 @@ impl<'hir> LoweringContext<'_, 'hir> { AssocItemKind::Fn(_, sig, ..) => { hir::AssocItemKind::Method { has_self: sig.decl.has_self() } } - AssocItemKind::Macro(..) => unimplemented!(), + AssocItemKind::MacCall(..) => unimplemented!(), }, } - - // [1] since `default impl` is not yet implemented, this is always true in impls } /// If an `explicit_owner` is given, this method allocates the `HirId` in @@ -934,12 +942,16 @@ impl<'hir> LoweringContext<'_, 'hir> { respan(v.span, node) } - fn lower_defaultness(&self, d: Defaultness, has_value: bool) -> hir::Defaultness { + fn lower_defaultness( + &self, + d: Defaultness, + has_value: bool, + ) -> (hir::Defaultness, Option) { match d { - Defaultness::Default(_) => hir::Defaultness::Default { has_value }, + Defaultness::Default(sp) => (hir::Defaultness::Default { has_value }, Some(sp)), Defaultness::Final => { assert!(has_value); - hir::Defaultness::Final + (hir::Defaultness::Final, None) } } } @@ -955,7 +967,7 @@ impl<'hir> LoweringContext<'_, 'hir> { id } - fn lower_body( + pub(super) fn lower_body( &mut self, f: impl FnOnce(&mut Self) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>), ) -> hir::BodyId { @@ -1211,7 +1223,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, generics: &Generics, sig: &FnSig, - fn_def_id: DefId, + fn_def_id: LocalDefId, impl_trait_return_allow: bool, is_async: Option, ) -> (hir::Generics<'hir>, hir::FnSig<'hir>) { @@ -1223,7 +1235,7 @@ impl<'hir> LoweringContext<'_, 'hir> { |this, idty| { this.lower_fn_decl( &sig.decl, - Some((fn_def_id, idty)), + Some((fn_def_id.to_def_id(), idty)), impl_trait_return_allow, is_async, ) diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index dd9526ccee41a..68cb1f8585fc7 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -32,13 +32,10 @@ #![feature(array_value_iter)] #![feature(crate_visibility_modifier)] +#![feature(marker_trait_attr)] +#![feature(specialization)] #![recursion_limit = "256"] -use rustc::arena::Arena; -use rustc::dep_graph::DepGraph; -use rustc::hir::map::definitions::{DefKey, DefPathData, Definitions}; -use rustc::hir::map::Map; -use rustc::{bug, span_bug}; use rustc_ast::ast; use rustc_ast::ast::*; use rustc_ast::attr; @@ -54,7 +51,8 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res}; -use rustc_hir::def_id::{DefId, DefIdMap, DefIndex, CRATE_DEF_INDEX}; +use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX}; +use rustc_hir::definitions::{DefKey, DefPathData, Definitions}; use rustc_hir::intravisit; use rustc_hir::{ConstArg, GenericArg, ParamName}; use rustc_index::vec::IndexVec; @@ -86,6 +84,8 @@ mod path; const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF; +rustc_hir::arena_types!(::arena::declare_arena, [], 'tcx); + struct LoweringContext<'a, 'hir: 'a> { crate_root: Option, @@ -117,6 +117,10 @@ struct LoweringContext<'a, 'hir: 'a> { generator_kind: Option, + /// When inside an `async` context, this is the `HirId` of the + /// `task_context` local bound to the resume argument of the generator. + task_context: Option, + /// Used to get the current `fn`'s def span to point to when using `await` /// outside of an `async fn`. current_item: Option, @@ -153,7 +157,7 @@ struct LoweringContext<'a, 'hir: 'a> { /// against this list to see if it is already in-scope, or if a definition /// needs to be created for it. /// - /// We always store a `modern()` version of the param-name in this + /// We always store a `normalize_to_macros_2_0()` version of the param-name in this /// vector. in_scope_lifetimes: Vec, @@ -161,7 +165,7 @@ struct LoweringContext<'a, 'hir: 'a> { type_def_lifetime_params: DefIdMap, - current_hir_id_owner: Vec<(DefIndex, u32)>, + current_hir_id_owner: Vec<(LocalDefId, u32)>, item_local_id_counters: NodeMap, node_id_to_hir_id: IndexVec, @@ -256,17 +260,11 @@ impl<'a> ImplTraitContext<'_, 'a> { pub fn lower_crate<'a, 'hir>( sess: &'a Session, - dep_graph: &'a DepGraph, krate: &'a Crate, resolver: &'a mut dyn Resolver, nt_to_tokenstream: NtToTokenstream, arena: &'hir Arena<'hir>, ) -> hir::Crate<'hir> { - // We're constructing the HIR here; we don't care what we will - // read, since we haven't even constructed the *input* to - // incr. comp. yet. - dep_graph.assert_ignored(); - let _prof_timer = sess.prof.verbose_generic_activity("hir_lowering"); LoweringContext { @@ -291,10 +289,11 @@ pub fn lower_crate<'a, 'hir>( anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough, type_def_lifetime_params: Default::default(), current_module: hir::CRATE_HIR_ID, - current_hir_id_owner: vec![(CRATE_DEF_INDEX, 0)], + current_hir_id_owner: vec![(LocalDefId { local_def_index: CRATE_DEF_INDEX }, 0)], item_local_id_counters: Default::default(), node_id_to_hir_id: IndexVec::new(), generator_kind: None, + task_context: None, current_item: None, lifetimes_to_define: Vec::new(), is_collecting_in_band_lifetimes: false, @@ -408,7 +407,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } impl MiscCollector<'_, '_, '_> { - fn allocate_use_tree_hir_id_counters(&mut self, tree: &UseTree, owner: DefIndex) { + fn allocate_use_tree_hir_id_counters(&mut self, tree: &UseTree, owner: LocalDefId) { match tree.kind { UseTreeKind::Simple(_, id1, id2) => { for &id in &[id1, id2] { @@ -464,7 +463,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { | ItemKind::Enum(_, ref generics) | ItemKind::TyAlias(_, ref generics, ..) | ItemKind::Trait(_, _, ref generics, ..) => { - let def_id = self.lctx.resolver.definitions().local_def_id(item.id); + let def_id = + self.lctx.resolver.definitions().local_def_id(item.id).expect_local(); let count = generics .params .iter() @@ -473,7 +473,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { _ => false, }) .count(); - self.lctx.type_def_lifetime_params.insert(def_id, count); + self.lctx.type_def_lifetime_params.insert(def_id.to_def_id(), count); } ItemKind::Use(ref use_tree) => { self.allocate_use_tree_hir_id_counters(use_tree, hir_id.owner); @@ -535,9 +535,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.resolver.definitions().init_node_id_to_hir_id_mapping(self.node_id_to_hir_id); hir::Crate { - module, - attrs, - span: c.span, + item: hir::CrateItem { module, attrs, span: c.span }, exported_macros: self.arena.alloc_from_iter(self.exported_macros), non_exported_macro_attrs: self.arena.alloc_from_iter(self.non_exported_macro_attrs), items: self.items, @@ -601,12 +599,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .item_local_id_counters .insert(owner, HIR_ID_COUNTER_LOCKED) .unwrap_or_else(|| panic!("no `item_local_id_counters` entry for {:?}", owner)); - let def_index = self.resolver.definitions().opt_def_index(owner).unwrap(); - self.current_hir_id_owner.push((def_index, counter)); + let def_id = self.resolver.definitions().local_def_id(owner).expect_local(); + self.current_hir_id_owner.push((def_id, counter)); let ret = f(self); - let (new_def_index, new_counter) = self.current_hir_id_owner.pop().unwrap(); + let (new_def_id, new_counter) = self.current_hir_id_owner.pop().unwrap(); - debug_assert!(def_index == new_def_index); + debug_assert!(def_id == new_def_id); debug_assert!(new_counter >= counter); let prev = self.item_local_id_counters.insert(owner, new_counter).unwrap(); @@ -622,11 +620,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// properly. Calling the method twice with the same `NodeId` is fine though. fn lower_node_id(&mut self, ast_node_id: NodeId) -> hir::HirId { self.lower_node_id_generic(ast_node_id, |this| { - let &mut (def_index, ref mut local_id_counter) = + let &mut (owner, ref mut local_id_counter) = this.current_hir_id_owner.last_mut().unwrap(); let local_id = *local_id_counter; *local_id_counter += 1; - hir::HirId { owner: def_index, local_id: hir::ItemLocalId::from_u32(local_id) } + hir::HirId { owner, local_id: hir::ItemLocalId::from_u32(local_id) } }) } @@ -644,12 +642,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug_assert!(local_id != HIR_ID_COUNTER_LOCKED); *local_id_counter += 1; - let def_index = this.resolver.definitions().opt_def_index(owner).expect( + let owner = this.resolver.definitions().opt_local_def_id(owner).expect( "you forgot to call `create_def_with_parent` or are lowering node-IDs \ - that do not belong to the current owner", + that do not belong to the current owner", ); - hir::HirId { owner: def_index, local_id: hir::ItemLocalId::from_u32(local_id) } + hir::HirId { owner, local_id: hir::ItemLocalId::from_u32(local_id) } }) } @@ -669,7 +667,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn expect_full_res(&mut self, id: NodeId) -> Res { self.resolver.get_partial_res(id).map_or(Res::Err, |pr| { if pr.unresolved_segments() != 0 { - bug!("path not fully resolved: {:?}", pr); + panic!("path not fully resolved: {:?}", pr); } pr.base_res() }) @@ -727,7 +725,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// parameter while `f` is running (and restored afterwards). fn collect_in_band_defs( &mut self, - parent_id: DefId, + parent_def_id: LocalDefId, anonymous_lifetime_mode: AnonymousLifetimeMode, f: impl FnOnce(&mut Self) -> (Vec>, T), ) -> (Vec>, T) { @@ -747,7 +745,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let params = lifetimes_to_define .into_iter() - .map(|(span, hir_name)| self.lifetime_to_generic_param(span, hir_name, parent_id.index)) + .map(|(span, hir_name)| self.lifetime_to_generic_param(span, hir_name, parent_def_id)) .chain(in_band_ty_params.into_iter()) .collect(); @@ -759,7 +757,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, span: Span, hir_name: ParamName, - parent_index: DefIndex, + parent_def_id: LocalDefId, ) -> hir::GenericParam<'hir> { let node_id = self.resolver.next_node_id(); @@ -774,7 +772,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Add a definition for the in-band lifetime def. self.resolver.definitions().create_def_with_parent( - parent_index, + parent_def_id, node_id, DefPathData::LifetimeNs(str_name), ExpnId::root(), @@ -805,14 +803,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { return; } - if self.in_scope_lifetimes.contains(&ParamName::Plain(ident.modern())) { + if self.in_scope_lifetimes.contains(&ParamName::Plain(ident.normalize_to_macros_2_0())) { return; } let hir_name = ParamName::Plain(ident); - if self.lifetimes_to_define.iter().any(|(_, lt_name)| lt_name.modern() == hir_name.modern()) - { + if self.lifetimes_to_define.iter().any(|(_, lt_name)| { + lt_name.normalize_to_macros_2_0() == hir_name.normalize_to_macros_2_0() + }) { return; } @@ -840,7 +839,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> T { let old_len = self.in_scope_lifetimes.len(); let lt_def_names = params.iter().filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => Some(ParamName::Plain(param.ident.modern())), + GenericParamKind::Lifetime { .. } => { + Some(ParamName::Plain(param.ident.normalize_to_macros_2_0())) + } _ => None, }); self.in_scope_lifetimes.extend(lt_def_names); @@ -860,13 +861,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn add_in_band_defs( &mut self, generics: &Generics, - parent_id: DefId, + parent_def_id: LocalDefId, anonymous_lifetime_mode: AnonymousLifetimeMode, f: impl FnOnce(&mut Self, &mut Vec>) -> T, ) -> (hir::Generics<'hir>, T) { let (in_band_defs, (mut lowered_generics, res)) = self.with_in_scope_lifetime_defs(&generics.params, |this| { - this.collect_in_band_defs(parent_id, anonymous_lifetime_mode, |this| { + this.collect_in_band_defs(parent_def_id, anonymous_lifetime_mode, |this| { let mut params = Vec::new(); // Note: it is necessary to lower generics *before* calling `f`. // When lowering `async fn`, there's a final step when lowering @@ -1048,9 +1049,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // constructing the HIR for `impl bounds...` and then lowering that. let impl_trait_node_id = self.resolver.next_node_id(); - let parent_def_index = self.current_hir_id_owner.last().unwrap().0; + let parent_def_id = self.current_hir_id_owner.last().unwrap().0; self.resolver.definitions().create_def_with_parent( - parent_def_index, + parent_def_id, impl_trait_node_id, DefPathData::ImplTrait, ExpnId::root(), @@ -1111,12 +1112,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Construct a AnonConst where the expr is the "ty"'s path. - let parent_def_index = self.current_hir_id_owner.last().unwrap().0; + let parent_def_id = self.current_hir_id_owner.last().unwrap().0; let node_id = self.resolver.next_node_id(); // Add a definition for the in-band const def. self.resolver.definitions().create_def_with_parent( - parent_def_index, + parent_def_id, node_id, DefPathData::AnonConst, ExpnId::root(), @@ -1278,8 +1279,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } ImplTraitContext::Universal(in_band_ty_params) => { // Add a definition for the in-band `Param`. - let def_index = - self.resolver.definitions().opt_def_index(def_node_id).unwrap(); + let def_id = + self.resolver.definitions().local_def_id(def_node_id).expect_local(); let hir_bounds = self.lower_param_bounds( bounds, @@ -1304,7 +1305,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { None, self.arena.alloc(hir::Path { span, - res: Res::Def(DefKind::TyParam, DefId::local(def_index)), + res: Res::Def(DefKind::TyParam, def_id.to_def_id()), segments: arena_vec![self; hir::PathSegment::from_ident(ident)], }), )) @@ -1334,7 +1335,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } } - TyKind::Mac(_) => bug!("`TyKind::Mac` should have been expanded by now"), + TyKind::MacCall(_) => panic!("`TyKind::MacCall` should have been expanded by now"), TyKind::CVarArgs => { self.sess.delay_span_bug( t.span, @@ -1367,18 +1368,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // frequently opened issues show. let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None); - let opaque_ty_def_index = - self.resolver.definitions().opt_def_index(opaque_ty_node_id).unwrap(); + let opaque_ty_def_id = + self.resolver.definitions().local_def_id(opaque_ty_node_id).expect_local(); self.allocate_hir_id_counter(opaque_ty_node_id); let hir_bounds = self.with_hir_id_owner(opaque_ty_node_id, lower_bounds); - let (lifetimes, lifetime_defs) = self.lifetimes_from_impl_trait_bounds( - opaque_ty_node_id, - opaque_ty_def_index, - &hir_bounds, - ); + let (lifetimes, lifetime_defs) = + self.lifetimes_from_impl_trait_bounds(opaque_ty_node_id, opaque_ty_def_id, &hir_bounds); debug!("lower_opaque_impl_trait: lifetimes={:#?}", lifetimes,); @@ -1396,7 +1394,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { origin, }; - trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_index); + trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_id); let opaque_ty_id = lctx.generate_opaque_type(opaque_ty_node_id, opaque_ty_item, span, opaque_ty_span); @@ -1437,14 +1435,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lifetimes_from_impl_trait_bounds( &mut self, opaque_ty_id: NodeId, - parent_index: DefIndex, + parent_def_id: LocalDefId, bounds: hir::GenericBounds<'hir>, ) -> (&'hir [hir::GenericArg<'hir>], &'hir [hir::GenericParam<'hir>]) { debug!( "lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \ - parent_index={:?}, \ + parent_def_id={:?}, \ bounds={:#?})", - opaque_ty_id, parent_index, bounds, + opaque_ty_id, parent_def_id, bounds, ); // This visitor walks over `impl Trait` bounds and creates defs for all lifetimes that @@ -1452,7 +1450,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`. struct ImplTraitLifetimeCollector<'r, 'a, 'hir> { context: &'r mut LoweringContext<'a, 'hir>, - parent: DefIndex, + parent: LocalDefId, opaque_ty_id: NodeId, collect_elided_lifetimes: bool, currently_bound_lifetimes: Vec, @@ -1462,9 +1460,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } impl<'r, 'a, 'v, 'hir> intravisit::Visitor<'v> for ImplTraitLifetimeCollector<'r, 'a, 'hir> { - type Map = Map<'v>; + type Map = intravisit::ErasedMap<'v>; - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { intravisit::NestedVisitorMap::None } @@ -1572,7 +1570,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::LifetimeName::Param(param_name) => { (param_name, hir::LifetimeParamKind::Explicit) } - _ => bug!("expected `LifetimeName::Param` or `ParamName::Plain`"), + _ => panic!("expected `LifetimeName::Param` or `ParamName::Plain`"), }; self.output_lifetime_params.push(hir::GenericParam { @@ -1590,7 +1588,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut lifetime_collector = ImplTraitLifetimeCollector { context: self, - parent: parent_index, + parent: parent_def_id, opaque_ty_id, collect_elided_lifetimes: true, currently_bound_lifetimes: Vec::new(), @@ -1620,12 +1618,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { visitor.visit_ty(ty); } } - let parent_def_id = DefId::local(self.current_hir_id_owner.last().unwrap().0); + let parent_def_id = self.current_hir_id_owner.last().unwrap().0; let ty = l.ty.as_ref().map(|t| { self.lower_ty( t, if self.sess.features_untracked().impl_trait_in_bindings { - ImplTraitContext::OpaqueTy(Some(parent_def_id), hir::OpaqueTyOrigin::Misc) + ImplTraitContext::OpaqueTy( + Some(parent_def_id.to_def_id()), + hir::OpaqueTyOrigin::Misc, + ) } else { ImplTraitContext::Disallowed(ImplTraitPosition::Binding) }, @@ -1797,8 +1798,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, span, None); - let opaque_ty_def_index = - self.resolver.definitions().opt_def_index(opaque_ty_node_id).unwrap(); + let opaque_ty_def_id = + self.resolver.definitions().local_def_id(opaque_ty_node_id).expect_local(); self.allocate_hir_id_counter(opaque_ty_node_id); @@ -1886,7 +1887,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let generic_params = this.arena.alloc_from_iter(lifetime_params.iter().map(|(span, hir_name)| { - this.lifetime_to_generic_param(*span, *hir_name, opaque_ty_def_index) + this.lifetime_to_generic_param(*span, *hir_name, opaque_ty_def_id) })); let opaque_ty_item = hir::OpaqueTy { @@ -1900,7 +1901,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { origin: hir::OpaqueTyOrigin::AsyncFn, }; - trace!("exist ty from async fn def index: {:#?}", opaque_ty_def_index); + trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id); let opaque_ty_id = this.generate_opaque_type(opaque_ty_node_id, opaque_ty_item, span, opaque_ty_span); @@ -2090,7 +2091,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { | hir::LifetimeName::Underscore | hir::LifetimeName::Static => hir::ParamName::Plain(lt.name.ident()), hir::LifetimeName::ImplicitObjectLifetimeDefault => { - span_bug!( + self.sess.diagnostic().span_bug( param.ident.span, "object-lifetime-default should not occur here", ); @@ -2157,7 +2158,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> hir::TraitRef<'hir> { let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit, itctx) { hir::QPath::Resolved(None, path) => path, - qpath => bug!("lower_trait_ref: unexpected QPath `{:?}`", qpath), + qpath => panic!("lower_trait_ref: unexpected QPath `{:?}`", qpath), }; hir::TraitRef { path, hir_ref_id: self.lower_node_id(p.ref_id) } } @@ -2282,7 +2283,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { StmtKind::Expr(ref e) => hir::StmtKind::Expr(self.lower_expr(e)), StmtKind::Semi(ref e) => hir::StmtKind::Semi(self.lower_expr(e)), StmtKind::Empty => return smallvec![], - StmtKind::Mac(..) => panic!("shouldn't exist here"), + StmtKind::MacCall(..) => panic!("shouldn't exist here"), }; smallvec![hir::Stmt { hir_id: self.lower_node_id(s.id), kind, span: s.span }] } diff --git a/src/librustc_ast_lowering/pat.rs b/src/librustc_ast_lowering/pat.rs index d6f4ba1529be6..8ba6576f69265 100644 --- a/src/librustc_ast_lowering/pat.rs +++ b/src/librustc_ast_lowering/pat.rs @@ -75,7 +75,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.ban_illegal_rest_pat(p.span) } PatKind::Paren(ref inner) => return self.lower_pat(inner), - PatKind::Mac(_) => panic!("Shouldn't exist here"), + PatKind::MacCall(_) => panic!("Shouldn't exist here"), }; self.pat_with_node_id_of(p, node) diff --git a/src/librustc_ast_lowering/path.rs b/src/librustc_ast_lowering/path.rs index db8517bfbf0c7..e996bdac7cb37 100644 --- a/src/librustc_ast_lowering/path.rs +++ b/src/librustc_ast_lowering/path.rs @@ -1,14 +1,13 @@ use super::{AnonymousLifetimeMode, ImplTraitContext, LoweringContext, ParamMode}; use super::{GenericArgsCtor, ParenthesizedGenericArgs}; -use rustc::lint::builtin::ELIDED_LIFETIMES_IN_PATHS; -use rustc::span_bug; use rustc_ast::ast::{self, *}; use rustc_errors::{struct_span_err, Applicability}; use rustc_hir as hir; use rustc_hir::def::{DefKind, PartialRes, Res}; use rustc_hir::def_id::DefId; use rustc_hir::GenericArg; +use rustc_session::lint::builtin::ELIDED_LIFETIMES_IN_PATHS; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_span::Span; @@ -163,12 +162,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } // We should've returned in the for loop above. - span_bug!( + + self.sess.diagnostic().span_bug( p.span, - "lower_qpath: no final extension segment in {}..{}", - proj_start, - p.segments.len() - ) + &format!( + "lower_qpath: no final extension segment in {}..{}", + proj_start, + p.segments.len() + ), + ); } crate fn lower_path_extra( @@ -272,7 +274,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { if !generic_args.parenthesized && !has_lifetimes { generic_args.args = self .elided_path_lifetimes(path_span, expected_lifetimes) - .map(|lt| GenericArg::Lifetime(lt)) + .map(GenericArg::Lifetime) .chain(generic_args.args.into_iter()) .collect(); if expected_lifetimes > 0 && param_mode == ParamMode::Explicit { @@ -304,7 +306,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { E0726, "implicit elided lifetime not allowed here" ); - rustc::lint::add_elided_lifetime_in_path_suggestion( + rustc_session::lint::add_elided_lifetime_in_path_suggestion( &self.sess, &mut err, expected_lifetimes, diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index a2d83a525cc78..d6d1153f2790f 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -289,11 +289,7 @@ impl<'a> AstValidator<'a> { match expr.kind { ExprKind::Lit(..) | ExprKind::Err => {} ExprKind::Path(..) if allow_paths => {} - ExprKind::Unary(UnOp::Neg, ref inner) - if match inner.kind { - ExprKind::Lit(_) => true, - _ => false, - } => {} + ExprKind::Unary(UnOp::Neg, ref inner) if matches!(inner.kind, ExprKind::Lit(_)) => {} _ => self.err_handler().span_err( expr.span, "arbitrary expressions aren't allowed \ @@ -402,7 +398,7 @@ impl<'a> AstValidator<'a> { fn check_defaultness(&self, span: Span, defaultness: Defaultness) { if let Defaultness::Default(def_span) = defaultness { - let span = self.session.source_map().def_span(span); + let span = self.session.source_map().guess_head_span(span); self.err_handler() .struct_span_err(span, "`default` is only allowed on items in `impl` definitions") .span_label(def_span, "`default` because of this") @@ -517,7 +513,7 @@ impl<'a> AstValidator<'a> { } fn current_extern_span(&self) -> Span { - self.session.source_map().def_span(self.extern_mod.unwrap().span) + self.session.source_map().guess_head_span(self.extern_mod.unwrap().span) } /// An `fn` in `extern { ... }` cannot have qualfiers, e.g. `async fn`. @@ -645,6 +641,8 @@ impl<'a> AstValidator<'a> { } } +/// Checks that generic parameters are in the correct order, +/// which is lifetimes, then types and then consts. (`<'a, T, const N: usize>`) fn validate_generic_param_order<'a>( sess: &Session, handler: &rustc_errors::Handler, @@ -1000,7 +998,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { ForeignItemKind::Static(_, _, body) => { self.check_foreign_kind_bodyless(fi.ident, "static", body.as_ref().map(|b| b.span)); } - ForeignItemKind::Macro(..) => {} + ForeignItemKind::MacCall(..) => {} } visit::walk_foreign_item(self, fi) diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs index 5f36149451dd2..a0d7b064d0ccf 100644 --- a/src/librustc_ast_passes/feature_gate.rs +++ b/src/librustc_ast_passes/feature_gate.rs @@ -257,7 +257,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!( &self, non_ascii_idents, - self.parse_sess.source_map().def_span(sp), + self.parse_sess.source_map().guess_head_span(sp), "non-ascii idents are not fully supported" ); } @@ -286,8 +286,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { start, i.span, "`#[start]` functions are experimental \ - and their signature may change \ - over time" + and their signature may change \ + over time" ); } if attr::contains_name(&i.attrs[..], sym::main) { @@ -296,8 +296,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { main, i.span, "declaration of a non-standard `#[main]` \ - function may change over time, for now \ - a top-level `fn main()` is required" + function may change over time, for now \ + a top-level `fn main()` is required" ); } } @@ -341,7 +341,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { if let ast::ImplPolarity::Negative(span) = polarity { gate_feature_post!( &self, - optin_builtin_traits, + negative_impls, span.to(of_trait.as_ref().map(|t| t.path.span).unwrap_or(span)), "negative trait bounds are not yet fully implemented; \ use marker types for now" @@ -366,7 +366,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, trait_alias, i.span, "trait aliases are experimental"); } - ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => { + ast::ItemKind::MacroDef(ast::MacroDef { macro_rules: false, .. }) => { let msg = "`macro` is experimental"; gate_feature_post!(&self, decl_macro, i.span, msg); } @@ -399,7 +399,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ForeignItemKind::TyAlias(..) => { gate_feature_post!(&self, extern_types, i.span, "extern types are experimental"); } - ast::ForeignItemKind::Macro(..) => {} + ast::ForeignItemKind::MacCall(..) => {} } visit::walk_foreign_item(self, i) @@ -542,15 +542,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) { - if let ast::Defaultness::Default(_) = i.kind.defaultness() { - gate_feature_post!(&self, specialization, i.span, "specialization is unstable"); - } - - match i.kind { + let is_fn = match i.kind { ast::AssocItemKind::Fn(_, ref sig, _, _) => { if let (ast::Const::Yes(_), AssocCtxt::Trait) = (sig.header.constness, ctxt) { gate_feature_post!(&self, const_fn, i.span, "const fn is unstable"); } + true } ast::AssocItemKind::TyAlias(_, ref generics, _, ref ty) => { if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) { @@ -565,8 +562,19 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { self.check_impl_trait(ty); } self.check_gat(generics, i.span); + false } - _ => {} + _ => false, + }; + if let ast::Defaultness::Default(_) = i.kind.defaultness() { + // Limit `min_specialization` to only specializing functions. + gate_feature_fn!( + &self, + |x: &Features| x.specialization || (is_fn && x.min_specialization), + i.span, + sym::specialization, + "specialization is unstable" + ); } visit::walk_assoc_item(self, i, ctxt) } diff --git a/src/librustc_ast_passes/node_count.rs b/src/librustc_ast_passes/node_count.rs index 16bcec8360e34..534d6c7b1ea70 100644 --- a/src/librustc_ast_passes/node_count.rs +++ b/src/librustc_ast_passes/node_count.rs @@ -113,7 +113,7 @@ impl<'ast> Visitor<'ast> for NodeCounter { self.count += 1; walk_lifetime(self, lifetime) } - fn visit_mac(&mut self, _mac: &Mac) { + fn visit_mac(&mut self, _mac: &MacCall) { self.count += 1; walk_mac(self, _mac) } diff --git a/src/librustc_ast_passes/show_span.rs b/src/librustc_ast_passes/show_span.rs index 73a66ba566bc6..2366426d4dcba 100644 --- a/src/librustc_ast_passes/show_span.rs +++ b/src/librustc_ast_passes/show_span.rs @@ -55,7 +55,7 @@ impl<'a> Visitor<'a> for ShowSpanVisitor<'a> { visit::walk_ty(self, t); } - fn visit_mac(&mut self, mac: &'a ast::Mac) { + fn visit_mac(&mut self, mac: &'a ast::MacCall) { visit::walk_mac(self, mac); } } diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index 007694f7276bb..bb73e982a9c28 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -148,12 +148,19 @@ pub fn to_string(f: impl FnOnce(&mut State<'_>)) -> String { // This makes comma-separated lists look slightly nicer, // and also addresses a specific regression described in issue #63896. -fn tt_prepend_space(tt: &TokenTree) -> bool { +fn tt_prepend_space(tt: &TokenTree, prev: &TokenTree) -> bool { match tt { TokenTree::Token(token) => match token.kind { token::Comma => false, _ => true, }, + TokenTree::Delimited(_, DelimToken::Paren, _) => match prev { + TokenTree::Token(token) => match token.kind { + token::Ident(_, _) => false, + _ => true, + }, + _ => true, + }, _ => true, } } @@ -650,11 +657,14 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere } fn print_tts(&mut self, tts: tokenstream::TokenStream, convert_dollar_crate: bool) { - for (i, tt) in tts.into_trees().enumerate() { - if i != 0 && tt_prepend_space(&tt) { + let mut iter = tts.into_trees().peekable(); + while let Some(tt) = iter.next() { + let show_space = + if let Some(next) = iter.peek() { tt_prepend_space(next, &tt) } else { false }; + self.print_tt(tt, convert_dollar_crate); + if show_space { self.space(); } - self.print_tt(tt, convert_dollar_crate); } } @@ -960,7 +970,7 @@ impl<'a> State<'a> { ast::TyKind::ImplicitSelf => { self.s.word("Self"); } - ast::TyKind::Mac(ref m) => { + ast::TyKind::MacCall(ref m) => { self.print_mac(m); } ast::TyKind::CVarArgs => { @@ -987,7 +997,7 @@ impl<'a> State<'a> { ast::ForeignItemKind::TyAlias(def, generics, bounds, ty) => { self.print_associated_type(ident, generics, bounds, ty.as_deref(), vis, *def); } - ast::ForeignItemKind::Macro(m) => { + ast::ForeignItemKind::MacCall(m) => { self.print_mac(m); if m.args.need_semicolon() { self.s.word(";"); @@ -1231,14 +1241,14 @@ impl<'a> State<'a> { self.print_where_clause(&generics.where_clause); self.s.word(";"); } - ast::ItemKind::Mac(ref mac) => { + ast::ItemKind::MacCall(ref mac) => { self.print_mac(mac); if mac.args.need_semicolon() { self.s.word(";"); } } ast::ItemKind::MacroDef(ref macro_def) => { - let (kw, has_bang) = if macro_def.legacy { + let (kw, has_bang) = if macro_def.macro_rules { ("macro_rules", true) } else { self.print_visibility(&item.vis); @@ -1413,7 +1423,7 @@ impl<'a> State<'a> { ast::AssocItemKind::TyAlias(def, generics, bounds, ty) => { self.print_associated_type(ident, generics, bounds, ty.as_deref(), vis, *def); } - ast::AssocItemKind::Macro(m) => { + ast::AssocItemKind::MacCall(m) => { self.print_mac(m); if m.args.need_semicolon() { self.s.word(";"); @@ -1460,7 +1470,7 @@ impl<'a> State<'a> { self.space_if_not_bol(); self.s.word(";"); } - ast::StmtKind::Mac(ref mac) => { + ast::StmtKind::MacCall(ref mac) => { let (ref mac, style, ref attrs) = **mac; self.space_if_not_bol(); self.print_outer_attributes(attrs); @@ -1570,7 +1580,7 @@ impl<'a> State<'a> { self.print_else(elseopt) } - crate fn print_mac(&mut self, m: &ast::Mac) { + crate fn print_mac(&mut self, m: &ast::MacCall) { self.print_mac_common( Some(MacHeader::Path(&m.path)), true, @@ -2070,7 +2080,7 @@ impl<'a> State<'a> { self.pclose(); } - ast::ExprKind::Mac(ref m) => self.print_mac(m), + ast::ExprKind::MacCall(ref m) => self.print_mac(m), ast::ExprKind::Paren(ref e) => { self.popen(); self.print_inner_attributes_inline(attrs); @@ -2254,7 +2264,7 @@ impl<'a> State<'a> { self.print_pat(inner); self.pclose(); } - PatKind::Mac(ref m) => self.print_mac(m), + PatKind::MacCall(ref m) => self.print_mac(m), } self.ann.post(self, AnnNode::Pat(pat)) } diff --git a/src/librustc_attr/builtin.rs b/src/librustc_attr/builtin.rs index 08eae24da9b68..a16b79993912d 100644 --- a/src/librustc_attr/builtin.rs +++ b/src/librustc_attr/builtin.rs @@ -120,17 +120,8 @@ pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Op } /// Represents the #[stable], #[unstable], #[rustc_deprecated] attributes. -#[derive( - RustcEncodable, - RustcDecodable, - Copy, - Clone, - Debug, - PartialEq, - Eq, - Hash, - HashStable_Generic -)] +#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(HashStable_Generic)] pub struct Stability { pub level: StabilityLevel, pub feature: Symbol, @@ -138,17 +129,8 @@ pub struct Stability { } /// Represents the #[rustc_const_unstable] and #[rustc_const_stable] attributes. -#[derive( - RustcEncodable, - RustcDecodable, - Copy, - Clone, - Debug, - PartialEq, - Eq, - Hash, - HashStable_Generic -)] +#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(HashStable_Generic)] pub struct ConstStability { pub level: StabilityLevel, pub feature: Symbol, @@ -159,18 +141,8 @@ pub struct ConstStability { } /// The available stability levels. -#[derive( - RustcEncodable, - RustcDecodable, - PartialEq, - PartialOrd, - Copy, - Clone, - Debug, - Eq, - Hash, - HashStable_Generic -)] +#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)] +#[derive(HashStable_Generic)] pub enum StabilityLevel { // Reason for the current stability level and the relevant rust-lang issue Unstable { reason: Option, issue: Option, is_soft: bool }, @@ -186,18 +158,8 @@ impl StabilityLevel { } } -#[derive( - RustcEncodable, - RustcDecodable, - PartialEq, - PartialOrd, - Copy, - Clone, - Debug, - Eq, - Hash, - HashStable_Generic -)] +#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)] +#[derive(HashStable_Generic)] pub struct RustcDeprecation { pub since: Symbol, pub reason: Symbol, @@ -1024,7 +986,7 @@ pub enum TransparencyError { pub fn find_transparency( attrs: &[Attribute], - is_legacy: bool, + macro_rules: bool, ) -> (Transparency, Option) { let mut transparency = None; let mut error = None; @@ -1049,7 +1011,7 @@ pub fn find_transparency( } } } - let fallback = if is_legacy { Transparency::SemiTransparent } else { Transparency::Opaque }; + let fallback = if macro_rules { Transparency::SemiTransparent } else { Transparency::Opaque }; (transparency.map_or(fallback, |t| t.0), error) } diff --git a/src/librustc_builtin_macros/assert.rs b/src/librustc_builtin_macros/assert.rs index 09ff770e87b59..3a3595b04d287 100644 --- a/src/librustc_builtin_macros/assert.rs +++ b/src/librustc_builtin_macros/assert.rs @@ -40,7 +40,7 @@ pub fn expand_assert<'cx>( )) }); let args = P(MacArgs::Delimited(DelimSpan::from_single(sp), MacDelimiter::Parenthesis, tokens)); - let panic_call = Mac { + let panic_call = MacCall { path: Path::from_ident(Ident::new(sym::panic, sp)), args, prior_type_ascription: None, @@ -48,7 +48,7 @@ pub fn expand_assert<'cx>( let if_expr = cx.expr_if( sp, cx.expr(sp, ExprKind::Unary(UnOp::Not, cond_expr)), - cx.expr(sp, ExprKind::Mac(panic_call)), + cx.expr(sp, ExprKind::MacCall(panic_call)), None, ); MacEager::expr(if_expr) diff --git a/src/librustc_builtin_macros/cfg_accessible.rs b/src/librustc_builtin_macros/cfg_accessible.rs new file mode 100644 index 0000000000000..3607a4d0d15b6 --- /dev/null +++ b/src/librustc_builtin_macros/cfg_accessible.rs @@ -0,0 +1,54 @@ +//! Implementation of the `#[cfg_accessible(path)]` attribute macro. + +use rustc_ast::ast; +use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier}; +use rustc_feature::AttributeTemplate; +use rustc_parse::validate_attr; +use rustc_span::symbol::sym; +use rustc_span::Span; + +crate struct Expander; + +fn validate_input<'a>(ecx: &mut ExtCtxt<'_>, mi: &'a ast::MetaItem) -> Option<&'a ast::Path> { + match mi.meta_item_list() { + None => {} + Some([]) => ecx.span_err(mi.span, "`cfg_accessible` path is not specified"), + Some([_, .., l]) => ecx.span_err(l.span(), "multiple `cfg_accessible` paths are specified"), + Some([nmi]) => match nmi.meta_item() { + None => ecx.span_err(nmi.span(), "`cfg_accessible` path cannot be a literal"), + Some(mi) => { + if !mi.is_word() { + ecx.span_err(mi.span, "`cfg_accessible` path cannot accept arguments"); + } + return Some(&mi.path); + } + }, + } + None +} + +impl MultiItemModifier for Expander { + fn expand( + &self, + ecx: &mut ExtCtxt<'_>, + _span: Span, + meta_item: &ast::MetaItem, + item: Annotatable, + ) -> ExpandResult, Annotatable> { + let template = AttributeTemplate { list: Some("path"), ..Default::default() }; + let attr = &ecx.attribute(meta_item.clone()); + validate_attr::check_builtin_attribute(ecx.parse_sess, attr, sym::cfg_accessible, template); + + let path = match validate_input(ecx, meta_item) { + Some(path) => path, + None => return ExpandResult::Ready(Vec::new()), + }; + + let failure_msg = "cannot determine whether the path is accessible or not"; + match ecx.resolver.cfg_accessible(ecx.current_expansion.id, path) { + Ok(true) => ExpandResult::Ready(vec![item]), + Ok(false) => ExpandResult::Ready(Vec::new()), + Err(_) => ExpandResult::Retry(item, failure_msg.into()), + } + } +} diff --git a/src/librustc_builtin_macros/cmdline_attrs.rs b/src/librustc_builtin_macros/cmdline_attrs.rs index 7ddbf08306b72..093815dbbcd4f 100644 --- a/src/librustc_builtin_macros/cmdline_attrs.rs +++ b/src/librustc_builtin_macros/cmdline_attrs.rs @@ -3,7 +3,6 @@ use rustc_ast::ast::{self, AttrItem, AttrStyle}; use rustc_ast::attr::mk_attr; use rustc_ast::token; -use rustc_expand::panictry; use rustc_session::parse::ParseSess; use rustc_span::FileName; @@ -16,7 +15,13 @@ pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) - ); let start_span = parser.token.span; - let AttrItem { path, args } = panictry!(parser.parse_attr_item()); + let AttrItem { path, args } = match parser.parse_attr_item() { + Ok(ai) => ai, + Err(mut err) => { + err.emit(); + continue; + } + }; let end_span = parser.token.span; if parser.token != token::Eof { parse_sess.span_diagnostic.span_err(start_span.to(end_span), "invalid crate attribute"); diff --git a/src/librustc_builtin_macros/deriving/decodable.rs b/src/librustc_builtin_macros/deriving/decodable.rs index ac5d08ba62d0d..64a810bdcf687 100644 --- a/src/librustc_builtin_macros/deriving/decodable.rs +++ b/src/librustc_builtin_macros/deriving/decodable.rs @@ -87,7 +87,7 @@ fn decodable_substructure( let blkarg = cx.ident_of("_d", trait_span); let blkdecoder = cx.expr_ident(trait_span, blkarg); - return match *substr.fields { + match *substr.fields { StaticStruct(_, ref summary) => { let nfields = match *summary { Unnamed(ref fields, _) => fields.len(), @@ -178,7 +178,7 @@ fn decodable_substructure( ) } _ => cx.bug("expected StaticEnum or StaticStruct in derive(Decodable)"), - }; + } } /// Creates a decoder for a single enum variant/struct: diff --git a/src/librustc_builtin_macros/deriving/default.rs b/src/librustc_builtin_macros/deriving/default.rs index cb85a0b1a10cc..27d5263320041 100644 --- a/src/librustc_builtin_macros/deriving/default.rs +++ b/src/librustc_builtin_macros/deriving/default.rs @@ -53,7 +53,7 @@ fn default_substructure( let default_ident = cx.std_path(&[kw::Default, sym::Default, kw::Default]); let default_call = |span| cx.expr_call_global(span, default_ident.clone(), Vec::new()); - return match *substr.fields { + match *substr.fields { StaticStruct(_, ref summary) => match *summary { Unnamed(ref fields, is_tuple) => { if !is_tuple { @@ -83,5 +83,5 @@ fn default_substructure( DummyResult::raw_expr(trait_span, true) } _ => cx.span_bug(trait_span, "method in `derive(Default)`"), - }; + } } diff --git a/src/librustc_builtin_macros/deriving/encodable.rs b/src/librustc_builtin_macros/deriving/encodable.rs index 9073085381ac1..54926ec3fd502 100644 --- a/src/librustc_builtin_macros/deriving/encodable.rs +++ b/src/librustc_builtin_macros/deriving/encodable.rs @@ -173,7 +173,7 @@ fn encodable_substructure( ], )); - return match *substr.fields { + match *substr.fields { Struct(_, ref fields) => { let emit_struct_field = cx.ident_of("emit_struct_field", trait_span); let mut stmts = Vec::new(); @@ -283,5 +283,5 @@ fn encodable_substructure( } _ => cx.bug("expected Struct or EnumMatching in derive(Encodable)"), - }; + } } diff --git a/src/librustc_builtin_macros/deriving/generic/mod.rs b/src/librustc_builtin_macros/deriving/generic/mod.rs index e0c619fcbd378..9338f9afbbb31 100644 --- a/src/librustc_builtin_macros/deriving/generic/mod.rs +++ b/src/librustc_builtin_macros/deriving/generic/mod.rs @@ -360,7 +360,7 @@ fn find_type_parameters( visit::walk_ty(self, ty) } - fn visit_mac(&mut self, mac: &ast::Mac) { + fn visit_mac(&mut self, mac: &ast::MacCall) { self.cx.span_err(mac.span(), "`derive` cannot be used on items with type macros"); } } @@ -489,7 +489,6 @@ impl<'a> TraitDef<'a> { // set earlier; see // librustc_expand/expand.rs:MacroExpander::fully_expand_fragment() // librustc_expand/base.rs:Annotatable::derive_allowed() - return; } } } @@ -1057,8 +1056,9 @@ impl<'a> MethodDef<'a> { self_: field, other: other_fields .iter_mut() - .map(|l| match l.next().unwrap() { - (.., ex, _) => ex, + .map(|l| { + let (.., ex, _) = l.next().unwrap(); + ex }) .collect(), attrs, diff --git a/src/librustc_builtin_macros/deriving/generic/ty.rs b/src/librustc_builtin_macros/deriving/generic/ty.rs index bd54a73531197..d83c98572a272 100644 --- a/src/librustc_builtin_macros/deriving/generic/ty.rs +++ b/src/librustc_builtin_macros/deriving/generic/ty.rs @@ -76,8 +76,8 @@ impl<'a> Path<'a> { self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect(); let params = lt .into_iter() - .map(|lt| GenericArg::Lifetime(lt)) - .chain(tys.into_iter().map(|ty| GenericArg::Type(ty))) + .map(GenericArg::Lifetime) + .chain(tys.into_iter().map(GenericArg::Type)) .collect(); match self.kind { diff --git a/src/librustc_builtin_macros/deriving/mod.rs b/src/librustc_builtin_macros/deriving/mod.rs index 5ba9d3800e118..b5ad67abf6201 100644 --- a/src/librustc_builtin_macros/deriving/mod.rs +++ b/src/librustc_builtin_macros/deriving/mod.rs @@ -2,7 +2,7 @@ use rustc_ast::ast::{self, ItemKind, MetaItem}; use rustc_ast::ptr::P; -use rustc_expand::base::{Annotatable, ExtCtxt, MultiItemModifier}; +use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; @@ -48,13 +48,13 @@ impl MultiItemModifier for BuiltinDerive { span: Span, meta_item: &MetaItem, item: Annotatable, - ) -> Vec { + ) -> ExpandResult, Annotatable> { // FIXME: Built-in derives often forget to give spans contexts, // so we are doing it here in a centralized way. let span = ecx.with_def_site_ctxt(span); let mut items = Vec::new(); (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a)); - items + ExpandResult::Ready(items) } } diff --git a/src/librustc_builtin_macros/format_foreign.rs b/src/librustc_builtin_macros/format_foreign.rs index cc3c403450e04..e6a87e4d82586 100644 --- a/src/librustc_builtin_macros/format_foreign.rs +++ b/src/librustc_builtin_macros/format_foreign.rs @@ -359,7 +359,7 @@ pub mod printf { // // Note: `move` used to capture copies of the cursors as they are *now*. let fallback = move || { - return Some(( + Some(( Substitution::Format(Format { span: start.slice_between(next).unwrap(), parameter: None, @@ -371,7 +371,7 @@ pub mod printf { position: InnerSpan::new(start.at, next.at), }), next.slice_after(), - )); + )) }; // Next parsing state. diff --git a/src/librustc_builtin_macros/lib.rs b/src/librustc_builtin_macros/lib.rs index 9a8b0a87cb793..26a59c6b1bedb 100644 --- a/src/librustc_builtin_macros/lib.rs +++ b/src/librustc_builtin_macros/lib.rs @@ -22,6 +22,7 @@ use rustc_span::symbol::sym; mod asm; mod assert; mod cfg; +mod cfg_accessible; mod compile_error; mod concat; mod concat_idents; @@ -85,6 +86,7 @@ pub fn register_builtin_macros(resolver: &mut dyn Resolver, edition: Edition) { register_attr! { bench: test::expand_bench, + cfg_accessible: cfg_accessible::Expander, global_allocator: global_allocator::expand, test: test::expand_test, test_case: test::expand_test_case, diff --git a/src/librustc_builtin_macros/proc_macro_harness.rs b/src/librustc_builtin_macros/proc_macro_harness.rs index 7972466236333..735de4f0a5b24 100644 --- a/src/librustc_builtin_macros/proc_macro_harness.rs +++ b/src/librustc_builtin_macros/proc_macro_harness.rs @@ -10,6 +10,7 @@ use rustc_expand::base::{ExtCtxt, Resolver}; use rustc_expand::expand::{AstFragment, ExpansionConfig}; use rustc_session::parse::ParseSess; use rustc_span::hygiene::AstPass; +use rustc_span::source_map::SourceMap; use rustc_span::symbol::{kw, sym}; use rustc_span::{Span, DUMMY_SP}; use smallvec::smallvec; @@ -44,6 +45,7 @@ struct CollectProcMacros<'a> { macros: Vec, in_root: bool, handler: &'a rustc_errors::Handler, + source_map: &'a SourceMap, is_proc_macro_crate: bool, is_test_crate: bool, } @@ -59,12 +61,13 @@ pub fn inject( handler: &rustc_errors::Handler, ) -> ast::Crate { let ecfg = ExpansionConfig::default("proc_macro".to_string()); - let mut cx = ExtCtxt::new(sess, ecfg, resolver); + let mut cx = ExtCtxt::new(sess, ecfg, resolver, None); let mut collect = CollectProcMacros { macros: Vec::new(), in_root: true, handler, + source_map: sess.source_map(), is_proc_macro_crate, is_test_crate, }; @@ -195,7 +198,7 @@ impl<'a> CollectProcMacros<'a> { } else { "functions tagged with `#[proc_macro_derive]` must be `pub`" }; - self.handler.span_err(item.span, msg); + self.handler.span_err(self.source_map.guess_head_span(item.span), msg); } } @@ -214,7 +217,7 @@ impl<'a> CollectProcMacros<'a> { } else { "functions tagged with `#[proc_macro_attribute]` must be `pub`" }; - self.handler.span_err(item.span, msg); + self.handler.span_err(self.source_map.guess_head_span(item.span), msg); } } @@ -233,7 +236,7 @@ impl<'a> CollectProcMacros<'a> { } else { "functions tagged with `#[proc_macro]` must be `pub`" }; - self.handler.span_err(item.span, msg); + self.handler.span_err(self.source_map.guess_head_span(item.span), msg); } } } @@ -244,7 +247,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { if self.is_proc_macro_crate && attr::contains_name(&item.attrs, sym::macro_export) { let msg = "cannot export macro_rules! macros from a `proc-macro` crate type currently"; - self.handler.span_err(item.span, msg); + self.handler.span_err(self.source_map.guess_head_span(item.span), msg); } } @@ -295,7 +298,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { let attr = match found_attr { None => { - self.check_not_pub_in_root(&item.vis, item.span); + self.check_not_pub_in_root(&item.vis, self.source_map.guess_head_span(item.span)); let prev_in_root = mem::replace(&mut self.in_root, false); visit::walk_item(self, item); self.in_root = prev_in_root; @@ -341,7 +344,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { self.in_root = prev_in_root; } - fn visit_mac(&mut self, mac: &'a ast::Mac) { + fn visit_mac(&mut self, mac: &'a ast::MacCall) { visit::walk_mac(self, mac) } } diff --git a/src/librustc_builtin_macros/source_util.rs b/src/librustc_builtin_macros/source_util.rs index 5ad72a7443dd2..67145c6bf433b 100644 --- a/src/librustc_builtin_macros/source_util.rs +++ b/src/librustc_builtin_macros/source_util.rs @@ -4,13 +4,14 @@ use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_ast_pretty::pprust; use rustc_expand::base::{self, *}; -use rustc_expand::panictry; -use rustc_parse::{self, new_sub_parser_from_file, parser::Parser, DirectoryOwnership}; +use rustc_expand::module::DirectoryOwnership; +use rustc_parse::{self, new_parser_from_file, parser::Parser}; use rustc_session::lint::builtin::INCOMPLETE_INCLUDE; use rustc_span::symbol::Symbol; use rustc_span::{self, Pos, Span}; use smallvec::SmallVec; +use std::rc::Rc; use rustc_data_structures::sync::Lrc; @@ -101,22 +102,30 @@ pub fn expand_include<'cx>( None => return DummyResult::any(sp), }; // The file will be added to the code map by the parser - let file = match cx.resolve_path(file, sp) { + let mut file = match cx.resolve_path(file, sp) { Ok(f) => f, Err(mut err) => { err.emit(); return DummyResult::any(sp); } }; - let directory_ownership = DirectoryOwnership::Owned { relative: None }; - let p = new_sub_parser_from_file(cx.parse_sess(), &file, directory_ownership, None, sp); + let p = new_parser_from_file(cx.parse_sess(), &file, Some(sp)); + + // If in the included file we have e.g., `mod bar;`, + // then the path of `bar.rs` should be relative to the directory of `file`. + // See https://github.com/rust-lang/rust/pull/69838/files#r395217057 for a discussion. + // `MacroExpander::fully_expand_fragment` later restores, so "stack discipline" is maintained. + file.pop(); + cx.current_expansion.directory_ownership = DirectoryOwnership::Owned { relative: None }; + let mod_path = cx.current_expansion.module.mod_path.clone(); + cx.current_expansion.module = Rc::new(ModuleData { mod_path, directory: file }); struct ExpandResult<'a> { p: Parser<'a>, } impl<'a> base::MacResult for ExpandResult<'a> { fn make_expr(mut self: Box>) -> Option> { - let r = panictry!(self.p.parse_expr()); + let r = base::parse_expr(&mut self.p)?; if self.p.token != token::Eof { self.p.sess.buffer_lint( &INCOMPLETE_INCLUDE, @@ -131,18 +140,17 @@ pub fn expand_include<'cx>( fn make_items(mut self: Box>) -> Option; 1]>> { let mut ret = SmallVec::new(); while self.p.token != token::Eof { - match panictry!(self.p.parse_item()) { - Some(item) => ret.push(item), - None => { + match self.p.parse_item() { + Err(mut err) => { + err.emit(); + break; + } + Ok(Some(item)) => ret.push(item), + Ok(None) => { let token = pprust::token_to_string(&self.p.token); - self.p - .sess - .span_diagnostic - .span_fatal( - self.p.token.span, - &format!("expected item, found `{}`", token), - ) - .raise(); + let msg = format!("expected item, found `{}`", token); + self.p.struct_span_err(self.p.token.span, &msg).emit(); + break; } } } diff --git a/src/librustc_builtin_macros/standard_library_imports.rs b/src/librustc_builtin_macros/standard_library_imports.rs index 30403f6dc41c1..f48fd6df9c98b 100644 --- a/src/librustc_builtin_macros/standard_library_imports.rs +++ b/src/librustc_builtin_macros/standard_library_imports.rs @@ -39,7 +39,7 @@ pub fn inject( let call_site = DUMMY_SP.with_call_site_ctxt(expn_id); let ecfg = ExpansionConfig::default("std_lib_injection".to_string()); - let cx = ExtCtxt::new(sess, ecfg, resolver); + let cx = ExtCtxt::new(sess, ecfg, resolver, None); // .rev() to preserve ordering above in combination with insert(0, ...) for &name in names.iter().rev() { diff --git a/src/librustc_builtin_macros/test.rs b/src/librustc_builtin_macros/test.rs index bc194a3eec4c3..bdc4ae2fe274b 100644 --- a/src/librustc_builtin_macros/test.rs +++ b/src/librustc_builtin_macros/test.rs @@ -74,19 +74,19 @@ pub fn expand_test_or_bench( return vec![]; } - let item = if let Annotatable::Item(i) = item { - i - } else { - cx.parse_sess - .span_diagnostic - .span_fatal( - item.span(), + let item = match item { + Annotatable::Item(i) => i, + other => { + cx.struct_span_err( + other.span(), "`#[test]` attribute is only allowed on non associated functions", ) - .raise(); + .emit(); + return vec![other]; + } }; - if let ast::ItemKind::Mac(_) = item.kind { + if let ast::ItemKind::MacCall(_) = item.kind { cx.parse_sess.span_diagnostic.span_warn( item.span, "`#[test]` attribute should not be used on macros. Use `#[cfg(test)]` instead.", diff --git a/src/librustc_builtin_macros/test_harness.rs b/src/librustc_builtin_macros/test_harness.rs index e7e1ad8eda784..160a5204eaf70 100644 --- a/src/librustc_builtin_macros/test_harness.rs +++ b/src/librustc_builtin_macros/test_harness.rs @@ -138,7 +138,7 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { smallvec![P(item)] } - fn visit_mac(&mut self, _mac: &mut ast::Mac) { + fn visit_mac(&mut self, _mac: &mut ast::MacCall) { // Do nothing. } } @@ -184,7 +184,7 @@ impl MutVisitor for EntryPointCleaner { smallvec![item] } - fn visit_mac(&mut self, _mac: &mut ast::Mac) { + fn visit_mac(&mut self, _mac: &mut ast::MacCall) { // Do nothing. } } @@ -202,7 +202,7 @@ fn generate_test_harness( let mut econfig = ExpansionConfig::default("test".to_string()); econfig.features = Some(features); - let ext_cx = ExtCtxt::new(sess, econfig, resolver); + let ext_cx = ExtCtxt::new(sess, econfig, resolver, None); let expn_id = ext_cx.resolver.expansion_for_ast_pass( DUMMY_SP, @@ -345,14 +345,14 @@ fn is_test_case(i: &ast::Item) -> bool { fn get_test_runner(sd: &rustc_errors::Handler, krate: &ast::Crate) -> Option { let test_attr = attr::find_by_name(&krate.attrs, sym::test_runner)?; - test_attr.meta_item_list().map(|meta_list| { - if meta_list.len() != 1 { - sd.span_fatal(test_attr.span, "`#![test_runner(..)]` accepts exactly 1 argument") - .raise() - } - match meta_list[0].meta_item() { - Some(meta_item) if meta_item.is_word() => meta_item.path.clone(), - _ => sd.span_fatal(test_attr.span, "`test_runner` argument must be a path").raise(), - } - }) + let meta_list = test_attr.meta_item_list()?; + let span = test_attr.span; + match &*meta_list { + [single] => match single.meta_item() { + Some(meta_item) if meta_item.is_word() => return Some(meta_item.path.clone()), + _ => sd.struct_span_err(span, "`test_runner` argument must be a path").emit(), + }, + _ => sd.struct_span_err(span, "`#![test_runner(..)]` accepts exactly 1 argument").emit(), + } + None } diff --git a/src/librustc_builtin_macros/util.rs b/src/librustc_builtin_macros/util.rs index 8ef76a8657e1e..b486eadd1a8be 100644 --- a/src/librustc_builtin_macros/util.rs +++ b/src/librustc_builtin_macros/util.rs @@ -6,7 +6,7 @@ use rustc_span::Symbol; pub fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, name: Symbol) { // All the built-in macro attributes are "words" at the moment. - let template = AttributeTemplate::only_word(); + let template = AttributeTemplate { word: true, ..Default::default() }; let attr = ecx.attribute(meta_item.clone()); validate_attr::check_builtin_attribute(ecx.parse_sess, &attr, name, template); } diff --git a/src/librustc_codegen_llvm/Cargo.toml b/src/librustc_codegen_llvm/Cargo.toml index 0776cb19760d5..16ed0854abe6e 100644 --- a/src/librustc_codegen_llvm/Cargo.toml +++ b/src/librustc_codegen_llvm/Cargo.toml @@ -20,7 +20,6 @@ rustc = { path = "../librustc" } rustc-demangle = "0.1" rustc_attr = { path = "../librustc_attr" } rustc_codegen_ssa = { path = "../librustc_codegen_ssa" } -rustc_codegen_utils = { path = "../librustc_codegen_utils" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } rustc_feature = { path = "../librustc_feature" } diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index a9e4fdba03036..072607fff85c7 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -3,8 +3,6 @@ use std::ffi::CString; use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc::session::config::{OptLevel, Sanitizer}; -use rustc::session::Session; use rustc::ty::layout::HasTyCtxt; use rustc::ty::query::Providers; use rustc::ty::{self, Ty, TyCtxt}; @@ -13,6 +11,8 @@ use rustc_data_structures::const_cstr; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_session::config::{OptLevel, Sanitizer}; +use rustc_session::Session; use rustc_target::abi::call::Conv; use rustc_target::spec::PanicStrategy; diff --git a/src/librustc_codegen_llvm/back/archive.rs b/src/librustc_codegen_llvm/back/archive.rs index 455b7086212ba..f1fe40d919eeb 100644 --- a/src/librustc_codegen_llvm/back/archive.rs +++ b/src/librustc_codegen_llvm/back/archive.rs @@ -9,9 +9,9 @@ use std::str; use crate::llvm::archive_ro::{ArchiveRO, Child}; use crate::llvm::{self, ArchiveKind}; -use rustc::session::Session; use rustc_codegen_ssa::back::archive::{find_library, ArchiveBuilder}; use rustc_codegen_ssa::{looks_like_rust_object_file, METADATA_FILENAME, RLIB_BYTECODE_EXTENSION}; +use rustc_session::Session; use rustc_span::symbol::Symbol; struct ArchiveConfig<'a> { @@ -146,7 +146,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> { } // ok, don't skip this - return false; + false }) } diff --git a/src/librustc_codegen_llvm/back/bytecode.rs b/src/librustc_codegen_llvm/back/bytecode.rs index db29556e70ccc..0c8ce39132abb 100644 --- a/src/librustc_codegen_llvm/back/bytecode.rs +++ b/src/librustc_codegen_llvm/back/bytecode.rs @@ -83,7 +83,7 @@ pub fn encode(identifier: &str, bytecode: &[u8]) -> Vec { encoded.push(0); } - return encoded; + encoded } pub struct DecodedBytecode<'a> { @@ -132,7 +132,7 @@ impl<'a> DecodedBytecode<'a> { pub fn bytecode(&self) -> Vec { let mut data = Vec::new(); DeflateDecoder::new(self.encoded_bytecode).read_to_end(&mut data).unwrap(); - return data; + data } pub fn identifier(&self) -> &'a str { diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index 310cae978bf5e..1b64750f51feb 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -9,7 +9,6 @@ use log::{debug, info}; use rustc::bug; use rustc::dep_graph::WorkProduct; use rustc::middle::exported_symbols::SymbolExportLevel; -use rustc::session::config::{self, Lto}; use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared}; use rustc_codegen_ssa::back::symbol_export; use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, ModuleConfig}; @@ -19,6 +18,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{FatalError, Handler}; use rustc_hir::def_id::LOCAL_CRATE; use rustc_session::cgu_reuse_tracker::CguReuse; +use rustc_session::config::{self, Lto}; use std::ffi::{CStr, CString}; use std::fs::File; diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 0c243128104e7..5759eb2991a81 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -15,16 +15,16 @@ use crate::LlvmCodegenBackend; use crate::ModuleLlvm; use log::debug; use rustc::bug; -use rustc::session::config::{self, Lto, OutputType, Passes, Sanitizer, SwitchWithOptPath}; -use rustc::session::Session; use rustc::ty::TyCtxt; -use rustc_codegen_ssa::back::write::{run_assembler, CodegenContext, ModuleConfig}; +use rustc_codegen_ssa::back::write::{run_assembler, CodegenContext, EmbedBitcode, ModuleConfig}; use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, RLIB_BYTECODE_EXTENSION}; use rustc_data_structures::small_c_str::SmallCStr; use rustc_errors::{FatalError, Handler}; use rustc_fs_util::{link_or_copy, path_to_c_string}; use rustc_hir::def_id::LOCAL_CRATE; +use rustc_session::config::{self, Lto, OutputType, Passes, Sanitizer, SwitchWithOptPath}; +use rustc_session::Session; use libc::{c_char, c_int, c_uint, c_void, size_t}; use std::ffi::CString; @@ -634,30 +634,24 @@ pub(crate) unsafe fn codegen( f(cpm) } - // If we don't have the integrated assembler, then we need to emit asm - // from LLVM and use `gcc` to create the object file. - let asm_to_obj = config.emit_obj && config.no_integrated_as; - - // Change what we write and cleanup based on whether obj files are - // just llvm bitcode. In that case write bitcode, and possibly - // delete the bitcode if it wasn't requested. Don't generate the - // machine code, instead copy the .o file from the .bc - let write_bc = config.emit_bc || config.obj_is_bitcode; - let rm_bc = !config.emit_bc && config.obj_is_bitcode; - let write_obj = config.emit_obj && !config.obj_is_bitcode && !asm_to_obj; - let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode; + // Two things to note: + // - If object files are just LLVM bitcode we write bitcode, copy it to + // the .o file, and delete the bitcode if it wasn't otherwise + // requested. + // - If we don't have the integrated assembler then we need to emit + // asm from LLVM and use `gcc` to create the object file. let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name); let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name); - if write_bc || config.emit_bc_compressed || config.embed_bitcode { + if config.bitcode_needed() { let _timer = cgcx .prof .generic_activity_with_arg("LLVM_module_codegen_make_bitcode", &module.name[..]); let thin = ThinBuffer::new(llmod); let data = thin.data(); - if write_bc { + if config.emit_bc || config.obj_is_bitcode { let _timer = cgcx.prof.generic_activity_with_arg( "LLVM_module_codegen_emit_bitcode", &module.name[..], @@ -668,7 +662,7 @@ pub(crate) unsafe fn codegen( } } - if config.embed_bitcode { + if config.embed_bitcode == EmbedBitcode::Full { let _timer = cgcx.prof.generic_activity_with_arg( "LLVM_module_codegen_embed_bitcode", &module.name[..], @@ -688,81 +682,75 @@ pub(crate) unsafe fn codegen( diag_handler.err(&msg); } } - } else if config.embed_bitcode_marker { + } else if config.embed_bitcode == EmbedBitcode::Marker { embed_bitcode(cgcx, llcx, llmod, None); } - { - if config.emit_ir { - let _timer = cgcx - .prof - .generic_activity_with_arg("LLVM_module_codegen_emit_ir", &module.name[..]); - let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name); - let out_c = path_to_c_string(&out); - - extern "C" fn demangle_callback( - input_ptr: *const c_char, - input_len: size_t, - output_ptr: *mut c_char, - output_len: size_t, - ) -> size_t { - let input = unsafe { - slice::from_raw_parts(input_ptr as *const u8, input_len as usize) - }; - - let input = match str::from_utf8(input) { - Ok(s) => s, - Err(_) => return 0, - }; - - let output = unsafe { - slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize) - }; - let mut cursor = io::Cursor::new(output); - - let demangled = match rustc_demangle::try_demangle(input) { - Ok(d) => d, - Err(_) => return 0, - }; - - if write!(cursor, "{:#}", demangled).is_err() { - // Possible only if provided buffer is not big enough - return 0; - } - - cursor.position() as size_t + if config.emit_ir { + let _timer = cgcx + .prof + .generic_activity_with_arg("LLVM_module_codegen_emit_ir", &module.name[..]); + let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name); + let out_c = path_to_c_string(&out); + + extern "C" fn demangle_callback( + input_ptr: *const c_char, + input_len: size_t, + output_ptr: *mut c_char, + output_len: size_t, + ) -> size_t { + let input = + unsafe { slice::from_raw_parts(input_ptr as *const u8, input_len as usize) }; + + let input = match str::from_utf8(input) { + Ok(s) => s, + Err(_) => return 0, + }; + + let output = unsafe { + slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize) + }; + let mut cursor = io::Cursor::new(output); + + let demangled = match rustc_demangle::try_demangle(input) { + Ok(d) => d, + Err(_) => return 0, + }; + + if write!(cursor, "{:#}", demangled).is_err() { + // Possible only if provided buffer is not big enough + return 0; } - let result = llvm::LLVMRustPrintModule(llmod, out_c.as_ptr(), demangle_callback); - result.into_result().map_err(|()| { - let msg = format!("failed to write LLVM IR to {}", out.display()); - llvm_err(diag_handler, &msg) - })?; + cursor.position() as size_t } - if config.emit_asm || asm_to_obj { - let _timer = cgcx - .prof - .generic_activity_with_arg("LLVM_module_codegen_emit_asm", &module.name[..]); - let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); + let result = llvm::LLVMRustPrintModule(llmod, out_c.as_ptr(), demangle_callback); + result.into_result().map_err(|()| { + let msg = format!("failed to write LLVM IR to {}", out.display()); + llvm_err(diag_handler, &msg) + })?; + } - // We can't use the same module for asm and binary output, because that triggers - // various errors like invalid IR or broken binaries, so we might have to clone the - // module to produce the asm output - let llmod = if config.emit_obj { llvm::LLVMCloneModule(llmod) } else { llmod }; - with_codegen(tm, llmod, config.no_builtins, |cpm| { - write_output_file( - diag_handler, - tm, - cpm, - llmod, - &path, - llvm::FileType::AssemblyFile, - ) - })?; - } + let config_emit_normal_obj = config.emit_obj && !config.obj_is_bitcode; - if write_obj { + if config.emit_asm || (config_emit_normal_obj && config.no_integrated_as) { + let _timer = cgcx + .prof + .generic_activity_with_arg("LLVM_module_codegen_emit_asm", &module.name[..]); + let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); + + // We can't use the same module for asm and binary output, because that triggers + // various errors like invalid IR or broken binaries, so we might have to clone the + // module to produce the asm output + let llmod = if config.emit_obj { llvm::LLVMCloneModule(llmod) } else { llmod }; + with_codegen(tm, llmod, config.no_builtins, |cpm| { + write_output_file(diag_handler, tm, cpm, llmod, &path, llvm::FileType::AssemblyFile) + })?; + } + + if config_emit_normal_obj { + if !config.no_integrated_as { let _timer = cgcx .prof .generic_activity_with_arg("LLVM_module_codegen_emit_obj", &module.name[..]); @@ -776,7 +764,7 @@ pub(crate) unsafe fn codegen( llvm::FileType::ObjectFile, ) })?; - } else if asm_to_obj { + } else { let _timer = cgcx .prof .generic_activity_with_arg("LLVM_module_codegen_asm_to_obj", &module.name[..]); @@ -789,17 +777,19 @@ pub(crate) unsafe fn codegen( } } - if copy_bc_to_obj { - debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out); - if let Err(e) = link_or_copy(&bc_out, &obj_out) { - diag_handler.err(&format!("failed to copy bitcode to object file: {}", e)); + if config.obj_is_bitcode { + if config.emit_obj { + debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out); + if let Err(e) = link_or_copy(&bc_out, &obj_out) { + diag_handler.err(&format!("failed to copy bitcode to object file: {}", e)); + } } - } - if rm_bc { - debug!("removing_bitcode {:?}", bc_out); - if let Err(e) = fs::remove_file(&bc_out) { - diag_handler.err(&format!("failed to remove bitcode: {}", e)); + if !config.emit_bc { + debug!("removing_bitcode {:?}", bc_out); + if let Err(e) = fs::remove_file(&bc_out) { + diag_handler.err(&format!("failed to remove bitcode: {}", e)); + } } } diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 04c084e459eab..1fb1965484af2 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -28,13 +28,13 @@ use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc::middle::cstore::EncodedMetadata; use rustc::middle::exported_symbols; use rustc::mir::mono::{Linkage, Visibility}; -use rustc::session::config::DebugInfo; use rustc::ty::TyCtxt; use rustc_codegen_ssa::base::maybe_create_entry_wrapper; use rustc_codegen_ssa::mono_item::MonoItemExt; use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{ModuleCodegen, ModuleKind}; use rustc_data_structures::small_c_str::SmallCStr; +use rustc_session::config::DebugInfo; use rustc_span::symbol::Symbol; use std::ffi::CString; @@ -71,8 +71,7 @@ pub fn write_compressed_metadata<'tcx>( // flags, at least for ELF outputs, so that the // metadata doesn't get loaded into memory. let directive = format!(".section {}", section_name); - let directive = CString::new(directive).unwrap(); - llvm::LLVMSetModuleInlineAsm(metadata_llmod, directive.as_ptr()) + llvm::LLVMSetModuleInlineAsm2(metadata_llmod, directive.as_ptr().cast(), directive.len()) } } diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 1c5987f26f129..b37d63fce6592 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -7,7 +7,6 @@ use crate::type_of::LayoutLlvmExt; use crate::value::Value; use libc::{c_char, c_uint}; use log::debug; -use rustc::session::config::{self, Sanitizer}; use rustc::ty::layout::{self, Align, Size, TyLayout}; use rustc::ty::{self, Ty, TyCtxt}; use rustc_codegen_ssa::base::to_immediate; @@ -19,6 +18,7 @@ use rustc_codegen_ssa::MemFlags; use rustc_data_structures::const_cstr; use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; +use rustc_session::config::{self, Sanitizer}; use rustc_target::spec::{HasTargetSpec, Target}; use std::borrow::Cow; use std::ffi::CStr; diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index df38eeec00fce..f72060868128c 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -96,15 +96,11 @@ impl BackendTypes for CodegenCx<'ll, 'tcx> { impl CodegenCx<'ll, 'tcx> { pub fn const_array(&self, ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value { - unsafe { - return llvm::LLVMConstArray(ty, elts.as_ptr(), elts.len() as c_uint); - } + unsafe { llvm::LLVMConstArray(ty, elts.as_ptr(), elts.len() as c_uint) } } pub fn const_vector(&self, elts: &[&'ll Value]) -> &'ll Value { - unsafe { - return llvm::LLVMConstVector(elts.as_ptr(), elts.len() as c_uint); - } + unsafe { llvm::LLVMConstVector(elts.as_ptr(), elts.len() as c_uint) } } pub fn const_bytes(&self, bytes: &[u8]) -> &'ll Value { @@ -259,11 +255,14 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { let base_addr = match alloc_kind { Some(GlobalAlloc::Memory(alloc)) => { let init = const_alloc_to_llvm(self, alloc); - if alloc.mutability == Mutability::Mut { - self.static_addr_of_mut(init, alloc.align, None) - } else { - self.static_addr_of(init, alloc.align, None) + let value = match alloc.mutability { + Mutability::Mut => self.static_addr_of_mut(init, alloc.align, None), + _ => self.static_addr_of(init, alloc.align, None), + }; + if !self.sess().fewer_names() { + llvm::set_value_name(value, format!("{:?}", ptr.alloc_id).as_bytes()); } + value } Some(GlobalAlloc::Function(fn_instance)) => self.get_fn_addr(fn_instance), Some(GlobalAlloc::Static(def_id)) => { @@ -320,14 +319,14 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { } } -pub fn val_ty(v: &'ll Value) -> &'ll Type { +pub fn val_ty(v: &Value) -> &Type { unsafe { llvm::LLVMTypeOf(v) } } pub fn bytes_in_context(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value { unsafe { let ptr = bytes.as_ptr() as *const c_char; - return llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True); + llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True) } } @@ -342,6 +341,6 @@ fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 { ((hi as u128) << 64) | (lo as u128) } -fn try_as_const_integral(v: &'ll Value) -> Option<&'ll ConstantInt> { +fn try_as_const_integral(v: &Value) -> Option<&ConstantInt> { unsafe { llvm::LLVMIsAConstantInt(v) } } diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index 09a84aff16811..619dee2909281 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -1,7 +1,7 @@ use crate::base; use crate::common::CodegenCx; use crate::debuginfo; -use crate::llvm::{self, SetUnnamedAddr, True}; +use crate::llvm::{self, True}; use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; @@ -183,7 +183,7 @@ impl CodegenCx<'ll, 'tcx> { }; llvm::LLVMSetInitializer(gv, cv); set_global_alignment(&self, gv, align); - SetUnnamedAddr(gv, true); + llvm::SetUnnamedAddress(gv, llvm::UnnamedAddr::Global); gv } } diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 3466363ac7972..92f59feef90fe 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -1,37 +1,32 @@ -use crate::abi::FnAbi; use crate::attributes; +use crate::callee::get_fn; use crate::debuginfo; use crate::llvm; use crate::llvm_util; -use crate::value::Value; -use rustc::dep_graph::DepGraphSafe; - use crate::type_::Type; -use rustc_codegen_ssa::traits::*; +use crate::value::Value; -use crate::callee::get_fn; use rustc::bug; +use rustc::dep_graph::DepGraphSafe; use rustc::mir::mono::CodegenUnit; -use rustc::session::config::{self, CFGuard, DebugInfo}; -use rustc::session::Session; use rustc::ty::layout::{ - FnAbiExt, HasParamEnv, LayoutError, LayoutOf, PointeeInfo, Size, TyLayout, VariantIdx, + HasParamEnv, LayoutError, LayoutOf, PointeeInfo, Size, TyLayout, VariantIdx, }; use rustc::ty::{self, Instance, Ty, TyCtxt}; use rustc_codegen_ssa::base::wants_msvc_seh; +use rustc_codegen_ssa::traits::*; use rustc_data_structures::base_n; use rustc_data_structures::const_cstr; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::small_c_str::SmallCStr; -use rustc_hir::Unsafety; -use rustc_target::spec::{HasTargetSpec, Target}; - -use crate::abi::Abi; +use rustc_session::config::{self, CFGuard, DebugInfo}; +use rustc_session::Session; use rustc_span::source_map::{Span, DUMMY_SP}; use rustc_span::symbol::Symbol; +use rustc_target::spec::{HasTargetSpec, Target}; + use std::cell::{Cell, RefCell}; use std::ffi::CStr; -use std::iter; use std::str; use std::sync::Arc; @@ -87,7 +82,6 @@ pub struct CodegenCx<'ll, 'tcx> { pub dbg_cx: Option>, eh_personality: Cell>, - eh_unwind_resume: Cell>, pub rust_try_fn: Cell>, intrinsics: RefCell>, @@ -172,7 +166,7 @@ pub unsafe fn create_module( llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, tm); llvm::LLVMRustDisposeTargetMachine(tm); - let llvm_data_layout = llvm::LLVMGetDataLayout(llmod); + let llvm_data_layout = llvm::LLVMGetDataLayoutStr(llmod); let llvm_data_layout = str::from_utf8(CStr::from_ptr(llvm_data_layout).to_bytes()) .expect("got a non-UTF8 data-layout from LLVM"); @@ -327,7 +321,6 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { isize_ty, dbg_cx, eh_personality: Cell::new(None), - eh_unwind_resume: Cell::new(None), rust_try_fn: Cell::new(None), intrinsics: Default::default(), local_gen_sym_counter: Cell::new(0), @@ -405,45 +398,6 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { llfn } - // Returns a Value of the "eh_unwind_resume" lang item if one is defined, - // otherwise declares it as an external function. - fn eh_unwind_resume(&self) -> &'ll Value { - let unwresume = &self.eh_unwind_resume; - if let Some(llfn) = unwresume.get() { - return llfn; - } - - let tcx = self.tcx; - assert!(self.sess().target.target.options.custom_unwind_resume); - if let Some(def_id) = tcx.lang_items().eh_unwind_resume() { - let llfn = self.get_fn_addr( - ty::Instance::resolve( - tcx, - ty::ParamEnv::reveal_all(), - def_id, - tcx.intern_substs(&[]), - ) - .unwrap(), - ); - unwresume.set(Some(llfn)); - return llfn; - } - - let sig = ty::Binder::bind(tcx.mk_fn_sig( - iter::once(tcx.mk_mut_ptr(tcx.types.u8)), - tcx.types.never, - false, - Unsafety::Unsafe, - Abi::C, - )); - - let fn_abi = FnAbi::of_fn_ptr(self, sig, &[]); - let llfn = self.declare_fn("rust_eh_unwind_resume", &fn_abi); - attributes::apply_target_cpu_attr(self, llfn); - unwresume.set(Some(llfn)); - llfn - } - fn sess(&self) -> &Session { &self.tcx.sess } @@ -504,7 +458,7 @@ impl CodegenCx<'b, 'tcx> { self.type_variadic_func(&[], ret) }; let f = self.declare_cfn(name, fn_ty); - llvm::SetUnnamedAddr(f, false); + llvm::SetUnnamedAddress(f, llvm::UnnamedAddr::No); self.intrinsics.borrow_mut().insert(name, f); f } @@ -846,7 +800,7 @@ impl CodegenCx<'b, 'tcx> { ifn!("llvm.dbg.declare", fn(self.type_metadata(), self.type_metadata()) -> void); ifn!("llvm.dbg.value", fn(self.type_metadata(), t_i64, self.type_metadata()) -> void); } - return None; + None } } diff --git a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs b/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs index cdb9657e1ff3c..13a36c36a309a 100644 --- a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs +++ b/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs @@ -1,15 +1,13 @@ -use super::metadata::file_metadata; -use super::utils::{span_start, DIB}; +use super::metadata::{file_metadata, UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER}; +use super::utils::DIB; use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext}; +use rustc_codegen_ssa::traits::*; use crate::common::CodegenCx; use crate::llvm; use crate::llvm::debuginfo::{DIScope, DISubprogram}; use rustc::mir::{Body, SourceScope}; - -use libc::c_uint; - -use rustc_span::Pos; +use rustc_session::config::DebugInfo; use rustc_index::bit_set::BitSet; use rustc_index::vec::Idx; @@ -23,10 +21,17 @@ pub fn compute_mir_scopes( ) { // Find all the scopes with variables defined in them. let mut has_variables = BitSet::new_empty(mir.source_scopes.len()); - // FIXME(eddyb) take into account that arguments always have debuginfo, - // irrespective of their name (assuming full debuginfo is enabled). - for var_debug_info in &mir.var_debug_info { - has_variables.insert(var_debug_info.source_info.scope); + + // Only consider variables when they're going to be emitted. + // FIXME(eddyb) don't even allocate `has_variables` otherwise. + if cx.sess().opts.debuginfo == DebugInfo::Full { + // FIXME(eddyb) take into account that arguments always have debuginfo, + // irrespective of their name (assuming full debuginfo is enabled). + // NOTE(eddyb) actually, on second thought, those are always in the + // function scope, which always exists. + for var_debug_info in &mir.var_debug_info { + has_variables.insert(var_debug_info.source_info.scope); + } } // Instantiate all scopes. @@ -54,7 +59,7 @@ fn make_mir_scope( debug_context.scopes[parent] } else { // The root is the function itself. - let loc = span_start(cx, mir.span); + let loc = cx.lookup_debug_loc(mir.span.lo()); debug_context.scopes[scope] = DebugScope { scope_metadata: Some(fn_metadata), file_start_pos: loc.file.start_pos, @@ -70,7 +75,7 @@ fn make_mir_scope( return; } - let loc = span_start(cx, scope_data.span); + let loc = cx.lookup_debug_loc(scope_data.span.lo()); let file_metadata = file_metadata(cx, &loc.file.name, debug_context.defining_crate); let scope_metadata = unsafe { @@ -78,8 +83,8 @@ fn make_mir_scope( DIB(cx), parent_scope.scope_metadata.unwrap(), file_metadata, - loc.line as c_uint, - loc.col.to_usize() as c_uint, + loc.line.unwrap_or(UNKNOWN_LINE_NUMBER), + loc.col.unwrap_or(UNKNOWN_COLUMN_NUMBER), )) }; debug_context.scopes[scope] = DebugScope { diff --git a/src/librustc_codegen_llvm/debuginfo/gdb.rs b/src/librustc_codegen_llvm/debuginfo/gdb.rs index 753a4e18faf5e..dccd287a2e38c 100644 --- a/src/librustc_codegen_llvm/debuginfo/gdb.rs +++ b/src/librustc_codegen_llvm/debuginfo/gdb.rs @@ -6,8 +6,8 @@ use crate::builder::Builder; use crate::common::CodegenCx; use crate::value::Value; use rustc::bug; -use rustc::session::config::DebugInfo; use rustc_codegen_ssa::traits::*; +use rustc_session::config::DebugInfo; use rustc_ast::attr; use rustc_span::symbol::sym; @@ -50,7 +50,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx<'ll, '_>) - llvm::LLVMSetSection(section_var, section_name.as_ptr().cast()); llvm::LLVMSetInitializer(section_var, cx.const_bytes(section_contents)); llvm::LLVMSetGlobalConstant(section_var, llvm::True); - llvm::LLVMSetUnnamedAddr(section_var, llvm::True); + llvm::LLVMSetUnnamedAddress(section_var, llvm::UnnamedAddr::Global); llvm::LLVMRustSetLinkage(section_var, llvm::Linkage::LinkOnceODRLinkage); // This should make sure that the whole section is not larger than // the string it contains. Otherwise we get a warning from GDB. diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 46c4a51111432..d7a0acb133956 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -5,7 +5,7 @@ use self::RecursiveTypeDescription::*; use super::namespace::mangled_name_of_instance; use super::type_names::compute_debuginfo_type_name; use super::utils::{ - create_DIArray, debug_context, get_namespace_for_item, is_node_local_to_unit, span_start, DIB, + create_DIArray, debug_context, get_namespace_for_item, is_node_local_to_unit, DIB, }; use super::CrateDebugContext; @@ -24,7 +24,6 @@ use rustc::ich::NodeIdHashingMode; use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc::mir::interpret::truncate; use rustc::mir::{self, Field, GeneratorLayout}; -use rustc::session::config::{self, DebugInfo}; use rustc::ty::layout::{ self, Align, Integer, IntegerExt, LayoutOf, PrimitiveExt, Size, TyLayout, VariantIdx, }; @@ -42,6 +41,7 @@ use rustc_fs_util::path_to_c_string; use rustc_hir::def::CtorKind; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_index::vec::{Idx, IndexVec}; +use rustc_session::config::{self, DebugInfo}; use rustc_span::symbol::{Interner, Symbol}; use rustc_span::{self, FileName, Span}; use rustc_target::abi::HasDataLayout; @@ -203,7 +203,7 @@ impl TypeMap<'ll, 'tcx> { let key = self.unique_id_interner.intern(&unique_type_id); self.type_to_unique_id.insert(type_, UniqueTypeId(key)); - return UniqueTypeId(key); + UniqueTypeId(key) } /// Gets the `UniqueTypeId` for an enum variant. Enum variants are not really @@ -314,7 +314,7 @@ impl RecursiveTypeDescription<'ll, 'tcx> { member_holding_stub, member_descriptions, ); - return MetadataCreationResult::new(metadata_stub, true); + MetadataCreationResult::new(metadata_stub, true) } } } @@ -364,7 +364,7 @@ fn fixed_vec_metadata( ) }; - return MetadataCreationResult::new(metadata, false); + MetadataCreationResult::new(metadata, false) } fn vec_slice_metadata( @@ -445,7 +445,7 @@ fn subroutine_type_metadata( return_if_metadata_created_in_meantime!(cx, unique_type_id); - return MetadataCreationResult::new( + MetadataCreationResult::new( unsafe { llvm::LLVMRustDIBuilderCreateSubroutineType( DIB(cx), @@ -454,7 +454,7 @@ fn subroutine_type_metadata( ) }, false, - ); + ) } // FIXME(1563): This is all a bit of a hack because 'trait pointer' is an ill- @@ -663,7 +663,7 @@ pub fn type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>, usage_site_span: Sp MetadataCreationResult::new(pointer_type_metadata(cx, t, fn_metadata), false) } ty::Closure(def_id, substs) => { - let upvar_tys: Vec<_> = substs.as_closure().upvar_tys(def_id, cx.tcx).collect(); + let upvar_tys: Vec<_> = substs.as_closure().upvar_tys().collect(); let containing_scope = get_namespace_for_item(cx, def_id); prepare_tuple_metadata( cx, @@ -678,7 +678,7 @@ pub fn type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>, usage_site_span: Sp ty::Generator(def_id, substs, _) => { let upvar_tys: Vec<_> = substs .as_generator() - .prefix_tys(def_id, cx.tcx) + .prefix_tys() .map(|t| cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)) .collect(); prepare_enum_metadata(cx, t, def_id, unique_type_id, usage_site_span, upvar_tys) @@ -781,7 +781,7 @@ fn file_metadata_raw( let key = (file_name, directory); match debug_context(cx).created_files.borrow_mut().entry(key) { - Entry::Occupied(o) => return o.get(), + Entry::Occupied(o) => o.get(), Entry::Vacant(v) => { let (file_name, directory) = v.key(); debug!("file_metadata: file_name: {:?}, directory: {:?}", file_name, directory); @@ -831,7 +831,7 @@ fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { ) }; - return ty_metadata; + ty_metadata } fn foreign_type_metadata( @@ -1273,11 +1273,11 @@ fn prepare_union_metadata( fn use_enum_fallback(cx: &CodegenCx<'_, '_>) -> bool { // On MSVC we have to use the fallback mode, because LLVM doesn't // lower variant parts to PDB. - return cx.sess().target.target.options.is_like_msvc + cx.sess().target.target.options.is_like_msvc // LLVM version 7 did not release with an important bug fix; // but the required patch is in the LLVM 8. Rust LLVM reports // 8 as well. - || llvm_util::get_major_version() < 8; + || llvm_util::get_major_version() < 8 } // FIXME(eddyb) maybe precompute this? Right now it's computed once @@ -2075,7 +2075,7 @@ fn prepare_enum_metadata( } }; - return create_and_register_recursive_type_forward_declaration( + create_and_register_recursive_type_forward_declaration( cx, enum_type, unique_type_id, @@ -2088,7 +2088,7 @@ fn prepare_enum_metadata( containing_scope, span, }), - ); + ) } /// Creates debug information for a composite type, that is, anything that @@ -2299,6 +2299,11 @@ pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global return; } + // Only create type information if full debuginfo is enabled + if cx.sess().opts.debuginfo != DebugInfo::Full { + return; + } + let tcx = cx.tcx; let attrs = tcx.codegen_fn_attrs(def_id); @@ -2309,10 +2314,10 @@ pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global let span = tcx.def_span(def_id); let (file_metadata, line_number) = if !span.is_dummy() { - let loc = span_start(cx, span); - (file_metadata(cx, &loc.file.name, LOCAL_CRATE), loc.line as c_uint) + let loc = cx.lookup_debug_loc(span.lo()); + (file_metadata(cx, &loc.file.name, LOCAL_CRATE), loc.line) } else { - (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) + (unknown_file_metadata(cx), None) }; let is_local_to_unit = is_node_local_to_unit(cx, def_id); @@ -2339,7 +2344,7 @@ pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global linkage_name.as_ptr().cast(), linkage_name.len(), file_metadata, - line_number, + line_number.unwrap_or(UNKNOWN_LINE_NUMBER), type_metadata, is_local_to_unit, global, @@ -2358,6 +2363,11 @@ pub fn create_vtable_metadata(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, vtable: & return; } + // Only create type information if full debuginfo is enabled + if cx.sess().opts.debuginfo != DebugInfo::Full { + return; + } + let type_metadata = type_metadata(cx, ty, rustc_span::DUMMY_SP); unsafe { diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index 8deab1be3d3a9..4b8140263f1f2 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -3,10 +3,10 @@ mod doc; use rustc_codegen_ssa::mir::debuginfo::VariableKind::*; -use self::metadata::{file_metadata, type_metadata, TypeMap}; +use self::metadata::{file_metadata, type_metadata, TypeMap, UNKNOWN_LINE_NUMBER}; use self::namespace::mangled_name_of_instance; use self::type_names::compute_debuginfo_type_name; -use self::utils::{create_DIArray, is_node_local_to_unit, span_start, DIB}; +use self::utils::{create_DIArray, is_node_local_to_unit, DIB}; use crate::llvm; use crate::llvm::debuginfo::{ @@ -20,12 +20,12 @@ use crate::builder::Builder; use crate::common::CodegenCx; use crate::value::Value; use rustc::mir; -use rustc::session::config::{self, DebugInfo}; use rustc::ty::{self, Instance, ParamEnv, Ty}; use rustc_codegen_ssa::debuginfo::type_names; use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_index::vec::IndexVec; +use rustc_session::config::{self, DebugInfo}; use libc::c_uint; use log::debug; @@ -248,7 +248,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { let def_id = instance.def_id(); let containing_scope = get_containing_scope(self, instance); - let loc = span_start(self, span); + let loc = self.lookup_debug_loc(span.lo()); let file_metadata = file_metadata(self, &loc.file.name, def_id.krate); let function_type_metadata = unsafe { @@ -304,9 +304,9 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { linkage_name.as_ptr().cast(), linkage_name.len(), file_metadata, - loc.line as c_uint, + loc.line.unwrap_or(UNKNOWN_LINE_NUMBER), function_type_metadata, - scope_line as c_uint, + scope_line.unwrap_or(UNKNOWN_LINE_NUMBER), flags, spflags, llfn, @@ -444,7 +444,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { vec![] }; - return create_DIArray(DIB(cx), &template_params[..]); + create_DIArray(DIB(cx), &template_params[..]) } fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec { @@ -475,7 +475,12 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { // so avoid methods on other types (e.g., `<*mut T>::null`). match impl_self_ty.kind { ty::Adt(def, ..) if !def.is_box() => { - Some(type_metadata(cx, impl_self_ty, rustc_span::DUMMY_SP)) + // Again, only create type information if full debuginfo is enabled + if cx.sess().opts.debuginfo == DebugInfo::Full { + Some(type_metadata(cx, impl_self_ty, rustc_span::DUMMY_SP)) + } else { + Some(namespace::item_namespace(cx, def.did)) + } } _ => None, } @@ -530,7 +535,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { variable_kind: VariableKind, span: Span, ) -> &'ll DIVariable { - let loc = span_start(self, span); + let loc = self.lookup_debug_loc(span.lo()); let file_metadata = file_metadata(self, &loc.file.name, dbg_context.defining_crate); let type_metadata = type_metadata(self, variable_type, span); @@ -550,7 +555,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { name.as_ptr().cast(), name.len(), file_metadata, - loc.line as c_uint, + loc.line.unwrap_or(UNKNOWN_LINE_NUMBER), type_metadata, true, DIFlags::FlagZero, diff --git a/src/librustc_codegen_llvm/debuginfo/namespace.rs b/src/librustc_codegen_llvm/debuginfo/namespace.rs index 55a3540809b48..4e507a569dcd1 100644 --- a/src/librustc_codegen_llvm/debuginfo/namespace.rs +++ b/src/librustc_codegen_llvm/debuginfo/namespace.rs @@ -6,8 +6,8 @@ use rustc::ty::{self, Instance}; use crate::common::CodegenCx; use crate::llvm; use crate::llvm::debuginfo::DIScope; -use rustc::hir::map::DefPathData; use rustc_hir::def_id::DefId; +use rustc_hir::definitions::DefPathData; pub fn mangled_name_of_instance<'a, 'tcx>( cx: &CodegenCx<'a, 'tcx>, diff --git a/src/librustc_codegen_llvm/debuginfo/source_loc.rs b/src/librustc_codegen_llvm/debuginfo/source_loc.rs index 1f871c7d207a4..66ae9d72c3e51 100644 --- a/src/librustc_codegen_llvm/debuginfo/source_loc.rs +++ b/src/librustc_codegen_llvm/debuginfo/source_loc.rs @@ -1,32 +1,58 @@ -use super::metadata::UNKNOWN_COLUMN_NUMBER; -use super::utils::{debug_context, span_start}; +use super::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER}; +use super::utils::debug_context; use crate::common::CodegenCx; use crate::llvm::debuginfo::DIScope; use crate::llvm::{self, Value}; use rustc_codegen_ssa::traits::*; -use libc::c_uint; -use rustc_span::{Pos, Span}; +use rustc_data_structures::sync::Lrc; +use rustc_span::{BytePos, Pos, SourceFile, SourceFileAndLine, Span}; + +/// A source code location used to generate debug information. +pub struct DebugLoc { + /// Information about the original source file. + pub file: Lrc, + /// The (1-based) line number. + pub line: Option, + /// The (1-based) column number. + pub col: Option, +} impl CodegenCx<'ll, '_> { - pub fn create_debug_loc(&self, scope: &'ll DIScope, span: Span) -> &'ll Value { - let loc = span_start(self, span); + /// Looks up debug source information about a `BytePos`. + pub fn lookup_debug_loc(&self, pos: BytePos) -> DebugLoc { + let (file, line, col) = match self.sess().source_map().lookup_line(pos) { + Ok(SourceFileAndLine { sf: file, line }) => { + let line_pos = file.line_begin_pos(pos); + + // Use 1-based indexing. + let line = (line + 1) as u32; + let col = (pos - line_pos).to_u32() + 1; + + (file, Some(line), Some(col)) + } + Err(file) => (file, None, None), + }; - // For MSVC, set the column number to zero. + // For MSVC, omit the column number. // Otherwise, emit it. This mimics clang behaviour. // See discussion in https://github.com/rust-lang/rust/issues/42921 - let col_used = if self.sess().target.target.options.is_like_msvc { - UNKNOWN_COLUMN_NUMBER + if self.sess().target.target.options.is_like_msvc { + DebugLoc { file, line, col: None } } else { - loc.col.to_usize() as c_uint - }; + DebugLoc { file, line, col } + } + } + + pub fn create_debug_loc(&self, scope: &'ll DIScope, span: Span) -> &'ll Value { + let DebugLoc { line, col, .. } = self.lookup_debug_loc(span.lo()); unsafe { llvm::LLVMRustDIBuilderCreateDebugLocation( debug_context(self).llcontext, - loc.line as c_uint, - col_used, + line.unwrap_or(UNKNOWN_LINE_NUMBER), + col.unwrap_or(UNKNOWN_COLUMN_NUMBER), scope, None, ) diff --git a/src/librustc_codegen_llvm/debuginfo/utils.rs b/src/librustc_codegen_llvm/debuginfo/utils.rs index 4e17387e057f9..b42d760a77345 100644 --- a/src/librustc_codegen_llvm/debuginfo/utils.rs +++ b/src/librustc_codegen_llvm/debuginfo/utils.rs @@ -9,9 +9,6 @@ use rustc_hir::def_id::DefId; use crate::common::CodegenCx; use crate::llvm; use crate::llvm::debuginfo::{DIArray, DIBuilder, DIDescriptor, DIScope}; -use rustc_codegen_ssa::traits::*; - -use rustc_span::Span; pub fn is_node_local_to_unit(cx: &CodegenCx<'_, '_>, def_id: DefId) -> bool { // The is_local_to_unit flag indicates whether a function is local to the @@ -27,14 +24,7 @@ pub fn is_node_local_to_unit(cx: &CodegenCx<'_, '_>, def_id: DefId) -> bool { #[allow(non_snake_case)] pub fn create_DIArray(builder: &DIBuilder<'ll>, arr: &[Option<&'ll DIDescriptor>]) -> &'ll DIArray { - return unsafe { - llvm::LLVMRustDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32) - }; -} - -/// Returns rustc_span::Loc corresponding to the beginning of the span -pub fn span_start(cx: &CodegenCx<'_, '_>, span: Span) -> rustc_span::Loc { - cx.sess().source_map().lookup_char_pos(span.lo()) + unsafe { llvm::LLVMRustDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32) } } #[inline] diff --git a/src/librustc_codegen_llvm/declare.rs b/src/librustc_codegen_llvm/declare.rs index fab6321186b2c..236f5bb1bfdfb 100644 --- a/src/librustc_codegen_llvm/declare.rs +++ b/src/librustc_codegen_llvm/declare.rs @@ -40,7 +40,7 @@ fn declare_raw_fn( llvm::SetFunctionCallConv(llfn, callconv); // Function addresses in Rust are never significant, allowing functions to // be merged. - llvm::SetUnnamedAddr(llfn, true); + llvm::SetUnnamedAddress(llfn, llvm::UnnamedAddr::Global); if cx.tcx.sess.opts.cg.no_redzone.unwrap_or(cx.tcx.sess.target.target.options.disable_redzone) { llvm::Attribute::NoRedZone.apply_llfn(Function, llfn); diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 1ae9d2a684131..bc25b9496d9b5 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -195,26 +195,8 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { .unwrap(); OperandRef::from_const(self, ty_name, ret_ty).immediate_or_packed_pair(self) } - "init" => { - let ty = substs.type_at(0); - if !self.layout_of(ty).is_zst() { - // Just zero out the stack slot. - // If we store a zero constant, LLVM will drown in vreg allocation for large - // data structures, and the generated code will be awful. (A telltale sign of - // this is large quantities of `mov [byte ptr foo],0` in the generated code.) - memset_intrinsic( - self, - false, - ty, - llresult, - self.const_u8(0), - self.const_usize(1), - ); - } - return; - } - // Effectively no-ops - "uninit" | "forget" => { + // Effectively no-op + "forget" => { return; } "offset" => { @@ -851,19 +833,21 @@ fn memset_intrinsic( fn try_intrinsic( bx: &mut Builder<'a, 'll, 'tcx>, - func: &'ll Value, + try_func: &'ll Value, data: &'ll Value, - local_ptr: &'ll Value, + catch_func: &'ll Value, dest: &'ll Value, ) { if bx.sess().no_landing_pads() { - bx.call(func, &[data], None); - let ptr_align = bx.tcx().data_layout.pointer_align.abi; - bx.store(bx.const_null(bx.type_i8p()), dest, ptr_align); + bx.call(try_func, &[data], None); + // Return 0 unconditionally from the intrinsic call; + // we can never unwind. + let ret_align = bx.tcx().data_layout.i32_align.abi; + bx.store(bx.const_i32(0), dest, ret_align); } else if wants_msvc_seh(bx.sess()) { - codegen_msvc_try(bx, func, data, local_ptr, dest); + codegen_msvc_try(bx, try_func, data, catch_func, dest); } else { - codegen_gnu_try(bx, func, data, local_ptr, dest); + codegen_gnu_try(bx, try_func, data, catch_func, dest); } } @@ -876,9 +860,9 @@ fn try_intrinsic( // as the old ones are still more optimized. fn codegen_msvc_try( bx: &mut Builder<'a, 'll, 'tcx>, - func: &'ll Value, + try_func: &'ll Value, data: &'ll Value, - local_ptr: &'ll Value, + catch_func: &'ll Value, dest: &'ll Value, ) { let llfn = get_rust_try_fn(bx, &mut |mut bx| { @@ -890,15 +874,15 @@ fn codegen_msvc_try( let mut catchpad = bx.build_sibling_block("catchpad"); let mut caught = bx.build_sibling_block("caught"); - let func = llvm::get_param(bx.llfn(), 0); + let try_func = llvm::get_param(bx.llfn(), 0); let data = llvm::get_param(bx.llfn(), 1); - let local_ptr = llvm::get_param(bx.llfn(), 2); + let catch_func = llvm::get_param(bx.llfn(), 2); // We're generating an IR snippet that looks like: // - // declare i32 @rust_try(%func, %data, %ptr) { - // %slot = alloca [2 x i64] - // invoke %func(%data) to label %normal unwind label %catchswitch + // declare i32 @rust_try(%try_func, %data, %catch_func) { + // %slot = alloca u8* + // invoke %try_func(%data) to label %normal unwind label %catchswitch // // normal: // ret i32 0 @@ -908,8 +892,8 @@ fn codegen_msvc_try( // // catchpad: // %tok = catchpad within %cs [%type_descriptor, 0, %slot] - // %ptr[0] = %slot[0] - // %ptr[1] = %slot[1] + // %ptr = load %slot + // call %catch_func(%data, %ptr) // catchret from %tok to label %caught // // caught: @@ -926,32 +910,57 @@ fn codegen_msvc_try( // ~rust_panic(); // // uint64_t x[2]; - // } + // }; // - // int bar(void (*foo)(void), uint64_t *ret) { + // int __rust_try( + // void (*try_func)(void*), + // void *data, + // void (*catch_func)(void*, void*) noexcept + // ) { // try { - // foo(); + // try_func(data); // return 0; // } catch(rust_panic& a) { - // ret[0] = a.x[0]; - // ret[1] = a.x[1]; - // a.x[0] = 0; + // catch_func(data, &a); // return 1; // } // } // // More information can be found in libstd's seh.rs implementation. - let i64_2 = bx.type_array(bx.type_i64(), 2); - let i64_2_ptr = bx.type_ptr_to(i64_2); let ptr_align = bx.tcx().data_layout.pointer_align.abi; - let slot = bx.alloca(i64_2_ptr, ptr_align); - bx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(), None); + let slot = bx.alloca(bx.type_i8p(), ptr_align); + bx.invoke(try_func, &[data], normal.llbb(), catchswitch.llbb(), None); normal.ret(bx.const_i32(0)); let cs = catchswitch.catch_switch(None, None, 1); catchswitch.add_handler(cs, catchpad.llbb()); + // We can't use the TypeDescriptor defined in libpanic_unwind because it + // might be in another DLL and the SEH encoding only supports specifying + // a TypeDescriptor from the current module. + // + // However this isn't an issue since the MSVC runtime uses string + // comparison on the type name to match TypeDescriptors rather than + // pointer equality. + // + // So instead we generate a new TypeDescriptor in each module that uses + // `try` and let the linker merge duplicate definitions in the same + // module. + // + // When modifying, make sure that the type_name string exactly matches + // the one used in src/libpanic_unwind/seh.rs. + let type_info_vtable = bx.declare_global("??_7type_info@@6B@", bx.type_i8p()); + let type_name = bx.const_bytes(b"rust_panic\0"); + let type_info = + bx.const_struct(&[type_info_vtable, bx.const_null(bx.type_i8p()), type_name], false); + let tydesc = bx.declare_global("__rust_panic_type_info", bx.val_ty(type_info)); + unsafe { + llvm::LLVMRustSetLinkage(tydesc, llvm::Linkage::LinkOnceODRLinkage); + llvm::SetUniqueComdat(bx.llmod, tydesc); + llvm::LLVMSetInitializer(tydesc, type_info); + } + // The flag value of 8 indicates that we are catching the exception by // reference instead of by value. We can't use catch by value because // that requires copying the exception object, which we don't support @@ -959,23 +968,9 @@ fn codegen_msvc_try( // // Source: MicrosoftCXXABI::getAddrOfCXXCatchHandlerType in clang let flags = bx.const_i32(8); - let tydesc = match bx.tcx().lang_items().eh_catch_typeinfo() { - Some(did) => bx.get_static(did), - None => bug!("eh_catch_typeinfo not defined, but needed for SEH unwinding"), - }; let funclet = catchpad.catch_pad(cs, &[tydesc, flags, slot]); - - let i64_align = bx.tcx().data_layout.i64_align.abi; - let payload_ptr = catchpad.load(slot, ptr_align); - let payload = catchpad.load(payload_ptr, i64_align); - let local_ptr = catchpad.bitcast(local_ptr, bx.type_ptr_to(i64_2)); - catchpad.store(payload, local_ptr, i64_align); - - // Clear the first word of the exception so avoid double-dropping it. - // This will be read by the destructor which is implicitly called at the - // end of the catch block by the runtime. - let payload_0_ptr = catchpad.inbounds_gep(payload_ptr, &[bx.const_i32(0), bx.const_i32(0)]); - catchpad.store(bx.const_u64(0), payload_0_ptr, i64_align); + let ptr = catchpad.load(slot, ptr_align); + catchpad.call(catch_func, &[data, ptr], Some(&funclet)); catchpad.catch_ret(&funclet, caught.llbb()); @@ -984,7 +979,7 @@ fn codegen_msvc_try( // Note that no invoke is used here because by definition this function // can't panic (that's what it's catching). - let ret = bx.call(llfn, &[func, data, local_ptr], None); + let ret = bx.call(llfn, &[try_func, data, catch_func], None); let i32_align = bx.tcx().data_layout.i32_align.abi; bx.store(ret, dest, i32_align); } @@ -1002,38 +997,34 @@ fn codegen_msvc_try( // the right personality function. fn codegen_gnu_try( bx: &mut Builder<'a, 'll, 'tcx>, - func: &'ll Value, + try_func: &'ll Value, data: &'ll Value, - local_ptr: &'ll Value, + catch_func: &'ll Value, dest: &'ll Value, ) { let llfn = get_rust_try_fn(bx, &mut |mut bx| { // Codegens the shims described above: // // bx: - // invoke %func(%args...) normal %normal unwind %catch + // invoke %try_func(%data) normal %normal unwind %catch // // normal: // ret 0 // // catch: - // (ptr, _) = landingpad - // store ptr, %local_ptr + // (%ptr, _) = landingpad + // call %catch_func(%data, %ptr) // ret 1 - // - // Note that the `local_ptr` data passed into the `try` intrinsic is - // expected to be `*mut *mut u8` for this to actually work, but that's - // managed by the standard library. bx.sideeffect(); let mut then = bx.build_sibling_block("then"); let mut catch = bx.build_sibling_block("catch"); - let func = llvm::get_param(bx.llfn(), 0); + let try_func = llvm::get_param(bx.llfn(), 0); let data = llvm::get_param(bx.llfn(), 1); - let local_ptr = llvm::get_param(bx.llfn(), 2); - bx.invoke(func, &[data], then.llbb(), catch.llbb(), None); + let catch_func = llvm::get_param(bx.llfn(), 2); + bx.invoke(try_func, &[data], then.llbb(), catch.llbb(), None); then.ret(bx.const_i32(0)); // Type indicator for the exception being thrown. @@ -1053,15 +1044,13 @@ fn codegen_gnu_try( }; catch.add_clause(vals, tydesc); let ptr = catch.extract_value(vals, 0); - let ptr_align = bx.tcx().data_layout.pointer_align.abi; - let bitcast = catch.bitcast(local_ptr, bx.type_ptr_to(bx.type_i8p())); - catch.store(ptr, bitcast, ptr_align); + catch.call(catch_func, &[data, ptr], None); catch.ret(bx.const_i32(1)); }); // Note that no invoke is used here because by definition this function // can't panic (that's what it's catching). - let ret = bx.call(llfn, &[func, data, local_ptr], None); + let ret = bx.call(llfn, &[try_func, data, catch_func], None); let i32_align = bx.tcx().data_layout.i32_align.abi; bx.store(ret, dest, i32_align); } @@ -1084,6 +1073,8 @@ fn gen_fn<'ll, 'tcx>( )); let fn_abi = FnAbi::of_fn_ptr(cx, rust_fn_sig, &[]); let llfn = cx.declare_fn(name, &fn_abi); + cx.set_frame_pointer_elimination(llfn); + cx.apply_target_cpu_attr(llfn); // FIXME(eddyb) find a nicer way to do this. unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) }; let bx = Builder::new_block(cx, llfn, "entry-block"); @@ -1106,15 +1097,22 @@ fn get_rust_try_fn<'ll, 'tcx>( // Define the type up front for the signature of the rust_try function. let tcx = cx.tcx; let i8p = tcx.mk_mut_ptr(tcx.types.i8); - let fn_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig( + let try_fn_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig( iter::once(i8p), tcx.mk_unit(), false, hir::Unsafety::Unsafe, Abi::Rust, ))); + let catch_fn_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig( + [i8p, i8p].iter().cloned(), + tcx.mk_unit(), + false, + hir::Unsafety::Unsafe, + Abi::Rust, + ))); let output = tcx.types.i32; - let rust_try = gen_fn(cx, "__rust_try", vec![fn_ty, i8p, i8p], output, codegen); + let rust_try = gen_fn(cx, "__rust_try", vec![try_fn_ty, i8p, catch_fn_ty], output, codegen); cx.rust_try_fn.set(Some(rust_try)); rust_try } @@ -1174,8 +1172,8 @@ fn generic_simd_intrinsic( let m_len = match in_ty.kind { // Note that this `.unwrap()` crashes for isize/usize, that's sort // of intentional as there's not currently a use case for that. - ty::Int(i) => i.bit_width().unwrap() as u64, - ty::Uint(i) => i.bit_width().unwrap() as u64, + ty::Int(i) => i.bit_width().unwrap(), + ty::Uint(i) => i.bit_width().unwrap(), _ => return_error!("`{}` is not an integral type", in_ty), }; require_simd!(arg_tys[1], "argument"); @@ -1356,20 +1354,18 @@ fn generic_simd_intrinsic( // trailing bits. let expected_int_bits = in_len.max(8); match ret_ty.kind { - ty::Uint(i) if i.bit_width() == Some(expected_int_bits as usize) => (), + ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => (), _ => return_error!("bitmask `{}`, expected `u{}`", ret_ty, expected_int_bits), } // Integer vector : let (i_xn, in_elem_bitwidth) = match in_elem.kind { - ty::Int(i) => ( - args[0].immediate(), - i.bit_width().unwrap_or(bx.data_layout().pointer_size.bits() as _), - ), - ty::Uint(i) => ( - args[0].immediate(), - i.bit_width().unwrap_or(bx.data_layout().pointer_size.bits() as _), - ), + ty::Int(i) => { + (args[0].immediate(), i.bit_width().unwrap_or(bx.data_layout().pointer_size.bits())) + } + ty::Uint(i) => { + (args[0].immediate(), i.bit_width().unwrap_or(bx.data_layout().pointer_size.bits())) + } _ => return_error!( "vector argument `{}`'s element type `{}`, expected integer element type", in_ty, @@ -1380,16 +1376,16 @@ fn generic_simd_intrinsic( // Shift the MSB to the right by "in_elem_bitwidth - 1" into the first bit position. let shift_indices = vec![ - bx.cx.const_int(bx.type_ix(in_elem_bitwidth as _), (in_elem_bitwidth - 1) as _); + bx.cx.const_int(bx.type_ix(in_elem_bitwidth), (in_elem_bitwidth - 1) as _); in_len as _ ]; let i_xn_msb = bx.lshr(i_xn, bx.const_vector(shift_indices.as_slice())); // Truncate vector to an - let i1xn = bx.trunc(i_xn_msb, bx.type_vector(bx.type_i1(), in_len as _)); + let i1xn = bx.trunc(i_xn_msb, bx.type_vector(bx.type_i1(), in_len)); // Bitcast to iN: - let i_ = bx.bitcast(i1xn, bx.type_ix(in_len as _)); + let i_ = bx.bitcast(i1xn, bx.type_ix(in_len)); // Zero-extend iN to the bitmask type: - return Ok(bx.zext(i_, bx.type_ix(expected_int_bits as _))); + return Ok(bx.zext(i_, bx.type_ix(expected_int_bits))); } fn simd_simple_float_intrinsic( @@ -1664,7 +1660,7 @@ fn generic_simd_intrinsic( llvm_elem_vec_ty, ), ); - llvm::SetUnnamedAddr(f, false); + llvm::SetUnnamedAddress(f, llvm::UnnamedAddr::No); let v = bx.call(f, &[args[1].immediate(), alignment, mask, args[0].immediate()], None); return Ok(v); } @@ -1786,7 +1782,7 @@ fn generic_simd_intrinsic( &llvm_intrinsic, bx.type_func(&[llvm_elem_vec_ty, llvm_pointer_vec_ty, alignment_ty, mask_ty], ret_t), ); - llvm::SetUnnamedAddr(f, false); + llvm::SetUnnamedAddress(f, llvm::UnnamedAddr::No); let v = bx.call(f, &[args[0].immediate(), args[1].immediate(), alignment, mask], None); return Ok(v); } @@ -2085,7 +2081,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, let vec_ty = bx.cx.type_vector(elem_ty, in_len as u64); let f = bx.declare_cfn(&llvm_intrinsic, bx.type_func(&[vec_ty, vec_ty], vec_ty)); - llvm::SetUnnamedAddr(f, false); + llvm::SetUnnamedAddress(f, llvm::UnnamedAddr::No); let v = bx.call(f, &[lhs, rhs], None); return Ok(v); } @@ -2101,7 +2097,7 @@ fn int_type_width_signed(ty: Ty<'_>, cx: &CodegenCx<'_, '_>) -> Option<(u64, boo match ty.kind { ty::Int(t) => Some(( match t { - ast::IntTy::Isize => cx.tcx.sess.target.ptr_width as u64, + ast::IntTy::Isize => u64::from(cx.tcx.sess.target.ptr_width), ast::IntTy::I8 => 8, ast::IntTy::I16 => 16, ast::IntTy::I32 => 32, @@ -2112,7 +2108,7 @@ fn int_type_width_signed(ty: Ty<'_>, cx: &CodegenCx<'_, '_>) -> Option<(u64, boo )), ty::Uint(t) => Some(( match t { - ast::UintTy::Usize => cx.tcx.sess.target.ptr_width as u64, + ast::UintTy::Usize => u64::from(cx.tcx.sess.target.ptr_width), ast::UintTy::U8 => 8, ast::UintTy::U16 => 16, ast::UintTy::U32 => 32, @@ -2129,7 +2125,7 @@ fn int_type_width_signed(ty: Ty<'_>, cx: &CodegenCx<'_, '_>) -> Option<(u64, boo // Returns None if the type is not a float fn float_type_width(ty: Ty<'_>) -> Option { match ty.kind { - ty::Float(t) => Some(t.bit_width() as u64), + ty::Float(t) => Some(t.bit_width()), _ => None, } } diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index f32657545745f..e36c80e15a5e0 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -15,31 +15,29 @@ #![recursion_limit = "256"] use back::write::{create_informational_target_machine, create_target_machine}; -use rustc_span::symbol::Symbol; pub use llvm_util::target_features; -use rustc::dep_graph::WorkProduct; +use rustc::dep_graph::{DepGraph, WorkProduct}; +use rustc::middle::cstore::{EncodedMetadata, MetadataLoaderDyn}; +use rustc::ty::{self, TyCtxt}; +use rustc::util::common::ErrorReported; use rustc_ast::expand::allocator::AllocatorKind; use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule}; use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, ModuleConfig}; use rustc_codegen_ssa::traits::*; +use rustc_codegen_ssa::ModuleCodegen; use rustc_codegen_ssa::{CodegenResults, CompiledModule}; use rustc_errors::{FatalError, Handler}; +use rustc_serialize::json; +use rustc_session::config::{self, OptLevel, OutputFilenames, PrintRequest}; +use rustc_session::Session; +use rustc_span::symbol::Symbol; + use std::any::Any; use std::ffi::CStr; use std::fs; use std::sync::Arc; -use rustc::dep_graph::DepGraph; -use rustc::middle::cstore::{EncodedMetadata, MetadataLoaderDyn}; -use rustc::session::config::{self, OptLevel, OutputFilenames, PrintRequest}; -use rustc::session::Session; -use rustc::ty::{self, TyCtxt}; -use rustc::util::common::ErrorReported; -use rustc_codegen_ssa::ModuleCodegen; -use rustc_codegen_utils::codegen_backend::CodegenBackend; -use rustc_serialize::json; - mod back { pub mod archive; pub mod bytecode; diff --git a/src/librustc_codegen_llvm/llvm/archive_ro.rs b/src/librustc_codegen_llvm/llvm/archive_ro.rs index ab9df4162472c..64db4f7462df8 100644 --- a/src/librustc_codegen_llvm/llvm/archive_ro.rs +++ b/src/librustc_codegen_llvm/llvm/archive_ro.rs @@ -27,13 +27,13 @@ impl ArchiveRO { /// If this archive is used with a mutable method, then an error will be /// raised. pub fn open(dst: &Path) -> Result { - return unsafe { + unsafe { let s = path_to_c_string(dst); let ar = super::LLVMRustOpenArchive(s.as_ptr()).ok_or_else(|| { super::last_error().unwrap_or_else(|| "failed to open archive".to_owned()) })?; Ok(ArchiveRO { raw: ar }) - }; + } } pub fn iter(&self) -> Iter<'_> { diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 388b6c7483958..69881e2149bc4 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -73,6 +73,14 @@ pub enum Visibility { Protected = 2, } +/// LLVMUnnamedAddr +#[repr(C)] +pub enum UnnamedAddr { + No, + Local, + Global, +} + /// LLVMDLLStorageClass #[derive(Copy, Clone)] #[repr(C)] @@ -694,8 +702,8 @@ pub mod debuginfo { } impl DebugEmissionKind { - pub fn from_generic(kind: rustc::session::config::DebugInfo) -> Self { - use rustc::session::config::DebugInfo; + pub fn from_generic(kind: rustc_session::config::DebugInfo) -> Self { + use rustc_session::config::DebugInfo; match kind { DebugInfo::None => DebugEmissionKind::NoDebug, DebugInfo::Limited => DebugEmissionKind::LineTablesOnly, @@ -727,11 +735,11 @@ extern "C" { pub fn LLVMCloneModule(M: &Module) -> &Module; /// Data layout. See Module::getDataLayout. - pub fn LLVMGetDataLayout(M: &Module) -> *const c_char; + pub fn LLVMGetDataLayoutStr(M: &Module) -> *const c_char; pub fn LLVMSetDataLayout(M: &Module, Triple: *const c_char); /// See Module::setModuleInlineAsm. - pub fn LLVMSetModuleInlineAsm(M: &Module, Asm: *const c_char); + pub fn LLVMSetModuleInlineAsm2(M: &Module, Asm: *const c_char, AsmLen: size_t); pub fn LLVMRustAppendModuleInlineAsm(M: &Module, Asm: *const c_char, AsmLen: size_t); /// See llvm::LLVMTypeKind::getTypeID. @@ -1853,7 +1861,7 @@ extern "C" { UniqueIdLen: size_t, ) -> &'a DIDerivedType; - pub fn LLVMSetUnnamedAddr(GlobalVar: &Value, UnnamedAddr: Bool); + pub fn LLVMSetUnnamedAddress(Global: &Value, UnnamedAddr: UnnamedAddr); pub fn LLVMRustDIBuilderCreateTemplateTypeParameter( Builder: &DIBuilder<'a>, diff --git a/src/librustc_codegen_llvm/llvm/mod.rs b/src/librustc_codegen_llvm/llvm/mod.rs index 96014cbee5da1..b7f1e1789c9e2 100644 --- a/src/librustc_codegen_llvm/llvm/mod.rs +++ b/src/librustc_codegen_llvm/llvm/mod.rs @@ -106,9 +106,9 @@ pub fn UnsetComdat(val: &'a Value) { } } -pub fn SetUnnamedAddr(global: &'a Value, unnamed: bool) { +pub fn SetUnnamedAddress(global: &'a Value, unnamed: UnnamedAddr) { unsafe { - LLVMSetUnnamedAddr(global, unnamed as Bool); + LLVMSetUnnamedAddress(global, unnamed); } } @@ -185,12 +185,12 @@ impl Drop for SectionIter<'a> { } } -pub fn mk_section_iter(llof: &'a ffi::ObjectFile) -> SectionIter<'a> { +pub fn mk_section_iter(llof: &ffi::ObjectFile) -> SectionIter<'_> { unsafe { SectionIter { llsi: LLVMGetSections(llof) } } } /// Safe wrapper around `LLVMGetParam`, because segfaults are no fun. -pub fn get_param(llfn: &'a Value, index: c_uint) -> &'a Value { +pub fn get_param(llfn: &Value, index: c_uint) -> &Value { unsafe { assert!( index < LLVMCountParams(llfn), @@ -203,7 +203,7 @@ pub fn get_param(llfn: &'a Value, index: c_uint) -> &'a Value { } /// Safe wrapper for `LLVMGetValueName2` into a byte slice -pub fn get_value_name(value: &'a Value) -> &'a [u8] { +pub fn get_value_name(value: &Value) -> &[u8] { unsafe { let mut len = 0; let data = LLVMGetValueName2(value, &mut len); diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index 0081a75a4da11..2ccc861ddbb42 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -2,10 +2,10 @@ use crate::back::write::create_informational_target_machine; use crate::llvm; use libc::c_int; use rustc::bug; -use rustc::session::config::PrintRequest; -use rustc::session::Session; use rustc_data_structures::fx::FxHashSet; use rustc_feature::UnstableFeatures; +use rustc_session::config::PrintRequest; +use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::symbol::Symbol; use rustc_target::spec::{MergeFunctions, PanicStrategy}; @@ -80,8 +80,7 @@ unsafe fn configure_llvm(sess: &Session) { if sess.print_llvm_passes() { add("-debug-pass=Structure", false); } - - if sess.opts.debugging_opts.generate_arange_section { + if !sess.opts.debugging_opts.no_generate_arange_section { add("-generate-arange-section", false); } if get_major_version() >= 8 { diff --git a/src/librustc_codegen_llvm/type_.rs b/src/librustc_codegen_llvm/type_.rs index aacaf130f9aa9..5bc1475df23a7 100644 --- a/src/librustc_codegen_llvm/type_.rs +++ b/src/librustc_codegen_llvm/type_.rs @@ -240,7 +240,7 @@ impl Type { unsafe { llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint) } } - pub fn i8p_llcx(llcx: &'ll llvm::Context) -> &'ll Type { + pub fn i8p_llcx(llcx: &llvm::Context) -> &Type { Type::i8_llcx(llcx).ptr_to() } diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml index 3181d568b013a..b4e3929eaa567 100644 --- a/src/librustc_codegen_ssa/Cargo.toml +++ b/src/librustc_codegen_ssa/Cargo.toml @@ -15,7 +15,7 @@ cc = "1.0.1" num_cpus = "1.0" memmap = "0.7" log = "0.4.5" -libc = "0.2.44" +libc = "0.2.50" jobserver = "0.1.11" tempfile = "3.1" @@ -25,7 +25,7 @@ rustc_span = { path = "../librustc_span" } rustc = { path = "../librustc" } rustc_apfloat = { path = "../librustc_apfloat" } rustc_attr = { path = "../librustc_attr" } -rustc_codegen_utils = { path = "../librustc_codegen_utils" } +rustc_symbol_mangling = { path = "../librustc_symbol_mangling" } rustc_data_structures = { path = "../librustc_data_structures"} rustc_errors = { path = "../librustc_errors" } rustc_fs_util = { path = "../librustc_fs_util" } @@ -34,3 +34,4 @@ rustc_incremental = { path = "../librustc_incremental" } rustc_index = { path = "../librustc_index" } rustc_target = { path = "../librustc_target" } rustc_session = { path = "../librustc_session" } +rustc_metadata = { path = "../librustc_metadata" } diff --git a/src/librustc_codegen_ssa/back/archive.rs b/src/librustc_codegen_ssa/back/archive.rs index a357c350287fb..f83b4b2b0c025 100644 --- a/src/librustc_codegen_ssa/back/archive.rs +++ b/src/librustc_codegen_ssa/back/archive.rs @@ -1,4 +1,4 @@ -use rustc::session::Session; +use rustc_session::Session; use rustc_span::symbol::Symbol; use std::io; diff --git a/src/librustc_codegen_ssa/back/command.rs b/src/librustc_codegen_ssa/back/command.rs index 30b055b313149..0208bb73abdbe 100644 --- a/src/librustc_codegen_ssa/back/command.rs +++ b/src/librustc_codegen_ssa/back/command.rs @@ -119,7 +119,7 @@ impl Command { for k in &self.env_remove { ret.env_remove(k); } - return ret; + ret } // extensions diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 0dd2f029e8d32..a40d92476c466 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1,15 +1,16 @@ use rustc::middle::cstore::{EncodedMetadata, LibSource, NativeLibrary, NativeLibraryKind}; use rustc::middle::dependency_format::Linkage; -use rustc::session::config::{ +use rustc_data_structures::fx::FxHashSet; +use rustc_fs_util::fix_windows_verbatim_for_gcc; +use rustc_hir::def_id::CrateNum; +use rustc_session::config::{ self, CFGuard, DebugInfo, OutputFilenames, OutputType, PrintRequest, Sanitizer, }; -use rustc::session::search_paths::PathKind; +use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename}; +use rustc_session::search_paths::PathKind; /// For all the linkers we support, and information they might /// need out of the shared crate context before we get rid of it. -use rustc::session::{filesearch, Session}; -use rustc_data_structures::fx::FxHashSet; -use rustc_fs_util::fix_windows_verbatim_for_gcc; -use rustc_hir::def_id::CrateNum; +use rustc_session::{filesearch, Session}; use rustc_span::symbol::Symbol; use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel}; @@ -36,8 +37,6 @@ use std::path::{Path, PathBuf}; use std::process::{ExitStatus, Output, Stdio}; use std::str; -pub use rustc_codegen_utils::link::*; - pub fn remove(sess: &Session, path: &Path) { if let Err(e) = fs::remove_file(path) { sess.err(&format!("failed to remove {}: {}", path.display(), e)); @@ -490,6 +489,11 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( info!("preparing {:?} to {:?}", crate_type, out_filename); let (linker, flavor) = linker_and_flavor(sess); + let any_dynamic_crate = crate_type == config::CrateType::Dylib + || codegen_results.crate_info.dependency_formats.iter().any(|(ty, list)| { + *ty == crate_type && list.iter().any(|&linkage| linkage == Linkage::Dynamic) + }); + // The invocations of cc share some flags across platforms let (pname, mut cmd) = get_linker(sess, &linker, flavor); @@ -497,7 +501,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( cmd.args(args); } if let Some(args) = sess.target.target.options.pre_link_args_crt.get(&flavor) { - if sess.crt_static() { + if sess.crt_static(Some(crate_type)) { cmd.args(args); } } @@ -523,7 +527,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( cmd.arg(get_file_path(sess, obj)); } - if crate_type == config::CrateType::Executable && sess.crt_static() { + if crate_type == config::CrateType::Executable && sess.crt_static(Some(crate_type)) { for obj in &sess.target.target.options.pre_link_objects_exe_crt { cmd.arg(get_file_path(sess, obj)); } @@ -555,10 +559,19 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( if let Some(args) = sess.target.target.options.late_link_args.get(&flavor) { cmd.args(args); } + if any_dynamic_crate { + if let Some(args) = sess.target.target.options.late_link_args_dynamic.get(&flavor) { + cmd.args(args); + } + } else { + if let Some(args) = sess.target.target.options.late_link_args_static.get(&flavor) { + cmd.args(args); + } + } for obj in &sess.target.target.options.post_link_objects { cmd.arg(get_file_path(sess, obj)); } - if sess.crt_static() { + if sess.crt_static(Some(crate_type)) { for obj in &sess.target.target.options.post_link_objects_crt { cmd.arg(get_file_path(sess, obj)); } @@ -825,7 +838,13 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { "emcc" } } - LinkerFlavor::Gcc => "cc", + LinkerFlavor::Gcc => { + if cfg!(target_os = "solaris") { + "gcc" + } else { + "cc" + } + } LinkerFlavor::Ld => "ld", LinkerFlavor::Msvc => "link.exe", LinkerFlavor::Lld(_) => "lld", @@ -1288,7 +1307,8 @@ fn link_args<'a, B: ArchiveBuilder<'a>>( let more_args = &sess.opts.cg.link_arg; let mut args = args.iter().chain(more_args.iter()).chain(used_link_args.iter()); - if is_pic(sess) && !sess.crt_static() && !args.any(|x| *x == "-static") { + if is_pic(sess) && !sess.crt_static(Some(crate_type)) && !args.any(|x| *x == "-static") + { position_independent_executable = true; } } @@ -1373,7 +1393,7 @@ fn link_args<'a, B: ArchiveBuilder<'a>>( if crate_type != config::CrateType::Executable { cmd.build_dylib(out_filename); } - if crate_type == config::CrateType::Executable && sess.crt_static() { + if crate_type == config::CrateType::Executable && sess.crt_static(Some(crate_type)) { cmd.build_static_executable(); } diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs index 5aafb8a12d74b..6b30ae8559db9 100644 --- a/src/librustc_codegen_ssa/back/linker.rs +++ b/src/librustc_codegen_ssa/back/linker.rs @@ -2,7 +2,6 @@ use super::archive; use super::command::Command; use super::symbol_export; -use rustc_data_structures::fx::FxHashMap; use std::ffi::{OsStr, OsString}; use std::fs::{self, File}; use std::io::prelude::*; @@ -10,11 +9,12 @@ use std::io::{self, BufWriter}; use std::path::{Path, PathBuf}; use rustc::middle::dependency_format::Linkage; -use rustc::session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel}; -use rustc::session::Session; use rustc::ty::TyCtxt; +use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_serialize::{json, Encoder}; +use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel}; +use rustc_session::Session; use rustc_span::symbol::Symbol; use rustc_target::spec::{LinkerFlavor, LldFlavor}; diff --git a/src/librustc_codegen_ssa/back/rpath.rs b/src/librustc_codegen_ssa/back/rpath.rs index 9d19cc25a32bc..0a0e975e5a54c 100644 --- a/src/librustc_codegen_ssa/back/rpath.rs +++ b/src/librustc_codegen_ssa/back/rpath.rs @@ -81,9 +81,7 @@ fn get_rpaths(config: &mut RPathConfig<'_>, libs: &[PathBuf]) -> Vec { rpaths.extend_from_slice(&fallback_rpaths); // Remove duplicates - let rpaths = minimize_rpaths(&rpaths); - - rpaths + minimize_rpaths(&rpaths) } fn get_rpaths_relative_to_output(config: &mut RPathConfig<'_>, libs: &[PathBuf]) -> Vec { diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs index 3fe256ce25b96..8a2503ce16730 100644 --- a/src/librustc_codegen_ssa/back/symbol_export.rs +++ b/src/librustc_codegen_ssa/back/symbol_export.rs @@ -3,19 +3,18 @@ use std::sync::Arc; use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc::middle::exported_symbols::{metadata_symbol_name, ExportedSymbol, SymbolExportLevel}; -use rustc::session::config::{self, Sanitizer}; use rustc::ty::query::Providers; use rustc::ty::subst::{GenericArgKind, SubstsRef}; use rustc::ty::Instance; use rustc::ty::{SymbolName, TyCtxt}; use rustc_ast::expand::allocator::ALLOCATOR_METHODS; -use rustc_codegen_utils::symbol_names; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::Node; use rustc_index::vec::IndexVec; +use rustc_session::config::{self, Sanitizer}; pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel { crates_export_threshold(&tcx.sess.crate_types.borrow()) @@ -88,7 +87,7 @@ fn reachable_non_generics_provider( // Only consider nodes that actually have exported symbols. Node::Item(&hir::Item { kind: hir::ItemKind::Static(..), .. }) | Node::Item(&hir::Item { kind: hir::ItemKind::Fn(..), .. }) - | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Method(..), .. }) => { + | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => { let def_id = tcx.hir().local_def_id(hir_id); let generics = tcx.generics_of(def_id); if !generics.requires_monomorphization(tcx) && @@ -423,17 +422,21 @@ pub fn symbol_name_for_instance_in_crate<'tcx>( // 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::DropGlue(ty) => symbol_names::symbol_name_for_instance_in_crate( + ExportedSymbol::NonGeneric(def_id) => { + rustc_symbol_mangling::symbol_name_for_instance_in_crate( + tcx, + Instance::mono(tcx, def_id), + instantiating_crate, + ) + } + ExportedSymbol::Generic(def_id, substs) => { + rustc_symbol_mangling::symbol_name_for_instance_in_crate( + tcx, + Instance::new(def_id, substs), + instantiating_crate, + ) + } + ExportedSymbol::DropGlue(ty) => rustc_symbol_mangling::symbol_name_for_instance_in_crate( tcx, Instance::resolve_drop_in_place(tcx, ty), instantiating_crate, diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 3afa4758253d9..a4b5acdcd18a2 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -14,10 +14,6 @@ use jobserver::{Acquired, Client}; use rustc::dep_graph::{WorkProduct, WorkProductFileKind, WorkProductId}; use rustc::middle::cstore::EncodedMetadata; use rustc::middle::exported_symbols::SymbolExportLevel; -use rustc::session::config::{ - self, Lto, OutputFilenames, OutputType, Passes, Sanitizer, SwitchWithOptPath, -}; -use rustc::session::Session; use rustc::ty::TyCtxt; use rustc_ast::attr; use rustc_data_structures::fx::FxHashMap; @@ -34,6 +30,10 @@ use rustc_incremental::{ copy_cgu_workproducts_to_incr_comp_cache_dir, in_incr_comp_dir, in_incr_comp_dir_sess, }; use rustc_session::cgu_reuse_tracker::CguReuseTracker; +use rustc_session::config::{ + self, Lto, OutputFilenames, OutputType, Passes, Sanitizer, SwitchWithOptPath, +}; +use rustc_session::Session; use rustc_span::hygiene::ExpnId; use rustc_span::source_map::SourceMap; use rustc_span::symbol::{sym, Symbol}; @@ -51,6 +51,14 @@ use std::thread; const PRE_LTO_BC_EXT: &str = "pre-lto.bc"; +/// The kind of bitcode to embed in object files. +#[derive(PartialEq)] +pub enum EmbedBitcode { + None, + Marker, + Full, +} + /// Module-specific configuration for `optimize_and_codegen`. pub struct ModuleConfig { /// Names of additional optimization passes to run. @@ -74,7 +82,6 @@ pub struct ModuleConfig { pub emit_no_opt_bc: bool, pub emit_bc: bool, pub emit_bc_compressed: bool, - pub emit_lto_bc: bool, pub emit_ir: bool, pub emit_asm: bool, pub emit_obj: bool, @@ -94,8 +101,7 @@ pub struct ModuleConfig { // emscripten's ecc compiler, when used as the linker. pub obj_is_bitcode: bool, pub no_integrated_as: bool, - pub embed_bitcode: bool, - pub embed_bitcode_marker: bool, + pub embed_bitcode: EmbedBitcode, } impl ModuleConfig { @@ -116,13 +122,11 @@ impl ModuleConfig { emit_pre_lto_bc: false, emit_bc: false, emit_bc_compressed: false, - emit_lto_bc: false, emit_ir: false, emit_asm: false, emit_obj: false, obj_is_bitcode: false, - embed_bitcode: false, - embed_bitcode_marker: false, + embed_bitcode: EmbedBitcode::None, no_integrated_as: false, verify_llvm_ir: false, @@ -145,16 +149,15 @@ impl ModuleConfig { self.new_llvm_pass_manager = sess.opts.debugging_opts.new_llvm_pass_manager; self.obj_is_bitcode = sess.target.target.options.obj_is_bitcode || sess.opts.cg.linker_plugin_lto.enabled(); - let embed_bitcode = - sess.target.target.options.embed_bitcode || sess.opts.debugging_opts.embed_bitcode; - if embed_bitcode { - match sess.opts.optimize { - config::OptLevel::No | config::OptLevel::Less => { - self.embed_bitcode_marker = embed_bitcode; + self.embed_bitcode = + if sess.target.target.options.embed_bitcode || sess.opts.debugging_opts.embed_bitcode { + match sess.opts.optimize { + config::OptLevel::No | config::OptLevel::Less => EmbedBitcode::Marker, + _ => EmbedBitcode::Full, } - _ => self.embed_bitcode = embed_bitcode, - } - } + } else { + EmbedBitcode::None + }; // Copy what clang does by turning on loop vectorization at O2 and // slp vectorization at O3. Otherwise configure other optimization aspects @@ -190,7 +193,10 @@ impl ModuleConfig { } pub fn bitcode_needed(&self) -> bool { - self.emit_bc || self.obj_is_bitcode || self.emit_bc_compressed || self.embed_bitcode + self.emit_bc + || self.obj_is_bitcode + || self.emit_bc_compressed + || self.embed_bitcode == EmbedBitcode::Full } } @@ -288,7 +294,7 @@ fn generate_lto_work( B::run_thin_lto(cgcx, needs_thin_lto, import_only_modules).unwrap_or_else(|e| e.raise()) }; - let result = lto_modules + lto_modules .into_iter() .map(|module| { let cost = module.cost(); @@ -303,9 +309,7 @@ fn generate_lto_work( 0, ) })) - .collect(); - - result + .collect() } pub struct CompiledModules { @@ -341,9 +345,9 @@ pub fn start_async_codegen( let crate_name = tcx.crate_name(LOCAL_CRATE); let crate_hash = tcx.crate_hash(LOCAL_CRATE); - let no_builtins = attr::contains_name(&tcx.hir().krate().attrs, sym::no_builtins); + let no_builtins = attr::contains_name(&tcx.hir().krate().item.attrs, sym::no_builtins); let subsystem = - attr::first_attr_value_str_by_name(&tcx.hir().krate().attrs, sym::windows_subsystem); + attr::first_attr_value_str_by_name(&tcx.hir().krate().item.attrs, sym::windows_subsystem); let windows_subsystem = subsystem.map(|subsystem| { if subsystem != sym::windows && subsystem != sym::console { tcx.sess.fatal(&format!( @@ -381,7 +385,6 @@ pub fn start_async_codegen( modules_config.emit_no_opt_bc = true; modules_config.emit_pre_lto_bc = true; modules_config.emit_bc = true; - modules_config.emit_lto_bc = true; metadata_config.emit_bc = true; allocator_config.emit_bc = true; } diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index d6e1ab8909c59..834702a30099c 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -31,14 +31,11 @@ use rustc::middle::cstore::{self, LinkagePreference}; use rustc::middle::lang_items; use rustc::middle::lang_items::StartFnLangItem; use rustc::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem}; -use rustc::session::config::{self, EntryFnType, Lto}; -use rustc::session::Session; use rustc::ty::layout::{self, Align, HasTyCtxt, LayoutOf, TyLayout, VariantIdx}; use rustc::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA}; use rustc::ty::query::Providers; use rustc::ty::{self, Instance, Ty, TyCtxt}; use rustc_attr as attr; -use rustc_codegen_utils::{check_for_rustc_errors_attr, symbol_names_test}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::profiling::print_time_passes_entry; use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator}; @@ -46,7 +43,10 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_index::vec::Idx; use rustc_session::cgu_reuse_tracker::CguReuse; +use rustc_session::config::{self, EntryFnType, Lto}; +use rustc_session::Session; use rustc_span::Span; +use rustc_symbol_mangling::test as symbol_names_test; use std::cmp; use std::ops::{Deref, DerefMut}; @@ -514,8 +514,6 @@ pub fn codegen_crate( metadata: EncodedMetadata, need_metadata_module: bool, ) -> OngoingCodegen { - check_for_rustc_errors_attr(tcx); - // Skip crate items and just output metadata in -Z no-codegen mode. if tcx.sess.opts.debugging_opts.no_codegen || !tcx.sess.opts.output_types.should_codegen() { let ongoing_codegen = start_async_codegen(backend, tcx, metadata, 1); @@ -852,7 +850,7 @@ impl CrateInfo { info.missing_lang_items.insert(cnum, missing); } - return info; + info } } @@ -887,7 +885,7 @@ pub fn provide_both(providers: &mut Providers<'_>) { } } } - return tcx.sess.opts.optimize; + tcx.sess.opts.optimize }; providers.dllimport_foreign_items = |tcx, krate| { diff --git a/src/librustc_codegen_ssa/common.rs b/src/librustc_codegen_ssa/common.rs index 28b61e0b36d64..147b23995023f 100644 --- a/src/librustc_codegen_ssa/common.rs +++ b/src/librustc_codegen_ssa/common.rs @@ -1,8 +1,8 @@ #![allow(non_camel_case_types, non_snake_case)] -use rustc::session::Session; use rustc::ty::{Ty, TyCtxt}; use rustc_errors::struct_span_err; +use rustc_session::Session; use rustc_span::Span; use crate::base; diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs index a2bb39b9e4019..d2afbdc23e1fd 100644 --- a/src/librustc_codegen_ssa/lib.rs +++ b/src/librustc_codegen_ssa/lib.rs @@ -21,12 +21,12 @@ use rustc::dep_graph::WorkProduct; use rustc::middle::cstore::{CrateSource, LibSource, NativeLibrary}; use rustc::middle::dependency_format::Dependencies; use rustc::middle::lang_items::LangItem; -use rustc::session::config::{OutputFilenames, OutputType, RUST_CGU_EXT}; use rustc::ty::query::Providers; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::Lrc; use rustc_hir::def_id::CrateNum; +use rustc_session::config::{OutputFilenames, OutputType, RUST_CGU_EXT}; use rustc_span::symbol::Symbol; use std::path::{Path, PathBuf}; diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 9ce23ff5f3fc8..8433f79302077 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -178,15 +178,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let lp1 = bx.load_operand(lp1).immediate(); slot.storage_dead(&mut bx); - if !bx.sess().target.target.options.custom_unwind_resume { - let mut lp = bx.const_undef(self.landing_pad_type()); - lp = bx.insert_value(lp, lp0, 0); - lp = bx.insert_value(lp, lp1, 1); - bx.resume(lp); - } else { - bx.call(bx.eh_unwind_resume(), &[lp0], helper.funclet(self)); - bx.unreachable(); - } + let mut lp = bx.const_undef(self.landing_pad_type()); + lp = bx.insert_value(lp, lp0, 0); + lp = bx.insert_value(lp, lp1, 1); + bx.resume(lp); } } @@ -449,38 +444,38 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { destination: &Option<(mir::Place<'tcx>, mir::BasicBlock)>, cleanup: Option, ) -> bool { - // Emit a panic or a no-op for `panic_if_uninhabited`. + // Emit a panic or a no-op for `assert_*` intrinsics. // These are intrinsics that compile to panics so that we can get a message // which mentions the offending type, even from a const context. #[derive(Debug, PartialEq)] - enum PanicIntrinsic { - IfUninhabited, - IfZeroInvalid, - IfAnyInvalid, + enum AssertIntrinsic { + Inhabited, + ZeroValid, + UninitValid, }; let panic_intrinsic = intrinsic.and_then(|i| match i { // FIXME: Move to symbols instead of strings. - "panic_if_uninhabited" => Some(PanicIntrinsic::IfUninhabited), - "panic_if_zero_invalid" => Some(PanicIntrinsic::IfZeroInvalid), - "panic_if_any_invalid" => Some(PanicIntrinsic::IfAnyInvalid), + "assert_inhabited" => Some(AssertIntrinsic::Inhabited), + "assert_zero_valid" => Some(AssertIntrinsic::ZeroValid), + "assert_uninit_valid" => Some(AssertIntrinsic::UninitValid), _ => None, }); if let Some(intrinsic) = panic_intrinsic { - use PanicIntrinsic::*; + use AssertIntrinsic::*; let ty = instance.unwrap().substs.type_at(0); let layout = bx.layout_of(ty); let do_panic = match intrinsic { - IfUninhabited => layout.abi.is_uninhabited(), + Inhabited => layout.abi.is_uninhabited(), // We unwrap as the error type is `!`. - IfZeroInvalid => !layout.might_permit_raw_init(bx, /*zero:*/ true).unwrap(), + ZeroValid => !layout.might_permit_raw_init(bx, /*zero:*/ true).unwrap(), // We unwrap as the error type is `!`. - IfAnyInvalid => !layout.might_permit_raw_init(bx, /*zero:*/ false).unwrap(), + UninitValid => !layout.might_permit_raw_init(bx, /*zero:*/ false).unwrap(), }; if do_panic { let msg_str = if layout.abi.is_uninhabited() { // Use this error even for the other intrinsics as it is more precise. format!("attempted to instantiate uninhabited type `{}`", ty) - } else if intrinsic == IfZeroInvalid { + } else if intrinsic == ZeroValid { format!("attempted to zero-initialize type `{}`, which is invalid", ty) } else { format!("attempted to leave type `{}` uninitialized, which is invalid", ty) diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs index 4248627dccaf2..74a9646a0c0af 100644 --- a/src/librustc_codegen_ssa/mir/constant.rs +++ b/src/librustc_codegen_ssa/mir/constant.rs @@ -40,31 +40,26 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &mut self, constant: &mir::Constant<'tcx>, ) -> Result, ErrorHandled> { - match constant.literal.val { - ty::ConstKind::Unevaluated(def_id, substs, promoted) => { - let substs = self.monomorphize(&substs); - self.cx - .tcx() - .const_eval_resolve(ty::ParamEnv::reveal_all(), def_id, substs, promoted, None) - .map_err(|err| { - if promoted.is_none() { - self.cx - .tcx() - .sess - .span_err(constant.span, "erroneous constant encountered"); - } - err - }) - } + match self.monomorphize(&constant.literal).val { + ty::ConstKind::Unevaluated(def_id, substs, promoted) => self + .cx + .tcx() + .const_eval_resolve(ty::ParamEnv::reveal_all(), def_id, substs, promoted, None) + .map_err(|err| { + if promoted.is_none() { + self.cx + .tcx() + .sess + .span_err(constant.span, "erroneous constant encountered"); + } + err + }), ty::ConstKind::Value(value) => Ok(value), - _ => { - let const_ = self.monomorphize(&constant.literal); - if let ty::ConstKind::Value(value) = const_.val { - Ok(value) - } else { - span_bug!(constant.span, "encountered bad ConstKind in codegen: {:?}", const_); - } - } + err => span_bug!( + constant.span, + "encountered bad ConstKind after monomorphizing: {:?}", + err + ), } } diff --git a/src/librustc_codegen_ssa/mir/debuginfo.rs b/src/librustc_codegen_ssa/mir/debuginfo.rs index 2dc1405f4e438..cbe5f51115246 100644 --- a/src/librustc_codegen_ssa/mir/debuginfo.rs +++ b/src/librustc_codegen_ssa/mir/debuginfo.rs @@ -1,10 +1,10 @@ use crate::traits::*; use rustc::mir; -use rustc::session::config::DebugInfo; use rustc::ty; use rustc::ty::layout::{LayoutOf, Size}; use rustc_hir::def_id::CrateNum; use rustc_index::vec::IndexVec; +use rustc_session::config::DebugInfo; use rustc_span::symbol::{kw, Symbol}; use rustc_span::{BytePos, Span}; diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 64ead19b35869..000db0155ada3 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -86,13 +86,18 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn monomorphize(&self, value: &T) -> T where - T: TypeFoldable<'tcx>, + T: Copy + TypeFoldable<'tcx>, { - self.cx.tcx().subst_and_normalize_erasing_regions( - self.instance.substs, - ty::ParamEnv::reveal_all(), - value, - ) + debug!("monomorphize: self.instance={:?}", self.instance); + if let Some(substs) = self.instance.substs_for_mir_body() { + self.cx.tcx().subst_and_normalize_erasing_regions( + substs, + ty::ParamEnv::reveal_all(), + &value, + ) + } else { + self.cx.tcx().normalize_erasing_regions(ty::ParamEnv::reveal_all(), *value) + } } } diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index 1e1fede2588df..5bb30d03d9f8d 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -91,7 +91,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { }; let a = Scalar::from(Pointer::new( bx.tcx().alloc_map.lock().create_memory_alloc(data), - Size::from_bytes(start as u64), + Size::from_bytes(start), )); let a_llval = bx.scalar_to_backend( a, diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 6d0046063989b..880bce7fde487 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -106,6 +106,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } + let count = + self.monomorphize(&count).eval_usize(bx.cx().tcx(), ty::ParamEnv::reveal_all()); + bx.write_operand_repeatedly(cg_elem, count, dest) } @@ -293,7 +296,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if let Some(discr) = operand.layout.ty.discriminant_for_variant(bx.tcx(), index) { - let discr_val = bx.cx().const_uint_big(ll_t_out, discr.val); + let discr_layout = bx.cx().layout_of(discr.ty); + let discr_t = bx.cx().immediate_backend_type(discr_layout); + let discr_val = bx.cx().const_uint_big(discr_t, discr.val); + let discr_val = + bx.intcast(discr_val, ll_t_out, discr.ty.is_signed()); + return ( bx, OperandRef { diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs index 5535841156acd..4e861f45ff7a5 100644 --- a/src/librustc_codegen_ssa/traits/backend.rs +++ b/src/librustc_codegen_ssa/traits/backend.rs @@ -2,15 +2,22 @@ use super::write::WriteBackendMethods; use super::CodegenObject; use crate::ModuleCodegen; -use rustc::middle::cstore::EncodedMetadata; -use rustc::session::{config, Session}; +use rustc::dep_graph::DepGraph; +use rustc::middle::cstore::{EncodedMetadata, MetadataLoaderDyn}; use rustc::ty::layout::{HasTyCtxt, LayoutOf, TyLayout}; -use rustc::ty::Ty; -use rustc::ty::TyCtxt; +use rustc::ty::query::Providers; +use rustc::ty::{Ty, TyCtxt}; +use rustc::util::common::ErrorReported; use rustc_ast::expand::allocator::AllocatorKind; -use rustc_codegen_utils::codegen_backend::CodegenBackend; +use rustc_session::{ + config::{self, OutputFilenames, PrintRequest}, + Session, +}; use rustc_span::symbol::Symbol; +pub use rustc_data_structures::sync::MetadataRef; + +use std::any::Any; use std::sync::Arc; pub trait BackendTypes { @@ -37,6 +44,50 @@ impl<'tcx, T> Backend<'tcx> for T where { } +pub trait CodegenBackend { + fn init(&self, _sess: &Session) {} + fn print(&self, _req: PrintRequest, _sess: &Session) {} + fn target_features(&self, _sess: &Session) -> Vec { + vec![] + } + fn print_passes(&self) {} + fn print_version(&self) {} + + fn metadata_loader(&self) -> Box; + fn provide(&self, _providers: &mut Providers<'_>); + fn provide_extern(&self, _providers: &mut Providers<'_>); + fn codegen_crate<'tcx>( + &self, + tcx: TyCtxt<'tcx>, + metadata: EncodedMetadata, + need_metadata_module: bool, + ) -> Box; + + /// This is called on the returned `Box` from `codegen_backend` + /// + /// # Panics + /// + /// Panics when the passed `Box` was not returned by `codegen_backend`. + fn join_codegen( + &self, + ongoing_codegen: Box, + sess: &Session, + dep_graph: &DepGraph, + ) -> Result, ErrorReported>; + + /// This is called on the returned `Box` from `join_codegen` + /// + /// # Panics + /// + /// Panics when the passed `Box` was not returned by `join_codegen`. + fn link( + &self, + sess: &Session, + codegen_results: Box, + outputs: &OutputFilenames, + ) -> Result<(), ErrorReported>; +} + pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Send + Sync { fn new_metadata(&self, sess: TyCtxt<'_>, mod_name: &str) -> Self::Module; fn write_compressed_metadata<'tcx>( diff --git a/src/librustc_codegen_ssa/traits/misc.rs b/src/librustc_codegen_ssa/traits/misc.rs index 691b94c2f9d48..6863b474cb6de 100644 --- a/src/librustc_codegen_ssa/traits/misc.rs +++ b/src/librustc_codegen_ssa/traits/misc.rs @@ -1,8 +1,8 @@ use super::BackendTypes; use rustc::mir::mono::CodegenUnit; -use rustc::session::Session; use rustc::ty::{self, Instance, Ty}; use rustc_data_structures::fx::FxHashMap; +use rustc_session::Session; use std::cell::RefCell; use std::sync::Arc; @@ -14,7 +14,6 @@ pub trait MiscMethods<'tcx>: BackendTypes { fn get_fn(&self, instance: Instance<'tcx>) -> Self::Function; fn get_fn_addr(&self, instance: Instance<'tcx>) -> Self::Value; fn eh_personality(&self) -> Self::Value; - fn eh_unwind_resume(&self) -> Self::Value; fn sess(&self) -> &Session; fn codegen_unit(&self) -> &Arc>; fn used_statics(&self) -> &RefCell>; diff --git a/src/librustc_codegen_ssa/traits/mod.rs b/src/librustc_codegen_ssa/traits/mod.rs index d03ff8d4d37d8..1bc9f297ea1b1 100644 --- a/src/librustc_codegen_ssa/traits/mod.rs +++ b/src/librustc_codegen_ssa/traits/mod.rs @@ -29,7 +29,7 @@ mod write; pub use self::abi::AbiBuilderMethods; pub use self::asm::{AsmBuilderMethods, AsmMethods}; -pub use self::backend::{Backend, BackendTypes, ExtraBackendMethods}; +pub use self::backend::{Backend, BackendTypes, CodegenBackend, ExtraBackendMethods}; pub use self::builder::{BuilderMethods, OverflowOp}; pub use self::consts::ConstMethods; pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoMethods}; diff --git a/src/librustc_codegen_utils/codegen_backend.rs b/src/librustc_codegen_utils/codegen_backend.rs deleted file mode 100644 index 96166e04c2e3c..0000000000000 --- a/src/librustc_codegen_utils/codegen_backend.rs +++ /dev/null @@ -1,64 +0,0 @@ -//! The Rust compiler. -//! -//! # Note -//! -//! This API is completely unstable and subject to change. - -#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] - -use std::any::Any; - -use rustc::dep_graph::DepGraph; -use rustc::middle::cstore::{EncodedMetadata, MetadataLoaderDyn}; -use rustc::session::config::{OutputFilenames, PrintRequest}; -use rustc::session::Session; -use rustc::ty::query::Providers; -use rustc::ty::TyCtxt; -use rustc::util::common::ErrorReported; -use rustc_span::symbol::Symbol; - -pub use rustc_data_structures::sync::MetadataRef; - -pub trait CodegenBackend { - fn init(&self, _sess: &Session) {} - fn print(&self, _req: PrintRequest, _sess: &Session) {} - fn target_features(&self, _sess: &Session) -> Vec { - vec![] - } - fn print_passes(&self) {} - fn print_version(&self) {} - - fn metadata_loader(&self) -> Box; - fn provide(&self, _providers: &mut Providers<'_>); - fn provide_extern(&self, _providers: &mut Providers<'_>); - fn codegen_crate<'tcx>( - &self, - tcx: TyCtxt<'tcx>, - metadata: EncodedMetadata, - need_metadata_module: bool, - ) -> Box; - - /// This is called on the returned `Box` from `codegen_backend` - /// - /// # Panics - /// - /// Panics when the passed `Box` was not returned by `codegen_backend`. - fn join_codegen( - &self, - ongoing_codegen: Box, - sess: &Session, - dep_graph: &DepGraph, - ) -> Result, ErrorReported>; - - /// This is called on the returned `Box` from `join_codegen` - /// - /// # Panics - /// - /// Panics when the passed `Box` was not returned by `join_codegen`. - fn link( - &self, - sess: &Session, - codegen_results: Box, - outputs: &OutputFilenames, - ) -> Result<(), ErrorReported>; -} diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs deleted file mode 100644 index 38906bbaef810..0000000000000 --- a/src/librustc_codegen_utils/lib.rs +++ /dev/null @@ -1,66 +0,0 @@ -//! # Note -//! -//! This API is completely unstable and subject to change. - -#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] -#![feature(never_type)] -#![feature(nll)] -#![feature(in_band_lifetimes)] -#![recursion_limit = "256"] - -#[macro_use] -extern crate rustc; - -use rustc::ty::query::Providers; -use rustc::ty::TyCtxt; -use rustc_hir::def_id::{DefId, LOCAL_CRATE}; -use rustc_span::symbol::sym; - -pub mod codegen_backend; -pub mod link; -pub mod symbol_names; -pub mod symbol_names_test; - -pub fn trigger_delay_span_bug(tcx: TyCtxt<'_>, key: DefId) { - tcx.sess.delay_span_bug( - tcx.def_span(key), - "delayed span bug triggered by #[rustc_error(delay_span_bug_from_inside_query)]", - ); -} - -/// check for the #[rustc_error] annotation, which forces an -/// error in codegen. This is used to write compile-fail tests -/// that actually test that compilation succeeds without -/// reporting an error. -pub fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) { - if let Some((def_id, _)) = tcx.entry_fn(LOCAL_CRATE) { - let attrs = &*tcx.get_attrs(def_id); - for attr in attrs { - if attr.check_name(sym::rustc_error) { - match attr.meta_item_list() { - // check if there is a #[rustc_error(delayed)] - Some(list) => { - if list.iter().any(|list_item| { - list_item.ident().map(|i| i.name) - == Some(sym::delay_span_bug_from_inside_query) - }) { - tcx.ensure().trigger_delay_span_bug(def_id); - } - } - // bare #[rustc_error] - None => { - tcx.sess.span_fatal( - tcx.def_span(def_id), - "fatal error triggered by #[rustc_error]", - ); - } - } - } - } - } -} - -pub fn provide(providers: &mut Providers<'_>) { - crate::symbol_names::provide(providers); - *providers = Providers { trigger_delay_span_bug, ..*providers }; -} diff --git a/src/librustc_data_structures/box_region.rs b/src/librustc_data_structures/box_region.rs index dbc54291f4087..edeb4f83c7d7e 100644 --- a/src/librustc_data_structures/box_region.rs +++ b/src/librustc_data_structures/box_region.rs @@ -25,22 +25,6 @@ pub struct PinnedGenerator { } impl PinnedGenerator { - #[cfg(bootstrap)] - pub fn new, Return = R> + 'static>( - generator: T, - ) -> (I, Self) { - let mut result = PinnedGenerator { generator: Box::pin(generator) }; - - // Run it to the first yield to set it up - let init = match Pin::new(&mut result.generator).resume() { - GeneratorState::Yielded(YieldType::Initial(y)) => y, - _ => panic!(), - }; - - (init, result) - } - - #[cfg(not(bootstrap))] pub fn new, Return = R> + 'static>( generator: T, ) -> (I, Self) { @@ -55,19 +39,6 @@ impl PinnedGenerator { (init, result) } - #[cfg(bootstrap)] - pub unsafe fn access(&mut self, closure: *mut dyn FnMut()) { - BOX_REGION_ARG.with(|i| { - i.set(Action::Access(AccessAction(closure))); - }); - - // Call the generator, which in turn will call the closure in BOX_REGION_ARG - if let GeneratorState::Complete(_) = Pin::new(&mut self.generator).resume() { - panic!() - } - } - - #[cfg(not(bootstrap))] pub unsafe fn access(&mut self, closure: *mut dyn FnMut()) { BOX_REGION_ARG.with(|i| { i.set(Action::Access(AccessAction(closure))); @@ -79,16 +50,6 @@ impl PinnedGenerator { } } - #[cfg(bootstrap)] - pub fn complete(&mut self) -> R { - // Tell the generator we want it to complete, consuming it and yielding a result - BOX_REGION_ARG.with(|i| i.set(Action::Complete)); - - let result = Pin::new(&mut self.generator).resume(); - if let GeneratorState::Complete(r) = result { r } else { panic!() } - } - - #[cfg(not(bootstrap))] pub fn complete(&mut self) -> R { // Tell the generator we want it to complete, consuming it and yielding a result BOX_REGION_ARG.with(|i| i.set(Action::Complete)); diff --git a/src/librustc_data_structures/frozen.rs b/src/librustc_data_structures/frozen.rs new file mode 100644 index 0000000000000..2daf5b0414172 --- /dev/null +++ b/src/librustc_data_structures/frozen.rs @@ -0,0 +1,63 @@ +//! An immutable, owned value (except for interior mutability). +//! +//! The purpose of `Frozen` is to make a value immutable for the sake of defensive programming. For example, +//! suppose we have the following: +//! +//! ```rust +//! struct Bar { /* some data */ } +//! +//! struct Foo { +//! /// Some computed data that should never change after construction. +//! pub computed: Bar, +//! +//! /* some other fields */ +//! } +//! +//! impl Bar { +//! /// Mutate the `Bar`. +//! pub fn mutate(&mut self) { } +//! } +//! ``` +//! +//! Now suppose we want to pass around a mutable `Foo` instance but, we want to make sure that +//! `computed` does not change accidentally (e.g. somebody might accidentally call +//! `foo.computed.mutate()`). This is what `Frozen` is for. We can do the following: +//! +//! ```rust +//! use rustc_data_structures::frozen::Frozen; +//! +//! struct Foo { +//! /// Some computed data that should never change after construction. +//! pub computed: Frozen, +//! +//! /* some other fields */ +//! } +//! ``` +//! +//! `Frozen` impls `Deref`, so we can ergonomically call methods on `Bar`, but it doesn't `impl +//! DerefMut`. Now calling `foo.compute.mutate()` will result in a compile-time error stating that +//! `mutate` requires a mutable reference but we don't have one. +//! +//! # Caveats +//! +//! - `Frozen` doesn't try to defend against interior mutability (e.g. `Frozen>`). +//! - `Frozen` doesn't pin it's contents (e.g. one could still do `foo.computed = +//! Frozen::freeze(new_bar)`). + +/// An owned immutable value. +#[derive(Debug)] +pub struct Frozen(T); + +impl Frozen { + pub fn freeze(val: T) -> Self { + Frozen(val) + } +} + +impl std::ops::Deref for Frozen { + type Target = T; + + fn deref(&self) -> &T { + &self.0 + } +} diff --git a/src/librustc_data_structures/graph/dominators/mod.rs b/src/librustc_data_structures/graph/dominators/mod.rs index 5283bd78a3029..a7f9340dead88 100644 --- a/src/librustc_data_structures/graph/dominators/mod.rs +++ b/src/librustc_data_structures/graph/dominators/mod.rs @@ -125,9 +125,9 @@ impl<'dom, Node: Idx> Iterator for Iter<'dom, Node> { } else { self.node = Some(dom); } - return Some(node); + Some(node) } else { - return None; + None } } } diff --git a/src/librustc_data_structures/graph/scc/mod.rs b/src/librustc_data_structures/graph/scc/mod.rs index 70fc2d7dad9ee..7ecf3e3cb8d5d 100644 --- a/src/librustc_data_structures/graph/scc/mod.rs +++ b/src/librustc_data_structures/graph/scc/mod.rs @@ -97,7 +97,7 @@ impl GraphSuccessors<'graph> for Sccs { } impl WithSuccessors for Sccs { - fn successors<'graph>(&'graph self, node: S) -> >::Iter { + fn successors(&self, node: S) -> >::Iter { self.successors(node).iter().cloned() } } diff --git a/src/librustc_data_structures/graph/vec_graph/mod.rs b/src/librustc_data_structures/graph/vec_graph/mod.rs index 22c50afe6d0b4..064467174cae2 100644 --- a/src/librustc_data_structures/graph/vec_graph/mod.rs +++ b/src/librustc_data_structures/graph/vec_graph/mod.rs @@ -101,7 +101,7 @@ impl GraphSuccessors<'graph> for VecGraph { } impl WithSuccessors for VecGraph { - fn successors<'graph>(&'graph self, node: N) -> >::Iter { + fn successors(&self, node: N) -> >::Iter { self.successors(node).iter().cloned() } } diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 13792a0c890c4..f9f8ff5303e10 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -94,6 +94,7 @@ pub mod profiling; pub mod vec_linked_list; pub mod work_queue; pub use atomic_ref::AtomicRef; +pub mod frozen; pub struct OnDrop(pub F); diff --git a/src/librustc_data_structures/profiling.rs b/src/librustc_data_structures/profiling.rs index a70314c35c07c..a7cdc48d60342 100644 --- a/src/librustc_data_structures/profiling.rs +++ b/src/librustc_data_structures/profiling.rs @@ -345,7 +345,7 @@ impl SelfProfilerRef { ) { drop(self.exec(event_filter, |profiler| { let event_id = StringId::new_virtual(query_invocation_id.0); - let thread_id = std::thread::current().id().as_u64() as u32; + let thread_id = std::thread::current().id().as_u64().get() as u32; profiler.profiler.record_instant_event( event_kind(profiler), @@ -522,7 +522,7 @@ impl<'a> TimingGuard<'a> { event_kind: StringId, event_id: EventId, ) -> TimingGuard<'a> { - let thread_id = std::thread::current().id().as_u64() as u32; + let thread_id = std::thread::current().id().as_u64().get() as u32; let raw_profiler = &profiler.profiler; let timing_guard = raw_profiler.start_recording_interval_event(event_kind, event_id, thread_id); diff --git a/src/librustc_data_structures/sharded.rs b/src/librustc_data_structures/sharded.rs index d08d46a7414d0..485719c517564 100644 --- a/src/librustc_data_structures/sharded.rs +++ b/src/librustc_data_structures/sharded.rs @@ -30,7 +30,7 @@ pub struct Sharded { impl Default for Sharded { #[inline] fn default() -> Self { - Self::new(|| T::default()) + Self::new(T::default) } } diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index 26f1741153c8c..aec10ee5ef537 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -27,7 +27,7 @@ rustc_parse = { path = "../librustc_parse" } rustc_plugin_impl = { path = "../librustc_plugin_impl" } rustc_save_analysis = { path = "../librustc_save_analysis" } rustc_codegen_ssa = { path = "../librustc_codegen_ssa" } -rustc_codegen_utils = { path = "../librustc_codegen_utils" } +rustc_session = { path = "../librustc_session" } rustc_error_codes = { path = "../librustc_error_codes" } rustc_interface = { path = "../librustc_interface" } rustc_serialize = { path = "../libserialize", package = "serialize" } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index e6c98ad27e8ef..9097a72f36f49 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -18,16 +18,11 @@ extern crate lazy_static; pub extern crate rustc_plugin_impl as plugin; -use rustc::lint::{Lint, LintId}; use rustc::middle::cstore::MetadataLoader; -use rustc::session::config::nightly_options; -use rustc::session::config::{ErrorOutputType, Input, OutputType, PrintRequest}; -use rustc::session::{config, DiagnosticOutput, Session}; -use rustc::session::{early_error, early_warn}; use rustc::ty::TyCtxt; use rustc::util::common::ErrorReported; -use rustc_codegen_ssa::CodegenResults; -use rustc_codegen_utils::codegen_backend::CodegenBackend; +use rustc_ast::ast; +use rustc_codegen_ssa::{traits::CodegenBackend, CodegenResults}; use rustc_data_structures::profiling::print_time_passes_entry; use rustc_data_structures::sync::SeqCst; use rustc_errors::{ @@ -43,6 +38,13 @@ use rustc_metadata::locator; use rustc_save_analysis as save; use rustc_save_analysis::DumpHandler; use rustc_serialize::json::{self, ToJson}; +use rustc_session::config::nightly_options; +use rustc_session::config::{ErrorOutputType, Input, OutputType, PrintRequest}; +use rustc_session::lint::{Lint, LintId}; +use rustc_session::{config, DiagnosticOutput, Session}; +use rustc_session::{early_error, early_warn}; +use rustc_span::source_map::{FileLoader, FileName}; +use rustc_span::symbol::sym; use std::borrow::Cow; use std::cmp::max; @@ -58,11 +60,6 @@ use std::process::{self, Command, Stdio}; use std::str; use std::time::Instant; -use rustc_ast::ast; -use rustc_span::source_map::FileLoader; -use rustc_span::symbol::sym; -use rustc_span::FileName; - mod args; pub mod pretty; @@ -652,7 +649,7 @@ impl RustcDefaultCalls { odir: &Option, ofile: &Option, ) -> Compilation { - use rustc::session::config::PrintRequest::*; + use rustc_session::config::PrintRequest::*; // PrintRequest::NativeStaticLibs is special - printed during linking // (empty iterator returns true) if sess.opts.prints.iter().all(|&p| p == PrintRequest::NativeStaticLibs) { @@ -693,16 +690,15 @@ impl RustcDefaultCalls { let t_outputs = rustc_interface::util::build_output_filenames( input, odir, ofile, attrs, sess, ); - let id = rustc_codegen_utils::link::find_crate_name(Some(sess), attrs, input); + let id = rustc_session::output::find_crate_name(Some(sess), attrs, input); if *req == PrintRequest::CrateName { println!("{}", id); continue; } let crate_types = collect_crate_types(sess, attrs); for &style in &crate_types { - let fname = rustc_codegen_utils::link::filename_for_input( - sess, style, &id, &t_outputs, - ); + let fname = + rustc_session::output::filename_for_input(sess, style, &id, &t_outputs); println!("{}", fname.file_name().unwrap().to_string_lossy()); } } @@ -752,7 +748,7 @@ impl RustcDefaultCalls { PrintRequest::NativeStaticLibs => {} } } - return Compilation::Stop; + Compilation::Stop } } @@ -1124,12 +1120,7 @@ fn extra_compiler_flags() -> Option<(Vec, bool)> { return None; } - let matches = if let Some(matches) = handle_options(&args) { - matches - } else { - return None; - }; - + let matches = handle_options(&args)?; let mut result = Vec::new(); let mut excluded_cargo_defaults = false; for flag in ICE_REPORT_COMPILER_FLAGS { diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index ca129ac59849a..1e5cc55a82853 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -1,8 +1,6 @@ //! The various pretty-printing routines. use rustc::hir::map as hir_map; -use rustc::session::config::{Input, PpMode, PpSourceMode}; -use rustc::session::Session; use rustc::ty::{self, TyCtxt}; use rustc::util::common::ErrorReported; use rustc_ast::ast; @@ -11,6 +9,8 @@ use rustc_hir as hir; use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::print as pprust_hir; use rustc_mir::util::{write_mir_graphviz, write_mir_pretty}; +use rustc_session::config::{Input, PpMode, PpSourceMode}; +use rustc_session::Session; use rustc_span::FileName; use std::cell::Cell; @@ -96,7 +96,7 @@ trait PrinterSupport: pprust::PpAnn { /// /// (Rust does not yet support upcasting from a trait object to /// an object for one of its super-traits.) - fn pp_ann<'a>(&'a self) -> &'a dyn pprust::PpAnn; + fn pp_ann(&self) -> &dyn pprust::PpAnn; } trait HirPrinterSupport<'hir>: pprust_hir::PpAnn { @@ -106,13 +106,13 @@ trait HirPrinterSupport<'hir>: pprust_hir::PpAnn { /// Provides a uniform interface for re-extracting a reference to an /// `hir_map::Map` from a value that now owns it. - fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'hir>>; + fn hir_map(&self) -> Option>; /// Produces the pretty-print annotation object. /// /// (Rust does not yet support upcasting from a trait object to /// an object for one of its super-traits.) - fn pp_ann<'a>(&'a self) -> &'a dyn pprust_hir::PpAnn; + fn pp_ann(&self) -> &dyn pprust_hir::PpAnn; /// Computes an user-readable representation of a path, if possible. fn node_path(&self, id: hir::HirId) -> Option { @@ -132,7 +132,7 @@ impl<'hir> PrinterSupport for NoAnn<'hir> { self.sess } - fn pp_ann<'a>(&'a self) -> &'a dyn pprust::PpAnn { + fn pp_ann(&self) -> &dyn pprust::PpAnn { self } } @@ -142,11 +142,11 @@ impl<'hir> HirPrinterSupport<'hir> for NoAnn<'hir> { self.sess } - fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'hir>> { - self.tcx.map(|tcx| *tcx.hir()) + fn hir_map(&self) -> Option> { + self.tcx.map(|tcx| tcx.hir()) } - fn pp_ann<'a>(&'a self) -> &'a dyn pprust_hir::PpAnn { + fn pp_ann(&self) -> &dyn pprust_hir::PpAnn { self } } @@ -155,7 +155,7 @@ impl<'hir> pprust::PpAnn for NoAnn<'hir> {} impl<'hir> pprust_hir::PpAnn for NoAnn<'hir> { fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) { if let Some(tcx) = self.tcx { - pprust_hir::PpAnn::nested(*tcx.hir(), state, nested) + pprust_hir::PpAnn::nested(&tcx.hir(), state, nested) } } } @@ -170,7 +170,7 @@ impl<'hir> PrinterSupport for IdentifiedAnnotation<'hir> { self.sess } - fn pp_ann<'a>(&'a self) -> &'a dyn pprust::PpAnn { + fn pp_ann(&self) -> &dyn pprust::PpAnn { self } } @@ -216,11 +216,11 @@ impl<'hir> HirPrinterSupport<'hir> for IdentifiedAnnotation<'hir> { self.sess } - fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'hir>> { - self.tcx.map(|tcx| *tcx.hir()) + fn hir_map(&self) -> Option> { + self.tcx.map(|tcx| tcx.hir()) } - fn pp_ann<'a>(&'a self) -> &'a dyn pprust_hir::PpAnn { + fn pp_ann(&self) -> &dyn pprust_hir::PpAnn { self } } @@ -228,7 +228,7 @@ impl<'hir> HirPrinterSupport<'hir> for IdentifiedAnnotation<'hir> { impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> { fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) { if let Some(ref tcx) = self.tcx { - pprust_hir::PpAnn::nested(*tcx.hir(), state, nested) + pprust_hir::PpAnn::nested(&tcx.hir(), state, nested) } } fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) { @@ -315,11 +315,11 @@ impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> { &self.tcx.sess } - fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'tcx>> { - Some(&self.tcx.hir()) + fn hir_map(&self) -> Option> { + Some(self.tcx.hir()) } - fn pp_ann<'a>(&'a self) -> &'a dyn pprust_hir::PpAnn { + fn pp_ann(&self) -> &dyn pprust_hir::PpAnn { self } @@ -334,7 +334,7 @@ impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> { if let pprust_hir::Nested::Body(id) = nested { self.tables.set(self.tcx.body_tables(id)); } - pprust_hir::PpAnn::nested(*self.tcx.hir(), state, nested); + pprust_hir::PpAnn::nested(&self.tcx.hir(), state, nested); self.tables.set(old_tables); } fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) { diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 0e14e2196caf0..fdcf3d639574b 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -97,7 +97,6 @@ E0184: include_str!("./error_codes/E0184.md"), E0185: include_str!("./error_codes/E0185.md"), E0186: include_str!("./error_codes/E0186.md"), E0191: include_str!("./error_codes/E0191.md"), -E0192: include_str!("./error_codes/E0192.md"), E0193: include_str!("./error_codes/E0193.md"), E0195: include_str!("./error_codes/E0195.md"), E0197: include_str!("./error_codes/E0197.md"), @@ -118,6 +117,7 @@ E0220: include_str!("./error_codes/E0220.md"), E0221: include_str!("./error_codes/E0221.md"), E0222: include_str!("./error_codes/E0222.md"), E0223: include_str!("./error_codes/E0223.md"), +E0224: include_str!("./error_codes/E0224.md"), E0225: include_str!("./error_codes/E0225.md"), E0229: include_str!("./error_codes/E0229.md"), E0230: include_str!("./error_codes/E0230.md"), @@ -349,8 +349,10 @@ E0623: include_str!("./error_codes/E0623.md"), E0624: include_str!("./error_codes/E0624.md"), E0626: include_str!("./error_codes/E0626.md"), E0627: include_str!("./error_codes/E0627.md"), +E0628: include_str!("./error_codes/E0628.md"), E0631: include_str!("./error_codes/E0631.md"), E0633: include_str!("./error_codes/E0633.md"), +E0634: include_str!("./error_codes/E0634.md"), E0635: include_str!("./error_codes/E0635.md"), E0636: include_str!("./error_codes/E0636.md"), E0637: include_str!("./error_codes/E0637.md"), @@ -380,6 +382,7 @@ E0689: include_str!("./error_codes/E0689.md"), E0690: include_str!("./error_codes/E0690.md"), E0691: include_str!("./error_codes/E0691.md"), E0692: include_str!("./error_codes/E0692.md"), +E0693: include_str!("./error_codes/E0693.md"), E0695: include_str!("./error_codes/E0695.md"), E0697: include_str!("./error_codes/E0697.md"), E0698: include_str!("./error_codes/E0698.md"), @@ -389,6 +392,7 @@ E0701: include_str!("./error_codes/E0701.md"), E0704: include_str!("./error_codes/E0704.md"), E0705: include_str!("./error_codes/E0705.md"), E0706: include_str!("./error_codes/E0706.md"), +E0710: include_str!("./error_codes/E0710.md"), E0712: include_str!("./error_codes/E0712.md"), E0713: include_str!("./error_codes/E0713.md"), E0714: include_str!("./error_codes/E0714.md"), @@ -421,6 +425,9 @@ E0745: include_str!("./error_codes/E0745.md"), E0746: include_str!("./error_codes/E0746.md"), E0747: include_str!("./error_codes/E0747.md"), E0748: include_str!("./error_codes/E0748.md"), +E0749: include_str!("./error_codes/E0749.md"), +E0750: include_str!("./error_codes/E0750.md"), +E0751: include_str!("./error_codes/E0751.md"), ; // E0006, // merged with E0005 // E0008, // cannot bind by-move into a pattern guard @@ -455,6 +462,7 @@ E0748: include_str!("./error_codes/E0748.md"), // E0188, // can not cast an immutable reference to a mutable pointer // E0189, // deprecated: can only cast a boxed pointer to a boxed object // E0190, // deprecated: can only cast a &-pointer to an &-object +// E0192, // negative impl only applicable to auto traits // E0194, // merged into E0403 // E0196, // cannot determine a type for this closure E0208, @@ -466,7 +474,6 @@ E0748: include_str!("./error_codes/E0748.md"), // E0217, // ambiguous associated type, defined in multiple supertraits // E0218, // no associated type defined // E0219, // associated type defined in higher-ranked supertrait - E0224, // at least one non-builtin train is required for an object type E0226, // only a single explicit lifetime bound is permitted E0227, // ambiguous lifetime bound, explicit lifetime bound required E0228, // explicit lifetime bound required @@ -581,21 +588,18 @@ E0748: include_str!("./error_codes/E0748.md"), // E0612, // merged into E0609 // E0613, // Removed (merged with E0609) E0625, // thread-local statics cannot be accessed at compile-time - E0628, // generators cannot have explicit parameters E0629, // missing 'feature' (rustc_const_unstable) // rustc_const_unstable attribute must be paired with stable/unstable // attribute E0630, E0632, // cannot provide explicit generic arguments when `impl Trait` is // used in argument position - E0634, // type has conflicting packed representaton hints E0640, // infer outlives requirements // E0645, // trait aliases not finished E0657, // `impl Trait` can only capture lifetimes bound at the fn level E0667, // `impl Trait` in projections E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders - E0693, // incorrect `repr(align)` attribute format // E0694, // an unknown tool name found in scoped attributes E0696, // `continue` pointing to a labeled block // E0702, // replaced with a generic attribute input check @@ -604,7 +608,6 @@ E0748: include_str!("./error_codes/E0748.md"), E0708, // `async` non-`move` closures with parameters are not currently // supported // E0709, // multiple different lifetimes used in arguments of `async fn` - E0710, // an unknown tool name found in scoped lint E0711, // a feature has been declared with conflicting stability attributes E0717, // rustc_promotable without stability attribute // E0721, // `await` keyword diff --git a/src/librustc_error_codes/error_codes/E0117.md b/src/librustc_error_codes/error_codes/E0117.md index 7fa211d4a27d4..0544667cccaea 100644 --- a/src/librustc_error_codes/error_codes/E0117.md +++ b/src/librustc_error_codes/error_codes/E0117.md @@ -1,4 +1,4 @@ -The `Drop` trait was implemented on a non-struct type. +Only traits defined in the current crate can be implemented for arbitrary types. Erroneous code example: diff --git a/src/librustc_error_codes/error_codes/E0224.md b/src/librustc_error_codes/error_codes/E0224.md new file mode 100644 index 0000000000000..fd89c1d52560f --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0224.md @@ -0,0 +1,15 @@ +A trait object was declaired with no traits. + +Erroneous code example: + +```compile_fail,E0224 +type Foo = dyn 'static +; +``` + +Rust does not currently support this. + +To solve ensure the the trait object has at least one trait: + +``` +type Foo = dyn 'static + Copy; +``` diff --git a/src/librustc_error_codes/error_codes/E0308.md b/src/librustc_error_codes/error_codes/E0308.md index a907ca272970e..b2c8437049001 100644 --- a/src/librustc_error_codes/error_codes/E0308.md +++ b/src/librustc_error_codes/error_codes/E0308.md @@ -1,10 +1,6 @@ -This error occurs when the compiler was unable to infer the concrete type of a -variable. It can occur for several cases, the most common of which is a -mismatch in the expected type that the compiler inferred for a variable's -initializing expression, and the actual type explicitly assigned to the -variable. +Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = "I am not a number!"; @@ -15,3 +11,9 @@ let x: i32 = "I am not a number!"; // | // type `i32` assigned to variable `x` ``` + +This error occurs when the compiler was unable to infer the concrete type of a +variable. It can happen in several cases, the most common being a mismatch +between the type that the compiler inferred for a variable based on its +initializing expression, on the one hand, and the type the author explicitly +assigned to the variable, on the other hand. diff --git a/src/librustc_error_codes/error_codes/E0412.md b/src/librustc_error_codes/error_codes/E0412.md index 60a09610d86f6..d9ebc852bbab7 100644 --- a/src/librustc_error_codes/error_codes/E0412.md +++ b/src/librustc_error_codes/error_codes/E0412.md @@ -1,4 +1,4 @@ -The type name used is not in scope. +A used type name is not in scope. Erroneous code examples: diff --git a/src/librustc_error_codes/error_codes/E0422.md b/src/librustc_error_codes/error_codes/E0422.md index a91ea6a9e22f6..828a52e734114 100644 --- a/src/librustc_error_codes/error_codes/E0422.md +++ b/src/librustc_error_codes/error_codes/E0422.md @@ -1,4 +1,5 @@ -You are trying to use an identifier that is either undefined or not a struct. +An identifier that is neither defined nor a struct was used. + Erroneous code example: ```compile_fail,E0422 diff --git a/src/librustc_error_codes/error_codes/E0423.md b/src/librustc_error_codes/error_codes/E0423.md index 6a7c31f5e0d43..a98ada17a469c 100644 --- a/src/librustc_error_codes/error_codes/E0423.md +++ b/src/librustc_error_codes/error_codes/E0423.md @@ -1,8 +1,7 @@ An identifier was used like a function name or a value was expected and the identifier exists but it belongs to a different namespace. -For (an erroneous) example, here a `struct` variant name were used as a -function: +Erroneous code example: ```compile_fail,E0423 struct Foo { a: bool }; diff --git a/src/librustc_error_codes/error_codes/E0434.md b/src/librustc_error_codes/error_codes/E0434.md index e093f0796da5e..8fd60412baf01 100644 --- a/src/librustc_error_codes/error_codes/E0434.md +++ b/src/librustc_error_codes/error_codes/E0434.md @@ -1,6 +1,4 @@ -This error indicates that a variable usage inside an inner function is invalid -because the variable comes from a dynamic environment. Inner functions do not -have access to their containing environment. +A variable used inside an inner function comes from a dynamic environment. Erroneous code example: @@ -14,8 +12,8 @@ fn foo() { } ``` -Functions do not capture local variables. To fix this error, you can replace the -function with a closure: +Inner functions do not have access to their containing environment. To fix this +error, you can replace the function with a closure: ``` fn foo() { @@ -26,7 +24,7 @@ fn foo() { } ``` -or replace the captured variable with a constant or a static item: +Or replace the captured variable with a constant or a static item: ``` fn foo() { diff --git a/src/librustc_error_codes/error_codes/E0436.md b/src/librustc_error_codes/error_codes/E0436.md index b1afd9e960337..48ecc49e92f54 100644 --- a/src/librustc_error_codes/error_codes/E0436.md +++ b/src/librustc_error_codes/error_codes/E0436.md @@ -1,5 +1,4 @@ -The functional record update syntax is only allowed for structs. (Struct-like -enum variants don't qualify, for example.) +The functional record update syntax was used on something other than a struct. Erroneous code example: @@ -24,7 +23,9 @@ fn one_up_competitor(competitor_frequency: PublicationFrequency) } ``` -Rewrite the expression without functional record update syntax: +The functional record update syntax is only allowed for structs (struct-like +enum variants don't qualify, for example). To fix the previous code, rewrite the +expression without functional record update syntax: ``` enum PublicationFrequency { diff --git a/src/librustc_error_codes/error_codes/E0437.md b/src/librustc_error_codes/error_codes/E0437.md index 834cf33dbc7f0..0f924ba692064 100644 --- a/src/librustc_error_codes/error_codes/E0437.md +++ b/src/librustc_error_codes/error_codes/E0437.md @@ -1,7 +1,5 @@ -Trait implementations can only implement associated types that are members of -the trait in question. This error indicates that you attempted to implement -an associated type whose name does not match the name of any associated type -in the trait. +An associated type whose name does not match any of the associated types +in the trait was used when implementing the trait. Erroneous code example: @@ -13,6 +11,9 @@ impl Foo for i32 { } ``` +Trait implementations can only implement associated types that are members of +the trait in question. + The solution to this problem is to remove the extraneous associated type: ``` diff --git a/src/librustc_error_codes/error_codes/E0438.md b/src/librustc_error_codes/error_codes/E0438.md index cb141a5d24aed..13723bc30090e 100644 --- a/src/librustc_error_codes/error_codes/E0438.md +++ b/src/librustc_error_codes/error_codes/E0438.md @@ -1,7 +1,5 @@ -Trait implementations can only implement associated constants that are -members of the trait in question. This error indicates that you -attempted to implement an associated constant whose name does not -match the name of any associated constant in the trait. +An associated constant whose name does not match any of the associated constants +in the trait was used when implementing the trait. Erroneous code example: @@ -13,6 +11,9 @@ impl Foo for i32 { } ``` +Trait implementations can only implement associated constants that are +members of the trait in question. + The solution to this problem is to remove the extraneous associated constant: ``` diff --git a/src/librustc_error_codes/error_codes/E0439.md b/src/librustc_error_codes/error_codes/E0439.md index e6da2117ac5f2..3e663df866caa 100644 --- a/src/librustc_error_codes/error_codes/E0439.md +++ b/src/librustc_error_codes/error_codes/E0439.md @@ -1,5 +1,6 @@ -The length of the platform-intrinsic function `simd_shuffle` -wasn't specified. Erroneous code example: +The length of the platform-intrinsic function `simd_shuffle` wasn't specified. + +Erroneous code example: ```compile_fail,E0439 #![feature(platform_intrinsics)] diff --git a/src/librustc_error_codes/error_codes/E0449.md b/src/librustc_error_codes/error_codes/E0449.md index a3eb51961d32e..9afc67689bf85 100644 --- a/src/librustc_error_codes/error_codes/E0449.md +++ b/src/librustc_error_codes/error_codes/E0449.md @@ -1,5 +1,6 @@ -A visibility qualifier was used when it was unnecessary. Erroneous code -examples: +A visibility qualifier was used when it was unnecessary. + +Erroneous code examples: ```compile_fail,E0449 struct Bar; diff --git a/src/librustc_error_codes/error_codes/E0452.md b/src/librustc_error_codes/error_codes/E0452.md index be3d573e10d2d..429813a7cdd4e 100644 --- a/src/librustc_error_codes/error_codes/E0452.md +++ b/src/librustc_error_codes/error_codes/E0452.md @@ -1,4 +1,6 @@ -An invalid lint attribute has been given. Erroneous code example: +An invalid lint attribute has been given. + +Erroneous code example: ```compile_fail,E0452 #![allow(foo = "")] // error: malformed lint attribute diff --git a/src/librustc_error_codes/error_codes/E0454.md b/src/librustc_error_codes/error_codes/E0454.md index 80eb91e43d16b..23ca6c7824df1 100644 --- a/src/librustc_error_codes/error_codes/E0454.md +++ b/src/librustc_error_codes/error_codes/E0454.md @@ -1,4 +1,6 @@ -A link name was given with an empty name. Erroneous code example: +A link name was given with an empty name. + +Erroneous code example: ```compile_fail,E0454 #[link(name = "")] extern {} diff --git a/src/librustc_error_codes/error_codes/E0458.md b/src/librustc_error_codes/error_codes/E0458.md index 5996f190b34f0..075226ac98b9d 100644 --- a/src/librustc_error_codes/error_codes/E0458.md +++ b/src/librustc_error_codes/error_codes/E0458.md @@ -1,4 +1,6 @@ -An unknown "kind" was specified for a link attribute. Erroneous code example: +An unknown "kind" was specified for a link attribute. + +Erroneous code example: ```compile_fail,E0458 #[link(kind = "wonderful_unicorn")] extern {} diff --git a/src/librustc_error_codes/error_codes/E0628.md b/src/librustc_error_codes/error_codes/E0628.md new file mode 100644 index 0000000000000..40040c9a56aac --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0628.md @@ -0,0 +1,30 @@ +More than one parameter was used for a generator. + +Erroneous code example: + +```compile_fail,E0628 +#![feature(generators, generator_trait)] + +fn main() { + let generator = |a: i32, b: i32| { + // error: too many parameters for a generator + // Allowed only 0 or 1 parameter + yield a; + }; +} +``` + +At present, it is not permitted to pass more than one explicit +parameter for a generator.This can be fixed by using +at most 1 parameter for the generator. For example, we might resolve +the previous example by passing only one parameter. + +``` +#![feature(generators, generator_trait)] + +fn main() { + let generator = |a: i32| { + yield a; + }; +} +``` diff --git a/src/librustc_error_codes/error_codes/E0634.md b/src/librustc_error_codes/error_codes/E0634.md new file mode 100644 index 0000000000000..0c4ed2596e2aa --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0634.md @@ -0,0 +1,20 @@ +A type has conflicting `packed` representation hints. + +Erroneous code examples: + +```compile_fail,E0634 +#[repr(packed, packed(2))] // error! +struct Company(i32); + +#[repr(packed(2))] // error! +#[repr(packed)] +struct Company(i32); +``` + +You cannot use conflicting `packed` hints on a same type. If you want to pack a +type to a given size, you should provide a size to packed: + +``` +#[repr(packed)] // ok! +struct Company(i32); +``` diff --git a/src/librustc_error_codes/error_codes/E0693.md b/src/librustc_error_codes/error_codes/E0693.md new file mode 100644 index 0000000000000..43e9d17979e68 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0693.md @@ -0,0 +1,19 @@ +`align` representation hint was incorrectly declared. + +Erroneous code examples: + +```compile_fail,E0693 +#[repr(align=8)] // error! +struct Align8(i8); + +#[repr(align="8")] // error! +struct Align8(i8); +``` + +This is a syntax error at the level of attribute declarations. The proper +syntax for `align` representation hint is the following: + +``` +#[repr(align(8))] // ok! +struct Align8(i8); +``` diff --git a/src/librustc_error_codes/error_codes/E0710.md b/src/librustc_error_codes/error_codes/E0710.md new file mode 100644 index 0000000000000..d9cefe2a6da72 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0710.md @@ -0,0 +1,34 @@ +An unknown tool name found in scoped lint + +Erroneous code examples: + +```compile_fail,E0710 +#[allow(clipp::filter_map)] // error!` +fn main() { + // business logic +} +``` + +```compile_fail,E0710 +#[warn(clipp::filter_map)] // error!` +fn main() { + // business logic +} +``` + +Please verify you didn't misspell the tool's name or that you didn't +forget to import it in you project: + +``` +#[allow(clippy::filter_map)] // ok! +fn main() { + // business logic +} +``` + +``` +#[warn(clippy::filter_map)] // ok! +fn main() { + // business logic +} +``` diff --git a/src/librustc_error_codes/error_codes/E0738.md b/src/librustc_error_codes/error_codes/E0738.md index 4c9588ef7b63b..8f31b701e495e 100644 --- a/src/librustc_error_codes/error_codes/E0738.md +++ b/src/librustc_error_codes/error_codes/E0738.md @@ -1,48 +1,11 @@ -`#[track_caller]` cannot be used in traits yet. This is due to limitations in -the compiler which are likely to be temporary. See [RFC 2091] for details on -this and other restrictions. +`#[track_caller]` cannot be used to annotate foreign functions. -Erroneous example with a trait method implementation: +Erroneous example: ```compile_fail,E0738 #![feature(track_caller)] - -trait Foo { - fn bar(&self); -} - -impl Foo for u64 { - #[track_caller] - fn bar(&self) {} -} -``` - -Erroneous example with a blanket trait method implementation: - -```compile_fail,E0738 -#![feature(track_caller)] - -trait Foo { +extern "Rust" { #[track_caller] - fn bar(&self) {} - fn baz(&self); + fn bar(); } ``` - -Erroneous example with a trait method declaration: - -```compile_fail,E0738 -#![feature(track_caller)] - -trait Foo { - fn bar(&self) {} - - #[track_caller] - fn baz(&self); -} -``` - -Note that while the compiler may be able to support the attribute in traits in -the future, [RFC 2091] prohibits their implementation without a follow-up RFC. - -[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md diff --git a/src/librustc_error_codes/error_codes/E0749.md b/src/librustc_error_codes/error_codes/E0749.md new file mode 100644 index 0000000000000..9eb8ee4e3fdf7 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0749.md @@ -0,0 +1,4 @@ +Negative impls are not allowed to have any items. Negative impls +declare that a trait is **not** implemented (and never will be) and +hence there is no need to specify the values for trait methods or +other items. diff --git a/src/librustc_error_codes/error_codes/E0750.md b/src/librustc_error_codes/error_codes/E0750.md new file mode 100644 index 0000000000000..e0cf56f716f9d --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0750.md @@ -0,0 +1,4 @@ +Negative impls cannot be default impls. A default impl supplies +default values for the items within to be used by other impls, whereas +a negative impl declares that there are no other impls. These don't +make sense to combine. diff --git a/src/librustc_error_codes/error_codes/E0751.md b/src/librustc_error_codes/error_codes/E0751.md new file mode 100644 index 0000000000000..a440f82e4b6b3 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0751.md @@ -0,0 +1,12 @@ +There are both a positive and negative trait implementation for the same type. + +Erroneous code example: + +```compile_fail,E0748 +trait MyTrait {} +impl MyTrait for i32 { } +impl !MyTrait for i32 { } +``` + +Negative implementations are a promise that the trait will never be +implemented for the given types. diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 008d2e92418f9..fffae0bfd24d9 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -162,7 +162,7 @@ impl<'a> DiagnosticBuilder<'a> { message: &str, span: Option, ) -> &mut Self { - let span = span.map(|s| s.into()).unwrap_or_else(|| MultiSpan::new()); + let span = span.map(|s| s.into()).unwrap_or_else(MultiSpan::new); self.0.diagnostic.sub(level, message, span, None); self } diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 03f83e616365b..94053b98cd75b 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -5,7 +5,7 @@ //! There are various `Emitter` implementations that generate different output formats such as //! JSON and human readable output. //! -//! The output types are defined in `librustc::session::config::ErrorOutputType`. +//! The output types are defined in `rustc_session::config::ErrorOutputType`. use Destination::*; @@ -1574,7 +1574,7 @@ impl EmitterWriter { .span_to_lines(parts[0].span) .expect("span_to_lines failed when emitting suggestion"); - assert!(!lines.lines.is_empty()); + assert!(!lines.lines.is_empty() || parts[0].span.is_dummy()); let line_start = sm.lookup_char_pos(parts[0].span.lo()).line; draw_col_separator_no_space(&mut buffer, 1, max_line_num_len + 1); diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index bed26c3736b83..6157c46f80cf9 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -194,7 +194,7 @@ impl CodeSuggestion { let bounding_span = Span::with_root_ctxt(lo, hi); // The different spans might belong to different contexts, if so ignore suggestion. let lines = sm.span_to_lines(bounding_span).ok()?; - assert!(!lines.lines.is_empty()); + assert!(!lines.lines.is_empty() || bounding_span.is_dummy()); // We can't splice anything if the source is unavailable. if !sm.ensure_source_file_source_present(lines.file.clone()) { @@ -213,8 +213,8 @@ impl CodeSuggestion { let sf = &lines.file; let mut prev_hi = sm.lookup_char_pos(bounding_span.lo()); prev_hi.col = CharPos::from_usize(0); - - let mut prev_line = sf.get_line(lines.lines[0].line_index); + let mut prev_line = + lines.lines.get(0).and_then(|line0| sf.get_line(line0.line_index)); let mut buf = String::new(); for part in &substitution.parts { @@ -802,13 +802,13 @@ impl HandlerInner { )); self.failure(&format!( "For more information about an error, try \ - `rustc --explain {}`.", + `rustc --explain {}`.", &error_codes[0] )); } else { self.failure(&format!( "For more information about this error, try \ - `rustc --explain {}`.", + `rustc --explain {}`.", &error_codes[0] )); } diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs index f15e626c2783b..59c1a5468f100 100644 --- a/src/librustc_expand/base.rs +++ b/src/librustc_expand/base.rs @@ -1,4 +1,5 @@ use crate::expand::{self, AstFragment, Invocation}; +use crate::module::DirectoryOwnership; use rustc_ast::ast::{self, Attribute, Name, NodeId, PatKind}; use rustc_ast::mut_visit::{self, MutVisitor}; @@ -9,8 +10,8 @@ use rustc_ast::visit::{AssocCtxt, Visitor}; use rustc_attr::{self as attr, Deprecation, HasAttrs, Stability}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{self, Lrc}; -use rustc_errors::{DiagnosticBuilder, DiagnosticId}; -use rustc_parse::{self, parser, DirectoryOwnership, MACRO_ARGUMENTS}; +use rustc_errors::{DiagnosticBuilder, ErrorReported}; +use rustc_parse::{self, parser, MACRO_ARGUMENTS}; use rustc_session::parse::ParseSess; use rustc_span::edition::Edition; use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind}; @@ -258,8 +259,17 @@ impl Annotatable { } } -// `meta_item` is the annotation, and `item` is the item being modified. -// FIXME Decorators should follow the same pattern too. +/// Result of an expansion that may need to be retried. +/// Consider using this for non-`MultiItemModifier` expanders as well. +pub enum ExpandResult { + /// Expansion produced a result (possibly dummy). + Ready(T), + /// Expansion could not produce a result and needs to be retried. + /// The string is an explanation that will be printed if we are stuck in an infinite retry loop. + Retry(U, String), +} + +// `meta_item` is the attribute, and `item` is the item being modified. pub trait MultiItemModifier { fn expand( &self, @@ -267,13 +277,12 @@ pub trait MultiItemModifier { span: Span, meta_item: &ast::MetaItem, item: Annotatable, - ) -> Vec; + ) -> ExpandResult, Annotatable>; } -impl MultiItemModifier for F +impl MultiItemModifier for F where - F: Fn(&mut ExtCtxt<'_>, Span, &ast::MetaItem, Annotatable) -> T, - T: Into>, + F: Fn(&mut ExtCtxt<'_>, Span, &ast::MetaItem, Annotatable) -> Vec, { fn expand( &self, @@ -281,28 +290,32 @@ where span: Span, meta_item: &ast::MetaItem, item: Annotatable, - ) -> Vec { - (*self)(ecx, span, meta_item, item).into() - } -} - -impl Into> for Annotatable { - fn into(self) -> Vec { - vec![self] + ) -> ExpandResult, Annotatable> { + ExpandResult::Ready(self(ecx, span, meta_item, item)) } } pub trait ProcMacro { - fn expand<'cx>(&self, ecx: &'cx mut ExtCtxt<'_>, span: Span, ts: TokenStream) -> TokenStream; + fn expand<'cx>( + &self, + ecx: &'cx mut ExtCtxt<'_>, + span: Span, + ts: TokenStream, + ) -> Result; } impl ProcMacro for F where F: Fn(TokenStream) -> TokenStream, { - fn expand<'cx>(&self, _ecx: &'cx mut ExtCtxt<'_>, _span: Span, ts: TokenStream) -> TokenStream { + fn expand<'cx>( + &self, + _ecx: &'cx mut ExtCtxt<'_>, + _span: Span, + ts: TokenStream, + ) -> Result { // FIXME setup implicit context in TLS before calling self. - (*self)(ts) + Ok((*self)(ts)) } } @@ -313,7 +326,7 @@ pub trait AttrProcMacro { span: Span, annotation: TokenStream, annotated: TokenStream, - ) -> TokenStream; + ) -> Result; } impl AttrProcMacro for F @@ -326,9 +339,9 @@ where _span: Span, annotation: TokenStream, annotated: TokenStream, - ) -> TokenStream { + ) -> Result { // FIXME setup implicit context in TLS before calling self. - (*self)(annotation, annotated) + Ok((*self)(annotation, annotated)) } } @@ -372,7 +385,7 @@ where mut_visit::noop_visit_tt(tt, self) } - fn visit_mac(&mut self, mac: &mut ast::Mac) { + fn visit_mac(&mut self, mac: &mut ast::MacCall) { mut_visit::noop_visit_mac(mac, self) } } @@ -895,6 +908,7 @@ pub trait Resolver { fn has_derive_copy(&self, expn_id: ExpnId) -> bool; fn add_derive_copy(&mut self, expn_id: ExpnId); + fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result; } #[derive(Clone)] @@ -918,10 +932,13 @@ pub struct ExpansionData { pub struct ExtCtxt<'a> { pub parse_sess: &'a ParseSess, pub ecfg: expand::ExpansionConfig<'a>, + pub reduced_recursion_limit: Option, pub root_path: PathBuf, pub resolver: &'a mut dyn Resolver, pub current_expansion: ExpansionData, pub expansions: FxHashMap>, + /// Called directly after having parsed an external `mod foo;` in expansion. + pub(super) extern_mod_loaded: Option<&'a dyn Fn(&ast::Crate)>, } impl<'a> ExtCtxt<'a> { @@ -929,12 +946,15 @@ impl<'a> ExtCtxt<'a> { parse_sess: &'a ParseSess, ecfg: expand::ExpansionConfig<'a>, resolver: &'a mut dyn Resolver, + extern_mod_loaded: Option<&'a dyn Fn(&ast::Crate)>, ) -> ExtCtxt<'a> { ExtCtxt { parse_sess, ecfg, - root_path: PathBuf::new(), + reduced_recursion_limit: None, resolver, + extern_mod_loaded, + root_path: PathBuf::new(), current_expansion: ExpansionData { id: ExpnId::root(), depth: 0, @@ -994,31 +1014,9 @@ impl<'a> ExtCtxt<'a> { self.current_expansion.id.expansion_cause() } - pub fn struct_span_warn>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'a> { - self.parse_sess.span_diagnostic.struct_span_warn(sp, msg) - } pub fn struct_span_err>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'a> { self.parse_sess.span_diagnostic.struct_span_err(sp, msg) } - pub fn struct_span_fatal>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'a> { - self.parse_sess.span_diagnostic.struct_span_fatal(sp, msg) - } - - /// Emit `msg` attached to `sp`, and stop compilation immediately. - /// - /// `span_err` should be strongly preferred where-ever possible: - /// this should *only* be used when: - /// - /// - continuing has a high risk of flow-on errors (e.g., errors in - /// declaring a macro would cause all uses of that macro to - /// complain about "undefined macro"), or - /// - there is literally nothing else that can be done (however, - /// in most cases one can construct a dummy expression/item to - /// substitute; we never hit resolve/type-checking so the dummy - /// value doesn't have to match anything) - pub fn span_fatal>(&self, sp: S, msg: &str) -> ! { - self.parse_sess.span_diagnostic.span_fatal(sp, msg).raise(); - } /// Emit `msg` attached to `sp`, without immediately stopping /// compilation. @@ -1028,9 +1026,6 @@ impl<'a> ExtCtxt<'a> { pub fn span_err>(&self, sp: S, msg: &str) { self.parse_sess.span_diagnostic.span_err(sp, msg); } - pub fn span_err_with_code>(&self, sp: S, msg: &str, code: DiagnosticId) { - self.parse_sess.span_diagnostic.span_err_with_code(sp, msg, code); - } pub fn span_warn>(&self, sp: S, msg: &str) { self.parse_sess.span_diagnostic.span_warn(sp, msg); } @@ -1158,6 +1153,18 @@ pub fn check_zero_tts(cx: &ExtCtxt<'_>, sp: Span, tts: TokenStream, name: &str) } } +/// Parse an expression. On error, emit it, advancing to `Eof`, and return `None`. +pub fn parse_expr(p: &mut parser::Parser<'_>) -> Option> { + match p.parse_expr() { + Ok(e) => return Some(e), + Err(mut err) => err.emit(), + } + while p.token != token::Eof { + p.bump(); + } + None +} + /// Interpreting `tts` as a comma-separated sequence of expressions, /// expect exactly one string literal, or emit an error and return `None`. pub fn get_single_str_from_tts( @@ -1171,7 +1178,7 @@ pub fn get_single_str_from_tts( cx.span_err(sp, &format!("{} takes 1 argument", name)); return None; } - let ret = panictry!(p.parse_expr()); + let ret = parse_expr(&mut p)?; let _ = p.eat(&token::Comma); if p.token != token::Eof { @@ -1180,8 +1187,8 @@ pub fn get_single_str_from_tts( expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| s.to_string()) } -/// Extracts comma-separated expressions from `tts`. If there is a -/// parsing error, emit a non-fatal error and return `None`. +/// Extracts comma-separated expressions from `tts`. +/// On error, emit it, and return `None`. pub fn get_exprs_from_tts( cx: &mut ExtCtxt<'_>, sp: Span, @@ -1190,7 +1197,7 @@ pub fn get_exprs_from_tts( let mut p = cx.new_parser_from_tts(tts); let mut es = Vec::new(); while p.token != token::Eof { - let expr = panictry!(p.parse_expr()); + let expr = parse_expr(&mut p)?; // Perform eager expansion on the expression. // We want to be able to handle e.g., `concat!("foo", "bar")`. diff --git a/src/librustc_parse/config.rs b/src/librustc_expand/config.rs similarity index 95% rename from src/librustc_parse/config.rs rename to src/librustc_expand/config.rs index f42091e7c296a..72c09f35dfa55 100644 --- a/src/librustc_parse/config.rs +++ b/src/librustc_expand/config.rs @@ -1,14 +1,5 @@ -//! Process the potential `cfg` attributes on a module. -//! Also determine if the module should be included in this configuration. -//! -//! This module properly belongs in rustc_expand, but for now it's tied into -//! parsing, so we leave it here to avoid complicated out-of-line dependencies. -//! -//! A principled solution to this wrong location would be to implement [#64197]. -//! -//! [#64197]: https://github.com/rust-lang/rust/issues/64197 - -use crate::{parse_in, validate_attr}; +//! Conditional compilation stripping. + use rustc_ast::ast::{self, AttrItem, Attribute, MetaItem}; use rustc_ast::attr::HasAttrs; use rustc_ast::mut_visit::*; @@ -21,6 +12,7 @@ use rustc_feature::{Feature, Features, State as FeatureState}; use rustc_feature::{ ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES, }; +use rustc_parse::{parse_in, validate_attr}; use rustc_session::parse::{feature_err, ParseSess}; use rustc_span::edition::{Edition, ALL_EDITIONS}; use rustc_span::symbol::{sym, Symbol}; @@ -519,7 +511,7 @@ impl<'a> MutVisitor for StripUnconfigured<'a> { noop_flat_map_assoc_item(configure!(self, item), self) } - fn visit_mac(&mut self, _mac: &mut ast::Mac) { + fn visit_mac(&mut self, _mac: &mut ast::MacCall) { // Don't configure interpolated AST (cf. issue #34171). // Interpolated AST will get configured once the surrounding tokens are parsed. } @@ -538,12 +530,3 @@ impl<'a> MutVisitor for StripUnconfigured<'a> { fn is_cfg(attr: &Attribute) -> bool { attr.check_name(sym::cfg) } - -/// Process the potential `cfg` attributes on a module. -/// Also determine if the module should be included in this configuration. -pub fn process_configure_mod(sess: &ParseSess, cfg_mods: bool, attrs: &mut Vec) -> bool { - // Don't perform gated feature checking. - let mut strip_unconfigured = StripUnconfigured { sess, features: None }; - strip_unconfigured.process_cfg_attrs(attrs); - !cfg_mods || strip_unconfigured.in_cfg(&attrs) -} diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index effa89e8bfb21..51208906c2f2d 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -1,7 +1,9 @@ use crate::base::*; use crate::config::StripUnconfigured; +use crate::configure; use crate::hygiene::{ExpnData, ExpnId, ExpnKind, SyntaxContext}; use crate::mbe::macro_rules::annotate_err_with_kind; +use crate::module::{parse_external_mod, push_directory, Directory, DirectoryOwnership}; use crate::placeholders::{placeholder, PlaceholderExpander}; use crate::proc_macro::collect_derives; @@ -15,12 +17,10 @@ use rustc_ast::util::map_in_place::MapInPlace; use rustc_ast::visit::{self, AssocCtxt, Visitor}; use rustc_ast_pretty::pprust; use rustc_attr::{self as attr, is_builtin_attr, HasAttrs}; -use rustc_errors::{Applicability, FatalError, PResult}; +use rustc_errors::{Applicability, PResult}; use rustc_feature::Features; -use rustc_parse::configure; use rustc_parse::parser::Parser; use rustc_parse::validate_attr; -use rustc_parse::DirectoryOwnership; use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::parse::{feature_err, ParseSess}; @@ -204,7 +204,7 @@ ast_fragments! { } impl AstFragmentKind { - fn dummy(self, span: Span) -> AstFragment { + crate fn dummy(self, span: Span) -> AstFragment { self.make_from(DummyResult::any(span)).expect("couldn't create a dummy AST fragment") } @@ -271,7 +271,7 @@ pub struct Invocation { pub enum InvocationKind { Bang { - mac: ast::Mac, + mac: ast::MacCall, span: Span, }, Attr { @@ -408,7 +408,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let mut undetermined_invocations = Vec::new(); let (mut progress, mut force) = (false, !self.monotonic); loop { - let invoc = if let Some(invoc) = invocations.pop() { + let (invoc, res) = if let Some(invoc) = invocations.pop() { invoc } else { self.resolve_imports(); @@ -420,30 +420,51 @@ impl<'a, 'b> MacroExpander<'a, 'b> { continue; }; - let eager_expansion_root = - if self.monotonic { invoc.expansion_data.id } else { orig_expansion_data.id }; - let res = match self.cx.resolver.resolve_macro_invocation( - &invoc, - eager_expansion_root, - force, - ) { - Ok(res) => res, - Err(Indeterminate) => { - undetermined_invocations.push(invoc); - continue; + let res = match res { + Some(res) => res, + None => { + let eager_expansion_root = if self.monotonic { + invoc.expansion_data.id + } else { + orig_expansion_data.id + }; + match self.cx.resolver.resolve_macro_invocation( + &invoc, + eager_expansion_root, + force, + ) { + Ok(res) => res, + Err(Indeterminate) => { + // Cannot resolve, will retry this invocation later. + undetermined_invocations.push((invoc, None)); + continue; + } + } } }; - progress = true; let ExpansionData { depth, id: expn_id, .. } = invoc.expansion_data; self.cx.current_expansion = invoc.expansion_data.clone(); // FIXME(jseyfried): Refactor out the following logic let (expanded_fragment, new_invocations) = match res { - InvocationRes::Single(ext) => { - let fragment = self.expand_invoc(invoc, &ext.kind); - self.collect_invocations(fragment, &[]) - } + InvocationRes::Single(ext) => match self.expand_invoc(invoc, &ext.kind) { + ExpandResult::Ready(fragment) => self.collect_invocations(fragment, &[]), + ExpandResult::Retry(invoc, explanation) => { + if force { + // We are stuck, stop retrying and produce a dummy fragment. + let span = invoc.span(); + self.cx.span_err(span, &explanation); + let fragment = invoc.fragment_kind.dummy(span); + self.collect_invocations(fragment, &[]) + } else { + // Cannot expand, will retry this invocation later. + undetermined_invocations + .push((invoc, Some(InvocationRes::Single(ext)))); + continue; + } + } + }, InvocationRes::DeriveContainer(_exts) => { // FIXME: Consider using the derive resolutions (`_exts`) immediately, // instead of enqueuing the derives to be resolved again later. @@ -463,14 +484,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> { for path in derives { let expn_id = ExpnId::fresh(None); derive_placeholders.push(NodeId::placeholder_from_expn_id(expn_id)); - invocations.push(Invocation { - kind: InvocationKind::Derive { path, item: item.clone() }, - fragment_kind: invoc.fragment_kind, - expansion_data: ExpansionData { - id: expn_id, - ..invoc.expansion_data.clone() + invocations.push(( + Invocation { + kind: InvocationKind::Derive { path, item: item.clone() }, + fragment_kind: invoc.fragment_kind, + expansion_data: ExpansionData { + id: expn_id, + ..invoc.expansion_data.clone() + }, }, - }); + None, + )); } let fragment = invoc.fragment_kind.expect_from_annotatables(::std::iter::once(item)); @@ -478,6 +502,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } }; + progress = true; if expanded_fragments.len() < depth { expanded_fragments.push(Vec::new()); } @@ -535,7 +560,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { &mut self, mut fragment: AstFragment, extra_placeholders: &[NodeId], - ) -> (AstFragment, Vec) { + ) -> (AstFragment, Vec<(Invocation, Option)>) { // Resolve `$crate`s in the fragment for pretty-printing. self.cx.resolver.resolve_dollar_crates(); @@ -620,12 +645,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> { )) .emit(); self.cx.trace_macros_diag(); - FatalError.raise(); } /// A macro's expansion does not fit in this fragment kind. /// For example, a non-type macro in a type position. - fn error_wrong_fragment_kind(&mut self, kind: AstFragmentKind, mac: &ast::Mac, span: Span) { + fn error_wrong_fragment_kind(&mut self, kind: AstFragmentKind, mac: &ast::MacCall, span: Span) { let msg = format!( "non-{kind} macro in {kind} position: {path}", kind = kind.name(), @@ -635,17 +659,33 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx.trace_macros_diag(); } - fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstFragment { - if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit { - self.error_recursion_limit_reached(); + fn expand_invoc( + &mut self, + invoc: Invocation, + ext: &SyntaxExtensionKind, + ) -> ExpandResult { + let recursion_limit = + self.cx.reduced_recursion_limit.unwrap_or(self.cx.ecfg.recursion_limit); + if self.cx.current_expansion.depth > recursion_limit { + if self.cx.reduced_recursion_limit.is_none() { + self.error_recursion_limit_reached(); + } + + // Reduce the recursion limit by half each time it triggers. + self.cx.reduced_recursion_limit = Some(recursion_limit / 2); + + return ExpandResult::Ready(invoc.fragment_kind.dummy(invoc.span())); } let (fragment_kind, span) = (invoc.fragment_kind, invoc.span()); - match invoc.kind { + ExpandResult::Ready(match invoc.kind { InvocationKind::Bang { mac, .. } => match ext { SyntaxExtensionKind::Bang(expander) => { self.gate_proc_macro_expansion_kind(span, fragment_kind); - let tok_result = expander.expand(self.cx, span, mac.args.inner_tokens()); + let tok_result = match expander.expand(self.cx, span, mac.args.inner_tokens()) { + Err(_) => return ExpandResult::Ready(fragment_kind.dummy(span)), + Ok(ts) => ts, + }; self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span) } SyntaxExtensionKind::LegacyBang(expander) => { @@ -663,7 +703,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } _ => unreachable!(), }, - InvocationKind::Attr { attr, mut item, .. } => match ext { + InvocationKind::Attr { attr, mut item, derives, after_derive } => match ext { SyntaxExtensionKind::Attr(expander) => { self.gate_proc_macro_input(&item); self.gate_proc_macro_attr_item(span, &item); @@ -672,15 +712,35 @@ impl<'a, 'b> MacroExpander<'a, 'b> { if let MacArgs::Eq(..) = attr_item.args { self.cx.span_err(span, "key-value macro attributes are not supported"); } - let tok_result = - expander.expand(self.cx, span, attr_item.args.inner_tokens(), tokens); + let inner_tokens = attr_item.args.inner_tokens(); + let tok_result = match expander.expand(self.cx, span, inner_tokens, tokens) { + Err(_) => return ExpandResult::Ready(fragment_kind.dummy(span)), + Ok(ts) => ts, + }; self.parse_ast_fragment(tok_result, fragment_kind, &attr_item.path, span) } SyntaxExtensionKind::LegacyAttr(expander) => { match validate_attr::parse_meta(self.cx.parse_sess, &attr) { Ok(meta) => { - let item = expander.expand(self.cx, span, &meta, item); - fragment_kind.expect_from_annotatables(item) + let items = match expander.expand(self.cx, span, &meta, item) { + ExpandResult::Ready(items) => items, + ExpandResult::Retry(item, explanation) => { + // Reassemble the original invocation for retrying. + return ExpandResult::Retry( + Invocation { + kind: InvocationKind::Attr { + attr, + item, + derives, + after_derive, + }, + ..invoc + }, + explanation, + ); + } + }; + fragment_kind.expect_from_annotatables(items) } Err(mut err) => { err.emit(); @@ -702,19 +762,31 @@ impl<'a, 'b> MacroExpander<'a, 'b> { SyntaxExtensionKind::Derive(expander) | SyntaxExtensionKind::LegacyDerive(expander) => { if !item.derive_allowed() { - return fragment_kind.dummy(span); + return ExpandResult::Ready(fragment_kind.dummy(span)); } if let SyntaxExtensionKind::Derive(..) = ext { self.gate_proc_macro_input(&item); } let meta = ast::MetaItem { kind: ast::MetaItemKind::Word, span, path }; - let items = expander.expand(self.cx, span, &meta, item); + let items = match expander.expand(self.cx, span, &meta, item) { + ExpandResult::Ready(items) => items, + ExpandResult::Retry(item, explanation) => { + // Reassemble the original invocation for retrying. + return ExpandResult::Retry( + Invocation { + kind: InvocationKind::Derive { path: meta.path, item }, + ..invoc + }, + explanation, + ); + } + }; fragment_kind.expect_from_annotatables(items) } _ => unreachable!(), }, InvocationKind::DeriveContainer { .. } => unreachable!(), - } + }) } fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) { @@ -768,7 +840,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { visit::walk_item(self, item); } - fn visit_mac(&mut self, _: &'ast ast::Mac) {} + fn visit_mac(&mut self, _: &'ast ast::MacCall) {} } if !self.cx.ecfg.proc_macro_hygiene() { @@ -933,7 +1005,7 @@ pub fn ensure_complete_parse<'a>( struct InvocationCollector<'a, 'b> { cx: &'a mut ExtCtxt<'b>, cfg: StripUnconfigured<'a>, - invocations: Vec, + invocations: Vec<(Invocation, Option)>, monotonic: bool, } @@ -955,19 +1027,27 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { }; let expn_id = ExpnId::fresh(expn_data); let vis = kind.placeholder_visibility(); - self.invocations.push(Invocation { - kind, - fragment_kind, - expansion_data: ExpansionData { - id: expn_id, - depth: self.cx.current_expansion.depth + 1, - ..self.cx.current_expansion.clone() + self.invocations.push(( + Invocation { + kind, + fragment_kind, + expansion_data: ExpansionData { + id: expn_id, + depth: self.cx.current_expansion.depth + 1, + ..self.cx.current_expansion.clone() + }, }, - }); + None, + )); placeholder(fragment_kind, NodeId::placeholder_from_expn_id(expn_id), vis) } - fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: AstFragmentKind) -> AstFragment { + fn collect_bang( + &mut self, + mac: ast::MacCall, + span: Span, + kind: AstFragmentKind, + ) -> AstFragment { self.collect(kind, InvocationKind::Bang { mac, span }) } @@ -1065,6 +1145,8 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { // macros are expanded before any lint passes so this warning has to be hardcoded if attr.has_name(sym::derive) { self.cx + .parse_sess() + .span_diagnostic .struct_span_warn(attr.span, "`#[derive]` does nothing on macro invocations") .note("this may become a hard error in a future release") .emit(); @@ -1110,7 +1192,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { .into_inner(); } - if let ast::ExprKind::Mac(mac) = expr.kind { + if let ast::ExprKind::MacCall(mac) = expr.kind { self.check_attributes(&expr.attrs); self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr().into_inner() } else { @@ -1257,7 +1339,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { .map(|expr| expr.into_inner()); } - if let ast::ExprKind::Mac(mac) = expr.kind { + if let ast::ExprKind::MacCall(mac) = expr.kind { self.check_attributes(&expr.attrs); self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr) .make_opt_expr() @@ -1274,12 +1356,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { fn visit_pat(&mut self, pat: &mut P) { self.cfg.configure_pat(pat); match pat.kind { - PatKind::Mac(_) => {} + PatKind::MacCall(_) => {} _ => return noop_visit_pat(pat, self), } visit_clobber(pat, |mut pat| match mem::replace(&mut pat.kind, PatKind::Wild) { - PatKind::Mac(mac) => self.collect_bang(mac, pat.span, AstFragmentKind::Pat).make_pat(), + PatKind::MacCall(mac) => { + self.collect_bang(mac, pat.span, AstFragmentKind::Pat).make_pat() + } _ => unreachable!(), }); } @@ -1311,7 +1395,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } } - if let StmtKind::Mac(mac) = stmt.kind { + if let StmtKind::MacCall(mac) = stmt.kind { let (mac, style, attrs) = mac.into_inner(); self.check_attributes(&attrs); let mut placeholder = @@ -1359,59 +1443,83 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { .make_items(); } + let mut attrs = mem::take(&mut item.attrs); // We do this to please borrowck. + let ident = item.ident; + let span = item.span; + match item.kind { - ast::ItemKind::Mac(..) => { + ast::ItemKind::MacCall(..) => { + item.attrs = attrs; self.check_attributes(&item.attrs); item.and_then(|item| match item.kind { - ItemKind::Mac(mac) => self - .collect( - AstFragmentKind::Items, - InvocationKind::Bang { mac, span: item.span }, - ) + ItemKind::MacCall(mac) => self + .collect(AstFragmentKind::Items, InvocationKind::Bang { mac, span }) .make_items(), _ => unreachable!(), }) } - ast::ItemKind::Mod(ast::Mod { inner, inline, .. }) - if item.ident != Ident::invalid() => - { - let orig_directory_ownership = self.cx.current_expansion.directory_ownership; + ast::ItemKind::Mod(ref mut old_mod @ ast::Mod { .. }) if ident != Ident::invalid() => { + let sess = self.cx.parse_sess; + let orig_ownership = self.cx.current_expansion.directory_ownership; let mut module = (*self.cx.current_expansion.module).clone(); - module.mod_path.push(item.ident); - if inline { - if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, sym::path) { - self.cx.current_expansion.directory_ownership = - DirectoryOwnership::Owned { relative: None }; - module.directory.push(&*path.as_str()); - } else { - module.directory.push(&*item.ident.as_str()); - } + let pushed = &mut false; // Record `parse_external_mod` pushing so we can pop. + let dir = Directory { ownership: orig_ownership, path: module.directory }; + let Directory { ownership, path } = if old_mod.inline { + // Inline `mod foo { ... }`, but we still need to push directories. + item.attrs = attrs; + push_directory(ident, &item.attrs, dir) } else { - let path = self.cx.parse_sess.source_map().span_to_unmapped_path(inner); - let mut path = match path { - FileName::Real(path) => path, - other => PathBuf::from(other.to_string()), + // We have an outline `mod foo;` so we need to parse the file. + let (new_mod, dir) = + parse_external_mod(sess, ident, span, dir, &mut attrs, pushed); + + let krate = ast::Crate { + span: new_mod.inner, + module: new_mod, + attrs, + proc_macros: vec![], }; - let directory_ownership = match path.file_name().unwrap().to_str() { - Some("mod.rs") => DirectoryOwnership::Owned { relative: None }, - Some(_) => DirectoryOwnership::Owned { relative: Some(item.ident) }, - None => DirectoryOwnership::UnownedViaMod, + if let Some(extern_mod_loaded) = self.cx.extern_mod_loaded { + extern_mod_loaded(&krate); + } + + *old_mod = krate.module; + item.attrs = krate.attrs; + // File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure. + item = match self.configure(item) { + Some(node) => node, + None => { + if *pushed { + sess.included_mod_stack.borrow_mut().pop(); + } + return Default::default(); + } }; - path.pop(); - module.directory = path; - self.cx.current_expansion.directory_ownership = directory_ownership; - } + dir + }; + // Set the module info before we flat map. + self.cx.current_expansion.directory_ownership = ownership; + module.directory = path; + module.mod_path.push(ident); let orig_module = mem::replace(&mut self.cx.current_expansion.module, Rc::new(module)); + let result = noop_flat_map_item(item, self); + + // Restore the module info. self.cx.current_expansion.module = orig_module; - self.cx.current_expansion.directory_ownership = orig_directory_ownership; + self.cx.current_expansion.directory_ownership = orig_ownership; + if *pushed { + sess.included_mod_stack.borrow_mut().pop(); + } result } - - _ => noop_flat_map_item(item, self), + _ => { + item.attrs = attrs; + noop_flat_map_item(item, self) + } } } @@ -1432,10 +1540,10 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } match item.kind { - ast::AssocItemKind::Macro(..) => { + ast::AssocItemKind::MacCall(..) => { self.check_attributes(&item.attrs); item.and_then(|item| match item.kind { - ast::AssocItemKind::Macro(mac) => self + ast::AssocItemKind::MacCall(mac) => self .collect_bang(mac, item.span, AstFragmentKind::TraitItems) .make_trait_items(), _ => unreachable!(), @@ -1462,10 +1570,10 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } match item.kind { - ast::AssocItemKind::Macro(..) => { + ast::AssocItemKind::MacCall(..) => { self.check_attributes(&item.attrs); item.and_then(|item| match item.kind { - ast::AssocItemKind::Macro(mac) => self + ast::AssocItemKind::MacCall(mac) => self .collect_bang(mac, item.span, AstFragmentKind::ImplItems) .make_impl_items(), _ => unreachable!(), @@ -1477,12 +1585,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { fn visit_ty(&mut self, ty: &mut P) { match ty.kind { - ast::TyKind::Mac(_) => {} + ast::TyKind::MacCall(_) => {} _ => return noop_visit_ty(ty, self), }; visit_clobber(ty, |mut ty| match mem::replace(&mut ty.kind, ast::TyKind::Err) { - ast::TyKind::Mac(mac) => self.collect_bang(mac, ty.span, AstFragmentKind::Ty).make_ty(), + ast::TyKind::MacCall(mac) => { + self.collect_bang(mac, ty.span, AstFragmentKind::Ty).make_ty() + } _ => unreachable!(), }); } @@ -1511,10 +1621,10 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } match foreign_item.kind { - ast::ForeignItemKind::Macro(..) => { + ast::ForeignItemKind::MacCall(..) => { self.check_attributes(&foreign_item.attrs); foreign_item.and_then(|item| match item.kind { - ast::ForeignItemKind::Macro(mac) => self + ast::ForeignItemKind::MacCall(mac) => self .collect_bang(mac, item.span, AstFragmentKind::ForeignItems) .make_foreign_items(), _ => unreachable!(), diff --git a/src/librustc_expand/lib.rs b/src/librustc_expand/lib.rs index f119c956ced04..876a26de3fb7e 100644 --- a/src/librustc_expand/lib.rs +++ b/src/librustc_expand/lib.rs @@ -1,31 +1,14 @@ +#![feature(bool_to_option)] #![feature(cow_is_borrowed)] #![feature(crate_visibility_modifier)] #![feature(decl_macro)] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_internals)] #![feature(proc_macro_span)] +#![feature(try_blocks)] extern crate proc_macro as pm; -// A variant of 'try!' that panics on an Err. This is used as a crutch on the -// way towards a non-panic!-prone parser. It should be used for fatal parsing -// errors; eventually we plan to convert all code using panictry to just use -// normal try. -#[macro_export] -macro_rules! panictry { - ($e:expr) => {{ - use rustc_errors::FatalError; - use std::result::Result::{Err, Ok}; - match $e { - Ok(e) => e, - Err(mut e) => { - e.emit(); - FatalError.raise() - } - } - }}; -} - mod placeholders; mod proc_macro_server; @@ -33,8 +16,10 @@ pub use mbe::macro_rules::compile_declarative_macro; crate use rustc_span::hygiene; pub mod base; pub mod build; +#[macro_use] +pub mod config; pub mod expand; -pub use rustc_parse::config; +pub mod module; pub mod proc_macro; crate mod mbe; diff --git a/src/librustc_expand/mbe/macro_check.rs b/src/librustc_expand/mbe/macro_check.rs index 6eb834beac652..582c26162ed6d 100644 --- a/src/librustc_expand/mbe/macro_check.rs +++ b/src/librustc_expand/mbe/macro_check.rs @@ -112,7 +112,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_session::lint::builtin::META_VARIABLE_MISUSE; use rustc_session::parse::ParseSess; use rustc_span::symbol::kw; -use rustc_span::{symbol::Ident, MultiSpan, Span}; +use rustc_span::{symbol::MacroRulesNormalizedIdent, MultiSpan, Span}; use smallvec::SmallVec; @@ -179,7 +179,7 @@ struct BinderInfo { } /// An environment of meta-variables to their binder information. -type Binders = FxHashMap; +type Binders = FxHashMap; /// The state at which we entered a macro definition in the RHS of another macro definition. struct MacroState<'a> { @@ -245,6 +245,7 @@ fn check_binders( if macros.is_empty() { sess.span_diagnostic.span_bug(span, "unexpected MetaVar in lhs"); } + let name = MacroRulesNormalizedIdent::new(name); // There are 3 possibilities: if let Some(prev_info) = binders.get(&name) { // 1. The meta-variable is already bound in the current LHS: This is an error. @@ -264,6 +265,7 @@ fn check_binders( if !macros.is_empty() { sess.span_diagnostic.span_bug(span, "unexpected MetaVarDecl in nested lhs"); } + let name = MacroRulesNormalizedIdent::new(name); if let Some(prev_info) = get_binder_info(macros, binders, name) { // Duplicate binders at the top-level macro definition are errors. The lint is only // for nested macro definitions. @@ -300,7 +302,7 @@ fn check_binders( fn get_binder_info<'a>( mut macros: &'a Stack<'a, MacroState<'a>>, binders: &'a Binders, - name: Ident, + name: MacroRulesNormalizedIdent, ) -> Option<&'a BinderInfo> { binders.get(&name).or_else(|| macros.find_map(|state| state.binders.get(&name))) } @@ -331,6 +333,7 @@ fn check_occurrences( sess.span_diagnostic.span_bug(span, "unexpected MetaVarDecl in rhs") } TokenTree::MetaVar(span, name) => { + let name = MacroRulesNormalizedIdent::new(name); check_ops_is_prefix(sess, node_id, macros, binders, ops, span, name); } TokenTree::Delimited(_, ref del) => { @@ -419,10 +422,10 @@ fn check_nested_occurrences( | (NestedMacroState::MacroName, &TokenTree::Delimited(_, ref del)) if del.delim == DelimToken::Brace => { - let legacy = state == NestedMacroState::MacroRulesNotName; + let macro_rules = state == NestedMacroState::MacroRulesNotName; state = NestedMacroState::Empty; let rest = - check_nested_macro(sess, node_id, legacy, &del.tts, &nested_macros, valid); + check_nested_macro(sess, node_id, macro_rules, &del.tts, &nested_macros, valid); // If we did not check the whole macro definition, then check the rest as if outside // the macro definition. check_nested_occurrences( @@ -493,21 +496,21 @@ fn check_nested_occurrences( /// Arguments: /// - `sess` is used to emit diagnostics and lints /// - `node_id` is used to emit lints -/// - `legacy` specifies whether the macro is legacy +/// - `macro_rules` specifies whether the macro is `macro_rules` /// - `tts` is checked as a list of (LHS) => {RHS} /// - `macros` is the stack of outer macros /// - `valid` is set in case of errors fn check_nested_macro( sess: &ParseSess, node_id: NodeId, - legacy: bool, + macro_rules: bool, tts: &[TokenTree], macros: &Stack<'_, MacroState<'_>>, valid: &mut bool, ) -> usize { let n = tts.len(); let mut i = 0; - let separator = if legacy { TokenKind::Semi } else { TokenKind::Comma }; + let separator = if macro_rules { TokenKind::Semi } else { TokenKind::Comma }; loop { // We expect 3 token trees: `(LHS) => {RHS}`. The separator is checked after. if i + 2 >= n @@ -522,7 +525,7 @@ fn check_nested_macro( let mut binders = Binders::default(); check_binders(sess, node_id, lhs, macros, &mut binders, &Stack::Empty, valid); check_occurrences(sess, node_id, rhs, macros, &binders, &Stack::Empty, valid); - // Since the last semicolon is optional for legacy macros and decl_macro are not terminated, + // Since the last semicolon is optional for `macro_rules` macros and decl_macro are not terminated, // we increment our checked position by how many token trees we already checked (the 3 // above) before checking for the separator. i += 3; @@ -552,7 +555,7 @@ fn check_ops_is_prefix( binders: &Binders, ops: &Stack<'_, KleeneToken>, span: Span, - name: Ident, + name: MacroRulesNormalizedIdent, ) { let macros = macros.push(MacroState { binders, ops: ops.into() }); // Accumulates the stacks the operators of each state until (and including when) the @@ -598,7 +601,7 @@ fn ops_is_prefix( sess: &ParseSess, node_id: NodeId, span: Span, - name: Ident, + name: MacroRulesNormalizedIdent, binder_ops: &[KleeneToken], occurrence_ops: &[KleeneToken], ) { diff --git a/src/librustc_expand/mbe/macro_parser.rs b/src/librustc_expand/mbe/macro_parser.rs index 6d4d7f5b4f394..e868b7e36aac5 100644 --- a/src/librustc_expand/mbe/macro_parser.rs +++ b/src/librustc_expand/mbe/macro_parser.rs @@ -76,15 +76,15 @@ use TokenTreeOrTokenTreeSlice::*; use crate::mbe::{self, TokenTree}; -use rustc_ast::ast::{Ident, Name}; +use rustc_ast::ast::Name; use rustc_ast::ptr::P; use rustc_ast::token::{self, DocComment, Nonterminal, Token}; use rustc_ast_pretty::pprust; use rustc_parse::parser::{FollowedByType, Parser, PathStyle}; use rustc_session::parse::ParseSess; -use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::symbol::{kw, sym, Ident, MacroRulesNormalizedIdent, Symbol}; -use rustc_errors::{FatalError, PResult}; +use rustc_errors::PResult; use rustc_span::Span; use smallvec::{smallvec, SmallVec}; @@ -271,11 +271,13 @@ crate enum ParseResult { Failure(Token, &'static str), /// Fatal error (malformed macro?). Abort compilation. Error(rustc_span::Span, String), + ErrorReported, } -/// A `ParseResult` where the `Success` variant contains a mapping of `Ident`s to `NamedMatch`es. -/// This represents the mapping of metavars to the token trees they bind to. -crate type NamedParseResult = ParseResult>; +/// A `ParseResult` where the `Success` variant contains a mapping of +/// `MacroRulesNormalizedIdent`s to `NamedMatch`es. This represents the mapping +/// of metavars to the token trees they bind to. +crate type NamedParseResult = ParseResult>; /// Count how many metavars are named in the given matcher `ms`. pub(super) fn count_names(ms: &[TokenTree]) -> usize { @@ -368,7 +370,7 @@ fn nameize>( sess: &ParseSess, m: &TokenTree, res: &mut I, - ret_val: &mut FxHashMap, + ret_val: &mut FxHashMap, ) -> Result<(), (rustc_span::Span, String)> { match *m { TokenTree::Sequence(_, ref seq) => { @@ -386,7 +388,9 @@ fn nameize>( return Err((span, "missing fragment specifier".to_string())); } } - TokenTree::MetaVarDecl(sp, bind_name, _) => match ret_val.entry(bind_name) { + TokenTree::MetaVarDecl(sp, bind_name, _) => match ret_val + .entry(MacroRulesNormalizedIdent::new(bind_name)) + { Vacant(spot) => { spot.insert(res.next().unwrap()); } @@ -649,6 +653,7 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na Success(_) => {} Failure(token, msg) => return Failure(token, msg), Error(sp, msg) => return Error(sp, msg), + ErrorReported => return ErrorReported, } // inner parse loop handled all cur_items, so it's empty @@ -732,10 +737,11 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na let mut item = bb_items.pop().unwrap(); if let TokenTree::MetaVarDecl(span, _, ident) = item.top_elts.get_tt(item.idx) { let match_cur = item.match_cur; - item.push_match( - match_cur, - MatchedNonterminal(Lrc::new(parse_nt(parser.to_mut(), span, ident.name))), - ); + let nt = match parse_nt(parser.to_mut(), span, ident.name) { + Err(()) => return ErrorReported, + Ok(nt) => nt, + }; + item.push_match(match_cur, MatchedNonterminal(Lrc::new(nt))); item.idx += 1; item.match_cur += 1; } else { @@ -775,7 +781,7 @@ fn may_begin_with(token: &Token, name: Name) -> bool { } sym::ty => token.can_begin_type(), sym::ident => get_macro_ident(token).is_some(), - sym::literal => token.can_begin_literal_or_bool(), + sym::literal => token.can_begin_literal_maybe_minus(), sym::vis => match token.kind { // The follow-set of :vis + "priv" keyword + interpolated token::Comma | token::Ident(..) | token::Interpolated(_) => true, @@ -846,20 +852,16 @@ fn may_begin_with(token: &Token, name: Name) -> bool { /// # Returns /// /// The parsed non-terminal. -fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Nonterminal { +fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Result { // FIXME(Centril): Consider moving this to `parser.rs` to make // the visibilities of the methods used below `pub(super)` at most. - if name == sym::tt { - return token::NtTT(p.parse_token_tree()); - } - match parse_nt_inner(p, sp, name) { - Ok(nt) => nt, - Err(mut err) => { - err.emit(); - FatalError.raise(); - } + return Ok(token::NtTT(p.parse_token_tree())); } + parse_nt_inner(p, sp, name).map_err(|mut err| { + err.span_label(sp, format!("while parsing argument for this `{}` macro fragment", name)) + .emit() + }) } fn parse_nt_inner<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> PResult<'a, Nonterminal> { diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs index 3040a9aefbb30..b9477be57ddda 100644 --- a/src/librustc_expand/mbe/macro_rules.rs +++ b/src/librustc_expand/mbe/macro_rules.rs @@ -1,10 +1,10 @@ -use crate::base::{DummyResult, ExpansionData, ExtCtxt, MacResult, TTMacroExpander}; +use crate::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander}; use crate::base::{SyntaxExtension, SyntaxExtensionKind}; use crate::expand::{ensure_complete_parse, parse_ast_fragment, AstFragment, AstFragmentKind}; use crate::mbe; use crate::mbe::macro_check; use crate::mbe::macro_parser::parse_tt; -use crate::mbe::macro_parser::{Error, Failure, Success}; +use crate::mbe::macro_parser::{Error, ErrorReported, Failure, Success}; use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq}; use crate::mbe::transcribe::transcribe; @@ -15,14 +15,13 @@ use rustc_ast_pretty::pprust; use rustc_attr::{self as attr, TransparencyError}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; -use rustc_errors::{Applicability, DiagnosticBuilder, FatalError}; +use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_feature::Features; use rustc_parse::parser::Parser; -use rustc_parse::Directory; use rustc_session::parse::ParseSess; use rustc_span::edition::Edition; use rustc_span::hygiene::Transparency; -use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::symbol::{kw, sym, MacroRulesNormalizedIdent, Symbol}; use rustc_span::Span; use log::debug; @@ -84,41 +83,56 @@ fn suggest_slice_pat(e: &mut DiagnosticBuilder<'_>, site_span: Span, parser: &Pa ); } +fn emit_frag_parse_err( + mut e: DiagnosticBuilder<'_>, + parser: &Parser<'_>, + site_span: Span, + macro_ident: ast::Ident, + arm_span: Span, + kind: AstFragmentKind, +) { + if parser.token == token::Eof && e.message().ends_with(", found ``") { + if !e.span.is_dummy() { + // early end of macro arm (#52866) + e.replace_span_with(parser.sess.source_map().next_point(parser.token.span)); + } + let msg = &e.message[0]; + e.message[0] = ( + format!( + "macro expansion ends with an incomplete expression: {}", + msg.0.replace(", found ``", ""), + ), + msg.1, + ); + } + if e.span.is_dummy() { + // Get around lack of span in error (#30128) + e.replace_span_with(site_span); + if !parser.sess.source_map().is_imported(arm_span) { + e.span_label(arm_span, "in this macro arm"); + } + } else if parser.sess.source_map().is_imported(parser.token.span) { + e.span_label(site_span, "in this macro invocation"); + } + match kind { + AstFragmentKind::Pat if macro_ident.name == sym::vec => { + suggest_slice_pat(&mut e, site_span, parser); + } + _ => annotate_err_with_kind(&mut e, kind, site_span), + }; + e.emit(); +} + impl<'a> ParserAnyMacro<'a> { crate fn make(mut self: Box>, kind: AstFragmentKind) -> AstFragment { let ParserAnyMacro { site_span, macro_ident, ref mut parser, arm_span } = *self; - let fragment = panictry!(parse_ast_fragment(parser, kind).map_err(|mut e| { - if parser.token == token::Eof && e.message().ends_with(", found ``") { - if !e.span.is_dummy() { - // early end of macro arm (#52866) - e.replace_span_with(parser.sess.source_map().next_point(parser.token.span)); - } - let msg = &e.message[0]; - e.message[0] = ( - format!( - "macro expansion ends with an incomplete expression: {}", - msg.0.replace(", found ``", ""), - ), - msg.1, - ); - } - if e.span.is_dummy() { - // Get around lack of span in error (#30128) - e.replace_span_with(site_span); - if !parser.sess.source_map().is_imported(arm_span) { - e.span_label(arm_span, "in this macro arm"); - } - } else if parser.sess.source_map().is_imported(parser.token.span) { - e.span_label(site_span, "in this macro invocation"); + let fragment = match parse_ast_fragment(parser, kind) { + Ok(f) => f, + Err(err) => { + emit_frag_parse_err(err, parser, site_span, macro_ident, arm_span, kind); + return kind.dummy(site_span); } - match kind { - AstFragmentKind::Pat if macro_ident.name == sym::vec => { - suggest_slice_pat(&mut e, site_span, parser); - } - _ => annotate_err_with_kind(&mut e, kind, site_span), - }; - e - })); + }; // We allow semicolons at the end of expressions -- e.g., the semicolon in // `macro_rules! m { () => { panic!(); } }` isn't parsed by `.parse_expr()`, @@ -166,6 +180,14 @@ impl TTMacroExpander for MacroRulesMacroExpander { } } +fn macro_rules_dummy_expander<'cx>( + _: &'cx mut ExtCtxt<'_>, + span: Span, + _: TokenStream, +) -> Box { + DummyResult::any(span) +} + fn trace_macros_note(cx_expansions: &mut FxHashMap>, sp: Span, message: String) { let sp = sp.macro_backtrace().last().map(|trace| trace.call_site).unwrap_or(sp); cx_expansions.entry(sp).or_default().push(message); @@ -182,6 +204,8 @@ fn generic_extension<'cx>( lhses: &[mbe::TokenTree], rhses: &[mbe::TokenTree], ) -> Box { + let sess = cx.parse_sess; + if cx.trace_macros() { let msg = format!("expanding `{}! {{ {} }}`", name, pprust::tts_to_string(arg.clone())); trace_macros_note(&mut cx.expansions, sp, msg); @@ -209,7 +233,7 @@ fn generic_extension<'cx>( // hacky, but speeds up the `html5ever` benchmark significantly. (Issue // 68836 suggests a more comprehensive but more complex change to deal with // this situation.) - let parser = parser_from_cx(&cx.current_expansion, &cx.parse_sess, arg.clone()); + let parser = parser_from_cx(sess, arg.clone()); for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers @@ -222,14 +246,13 @@ fn generic_extension<'cx>( // This is used so that if a matcher is not `Success(..)`ful, // then the spans which became gated when parsing the unsuccessful matcher // are not recorded. On the first `Success(..)`ful matcher, the spans are merged. - let mut gated_spans_snapshot = - mem::take(&mut *cx.parse_sess.gated_spans.spans.borrow_mut()); + let mut gated_spans_snapshot = mem::take(&mut *sess.gated_spans.spans.borrow_mut()); match parse_tt(&mut Cow::Borrowed(&parser), lhs_tt) { Success(named_matches) => { // The matcher was `Success(..)`ful. // Merge the gated spans from parsing the matcher with the pre-existing ones. - cx.parse_sess.gated_spans.merge(gated_spans_snapshot); + sess.gated_spans.merge(gated_spans_snapshot); let rhs = match rhses[i] { // ignore delimiters @@ -240,7 +263,13 @@ fn generic_extension<'cx>( let rhs_spans = rhs.iter().map(|t| t.span()).collect::>(); // rhs has holes ( `$id` and `$(...)` that need filled) - let mut tts = transcribe(cx, &named_matches, rhs, transparency); + let mut tts = match transcribe(cx, &named_matches, rhs, transparency) { + Ok(tts) => tts, + Err(mut err) => { + err.emit(); + return DummyResult::any(arm_span); + } + }; // Replace all the tokens for the corresponding positions in the macro, to maintain // proper positions in error reporting, while maintaining the macro_backtrace. @@ -258,13 +287,7 @@ fn generic_extension<'cx>( trace_macros_note(&mut cx.expansions, sp, msg); } - let directory = Directory { - path: cx.current_expansion.module.directory.clone(), - ownership: cx.current_expansion.directory_ownership, - }; - let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), true, false, None); - p.root_module_name = - cx.current_expansion.module.mod_path.last().map(|id| id.to_string()); + let mut p = Parser::new(sess, tts, false, None); p.last_type_ascription = cx.current_expansion.prior_type_ascription; // Let the context choose how to interpret the result. @@ -284,12 +307,17 @@ fn generic_extension<'cx>( Some((ref best_token, _)) if best_token.span.lo() >= token.span.lo() => {} _ => best_failure = Some((token, msg)), }, - Error(err_sp, ref msg) => cx.span_fatal(err_sp.substitute_dummy(sp), &msg[..]), + Error(err_sp, ref msg) => { + let span = err_sp.substitute_dummy(sp); + cx.struct_span_err(span, &msg).emit(); + return DummyResult::any(span); + } + ErrorReported => return DummyResult::any(sp), } // The matcher was not `Success(..)`ful. // Restore to the state before snapshotting and maybe try again. - mem::swap(&mut gated_spans_snapshot, &mut cx.parse_sess.gated_spans.spans.borrow_mut()); + mem::swap(&mut gated_spans_snapshot, &mut sess.gated_spans.spans.borrow_mut()); } drop(parser); @@ -298,7 +326,7 @@ fn generic_extension<'cx>( let mut err = cx.struct_span_err(span, &parse_failure_msg(&token)); err.span_label(span, label); if !def_span.is_dummy() && !cx.source_map().is_imported(def_span) { - err.span_label(cx.source_map().def_span(def_span), "when calling this macro"); + err.span_label(cx.source_map().guess_head_span(def_span), "when calling this macro"); } // Check whether there's a missing comma in this macro call, like `println!("{}" a);` @@ -309,8 +337,7 @@ fn generic_extension<'cx>( mbe::TokenTree::Delimited(_, ref delim) => &delim.tts[..], _ => continue, }; - let parser = parser_from_cx(&cx.current_expansion, &cx.parse_sess, arg.clone()); - match parse_tt(&mut Cow::Borrowed(&parser), lhs_tt) { + match parse_tt(&mut Cow::Borrowed(&parser_from_cx(sess, arg.clone())), lhs_tt) { Success(_) => { if comma_span.is_dummy() { err.note("you might be missing a comma"); @@ -344,14 +371,26 @@ pub fn compile_declarative_macro( def: &ast::Item, edition: Edition, ) -> SyntaxExtension { + let mk_syn_ext = |expander| { + SyntaxExtension::new( + sess, + SyntaxExtensionKind::LegacyBang(expander), + def.span, + Vec::new(), + edition, + def.ident.name, + &def.attrs, + ) + }; + let diag = &sess.span_diagnostic; let lhs_nm = ast::Ident::new(sym::lhs, def.span); let rhs_nm = ast::Ident::new(sym::rhs, def.span); let tt_spec = ast::Ident::new(sym::tt, def.span); // Parse the macro_rules! invocation - let (is_legacy, body) = match &def.kind { - ast::ItemKind::MacroDef(macro_def) => (macro_def.legacy, macro_def.body.inner_tokens()), + let (macro_rules, body) = match &def.kind { + ast::ItemKind::MacroDef(def) => (def.macro_rules, def.body.inner_tokens()), _ => unreachable!(), }; @@ -370,7 +409,7 @@ pub fn compile_declarative_macro( mbe::TokenTree::MetaVarDecl(def.span, rhs_nm, tt_spec), ], separator: Some(Token::new( - if is_legacy { token::Semi } else { token::Comma }, + if macro_rules { token::Semi } else { token::Comma }, def.span, )), kleene: mbe::KleeneToken::new(mbe::KleeneOp::OneOrMore, def.span), @@ -382,7 +421,7 @@ pub fn compile_declarative_macro( DelimSpan::dummy(), Lrc::new(mbe::SequenceRepetition { tts: vec![mbe::TokenTree::token( - if is_legacy { token::Semi } else { token::Comma }, + if macro_rules { token::Semi } else { token::Comma }, def.span, )], separator: None, @@ -392,26 +431,28 @@ pub fn compile_declarative_macro( ), ]; - let parser = Parser::new(sess, body, None, true, true, rustc_parse::MACRO_ARGUMENTS); + let parser = Parser::new(sess, body, true, rustc_parse::MACRO_ARGUMENTS); let argument_map = match parse_tt(&mut Cow::Borrowed(&parser), &argument_gram) { Success(m) => m, Failure(token, msg) => { let s = parse_failure_msg(&token); let sp = token.span.substitute_dummy(def.span); - let mut err = sess.span_diagnostic.struct_span_fatal(sp, &s); - err.span_label(sp, msg); - err.emit(); - FatalError.raise(); + sess.span_diagnostic.struct_span_err(sp, &s).span_label(sp, msg).emit(); + return mk_syn_ext(Box::new(macro_rules_dummy_expander)); } - Error(sp, s) => { - sess.span_diagnostic.span_fatal(sp.substitute_dummy(def.span), &s).raise(); + Error(sp, msg) => { + sess.span_diagnostic.struct_span_err(sp.substitute_dummy(def.span), &msg).emit(); + return mk_syn_ext(Box::new(macro_rules_dummy_expander)); + } + ErrorReported => { + return mk_syn_ext(Box::new(macro_rules_dummy_expander)); } }; let mut valid = true; // Extract the arguments: - let lhses = match argument_map[&lhs_nm] { + let lhses = match argument_map[&MacroRulesNormalizedIdent::new(lhs_nm)] { MatchedSeq(ref s) => s .iter() .map(|m| { @@ -428,7 +469,7 @@ pub fn compile_declarative_macro( _ => sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs"), }; - let rhses = match argument_map[&rhs_nm] { + let rhses = match argument_map[&MacroRulesNormalizedIdent::new(rhs_nm)] { MatchedSeq(ref s) => s .iter() .map(|m| { @@ -456,7 +497,7 @@ pub fn compile_declarative_macro( // that is not lint-checked and trigger the "failed to process buffered lint here" bug. valid &= macro_check::check_meta_variables(sess, ast::CRATE_NODE_ID, def.span, &lhses, &rhses); - let (transparency, transparency_error) = attr::find_transparency(&def.attrs, is_legacy); + let (transparency, transparency_error) = attr::find_transparency(&def.attrs, macro_rules); match transparency_error { Some(TransparencyError::UnknownTransparency(value, span)) => { diag.span_err(span, &format!("unknown macro transparency: `{}`", value)) @@ -467,24 +508,14 @@ pub fn compile_declarative_macro( None => {} } - let expander: Box<_> = Box::new(MacroRulesMacroExpander { + mk_syn_ext(Box::new(MacroRulesMacroExpander { name: def.ident, span: def.span, transparency, lhses, rhses, valid, - }); - - SyntaxExtension::new( - sess, - SyntaxExtensionKind::LegacyBang(expander), - def.span, - Vec::new(), - edition, - def.ident.name, - &def.attrs, - ) + })) } fn check_lhs_nt_follows( @@ -1209,16 +1240,8 @@ fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String { } } -fn parser_from_cx<'cx>( - current_expansion: &'cx ExpansionData, - sess: &'cx ParseSess, - tts: TokenStream, -) -> Parser<'cx> { - let directory = Directory { - path: current_expansion.module.directory.clone(), - ownership: current_expansion.directory_ownership, - }; - Parser::new(sess, tts, Some(directory), true, true, rustc_parse::MACRO_ARGUMENTS) +fn parser_from_cx(sess: &ParseSess, tts: TokenStream) -> Parser<'_> { + Parser::new(sess, tts, true, rustc_parse::MACRO_ARGUMENTS) } /// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For diff --git a/src/librustc_expand/mbe/transcribe.rs b/src/librustc_expand/mbe/transcribe.rs index d12dedf9e0c7a..e2d3d5c4d644e 100644 --- a/src/librustc_expand/mbe/transcribe.rs +++ b/src/librustc_expand/mbe/transcribe.rs @@ -2,14 +2,15 @@ use crate::base::ExtCtxt; use crate::mbe; use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch}; -use rustc_ast::ast::{Ident, Mac}; +use rustc_ast::ast::MacCall; use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::token::{self, NtTT, Token}; use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; -use rustc_errors::pluralize; +use rustc_errors::{pluralize, PResult}; use rustc_span::hygiene::{ExpnId, Transparency}; +use rustc_span::symbol::MacroRulesNormalizedIdent; use rustc_span::Span; use smallvec::{smallvec, SmallVec}; @@ -23,7 +24,7 @@ impl MutVisitor for Marker { *span = span.apply_mark(self.0, self.1) } - fn visit_mac(&mut self, mac: &mut Mac) { + fn visit_mac(&mut self, mac: &mut MacCall) { mut_visit::noop_visit_mac(mac, self) } } @@ -79,15 +80,15 @@ impl Iterator for Frame { /// `transcribe` would return a `TokenStream` containing `println!("{}", stringify!(bar));`. /// /// Along the way, we do some additional error checking. -pub(super) fn transcribe( - cx: &ExtCtxt<'_>, - interp: &FxHashMap, +pub(super) fn transcribe<'a>( + cx: &ExtCtxt<'a>, + interp: &FxHashMap, src: Vec, transparency: Transparency, -) -> TokenStream { +) -> PResult<'a, TokenStream> { // Nothing for us to transcribe... if src.is_empty() { - return TokenStream::default(); + return Ok(TokenStream::default()); } // We descend into the RHS (`src`), expanding things as we go. This stack contains the things @@ -151,7 +152,7 @@ pub(super) fn transcribe( Frame::Delimited { forest, span, .. } => { if result_stack.is_empty() { // No results left to compute! We are back at the top-level. - return TokenStream::new(result); + return Ok(TokenStream::new(result)); } // Step back into the parent Delimited. @@ -172,11 +173,11 @@ pub(super) fn transcribe( seq @ mbe::TokenTree::Sequence(..) => { match lockstep_iter_size(&seq, interp, &repeats) { LockstepIterSize::Unconstrained => { - cx.span_fatal( + return Err(cx.struct_span_err( seq.span(), /* blame macro writer */ "attempted to repeat an expression containing no syntax variables \ matched as repeating at this depth", - ); + )); } LockstepIterSize::Contradiction(ref msg) => { @@ -184,7 +185,7 @@ pub(super) fn transcribe( // happens when two meta-variables are used in the same repetition in a // sequence, but they come from different sequence matchers and repeat // different amounts. - cx.span_fatal(seq.span(), &msg[..]); + return Err(cx.struct_span_err(seq.span(), &msg[..])); } LockstepIterSize::Constraint(len, _) => { @@ -202,7 +203,10 @@ pub(super) fn transcribe( // FIXME: this really ought to be caught at macro definition // time... It happens when the Kleene operator in the matcher and // the body for the same meta-variable do not match. - cx.span_fatal(sp.entire(), "this must repeat at least once"); + return Err(cx.struct_span_err( + sp.entire(), + "this must repeat at least once", + )); } } else { // 0 is the initial counter (we have done 0 repretitions so far). `len` @@ -223,9 +227,10 @@ pub(super) fn transcribe( } // Replace the meta-var with the matched token tree from the invocation. - mbe::TokenTree::MetaVar(mut sp, mut ident) => { + mbe::TokenTree::MetaVar(mut sp, mut orignal_ident) => { // Find the matched nonterminal from the macro invocation, and use it to replace // the meta-var. + let ident = MacroRulesNormalizedIdent::new(orignal_ident); if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) { if let MatchedNonterminal(ref nt) = cur_matched { // FIXME #2887: why do we apply a mark when matching a token tree meta-var @@ -240,18 +245,18 @@ pub(super) fn transcribe( } } else { // We were unable to descend far enough. This is an error. - cx.span_fatal( + return Err(cx.struct_span_err( sp, /* blame the macro writer */ &format!("variable '{}' is still repeating at this depth", ident), - ); + )); } } else { // If we aren't able to match the meta-var, we push it back into the result but // with modified syntax context. (I believe this supports nested macros). marker.visit_span(&mut sp); - marker.visit_ident(&mut ident); + marker.visit_ident(&mut orignal_ident); result.push(TokenTree::token(token::Dollar, sp).into()); - result.push(TokenTree::Token(Token::from_ast_ident(ident)).into()); + result.push(TokenTree::Token(Token::from_ast_ident(orignal_ident)).into()); } } @@ -287,8 +292,8 @@ pub(super) fn transcribe( /// into the right place in nested matchers. If we attempt to descend too far, the macro writer has /// made a mistake, and we return `None`. fn lookup_cur_matched<'a>( - ident: Ident, - interpolations: &'a FxHashMap, + ident: MacroRulesNormalizedIdent, + interpolations: &'a FxHashMap, repeats: &[(usize, usize)], ) -> Option<&'a NamedMatch> { interpolations.get(&ident).map(|matched| { @@ -316,7 +321,7 @@ enum LockstepIterSize { /// A `MetaVar` with an actual `MatchedSeq`. The length of the match and the name of the /// meta-var are returned. - Constraint(usize, Ident), + Constraint(usize, MacroRulesNormalizedIdent), /// Two `Constraint`s on the same sequence had different lengths. This is an error. Contradiction(String), @@ -360,7 +365,7 @@ impl LockstepIterSize { /// multiple nested matcher sequences. fn lockstep_iter_size( tree: &mbe::TokenTree, - interpolations: &FxHashMap, + interpolations: &FxHashMap, repeats: &[(usize, usize)], ) -> LockstepIterSize { use mbe::TokenTree; @@ -376,6 +381,7 @@ fn lockstep_iter_size( }) } TokenTree::MetaVar(_, name) | TokenTree::MetaVarDecl(_, name, _) => { + let name = MacroRulesNormalizedIdent::new(name); match lookup_cur_matched(name, interpolations, repeats) { Some(matched) => match matched { MatchedNonterminal(_) => LockstepIterSize::Unconstrained, diff --git a/src/librustc_expand/module.rs b/src/librustc_expand/module.rs new file mode 100644 index 0000000000000..aad92a09743b3 --- /dev/null +++ b/src/librustc_expand/module.rs @@ -0,0 +1,305 @@ +use rustc_ast::ast::{self, Attribute, Ident, Mod}; +use rustc_ast::{attr, token}; +use rustc_errors::{struct_span_err, PResult}; +use rustc_parse::new_parser_from_file; +use rustc_session::parse::ParseSess; +use rustc_span::source_map::{FileName, Span}; +use rustc_span::symbol::sym; + +use std::path::{self, Path, PathBuf}; + +#[derive(Clone)] +pub struct Directory { + pub path: PathBuf, + pub ownership: DirectoryOwnership, +} + +#[derive(Copy, Clone)] +pub enum DirectoryOwnership { + Owned { + // None if `mod.rs`, `Some("foo")` if we're in `foo.rs`. + relative: Option, + }, + UnownedViaBlock, + UnownedViaMod, +} + +/// Information about the path to a module. +// Public for rustfmt usage. +pub struct ModulePath<'a> { + name: String, + path_exists: bool, + pub result: PResult<'a, ModulePathSuccess>, +} + +// Public for rustfmt usage. +pub struct ModulePathSuccess { + pub path: PathBuf, + pub ownership: DirectoryOwnership, +} + +crate fn parse_external_mod( + sess: &ParseSess, + id: ast::Ident, + span: Span, // The span to blame on errors. + Directory { mut ownership, path }: Directory, + attrs: &mut Vec, + pop_mod_stack: &mut bool, +) -> (Mod, Directory) { + // We bail on the first error, but that error does not cause a fatal error... (1) + let result: PResult<'_, _> = try { + // Extract the file path and the new ownership. + let mp = submod_path(sess, id, span, &attrs, ownership, &path)?; + ownership = mp.ownership; + + // Ensure file paths are acyclic. + let mut included_mod_stack = sess.included_mod_stack.borrow_mut(); + error_on_circular_module(sess, span, &mp.path, &included_mod_stack)?; + included_mod_stack.push(mp.path.clone()); + *pop_mod_stack = true; // We have pushed, so notify caller. + drop(included_mod_stack); + + // Actually parse the external file as a module. + let mut module = new_parser_from_file(sess, &mp.path, Some(span)).parse_mod(&token::Eof)?; + module.0.inline = false; + module + }; + // (1) ...instead, we return a dummy module. + let (module, mut new_attrs) = result.map_err(|mut err| err.emit()).unwrap_or_default(); + attrs.append(&mut new_attrs); + + // Extract the directory path for submodules of `module`. + let path = sess.source_map().span_to_unmapped_path(module.inner); + let mut path = match path { + FileName::Real(path) => path, + other => PathBuf::from(other.to_string()), + }; + path.pop(); + + (module, Directory { ownership, path }) +} + +fn error_on_circular_module<'a>( + sess: &'a ParseSess, + span: Span, + path: &Path, + included_mod_stack: &[PathBuf], +) -> PResult<'a, ()> { + if let Some(i) = included_mod_stack.iter().position(|p| *p == path) { + let mut err = String::from("circular modules: "); + for p in &included_mod_stack[i..] { + err.push_str(&p.to_string_lossy()); + err.push_str(" -> "); + } + err.push_str(&path.to_string_lossy()); + return Err(sess.span_diagnostic.struct_span_err(span, &err[..])); + } + Ok(()) +} + +crate fn push_directory( + id: Ident, + attrs: &[Attribute], + Directory { mut ownership, mut path }: Directory, +) -> Directory { + if let Some(filename) = attr::first_attr_value_str_by_name(attrs, sym::path) { + path.push(&*filename.as_str()); + ownership = DirectoryOwnership::Owned { relative: None }; + } else { + // We have to push on the current module name in the case of relative + // paths in order to ensure that any additional module paths from inline + // `mod x { ... }` come after the relative extension. + // + // For example, a `mod z { ... }` inside `x/y.rs` should set the current + // directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`. + if let DirectoryOwnership::Owned { relative } = &mut ownership { + if let Some(ident) = relative.take() { + // Remove the relative offset. + path.push(&*ident.as_str()); + } + } + path.push(&*id.as_str()); + } + Directory { ownership, path } +} + +fn submod_path<'a>( + sess: &'a ParseSess, + id: ast::Ident, + span: Span, + attrs: &[Attribute], + ownership: DirectoryOwnership, + dir_path: &Path, +) -> PResult<'a, ModulePathSuccess> { + if let Some(path) = submod_path_from_attr(attrs, dir_path) { + let ownership = match path.file_name().and_then(|s| s.to_str()) { + // All `#[path]` files are treated as though they are a `mod.rs` file. + // This means that `mod foo;` declarations inside `#[path]`-included + // files are siblings, + // + // Note that this will produce weirdness when a file named `foo.rs` is + // `#[path]` included and contains a `mod foo;` declaration. + // If you encounter this, it's your own darn fault :P + Some(_) => DirectoryOwnership::Owned { relative: None }, + _ => DirectoryOwnership::UnownedViaMod, + }; + return Ok(ModulePathSuccess { ownership, path }); + } + + let relative = match ownership { + DirectoryOwnership::Owned { relative } => relative, + DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod => None, + }; + let ModulePath { path_exists, name, result } = + default_submod_path(sess, id, span, relative, dir_path); + match ownership { + DirectoryOwnership::Owned { .. } => Ok(result?), + DirectoryOwnership::UnownedViaBlock => { + let _ = result.map_err(|mut err| err.cancel()); + error_decl_mod_in_block(sess, span, path_exists, &name) + } + DirectoryOwnership::UnownedViaMod => { + let _ = result.map_err(|mut err| err.cancel()); + error_cannot_declare_mod_here(sess, span, path_exists, &name) + } + } +} + +fn error_decl_mod_in_block<'a, T>( + sess: &'a ParseSess, + span: Span, + path_exists: bool, + name: &str, +) -> PResult<'a, T> { + let msg = "Cannot declare a non-inline module inside a block unless it has a path attribute"; + let mut err = sess.span_diagnostic.struct_span_err(span, msg); + if path_exists { + let msg = format!("Maybe `use` the module `{}` instead of redeclaring it", name); + err.span_note(span, &msg); + } + Err(err) +} + +fn error_cannot_declare_mod_here<'a, T>( + sess: &'a ParseSess, + span: Span, + path_exists: bool, + name: &str, +) -> PResult<'a, T> { + let mut err = + sess.span_diagnostic.struct_span_err(span, "cannot declare a new module at this location"); + if !span.is_dummy() { + if let FileName::Real(src_path) = sess.source_map().span_to_filename(span) { + if let Some(stem) = src_path.file_stem() { + let mut dest_path = src_path.clone(); + dest_path.set_file_name(stem); + dest_path.push("mod.rs"); + err.span_note( + span, + &format!( + "maybe move this module `{}` to its own directory via `{}`", + src_path.display(), + dest_path.display() + ), + ); + } + } + } + if path_exists { + err.span_note( + span, + &format!("... or maybe `use` the module `{}` instead of possibly redeclaring it", name), + ); + } + Err(err) +} + +/// Derive a submodule path from the first found `#[path = "path_string"]`. +/// The provided `dir_path` is joined with the `path_string`. +// Public for rustfmt usage. +pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option { + // Extract path string from first `#[path = "path_string"]` attribute. + let path_string = attr::first_attr_value_str_by_name(attrs, sym::path)?; + let path_string = path_string.as_str(); + + // On windows, the base path might have the form + // `\\?\foo\bar` in which case it does not tolerate + // mixed `/` and `\` separators, so canonicalize + // `/` to `\`. + #[cfg(windows)] + let path_string = path_string.replace("/", "\\"); + + Some(dir_path.join(&*path_string)) +} + +/// Returns a path to a module. +// Public for rustfmt usage. +pub fn default_submod_path<'a>( + sess: &'a ParseSess, + id: ast::Ident, + span: Span, + relative: Option, + dir_path: &Path, +) -> ModulePath<'a> { + // If we're in a foo.rs file instead of a mod.rs file, + // we need to look for submodules in + // `./foo/.rs` and `./foo//mod.rs` rather than + // `./.rs` and `.//mod.rs`. + let relative_prefix_string; + let relative_prefix = if let Some(ident) = relative { + relative_prefix_string = format!("{}{}", ident.name, path::MAIN_SEPARATOR); + &relative_prefix_string + } else { + "" + }; + + let mod_name = id.name.to_string(); + let default_path_str = format!("{}{}.rs", relative_prefix, mod_name); + let secondary_path_str = + format!("{}{}{}mod.rs", relative_prefix, mod_name, path::MAIN_SEPARATOR); + let default_path = dir_path.join(&default_path_str); + let secondary_path = dir_path.join(&secondary_path_str); + let default_exists = sess.source_map().file_exists(&default_path); + let secondary_exists = sess.source_map().file_exists(&secondary_path); + + let result = match (default_exists, secondary_exists) { + (true, false) => Ok(ModulePathSuccess { + path: default_path, + ownership: DirectoryOwnership::Owned { relative: Some(id) }, + }), + (false, true) => Ok(ModulePathSuccess { + path: secondary_path, + ownership: DirectoryOwnership::Owned { relative: None }, + }), + (false, false) => { + let mut err = struct_span_err!( + sess.span_diagnostic, + span, + E0583, + "file not found for module `{}`", + mod_name, + ); + err.help(&format!( + "to create the module `{}`, create file \"{}\"", + mod_name, + default_path.display(), + )); + Err(err) + } + (true, true) => { + let mut err = struct_span_err!( + sess.span_diagnostic, + span, + E0584, + "file for module `{}` found at both {} and {}", + mod_name, + default_path_str, + secondary_path_str, + ); + err.help("delete or rename one of them to remove the ambiguity"); + Err(err) + } + }; + + ModulePath { name: mod_name, path_exists: default_exists || secondary_exists, result } +} diff --git a/src/librustc_expand/mut_visit/tests.rs b/src/librustc_expand/mut_visit/tests.rs index 4c947d8fa2b4e..70fb8975d4d08 100644 --- a/src/librustc_expand/mut_visit/tests.rs +++ b/src/librustc_expand/mut_visit/tests.rs @@ -17,7 +17,7 @@ impl MutVisitor for ToZzIdentMutVisitor { fn visit_ident(&mut self, ident: &mut ast::Ident) { *ident = Ident::from_str("zz"); } - fn visit_mac(&mut self, mac: &mut ast::Mac) { + fn visit_mac(&mut self, mac: &mut ast::MacCall) { mut_visit::noop_visit_mac(mac, self) } } diff --git a/src/librustc_expand/parse/tests.rs b/src/librustc_expand/parse/tests.rs index 55e815bd4a4e0..4add896258fa8 100644 --- a/src/librustc_expand/parse/tests.rs +++ b/src/librustc_expand/parse/tests.rs @@ -281,7 +281,7 @@ fn ttdelim_span() { .unwrap(); let tts: Vec<_> = match expr.kind { - ast::ExprKind::Mac(ref mac) => mac.args.inner_tokens().trees().collect(), + ast::ExprKind::MacCall(ref mac) => mac.args.inner_tokens().trees().collect(), _ => panic!("not a macro"), }; diff --git a/src/librustc_expand/placeholders.rs b/src/librustc_expand/placeholders.rs index cd4f0a61d424a..e1781f8636e58 100644 --- a/src/librustc_expand/placeholders.rs +++ b/src/librustc_expand/placeholders.rs @@ -15,8 +15,8 @@ pub fn placeholder( id: ast::NodeId, vis: Option, ) -> AstFragment { - fn mac_placeholder() -> ast::Mac { - ast::Mac { + fn mac_placeholder() -> ast::MacCall { + ast::MacCall { path: ast::Path { span: DUMMY_SP, segments: Vec::new() }, args: P(ast::MacArgs::Empty), prior_type_ascription: None, @@ -32,11 +32,11 @@ pub fn placeholder( id, span, attrs: ast::AttrVec::new(), - kind: ast::ExprKind::Mac(mac_placeholder()), + kind: ast::ExprKind::MacCall(mac_placeholder()), }) }; - let ty = || P(ast::Ty { id, kind: ast::TyKind::Mac(mac_placeholder()), span }); - let pat = || P(ast::Pat { id, kind: ast::PatKind::Mac(mac_placeholder()), span }); + let ty = || P(ast::Ty { id, kind: ast::TyKind::MacCall(mac_placeholder()), span }); + let pat = || P(ast::Pat { id, kind: ast::PatKind::MacCall(mac_placeholder()), span }); match kind { AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()), @@ -47,7 +47,7 @@ pub fn placeholder( ident, vis, attrs, - kind: ast::ItemKind::Mac(mac_placeholder()), + kind: ast::ItemKind::MacCall(mac_placeholder()), tokens: None, })]), AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![P(ast::AssocItem { @@ -56,7 +56,7 @@ pub fn placeholder( ident, vis, attrs, - kind: ast::AssocItemKind::Macro(mac_placeholder()), + kind: ast::AssocItemKind::MacCall(mac_placeholder()), tokens: None, })]), AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![P(ast::AssocItem { @@ -65,7 +65,7 @@ pub fn placeholder( ident, vis, attrs, - kind: ast::AssocItemKind::Macro(mac_placeholder()), + kind: ast::AssocItemKind::MacCall(mac_placeholder()), tokens: None, })]), AstFragmentKind::ForeignItems => { @@ -75,19 +75,21 @@ pub fn placeholder( ident, vis, attrs, - kind: ast::ForeignItemKind::Macro(mac_placeholder()), + kind: ast::ForeignItemKind::MacCall(mac_placeholder()), tokens: None, })]) } - AstFragmentKind::Pat => { - AstFragment::Pat(P(ast::Pat { id, span, kind: ast::PatKind::Mac(mac_placeholder()) })) - } + AstFragmentKind::Pat => AstFragment::Pat(P(ast::Pat { + id, + span, + kind: ast::PatKind::MacCall(mac_placeholder()), + })), AstFragmentKind::Ty => { - AstFragment::Ty(P(ast::Ty { id, span, kind: ast::TyKind::Mac(mac_placeholder()) })) + AstFragment::Ty(P(ast::Ty { id, span, kind: ast::TyKind::MacCall(mac_placeholder()) })) } AstFragmentKind::Stmts => AstFragment::Stmts(smallvec![{ let mac = P((mac_placeholder(), ast::MacStmtStyle::Braces, ast::AttrVec::new())); - ast::Stmt { id, span, kind: ast::StmtKind::Mac(mac) } + ast::Stmt { id, span, kind: ast::StmtKind::MacCall(mac) } }]), AstFragmentKind::Arms => AstFragment::Arms(smallvec![ast::Arm { attrs: Default::default(), @@ -239,7 +241,7 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> { fn flat_map_item(&mut self, item: P) -> SmallVec<[P; 1]> { match item.kind { - ast::ItemKind::Mac(_) => return self.remove(item.id).make_items(), + ast::ItemKind::MacCall(_) => return self.remove(item.id).make_items(), ast::ItemKind::MacroDef(_) => return smallvec![item], _ => {} } @@ -249,14 +251,14 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> { fn flat_map_trait_item(&mut self, item: P) -> SmallVec<[P; 1]> { match item.kind { - ast::AssocItemKind::Macro(_) => self.remove(item.id).make_trait_items(), + ast::AssocItemKind::MacCall(_) => self.remove(item.id).make_trait_items(), _ => noop_flat_map_assoc_item(item, self), } } fn flat_map_impl_item(&mut self, item: P) -> SmallVec<[P; 1]> { match item.kind { - ast::AssocItemKind::Macro(_) => self.remove(item.id).make_impl_items(), + ast::AssocItemKind::MacCall(_) => self.remove(item.id).make_impl_items(), _ => noop_flat_map_assoc_item(item, self), } } @@ -266,28 +268,28 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> { item: P, ) -> SmallVec<[P; 1]> { match item.kind { - ast::ForeignItemKind::Macro(_) => self.remove(item.id).make_foreign_items(), + ast::ForeignItemKind::MacCall(_) => self.remove(item.id).make_foreign_items(), _ => noop_flat_map_foreign_item(item, self), } } fn visit_expr(&mut self, expr: &mut P) { match expr.kind { - ast::ExprKind::Mac(_) => *expr = self.remove(expr.id).make_expr(), + ast::ExprKind::MacCall(_) => *expr = self.remove(expr.id).make_expr(), _ => noop_visit_expr(expr, self), } } fn filter_map_expr(&mut self, expr: P) -> Option> { match expr.kind { - ast::ExprKind::Mac(_) => self.remove(expr.id).make_opt_expr(), + ast::ExprKind::MacCall(_) => self.remove(expr.id).make_opt_expr(), _ => noop_filter_map_expr(expr, self), } } fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> { let (style, mut stmts) = match stmt.kind { - ast::StmtKind::Mac(mac) => (mac.1, self.remove(stmt.id).make_stmts()), + ast::StmtKind::MacCall(mac) => (mac.1, self.remove(stmt.id).make_stmts()), _ => return noop_flat_map_stmt(stmt, self), }; @@ -302,14 +304,14 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> { fn visit_pat(&mut self, pat: &mut P) { match pat.kind { - ast::PatKind::Mac(_) => *pat = self.remove(pat.id).make_pat(), + ast::PatKind::MacCall(_) => *pat = self.remove(pat.id).make_pat(), _ => noop_visit_pat(pat, self), } } fn visit_ty(&mut self, ty: &mut P) { match ty.kind { - ast::TyKind::Mac(_) => *ty = self.remove(ty.id).make_ty(), + ast::TyKind::MacCall(_) => *ty = self.remove(ty.id).make_ty(), _ => noop_visit_ty(ty, self), } } @@ -328,12 +330,12 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> { fn visit_mod(&mut self, module: &mut ast::Mod) { noop_visit_mod(module, self); module.items.retain(|item| match item.kind { - ast::ItemKind::Mac(_) if !self.cx.ecfg.keep_macs => false, // remove macro definitions + ast::ItemKind::MacCall(_) if !self.cx.ecfg.keep_macs => false, // remove macro definitions _ => true, }); } - fn visit_mac(&mut self, _mac: &mut ast::Mac) { + fn visit_mac(&mut self, _mac: &mut ast::MacCall) { // Do nothing. } } diff --git a/src/librustc_expand/proc_macro.rs b/src/librustc_expand/proc_macro.rs index 84a546345bb28..df7bf9438c3d0 100644 --- a/src/librustc_expand/proc_macro.rs +++ b/src/librustc_expand/proc_macro.rs @@ -5,7 +5,7 @@ use rustc_ast::ast::{self, ItemKind, MetaItemKind, NestedMetaItem}; use rustc_ast::token; use rustc_ast::tokenstream::{self, TokenStream}; use rustc_data_structures::sync::Lrc; -use rustc_errors::{Applicability, FatalError}; +use rustc_errors::{Applicability, ErrorReported}; use rustc_span::symbol::sym; use rustc_span::{Span, DUMMY_SP}; @@ -21,21 +21,16 @@ impl base::ProcMacro for BangProcMacro { ecx: &'cx mut ExtCtxt<'_>, span: Span, input: TokenStream, - ) -> TokenStream { + ) -> Result { let server = proc_macro_server::Rustc::new(ecx); - match self.client.run(&EXEC_STRATEGY, server, input) { - Ok(stream) => stream, - Err(e) => { - let msg = "proc macro panicked"; - let mut err = ecx.struct_span_fatal(span, msg); - if let Some(s) = e.as_str() { - err.help(&format!("message: {}", s)); - } - - err.emit(); - FatalError.raise(); + self.client.run(&EXEC_STRATEGY, server, input).map_err(|e| { + let mut err = ecx.struct_span_err(span, "proc macro panicked"); + if let Some(s) = e.as_str() { + err.help(&format!("message: {}", s)); } - } + err.emit(); + ErrorReported + }) } } @@ -50,21 +45,16 @@ impl base::AttrProcMacro for AttrProcMacro { span: Span, annotation: TokenStream, annotated: TokenStream, - ) -> TokenStream { + ) -> Result { let server = proc_macro_server::Rustc::new(ecx); - match self.client.run(&EXEC_STRATEGY, server, annotation, annotated) { - Ok(stream) => stream, - Err(e) => { - let msg = "custom attribute panicked"; - let mut err = ecx.struct_span_fatal(span, msg); - if let Some(s) = e.as_str() { - err.help(&format!("message: {}", s)); - } - - err.emit(); - FatalError.raise(); + self.client.run(&EXEC_STRATEGY, server, annotation, annotated).map_err(|e| { + let mut err = ecx.struct_span_err(span, "custom attribute panicked"); + if let Some(s) = e.as_str() { + err.help(&format!("message: {}", s)); } - } + err.emit(); + ErrorReported + }) } } @@ -79,7 +69,7 @@ impl MultiItemModifier for ProcMacroDerive { span: Span, _meta_item: &ast::MetaItem, item: Annotatable, - ) -> Vec { + ) -> ExpandResult, Annotatable> { let item = match item { Annotatable::Arm(..) | Annotatable::Field(..) @@ -96,10 +86,9 @@ impl MultiItemModifier for ProcMacroDerive { | Annotatable::Expr(_) => { ecx.span_err( span, - "proc-macro derives may only be \ - applied to a struct, enum, or union", + "proc-macro derives may only be applied to a struct, enum, or union", ); - return Vec::new(); + return ExpandResult::Ready(Vec::new()); } }; match item.kind { @@ -107,10 +96,9 @@ impl MultiItemModifier for ProcMacroDerive { _ => { ecx.span_err( span, - "proc-macro derives may only be \ - applied to a struct, enum, or union", + "proc-macro derives may only be applied to a struct, enum, or union", ); - return Vec::new(); + return ExpandResult::Ready(Vec::new()); } } @@ -121,20 +109,16 @@ impl MultiItemModifier for ProcMacroDerive { let stream = match self.client.run(&EXEC_STRATEGY, server, input) { Ok(stream) => stream, Err(e) => { - let msg = "proc-macro derive panicked"; - let mut err = ecx.struct_span_fatal(span, msg); + let mut err = ecx.struct_span_err(span, "proc-macro derive panicked"); if let Some(s) = e.as_str() { err.help(&format!("message: {}", s)); } - err.emit(); - FatalError.raise(); + return ExpandResult::Ready(vec![]); } }; let error_count_before = ecx.parse_sess.span_diagnostic.err_count(); - let msg = "proc-macro derive produced unparseable tokens"; - let mut parser = rustc_parse::stream_to_parser(ecx.parse_sess, stream, Some("proc-macro derive")); let mut items = vec![]; @@ -144,21 +128,18 @@ impl MultiItemModifier for ProcMacroDerive { Ok(None) => break, Ok(Some(item)) => items.push(Annotatable::Item(item)), Err(mut err) => { - // FIXME: handle this better - err.cancel(); - ecx.struct_span_fatal(span, msg).emit(); - FatalError.raise(); + err.emit(); + break; } } } // fail if there have been errors emitted if ecx.parse_sess.span_diagnostic.err_count() > error_count_before { - ecx.struct_span_fatal(span, msg).emit(); - FatalError.raise(); + ecx.struct_span_err(span, "proc-macro derive produced unparseable tokens").emit(); } - items + ExpandResult::Ready(items) } } diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 3a0fc6f8da143..4dfa309540cad 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -301,6 +301,11 @@ declare_features! ( /// Allows specialization of implementations (RFC 1210). (active, specialization, "1.7.0", Some(31844), None), + /// A minimal, sound subset of specialization intended to be used by the + /// standard library until the soundness issues with specialization + /// are fixed. + (active, min_specialization, "1.7.0", Some(31844), None), + /// Allows using `#[naked]` on functions. (active, naked_functions, "1.9.0", Some(32408), None), @@ -549,6 +554,9 @@ declare_features! ( // Allows limiting the evaluation steps of const expressions (active, const_eval_limit, "1.43.0", Some(67217), None), + /// Allow negative trait implementations. + (active, negative_impls, "1.44.0", Some(68318), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/src/librustc_feature/builtin_attrs.rs b/src/librustc_feature/builtin_attrs.rs index e9a5364c65838..eaebdd9fb95a2 100644 --- a/src/librustc_feature/builtin_attrs.rs +++ b/src/librustc_feature/builtin_attrs.rs @@ -85,19 +85,13 @@ impl AttributeGate { /// A template that the attribute input must match. /// Only top-level shape (`#[attr]` vs `#[attr(...)]` vs `#[attr = ...]`) is considered now. -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct AttributeTemplate { pub word: bool, pub list: Option<&'static str>, pub name_value_str: Option<&'static str>, } -impl AttributeTemplate { - pub fn only_word() -> Self { - Self { word: true, list: None, name_value_str: None } - } -} - /// A convenience macro for constructing attribute templates. /// E.g., `template!(Word, List: "description")` means that the attribute /// supports forms `#[attr]` and `#[attr(description)]`. @@ -530,6 +524,14 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_test_marker, Normal, template!(Word), "the `#[rustc_test_marker]` attribute is used internally to track tests", ), + rustc_attr!( + rustc_unsafe_specialization_marker, Normal, template!(Word), + "the `#[rustc_unsafe_specialization_marker]` attribute is used to check specializations" + ), + rustc_attr!( + rustc_specialization_trait, Normal, template!(Word), + "the `#[rustc_specialization_trait]` attribute is used to check specializations" + ), // ========================================================================== // Internal attributes, Testing: diff --git a/src/librustc_feature/lib.rs b/src/librustc_feature/lib.rs index 01546f7825774..f8bf0315d0c9f 100644 --- a/src/librustc_feature/lib.rs +++ b/src/librustc_feature/lib.rs @@ -51,7 +51,7 @@ pub struct Feature { impl Feature { fn issue(&self) -> Option { - self.issue.and_then(|i| NonZeroU32::new(i)) + self.issue.and_then(NonZeroU32::new) } } diff --git a/src/librustc_hir/Cargo.toml b/src/librustc_hir/Cargo.toml index 872d114fb1800..b3682ea5a807c 100644 --- a/src/librustc_hir/Cargo.toml +++ b/src/librustc_hir/Cargo.toml @@ -20,4 +20,5 @@ rustc_errors = { path = "../librustc_errors" } rustc_serialize = { path = "../libserialize", package = "serialize" } rustc_ast = { path = "../librustc_ast" } lazy_static = "1" +log = { version = "0.4", features = ["release_max_level_info", "std"] } smallvec = { version = "1.0", features = ["union", "may_dangle"] } diff --git a/src/librustc_hir/arena.rs b/src/librustc_hir/arena.rs new file mode 100644 index 0000000000000..978565a4c39d7 --- /dev/null +++ b/src/librustc_hir/arena.rs @@ -0,0 +1,49 @@ +/// This declares a list of types which can be allocated by `Arena`. +/// +/// The `few` modifier will cause allocation to use the shared arena and recording the destructor. +/// This is faster and more memory efficient if there's only a few allocations of the type. +/// Leaving `few` out will cause the type to get its own dedicated `TypedArena` which is +/// faster and more memory efficient if there is lots of allocations. +/// +/// Specifying the `decode` modifier will add decode impls for &T and &[T] where T is the type +/// listed. These impls will appear in the implement_ty_decoder! macro. +#[macro_export] +macro_rules! arena_types { + ($macro:path, $args:tt, $tcx:lifetime) => ( + $macro!($args, [ + // HIR types + [few] hir_krate: rustc_hir::Crate<$tcx>, + [] arm: rustc_hir::Arm<$tcx>, + [] attribute: rustc_ast::ast::Attribute, + [] block: rustc_hir::Block<$tcx>, + [] bare_fn_ty: rustc_hir::BareFnTy<$tcx>, + [few] global_asm: rustc_hir::GlobalAsm, + [] generic_arg: rustc_hir::GenericArg<$tcx>, + [] generic_args: rustc_hir::GenericArgs<$tcx>, + [] generic_bound: rustc_hir::GenericBound<$tcx>, + [] generic_param: rustc_hir::GenericParam<$tcx>, + [] expr: rustc_hir::Expr<$tcx>, + [] field: rustc_hir::Field<$tcx>, + [] field_pat: rustc_hir::FieldPat<$tcx>, + [] fn_decl: rustc_hir::FnDecl<$tcx>, + [] foreign_item: rustc_hir::ForeignItem<$tcx>, + [] impl_item_ref: rustc_hir::ImplItemRef<$tcx>, + [] inline_asm: rustc_hir::InlineAsm<$tcx>, + [] local: rustc_hir::Local<$tcx>, + [few] macro_def: rustc_hir::MacroDef<$tcx>, + [] param: rustc_hir::Param<$tcx>, + [] pat: rustc_hir::Pat<$tcx>, + [] path: rustc_hir::Path<$tcx>, + [] path_segment: rustc_hir::PathSegment<$tcx>, + [] poly_trait_ref: rustc_hir::PolyTraitRef<$tcx>, + [] qpath: rustc_hir::QPath<$tcx>, + [] stmt: rustc_hir::Stmt<$tcx>, + [] struct_field: rustc_hir::StructField<$tcx>, + [] trait_item_ref: rustc_hir::TraitItemRef, + [] ty: rustc_hir::Ty<$tcx>, + [] type_binding: rustc_hir::TypeBinding<$tcx>, + [] variant: rustc_hir::Variant<$tcx>, + [] where_predicate: rustc_hir::WherePredicate<$tcx>, + ], $tcx); + ) +} diff --git a/src/librustc_hir/def.rs b/src/librustc_hir/def.rs index 5b2c1453de642..3334cc32a52f7 100644 --- a/src/librustc_hir/def.rs +++ b/src/librustc_hir/def.rs @@ -107,8 +107,7 @@ impl DefKind { DefKind::Union => "union", DefKind::Trait => "trait", DefKind::ForeignTy => "foreign type", - // FIXME: Update the description to "assoc fn" - DefKind::AssocFn => "method", + DefKind::AssocFn => "associated function", DefKind::Const => "constant", DefKind::AssocConst => "associated constant", DefKind::TyParam => "type parameter", @@ -123,6 +122,7 @@ impl DefKind { DefKind::AssocTy | DefKind::AssocConst | DefKind::AssocOpaqueTy + | DefKind::AssocFn | DefKind::Enum | DefKind::OpaqueTy => "an", DefKind::Macro(macro_kind) => macro_kind.article(), @@ -159,6 +159,7 @@ impl DefKind { } } +/// The resolution of a path or export. #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] #[derive(HashStable_Generic)] pub enum Res { diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc_hir/definitions.rs similarity index 76% rename from src/librustc/hir/map/definitions.rs rename to src/librustc_hir/definitions.rs index e1b5ec041db06..3b86dd42a68b9 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc_hir/definitions.rs @@ -4,20 +4,21 @@ //! There are also some rather random cases (like const initializer //! expressions) that are mostly just leftovers. +pub use crate::def_id::DefPathHash; +use crate::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use crate::hir; +use crate::hir_id::DUMMY_HIR_ID; + use rustc_ast::ast; -use rustc_ast::node_id::NodeMap; -use rustc_data_structures::fingerprint::Fingerprint; +use rustc_ast::crate_disambiguator::CrateDisambiguator; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; -use rustc_hir as hir; -use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_index::vec::IndexVec; -use rustc_session::CrateDisambiguator; use rustc_span::hygiene::ExpnId; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; -use std::borrow::Borrow; +use log::debug; use std::fmt::Write; use std::hash::Hash; @@ -78,21 +79,29 @@ impl DefPathTable { #[derive(Clone, Default)] pub struct Definitions { table: DefPathTable, - node_to_def_index: NodeMap, - def_index_to_node: IndexVec, - pub(super) node_to_hir_id: IndexVec, + + def_id_to_span: IndexVec, + + // FIXME(eddyb) don't go through `ast::NodeId` to convert between `HirId` + // and `LocalDefId` - ideally all `LocalDefId`s would be HIR owners. + node_id_to_def_id: FxHashMap, + def_id_to_node_id: IndexVec, + + pub(super) node_id_to_hir_id: IndexVec, + /// The reverse mapping of `node_id_to_hir_id`. + pub(super) hir_id_to_node_id: FxHashMap, + /// If `ExpnId` is an ID of some macro expansion, /// then `DefId` is the normal module (`mod`) in which the expanded macro was defined. parent_modules_of_macro_defs: FxHashMap, - /// Item with a given `DefIndex` was defined during macro expansion with ID `ExpnId`. - expansions_that_defined: FxHashMap, - next_disambiguator: FxHashMap<(DefIndex, DefPathData), u32>, - def_index_to_span: FxHashMap, + /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`. + expansions_that_defined: FxHashMap, + next_disambiguator: FxHashMap<(LocalDefId, DefPathData), u32>, /// When collecting definitions from an AST fragment produced by a macro invocation `ExpnId` /// we know what parent node that fragment should be attached to thanks to this table. - invocation_parents: FxHashMap, + invocation_parents: FxHashMap, /// Indices of unnamed struct or variant fields with unresolved attributes. - placeholder_field_indices: NodeMap, + placeholder_field_indices: FxHashMap, } /// A unique identifier that we can use to lookup a definition @@ -282,28 +291,6 @@ pub enum DefPathData { ImplTrait, } -#[derive( - Copy, - Clone, - Hash, - PartialEq, - Eq, - PartialOrd, - Ord, - Debug, - RustcEncodable, - RustcDecodable, - HashStable -)] -pub struct DefPathHash(pub Fingerprint); - -impl Borrow for DefPathHash { - #[inline] - fn borrow(&self) -> &Fingerprint { - &self.0 - } -} - impl Definitions { pub fn def_path_table(&self) -> &DefPathTable { &self.table @@ -314,13 +301,13 @@ impl Definitions { self.table.index_to_key.len() } - pub fn def_key(&self, index: DefIndex) -> DefKey { - self.table.def_key(index) + pub fn def_key(&self, id: LocalDefId) -> DefKey { + self.table.def_key(id.local_def_index) } #[inline(always)] - pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash { - self.table.def_path_hash(index) + pub fn def_path_hash(&self, id: LocalDefId) -> DefPathHash { + self.table.def_path_hash(id.local_def_index) } /// Returns the path from the crate root to `index`. The root @@ -328,29 +315,27 @@ impl Definitions { /// empty vector for the crate root). For an inlined item, this /// will be the path of the item in the external crate (but the /// path will begin with the path to the external crate). - pub fn def_path(&self, index: DefIndex) -> DefPath { - DefPath::make(LOCAL_CRATE, index, |p| self.def_key(p)) - } - - #[inline] - pub fn opt_def_index(&self, node: ast::NodeId) -> Option { - self.node_to_def_index.get(&node).copied() + pub fn def_path(&self, id: LocalDefId) -> DefPath { + DefPath::make(LOCAL_CRATE, id.local_def_index, |index| { + self.def_key(LocalDefId { local_def_index: index }) + }) } #[inline] - pub fn opt_local_def_id(&self, node: ast::NodeId) -> Option { - self.opt_def_index(node).map(DefId::local) + pub fn opt_local_def_id(&self, node: ast::NodeId) -> Option { + self.node_id_to_def_id.get(&node).copied() } + // FIXME(eddyb) this function can and should return `LocalDefId`. #[inline] pub fn local_def_id(&self, node: ast::NodeId) -> DefId { - self.opt_local_def_id(node).unwrap() + self.opt_local_def_id(node).unwrap().to_def_id() } #[inline] pub fn as_local_node_id(&self, def_id: DefId) -> Option { - if def_id.krate == LOCAL_CRATE { - let node_id = self.def_index_to_node[def_id.index]; + if let Some(def_id) = def_id.as_local() { + let node_id = self.def_id_to_node_id[def_id]; if node_id != ast::DUMMY_NODE_ID { return Some(node_id); } @@ -360,34 +345,36 @@ impl Definitions { #[inline] pub fn as_local_hir_id(&self, def_id: DefId) -> Option { - if def_id.krate == LOCAL_CRATE { - let hir_id = self.def_index_to_hir_id(def_id.index); - if hir_id != hir::DUMMY_HIR_ID { Some(hir_id) } else { None } + if let Some(def_id) = def_id.as_local() { + let hir_id = self.local_def_id_to_hir_id(def_id); + if hir_id != DUMMY_HIR_ID { Some(hir_id) } else { None } } else { None } } + // FIXME(eddyb) rename to `hir_id_to_node_id`. + #[inline] + pub fn hir_to_node_id(&self, hir_id: hir::HirId) -> ast::NodeId { + self.hir_id_to_node_id[&hir_id] + } + + // FIXME(eddyb) rename to `node_id_to_hir_id`. #[inline] pub fn node_to_hir_id(&self, node_id: ast::NodeId) -> hir::HirId { - self.node_to_hir_id[node_id] + self.node_id_to_hir_id[node_id] } #[inline] - pub fn def_index_to_hir_id(&self, def_index: DefIndex) -> hir::HirId { - let node_id = self.def_index_to_node[def_index]; - self.node_to_hir_id[node_id] + pub fn local_def_id_to_hir_id(&self, id: LocalDefId) -> hir::HirId { + let node_id = self.def_id_to_node_id[id]; + self.node_id_to_hir_id[node_id] } - /// Retrieves the span of the given `DefId` if `DefId` is in the local crate, the span exists - /// and it's not `DUMMY_SP`. + /// Retrieves the span of the given `DefId` if `DefId` is in the local crate. #[inline] pub fn opt_span(&self, def_id: DefId) -> Option { - if def_id.krate == LOCAL_CRATE { - self.def_index_to_span.get(&def_id.index).copied() - } else { - None - } + if let Some(def_id) = def_id.as_local() { Some(self.def_id_to_span[def_id]) } else { None } } /// Adds a root definition (no parent) and a few other reserved definitions. @@ -395,7 +382,7 @@ impl Definitions { &mut self, crate_name: &str, crate_disambiguator: CrateDisambiguator, - ) -> DefIndex { + ) -> LocalDefId { let key = DefKey { parent: None, disambiguated_data: DisambiguatedDefPathData { @@ -408,36 +395,38 @@ impl Definitions { let def_path_hash = key.compute_stable_hash(parent_hash); // Create the definition. - let root_index = self.table.allocate(key, def_path_hash); - assert_eq!(root_index, CRATE_DEF_INDEX); - assert!(self.def_index_to_node.is_empty()); - self.def_index_to_node.push(ast::CRATE_NODE_ID); - self.node_to_def_index.insert(ast::CRATE_NODE_ID, root_index); - self.set_invocation_parent(ExpnId::root(), root_index); + let root = LocalDefId { local_def_index: self.table.allocate(key, def_path_hash) }; + assert_eq!(root.local_def_index, CRATE_DEF_INDEX); + + assert_eq!(self.def_id_to_node_id.push(ast::CRATE_NODE_ID), root); + assert_eq!(self.def_id_to_span.push(rustc_span::DUMMY_SP), root); - root_index + self.node_id_to_def_id.insert(ast::CRATE_NODE_ID, root); + self.set_invocation_parent(ExpnId::root(), root); + + root } /// Adds a definition with a parent definition. pub fn create_def_with_parent( &mut self, - parent: DefIndex, + parent: LocalDefId, node_id: ast::NodeId, data: DefPathData, expn_id: ExpnId, span: Span, - ) -> DefIndex { + ) -> LocalDefId { debug!( "create_def_with_parent(parent={:?}, node_id={:?}, data={:?})", parent, node_id, data ); assert!( - !self.node_to_def_index.contains_key(&node_id), + !self.node_id_to_def_id.contains_key(&node_id), "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}", node_id, data, - self.table.def_key(self.node_to_def_index[&node_id]) + self.table.def_key(self.node_id_to_def_id[&node_id].local_def_index), ); // The root node must be created with `create_root_def()`. @@ -452,52 +441,55 @@ impl Definitions { }; let key = DefKey { - parent: Some(parent), + parent: Some(parent.local_def_index), disambiguated_data: DisambiguatedDefPathData { data, disambiguator }, }; - let parent_hash = self.table.def_path_hash(parent); + let parent_hash = self.table.def_path_hash(parent.local_def_index); let def_path_hash = key.compute_stable_hash(parent_hash); debug!("create_def_with_parent: after disambiguation, key = {:?}", key); // Create the definition. - let index = self.table.allocate(key, def_path_hash); - assert_eq!(index.index(), self.def_index_to_node.len()); - self.def_index_to_node.push(node_id); + let def_id = LocalDefId { local_def_index: self.table.allocate(key, def_path_hash) }; + + assert_eq!(self.def_id_to_node_id.push(node_id), def_id); + assert_eq!(self.def_id_to_span.push(span), def_id); - // Some things for which we allocate `DefIndex`es don't correspond to + // Some things for which we allocate `LocalDefId`s don't correspond to // anything in the AST, so they don't have a `NodeId`. For these cases - // we don't need a mapping from `NodeId` to `DefIndex`. + // we don't need a mapping from `NodeId` to `LocalDefId`. if node_id != ast::DUMMY_NODE_ID { - debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id); - self.node_to_def_index.insert(node_id, index); + debug!("create_def_with_parent: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id); + self.node_id_to_def_id.insert(node_id, def_id); } if expn_id != ExpnId::root() { - self.expansions_that_defined.insert(index, expn_id); - } - - // The span is added if it isn't dummy. - if !span.is_dummy() { - self.def_index_to_span.insert(index, span); + self.expansions_that_defined.insert(def_id, expn_id); } - index + def_id } /// Initializes the `ast::NodeId` to `HirId` mapping once it has been generated during /// AST to HIR lowering. pub fn init_node_id_to_hir_id_mapping(&mut self, mapping: IndexVec) { assert!( - self.node_to_hir_id.is_empty(), + self.node_id_to_hir_id.is_empty(), "trying to initialize `NodeId` -> `HirId` mapping twice" ); - self.node_to_hir_id = mapping; + self.node_id_to_hir_id = mapping; + + // Build the reverse mapping of `node_id_to_hir_id`. + self.hir_id_to_node_id = self + .node_id_to_hir_id + .iter_enumerated() + .map(|(node_id, &hir_id)| (hir_id, node_id)) + .collect(); } - pub fn expansion_that_defined(&self, index: DefIndex) -> ExpnId { - self.expansions_that_defined.get(&index).copied().unwrap_or(ExpnId::root()) + pub fn expansion_that_defined(&self, id: LocalDefId) -> ExpnId { + self.expansions_that_defined.get(&id).copied().unwrap_or(ExpnId::root()) } pub fn parent_module_of_macro_def(&self, expn_id: ExpnId) -> DefId { @@ -508,13 +500,13 @@ impl Definitions { self.parent_modules_of_macro_defs.insert(expn_id, module); } - pub fn invocation_parent(&self, invoc_id: ExpnId) -> DefIndex { + pub fn invocation_parent(&self, invoc_id: ExpnId) -> LocalDefId { self.invocation_parents[&invoc_id] } - pub fn set_invocation_parent(&mut self, invoc_id: ExpnId, parent: DefIndex) { + pub fn set_invocation_parent(&mut self, invoc_id: ExpnId, parent: LocalDefId) { let old_parent = self.invocation_parents.insert(invoc_id, parent); - assert!(old_parent.is_none(), "parent `DefIndex` is reset for an invocation"); + assert!(old_parent.is_none(), "parent `LocalDefId` is reset for an invocation"); } pub fn placeholder_field_index(&self, node_id: ast::NodeId) -> usize { diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index 9993e5c55f667..bb864edc99969 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -13,7 +13,6 @@ use rustc_ast::ast::{AttrVec, Attribute, FloatTy, IntTy, Label, LitKind, StrStyl pub use rustc_ast::ast::{BorrowKind, ImplPolarity, IsAuto}; pub use rustc_ast::ast::{CaptureBy, Movability, Mutability}; use rustc_ast::node_id::NodeMap; -use rustc_ast::tokenstream::TokenStream; use rustc_ast::util::parser::ExprPrecedence; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::{par_for_each_in, Send, Sync}; @@ -80,9 +79,9 @@ impl ParamName { } } - pub fn modern(&self) -> ParamName { + pub fn normalize_to_macros_2_0(&self) -> ParamName { match *self { - ParamName::Plain(ident) => ParamName::Plain(ident.modern()), + ParamName::Plain(ident) => ParamName::Plain(ident.normalize_to_macros_2_0()), param_name => param_name, } } @@ -152,9 +151,11 @@ impl LifetimeName { self == &LifetimeName::Static } - pub fn modern(&self) -> LifetimeName { + pub fn normalize_to_macros_2_0(&self) -> LifetimeName { match *self { - LifetimeName::Param(param_name) => LifetimeName::Param(param_name.modern()), + LifetimeName::Param(param_name) => { + LifetimeName::Param(param_name.normalize_to_macros_2_0()) + } lifetime_name => lifetime_name, } } @@ -597,7 +598,7 @@ pub struct WhereEqPredicate<'hir> { pub rhs_ty: &'hir Ty<'hir>, } -#[derive(RustcEncodable, RustcDecodable, Debug)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] pub struct ModuleItems { // Use BTreeSets here so items are in the same order as in the // list of all items in Crate @@ -606,6 +607,14 @@ pub struct ModuleItems { pub impl_items: BTreeSet, } +/// A type representing only the top-level module. +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] +pub struct CrateItem<'hir> { + pub module: Mod<'hir>, + pub attrs: &'hir [Attribute], + pub span: Span, +} + /// The top-level data structure that stores the entire contents of /// the crate currently being compiled. /// @@ -614,9 +623,7 @@ pub struct ModuleItems { /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html #[derive(RustcEncodable, RustcDecodable, Debug)] pub struct Crate<'hir> { - pub module: Mod<'hir>, - pub attrs: &'hir [Attribute], - pub span: Span, + pub item: CrateItem<'hir>, pub exported_macros: &'hir [MacroDef<'hir>], // Attributes from non-exported macros, kept only for collecting the library feature list. pub non_exported_macro_attrs: &'hir [Attribute], @@ -722,13 +729,12 @@ impl Crate<'_> { /// Not parsed directly, but created on macro import or `macro_rules!` expansion. #[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] pub struct MacroDef<'hir> { - pub name: Name, + pub ident: Ident, pub vis: Visibility<'hir>, pub attrs: &'hir [Attribute], pub hir_id: HirId, pub span: Span, - pub body: TokenStream, - pub legacy: bool, + pub ast: ast::MacroDef, } /// A block of statements `{ .. }`, which may have a label (in this case the @@ -1850,7 +1856,7 @@ pub struct TraitItem<'hir> { /// Represents a trait method's body (or just argument names). #[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] -pub enum TraitMethod<'hir> { +pub enum TraitFn<'hir> { /// No default body in the trait, just a signature. Required(&'hir [Ident]), @@ -1864,7 +1870,7 @@ pub enum TraitItemKind<'hir> { /// An associated constant with an optional value (otherwise `impl`s must contain a value). Const(&'hir Ty<'hir>, Option), /// An associated function with an optional body. - Fn(FnSig<'hir>, TraitMethod<'hir>), + Fn(FnSig<'hir>, TraitFn<'hir>), /// An associated type with (possibly empty) bounds and optional concrete /// type. Type(GenericBounds<'hir>, Option<&'hir Ty<'hir>>), @@ -1897,8 +1903,8 @@ pub enum ImplItemKind<'hir> { /// An associated constant of the given type, set to the constant result /// of the expression. Const(&'hir Ty<'hir>, BodyId), - /// A method implementation with the given signature and body. - Method(FnSig<'hir>, BodyId), + /// An associated function implementation with the given signature and body. + Fn(FnSig<'hir>, BodyId), /// An associated type. TyAlias(&'hir Ty<'hir>), /// An associated `type = impl Trait`. @@ -1909,7 +1915,7 @@ impl ImplItemKind<'_> { pub fn namespace(&self) -> Namespace { match self { ImplItemKind::OpaqueTy(..) | ImplItemKind::TyAlias(..) => Namespace::TypeNS, - ImplItemKind::Const(..) | ImplItemKind::Method(..) => Namespace::ValueNS, + ImplItemKind::Const(..) | ImplItemKind::Fn(..) => Namespace::ValueNS, } } } @@ -2147,7 +2153,7 @@ pub enum Defaultness { impl Defaultness { pub fn has_value(&self) -> bool { match *self { - Defaultness::Default { has_value, .. } => has_value, + Defaultness::Default { has_value } => has_value, Defaultness::Final => true, } } @@ -2496,6 +2502,9 @@ pub enum ItemKind<'hir> { unsafety: Unsafety, polarity: ImplPolarity, defaultness: Defaultness, + // We do not put a `Span` in `Defaultness` because it breaks foreign crate metadata + // decoding as `Span`s cannot be decoded when a `Session` is not available. + defaultness_span: Option, constness: Constness, generics: Generics<'hir>, @@ -2653,7 +2662,7 @@ pub type TraitMap = NodeMap>>; // imported. pub type GlobMap = NodeMap>; -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, HashStable_Generic)] pub enum Node<'hir> { Param(&'hir Param<'hir>), Item(&'hir Item<'hir>), @@ -2683,7 +2692,7 @@ pub enum Node<'hir> { GenericParam(&'hir GenericParam<'hir>), Visibility(&'hir Visibility<'hir>), - Crate, + Crate(&'hir CrateItem<'hir>), } impl Node<'_> { @@ -2700,7 +2709,7 @@ impl Node<'_> { pub fn fn_decl(&self) -> Option<&FnDecl<'_>> { match self { Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. }) - | Node::ImplItem(ImplItem { kind: ImplItemKind::Method(fn_sig, _), .. }) + | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. }) | Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig.decl), Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => { Some(fn_decl) diff --git a/src/librustc_hir/hir_id.rs b/src/librustc_hir/hir_id.rs index 6d2ec44576353..1c7987e965f85 100644 --- a/src/librustc_hir/hir_id.rs +++ b/src/librustc_hir/hir_id.rs @@ -1,9 +1,8 @@ -use crate::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX}; -use rustc_serialize::{self, Decodable, Decoder, Encodable, Encoder}; +use crate::def_id::{LocalDefId, CRATE_DEF_INDEX}; use std::fmt; /// Uniquely identifies a node in the HIR of the current crate. It is -/// composed of the `owner`, which is the `DefIndex` of the directly enclosing +/// composed of the `owner`, which is the `LocalDefId` of the directly enclosing /// `hir::Item`, `hir::TraitItem`, or `hir::ImplItem` (i.e., the closest "item-like"), /// and the `local_id` which is unique within the given owner. /// @@ -12,41 +11,12 @@ use std::fmt; /// the `local_id` part of the `HirId` changing, which is a very useful property in /// incremental compilation where we have to persist things through changes to /// the code base. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord, RustcEncodable, RustcDecodable)] pub struct HirId { - pub owner: DefIndex, + pub owner: LocalDefId, pub local_id: ItemLocalId, } -impl HirId { - pub fn owner_def_id(self) -> DefId { - DefId::local(self.owner) - } - - pub fn owner_local_def_id(self) -> LocalDefId { - LocalDefId::from_def_id(DefId::local(self.owner)) - } -} - -impl rustc_serialize::UseSpecializedEncodable for HirId { - fn default_encode(&self, s: &mut S) -> Result<(), S::Error> { - let HirId { owner, local_id } = *self; - - owner.encode(s)?; - local_id.encode(s)?; - Ok(()) - } -} - -impl rustc_serialize::UseSpecializedDecodable for HirId { - fn default_decode(d: &mut D) -> Result { - let owner = DefIndex::decode(d)?; - let local_id = ItemLocalId::decode(d)?; - - Ok(HirId { owner, local_id }) - } -} - impl fmt::Display for HirId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", self) @@ -70,9 +40,12 @@ rustc_index::newtype_index! { rustc_data_structures::impl_stable_hash_via_hash!(ItemLocalId); /// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_INDEX`. -pub const CRATE_HIR_ID: HirId = - HirId { owner: CRATE_DEF_INDEX, local_id: ItemLocalId::from_u32_const(0) }; +pub const CRATE_HIR_ID: HirId = HirId { + owner: LocalDefId { local_def_index: CRATE_DEF_INDEX }, + local_id: ItemLocalId::from_u32(0), +}; -pub const DUMMY_HIR_ID: HirId = HirId { owner: CRATE_DEF_INDEX, local_id: DUMMY_ITEM_LOCAL_ID }; +pub const DUMMY_HIR_ID: HirId = + HirId { owner: LocalDefId { local_def_index: CRATE_DEF_INDEX }, local_id: DUMMY_ITEM_LOCAL_ID }; pub const DUMMY_ITEM_LOCAL_ID: ItemLocalId = ItemLocalId::MAX; diff --git a/src/librustc_hir/intravisit.rs b/src/librustc_hir/intravisit.rs index e92192c8b1f72..11749cf996b44 100644 --- a/src/librustc_hir/intravisit.rs +++ b/src/librustc_hir/intravisit.rs @@ -127,6 +127,25 @@ pub trait Map<'hir> { fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir>; } +/// An erased version of `Map<'hir>`, using dynamic dispatch. +/// NOTE: This type is effectively only usable with `NestedVisitorMap::None`. +pub struct ErasedMap<'hir>(&'hir dyn Map<'hir>); + +impl<'hir> Map<'hir> for ErasedMap<'hir> { + fn body(&self, id: BodyId) -> &'hir Body<'hir> { + self.0.body(id) + } + fn item(&self, id: HirId) -> &'hir Item<'hir> { + self.0.item(id) + } + fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> { + self.0.trait_item(id) + } + fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> { + self.0.impl_item(id) + } +} + /// Specifies what nested things a visitor wants to visit. The most /// common choice is `OnlyBodies`, which will cause the visitor to /// visit fn bodies for fns that it encounters, but skip over nested @@ -134,7 +153,7 @@ pub trait Map<'hir> { /// /// See the comments on `ItemLikeVisitor` for more details on the overall /// visit strategy. -pub enum NestedVisitorMap<'this, M> { +pub enum NestedVisitorMap { /// Do not visit any nested things. When you add a new /// "non-nested" thing, you will want to audit such uses to see if /// they remain valid. @@ -151,20 +170,20 @@ pub enum NestedVisitorMap<'this, M> { /// to use `visit_all_item_likes()` as an outer loop, /// and to have the visitor that visits the contents of each item /// using this setting. - OnlyBodies(&'this M), + OnlyBodies(M), /// Visits all nested things, including item-likes. /// /// **This is an unusual choice.** It is used when you want to /// process everything within their lexical context. Typically you /// kick off the visit by doing `walk_krate()`. - All(&'this M), + All(M), } -impl<'this, M> NestedVisitorMap<'this, M> { +impl NestedVisitorMap { /// Returns the map to use for an "intra item-like" thing (if any). /// E.g., function body. - fn intra(self) -> Option<&'this M> { + fn intra(self) -> Option { match self { NestedVisitorMap::None => None, NestedVisitorMap::OnlyBodies(map) => Some(map), @@ -174,7 +193,7 @@ impl<'this, M> NestedVisitorMap<'this, M> { /// Returns the map to use for an "item-like" thing (if any). /// E.g., item, impl-item. - fn inter(self) -> Option<&'this M> { + fn inter(self) -> Option { match self { NestedVisitorMap::None => None, NestedVisitorMap::OnlyBodies(_) => None, @@ -221,7 +240,7 @@ pub trait Visitor<'v>: Sized { /// `panic!()`. This way, if a new `visit_nested_XXX` variant is /// added in the future, we will see the panic in your code and /// fix it appropriately. - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map>; + fn nested_visit_map(&mut self) -> NestedVisitorMap; /// Invoked when a nested item is encountered. By default does /// nothing unless you override `nested_visit_map` to return other than @@ -284,7 +303,7 @@ pub trait Visitor<'v>: Sized { /// If you use this, you probably don't want to process the /// contents of nested item-like things, since the outer loop will /// visit them as well. - fn as_deep_visitor<'s>(&'s mut self) -> DeepVisitor<'s, Self> { + fn as_deep_visitor(&mut self) -> DeepVisitor<'_, Self> { DeepVisitor::new(self) } @@ -438,14 +457,14 @@ pub trait Visitor<'v>: Sized { /// Walks the contents of a crate. See also `Crate::visit_all_items`. pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate<'v>) { - visitor.visit_mod(&krate.module, krate.span, CRATE_HIR_ID); - walk_list!(visitor, visit_attribute, krate.attrs); + visitor.visit_mod(&krate.item.module, krate.item.span, CRATE_HIR_ID); + walk_list!(visitor, visit_attribute, krate.item.attrs); walk_list!(visitor, visit_macro_def, krate.exported_macros); } pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef<'v>) { visitor.visit_id(macro_def.hir_id); - visitor.visit_name(macro_def.span, macro_def.name); + visitor.visit_ident(macro_def.ident); walk_list!(visitor, visit_attribute, macro_def.attrs); } @@ -571,6 +590,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) { defaultness: _, polarity: _, constness: _, + defaultness_span: _, ref generics, ref of_trait, ref self_ty, @@ -911,14 +931,14 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai visitor.visit_ty(ty); walk_list!(visitor, visit_nested_body, default); } - TraitItemKind::Fn(ref sig, TraitMethod::Required(param_names)) => { + TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => { visitor.visit_id(trait_item.hir_id); visitor.visit_fn_decl(&sig.decl); for ¶m_name in param_names { visitor.visit_ident(param_name); } } - TraitItemKind::Fn(ref sig, TraitMethod::Provided(body_id)) => { + TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => { visitor.visit_fn( FnKind::Method(trait_item.ident, sig, None, &trait_item.attrs), &sig.decl, @@ -968,7 +988,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt visitor.visit_ty(ty); visitor.visit_nested_body(body); } - ImplItemKind::Method(ref sig, body_id) => { + ImplItemKind::Fn(ref sig, body_id) => { visitor.visit_fn( FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis), &impl_item.attrs), &sig.decl, diff --git a/src/librustc_hir/lang_items.rs b/src/librustc_hir/lang_items.rs index fc91b68e3ea44..89457009a8bfa 100644 --- a/src/librustc_hir/lang_items.rs +++ b/src/librustc_hir/lang_items.rs @@ -240,7 +240,6 @@ language_item_table! { StartFnLangItem, "start", start_fn, Target::Fn; EhPersonalityLangItem, "eh_personality", eh_personality, Target::Fn; - EhUnwindResumeLangItem, "eh_unwind_resume", eh_unwind_resume, Target::Fn; EhCatchTypeinfoLangItem, "eh_catch_typeinfo", eh_catch_typeinfo, Target::Static; OwnedBoxLangItem, "owned_box", owned_box, Target::Struct; diff --git a/src/librustc_hir/lib.rs b/src/librustc_hir/lib.rs index 45f806b53f50c..fbb3d6b2af37c 100644 --- a/src/librustc_hir/lib.rs +++ b/src/librustc_hir/lib.rs @@ -3,7 +3,9 @@ //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html #![feature(crate_visibility_modifier)] +#![feature(const_if_match)] #![feature(const_fn)] // For the unsizing cast on `&[]` +#![feature(const_panic)] #![feature(in_band_lifetimes)] #![feature(specialization)] #![recursion_limit = "256"] @@ -11,7 +13,9 @@ #[macro_use] extern crate rustc_data_structures; +mod arena; pub mod def; +pub mod definitions; pub use rustc_span::def_id; mod hir; pub mod hir_id; diff --git a/src/librustc_hir/print.rs b/src/librustc_hir/print.rs index 7eb5cc417b7e6..cd16e451f1db8 100644 --- a/src/librustc_hir/print.rs +++ b/src/librustc_hir/print.rs @@ -102,7 +102,7 @@ impl<'a> State<'a> { Node::Ctor(..) => panic!("cannot print isolated Ctor"), Node::Local(a) => self.print_local_decl(&a), Node::MacroDef(_) => panic!("cannot print MacroDef"), - Node::Crate => panic!("cannot print Crate"), + Node::Crate(..) => panic!("cannot print Crate"), } } } @@ -151,7 +151,7 @@ pub fn print_crate<'a>( // When printing the AST, we sometimes need to inject `#[no_std]` here. // Since you can't compile the HIR, it's not necessary. - s.print_mod(&krate.module, &krate.attrs); + s.print_mod(&krate.item.module, &krate.item.attrs); s.print_remaining_comments(); s.s.eof() } @@ -632,6 +632,7 @@ impl<'a> State<'a> { polarity, defaultness, constness, + defaultness_span: _, ref generics, ref of_trait, ref self_ty, @@ -886,13 +887,13 @@ impl<'a> State<'a> { Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited }; self.print_associated_const(ti.ident, &ty, default, &vis); } - hir::TraitItemKind::Fn(ref sig, hir::TraitMethod::Required(ref arg_names)) => { + hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(ref arg_names)) => { let vis = Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited }; self.print_method_sig(ti.ident, sig, &ti.generics, &vis, arg_names, None); self.s.word(";"); } - hir::TraitItemKind::Fn(ref sig, hir::TraitMethod::Provided(body)) => { + hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { let vis = Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited }; self.head(""); @@ -925,7 +926,7 @@ impl<'a> State<'a> { hir::ImplItemKind::Const(ref ty, expr) => { self.print_associated_const(ii.ident, &ty, Some(expr), &ii.vis); } - hir::ImplItemKind::Method(ref sig, body) => { + hir::ImplItemKind::Fn(ref sig, body) => { self.head(""); self.print_method_sig(ii.ident, sig, &ii.generics, &ii.vis, &[], Some(body)); self.nbsp(); diff --git a/src/librustc_hir/stable_hash_impls.rs b/src/librustc_hir/stable_hash_impls.rs index 3938a0369b924..996b310896904 100644 --- a/src/librustc_hir/stable_hash_impls.rs +++ b/src/librustc_hir/stable_hash_impls.rs @@ -1,7 +1,11 @@ -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; -use crate::hir::{BodyId, Expr, ImplItemId, ItemId, Mod, TraitItemId, Ty, VisibilityKind}; -use crate::hir_id::HirId; +use crate::hir::{ + BodyId, Expr, ImplItem, ImplItemId, Item, ItemId, Mod, TraitItem, TraitItemId, Ty, + VisibilityKind, +}; +use crate::hir_id::{HirId, ItemLocalId}; +use rustc_span::def_id::{DefPathHash, LocalDefId}; /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro @@ -16,6 +20,36 @@ pub trait HashStableContext: fn hash_hir_expr(&mut self, _: &Expr<'_>, hasher: &mut StableHasher); fn hash_hir_ty(&mut self, _: &Ty<'_>, hasher: &mut StableHasher); fn hash_hir_visibility_kind(&mut self, _: &VisibilityKind<'_>, hasher: &mut StableHasher); + fn hash_hir_item_like(&mut self, f: F); + fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash; +} + +impl ToStableHashKey for HirId { + type KeyType = (DefPathHash, ItemLocalId); + + #[inline] + fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) { + let def_path_hash = hcx.local_def_path_hash(self.owner); + (def_path_hash, self.local_id) + } +} + +impl ToStableHashKey for TraitItemId { + type KeyType = (DefPathHash, ItemLocalId); + + #[inline] + fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) { + self.hir_id.to_stable_hash_key(hcx) + } +} + +impl ToStableHashKey for ImplItemId { + type KeyType = (DefPathHash, ItemLocalId); + + #[inline] + fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) { + self.hir_id.to_stable_hash_key(hcx) + } } impl HashStable for HirId { @@ -78,3 +112,56 @@ impl HashStable for VisibilityKind<'_> hcx.hash_hir_visibility_kind(self, hasher) } } + +impl HashStable for TraitItem<'_> { + fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { + let TraitItem { hir_id: _, ident, ref attrs, ref generics, ref kind, span } = *self; + + hcx.hash_hir_item_like(|hcx| { + ident.name.hash_stable(hcx, hasher); + attrs.hash_stable(hcx, hasher); + generics.hash_stable(hcx, hasher); + kind.hash_stable(hcx, hasher); + span.hash_stable(hcx, hasher); + }); + } +} + +impl HashStable for ImplItem<'_> { + fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { + let ImplItem { + hir_id: _, + ident, + ref vis, + defaultness, + ref attrs, + ref generics, + ref kind, + span, + } = *self; + + hcx.hash_hir_item_like(|hcx| { + ident.name.hash_stable(hcx, hasher); + vis.hash_stable(hcx, hasher); + defaultness.hash_stable(hcx, hasher); + attrs.hash_stable(hcx, hasher); + generics.hash_stable(hcx, hasher); + kind.hash_stable(hcx, hasher); + span.hash_stable(hcx, hasher); + }); + } +} + +impl HashStable for Item<'_> { + fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { + let Item { ident, ref attrs, hir_id: _, ref kind, ref vis, span } = *self; + + hcx.hash_hir_item_like(|hcx| { + ident.name.hash_stable(hcx, hasher); + attrs.hash_stable(hcx, hasher); + kind.hash_stable(hcx, hasher); + vis.hash_stable(hcx, hasher); + span.hash_stable(hcx, hasher); + }); + } +} diff --git a/src/librustc_hir/target.rs b/src/librustc_hir/target.rs index b7bc555d7b410..3a4485a1b17fd 100644 --- a/src/librustc_hir/target.rs +++ b/src/librustc_hir/target.rs @@ -105,10 +105,10 @@ impl Target { pub fn from_trait_item(trait_item: &TraitItem<'_>) -> Target { match trait_item.kind { TraitItemKind::Const(..) => Target::AssocConst, - TraitItemKind::Fn(_, hir::TraitMethod::Required(_)) => { + TraitItemKind::Fn(_, hir::TraitFn::Required(_)) => { Target::Method(MethodKind::Trait { body: false }) } - TraitItemKind::Fn(_, hir::TraitMethod::Provided(_)) => { + TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => { Target::Method(MethodKind::Trait { body: true }) } TraitItemKind::Type(..) => Target::AssocTy, diff --git a/src/librustc_hir/weak_lang_items.rs b/src/librustc_hir/weak_lang_items.rs index 405a31d5a69ad..c0560eb8d455a 100644 --- a/src/librustc_hir/weak_lang_items.rs +++ b/src/librustc_hir/weak_lang_items.rs @@ -43,6 +43,5 @@ impl LanguageItems { weak_lang_items! { panic_impl, PanicImplLangItem, rust_begin_unwind; eh_personality, EhPersonalityLangItem, rust_eh_personality; - eh_unwind_resume, EhUnwindResumeLangItem, rust_eh_unwind_resume; oom, OomLangItem, rust_oom; } diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs index c82ed0c2c4970..305e0fcc383ad 100644 --- a/src/librustc_incremental/assert_dep_graph.rs +++ b/src/librustc_incremental/assert_dep_graph.rs @@ -35,7 +35,7 @@ use graphviz as dot; use rustc::dep_graph::debug::{DepNodeFilter, EdgeFilter}; -use rustc::dep_graph::{DepGraphQuery, DepKind, DepNode}; +use rustc::dep_graph::{DepGraphQuery, DepKind, DepNode, DepNodeExt}; use rustc::hir::map::Map; use rustc::ty::TyCtxt; use rustc_ast::ast; @@ -68,7 +68,7 @@ pub fn assert_dep_graph(tcx: TyCtxt<'_>) { let (if_this_changed, then_this_would_need) = { let mut visitor = IfThisChanged { tcx, if_this_changed: vec![], then_this_would_need: vec![] }; - visitor.process_attrs(hir::CRATE_HIR_ID, &tcx.hir().krate().attrs); + visitor.process_attrs(hir::CRATE_HIR_ID, &tcx.hir().krate().item.attrs); tcx.hir().krate().visit_all_item_likes(&mut visitor.as_deep_visitor()); (visitor.if_this_changed, visitor.then_this_would_need) }; @@ -120,7 +120,7 @@ impl IfThisChanged<'tcx> { if attr.check_name(sym::rustc_if_this_changed) { let dep_node_interned = self.argument(attr); let dep_node = match dep_node_interned { - None => def_path_hash.to_dep_node(DepKind::Hir), + None => DepNode::from_def_path_hash(def_path_hash, DepKind::hir_owner), Some(n) => match DepNode::from_label_string(&n.as_str(), def_path_hash) { Ok(n) => n, Err(()) => { @@ -162,8 +162,8 @@ impl IfThisChanged<'tcx> { impl Visitor<'tcx> for IfThisChanged<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs index 261540abcad5d..c5446116f4c50 100644 --- a/src/librustc_incremental/assert_module_sources.rs +++ b/src/librustc_incremental/assert_module_sources.rs @@ -44,7 +44,7 @@ pub fn assert_module_sources(tcx: TyCtxt<'_>) { let ams = AssertModuleSource { tcx, available_cgus }; - for attr in tcx.hir().krate().attrs { + for attr in tcx.hir().krate().item.attrs { ams.check_attr(attr); } }) @@ -175,6 +175,6 @@ impl AssertModuleSource<'tcx> { return true; } debug!("check_config: no match found"); - return false; + false } } diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index 54815fe3468ea..9ddd238afff2b 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -13,7 +13,7 @@ //! Errors are reported if we are in the suitable configuration but //! the required condition is not met. -use rustc::dep_graph::{label_strs, DepNode}; +use rustc::dep_graph::{label_strs, DepNode, DepNodeExt}; use rustc::hir::map::Map; use rustc::ty::TyCtxt; use rustc_ast::ast::{self, Attribute, NestedMetaItem}; @@ -53,9 +53,9 @@ const BASE_FN: &[&str] = &[ /// DepNodes for Hir, which is pretty much everything const BASE_HIR: &[&str] = &[ - // Hir and HirBody should be computed for all nodes - label_strs::Hir, - label_strs::HirBody, + // hir_owner and hir_owner_nodes should be computed for all nodes + label_strs::hir_owner, + label_strs::hir_owner_nodes, ]; /// `impl` implementation of struct/trait @@ -333,7 +333,7 @@ impl DirtyCleanVisitor<'tcx> { TraitItemKind::Type(..) => ("NodeTraitType", LABELS_CONST_IN_TRAIT), }, HirNode::ImplItem(item) => match item.kind { - ImplItemKind::Method(..) => ("Node::ImplItem", LABELS_FN_IN_IMPL), + ImplItemKind::Fn(..) => ("Node::ImplItem", LABELS_FN_IN_IMPL), ImplItemKind::Const(..) => ("NodeImplConst", LABELS_CONST_IN_IMPL), ImplItemKind::TyAlias(..) => ("NodeImplType", LABELS_CONST_IN_IMPL), ImplItemKind::OpaqueTy(..) => ("NodeImplType", LABELS_CONST_IN_IMPL), @@ -548,8 +548,8 @@ impl FindAllAttrs<'tcx> { impl intravisit::Visitor<'tcx> for FindAllAttrs<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, Self::Map> { - intravisit::NestedVisitorMap::All(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { + intravisit::NestedVisitorMap::All(self.tcx.hir()) } fn visit_attribute(&mut self, attr: &'tcx Attribute) { diff --git a/src/librustc_incremental/persist/file_format.rs b/src/librustc_incremental/persist/file_format.rs index 5c72b049d97e9..048a81b81bab3 100644 --- a/src/librustc_incremental/persist/file_format.rs +++ b/src/librustc_incremental/persist/file_format.rs @@ -14,8 +14,8 @@ use std::fs; use std::io::{self, Read}; use std::path::Path; -use rustc::session::config::nightly_options; use rustc_serialize::opaque::Encoder; +use rustc_session::config::nightly_options; /// The first few bytes of files generated by incremental compilation. const FILE_MAGIC: &[u8] = b"RSIC"; diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs index 8548ad392d2dd..4926f726f3593 100644 --- a/src/librustc_incremental/persist/fs.rs +++ b/src/librustc_incremental/persist/fs.rs @@ -103,11 +103,11 @@ //! unsupported file system and emit a warning in that case. This is not yet //! implemented. -use rustc::session::{CrateDisambiguator, Session}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::svh::Svh; use rustc_data_structures::{base_n, flock}; use rustc_fs_util::{link_or_copy, LinkOrCopy}; +use rustc_session::{CrateDisambiguator, Session}; use std::fs as std_fs; use std::io; diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index 6c57f79e1a7fb..537906eb87189 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -1,12 +1,12 @@ //! Code to save/load the dep-graph from files. use rustc::dep_graph::{PreviousDepGraph, SerializedDepGraph, WorkProduct, WorkProductId}; -use rustc::session::Session; use rustc::ty::query::OnDiskCache; use rustc::ty::TyCtxt; use rustc_data_structures::fx::FxHashMap; use rustc_serialize::opaque::Decoder; use rustc_serialize::Decodable as RustcDecodable; +use rustc_session::Session; use std::path::Path; use super::data::*; @@ -195,7 +195,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { } pub fn load_query_result_cache(sess: &Session) -> OnDiskCache<'_> { - if sess.opts.incremental.is_none() || !sess.opts.debugging_opts.incremental_queries { + if sess.opts.incremental.is_none() { return OnDiskCache::new_empty(sess.source_map()); } diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs index 87f39dedd0273..17dbad5c8bb49 100644 --- a/src/librustc_incremental/persist/save.rs +++ b/src/librustc_incremental/persist/save.rs @@ -1,10 +1,10 @@ use rustc::dep_graph::{DepGraph, DepKind, WorkProduct, WorkProductId}; -use rustc::session::Session; use rustc::ty::TyCtxt; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::join; use rustc_serialize::opaque::Encoder; use rustc_serialize::Encodable as RustcEncodable; +use rustc_session::Session; use std::fs; use std::path::PathBuf; @@ -31,11 +31,9 @@ pub fn save_dep_graph(tcx: TyCtxt<'_>) { join( move || { - if tcx.sess.opts.debugging_opts.incremental_queries { - sess.time("incr_comp_persist_result_cache", || { - save_in(sess, query_cache_path, |e| encode_query_cache(tcx, e)); - }); - } + sess.time("incr_comp_persist_result_cache", || { + save_in(sess, query_cache_path, |e| encode_query_cache(tcx, e)); + }); }, || { sess.time("incr_comp_persist_dep_graph", || { @@ -132,7 +130,6 @@ where } Err(err) => { sess.err(&format!("failed to write dep-graph to `{}`: {}", path_buf.display(), err)); - return; } } } diff --git a/src/librustc_incremental/persist/work_product.rs b/src/librustc_incremental/persist/work_product.rs index b1861acec0426..aa3588b284b28 100644 --- a/src/librustc_incremental/persist/work_product.rs +++ b/src/librustc_incremental/persist/work_product.rs @@ -2,8 +2,8 @@ use crate::persist::fs::*; use rustc::dep_graph::{WorkProduct, WorkProductFileKind, WorkProductId}; -use rustc::session::Session; use rustc_fs_util::link_or_copy; +use rustc_session::Session; use std::fs as std_fs; use std::path::PathBuf; diff --git a/src/librustc_index/lib.rs b/src/librustc_index/lib.rs index 86dd1a29d0ce3..e8aa1a209e929 100644 --- a/src/librustc_index/lib.rs +++ b/src/librustc_index/lib.rs @@ -1,4 +1,7 @@ #![feature(allow_internal_unstable)] +#![feature(const_if_match)] +#![feature(const_fn)] +#![feature(const_panic)] #![feature(unboxed_closures)] #![feature(test)] #![feature(fn_traits)] diff --git a/src/librustc_index/vec.rs b/src/librustc_index/vec.rs index 7020939fa20b2..d8c67f6210c75 100644 --- a/src/librustc_index/vec.rs +++ b/src/librustc_index/vec.rs @@ -120,10 +120,10 @@ macro_rules! newtype_index { impl $type { $v const MAX_AS_U32: u32 = $max; - $v const MAX: Self = Self::from_u32_const($max); + $v const MAX: Self = Self::from_u32($max); #[inline] - $v fn from_usize(value: usize) -> Self { + $v const fn from_usize(value: usize) -> Self { assert!(value <= ($max as usize)); unsafe { Self::from_u32_unchecked(value as u32) @@ -131,31 +131,13 @@ macro_rules! newtype_index { } #[inline] - $v fn from_u32(value: u32) -> Self { + $v const fn from_u32(value: u32) -> Self { assert!(value <= $max); unsafe { Self::from_u32_unchecked(value) } } - /// Hacky variant of `from_u32` for use in constants. - /// This version checks the "max" constraint by using an - /// invalid array dereference. - #[inline] - $v const fn from_u32_const(value: u32) -> Self { - // This will fail at const eval time unless `value <= - // max` is true (in which case we get the index 0). - // It will also fail at runtime, of course, but in a - // kind of wacky way. - let _ = ["out of range value used"][ - !(value <= $max) as usize - ]; - - unsafe { - Self { private: value } - } - } - #[inline] $v const unsafe fn from_u32_unchecked(value: u32) -> Self { Self { private: value } @@ -163,19 +145,19 @@ macro_rules! newtype_index { /// Extracts the value of this index as an integer. #[inline] - $v fn index(self) -> usize { + $v const fn index(self) -> usize { self.as_usize() } /// Extracts the value of this index as a `u32`. #[inline] - $v fn as_u32(self) -> u32 { + $v const fn as_u32(self) -> u32 { self.private } /// Extracts the value of this index as a `usize`. #[inline] - $v fn as_usize(self) -> usize { + $v const fn as_usize(self) -> usize { self.as_u32() as usize } } @@ -500,7 +482,7 @@ macro_rules! newtype_index { const $name:ident = $constant:expr, $($tokens:tt)*) => ( $(#[doc = $doc])* - $v const $name: $type = $type::from_u32_const($constant); + $v const $name: $type = $type::from_u32($constant); $crate::newtype_index!( @derives [$($derives,)*] @attrs [$(#[$attrs])*] diff --git a/src/librustc_infer/Cargo.toml b/src/librustc_infer/Cargo.toml index de99214901d9b..9ecd056430c20 100644 --- a/src/librustc_infer/Cargo.toml +++ b/src/librustc_infer/Cargo.toml @@ -10,14 +10,11 @@ path = "lib.rs" doctest = false [dependencies] -fmt_macros = { path = "../libfmt_macros" } graphviz = { path = "../libgraphviz" } log = { version = "0.4", features = ["release_max_level_info", "std"] } -rustc_attr = { path = "../librustc_attr" } rustc = { path = "../librustc" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } -rustc_error_codes = { path = "../librustc_error_codes" } rustc_hir = { path = "../librustc_hir" } rustc_index = { path = "../librustc_index" } rustc_macros = { path = "../librustc_macros" } diff --git a/src/librustc_infer/infer/canonical/canonicalizer.rs b/src/librustc_infer/infer/canonical/canonicalizer.rs index 964e378f7abc8..4d9a81d440695 100644 --- a/src/librustc_infer/infer/canonical/canonicalizer.rs +++ b/src/librustc_infer/infer/canonical/canonicalizer.rs @@ -336,10 +336,6 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { | ty::ReEmpty(_) | ty::RePlaceholder(..) | ty::ReErased => self.canonicalize_region_mode.canonicalize_free_region(self, r), - - ty::ReClosureBound(..) => { - bug!("closure bound region encountered during canonicalization"); - } } } @@ -555,7 +551,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { // avoid allocations in those cases. We also don't use `indices` to // determine if a kind has been seen before until the limit of 8 has // been exceeded, to also avoid allocations for `indices`. - let var = if !var_values.spilled() { + if !var_values.spilled() { // `var_values` is stack-allocated. `indices` isn't used yet. Do a // direct linear search of `var_values`. if let Some(idx) = var_values.iter().position(|&k| k == kind) { @@ -589,9 +585,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { assert_eq!(variables.len(), var_values.len()); BoundVar::new(variables.len() - 1) }) - }; - - var + } } /// Shorthand helper that creates a canonical region variable for diff --git a/src/librustc_infer/infer/canonical/query_response.rs b/src/librustc_infer/infer/canonical/query_response.rs index b6c0dc3939bff..9322df4823511 100644 --- a/src/librustc_infer/infer/canonical/query_response.rs +++ b/src/librustc_infer/infer/canonical/query_response.rs @@ -14,7 +14,7 @@ use crate::infer::canonical::{ }; use crate::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate}; use crate::infer::region_constraints::{Constraint, RegionConstraintData}; -use crate::infer::{InferCtxt, InferCtxtBuilder, InferOk, InferResult, NLLRegionVariableOrigin}; +use crate::infer::{InferCtxt, InferOk, InferResult, NLLRegionVariableOrigin}; use crate::traits::query::{Fallible, NoSolution}; use crate::traits::{DomainGoal, TraitEngine}; use crate::traits::{Obligation, ObligationCause, PredicateObligation}; @@ -26,52 +26,8 @@ use rustc::ty::{self, BoundVar, Ty, TyCtxt}; use rustc_data_structures::captures::Captures; use rustc_index::vec::Idx; use rustc_index::vec::IndexVec; -use rustc_span::DUMMY_SP; use std::fmt::Debug; -impl<'tcx> InferCtxtBuilder<'tcx> { - /// The "main method" for a canonicalized trait query. Given the - /// canonical key `canonical_key`, this method will create a new - /// inference context, instantiate the key, and run your operation - /// `op`. The operation should yield up a result (of type `R`) as - /// well as a set of trait obligations that must be fully - /// satisfied. These obligations will be processed and the - /// canonical result created. - /// - /// Returns `NoSolution` in the event of any error. - /// - /// (It might be mildly nicer to implement this on `TyCtxt`, and - /// not `InferCtxtBuilder`, but that is a bit tricky right now. - /// In part because we would need a `for<'tcx>` sort of - /// bound for the closure and in part because it is convenient to - /// have `'tcx` be free on this function so that we can talk about - /// `K: TypeFoldable<'tcx>`.) - pub fn enter_canonical_trait_query( - &mut self, - canonical_key: &Canonical<'tcx, K>, - operation: impl FnOnce(&InferCtxt<'_, 'tcx>, &mut dyn TraitEngine<'tcx>, K) -> Fallible, - ) -> Fallible> - where - K: TypeFoldable<'tcx>, - R: Debug + TypeFoldable<'tcx>, - Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable, - { - self.enter_with_canonical( - DUMMY_SP, - canonical_key, - |ref infcx, key, canonical_inference_vars| { - let mut fulfill_cx = TraitEngine::new(infcx.tcx); - let value = operation(infcx, &mut *fulfill_cx, key)?; - infcx.make_canonicalized_query_response( - canonical_inference_vars, - value, - &mut *fulfill_cx, - ) - }, - ) - } -} - impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// This method is meant to be invoked as the final step of a canonical query /// implementation. It is given: diff --git a/src/librustc_infer/infer/combine.rs b/src/librustc_infer/infer/combine.rs index 9d06e26d9bb3c..0f5d4d30a2385 100644 --- a/src/librustc_infer/infer/combine.rs +++ b/src/librustc_infer/infer/combine.rs @@ -581,10 +581,6 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { return Ok(r); } - ty::ReClosureBound(..) => { - span_bug!(self.span, "encountered unexpected ReClosureBound: {:?}", r,); - } - ty::RePlaceholder(..) | ty::ReVar(..) | ty::ReEmpty(_) diff --git a/src/librustc_infer/infer/equate.rs b/src/librustc_infer/infer/equate.rs index bb0c124a1892d..8f8fc4f137b73 100644 --- a/src/librustc_infer/infer/equate.rs +++ b/src/librustc_infer/infer/equate.rs @@ -136,7 +136,7 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> { } else { // Fast path for the common case. self.relate(a.skip_binder(), b.skip_binder())?; - return Ok(a.clone()); + Ok(a.clone()) } } } diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index 7e418898910dc..129bc9e22a667 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -49,14 +49,12 @@ use super::lexical_region_resolve::RegionResolutionError; use super::region_constraints::GenericKind; use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs}; -use crate::infer::opaque_types; -use crate::infer::{self, SuppressRegionErrors}; +use crate::infer; use crate::traits::error_reporting::report_object_safety_error; use crate::traits::{ IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode, }; -use rustc::hir::map; use rustc::middle::region; use rustc::ty::error::TypeError; use rustc::ty::{ @@ -153,11 +151,6 @@ pub(super) fn note_and_explain_region( ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => { (format!("lifetime {:?}", region), None) } - - // We shouldn't encounter an error message with ReClosureBound. - ty::ReClosureBound(..) => { - bug!("encountered unexpected ReClosureBound: {:?}", region,); - } }; emit_msg_span(err, prefix, description, span, suffix); @@ -207,7 +200,7 @@ fn msg_span_from_early_bound_and_free_regions( }; let (prefix, span) = match *region { ty::ReEarlyBound(ref br) => { - let mut sp = sm.def_span(tcx.hir().span(node)); + let mut sp = sm.guess_head_span(tcx.hir().span(node)); if let Some(param) = tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name)) { @@ -216,7 +209,7 @@ fn msg_span_from_early_bound_and_free_regions( (format!("the lifetime `{}` as defined on", br.name), sp) } ty::ReFree(ty::FreeRegion { bound_region: ty::BoundRegion::BrNamed(_, name), .. }) => { - let mut sp = sm.def_span(tcx.hir().span(node)); + let mut sp = sm.guess_head_span(tcx.hir().span(node)); if let Some(param) = tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(name)) { @@ -230,7 +223,7 @@ fn msg_span_from_early_bound_and_free_regions( } _ => ( format!("the lifetime `{}` as defined on", region), - sm.def_span(tcx.hir().span(node)), + sm.guess_head_span(tcx.hir().span(node)), ), }, _ => bug!(), @@ -276,7 +269,7 @@ fn trait_item_scope_tag(item: &hir::TraitItem<'_>) -> &'static str { fn impl_item_scope_tag(item: &hir::ImplItem<'_>) -> &'static str { match item.kind { - hir::ImplItemKind::Method(..) => "method body", + hir::ImplItemKind::Fn(..) => "method body", hir::ImplItemKind::Const(..) | hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(..) => "associated item", @@ -288,22 +281,93 @@ fn explain_span(tcx: TyCtxt<'tcx>, heading: &str, span: Span) -> (String, Option (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1), Some(span)) } +pub fn unexpected_hidden_region_diagnostic( + tcx: TyCtxt<'tcx>, + region_scope_tree: Option<®ion::ScopeTree>, + span: Span, + hidden_ty: Ty<'tcx>, + hidden_region: ty::Region<'tcx>, +) -> DiagnosticBuilder<'tcx> { + let mut err = struct_span_err!( + tcx.sess, + span, + E0700, + "hidden type for `impl Trait` captures lifetime that does not appear in bounds", + ); + + // Explain the region we are capturing. + if let ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic | ty::ReEmpty(_) = hidden_region { + // Assuming regionck succeeded (*), we ought to always be + // capturing *some* region from the fn header, and hence it + // ought to be free. So under normal circumstances, we will go + // down this path which gives a decent human readable + // explanation. + // + // (*) if not, the `tainted_by_errors` flag would be set to + // true in any case, so we wouldn't be here at all. + note_and_explain_free_region( + tcx, + &mut err, + &format!("hidden type `{}` captures ", hidden_ty), + hidden_region, + "", + ); + } else { + // Ugh. This is a painful case: the hidden region is not one + // that we can easily summarize or explain. This can happen + // in a case like + // `src/test/ui/multiple-lifetimes/ordinary-bounds-unsuited.rs`: + // + // ``` + // fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> { + // if condition() { a } else { b } + // } + // ``` + // + // Here the captured lifetime is the intersection of `'a` and + // `'b`, which we can't quite express. + + if let Some(region_scope_tree) = region_scope_tree { + // If the `region_scope_tree` is available, this is being + // invoked from the "region inferencer error". We can at + // least report a really cryptic error for now. + note_and_explain_region( + tcx, + region_scope_tree, + &mut err, + &format!("hidden type `{}` captures ", hidden_ty), + hidden_region, + "", + ); + } else { + // If the `region_scope_tree` is *unavailable*, this is + // being invoked by the code that comes *after* region + // inferencing. This is a bug, as the region inferencer + // ought to have noticed the failed constraint and invoked + // error reporting, which in turn should have prevented us + // from getting trying to infer the hidden type + // completely. + tcx.sess.delay_span_bug( + span, + &format!( + "hidden type captures unexpected lifetime `{:?}` \ + but no region inference failure", + hidden_region, + ), + ); + } + } + + err +} + impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn report_region_errors( &self, region_scope_tree: ®ion::ScopeTree, errors: &Vec>, - suppress: SuppressRegionErrors, ) { - debug!( - "report_region_errors(): {} errors to start, suppress = {:?}", - errors.len(), - suppress - ); - - if suppress.suppressed() { - return; - } + debug!("report_region_errors(): {} errors to start", errors.len()); // try to pre-process the errors, which will group some of them // together into a `ProcessedErrors` group: @@ -410,7 +474,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { span, } => { let hidden_ty = self.resolve_vars_if_possible(&hidden_ty); - opaque_types::unexpected_hidden_region_diagnostic( + unexpected_hidden_region_diagnostic( self.tcx, Some(region_scope_tree), span, @@ -484,7 +548,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { terr: &TypeError<'tcx>, ) { use hir::def_id::CrateNum; - use map::DisambiguatedDefPathData; + use rustc_hir::definitions::DisambiguatedDefPathData; use ty::print::Printer; use ty::subst::GenericArg; @@ -1714,11 +1778,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // suggest adding an explicit lifetime bound to it. let type_param_span = match (self.in_progress_tables, bound_kind) { (Some(ref table), GenericKind::Param(ref param)) => { - let table = table.borrow(); - table.local_id_root.and_then(|did| { - let generics = self.tcx.generics_of(did); - // Account for the case where `did` corresponds to `Self`, which doesn't have - // the expected type argument. + let table_owner = table.borrow().hir_owner; + table_owner.and_then(|table_owner| { + let generics = self.tcx.generics_of(table_owner.to_def_id()); + // Account for the case where `param` corresponds to `Self`, + // which doesn't have the expected type argument. if !(generics.has_self && param.index == 0) { let type_param = generics.type_param(param, self.tcx); let hir = &self.tcx.hir(); @@ -2077,7 +2141,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { /// This is a bare signal of what kind of type we're dealing with. `ty::TyKind` tracks /// extra information about each type, but we only care about the category. #[derive(Clone, Copy, PartialEq, Eq, Hash)] -crate enum TyCategory { +pub enum TyCategory { Closure, Opaque, Generator, diff --git a/src/librustc_infer/infer/error_reporting/need_type_info.rs b/src/librustc_infer/infer/error_reporting/need_type_info.rs index fe70215dc27a5..fcbe938a8c7ac 100644 --- a/src/librustc_infer/infer/error_reporting/need_type_info.rs +++ b/src/librustc_infer/infer/error_reporting/need_type_info.rs @@ -3,7 +3,7 @@ use crate::infer::InferCtxt; use rustc::hir::map::Map; use rustc::ty::print::Print; use rustc::ty::{self, DefIdTree, Infer, Ty, TyVar}; -use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; +use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; @@ -16,7 +16,7 @@ use std::borrow::Cow; struct FindLocalByTypeVisitor<'a, 'tcx> { infcx: &'a InferCtxt<'a, 'tcx>, target_ty: Ty<'tcx>, - hir_map: &'a Map<'tcx>, + hir_map: Map<'tcx>, found_local_pattern: Option<&'tcx Pat<'tcx>>, found_arg_pattern: Option<&'tcx Pat<'tcx>>, found_ty: Option>, @@ -25,7 +25,7 @@ struct FindLocalByTypeVisitor<'a, 'tcx> { } impl<'a, 'tcx> FindLocalByTypeVisitor<'a, 'tcx> { - fn new(infcx: &'a InferCtxt<'a, 'tcx>, target_ty: Ty<'tcx>, hir_map: &'a Map<'tcx>) -> Self { + fn new(infcx: &'a InferCtxt<'a, 'tcx>, target_ty: Ty<'tcx>, hir_map: Map<'tcx>) -> Self { Self { infcx, target_ty, @@ -69,8 +69,8 @@ impl<'a, 'tcx> FindLocalByTypeVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for FindLocalByTypeVisitor<'a, 'tcx> { type Map = Map<'tcx>; - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.hir_map) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.hir_map) } fn visit_local(&mut self, local: &'tcx Local<'tcx>) { @@ -223,7 +223,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let ty = self.resolve_vars_if_possible(&ty); let (name, name_sp, descr, parent_name, parent_descr) = self.extract_type_name(&ty, None); - let mut local_visitor = FindLocalByTypeVisitor::new(&self, ty, &self.tcx.hir()); + let mut local_visitor = FindLocalByTypeVisitor::new(&self, ty, self.tcx.hir()); let ty_to_string = |ty: Ty<'tcx>| -> String { let mut s = String::new(); let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS); @@ -277,8 +277,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }; let ty_msg = match local_visitor.found_ty { - Some(ty::TyS { kind: ty::Closure(def_id, substs), .. }) => { - let fn_sig = substs.as_closure().sig(*def_id, self.tcx); + Some(ty::TyS { kind: ty::Closure(_, substs), .. }) => { + let fn_sig = substs.as_closure().sig(); let args = closure_args(&fn_sig); let ret = fn_sig.output().skip_binder().to_string(); format!(" for the closure `fn({}) -> {}`", args, ret) @@ -311,8 +311,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ); let suffix = match local_visitor.found_ty { - Some(ty::TyS { kind: ty::Closure(def_id, substs), .. }) => { - let fn_sig = substs.as_closure().sig(*def_id, self.tcx); + Some(ty::TyS { kind: ty::Closure(_, substs), .. }) => { + let fn_sig = substs.as_closure().sig(); let ret = fn_sig.output().skip_binder().to_string(); if let Some(ExprKind::Closure(_, decl, body_id, ..)) = local_visitor.found_closure { @@ -462,24 +462,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { e: &Expr<'_>, err: &mut DiagnosticBuilder<'_>, ) { - if let (Ok(snippet), Some(tables), None) = ( - self.tcx.sess.source_map().span_to_snippet(segment.ident.span), - self.in_progress_tables, - &segment.args, - ) { + if let (Some(tables), None) = (self.in_progress_tables, &segment.args) { let borrow = tables.borrow(); if let Some((DefKind::AssocFn, did)) = borrow.type_dependent_def(e.hir_id) { let generics = self.tcx.generics_of(did); if !generics.params.is_empty() { - err.span_suggestion( - segment.ident.span, + err.span_suggestion_verbose( + segment.ident.span.shrink_to_hi(), &format!( "consider specifying the type argument{} in the method call", - if generics.params.len() > 1 { "s" } else { "" }, + pluralize!(generics.params.len()), ), format!( - "{}::<{}>", - snippet, + "::<{}>", generics .params .iter() diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs index 1a09729ef6443..689323ce48346 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -3,6 +3,8 @@ use crate::infer::error_reporting::nice_region_error::util::AnonymousParamInfo; use crate::infer::error_reporting::nice_region_error::NiceRegionError; +use crate::infer::lexical_region_resolve::RegionResolutionError; +use crate::infer::SubregionOrigin; use rustc::util::common::ErrorReported; use rustc_errors::struct_span_err; @@ -47,6 +49,15 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { pub(super) fn try_report_anon_anon_conflict(&self) -> Option { let (span, sub, sup) = self.regions()?; + if let Some(RegionResolutionError::ConcreteFailure( + SubregionOrigin::ReferenceOutlivesReferent(..), + .., + )) = self.error + { + // This error doesn't make much sense in this case. + return None; + } + // Determine whether the sub and sup consist of both anonymous (elided) regions. let anon_reg_sup = self.tcx().is_suitable_region(sup)?; @@ -131,6 +142,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { .span_label(span_2, String::new()) .span_label(span, span_label) .emit(); - return Some(ErrorReported); + Some(ErrorReported) } } diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs index 7346cb0a03393..15acf632b2c98 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -37,7 +37,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { .. }) | Node::ImplItem(&hir::ImplItem { - kind: hir::ImplItemKind::Method(ref m, ..), + kind: hir::ImplItemKind::Fn(ref m, ..), .. }) => &m.decl, _ => return None, @@ -93,8 +93,8 @@ struct FindNestedTypeVisitor<'tcx> { impl Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.tcx.hir()) } fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) { @@ -212,8 +212,8 @@ struct TyPathVisitor<'tcx> { impl Visitor<'tcx> for TyPathVisitor<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Map<'tcx>> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap> { + NestedVisitorMap::OnlyBodies(self.tcx.hir()) } fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) { diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs index d8c314a0d2f1f..2357ee689d59e 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs @@ -17,12 +17,7 @@ mod util; impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { pub fn try_report_nice_region_error(&self, error: &RegionResolutionError<'tcx>) -> bool { - if let Some(tables) = self.in_progress_tables { - let tables = tables.borrow(); - NiceRegionError::new(self, error.clone(), Some(&tables)).try_report().is_some() - } else { - NiceRegionError::new(self, error.clone(), None).try_report().is_some() - } + NiceRegionError::new(self, error.clone()).try_report().is_some() } } @@ -30,16 +25,11 @@ pub struct NiceRegionError<'cx, 'tcx> { infcx: &'cx InferCtxt<'cx, 'tcx>, error: Option>, regions: Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)>, - tables: Option<&'cx ty::TypeckTables<'tcx>>, } impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> { - pub fn new( - infcx: &'cx InferCtxt<'cx, 'tcx>, - error: RegionResolutionError<'tcx>, - tables: Option<&'cx ty::TypeckTables<'tcx>>, - ) -> Self { - Self { infcx, error: Some(error), regions: None, tables } + pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>, error: RegionResolutionError<'tcx>) -> Self { + Self { infcx, error: Some(error), regions: None } } pub fn new_from_span( @@ -47,9 +37,8 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> { span: Span, sub: ty::Region<'tcx>, sup: ty::Region<'tcx>, - tables: Option<&'cx ty::TypeckTables<'tcx>>, ) -> Self { - Self { infcx, error: None, regions: Some((span, sub, sup)), tables } + Self { infcx, error: None, regions: Some((span, sub, sup)) } } fn tcx(&self) -> TyCtxt<'tcx> { diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs index cab632935fd8e..de72c276595f7 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs @@ -51,52 +51,44 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { }; let hir = &self.tcx().hir(); - if let Some(hir_id) = hir.as_local_hir_id(id) { - if let Some(body_id) = hir.maybe_body_owned_by(hir_id) { - let body = hir.body(body_id); - let owner_id = hir.body_owner(body_id); - let fn_decl = hir.fn_decl_by_hir_id(owner_id).unwrap(); - if let Some(tables) = self.tables { - body.params - .iter() - .enumerate() - .filter_map(|(index, param)| { - // May return None; sometimes the tables are not yet populated. - let ty_hir_id = fn_decl.inputs[index].hir_id; - let param_ty_span = hir.span(ty_hir_id); - let ty = tables.node_type_opt(param.hir_id)?; - let mut found_anon_region = false; - let new_param_ty = self.tcx().fold_regions(&ty, &mut false, |r, _| { - if *r == *anon_region { - found_anon_region = true; - replace_region - } else { - r - } - }); - if found_anon_region { - let is_first = index == 0; - Some(AnonymousParamInfo { - param, - param_ty: new_param_ty, - param_ty_span, - bound_region, - is_first, - }) - } else { - None - } - }) - .next() + let hir_id = hir.as_local_hir_id(id)?; + let body_id = hir.maybe_body_owned_by(hir_id)?; + let body = hir.body(body_id); + let owner_id = hir.body_owner(body_id); + let fn_decl = hir.fn_decl_by_hir_id(owner_id).unwrap(); + let poly_fn_sig = self.tcx().fn_sig(id); + let fn_sig = self.tcx().liberate_late_bound_regions(id, &poly_fn_sig); + body.params + .iter() + .enumerate() + .filter_map(|(index, param)| { + // May return None; sometimes the tables are not yet populated. + let ty = fn_sig.inputs()[index]; + let mut found_anon_region = false; + let new_param_ty = self.tcx().fold_regions(&ty, &mut false, |r, _| { + if *r == *anon_region { + found_anon_region = true; + replace_region + } else { + r + } + }); + if found_anon_region { + let ty_hir_id = fn_decl.inputs[index].hir_id; + let param_ty_span = hir.span(ty_hir_id); + let is_first = index == 0; + Some(AnonymousParamInfo { + param, + param_ty: new_param_ty, + param_ty_span, + bound_region, + is_first, + }) } else { None } - } else { - None - } - } else { - None - } + }) + .next() } // Here, we check for the case where the anonymous region diff --git a/src/librustc_infer/infer/freshen.rs b/src/librustc_infer/infer/freshen.rs index a454feea36b70..fa28cf5b45464 100644 --- a/src/librustc_infer/infer/freshen.rs +++ b/src/librustc_infer/infer/freshen.rs @@ -135,10 +135,6 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { // replace all free regions with 'erased self.tcx().lifetimes.re_erased } - - ty::ReClosureBound(..) => { - bug!("encountered unexpected region: {:?}", r,); - } } } diff --git a/src/librustc_infer/infer/higher_ranked/mod.rs b/src/librustc_infer/infer/higher_ranked/mod.rs index 105b987f85e96..6a5a1c46d4caf 100644 --- a/src/librustc_infer/infer/higher_ranked/mod.rs +++ b/src/librustc_infer/infer/higher_ranked/mod.rs @@ -30,7 +30,7 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { let span = self.trace.cause.span; - return self.infcx.commit_if_ok(|snapshot| { + self.infcx.commit_if_ok(|snapshot| { // First, we instantiate each bound region in the supertype with a // fresh placeholder region. let (b_prime, placeholder_map) = self.infcx.replace_bound_vars_with_placeholders(b); @@ -53,7 +53,7 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { debug!("higher_ranked_sub: OK result={:?}", result); Ok(ty::Binder::bind(result)) - }); + }) } } diff --git a/src/librustc_infer/infer/lexical_region_resolve/mod.rs b/src/librustc_infer/infer/lexical_region_resolve/mod.rs index b7278ecd5e407..d81c7454a0fe5 100644 --- a/src/librustc_infer/infer/lexical_region_resolve/mod.rs +++ b/src/librustc_infer/infer/lexical_region_resolve/mod.rs @@ -7,6 +7,7 @@ use crate::infer::region_constraints::RegionConstraintData; use crate::infer::region_constraints::VarInfos; use crate::infer::region_constraints::VerifyBound; use crate::infer::RegionVariableOrigin; +use crate::infer::RegionckMode; use crate::infer::SubregionOrigin; use rustc::middle::free_region::RegionRelations; use rustc::ty::fold::TypeFoldable; @@ -33,12 +34,29 @@ pub fn resolve<'tcx>( region_rels: &RegionRelations<'_, 'tcx>, var_infos: VarInfos, data: RegionConstraintData<'tcx>, + mode: RegionckMode, ) -> (LexicalRegionResolutions<'tcx>, Vec>) { debug!("RegionConstraintData: resolve_regions()"); let mut errors = vec![]; let mut resolver = LexicalResolver { region_rels, var_infos, data }; - let values = resolver.infer_variable_values(&mut errors); - (values, errors) + match mode { + RegionckMode::Solve => { + let values = resolver.infer_variable_values(&mut errors); + (values, errors) + } + RegionckMode::Erase { suppress_errors: false } => { + // Do real inference to get errors, then erase the results. + let mut values = resolver.infer_variable_values(&mut errors); + let re_erased = region_rels.tcx.lifetimes.re_erased; + + values.values.iter_mut().for_each(|v| *v = VarValue::Value(re_erased)); + (values, errors) + } + RegionckMode::Erase { suppress_errors: true } => { + // Skip region inference entirely. + (resolver.erased_data(region_rels.tcx), Vec::new()) + } + } } /// Contains the result of lexical region resolution. Offers methods @@ -163,6 +181,19 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { } } + /// An erased version of the lexical region resolutions. Used when we're + /// erasing regions and suppressing errors: in item bodies with + /// `-Zborrowck=mir`. + fn erased_data(&self, tcx: TyCtxt<'tcx>) -> LexicalRegionResolutions<'tcx> { + LexicalRegionResolutions { + error_region: tcx.lifetimes.re_static, + values: IndexVec::from_elem_n( + VarValue::Value(tcx.lifetimes.re_erased), + self.num_vars(), + ), + } + } + fn dump_constraints(&self, free_regions: &RegionRelations<'_, 'tcx>) { debug!("----() Start constraint listing (context={:?}) ()----", free_regions.context); for (idx, (constraint, _)) in self.data.constraints.iter().enumerate() { @@ -421,12 +452,10 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { debug!("Expanding value of {:?} from {:?} to {:?}", b_vid, cur_region, lub); *b_data = VarValue::Value(lub); - return true; + true } - VarValue::ErrorValue => { - return false; - } + VarValue::ErrorValue => false, } } @@ -464,12 +493,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { /// term "concrete regions"). fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> { let r = match (a, b) { - (&ty::ReClosureBound(..), _) - | (_, &ty::ReClosureBound(..)) - | (&ReLateBound(..), _) - | (_, &ReLateBound(..)) - | (&ReErased, _) - | (_, &ReErased) => { + (&ReLateBound(..), _) | (_, &ReLateBound(..)) | (&ReErased, _) | (_, &ReErased) => { bug!("cannot relate region: LUB({:?}, {:?})", a, b); } @@ -773,7 +797,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { } } - return graph; + graph } fn collect_error_for_expanding_node( diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs index 938a0e7ab39df..dc494b8e41370 100644 --- a/src/librustc_infer/infer/mod.rs +++ b/src/librustc_infer/infer/mod.rs @@ -5,7 +5,6 @@ pub use self::LateBoundRegionConversionTime::*; pub use self::RegionVariableOrigin::*; pub use self::SubregionOrigin::*; pub use self::ValuePairs::*; -pub use rustc::ty::IntVarValue; use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine}; @@ -13,27 +12,28 @@ use rustc::infer::canonical::{Canonical, CanonicalVarValues}; use rustc::infer::unify_key::{ConstVarValue, ConstVariableValue}; use rustc::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType}; use rustc::middle::free_region::RegionRelations; -use rustc::middle::lang_items; use rustc::middle::region; use rustc::mir; use rustc::mir::interpret::ConstEvalResult; -use rustc::session::config::BorrowckMode; +use rustc::traits::select; use rustc::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric}; use rustc::ty::fold::{TypeFoldable, TypeFolder}; use rustc::ty::relate::RelateResult; -use rustc::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; +use rustc::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef}; +pub use rustc::ty::IntVarValue; use rustc::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt}; use rustc::ty::{ConstVid, FloatVid, IntVid, TyVid}; - use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::unify as ut; use rustc_errors::DiagnosticBuilder; use rustc_hir as hir; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_session::config::BorrowckMode; use rustc_span::symbol::Symbol; use rustc_span::Span; + use std::cell::{Cell, Ref, RefCell}; use std::collections::BTreeMap; use std::fmt; @@ -58,7 +58,6 @@ pub mod lattice; mod lexical_region_resolve; mod lub; pub mod nll_relate; -pub mod opaque_types; pub mod outlives; pub mod region_constraints; pub mod resolve; @@ -80,31 +79,50 @@ pub type Bound = Option; pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result" pub type FixupResult<'tcx, T> = Result>; // "fixup result" -/// A flag that is used to suppress region errors. This is normally -/// false, but sometimes -- when we are doing region checks that the -/// NLL borrow checker will also do -- it might be set to true. -#[derive(Copy, Clone, Default, Debug)] -pub struct SuppressRegionErrors { - suppressed: bool, +/// How we should handle region solving. +/// +/// This is used so that the region values inferred by HIR region solving are +/// not exposed, and so that we can avoid doing work in HIR typeck that MIR +/// typeck will also do. +#[derive(Copy, Clone, Debug)] +pub enum RegionckMode { + /// The default mode: report region errors, don't erase regions. + Solve, + /// Erase the results of region after solving. + Erase { + /// A flag that is used to suppress region errors, when we are doing + /// region checks that the NLL borrow checker will also do -- it might + /// be set to true. + suppress_errors: bool, + }, +} + +impl Default for RegionckMode { + fn default() -> Self { + RegionckMode::Solve + } } -impl SuppressRegionErrors { +impl RegionckMode { pub fn suppressed(self) -> bool { - self.suppressed + match self { + Self::Solve => false, + Self::Erase { suppress_errors } => suppress_errors, + } } /// Indicates that the MIR borrowck will repeat these region /// checks, so we should ignore errors if NLL is (unconditionally) /// enabled. - pub fn when_nll_is_enabled(tcx: TyCtxt<'_>) -> Self { + pub fn for_item_body(tcx: TyCtxt<'_>) -> Self { // FIXME(Centril): Once we actually remove `::Migrate` also make // this always `true` and then proceed to eliminate the dead code. match tcx.borrowck_mode() { // If we're on Migrate mode, report AST region errors - BorrowckMode::Migrate => SuppressRegionErrors { suppressed: false }, + BorrowckMode::Migrate => RegionckMode::Erase { suppress_errors: false }, // If we're on MIR, don't report AST region errors as they should be reported by NLL - BorrowckMode::Mir => SuppressRegionErrors { suppressed: true }, + BorrowckMode::Mir => RegionckMode::Erase { suppress_errors: true }, } } } @@ -215,10 +233,10 @@ pub struct InferCtxt<'a, 'tcx> { /// Caches the results of trait selection. This cache is used /// for things that have to do with the parameters in scope. - pub selection_cache: traits::SelectionCache<'tcx>, + pub selection_cache: select::SelectionCache<'tcx>, /// Caches the results of trait evaluation. - pub evaluation_cache: traits::EvaluationCache<'tcx>, + pub evaluation_cache: select::EvaluationCache<'tcx>, /// the set of predicates on which errors have been reported, to /// avoid reporting the same error twice. @@ -483,6 +501,7 @@ impl NLLRegionVariableOrigin { } } +// FIXME(eddyb) investigate overlap between this and `TyOrConstInferVar`. #[derive(Copy, Clone, Debug)] pub enum FixupError<'tcx> { UnresolvedIntTy(IntVid), @@ -541,7 +560,7 @@ impl TyCtxtInferExt<'tcx> for TyCtxt<'tcx> { impl<'tcx> InferCtxtBuilder<'tcx> { /// Used only by `rustc_typeck` during body type-checking/inference, /// will initialize `in_progress_tables` with fresh `TypeckTables`. - pub fn with_fresh_in_progress_tables(mut self, table_owner: DefId) -> Self { + pub fn with_fresh_in_progress_tables(mut self, table_owner: LocalDefId) -> Self { self.fresh_tables = Some(RefCell::new(ty::TypeckTables::empty(Some(table_owner)))); self } @@ -1208,20 +1227,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { region_context: DefId, region_map: ®ion::ScopeTree, outlives_env: &OutlivesEnvironment<'tcx>, - suppress: SuppressRegionErrors, + mode: RegionckMode, ) { assert!( self.is_tainted_by_errors() || self.inner.borrow().region_obligations.is_empty(), "region_obligations not empty: {:#?}", self.inner.borrow().region_obligations ); - - let region_rels = &RegionRelations::new( - self.tcx, - region_context, - region_map, - outlives_env.free_region_map(), - ); let (var_infos, data) = self .inner .borrow_mut() @@ -1229,8 +1241,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .take() .expect("regions already resolved") .into_infos_and_data(); + + let region_rels = &RegionRelations::new( + self.tcx, + region_context, + region_map, + outlives_env.free_region_map(), + ); + let (lexical_region_resolutions, errors) = - lexical_region_resolve::resolve(region_rels, var_infos, data); + lexical_region_resolve::resolve(region_rels, var_infos, data, mode); let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions)); assert!(old_value.is_none()); @@ -1241,7 +1261,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // this infcx was in use. This is totally hokey but // otherwise we have a hard time separating legit region // errors from silly ones. - self.report_region_errors(region_map, &errors, suppress); + self.report_region_errors(region_map, &errors); } } @@ -1328,8 +1348,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { where T: TypeFoldable<'tcx>, { - let mut r = ShallowResolver::new(self); - value.fold_with(&mut r) + value.fold_with(&mut ShallowResolver { infcx: self }) } pub fn root_var(&self, var: ty::TyVid) -> ty::TyVid { @@ -1474,74 +1493,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .verify_generic_bound(origin, kind, a, bound); } - pub fn type_is_copy_modulo_regions( - &self, - param_env: ty::ParamEnv<'tcx>, - ty: Ty<'tcx>, - span: Span, - ) -> bool { - let ty = self.resolve_vars_if_possible(&ty); - - if !(param_env, ty).has_local_value() { - return ty.is_copy_modulo_regions(self.tcx, param_env, span); - } - - let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem, None); - - // This can get called from typeck (by euv), and `moves_by_default` - // rightly refuses to work with inference variables, but - // moves_by_default has a cache, which we want to use in other - // cases. - traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id, span) - } - /// Obtains the latest type of the given closure; this may be a /// closure in the current function, in which case its /// `ClosureKind` may not yet be known. - pub fn closure_kind( - &self, - closure_def_id: DefId, - closure_substs: SubstsRef<'tcx>, - ) -> Option { - let closure_kind_ty = closure_substs.as_closure().kind_ty(closure_def_id, self.tcx); + pub fn closure_kind(&self, closure_substs: SubstsRef<'tcx>) -> Option { + let closure_kind_ty = closure_substs.as_closure().kind_ty(); let closure_kind_ty = self.shallow_resolve(closure_kind_ty); closure_kind_ty.to_opt_closure_kind() } - /// Obtains the signature of a closure. For closures, unlike - /// `tcx.fn_sig(def_id)`, this method will work during the - /// type-checking of the enclosing function and return the closure - /// signature in its partially inferred state. - pub fn closure_sig(&self, def_id: DefId, substs: SubstsRef<'tcx>) -> ty::PolyFnSig<'tcx> { - let closure_sig_ty = substs.as_closure().sig_ty(def_id, self.tcx); - let closure_sig_ty = self.shallow_resolve(closure_sig_ty); - closure_sig_ty.fn_sig(self.tcx) - } - - /// Normalizes associated types in `value`, potentially returning - /// new obligations that must further be processed. - pub fn partially_normalize_associated_types_in( - &self, - span: Span, - body_id: hir::HirId, - param_env: ty::ParamEnv<'tcx>, - value: &T, - ) -> InferOk<'tcx, T> - where - T: TypeFoldable<'tcx>, - { - debug!("partially_normalize_associated_types_in(value={:?})", value); - let mut selcx = traits::SelectionContext::new(self); - let cause = ObligationCause::misc(span, body_id); - let traits::Normalized { value, obligations } = - traits::normalize(&mut selcx, param_env, cause, value); - debug!( - "partially_normalize_associated_types_in: result={:?} predicates={:?}", - value, obligations - ); - InferOk { value, obligations } - } - /// Clears the selection, evaluation, and projection caches. This is useful when /// repeatedly attempting to select an `Obligation` while changing only /// its `ParamEnv`, since `FulfillmentContext` doesn't use probing. @@ -1591,22 +1551,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // variables, thus we don't need to substitute back the original values. self.tcx.const_eval_resolve(param_env, def_id, substs, promoted, span) } -} - -pub struct ShallowResolver<'a, 'tcx> { - infcx: &'a InferCtxt<'a, 'tcx>, -} - -impl<'a, 'tcx> ShallowResolver<'a, 'tcx> { - #[inline(always)] - pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Self { - ShallowResolver { infcx } - } /// If `typ` is a type variable of some kind, resolve it one level /// (but do not resolve types found in the result). If `typ` is /// not a type variable, just return it unmodified. - pub fn shallow_resolve(&mut self, typ: Ty<'tcx>) -> Ty<'tcx> { + // FIXME(eddyb) inline into `ShallowResolver::visit_ty`. + fn shallow_resolve_ty(&self, typ: Ty<'tcx>) -> Ty<'tcx> { match typ.kind { ty::Infer(ty::TyVar(v)) => { // Not entirely obvious: if `typ` is a type variable, @@ -1620,69 +1570,133 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> { // depth. // // Note: if these two lines are combined into one we get - // dynamic borrow errors on `self.infcx.inner`. - let known = self.infcx.inner.borrow_mut().type_variables.probe(v).known(); - known.map(|t| self.fold_ty(t)).unwrap_or(typ) + // dynamic borrow errors on `self.inner`. + let known = self.inner.borrow_mut().type_variables.probe(v).known(); + known.map(|t| self.shallow_resolve_ty(t)).unwrap_or(typ) } ty::Infer(ty::IntVar(v)) => self - .infcx .inner .borrow_mut() .int_unification_table .probe_value(v) - .map(|v| v.to_type(self.infcx.tcx)) + .map(|v| v.to_type(self.tcx)) .unwrap_or(typ), ty::Infer(ty::FloatVar(v)) => self - .infcx .inner .borrow_mut() .float_unification_table .probe_value(v) - .map(|v| v.to_type(self.infcx.tcx)) + .map(|v| v.to_type(self.tcx)) .unwrap_or(typ), _ => typ, } } - // `resolver.shallow_resolve_changed(ty)` is equivalent to - // `resolver.shallow_resolve(ty) != ty`, but more efficient. It's always - // inlined, despite being large, because it has only two call sites that - // are extremely hot. + /// `ty_or_const_infer_var_changed` is equivalent to one of these two: + /// * `shallow_resolve(ty) != ty` (where `ty.kind = ty::Infer(_)`) + /// * `shallow_resolve(ct) != ct` (where `ct.kind = ty::ConstKind::Infer(_)`) + /// + /// However, `ty_or_const_infer_var_changed` is more efficient. It's always + /// inlined, despite being large, because it has only two call sites that + /// are extremely hot (both in `traits::fulfill`'s checking of `stalled_on` + /// inference variables), and it handles both `Ty` and `ty::Const` without + /// having to resort to storing full `GenericArg`s in `stalled_on`. #[inline(always)] - pub fn shallow_resolve_changed(&self, infer: ty::InferTy) -> bool { - match infer { - ty::TyVar(v) => { + pub fn ty_or_const_infer_var_changed(&self, infer_var: TyOrConstInferVar<'tcx>) -> bool { + match infer_var { + TyOrConstInferVar::Ty(v) => { use self::type_variable::TypeVariableValue; - // If `inlined_probe` returns a `Known` value its `kind` never - // matches `infer`. - match self.infcx.inner.borrow_mut().type_variables.inlined_probe(v) { + // If `inlined_probe` returns a `Known` value, it never equals + // `ty::Infer(ty::TyVar(v))`. + match self.inner.borrow_mut().type_variables.inlined_probe(v) { TypeVariableValue::Unknown { .. } => false, TypeVariableValue::Known { .. } => true, } } - ty::IntVar(v) => { - // If inlined_probe_value returns a value it's always a + TyOrConstInferVar::TyInt(v) => { + // If `inlined_probe_value` returns a value it's always a // `ty::Int(_)` or `ty::UInt(_)`, which never matches a // `ty::Infer(_)`. - self.infcx.inner.borrow_mut().int_unification_table.inlined_probe_value(v).is_some() + self.inner.borrow_mut().int_unification_table.inlined_probe_value(v).is_some() } - ty::FloatVar(v) => { - // If inlined_probe_value returns a value it's always a + TyOrConstInferVar::TyFloat(v) => { + // If `probe_value` returns a value it's always a // `ty::Float(_)`, which never matches a `ty::Infer(_)`. // // Not `inlined_probe_value(v)` because this call site is colder. - self.infcx.inner.borrow_mut().float_unification_table.probe_value(v).is_some() + self.inner.borrow_mut().float_unification_table.probe_value(v).is_some() + } + + TyOrConstInferVar::Const(v) => { + // If `probe_value` returns a `Known` value, it never equals + // `ty::ConstKind::Infer(ty::InferConst::Var(v))`. + // + // Not `inlined_probe_value(v)` because this call site is colder. + match self.inner.borrow_mut().const_unification_table.probe_value(v).val { + ConstVariableValue::Unknown { .. } => false, + ConstVariableValue::Known { .. } => true, + } } + } + } +} + +/// Helper for `ty_or_const_infer_var_changed` (see comment on that), currently +/// used only for `traits::fulfill`'s list of `stalled_on` inference variables. +#[derive(Copy, Clone, Debug)] +pub enum TyOrConstInferVar<'tcx> { + /// Equivalent to `ty::Infer(ty::TyVar(_))`. + Ty(TyVid), + /// Equivalent to `ty::Infer(ty::IntVar(_))`. + TyInt(IntVid), + /// Equivalent to `ty::Infer(ty::FloatVar(_))`. + TyFloat(FloatVid), + + /// Equivalent to `ty::ConstKind::Infer(ty::InferConst::Var(_))`. + Const(ConstVid<'tcx>), +} - _ => unreachable!(), +impl TyOrConstInferVar<'tcx> { + /// Tries to extract an inference variable from a type or a constant, returns `None` + /// for types other than `ty::Infer(_)` (or `InferTy::Fresh*`) and + /// for constants other than `ty::ConstKind::Infer(_)` (or `InferConst::Fresh`). + pub fn maybe_from_generic_arg(arg: GenericArg<'tcx>) -> Option { + match arg.unpack() { + GenericArgKind::Type(ty) => Self::maybe_from_ty(ty), + GenericArgKind::Const(ct) => Self::maybe_from_const(ct), + GenericArgKind::Lifetime(_) => None, } } + + /// Tries to extract an inference variable from a type, returns `None` + /// for types other than `ty::Infer(_)` (or `InferTy::Fresh*`). + pub fn maybe_from_ty(ty: Ty<'tcx>) -> Option { + match ty.kind { + ty::Infer(ty::TyVar(v)) => Some(TyOrConstInferVar::Ty(v)), + ty::Infer(ty::IntVar(v)) => Some(TyOrConstInferVar::TyInt(v)), + ty::Infer(ty::FloatVar(v)) => Some(TyOrConstInferVar::TyFloat(v)), + _ => None, + } + } + + /// Tries to extract an inference variable from a constant, returns `None` + /// for constants other than `ty::ConstKind::Infer(_)` (or `InferConst::Fresh`). + pub fn maybe_from_const(ct: &'tcx ty::Const<'tcx>) -> Option { + match ct.val { + ty::ConstKind::Infer(InferConst::Var(v)) => Some(TyOrConstInferVar::Const(v)), + _ => None, + } + } +} + +struct ShallowResolver<'a, 'tcx> { + infcx: &'a InferCtxt<'a, 'tcx>, } impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> { @@ -1691,7 +1705,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> { } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.shallow_resolve(ty) + self.infcx.shallow_resolve_ty(ty) } fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { diff --git a/src/librustc_infer/infer/nll_relate/mod.rs b/src/librustc_infer/infer/nll_relate/mod.rs index 50bea300c5064..c194e968013eb 100644 --- a/src/librustc_infer/infer/nll_relate/mod.rs +++ b/src/librustc_infer/infer/nll_relate/mod.rs @@ -877,7 +877,7 @@ where // If sub-roots are equal, then `for_vid` and // `vid` are related via subtyping. debug!("TypeGeneralizer::tys: occurs check failed"); - return Err(TypeError::Mismatch); + Err(TypeError::Mismatch) } else { match variables.probe(vid) { TypeVariableValue::Known { value: u } => { @@ -898,7 +898,7 @@ where let u = self.tcx().mk_ty_var(new_var_id); debug!("generalize: replacing original vid={:?} with new={:?}", vid, u); - return Ok(u); + Ok(u) } } } diff --git a/src/librustc_infer/infer/outlives/env.rs b/src/librustc_infer/infer/outlives/env.rs index aac6c7640ca6b..6c1e86bf408b0 100644 --- a/src/librustc_infer/infer/outlives/env.rs +++ b/src/librustc_infer/infer/outlives/env.rs @@ -1,10 +1,11 @@ use crate::infer::{GenericKind, InferCtxt}; -use crate::traits::query::outlives_bounds::{self, OutlivesBound}; +use crate::traits::query::OutlivesBound; +use rustc::ty; use rustc::ty::free_region_map::FreeRegionMap; -use rustc::ty::{self, Ty}; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; -use rustc_span::Span; + +use super::explicit_outlives_bounds; /// The `OutlivesEnvironment` collects information about what outlives /// what in a given type-checking setting. For example, if we have a @@ -76,7 +77,7 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> { region_bound_pairs_accum: vec![], }; - env.add_outlives_bounds(None, outlives_bounds::explicit_outlives_bounds(param_env)); + env.add_outlives_bounds(None, explicit_outlives_bounds(param_env)); env } @@ -142,39 +143,6 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> { self.region_bound_pairs_accum.truncate(len); } - /// This method adds "implied bounds" into the outlives environment. - /// Implied bounds are outlives relationships that we can deduce - /// on the basis that certain types must be well-formed -- these are - /// either the types that appear in the function signature or else - /// the input types to an impl. For example, if you have a function - /// like - /// - /// ``` - /// fn foo<'a, 'b, T>(x: &'a &'b [T]) { } - /// ``` - /// - /// we can assume in the caller's body that `'b: 'a` and that `T: - /// 'b` (and hence, transitively, that `T: 'a`). This method would - /// add those assumptions into the outlives-environment. - /// - /// Tests: `src/test/compile-fail/regions-free-region-ordering-*.rs` - pub fn add_implied_bounds( - &mut self, - infcx: &InferCtxt<'a, 'tcx>, - fn_sig_tys: &[Ty<'tcx>], - body_id: hir::HirId, - span: Span, - ) { - debug!("add_implied_bounds()"); - - for &ty in fn_sig_tys { - let ty = infcx.resolve_vars_if_possible(&ty); - debug!("add_implied_bounds: ty = {}", ty); - let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty, span); - self.add_outlives_bounds(Some(infcx), implied_bounds) - } - } - /// Save the current set of region-bound pairs under the given `body_id`. pub fn save_implied_bounds(&mut self, body_id: hir::HirId) { let old = @@ -188,8 +156,11 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> { /// contain inference variables, it must be supplied, in which /// case we will register "givens" on the inference context. (See /// `RegionConstraintData`.) - fn add_outlives_bounds(&mut self, infcx: Option<&InferCtxt<'a, 'tcx>>, outlives_bounds: I) - where + pub fn add_outlives_bounds( + &mut self, + infcx: Option<&InferCtxt<'a, 'tcx>>, + outlives_bounds: I, + ) where I: IntoIterator>, { // Record relationships such as `T:'x` that don't go into the diff --git a/src/librustc_infer/infer/outlives/mod.rs b/src/librustc_infer/infer/outlives/mod.rs index 6fc72470c9fb7..75cf742de31a7 100644 --- a/src/librustc_infer/infer/outlives/mod.rs +++ b/src/librustc_infer/infer/outlives/mod.rs @@ -3,3 +3,25 @@ pub mod env; pub mod obligations; pub mod verify; + +use rustc::traits::query::OutlivesBound; +use rustc::ty; + +pub fn explicit_outlives_bounds<'tcx>( + param_env: ty::ParamEnv<'tcx>, +) -> impl Iterator> + 'tcx { + debug!("explicit_outlives_bounds()"); + param_env.caller_bounds.into_iter().filter_map(move |predicate| match predicate { + ty::Predicate::Projection(..) + | ty::Predicate::Trait(..) + | ty::Predicate::Subtype(..) + | ty::Predicate::WellFormed(..) + | ty::Predicate::ObjectSafe(..) + | ty::Predicate::ClosureKind(..) + | ty::Predicate::TypeOutlives(..) + | ty::Predicate::ConstEvaluatable(..) => None, + ty::Predicate::RegionOutlives(ref data) => data + .no_bound_vars() + .map(|ty::OutlivesPredicate(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a)), + }) +} diff --git a/src/librustc_infer/infer/region_constraints/mod.rs b/src/librustc_infer/infer/region_constraints/mod.rs index 868b95043796b..72637f4544a35 100644 --- a/src/librustc_infer/infer/region_constraints/mod.rs +++ b/src/librustc_infer/infer/region_constraints/mod.rs @@ -505,7 +505,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { self.undo_log.push(AddVar(vid)); } debug!("created new region variable {:?} in {:?} with origin {:?}", vid, universe, origin); - return vid; + vid } /// Returns the universe for the given variable. @@ -798,7 +798,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { | ty::ReEarlyBound(..) => ty::UniverseIndex::ROOT, ty::ReEmpty(ui) => ui, ty::RePlaceholder(placeholder) => placeholder.universe, - ty::ReClosureBound(vid) | ty::ReVar(vid) => self.var_universe(vid), + ty::ReVar(vid) => self.var_universe(vid), ty::ReLateBound(..) => bug!("universe(): encountered bound region {:?}", region), } } diff --git a/src/librustc_infer/infer/type_variable.rs b/src/librustc_infer/infer/type_variable.rs index b59c560669181..53bc70a5344ec 100644 --- a/src/librustc_infer/infer/type_variable.rs +++ b/src/librustc_infer/infer/type_variable.rs @@ -54,6 +54,7 @@ pub enum TypeVariableOriginKind { /// One of the upvars or closure kind parameters in a `ClosureSubsts` /// (before it has been determined). + // FIXME(eddyb) distinguish upvar inference variables from the rest. ClosureSynthetic, SubstitutionPlaceholder, AutoDeref, diff --git a/src/librustc_infer/lib.rs b/src/librustc_infer/lib.rs index 49e99b574b892..cb8ae8c592b22 100644 --- a/src/librustc_infer/lib.rs +++ b/src/librustc_infer/lib.rs @@ -1,6 +1,5 @@ -//! This crates defines the trait resolution method and the type inference engine. +//! This crates defines the type inference engine. //! -//! - **Traits.** Trait resolution is implemented in the `traits` module. //! - **Type inference.** The type inference code can be found in the `infer` module; //! this code handles low-level equality and subtyping operations. The //! type check pass in the compiler is found in the `librustc_typeck` crate. @@ -17,12 +16,11 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(drain_filter)] #![feature(never_type)] #![feature(range_is_empty)] #![feature(in_band_lifetimes)] #![feature(crate_visibility_modifier)] -#![recursion_limit = "512"] +#![recursion_limit = "512"] // For rustdoc #[macro_use] extern crate rustc_macros; diff --git a/src/librustc_infer/traits/engine.rs b/src/librustc_infer/traits/engine.rs index e23810dd1612d..9ad722342a19e 100644 --- a/src/librustc_infer/traits/engine.rs +++ b/src/librustc_infer/traits/engine.rs @@ -1,9 +1,9 @@ use crate::infer::InferCtxt; use crate::traits::Obligation; -use rustc::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness}; +use rustc::ty::{self, ToPredicate, Ty, WithConstness}; use rustc_hir::def_id::DefId; -use super::{FulfillmentContext, FulfillmentError}; +use super::FulfillmentError; use super::{ObligationCause, PredicateObligation}; pub trait TraitEngine<'tcx>: 'tcx { @@ -76,9 +76,3 @@ impl> TraitEngineExt<'tcx> for T { } } } - -impl dyn TraitEngine<'tcx> { - pub fn new(_tcx: TyCtxt<'tcx>) -> Box { - Box::new(FulfillmentContext::new()) - } -} diff --git a/src/librustc_infer/traits/error_reporting/mod.rs b/src/librustc_infer/traits/error_reporting/mod.rs index 10143ae015f2f..47d3cdb7a4e2b 100644 --- a/src/librustc_infer/traits/error_reporting/mod.rs +++ b/src/librustc_infer/traits/error_reporting/mod.rs @@ -1,452 +1,16 @@ -pub mod on_unimplemented; -pub mod suggestions; +use super::ObjectSafetyViolation; -use super::{ - ConstEvalFailure, EvaluationResult, FulfillmentError, FulfillmentErrorCode, - MismatchedProjectionTypes, ObjectSafetyViolation, Obligation, ObligationCause, - ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote, - OutputTypeParameterMismatch, Overflow, PredicateObligation, SelectionContext, SelectionError, - TraitNotObjectSafe, -}; - -use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode}; -use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use crate::infer::{self, InferCtxt, TyCtxtInferExt}; -use rustc::mir::interpret::ErrorHandled; -use rustc::session::DiagnosticMessageId; -use rustc::ty::error::ExpectedFound; -use rustc::ty::fast_reject; -use rustc::ty::fold::TypeFolder; -use rustc::ty::SubtypePredicate; -use rustc::ty::{ - self, AdtKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, -}; +use crate::infer::InferCtxt; +use rustc::ty::TyCtxt; use rustc_ast::ast; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, LOCAL_CRATE}; -use rustc_hir::{QPath, TyKind, WhereBoundPredicate, WherePredicate}; -use rustc_span::source_map::SourceMap; -use rustc_span::{ExpnKind, Span, DUMMY_SP}; +use rustc_hir::def_id::DefId; +use rustc_span::Span; use std::fmt; impl<'a, 'tcx> InferCtxt<'a, 'tcx> { - pub fn report_fulfillment_errors( - &self, - errors: &[FulfillmentError<'tcx>], - body_id: Option, - fallback_has_occurred: bool, - ) { - #[derive(Debug)] - struct ErrorDescriptor<'tcx> { - predicate: ty::Predicate<'tcx>, - index: Option, // None if this is an old error - } - - let mut error_map: FxHashMap<_, Vec<_>> = self - .reported_trait_errors - .borrow() - .iter() - .map(|(&span, predicates)| { - ( - span, - predicates - .iter() - .map(|&predicate| ErrorDescriptor { predicate, index: None }) - .collect(), - ) - }) - .collect(); - - for (index, error) in errors.iter().enumerate() { - // We want to ignore desugarings here: spans are equivalent even - // if one is the result of a desugaring and the other is not. - let mut span = error.obligation.cause.span; - let expn_data = span.ctxt().outer_expn_data(); - if let ExpnKind::Desugaring(_) = expn_data.kind { - span = expn_data.call_site; - } - - error_map.entry(span).or_default().push(ErrorDescriptor { - predicate: error.obligation.predicate, - index: Some(index), - }); - - self.reported_trait_errors - .borrow_mut() - .entry(span) - .or_default() - .push(error.obligation.predicate.clone()); - } - - // We do this in 2 passes because we want to display errors in order, though - // maybe it *is* better to sort errors by span or something. - let mut is_suppressed = vec![false; errors.len()]; - for (_, error_set) in error_map.iter() { - // We want to suppress "duplicate" errors with the same span. - for error in error_set { - if let Some(index) = error.index { - // Suppress errors that are either: - // 1) strictly implied by another error. - // 2) implied by an error with a smaller index. - for error2 in error_set { - if error2.index.map_or(false, |index2| is_suppressed[index2]) { - // Avoid errors being suppressed by already-suppressed - // errors, to prevent all errors from being suppressed - // at once. - continue; - } - - if self.error_implies(&error2.predicate, &error.predicate) - && !(error2.index >= error.index - && self.error_implies(&error.predicate, &error2.predicate)) - { - info!("skipping {:?} (implied by {:?})", error, error2); - is_suppressed[index] = true; - break; - } - } - } - } - } - - for (error, suppressed) in errors.iter().zip(is_suppressed) { - if !suppressed { - self.report_fulfillment_error(error, body_id, fallback_has_occurred); - } - } - } - - // returns if `cond` not occurring implies that `error` does not occur - i.e., that - // `error` occurring implies that `cond` occurs. - fn error_implies(&self, cond: &ty::Predicate<'tcx>, error: &ty::Predicate<'tcx>) -> bool { - if cond == error { - return true; - } - - let (cond, error) = match (cond, error) { - (&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error, _)) => (cond, error), - _ => { - // FIXME: make this work in other cases too. - return false; - } - }; - - for implication in super::elaborate_predicates(self.tcx, vec![*cond]) { - 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. - // Eventually I'll need to implement param-env-aware - // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic. - let param_env = ty::ParamEnv::empty(); - if self.can_sub(param_env, error, implication).is_ok() { - debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication); - return true; - } - } - } - - false - } - - fn report_fulfillment_error( - &self, - error: &FulfillmentError<'tcx>, - body_id: Option, - fallback_has_occurred: bool, - ) { - debug!("report_fulfillment_error({:?})", error); - match error.code { - FulfillmentErrorCode::CodeSelectionError(ref selection_error) => { - self.report_selection_error( - &error.obligation, - selection_error, - fallback_has_occurred, - error.points_at_arg_span, - ); - } - FulfillmentErrorCode::CodeProjectionError(ref e) => { - self.report_projection_error(&error.obligation, e); - } - FulfillmentErrorCode::CodeAmbiguity => { - self.maybe_report_ambiguity(&error.obligation, body_id); - } - FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => { - self.report_mismatched_types( - &error.obligation.cause, - expected_found.expected, - expected_found.found, - err.clone(), - ) - .emit(); - } - } - } - - fn report_projection_error( - &self, - obligation: &PredicateObligation<'tcx>, - error: &MismatchedProjectionTypes<'tcx>, - ) { - let predicate = self.resolve_vars_if_possible(&obligation.predicate); - - if predicate.references_error() { - return; - } - - self.probe(|_| { - let err_buf; - let mut err = &error.err; - let mut values = None; - - // try to find the mismatched types to report the error with. - // - // this can fail if the problem was higher-ranked, in which - // cause I have no idea for a good error message. - if let ty::Predicate::Projection(ref data) = predicate { - let mut selcx = SelectionContext::new(self); - let (data, _) = self.replace_bound_vars_with_fresh_vars( - obligation.cause.span, - infer::LateBoundRegionConversionTime::HigherRankedType, - data, - ); - let mut obligations = vec![]; - let normalized_ty = super::normalize_projection_type( - &mut selcx, - obligation.param_env, - data.projection_ty, - obligation.cause.clone(), - 0, - &mut obligations, - ); - - debug!( - "report_projection_error obligation.cause={:?} obligation.param_env={:?}", - obligation.cause, obligation.param_env - ); - - debug!( - "report_projection_error normalized_ty={:?} data.ty={:?}", - normalized_ty, data.ty - ); - - let is_normalized_ty_expected = match &obligation.cause.code { - ObligationCauseCode::ItemObligation(_) - | ObligationCauseCode::BindingObligation(_, _) - | ObligationCauseCode::ObjectCastObligation(_) => false, - _ => true, - }; - - if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp( - is_normalized_ty_expected, - normalized_ty, - data.ty, - ) { - values = Some(infer::ValuePairs::Types(ExpectedFound::new( - is_normalized_ty_expected, - normalized_ty, - data.ty, - ))); - - err_buf = error; - err = &err_buf; - } - } - - let msg = format!("type mismatch resolving `{}`", predicate); - let error_id = (DiagnosticMessageId::ErrorId(271), Some(obligation.cause.span), msg); - let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id); - if fresh { - let mut diag = struct_span_err!( - self.tcx.sess, - obligation.cause.span, - E0271, - "type mismatch resolving `{}`", - predicate - ); - self.note_type_err(&mut diag, &obligation.cause, None, values, err); - self.note_obligation_cause(&mut diag, obligation); - diag.emit(); - } - }); - } - - fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool { - /// returns the fuzzy category of a given type, or None - /// if the type can be equated to any type. - fn type_category(t: Ty<'_>) -> Option { - match t.kind { - ty::Bool => Some(0), - ty::Char => Some(1), - ty::Str => Some(2), - ty::Int(..) | ty::Uint(..) | ty::Infer(ty::IntVar(..)) => Some(3), - ty::Float(..) | ty::Infer(ty::FloatVar(..)) => Some(4), - ty::Ref(..) | ty::RawPtr(..) => Some(5), - ty::Array(..) | ty::Slice(..) => Some(6), - ty::FnDef(..) | ty::FnPtr(..) => Some(7), - ty::Dynamic(..) => Some(8), - ty::Closure(..) => Some(9), - ty::Tuple(..) => Some(10), - ty::Projection(..) => Some(11), - ty::Param(..) => Some(12), - ty::Opaque(..) => Some(13), - ty::Never => Some(14), - ty::Adt(adt, ..) => match adt.adt_kind() { - AdtKind::Struct => Some(15), - AdtKind::Union => Some(16), - AdtKind::Enum => Some(17), - }, - ty::Generator(..) => Some(18), - ty::Foreign(..) => Some(19), - ty::GeneratorWitness(..) => Some(20), - ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => None, - ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), - } - } - - match (type_category(a), type_category(b)) { - (Some(cat_a), Some(cat_b)) => match (&a.kind, &b.kind) { - (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => def_a == def_b, - _ => cat_a == cat_b, - }, - // infer and error can be equated to all types - _ => true, - } - } - - fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> { - self.tcx.hir().body(body_id).generator_kind.map(|gen_kind| match gen_kind { - hir::GeneratorKind::Gen => "a generator", - hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "an async block", - hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "an async function", - hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "an async closure", - }) - } - - fn find_similar_impl_candidates( - &self, - trait_ref: ty::PolyTraitRef<'tcx>, - ) -> Vec> { - let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true); - let all_impls = self.tcx.all_impls(trait_ref.def_id()); - - match simp { - Some(simp) => all_impls - .iter() - .filter_map(|&def_id| { - let imp = self.tcx.impl_trait_ref(def_id).unwrap(); - let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true); - if let Some(imp_simp) = imp_simp { - if simp != imp_simp { - return None; - } - } - - Some(imp) - }) - .collect(), - None => { - all_impls.iter().map(|&def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect() - } - } - } - - fn report_similar_impl_candidates( - &self, - impl_candidates: Vec>, - err: &mut DiagnosticBuilder<'_>, - ) { - if impl_candidates.is_empty() { - return; - } - - let len = impl_candidates.len(); - let end = if impl_candidates.len() <= 5 { impl_candidates.len() } else { 4 }; - - let normalize = |candidate| { - self.tcx.infer_ctxt().enter(|ref infcx| { - let normalized = infcx - .at(&ObligationCause::dummy(), ty::ParamEnv::empty()) - .normalize(candidate) - .ok(); - match normalized { - Some(normalized) => format!("\n {:?}", normalized.value), - None => format!("\n {:?}", candidate), - } - }) - }; - - // Sort impl candidates so that ordering is consistent for UI tests. - let mut normalized_impl_candidates = - impl_candidates.iter().map(normalize).collect::>(); - - // Sort before taking the `..end` range, - // because the ordering of `impl_candidates` may not be deterministic: - // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507 - normalized_impl_candidates.sort(); - - err.help(&format!( - "the following implementations were found:{}{}", - normalized_impl_candidates[..end].join(""), - if len > 5 { format!("\nand {} others", len - 4) } else { String::new() } - )); - } - - /// Reports that an overflow has occurred and halts compilation. We - /// halt compilation unconditionally because it is important that - /// overflows never be masked -- they basically represent computations - /// whose result could not be truly determined and thus we can't say - /// if the program type checks or not -- and they are unusual - /// occurrences in any case. - pub fn report_overflow_error( - &self, - obligation: &Obligation<'tcx, T>, - suggest_increasing_limit: bool, - ) -> ! - where - T: fmt::Display + TypeFoldable<'tcx>, - { - let predicate = self.resolve_vars_if_possible(&obligation.predicate); - let mut err = struct_span_err!( - self.tcx.sess, - obligation.cause.span, - E0275, - "overflow evaluating the requirement `{}`", - predicate - ); - - if suggest_increasing_limit { - self.suggest_new_overflow_limit(&mut err); - } - - self.note_obligation_cause_code( - &mut err, - &obligation.predicate, - &obligation.cause.code, - &mut vec![], - ); - - err.emit(); - self.tcx.sess.abort_if_errors(); - bug!(); - } - - /// Reports that a cycle was detected which led to overflow and halts - /// compilation. This is equivalent to `report_overflow_error` except - /// that we can give a more helpful error message (and, in particular, - /// we do not suggest increasing the overflow limit, which is not - /// going to help). - pub fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! { - let cycle = self.resolve_vars_if_possible(&cycle.to_owned()); - assert!(!cycle.is_empty()); - - debug!("report_overflow_error_cycle: cycle={:?}", cycle); - - self.report_overflow_error(&cycle[0], false); - } - pub fn report_extra_impl_obligation( &self, error_span: Span, @@ -456,12 +20,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { requirement: &dyn fmt::Display, ) -> DiagnosticBuilder<'tcx> { let msg = "impl has stricter requirements than trait"; - let sp = self.tcx.sess.source_map().def_span(error_span); + let sp = self.tcx.sess.source_map().guess_head_span(error_span); let mut err = struct_span_err!(self.tcx.sess, sp, E0276, "{}", msg); if let Some(trait_item_span) = self.tcx.hir().span_if_local(trait_item_def_id) { - let span = self.tcx.sess.source_map().def_span(trait_item_span); + let span = self.tcx.sess.source_map().guess_head_span(trait_item_span); err.span_label(span, format!("definition of `{}` from trait", item_name)); } @@ -469,550 +33,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err } - - /// Gets the parent trait chain start - fn get_parent_trait_ref( - &self, - code: &ObligationCauseCode<'tcx>, - ) -> Option<(String, Option)> { - match code { - &ObligationCauseCode::BuiltinDerivedObligation(ref data) => { - let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref); - match self.get_parent_trait_ref(&data.parent_code) { - Some(t) => Some(t), - None => { - let ty = parent_trait_ref.skip_binder().self_ty(); - let span = - TyCategory::from_ty(ty).map(|(_, def_id)| self.tcx.def_span(def_id)); - Some((ty.to_string(), span)) - } - } - } - _ => None, - } - } - - pub fn report_selection_error( - &self, - obligation: &PredicateObligation<'tcx>, - error: &SelectionError<'tcx>, - fallback_has_occurred: bool, - points_at_arg: bool, - ) { - let tcx = self.tcx; - let span = obligation.cause.span; - - let mut err = match *error { - SelectionError::Unimplemented => { - if let ObligationCauseCode::CompareImplMethodObligation { - item_name, - impl_item_def_id, - trait_item_def_id, - } - | ObligationCauseCode::CompareImplTypeObligation { - item_name, - impl_item_def_id, - trait_item_def_id, - } = obligation.cause.code - { - self.report_extra_impl_obligation( - span, - item_name, - impl_item_def_id, - trait_item_def_id, - &format!("`{}`", obligation.predicate), - ) - .emit(); - return; - } - match obligation.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() { - return; - } - let trait_ref = trait_predicate.to_poly_trait_ref(); - let (post_message, pre_message, type_def) = self - .get_parent_trait_ref(&obligation.cause.code) - .map(|(t, s)| { - ( - format!(" in `{}`", t), - format!("within `{}`, ", t), - s.map(|s| (format!("within this `{}`", t), s)), - ) - }) - .unwrap_or_default(); - - let OnUnimplementedNote { message, label, note, enclosing_scope } = - self.on_unimplemented_note(trait_ref, obligation); - let have_alt_message = message.is_some() || label.is_some(); - let is_try = self - .tcx - .sess - .source_map() - .span_to_snippet(span) - .map(|s| &s == "?") - .unwrap_or(false); - let is_from = format!("{}", trait_ref.print_only_trait_path()) - .starts_with("std::convert::From<"); - let (message, note) = if is_try && is_from { - ( - Some(format!( - "`?` couldn't convert the error to `{}`", - trait_ref.self_ty(), - )), - Some( - "the question mark operation (`?`) implicitly performs a \ - conversion on the error value using the `From` trait" - .to_owned(), - ), - ) - } else { - (message, note) - }; - - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0277, - "{}", - message.unwrap_or_else(|| format!( - "the trait bound `{}` is not satisfied{}", - trait_ref.without_const().to_predicate(), - post_message, - )) - ); - - let explanation = - if obligation.cause.code == ObligationCauseCode::MainFunctionType { - "consider using `()`, or a `Result`".to_owned() - } else { - format!( - "{}the trait `{}` is not implemented for `{}`", - pre_message, - trait_ref.print_only_trait_path(), - trait_ref.self_ty(), - ) - }; - - if self.suggest_add_reference_to_arg( - &obligation, - &mut err, - &trait_ref, - points_at_arg, - have_alt_message, - ) { - self.note_obligation_cause(&mut err, obligation); - err.emit(); - return; - } - if let Some(ref s) = label { - // If it has a custom `#[rustc_on_unimplemented]` - // error message, let's display it as the label! - err.span_label(span, s.as_str()); - err.help(&explanation); - } else { - err.span_label(span, explanation); - } - if let Some((msg, span)) = type_def { - err.span_label(span, &msg); - } - if let Some(ref s) = note { - // If it has a custom `#[rustc_on_unimplemented]` note, let's display it - err.note(s.as_str()); - } - if let Some(ref s) = enclosing_scope { - let enclosing_scope_span = tcx.def_span( - tcx.hir() - .opt_local_def_id(obligation.cause.body_id) - .unwrap_or_else(|| { - tcx.hir().body_owner_def_id(hir::BodyId { - hir_id: obligation.cause.body_id, - }) - }), - ); - - err.span_label(enclosing_scope_span, s.as_str()); - } - - self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err); - self.suggest_fn_call(&obligation, &mut err, &trait_ref, points_at_arg); - self.suggest_remove_reference(&obligation, &mut err, &trait_ref); - self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref); - self.note_version_mismatch(&mut err, &trait_ref); - if self.suggest_impl_trait(&mut err, span, &obligation, &trait_ref) { - err.emit(); - return; - } - - // Try to report a help message - if !trait_ref.has_infer_types_or_consts() - && self.predicate_can_apply(obligation.param_env, trait_ref) - { - // If a where-clause may be useful, remind the - // user that they can add it. - // - // don't display an on-unimplemented note, as - // these notes will often be of the form - // "the type `T` can't be frobnicated" - // which is somewhat confusing. - self.suggest_restricting_param_bound( - &mut err, - &trait_ref, - obligation.cause.body_id, - ); - } else { - if !have_alt_message { - // Can't show anything else useful, try to find similar impls. - let impl_candidates = self.find_similar_impl_candidates(trait_ref); - self.report_similar_impl_candidates(impl_candidates, &mut err); - } - self.suggest_change_mut( - &obligation, - &mut err, - &trait_ref, - points_at_arg, - ); - } - - // If this error is due to `!: Trait` not implemented but `(): Trait` is - // implemented, and fallback has occurred, then it could be due to a - // variable that used to fallback to `()` now falling back to `!`. Issue a - // note informing about the change in behaviour. - if trait_predicate.skip_binder().self_ty().is_never() - && fallback_has_occurred - { - let predicate = trait_predicate.map_bound(|mut trait_pred| { - trait_pred.trait_ref.substs = self.tcx.mk_substs_trait( - self.tcx.mk_unit(), - &trait_pred.trait_ref.substs[1..], - ); - trait_pred - }); - let unit_obligation = Obligation { - predicate: ty::Predicate::Trait( - predicate, - hir::Constness::NotConst, - ), - ..obligation.clone() - }; - if self.predicate_may_hold(&unit_obligation) { - err.note( - "the trait is implemented for `()`. \ - Possibly this error has been caused by changes to \ - Rust's type-inference algorithm (see issue #48950 \ - \ - for more information). Consider whether you meant to use \ - the type `()` here instead.", - ); - } - } - - err - } - - ty::Predicate::Subtype(ref predicate) => { - // Errors for Subtype predicates show up as - // `FulfillmentErrorCode::CodeSubtypeError`, - // not selection error. - span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate) - } - - ty::Predicate::RegionOutlives(ref predicate) => { - let predicate = self.resolve_vars_if_possible(predicate); - let err = self - .region_outlives_predicate(&obligation.cause, &predicate) - .err() - .unwrap(); - struct_span_err!( - self.tcx.sess, - span, - E0279, - "the requirement `{}` is not satisfied (`{}`)", - predicate, - err, - ) - } - - ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => { - let predicate = self.resolve_vars_if_possible(&obligation.predicate); - struct_span_err!( - self.tcx.sess, - span, - E0280, - "the requirement `{}` is not satisfied", - predicate - ) - } - - ty::Predicate::ObjectSafe(trait_def_id) => { - let violations = self.tcx.object_safety_violations(trait_def_id); - report_object_safety_error(self.tcx, span, trait_def_id, violations) - } - - ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => { - let found_kind = self.closure_kind(closure_def_id, closure_substs).unwrap(); - let closure_span = self - .tcx - .sess - .source_map() - .def_span(self.tcx.hir().span_if_local(closure_def_id).unwrap()); - let hir_id = self.tcx.hir().as_local_hir_id(closure_def_id).unwrap(); - let mut err = struct_span_err!( - self.tcx.sess, - closure_span, - E0525, - "expected a closure that implements the `{}` trait, \ - but this closure only implements `{}`", - kind, - found_kind - ); - - err.span_label( - closure_span, - format!("this closure implements `{}`, not `{}`", found_kind, kind), - ); - err.span_label( - obligation.cause.span, - format!("the requirement to implement `{}` derives from here", kind), - ); - - // Additional context information explaining why the closure only implements - // a particular trait. - if let Some(tables) = self.in_progress_tables { - let tables = tables.borrow(); - match (found_kind, tables.closure_kind_origins().get(hir_id)) { - (ty::ClosureKind::FnOnce, Some((span, name))) => { - err.span_label( - *span, - format!( - "closure is `FnOnce` because it moves the \ - variable `{}` out of its environment", - name - ), - ); - } - (ty::ClosureKind::FnMut, Some((span, name))) => { - err.span_label( - *span, - format!( - "closure is `FnMut` because it mutates the \ - variable `{}` here", - name - ), - ); - } - _ => {} - } - } - - err.emit(); - return; - } - - ty::Predicate::WellFormed(ty) => { - // WF predicates cannot themselves make - // errors. They can only block due to - // ambiguity; otherwise, they always - // degenerate into other obligations - // (which may fail). - span_bug!(span, "WF predicate not satisfied for {:?}", ty); - } - - ty::Predicate::ConstEvaluatable(..) => { - // Errors for `ConstEvaluatable` predicates show up as - // `SelectionError::ConstEvalFailure`, - // not `Unimplemented`. - span_bug!( - span, - "const-evaluatable requirement gave wrong error: `{:?}`", - obligation - ) - } - } - } - - OutputTypeParameterMismatch(ref found_trait_ref, ref expected_trait_ref, _) => { - let found_trait_ref = self.resolve_vars_if_possible(&*found_trait_ref); - let expected_trait_ref = self.resolve_vars_if_possible(&*expected_trait_ref); - - if expected_trait_ref.self_ty().references_error() { - return; - } - - let found_trait_ty = found_trait_ref.self_ty(); - - let found_did = match found_trait_ty.kind { - ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did), - ty::Adt(def, _) => Some(def.did), - _ => None, - }; - - let found_span = found_did - .and_then(|did| self.tcx.hir().span_if_local(did)) - .map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def - - if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) { - // We check closures twice, with obligations flowing in different directions, - // but we want to complain about them only once. - return; - } - - self.reported_closure_mismatch.borrow_mut().insert((span, found_span)); - - let found = match found_trait_ref.skip_binder().substs.type_at(1).kind { - ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()], - _ => vec![ArgKind::empty()], - }; - - let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1); - let expected = match expected_ty.kind { - ty::Tuple(ref tys) => tys - .iter() - .map(|t| ArgKind::from_expected_ty(t.expect_ty(), Some(span))) - .collect(), - _ => vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())], - }; - - if found.len() == expected.len() { - self.report_closure_arg_mismatch( - span, - found_span, - found_trait_ref, - expected_trait_ref, - ) - } else { - let (closure_span, found) = found_did - .and_then(|did| self.tcx.hir().get_if_local(did)) - .map(|node| { - let (found_span, found) = self.get_fn_like_arguments(node); - (Some(found_span), found) - }) - .unwrap_or((found_span, found)); - - self.report_arg_count_mismatch( - span, - closure_span, - expected, - found, - found_trait_ty.is_closure(), - ) - } - } - - TraitNotObjectSafe(did) => { - let violations = self.tcx.object_safety_violations(did); - report_object_safety_error(self.tcx, span, did, violations) - } - - ConstEvalFailure(ErrorHandled::TooGeneric) => { - // In this instance, we have a const expression containing an unevaluated - // generic parameter. We have no idea whether this expression is valid or - // not (e.g. it might result in an error), but we don't want to just assume - // that it's okay, because that might result in post-monomorphisation time - // errors. The onus is really on the caller to provide values that it can - // prove are well-formed. - let mut err = self - .tcx - .sess - .struct_span_err(span, "constant expression depends on a generic parameter"); - // FIXME(const_generics): we should suggest to the user how they can resolve this - // issue. However, this is currently not actually possible - // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083). - err.note("this may fail depending on what value the parameter takes"); - err - } - - // Already reported in the query. - ConstEvalFailure(ErrorHandled::Reported) => { - self.tcx.sess.delay_span_bug(span, "constant in type had an ignored error"); - return; - } - - Overflow => { - bug!("overflow should be handled before the `report_selection_error` path"); - } - }; - - self.note_obligation_cause(&mut err, obligation); - self.point_at_returns_when_relevant(&mut err, &obligation); - - err.emit(); - } - - /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait - /// with the same path as `trait_ref`, a help message about - /// a probable version mismatch is added to `err` - fn note_version_mismatch( - &self, - err: &mut DiagnosticBuilder<'_>, - trait_ref: &ty::PolyTraitRef<'tcx>, - ) { - let get_trait_impl = |trait_def_id| { - let mut trait_impl = None; - self.tcx.for_each_relevant_impl(trait_def_id, trait_ref.self_ty(), |impl_def_id| { - if trait_impl.is_none() { - trait_impl = Some(impl_def_id); - } - }); - trait_impl - }; - let required_trait_path = self.tcx.def_path_str(trait_ref.def_id()); - let all_traits = self.tcx.all_traits(LOCAL_CRATE); - let traits_with_same_path: std::collections::BTreeSet<_> = all_traits - .iter() - .filter(|trait_def_id| **trait_def_id != trait_ref.def_id()) - .filter(|trait_def_id| self.tcx.def_path_str(**trait_def_id) == required_trait_path) - .collect(); - for trait_with_same_path in traits_with_same_path { - if let Some(impl_def_id) = get_trait_impl(*trait_with_same_path) { - let impl_span = self.tcx.def_span(impl_def_id); - err.span_help(impl_span, "trait impl with same name found"); - let trait_crate = self.tcx.crate_name(trait_with_same_path.krate); - let crate_msg = format!( - "perhaps two different versions of crate `{}` are being used?", - trait_crate - ); - err.note(&crate_msg); - } - } - } - - fn mk_obligation_for_def_id( - &self, - def_id: DefId, - output_ty: Ty<'tcx>, - cause: ObligationCause<'tcx>, - param_env: ty::ParamEnv<'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.without_const().to_predicate()) - } -} - -pub fn recursive_type_with_infinite_size_error( - tcx: TyCtxt<'tcx>, - type_def_id: DefId, -) -> DiagnosticBuilder<'tcx> { - assert!(type_def_id.is_local()); - let span = tcx.hir().span_if_local(type_def_id).unwrap(); - let span = tcx.sess.source_map().def_span(span); - let mut err = struct_span_err!( - tcx.sess, - span, - E0072, - "recursive type `{}` has infinite size", - tcx.def_path_str(type_def_id) - ); - err.span_label(span, "recursive type has infinite size"); - err.help(&format!( - "insert indirection (e.g., a `Box`, `Rc`, or `&`) \ - at some point to make `{}` representable", - tcx.def_path_str(type_def_id) - )); - err } pub fn report_object_safety_error( @@ -1026,7 +46,7 @@ pub fn report_object_safety_error( hir::Node::Item(item) => Some(item.ident.span), _ => None, }); - let span = tcx.sess.source_map().def_span(span); + let span = tcx.sess.source_map().guess_head_span(span); let mut err = struct_span_err!( tcx.sess, span, @@ -1084,560 +104,3 @@ pub fn report_object_safety_error( err } - -impl<'a, 'tcx> InferCtxt<'a, 'tcx> { - fn maybe_report_ambiguity( - &self, - obligation: &PredicateObligation<'tcx>, - body_id: Option, - ) { - // Unable to successfully determine, probably means - // insufficient type information, but could mean - // ambiguous impls. The latter *ought* to be a - // coherence violation, so we don't report it here. - - let predicate = self.resolve_vars_if_possible(&obligation.predicate); - let span = obligation.cause.span; - - debug!( - "maybe_report_ambiguity(predicate={:?}, obligation={:?} body_id={:?}, code={:?})", - predicate, obligation, body_id, obligation.cause.code, - ); - - // Ambiguity errors are often caused as fallout from earlier - // errors. So just ignore them if this infcx is tainted. - if self.is_tainted_by_errors() { - return; - } - - let mut err = match predicate { - 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); - - if predicate.references_error() { - return; - } - // Typically, this ambiguity should only happen if - // there are unresolved type inference variables - // (otherwise it would suggest a coherence - // failure). But given #21974 that is not necessarily - // the case -- we can have multiple where clauses that - // are only distinguished by a region, which results - // in an ambiguity even when all types are fully - // known, since we don't dispatch based on region - // relationships. - - // This is kind of a hack: it frequently happens that some earlier - // error prevents types from being fully inferred, and then we get - // a bunch of uninteresting errors saying something like " doesn't implement Sized". It may even be true that we - // could just skip over all checks where the self-ty is an - // inference variable, but I was afraid that there might be an - // inference variable created, registered as an obligation, and - // then never forced by writeback, and hence by skipping here we'd - // be ignoring the fact that we don't KNOW the type works - // out. Though even that would probably be harmless, given that - // we're only talking about builtin traits, which are known to be - // inhabited. We used to check for `self.tcx.sess.has_errors()` to - // avoid inundating the user with unnecessary errors, but we now - // check upstream for type errors and don't add the obligations to - // begin with in those cases. - if self - .tcx - .lang_items() - .sized_trait() - .map_or(false, |sized_id| sized_id == trait_ref.def_id()) - { - self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0282).emit(); - return; - } - let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0283); - err.note(&format!("cannot resolve `{}`", predicate)); - if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code { - self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id()); - } else if let ( - Ok(ref snippet), - ObligationCauseCode::BindingObligation(ref def_id, _), - ) = - (self.tcx.sess.source_map().span_to_snippet(span), &obligation.cause.code) - { - let generics = self.tcx.generics_of(*def_id); - if !generics.params.is_empty() && !snippet.ends_with('>') { - // FIXME: To avoid spurious suggestions in functions where type arguments - // where already supplied, we check the snippet to make sure it doesn't - // end with a turbofish. Ideally we would have access to a `PathSegment` - // instead. Otherwise we would produce the following output: - // - // error[E0283]: type annotations needed - // --> $DIR/issue-54954.rs:3:24 - // | - // LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>(); - // | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - // | | - // | cannot infer type - // | help: consider specifying the type argument - // | in the function call: - // | `Tt::const_val::<[i8; 123]>::` - // ... - // LL | const fn const_val() -> usize { - // | --------- - required by this bound in `Tt::const_val` - // | - // = note: cannot resolve `_: Tt` - - err.span_suggestion( - span, - &format!( - "consider specifying the type argument{} in the function call", - if generics.params.len() > 1 { "s" } else { "" }, - ), - format!( - "{}::<{}>", - snippet, - generics - .params - .iter() - .map(|p| p.name.to_string()) - .collect::>() - .join(", ") - ), - Applicability::HasPlaceholders, - ); - } - } - err - } - - ty::Predicate::WellFormed(ty) => { - // Same hacky approach as above to avoid deluging user - // with error messages. - if ty.references_error() || self.tcx.sess.has_errors() { - return; - } - self.need_type_info_err(body_id, span, ty, ErrorCode::E0282) - } - - ty::Predicate::Subtype(ref data) => { - if data.references_error() || self.tcx.sess.has_errors() { - // no need to overload user in such cases - return; - } - let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder(); - // both must be type variables, or the other would've been instantiated - assert!(a.is_ty_var() && b.is_ty_var()); - self.need_type_info_err(body_id, span, a, ErrorCode::E0282) - } - ty::Predicate::Projection(ref data) => { - let trait_ref = data.to_poly_trait_ref(self.tcx); - let self_ty = trait_ref.self_ty(); - if predicate.references_error() { - return; - } - let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0284); - err.note(&format!("cannot resolve `{}`", predicate)); - err - } - - _ => { - if self.tcx.sess.has_errors() { - return; - } - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0284, - "type annotations needed: cannot resolve `{}`", - predicate, - ); - err.span_label(span, &format!("cannot resolve `{}`", predicate)); - err - } - }; - self.note_obligation_cause(&mut err, obligation); - err.emit(); - } - - /// Returns `true` if the trait predicate may apply for *some* assignment - /// to the type parameters. - fn predicate_can_apply( - &self, - param_env: ty::ParamEnv<'tcx>, - pred: ty::PolyTraitRef<'tcx>, - ) -> bool { - struct ParamToVarFolder<'a, 'tcx> { - infcx: &'a InferCtxt<'a, 'tcx>, - var_map: FxHashMap, Ty<'tcx>>, - } - - impl<'a, 'tcx> TypeFolder<'tcx> for ParamToVarFolder<'a, 'tcx> { - fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { - self.infcx.tcx - } - - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if let ty::Param(ty::ParamTy { name, .. }) = ty.kind { - let infcx = self.infcx; - self.var_map.entry(ty).or_insert_with(|| { - infcx.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeParameterDefinition(name, None), - span: DUMMY_SP, - }) - }) - } else { - ty.super_fold_with(self) - } - } - } - - self.probe(|_| { - let mut selcx = SelectionContext::new(self); - - let cleaned_pred = - pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() }); - - let cleaned_pred = super::project::normalize( - &mut selcx, - param_env, - ObligationCause::dummy(), - &cleaned_pred, - ) - .value; - - let obligation = Obligation::new( - ObligationCause::dummy(), - param_env, - cleaned_pred.without_const().to_predicate(), - ); - - self.predicate_may_hold(&obligation) - }) - } - - fn note_obligation_cause( - &self, - err: &mut DiagnosticBuilder<'_>, - obligation: &PredicateObligation<'tcx>, - ) { - // First, attempt to add note to this error with an async-await-specific - // message, and fall back to regular note otherwise. - if !self.maybe_note_obligation_cause_for_async_await(err, obligation) { - self.note_obligation_cause_code( - err, - &obligation.predicate, - &obligation.cause.code, - &mut vec![], - ); - self.suggest_unsized_bound_if_applicable(err, obligation); - } - } - - fn suggest_unsized_bound_if_applicable( - &self, - err: &mut DiagnosticBuilder<'_>, - obligation: &PredicateObligation<'tcx>, - ) { - if let ( - ty::Predicate::Trait(pred, _), - ObligationCauseCode::BindingObligation(item_def_id, span), - ) = (&obligation.predicate, &obligation.cause.code) - { - if let (Some(generics), true) = ( - self.tcx.hir().get_if_local(*item_def_id).as_ref().and_then(|n| n.generics()), - Some(pred.def_id()) == self.tcx.lang_items().sized_trait(), - ) { - for param in generics.params { - if param.span == *span - && !param.bounds.iter().any(|bound| { - bound.trait_def_id() == self.tcx.lang_items().sized_trait() - }) - { - let (span, separator) = match param.bounds { - [] => (span.shrink_to_hi(), ":"), - [.., bound] => (bound.span().shrink_to_hi(), " + "), - }; - err.span_suggestion( - span, - "consider relaxing the implicit `Sized` restriction", - format!("{} ?Sized", separator), - Applicability::MachineApplicable, - ); - return; - } - } - } - } - } - - fn is_recursive_obligation( - &self, - obligated_types: &mut Vec<&ty::TyS<'tcx>>, - cause_code: &ObligationCauseCode<'tcx>, - ) -> bool { - if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code { - let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref); - - if obligated_types.iter().any(|ot| ot == &parent_trait_ref.skip_binder().self_ty()) { - return true; - } - } - false - } -} - -/// Summarizes information -#[derive(Clone)] -pub enum ArgKind { - /// An argument of non-tuple type. Parameters are (name, ty) - Arg(String, String), - - /// An argument of tuple type. For a "found" argument, the span is - /// the locationo in the source of the pattern. For a "expected" - /// argument, it will be None. The vector is a list of (name, ty) - /// strings for the components of the tuple. - Tuple(Option, Vec<(String, String)>), -} - -impl ArgKind { - fn empty() -> ArgKind { - ArgKind::Arg("_".to_owned(), "_".to_owned()) - } - - /// Creates an `ArgKind` from the expected type of an - /// argument. It has no name (`_`) and an optional source span. - pub fn from_expected_ty(t: Ty<'_>, span: Option) -> ArgKind { - match t.kind { - ty::Tuple(ref tys) => ArgKind::Tuple( - span, - tys.iter().map(|ty| ("_".to_owned(), ty.to_string())).collect::>(), - ), - _ => ArgKind::Arg("_".to_owned(), t.to_string()), - } - } -} - -/// Suggest restricting a type param with a new bound. -pub fn suggest_constraining_type_param( - tcx: TyCtxt<'_>, - generics: &hir::Generics<'_>, - err: &mut DiagnosticBuilder<'_>, - param_name: &str, - constraint: &str, - source_map: &SourceMap, - span: Span, - def_id: Option, -) -> bool { - const MSG_RESTRICT_BOUND_FURTHER: &str = "consider further restricting this bound with"; - const MSG_RESTRICT_TYPE: &str = "consider restricting this type parameter with"; - const MSG_RESTRICT_TYPE_FURTHER: &str = "consider further restricting this type parameter with"; - - let param = generics.params.iter().find(|p| p.name.ident().as_str() == param_name); - - let param = if let Some(param) = param { - param - } else { - return false; - }; - - if def_id == tcx.lang_items().sized_trait() { - // Type parameters are already `Sized` by default. - err.span_label(param.span, &format!("this type parameter needs to be `{}`", constraint)); - return true; - } - - if param_name.starts_with("impl ") { - // If there's an `impl Trait` used in argument position, suggest - // restricting it: - // - // fn foo(t: impl Foo) { ... } - // -------- - // | - // help: consider further restricting this bound with `+ Bar` - // - // Suggestion for tools in this case is: - // - // fn foo(t: impl Foo) { ... } - // -------- - // | - // replace with: `impl Foo + Bar` - - err.span_help(param.span, &format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint)); - - err.tool_only_span_suggestion( - param.span, - MSG_RESTRICT_BOUND_FURTHER, - format!("{} + {}", param_name, constraint), - Applicability::MachineApplicable, - ); - - return true; - } - - if generics.where_clause.predicates.is_empty() { - if let Some(bounds_span) = param.bounds_span() { - // If user has provided some bounds, suggest restricting them: - // - // fn foo(t: T) { ... } - // --- - // | - // help: consider further restricting this bound with `+ Bar` - // - // Suggestion for tools in this case is: - // - // fn foo(t: T) { ... } - // -- - // | - // replace with: `T: Bar +` - - err.span_help( - bounds_span, - &format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint), - ); - - let span_hi = param.span.with_hi(span.hi()); - let span_with_colon = source_map.span_through_char(span_hi, ':'); - - if span_hi != param.span && span_with_colon != span_hi { - err.tool_only_span_suggestion( - span_with_colon, - MSG_RESTRICT_BOUND_FURTHER, - format!("{}: {} + ", param_name, constraint), - Applicability::MachineApplicable, - ); - } - } else { - // If user hasn't provided any bounds, suggest adding a new one: - // - // fn foo(t: T) { ... } - // - help: consider restricting this type parameter with `T: Foo` - - err.span_help( - param.span, - &format!("{} `{}: {}`", MSG_RESTRICT_TYPE, param_name, constraint), - ); - - err.tool_only_span_suggestion( - param.span, - MSG_RESTRICT_TYPE, - format!("{}: {}", param_name, constraint), - Applicability::MachineApplicable, - ); - } - - true - } else { - // This part is a bit tricky, because using the `where` clause user can - // provide zero, one or many bounds for the same type parameter, so we - // have following cases to consider: - // - // 1) When the type parameter has been provided zero bounds - // - // Message: - // fn foo(x: X, y: Y) where Y: Foo { ... } - // - help: consider restricting this type parameter with `where X: Bar` - // - // Suggestion: - // fn foo(x: X, y: Y) where Y: Foo { ... } - // - insert: `, X: Bar` - // - // - // 2) When the type parameter has been provided one bound - // - // Message: - // fn foo(t: T) where T: Foo { ... } - // ^^^^^^ - // | - // help: consider further restricting this bound with `+ Bar` - // - // Suggestion: - // fn foo(t: T) where T: Foo { ... } - // ^^ - // | - // replace with: `T: Bar +` - // - // - // 3) When the type parameter has been provided many bounds - // - // Message: - // fn foo(t: T) where T: Foo, T: Bar {... } - // - help: consider further restricting this type parameter with `where T: Zar` - // - // Suggestion: - // fn foo(t: T) where T: Foo, T: Bar {... } - // - insert: `, T: Zar` - - let mut param_spans = Vec::new(); - - for predicate in generics.where_clause.predicates { - if let WherePredicate::BoundPredicate(WhereBoundPredicate { - span, bounded_ty, .. - }) = predicate - { - if let TyKind::Path(QPath::Resolved(_, path)) = &bounded_ty.kind { - if let Some(segment) = path.segments.first() { - if segment.ident.to_string() == param_name { - param_spans.push(span); - } - } - } - } - } - - let where_clause_span = - generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(); - - match ¶m_spans[..] { - &[] => { - err.span_help( - param.span, - &format!("{} `where {}: {}`", MSG_RESTRICT_TYPE, param_name, constraint), - ); - - err.tool_only_span_suggestion( - where_clause_span, - MSG_RESTRICT_TYPE, - format!(", {}: {}", param_name, constraint), - Applicability::MachineApplicable, - ); - } - - &[¶m_span] => { - err.span_help( - param_span, - &format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint), - ); - - let span_hi = param_span.with_hi(span.hi()); - let span_with_colon = source_map.span_through_char(span_hi, ':'); - - if span_hi != param_span && span_with_colon != span_hi { - err.tool_only_span_suggestion( - span_with_colon, - MSG_RESTRICT_BOUND_FURTHER, - format!("{}: {} +", param_name, constraint), - Applicability::MachineApplicable, - ); - } - } - - _ => { - err.span_help( - param.span, - &format!( - "{} `where {}: {}`", - MSG_RESTRICT_TYPE_FURTHER, param_name, constraint, - ), - ); - - err.tool_only_span_suggestion( - where_clause_span, - MSG_RESTRICT_BOUND_FURTHER, - format!(", {}: {}", param_name, constraint), - Applicability::MachineApplicable, - ); - } - } - - true - } -} diff --git a/src/librustc_infer/traits/mod.rs b/src/librustc_infer/traits/mod.rs index aa0cfedff9e8b..1c0785497be22 100644 --- a/src/librustc_infer/traits/mod.rs +++ b/src/librustc_infer/traits/mod.rs @@ -1,115 +1,33 @@ -//! Trait Resolution. See the [rustc dev guide] for more information on how this works. +//! Trait Resolution. See the [rustc guide] for more information on how this works. //! -//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html +//! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/resolution.html -#[allow(dead_code)] -pub mod auto_trait; -pub mod codegen; -mod coherence; mod engine; pub mod error_reporting; -mod fulfill; -pub mod misc; -mod object_safety; -mod on_unimplemented; mod project; -pub mod query; -mod select; -mod specialize; mod structural_impls; -mod structural_match; mod util; -pub mod wf; -use crate::infer::outlives::env::OutlivesEnvironment; -use crate::infer::{InferCtxt, SuppressRegionErrors, TyCtxtInferExt}; -use rustc::middle::region; use rustc::ty::error::{ExpectedFound, TypeError}; -use rustc::ty::fold::TypeFoldable; -use rustc::ty::subst::{InternalSubsts, SubstsRef}; -use rustc::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, WithConstness}; -use rustc::util::common::ErrorReported; +use rustc::ty::{self, Ty}; use rustc_hir as hir; -use rustc_hir::def_id::DefId; -use rustc_span::{Span, DUMMY_SP}; - -use std::fmt::Debug; +use rustc_span::Span; pub use self::FulfillmentErrorCode::*; pub use self::ObligationCauseCode::*; pub use self::SelectionError::*; pub use self::Vtable::*; -pub use self::coherence::{add_placeholder_note, orphan_check, overlapping_impls}; -pub use self::coherence::{OrphanCheckErr, OverlapResult}; pub use self::engine::{TraitEngine, TraitEngineExt}; -pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation}; -pub use self::object_safety::astconv_object_safety_violations; -pub use self::object_safety::is_vtable_safe_method; -pub use self::object_safety::MethodViolationCode; -pub use self::object_safety::ObjectSafetyViolation; -pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote}; pub use self::project::MismatchedProjectionTypes; pub use self::project::{ - normalize, normalize_projection_type, normalize_to, poly_project_and_unify_type, -}; -pub use self::project::{Normalized, ProjectionCache, ProjectionCacheSnapshot, Reveal}; -pub use self::select::{EvaluationCache, SelectionCache, SelectionContext}; -pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError}; -pub use self::specialize::find_associated_item; -pub use self::specialize::specialization_graph::FutureCompatOverlapError; -pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind; -pub use self::specialize::{specialization_graph, translate_substs, OverlapError}; -pub use self::structural_match::search_for_structural_match_violation; -pub use self::structural_match::type_marked_structural; -pub use self::structural_match::NonStructuralMatchTy; -pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs}; -pub use self::util::{expand_trait_aliases, TraitAliasExpander}; -pub use self::util::{ - get_vtable_index_of_object_method, impl_is_default, impl_item_is_final, - predicate_for_trait_def, upcast_choices, -}; -pub use self::util::{ - supertrait_def_ids, supertraits, transitive_bounds, SupertraitDefIds, Supertraits, + Normalized, NormalizedTy, ProjectionCache, ProjectionCacheEntry, ProjectionCacheKey, + ProjectionCacheSnapshot, Reveal, }; +crate use self::util::elaborate_predicates; pub use rustc::traits::*; -/// Whether to skip the leak check, as part of a future compatibility warning step. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum SkipLeakCheck { - Yes, - No, -} - -impl SkipLeakCheck { - fn is_yes(self) -> bool { - self == SkipLeakCheck::Yes - } -} - -/// The "default" for skip-leak-check corresponds to the current -/// behavior (do not skip the leak check) -- not the behavior we are -/// transitioning into. -impl Default for SkipLeakCheck { - fn default() -> Self { - SkipLeakCheck::No - } -} - -/// The mode that trait queries run in. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum TraitQueryMode { - // Standard/un-canonicalized queries get accurate - // spans etc. passed in and hence can do reasonable - // error reporting on their own. - Standard, - // Canonicalized queries get dummy spans and hence - // must generally propagate errors to - // pre-canonicalization callsites. - Canonical, -} - /// An `Obligation` represents some trait reference (e.g., `int: Eq`) for /// which the vtable must be found. The process of finding a vtable is /// called "resolving" the `Obligation`. This process consists of @@ -165,418 +83,6 @@ pub enum FulfillmentErrorCode<'tcx> { CodeAmbiguity, } -/// Creates predicate obligations from the generic bounds. -pub fn predicates_for_generics<'tcx>( - cause: ObligationCause<'tcx>, - param_env: ty::ParamEnv<'tcx>, - generic_bounds: &ty::InstantiatedPredicates<'tcx>, -) -> PredicateObligations<'tcx> { - util::predicates_for_generics(cause, 0, param_env, generic_bounds) -} - -/// Determines whether the type `ty` is known to meet `bound` and -/// returns true if so. Returns false if `ty` either does not meet -/// `bound` or is not known to meet bound (note that this is -/// conservative towards *no impl*, which is the opposite of the -/// `evaluate` methods). -pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>( - infcx: &InferCtxt<'a, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - ty: Ty<'tcx>, - def_id: DefId, - span: Span, -) -> bool { - debug!( - "type_known_to_meet_bound_modulo_regions(ty={:?}, bound={:?})", - ty, - infcx.tcx.def_path_str(def_id) - ); - - let trait_ref = ty::TraitRef { def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]) }; - let obligation = Obligation { - param_env, - cause: ObligationCause::misc(span, hir::DUMMY_HIR_ID), - recursion_depth: 0, - predicate: trait_ref.without_const().to_predicate(), - }; - - let result = infcx.predicate_must_hold_modulo_regions(&obligation); - debug!( - "type_known_to_meet_ty={:?} bound={} => {:?}", - ty, - infcx.tcx.def_path_str(def_id), - result - ); - - if result && ty.has_infer_types_or_consts() { - // Because of inference "guessing", selection can sometimes claim - // to succeed while the success requires a guess. To ensure - // this function's result remains infallible, we must confirm - // that guess. While imperfect, I believe this is sound. - - // The handling of regions in this area of the code is terrible, - // see issue #29149. We should be able to improve on this with - // NLL. - let mut fulfill_cx = FulfillmentContext::new_ignoring_regions(); - - // We can use a dummy node-id here because we won't pay any mind - // to region obligations that arise (there shouldn't really be any - // anyhow). - let cause = ObligationCause::misc(span, hir::DUMMY_HIR_ID); - - fulfill_cx.register_bound(infcx, param_env, ty, def_id, cause); - - // Note: we only assume something is `Copy` if we can - // *definitively* show that it implements `Copy`. Otherwise, - // assume it is move; linear is always ok. - match fulfill_cx.select_all_or_error(infcx) { - Ok(()) => { - debug!( - "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} success", - ty, - infcx.tcx.def_path_str(def_id) - ); - true - } - Err(e) => { - debug!( - "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} errors={:?}", - ty, - infcx.tcx.def_path_str(def_id), - e - ); - false - } - } - } else { - result - } -} - -fn do_normalize_predicates<'tcx>( - tcx: TyCtxt<'tcx>, - region_context: DefId, - cause: ObligationCause<'tcx>, - elaborated_env: ty::ParamEnv<'tcx>, - predicates: Vec>, -) -> Result>, ErrorReported> { - debug!( - "do_normalize_predicates(predicates={:?}, region_context={:?}, cause={:?})", - predicates, region_context, cause, - ); - let span = cause.span; - tcx.infer_ctxt().enter(|infcx| { - // FIXME. We should really... do something with these region - // obligations. But this call just continues the older - // behavior (i.e., doesn't cause any new bugs), and it would - // take some further refactoring to actually solve them. In - // particular, we would have to handle implied bounds - // properly, and that code is currently largely confined to - // regionck (though I made some efforts to extract it - // out). -nmatsakis - // - // @arielby: In any case, these obligations are checked - // by wfcheck anyway, so I'm not sure we have to check - // them here too, and we will remove this function when - // we move over to lazy normalization *anyway*. - let fulfill_cx = FulfillmentContext::new_ignoring_regions(); - let predicates = - match fully_normalize(&infcx, fulfill_cx, cause, elaborated_env, &predicates) { - Ok(predicates) => predicates, - Err(errors) => { - infcx.report_fulfillment_errors(&errors, None, false); - return Err(ErrorReported); - } - }; - - debug!("do_normalize_predictes: normalized predicates = {:?}", predicates); - - let region_scope_tree = region::ScopeTree::default(); - - // We can use the `elaborated_env` here; the region code only - // cares about declarations like `'a: 'b`. - let outlives_env = OutlivesEnvironment::new(elaborated_env); - - infcx.resolve_regions_and_report_errors( - region_context, - ®ion_scope_tree, - &outlives_env, - SuppressRegionErrors::default(), - ); - - let predicates = match infcx.fully_resolve(&predicates) { - Ok(predicates) => predicates, - Err(fixup_err) => { - // If we encounter a fixup error, it means that some type - // variable wound up unconstrained. I actually don't know - // if this can happen, and I certainly don't expect it to - // happen often, but if it did happen it probably - // represents a legitimate failure due to some kind of - // unconstrained variable, and it seems better not to ICE, - // all things considered. - tcx.sess.span_err(span, &fixup_err.to_string()); - return Err(ErrorReported); - } - }; - if predicates.has_local_value() { - // FIXME: shouldn't we, you know, actually report an error here? or an ICE? - Err(ErrorReported) - } else { - Ok(predicates) - } - }) -} - -// FIXME: this is gonna need to be removed ... -/// Normalizes the parameter environment, reporting errors if they occur. -pub fn normalize_param_env_or_error<'tcx>( - tcx: TyCtxt<'tcx>, - region_context: DefId, - unnormalized_env: ty::ParamEnv<'tcx>, - cause: ObligationCause<'tcx>, -) -> ty::ParamEnv<'tcx> { - // I'm not wild about reporting errors here; I'd prefer to - // have the errors get reported at a defined place (e.g., - // during typeck). Instead I have all parameter - // environments, in effect, going through this function - // and hence potentially reporting errors. This ensures of - // course that we never forget to normalize (the - // alternative seemed like it would involve a lot of - // manual invocations of this fn -- and then we'd have to - // deal with the errors at each of those sites). - // - // In any case, in practice, typeck constructs all the - // parameter environments once for every fn as it goes, - // and errors will get reported then; so after typeck we - // can be sure that no errors should occur. - - debug!( - "normalize_param_env_or_error(region_context={:?}, unnormalized_env={:?}, cause={:?})", - region_context, unnormalized_env, cause - ); - - let mut predicates: Vec<_> = - util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.to_vec()).collect(); - - debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates); - - let elaborated_env = ty::ParamEnv::new( - tcx.intern_predicates(&predicates), - unnormalized_env.reveal, - unnormalized_env.def_id, - ); - - // HACK: we are trying to normalize the param-env inside *itself*. The problem is that - // normalization expects its param-env to be already normalized, which means we have - // a circularity. - // - // The way we handle this is by normalizing the param-env inside an unnormalized version - // of the param-env, which means that if the param-env contains unnormalized projections, - // we'll have some normalization failures. This is unfortunate. - // - // Lazy normalization would basically handle this by treating just the - // normalizing-a-trait-ref-requires-itself cycles as evaluation failures. - // - // Inferred outlives bounds can create a lot of `TypeOutlives` predicates for associated - // types, so to make the situation less bad, we normalize all the predicates *but* - // the `TypeOutlives` predicates first inside the unnormalized parameter environment, and - // then we normalize the `TypeOutlives` bounds inside the normalized parameter environment. - // - // This works fairly well because trait matching does not actually care about param-env - // TypeOutlives predicates - these are normally used by regionck. - let outlives_predicates: Vec<_> = predicates - .drain_filter(|predicate| match predicate { - ty::Predicate::TypeOutlives(..) => true, - _ => false, - }) - .collect(); - - debug!( - "normalize_param_env_or_error: predicates=(non-outlives={:?}, outlives={:?})", - predicates, outlives_predicates - ); - let non_outlives_predicates = match do_normalize_predicates( - tcx, - region_context, - cause.clone(), - elaborated_env, - predicates, - ) { - Ok(predicates) => predicates, - // An unnormalized env is better than nothing. - Err(ErrorReported) => { - debug!("normalize_param_env_or_error: errored resolving non-outlives predicates"); - return elaborated_env; - } - }; - - debug!("normalize_param_env_or_error: non-outlives predicates={:?}", non_outlives_predicates); - - // Not sure whether it is better to include the unnormalized TypeOutlives predicates - // here. I believe they should not matter, because we are ignoring TypeOutlives param-env - // predicates here anyway. Keeping them here anyway because it seems safer. - let outlives_env: Vec<_> = - non_outlives_predicates.iter().chain(&outlives_predicates).cloned().collect(); - let outlives_env = - ty::ParamEnv::new(tcx.intern_predicates(&outlives_env), unnormalized_env.reveal, None); - let outlives_predicates = match do_normalize_predicates( - tcx, - region_context, - cause, - outlives_env, - outlives_predicates, - ) { - Ok(predicates) => predicates, - // An unnormalized env is better than nothing. - Err(ErrorReported) => { - debug!("normalize_param_env_or_error: errored resolving outlives predicates"); - return elaborated_env; - } - }; - debug!("normalize_param_env_or_error: outlives predicates={:?}", outlives_predicates); - - let mut predicates = non_outlives_predicates; - predicates.extend(outlives_predicates); - debug!("normalize_param_env_or_error: final predicates={:?}", predicates); - ty::ParamEnv::new( - tcx.intern_predicates(&predicates), - unnormalized_env.reveal, - unnormalized_env.def_id, - ) -} - -pub fn fully_normalize<'a, 'tcx, T>( - infcx: &InferCtxt<'a, 'tcx>, - mut fulfill_cx: FulfillmentContext<'tcx>, - cause: ObligationCause<'tcx>, - param_env: ty::ParamEnv<'tcx>, - value: &T, -) -> Result>> -where - T: TypeFoldable<'tcx>, -{ - debug!("fully_normalize_with_fulfillcx(value={:?})", value); - let selcx = &mut SelectionContext::new(infcx); - let Normalized { value: normalized_value, obligations } = - project::normalize(selcx, param_env, cause, value); - debug!( - "fully_normalize: normalized_value={:?} obligations={:?}", - normalized_value, obligations - ); - for obligation in obligations { - fulfill_cx.register_predicate_obligation(selcx.infcx(), obligation); - } - - debug!("fully_normalize: select_all_or_error start"); - fulfill_cx.select_all_or_error(infcx)?; - debug!("fully_normalize: select_all_or_error complete"); - let resolved_value = infcx.resolve_vars_if_possible(&normalized_value); - debug!("fully_normalize: resolved_value={:?}", resolved_value); - Ok(resolved_value) -} - -/// Normalizes the predicates and checks whether they hold in an empty -/// 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. -pub fn normalize_and_test_predicates<'tcx>( - tcx: TyCtxt<'tcx>, - predicates: Vec>, -) -> bool { - 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::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); - for obligation in obligations { - fulfill_cx.register_predicate_obligation(&infcx, obligation); - } - for predicate in predicates { - let obligation = Obligation::new(cause.clone(), param_env, predicate); - fulfill_cx.register_predicate_obligation(&infcx, obligation); - } - - fulfill_cx.select_all_or_error(&infcx).is_ok() - }); - debug!("normalize_and_test_predicates(predicates={:?}) = {:?}", predicates, result); - result -} - -fn substitute_normalize_and_test_predicates<'tcx>( - tcx: TyCtxt<'tcx>, - 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); - - debug!("substitute_normalize_and_test_predicates(key={:?}) = {:?}", key, result); - result -} - -/// Given a trait `trait_ref`, iterates the vtable entries -/// that come from `trait_ref`, including its supertraits. -#[inline] // FIXME(#35870): avoid closures being unexported due to `impl Trait`. -fn vtable_methods<'tcx>( - tcx: TyCtxt<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, -) -> &'tcx [Option<(DefId, SubstsRef<'tcx>)>] { - debug!("vtable_methods({:?})", trait_ref); - - tcx.arena.alloc_from_iter(supertraits(tcx, trait_ref).flat_map(move |trait_ref| { - let trait_methods = tcx - .associated_items(trait_ref.def_id()) - .in_definition_order() - .filter(|item| item.kind == ty::AssocKind::Method); - - // Now list each method's DefId and InternalSubsts (for within its trait). - // If the method can never be called from this object, produce None. - trait_methods.map(move |trait_method| { - debug!("vtable_methods: trait_method={:?}", trait_method); - let def_id = trait_method.def_id; - - // Some methods cannot be called on an object; skip those. - if !is_vtable_safe_method(tcx, trait_ref.def_id(), &trait_method) { - debug!("vtable_methods: not vtable safe"); - return None; - } - - // The method may have some early-bound lifetimes; add regions for those. - let substs = trait_ref.map_bound(|trait_ref| { - InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind { - GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(), - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => { - trait_ref.substs[param.index as usize] - } - }) - }); - - // The trait type may have higher-ranked lifetimes in it; - // erase them if they appear, so that we get the type - // at some particular call site. - let substs = - tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &substs); - - // It's possible that the method relies on where-clauses that - // do not hold for this particular set of type parameters. - // 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); - if !normalize_and_test_predicates(tcx, predicates.predicates) { - debug!("vtable_methods: predicates do not hold"); - return None; - } - - Some((def_id, substs)) - }) - })) -} - impl<'tcx, O> Obligation<'tcx, O> { pub fn new( cause: ObligationCause<'tcx>, @@ -586,7 +92,7 @@ impl<'tcx, O> Obligation<'tcx, O> { Obligation { cause, param_env, recursion_depth: 0, predicate } } - fn with_depth( + pub fn with_depth( cause: ObligationCause<'tcx>, recursion_depth: usize, param_env: ty::ParamEnv<'tcx>, @@ -615,7 +121,7 @@ impl<'tcx, O> Obligation<'tcx, O> { } impl<'tcx> FulfillmentError<'tcx> { - fn new( + pub fn new( obligation: PredicateObligation<'tcx>, code: FulfillmentErrorCode<'tcx>, ) -> FulfillmentError<'tcx> { @@ -624,19 +130,7 @@ impl<'tcx> FulfillmentError<'tcx> { } impl<'tcx> TraitObligation<'tcx> { - fn self_ty(&self) -> ty::Binder> { + pub fn self_ty(&self) -> ty::Binder> { self.predicate.map_bound(|p| p.self_ty()) } } - -pub fn provide(providers: &mut ty::query::Providers<'_>) { - object_safety::provide(providers); - *providers = ty::query::Providers { - specialization_graph_of: specialize::specialization_graph_provider, - specializes: specialize::specializes, - codegen_fulfill_obligation: codegen::codegen_fulfill_obligation, - vtable_methods, - substitute_normalize_and_test_predicates, - ..*providers - }; -} diff --git a/src/librustc_infer/traits/project.rs b/src/librustc_infer/traits/project.rs index 78483cf6577de..06870ccc7dd5e 100644 --- a/src/librustc_infer/traits/project.rs +++ b/src/librustc_infer/traits/project.rs @@ -1,398 +1,18 @@ //! Code for projecting associated types out of trait references. -use super::elaborate_predicates; -use super::specialization_graph; -use super::translate_substs; -use super::util; -use super::Obligation; -use super::ObligationCause; use super::PredicateObligation; -use super::Selection; -use super::SelectionContext; -use super::SelectionError; -use super::{VtableClosureData, VtableFnPointerData, VtableGeneratorData, VtableImplData}; -use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime}; -use rustc::ty::fold::{TypeFoldable, TypeFolder}; -use rustc::ty::subst::{InternalSubsts, Subst}; -use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness}; -use rustc_ast::ast::Ident; +use rustc::ty::fold::TypeFoldable; +use rustc::ty::{self, Ty}; use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap}; -use rustc_hir::def_id::DefId; -use rustc_span::symbol::sym; -use rustc_span::DUMMY_SP; pub use rustc::traits::Reveal; -pub type PolyProjectionObligation<'tcx> = Obligation<'tcx, ty::PolyProjectionPredicate<'tcx>>; - -pub type ProjectionObligation<'tcx> = Obligation<'tcx, ty::ProjectionPredicate<'tcx>>; - -pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::ProjectionTy<'tcx>>; - -/// When attempting to resolve `::Name` ... -#[derive(Debug)] -pub enum ProjectionTyError<'tcx> { - /// ...we found multiple sources of information and couldn't resolve the ambiguity. - TooManyCandidates, - - /// ...an error occurred matching `T : TraitRef` - TraitSelectionError(SelectionError<'tcx>), -} - #[derive(Clone)] pub struct MismatchedProjectionTypes<'tcx> { pub err: ty::error::TypeError<'tcx>, } -#[derive(PartialEq, Eq, Debug)] -enum ProjectionTyCandidate<'tcx> { - // from a where-clause in the env or object type - ParamEnv(ty::PolyProjectionPredicate<'tcx>), - - // from the definition of `Trait` when you have something like <::B as Trait2>::C - TraitDef(ty::PolyProjectionPredicate<'tcx>), - - // from a "impl" (or a "pseudo-impl" returned by select) - Select(Selection<'tcx>), -} - -enum ProjectionTyCandidateSet<'tcx> { - None, - Single(ProjectionTyCandidate<'tcx>), - Ambiguous, - Error(SelectionError<'tcx>), -} - -impl<'tcx> ProjectionTyCandidateSet<'tcx> { - fn mark_ambiguous(&mut self) { - *self = ProjectionTyCandidateSet::Ambiguous; - } - - fn mark_error(&mut self, err: SelectionError<'tcx>) { - *self = ProjectionTyCandidateSet::Error(err); - } - - // Returns true if the push was successful, or false if the candidate - // was discarded -- this could be because of ambiguity, or because - // a higher-priority candidate is already there. - fn push_candidate(&mut self, candidate: ProjectionTyCandidate<'tcx>) -> bool { - use self::ProjectionTyCandidate::*; - use self::ProjectionTyCandidateSet::*; - - // This wacky variable is just used to try and - // make code readable and avoid confusing paths. - // It is assigned a "value" of `()` only on those - // paths in which we wish to convert `*self` to - // ambiguous (and return false, because the candidate - // was not used). On other paths, it is not assigned, - // and hence if those paths *could* reach the code that - // comes after the match, this fn would not compile. - let convert_to_ambiguous; - - match self { - None => { - *self = Single(candidate); - return true; - } - - Single(current) => { - // Duplicates can happen inside ParamEnv. In the case, we - // perform a lazy deduplication. - if current == &candidate { - return false; - } - - // Prefer where-clauses. As in select, if there are multiple - // candidates, we prefer where-clause candidates over impls. This - // may seem a bit surprising, since impls are the source of - // "truth" in some sense, but in fact some of the impls that SEEM - // applicable are not, because of nested obligations. Where - // clauses are the safer choice. See the comment on - // `select::SelectionCandidate` and #21974 for more details. - match (current, candidate) { - (ParamEnv(..), ParamEnv(..)) => convert_to_ambiguous = (), - (ParamEnv(..), _) => return false, - (_, ParamEnv(..)) => unreachable!(), - (_, _) => convert_to_ambiguous = (), - } - } - - Ambiguous | Error(..) => { - return false; - } - } - - // We only ever get here when we moved from a single candidate - // to ambiguous. - let () = convert_to_ambiguous; - *self = Ambiguous; - false - } -} - -/// Evaluates constraints of the form: -/// -/// for<...> ::U == V -/// -/// If successful, this may result in additional obligations. Also returns -/// the projection cache key used to track these additional obligations. -pub fn poly_project_and_unify_type<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &PolyProjectionObligation<'tcx>, -) -> Result>>, MismatchedProjectionTypes<'tcx>> { - debug!("poly_project_and_unify_type(obligation={:?})", obligation); - - let infcx = selcx.infcx(); - infcx.commit_if_ok(|snapshot| { - let (placeholder_predicate, placeholder_map) = - infcx.replace_bound_vars_with_placeholders(&obligation.predicate); - - let placeholder_obligation = obligation.with(placeholder_predicate); - let result = project_and_unify_type(selcx, &placeholder_obligation)?; - infcx - .leak_check(false, &placeholder_map, snapshot) - .map_err(|err| MismatchedProjectionTypes { err })?; - Ok(result) - }) -} - -/// Evaluates constraints of the form: -/// -/// ::U == V -/// -/// If successful, this may result in additional obligations. -fn project_and_unify_type<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionObligation<'tcx>, -) -> Result>>, MismatchedProjectionTypes<'tcx>> { - debug!("project_and_unify_type(obligation={:?})", obligation); - - let mut obligations = vec![]; - let normalized_ty = match opt_normalize_projection_type( - selcx, - obligation.param_env, - obligation.predicate.projection_ty, - obligation.cause.clone(), - obligation.recursion_depth, - &mut obligations, - ) { - Some(n) => n, - None => return Ok(None), - }; - - debug!( - "project_and_unify_type: normalized_ty={:?} obligations={:?}", - normalized_ty, obligations - ); - - let infcx = selcx.infcx(); - match infcx - .at(&obligation.cause, obligation.param_env) - .eq(normalized_ty, obligation.predicate.ty) - { - Ok(InferOk { obligations: inferred_obligations, value: () }) => { - obligations.extend(inferred_obligations); - Ok(Some(obligations)) - } - Err(err) => { - debug!("project_and_unify_type: equating types encountered error {:?}", err); - Err(MismatchedProjectionTypes { err }) - } - } -} - -/// Normalizes any associated type projections in `value`, replacing -/// them with a fully resolved type where possible. The return value -/// combines the normalized result and any additional obligations that -/// were incurred as result. -pub fn normalize<'a, 'b, 'tcx, T>( - selcx: &'a mut SelectionContext<'b, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - cause: ObligationCause<'tcx>, - value: &T, -) -> Normalized<'tcx, T> -where - T: TypeFoldable<'tcx>, -{ - let mut obligations = Vec::new(); - let value = normalize_to(selcx, param_env, cause, value, &mut obligations); - Normalized { value, obligations } -} - -pub fn normalize_to<'a, 'b, 'tcx, T>( - selcx: &'a mut SelectionContext<'b, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - cause: ObligationCause<'tcx>, - value: &T, - obligations: &mut Vec>, -) -> T -where - T: TypeFoldable<'tcx>, -{ - normalize_with_depth_to(selcx, param_env, cause, 0, value, obligations) -} - -/// As `normalize`, but with a custom depth. -pub fn normalize_with_depth<'a, 'b, 'tcx, T>( - selcx: &'a mut SelectionContext<'b, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - cause: ObligationCause<'tcx>, - depth: usize, - value: &T, -) -> Normalized<'tcx, T> -where - T: TypeFoldable<'tcx>, -{ - let mut obligations = Vec::new(); - let value = normalize_with_depth_to(selcx, param_env, cause, depth, value, &mut obligations); - Normalized { value, obligations } -} - -pub fn normalize_with_depth_to<'a, 'b, 'tcx, T>( - selcx: &'a mut SelectionContext<'b, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - cause: ObligationCause<'tcx>, - depth: usize, - value: &T, - obligations: &mut Vec>, -) -> T -where - T: TypeFoldable<'tcx>, -{ - debug!("normalize_with_depth(depth={}, value={:?})", depth, value); - let mut normalizer = AssocTypeNormalizer::new(selcx, param_env, cause, depth, obligations); - let result = normalizer.fold(value); - debug!( - "normalize_with_depth: depth={} result={:?} with {} obligations", - depth, - result, - normalizer.obligations.len() - ); - debug!("normalize_with_depth: depth={} obligations={:?}", depth, normalizer.obligations); - result -} - -struct AssocTypeNormalizer<'a, 'b, 'tcx> { - selcx: &'a mut SelectionContext<'b, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - cause: ObligationCause<'tcx>, - obligations: &'a mut Vec>, - depth: usize, -} - -impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { - fn new( - selcx: &'a mut SelectionContext<'b, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - cause: ObligationCause<'tcx>, - depth: usize, - obligations: &'a mut Vec>, - ) -> AssocTypeNormalizer<'a, 'b, 'tcx> { - AssocTypeNormalizer { selcx, param_env, cause, obligations, depth } - } - - fn fold>(&mut self, value: &T) -> T { - let value = self.selcx.infcx().resolve_vars_if_possible(value); - - if !value.has_projections() { value } else { value.fold_with(self) } - } -} - -impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { - fn tcx<'c>(&'c self) -> TyCtxt<'tcx> { - self.selcx.tcx() - } - - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if !ty.has_projections() { - return ty; - } - // We don't want to normalize associated types that occur inside of region - // binders, because they may contain bound regions, and we can't cope with that. - // - // Example: - // - // for<'a> fn(>::A) - // - // Instead of normalizing `>::A` here, we'll - // normalize it when we instantiate those bound regions (which - // should occur eventually). - - let ty = ty.super_fold_with(self); - match ty.kind { - ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { - // (*) - // Only normalize `impl Trait` after type-checking, usually in codegen. - match self.param_env.reveal { - Reveal::UserFacing => ty, - - Reveal::All => { - let recursion_limit = *self.tcx().sess.recursion_limit.get(); - if self.depth >= recursion_limit { - let obligation = Obligation::with_depth( - self.cause.clone(), - recursion_limit, - self.param_env, - ty, - ); - self.selcx.infcx().report_overflow_error(&obligation, true); - } - - let generic_ty = self.tcx().type_of(def_id); - let concrete_ty = generic_ty.subst(self.tcx(), substs); - self.depth += 1; - let folded_ty = self.fold_ty(concrete_ty); - self.depth -= 1; - folded_ty - } - } - } - - ty::Projection(ref data) if !data.has_escaping_bound_vars() => { - // (*) - - // (*) This is kind of hacky -- we need to be able to - // handle normalization within binders because - // otherwise we wind up a need to normalize when doing - // trait matching (since you can have a trait - // obligation like `for<'a> T::B : Fn(&'a int)`), but - // we can't normalize with bound regions in scope. So - // far now we just ignore binders but only normalize - // if all bound regions are gone (and then we still - // have to renormalize whenever we instantiate a - // binder). It would be better to normalize in a - // binding-aware fashion. - - let normalized_ty = normalize_projection_type( - self.selcx, - self.param_env, - *data, - self.cause.clone(), - self.depth, - &mut self.obligations, - ); - debug!( - "AssocTypeNormalizer: depth={} normalized {:?} to {:?}, \ - now with {} obligations", - self.depth, - ty, - normalized_ty, - self.obligations.len() - ); - normalized_ty - } - - _ => ty, - } - } - - fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - constant.eval(self.selcx.tcx(), self.param_env) - } -} - #[derive(Clone, TypeFoldable)] pub struct Normalized<'tcx, T> { pub value: T, @@ -407,1099 +27,6 @@ impl<'tcx, T> Normalized<'tcx, T> { } } -/// The guts of `normalize`: normalize a specific projection like `::Item`. The result is always a type (and possibly -/// additional obligations). If ambiguity arises, which implies that -/// there are unresolved type variables in the projection, we will -/// substitute a fresh type variable `$X` and generate a new -/// obligation `::Item == $X` for later. -pub fn normalize_projection_type<'a, 'b, 'tcx>( - selcx: &'a mut SelectionContext<'b, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - projection_ty: ty::ProjectionTy<'tcx>, - cause: ObligationCause<'tcx>, - depth: usize, - obligations: &mut Vec>, -) -> Ty<'tcx> { - opt_normalize_projection_type( - selcx, - param_env, - projection_ty, - cause.clone(), - depth, - obligations, - ) - .unwrap_or_else(move || { - // if we bottom out in ambiguity, create a type variable - // and a deferred predicate to resolve this when more type - // information is available. - - let tcx = selcx.infcx().tcx; - let def_id = projection_ty.item_def_id; - let ty_var = selcx.infcx().next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::NormalizeProjectionType, - span: tcx.def_span(def_id), - }); - let projection = ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, ty: ty_var }); - let obligation = - Obligation::with_depth(cause, depth + 1, param_env, projection.to_predicate()); - obligations.push(obligation); - ty_var - }) -} - -/// The guts of `normalize`: normalize a specific projection like `::Item`. The result is always a type (and possibly -/// additional obligations). Returns `None` in the case of ambiguity, -/// which indicates that there are unbound type variables. -/// -/// This function used to return `Option>`, which contains a -/// `Ty<'tcx>` and an obligations vector. But that obligation vector was very -/// often immediately appended to another obligations vector. So now this -/// function takes an obligations vector and appends to it directly, which is -/// slightly uglier but avoids the need for an extra short-lived allocation. -fn opt_normalize_projection_type<'a, 'b, 'tcx>( - selcx: &'a mut SelectionContext<'b, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - projection_ty: ty::ProjectionTy<'tcx>, - cause: ObligationCause<'tcx>, - depth: usize, - obligations: &mut Vec>, -) -> Option> { - let infcx = selcx.infcx(); - - let projection_ty = infcx.resolve_vars_if_possible(&projection_ty); - let cache_key = ProjectionCacheKey { ty: projection_ty }; - - debug!( - "opt_normalize_projection_type(\ - projection_ty={:?}, \ - depth={})", - projection_ty, depth - ); - - // FIXME(#20304) For now, I am caching here, which is good, but it - // means we don't capture the type variables that are created in - // the case of ambiguity. Which means we may create a large stream - // of such variables. OTOH, if we move the caching up a level, we - // would not benefit from caching when proving `T: Trait` - // bounds. It might be the case that we want two distinct caches, - // or else another kind of cache entry. - - let cache_result = infcx.inner.borrow_mut().projection_cache.try_start(cache_key); - match cache_result { - Ok(()) => {} - Err(ProjectionCacheEntry::Ambiguous) => { - // If we found ambiguity the last time, that means we will continue - // to do so until some type in the key changes (and we know it - // hasn't, because we just fully resolved it). - debug!( - "opt_normalize_projection_type: \ - found cache entry: ambiguous" - ); - return None; - } - Err(ProjectionCacheEntry::InProgress) => { - // If while normalized A::B, we are asked to normalize - // A::B, just return A::B itself. This is a conservative - // answer, in the sense that A::B *is* clearly equivalent - // to A::B, though there may be a better value we can - // find. - - // Under lazy normalization, this can arise when - // bootstrapping. That is, imagine an environment with a - // where-clause like `A::B == u32`. Now, if we are asked - // to normalize `A::B`, we will want to check the - // where-clauses in scope. So we will try to unify `A::B` - // with `A::B`, which can trigger a recursive - // normalization. In that case, I think we will want this code: - // - // ``` - // let ty = selcx.tcx().mk_projection(projection_ty.item_def_id, - // projection_ty.substs; - // return Some(NormalizedTy { value: v, obligations: vec![] }); - // ``` - - debug!( - "opt_normalize_projection_type: \ - found cache entry: in-progress" - ); - - // But for now, let's classify this as an overflow: - let recursion_limit = *selcx.tcx().sess.recursion_limit.get(); - let obligation = - Obligation::with_depth(cause, recursion_limit, param_env, projection_ty); - selcx.infcx().report_overflow_error(&obligation, false); - } - Err(ProjectionCacheEntry::NormalizedTy(ty)) => { - // This is the hottest path in this function. - // - // If we find the value in the cache, then return it along - // with the obligations that went along with it. Note - // that, when using a fulfillment context, these - // obligations could in principle be ignored: they have - // already been registered when the cache entry was - // created (and hence the new ones will quickly be - // discarded as duplicated). But when doing trait - // evaluation this is not the case, and dropping the trait - // evaluations can causes ICEs (e.g., #43132). - debug!( - "opt_normalize_projection_type: \ - found normalized ty `{:?}`", - ty - ); - - // Once we have inferred everything we need to know, we - // can ignore the `obligations` from that point on. - if infcx.unresolved_type_vars(&ty.value).is_none() { - infcx.inner.borrow_mut().projection_cache.complete_normalized(cache_key, &ty); - // No need to extend `obligations`. - } else { - obligations.extend(ty.obligations); - } - - obligations.push(get_paranoid_cache_value_obligation( - infcx, - param_env, - projection_ty, - cause, - depth, - )); - return Some(ty.value); - } - Err(ProjectionCacheEntry::Error) => { - debug!( - "opt_normalize_projection_type: \ - found error" - ); - let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth); - obligations.extend(result.obligations); - return Some(result.value); - } - } - - let obligation = Obligation::with_depth(cause.clone(), depth, param_env, projection_ty); - match project_type(selcx, &obligation) { - Ok(ProjectedTy::Progress(Progress { - ty: projected_ty, - obligations: mut projected_obligations, - })) => { - // if projection succeeded, then what we get out of this - // is also non-normalized (consider: it was derived from - // an impl, where-clause etc) and hence we must - // re-normalize it - - debug!( - "opt_normalize_projection_type: \ - projected_ty={:?} \ - depth={} \ - projected_obligations={:?}", - projected_ty, depth, projected_obligations - ); - - let result = if projected_ty.has_projections() { - let mut normalizer = AssocTypeNormalizer::new( - selcx, - param_env, - cause, - depth + 1, - &mut projected_obligations, - ); - let normalized_ty = normalizer.fold(&projected_ty); - - debug!( - "opt_normalize_projection_type: \ - normalized_ty={:?} depth={}", - normalized_ty, depth - ); - - Normalized { value: normalized_ty, obligations: projected_obligations } - } else { - Normalized { value: projected_ty, obligations: projected_obligations } - }; - - let cache_value = prune_cache_value_obligations(infcx, &result); - infcx.inner.borrow_mut().projection_cache.insert_ty(cache_key, cache_value); - obligations.extend(result.obligations); - Some(result.value) - } - Ok(ProjectedTy::NoProgress(projected_ty)) => { - debug!( - "opt_normalize_projection_type: \ - projected_ty={:?} no progress", - projected_ty - ); - let result = Normalized { value: projected_ty, obligations: vec![] }; - infcx.inner.borrow_mut().projection_cache.insert_ty(cache_key, result.clone()); - // No need to extend `obligations`. - Some(result.value) - } - Err(ProjectionTyError::TooManyCandidates) => { - debug!( - "opt_normalize_projection_type: \ - too many candidates" - ); - infcx.inner.borrow_mut().projection_cache.ambiguous(cache_key); - None - } - Err(ProjectionTyError::TraitSelectionError(_)) => { - debug!("opt_normalize_projection_type: ERROR"); - // if we got an error processing the `T as Trait` part, - // just return `ty::err` but add the obligation `T : - // Trait`, which when processed will cause the error to be - // reported later - - infcx.inner.borrow_mut().projection_cache.error(cache_key); - let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth); - obligations.extend(result.obligations); - Some(result.value) - } - } -} - -/// If there are unresolved type variables, then we need to include -/// any subobligations that bind them, at least until those type -/// variables are fully resolved. -fn prune_cache_value_obligations<'a, 'tcx>( - infcx: &'a InferCtxt<'a, 'tcx>, - result: &NormalizedTy<'tcx>, -) -> NormalizedTy<'tcx> { - if infcx.unresolved_type_vars(&result.value).is_none() { - return NormalizedTy { value: result.value, obligations: vec![] }; - } - - let mut obligations: Vec<_> = result - .obligations - .iter() - .filter(|obligation| match obligation.predicate { - // We found a `T: Foo` predicate, let's check - // if `U` references any unresolved type - // variables. In principle, we only care if this - // projection can help resolve any of the type - // variables found in `result.value` -- but we just - // check for any type variables here, for fear of - // indirect obligations (e.g., we project to `?0`, - // but we have `T: Foo` and `?1: Bar`). - ty::Predicate::Projection(ref data) => infcx.unresolved_type_vars(&data.ty()).is_some(), - - // We are only interested in `T: Foo` predicates, whre - // `U` references one of `unresolved_type_vars`. =) - _ => false, - }) - .cloned() - .collect(); - - obligations.shrink_to_fit(); - - NormalizedTy { value: result.value, obligations } -} - -/// Whenever we give back a cache result for a projection like `::Item ==> X`, we *always* include the obligation to prove -/// that `T: Trait` (we may also include some other obligations). This -/// may or may not be necessary -- in principle, all the obligations -/// that must be proven to show that `T: Trait` were also returned -/// when the cache was first populated. But there are some vague concerns, -/// and so we take the precautionary measure of including `T: Trait` in -/// the result: -/// -/// Concern #1. The current setup is fragile. Perhaps someone could -/// have failed to prove the concerns from when the cache was -/// populated, but also not have used a snapshot, in which case the -/// cache could remain populated even though `T: Trait` has not been -/// shown. In this case, the "other code" is at fault -- when you -/// project something, you are supposed to either have a snapshot or -/// else prove all the resulting obligations -- but it's still easy to -/// get wrong. -/// -/// Concern #2. Even within the snapshot, if those original -/// obligations are not yet proven, then we are able to do projections -/// that may yet turn out to be wrong. This *may* lead to some sort -/// of trouble, though we don't have a concrete example of how that -/// can occur yet. But it seems risky at best. -fn get_paranoid_cache_value_obligation<'a, 'tcx>( - infcx: &'a InferCtxt<'a, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - projection_ty: ty::ProjectionTy<'tcx>, - cause: ObligationCause<'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.without_const().to_predicate(), - } -} - -/// If we are projecting `::Item`, but `T: Trait` does not -/// hold. In various error cases, we cannot generate a valid -/// normalized projection. Therefore, we create an inference variable -/// return an associated obligation that, when fulfilled, will lead to -/// an error. -/// -/// Note that we used to return `Error` here, but that was quite -/// dubious -- the premise was that an error would *eventually* be -/// reported, when the obligation was processed. But in general once -/// you see a `Error` you are supposed to be able to assume that an -/// error *has been* reported, so that you can take whatever heuristic -/// paths you want to take. To make things worse, it was possible for -/// cycles to arise, where you basically had a setup like ` -/// as Trait>::Foo == $0`. Here, normalizing ` as -/// Trait>::Foo> to `[type error]` would lead to an obligation of -/// ` as Trait>::Foo`. We are supposed to report -/// an error for this obligation, but we legitimately should not, -/// because it contains `[type error]`. Yuck! (See issue #29857 for -/// one case where this arose.) -fn normalize_to_error<'a, 'tcx>( - selcx: &mut SelectionContext<'a, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - projection_ty: ty::ProjectionTy<'tcx>, - cause: ObligationCause<'tcx>, - depth: usize, -) -> NormalizedTy<'tcx> { - let trait_ref = projection_ty.trait_ref(selcx.tcx()).to_poly_trait_ref(); - let trait_obligation = Obligation { - cause, - recursion_depth: depth, - param_env, - predicate: trait_ref.without_const().to_predicate(), - }; - let tcx = selcx.infcx().tcx; - let def_id = projection_ty.item_def_id; - let new_value = selcx.infcx().next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::NormalizeProjectionType, - span: tcx.def_span(def_id), - }); - Normalized { value: new_value, obligations: vec![trait_obligation] } -} - -enum ProjectedTy<'tcx> { - Progress(Progress<'tcx>), - NoProgress(Ty<'tcx>), -} - -struct Progress<'tcx> { - ty: Ty<'tcx>, - obligations: Vec>, -} - -impl<'tcx> Progress<'tcx> { - fn error(tcx: TyCtxt<'tcx>) -> Self { - Progress { ty: tcx.types.err, obligations: vec![] } - } - - fn with_addl_obligations(mut self, mut obligations: Vec>) -> Self { - debug!( - "with_addl_obligations: self.obligations.len={} obligations.len={}", - self.obligations.len(), - obligations.len() - ); - - debug!( - "with_addl_obligations: self.obligations={:?} obligations={:?}", - self.obligations, obligations - ); - - self.obligations.append(&mut obligations); - self - } -} - -/// Computes the result of a projection type (if we can). -/// -/// IMPORTANT: -/// - `obligation` must be fully normalized -fn project_type<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, -) -> Result, ProjectionTyError<'tcx>> { - debug!("project(obligation={:?})", obligation); - - let recursion_limit = *selcx.tcx().sess.recursion_limit.get(); - if obligation.recursion_depth >= recursion_limit { - debug!("project: overflow!"); - return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow)); - } - - let obligation_trait_ref = &obligation.predicate.trait_ref(selcx.tcx()); - - debug!("project: obligation_trait_ref={:?}", obligation_trait_ref); - - if obligation_trait_ref.references_error() { - return Ok(ProjectedTy::Progress(Progress::error(selcx.tcx()))); - } - - let mut candidates = ProjectionTyCandidateSet::None; - - // Make sure that the following procedures are kept in order. ParamEnv - // needs to be first because it has highest priority, and Select checks - // the return value of push_candidate which assumes it's ran at last. - assemble_candidates_from_param_env(selcx, obligation, &obligation_trait_ref, &mut candidates); - - assemble_candidates_from_trait_def(selcx, obligation, &obligation_trait_ref, &mut candidates); - - assemble_candidates_from_impls(selcx, obligation, &obligation_trait_ref, &mut candidates); - - match candidates { - ProjectionTyCandidateSet::Single(candidate) => Ok(ProjectedTy::Progress( - confirm_candidate(selcx, obligation, &obligation_trait_ref, candidate), - )), - ProjectionTyCandidateSet::None => Ok(ProjectedTy::NoProgress( - selcx - .tcx() - .mk_projection(obligation.predicate.item_def_id, obligation.predicate.substs), - )), - // Error occurred while trying to processing impls. - ProjectionTyCandidateSet::Error(e) => Err(ProjectionTyError::TraitSelectionError(e)), - // Inherent ambiguity that prevents us from even enumerating the - // candidates. - ProjectionTyCandidateSet::Ambiguous => Err(ProjectionTyError::TooManyCandidates), - } -} - -/// The first thing we have to do is scan through the parameter -/// environment to see whether there are any projection predicates -/// there that can answer this question. -fn assemble_candidates_from_param_env<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, - obligation_trait_ref: &ty::TraitRef<'tcx>, - candidate_set: &mut ProjectionTyCandidateSet<'tcx>, -) { - debug!("assemble_candidates_from_param_env(..)"); - assemble_candidates_from_predicates( - selcx, - obligation, - obligation_trait_ref, - candidate_set, - ProjectionTyCandidate::ParamEnv, - obligation.param_env.caller_bounds.iter().cloned(), - ); -} - -/// In the case of a nested projection like <::FooT as Bar>::BarT, we may find -/// that the definition of `Foo` has some clues: -/// -/// ``` -/// trait Foo { -/// type FooT : Bar -/// } -/// ``` -/// -/// Here, for example, we could conclude that the result is `i32`. -fn assemble_candidates_from_trait_def<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, - obligation_trait_ref: &ty::TraitRef<'tcx>, - candidate_set: &mut ProjectionTyCandidateSet<'tcx>, -) { - debug!("assemble_candidates_from_trait_def(..)"); - - let tcx = selcx.tcx(); - // Check whether the self-type is itself a projection. - let (def_id, substs) = match obligation_trait_ref.self_ty().kind { - ty::Projection(ref data) => (data.trait_ref(tcx).def_id, data.substs), - ty::Opaque(def_id, substs) => (def_id, substs), - ty::Infer(ty::TyVar(_)) => { - // If the self-type is an inference variable, then it MAY wind up - // being a projected type, so induce an ambiguity. - candidate_set.mark_ambiguous(); - return; - } - _ => return, - }; - - // If so, extract what we know from the trait and try to come up with a good answer. - let trait_predicates = tcx.predicates_of(def_id); - let bounds = trait_predicates.instantiate(tcx, substs); - let bounds = elaborate_predicates(tcx, bounds.predicates); - assemble_candidates_from_predicates( - selcx, - obligation, - obligation_trait_ref, - candidate_set, - ProjectionTyCandidate::TraitDef, - bounds, - ) -} - -fn assemble_candidates_from_predicates<'cx, 'tcx, I>( - selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, - obligation_trait_ref: &ty::TraitRef<'tcx>, - candidate_set: &mut ProjectionTyCandidateSet<'tcx>, - ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionTyCandidate<'tcx>, - env_predicates: I, -) where - I: IntoIterator>, -{ - debug!("assemble_candidates_from_predicates(obligation={:?})", obligation); - let infcx = selcx.infcx(); - for predicate in env_predicates { - debug!("assemble_candidates_from_predicates: predicate={:?}", predicate); - if let ty::Predicate::Projection(data) = predicate { - let same_def_id = data.projection_def_id() == obligation.predicate.item_def_id; - - let is_match = same_def_id - && infcx.probe(|_| { - let data_poly_trait_ref = data.to_poly_trait_ref(infcx.tcx); - let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref(); - infcx - .at(&obligation.cause, obligation.param_env) - .sup(obligation_poly_trait_ref, data_poly_trait_ref) - .map(|InferOk { obligations: _, value: () }| { - // FIXME(#32730) -- do we need to take obligations - // into account in any way? At the moment, no. - }) - .is_ok() - }); - - debug!( - "assemble_candidates_from_predicates: candidate={:?} \ - is_match={} same_def_id={}", - data, is_match, same_def_id - ); - - if is_match { - candidate_set.push_candidate(ctor(data)); - } - } - } -} - -fn assemble_candidates_from_impls<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, - obligation_trait_ref: &ty::TraitRef<'tcx>, - candidate_set: &mut ProjectionTyCandidateSet<'tcx>, -) { - // If we are resolving `>::Item == Type`, - // start out by selecting the predicate `T as TraitRef<...>`: - let poly_trait_ref = obligation_trait_ref.to_poly_trait_ref(); - let trait_obligation = obligation.with(poly_trait_ref.to_poly_trait_predicate()); - let _ = selcx.infcx().commit_if_ok(|_| { - let vtable = match selcx.select(&trait_obligation) { - Ok(Some(vtable)) => vtable, - Ok(None) => { - candidate_set.mark_ambiguous(); - return Err(()); - } - Err(e) => { - debug!("assemble_candidates_from_impls: selection error {:?}", e); - candidate_set.mark_error(e); - return Err(()); - } - }; - - let eligible = match &vtable { - super::VtableClosure(_) - | super::VtableGenerator(_) - | super::VtableFnPointer(_) - | super::VtableObject(_) - | super::VtableTraitAlias(_) => { - debug!("assemble_candidates_from_impls: vtable={:?}", vtable); - true - } - super::VtableImpl(impl_data) => { - // We have to be careful when projecting out of an - // impl because of specialization. If we are not in - // codegen (i.e., projection mode is not "any"), and the - // impl's type is declared as default, then we disable - // projection (even if the trait ref is fully - // monomorphic). In the case where trait ref is not - // fully monomorphic (i.e., includes type parameters), - // this is because those type parameters may - // ultimately be bound to types from other crates that - // may have specialized impls we can't see. In the - // case where the trait ref IS fully monomorphic, this - // is a policy decision that we made in the RFC in - // order to preserve flexibility for the crate that - // defined the specializable impl to specialize later - // for existing types. - // - // In either case, we handle this by not adding a - // candidate for an impl if it contains a `default` - // type. - // - // NOTE: This should be kept in sync with the similar code in - // `rustc::ty::instance::resolve_associated_item()`. - let node_item = - assoc_ty_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id); - - let is_default = if node_item.node.is_from_trait() { - // If true, the impl inherited a `type Foo = Bar` - // given in the trait, which is implicitly default. - // Otherwise, the impl did not specify `type` and - // neither did the trait: - // - // ```rust - // trait Foo { type T; } - // impl Foo for Bar { } - // ``` - // - // This is an error, but it will be - // reported in `check_impl_items_against_trait`. - // We accept it here but will flag it as - // an error when we confirm the candidate - // (which will ultimately lead to `normalize_to_error` - // being invoked). - false - } else { - // If we're looking at a trait *impl*, the item is - // specializable if the impl or the item are marked - // `default`. - node_item.item.defaultness.is_default() - || super::util::impl_is_default(selcx.tcx(), node_item.node.def_id()) - }; - - match is_default { - // Non-specializable items are always projectable - false => true, - - // Only reveal a specializable default if we're past type-checking - // and the obligation is monomorphic, otherwise passes such as - // transmute checking and polymorphic MIR optimizations could - // get a result which isn't correct for all monomorphizations. - true if obligation.param_env.reveal == Reveal::All => { - // NOTE(eddyb) inference variables can resolve to parameters, so - // assume `poly_trait_ref` isn't monomorphic, if it contains any. - let poly_trait_ref = - selcx.infcx().resolve_vars_if_possible(&poly_trait_ref); - !poly_trait_ref.needs_infer() && !poly_trait_ref.needs_subst() - } - - true => { - debug!( - "assemble_candidates_from_impls: not eligible due to default: \ - assoc_ty={} predicate={}", - selcx.tcx().def_path_str(node_item.item.def_id), - obligation.predicate, - ); - false - } - } - } - super::VtableParam(..) => { - // This case tell us nothing about the value of an - // associated type. Consider: - // - // ``` - // trait SomeTrait { type Foo; } - // fn foo(...) { } - // ``` - // - // If the user writes `::Foo`, then the `T - // : SomeTrait` binding does not help us decide what the - // type `Foo` is (at least, not more specifically than - // what we already knew). - // - // But wait, you say! What about an example like this: - // - // ``` - // fn bar>(...) { ... } - // ``` - // - // Doesn't the `T : Sometrait` predicate help - // resolve `T::Foo`? And of course it does, but in fact - // that single predicate is desugared into two predicates - // in the compiler: a trait predicate (`T : SomeTrait`) and a - // projection. And the projection where clause is handled - // in `assemble_candidates_from_param_env`. - false - } - super::VtableAutoImpl(..) | super::VtableBuiltin(..) => { - // These traits have no associated types. - span_bug!( - obligation.cause.span, - "Cannot project an associated type from `{:?}`", - vtable - ); - } - }; - - if eligible { - if candidate_set.push_candidate(ProjectionTyCandidate::Select(vtable)) { - Ok(()) - } else { - Err(()) - } - } else { - Err(()) - } - }); -} - -fn confirm_candidate<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, - obligation_trait_ref: &ty::TraitRef<'tcx>, - candidate: ProjectionTyCandidate<'tcx>, -) -> Progress<'tcx> { - debug!("confirm_candidate(candidate={:?}, obligation={:?})", candidate, obligation); - - match candidate { - ProjectionTyCandidate::ParamEnv(poly_projection) - | ProjectionTyCandidate::TraitDef(poly_projection) => { - confirm_param_env_candidate(selcx, obligation, poly_projection) - } - - ProjectionTyCandidate::Select(vtable) => { - confirm_select_candidate(selcx, obligation, obligation_trait_ref, vtable) - } - } -} - -fn confirm_select_candidate<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, - obligation_trait_ref: &ty::TraitRef<'tcx>, - vtable: Selection<'tcx>, -) -> Progress<'tcx> { - match vtable { - super::VtableImpl(data) => confirm_impl_candidate(selcx, obligation, data), - super::VtableGenerator(data) => confirm_generator_candidate(selcx, obligation, data), - super::VtableClosure(data) => confirm_closure_candidate(selcx, obligation, data), - super::VtableFnPointer(data) => confirm_fn_pointer_candidate(selcx, obligation, data), - super::VtableObject(_) => confirm_object_candidate(selcx, obligation, obligation_trait_ref), - super::VtableAutoImpl(..) - | super::VtableParam(..) - | super::VtableBuiltin(..) - | super::VtableTraitAlias(..) => - // we don't create Select candidates with this kind of resolution - { - span_bug!( - obligation.cause.span, - "Cannot project an associated type from `{:?}`", - vtable - ) - } - } -} - -fn confirm_object_candidate<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, - obligation_trait_ref: &ty::TraitRef<'tcx>, -) -> Progress<'tcx> { - let self_ty = obligation_trait_ref.self_ty(); - let object_ty = selcx.infcx().shallow_resolve(self_ty); - debug!("confirm_object_candidate(object_ty={:?})", object_ty); - let data = match object_ty.kind { - ty::Dynamic(ref data, ..) => data, - _ => span_bug!( - obligation.cause.span, - "confirm_object_candidate called with non-object: {:?}", - object_ty - ), - }; - let env_predicates = data - .projection_bounds() - .map(|p| p.with_self_ty(selcx.tcx(), object_ty).to_predicate()) - .collect(); - let env_predicate = { - let env_predicates = elaborate_predicates(selcx.tcx(), env_predicates); - - // select only those projections that are actually projecting an - // item with the correct name - let env_predicates = env_predicates.filter_map(|p| match p { - ty::Predicate::Projection(data) => { - if data.projection_def_id() == obligation.predicate.item_def_id { - Some(data) - } else { - None - } - } - _ => None, - }); - - // select those with a relevant trait-ref - let mut env_predicates = env_predicates.filter(|data| { - let data_poly_trait_ref = data.to_poly_trait_ref(selcx.tcx()); - let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref(); - selcx.infcx().probe(|_| { - selcx - .infcx() - .at(&obligation.cause, obligation.param_env) - .sup(obligation_poly_trait_ref, data_poly_trait_ref) - .is_ok() - }) - }); - - // select the first matching one; there really ought to be one or - // else the object type is not WF, since an object type should - // include all of its projections explicitly - match env_predicates.next() { - Some(env_predicate) => env_predicate, - None => { - debug!( - "confirm_object_candidate: no env-predicate \ - found in object type `{:?}`; ill-formed", - object_ty - ); - return Progress::error(selcx.tcx()); - } - } - }; - - confirm_param_env_candidate(selcx, obligation, env_predicate) -} - -fn confirm_generator_candidate<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, - vtable: VtableGeneratorData<'tcx, PredicateObligation<'tcx>>, -) -> Progress<'tcx> { - let gen_sig = vtable.substs.as_generator().poly_sig(vtable.generator_def_id, selcx.tcx()); - let Normalized { value: gen_sig, obligations } = normalize_with_depth( - selcx, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - &gen_sig, - ); - - debug!( - "confirm_generator_candidate: obligation={:?},gen_sig={:?},obligations={:?}", - obligation, gen_sig, obligations - ); - - let tcx = selcx.tcx(); - - let gen_def_id = tcx.lang_items().gen_trait().unwrap(); - - let predicate = super::util::generator_trait_ref_and_outputs( - tcx, - gen_def_id, - obligation.predicate.self_ty(), - gen_sig, - ) - .map_bound(|(trait_ref, yield_ty, return_ty)| { - let name = tcx.associated_item(obligation.predicate.item_def_id).ident.name; - let ty = if name == sym::Return { - return_ty - } else if name == sym::Yield { - yield_ty - } else { - bug!() - }; - - ty::ProjectionPredicate { - projection_ty: ty::ProjectionTy { - substs: trait_ref.substs, - item_def_id: obligation.predicate.item_def_id, - }, - ty, - } - }); - - confirm_param_env_candidate(selcx, obligation, predicate) - .with_addl_obligations(vtable.nested) - .with_addl_obligations(obligations) -} - -fn confirm_fn_pointer_candidate<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, - fn_pointer_vtable: VtableFnPointerData<'tcx, PredicateObligation<'tcx>>, -) -> Progress<'tcx> { - let fn_type = selcx.infcx().shallow_resolve(fn_pointer_vtable.fn_ty); - let sig = fn_type.fn_sig(selcx.tcx()); - let Normalized { value: sig, obligations } = normalize_with_depth( - selcx, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - &sig, - ); - - confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes) - .with_addl_obligations(fn_pointer_vtable.nested) - .with_addl_obligations(obligations) -} - -fn confirm_closure_candidate<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, - vtable: VtableClosureData<'tcx, PredicateObligation<'tcx>>, -) -> Progress<'tcx> { - let tcx = selcx.tcx(); - let infcx = selcx.infcx(); - let closure_sig_ty = vtable.substs.as_closure().sig_ty(vtable.closure_def_id, tcx); - let closure_sig = infcx.shallow_resolve(closure_sig_ty).fn_sig(tcx); - let Normalized { value: closure_sig, obligations } = normalize_with_depth( - selcx, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - &closure_sig, - ); - - debug!( - "confirm_closure_candidate: obligation={:?},closure_sig={:?},obligations={:?}", - obligation, closure_sig, obligations - ); - - confirm_callable_candidate(selcx, obligation, closure_sig, util::TupleArgumentsFlag::No) - .with_addl_obligations(vtable.nested) - .with_addl_obligations(obligations) -} - -fn confirm_callable_candidate<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, - fn_sig: ty::PolyFnSig<'tcx>, - flag: util::TupleArgumentsFlag, -) -> Progress<'tcx> { - let tcx = selcx.tcx(); - - debug!("confirm_callable_candidate({:?},{:?})", obligation, fn_sig); - - // the `Output` associated type is declared on `FnOnce` - let fn_once_def_id = tcx.lang_items().fn_once_trait().unwrap(); - - let predicate = super::util::closure_trait_ref_and_return_type( - tcx, - fn_once_def_id, - obligation.predicate.self_ty(), - fn_sig, - flag, - ) - .map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate { - projection_ty: ty::ProjectionTy::from_ref_and_name( - tcx, - trait_ref, - Ident::with_dummy_span(rustc_hir::FN_OUTPUT_NAME), - ), - ty: ret_type, - }); - - confirm_param_env_candidate(selcx, obligation, predicate) -} - -fn confirm_param_env_candidate<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, - poly_cache_entry: ty::PolyProjectionPredicate<'tcx>, -) -> Progress<'tcx> { - let infcx = selcx.infcx(); - let cause = &obligation.cause; - let param_env = obligation.param_env; - - let (cache_entry, _) = infcx.replace_bound_vars_with_fresh_vars( - cause.span, - LateBoundRegionConversionTime::HigherRankedType, - &poly_cache_entry, - ); - - let cache_trait_ref = cache_entry.projection_ty.trait_ref(infcx.tcx); - let obligation_trait_ref = obligation.predicate.trait_ref(infcx.tcx); - match infcx.at(cause, param_env).eq(cache_trait_ref, obligation_trait_ref) { - Ok(InferOk { value: _, obligations }) => Progress { ty: cache_entry.ty, obligations }, - Err(e) => { - let msg = format!( - "Failed to unify obligation `{:?}` with poly_projection `{:?}`: {:?}", - obligation, poly_cache_entry, e, - ); - debug!("confirm_param_env_candidate: {}", msg); - infcx.tcx.sess.delay_span_bug(obligation.cause.span, &msg); - Progress { ty: infcx.tcx.types.err, obligations: vec![] } - } - } -} - -fn confirm_impl_candidate<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, - impl_vtable: VtableImplData<'tcx, PredicateObligation<'tcx>>, -) -> Progress<'tcx> { - let tcx = selcx.tcx(); - - let VtableImplData { impl_def_id, substs, nested } = impl_vtable; - let assoc_item_id = obligation.predicate.item_def_id; - let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap(); - - let param_env = obligation.param_env; - let assoc_ty = assoc_ty_def(selcx, impl_def_id, assoc_item_id); - - if !assoc_ty.item.defaultness.has_value() { - // This means that the impl is missing a definition for the - // associated type. This error will be reported by the type - // checker method `check_impl_items_against_trait`, so here we - // just return Error. - debug!( - "confirm_impl_candidate: no associated type {:?} for {:?}", - assoc_ty.item.ident, obligation.predicate - ); - return Progress { ty: tcx.types.err, obligations: nested }; - } - let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs); - let substs = translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.node); - let ty = if let ty::AssocKind::OpaqueTy = assoc_ty.item.kind { - let item_substs = InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id); - tcx.mk_opaque(assoc_ty.item.def_id, item_substs) - } else { - tcx.type_of(assoc_ty.item.def_id) - }; - if substs.len() != tcx.generics_of(assoc_ty.item.def_id).count() { - tcx.sess - .delay_span_bug(DUMMY_SP, "impl item and trait item have different parameter counts"); - Progress { ty: tcx.types.err, obligations: nested } - } else { - Progress { ty: ty.subst(tcx, substs), obligations: nested } - } -} - -/// Locate the definition of an associated type in the specialization hierarchy, -/// starting from the given impl. -/// -/// Based on the "projection mode", this lookup may in fact only examine the -/// topmost impl. See the comments for `Reveal` for more details. -fn assoc_ty_def( - selcx: &SelectionContext<'_, '_>, - impl_def_id: DefId, - assoc_ty_def_id: DefId, -) -> specialization_graph::NodeItem { - let tcx = selcx.tcx(); - let assoc_ty_name = tcx.associated_item(assoc_ty_def_id).ident; - let trait_def_id = tcx.impl_trait_ref(impl_def_id).unwrap().def_id; - let trait_def = tcx.trait_def(trait_def_id); - - // This function may be called while we are still building the - // specialization graph that is queried below (via TraidDef::ancestors()), - // so, in order to avoid unnecessary infinite recursion, we manually look - // for the associated item at the given impl. - // If there is no such item in that impl, this function will fail with a - // cycle error if the specialization graph is currently being built. - let impl_node = specialization_graph::Node::Impl(impl_def_id); - for item in impl_node.items(tcx) { - if matches!(item.kind, ty::AssocKind::Type | ty::AssocKind::OpaqueTy) - && tcx.hygienic_eq(item.ident, assoc_ty_name, trait_def_id) - { - return specialization_graph::NodeItem { - node: specialization_graph::Node::Impl(impl_def_id), - item: *item, - }; - } - } - - if let Some(assoc_item) = - trait_def.ancestors(tcx, impl_def_id).leaf_def(tcx, assoc_ty_name, ty::AssocKind::Type) - { - assoc_item - } else { - // This is saying that neither the trait nor - // the impl contain a definition for this - // associated type. Normally this situation - // could only arise through a compiler bug -- - // if the user wrote a bad item name, it - // should have failed in astconv. - bug!("No associated type `{}` for {}", assoc_ty_name, tcx.def_path_str(impl_def_id)) - } -} - // # Cache /// The projection cache. Unlike the standard caches, this can include @@ -1541,26 +68,14 @@ pub struct ProjectionCacheKey<'tcx> { ty: ty::ProjectionTy<'tcx>, } -impl<'cx, 'tcx> ProjectionCacheKey<'tcx> { - pub fn from_poly_projection_predicate( - selcx: &mut SelectionContext<'cx, 'tcx>, - predicate: &ty::PolyProjectionPredicate<'tcx>, - ) -> Option { - let infcx = selcx.infcx(); - // We don't do cross-snapshot caching of obligations with escaping regions, - // so there's no cache key to use - predicate.no_bound_vars().map(|predicate| ProjectionCacheKey { - // We don't attempt to match up with a specific type-variable state - // from a specific call to `opt_normalize_projection_type` - if - // there's no precise match, the original cache entry is "stranded" - // anyway. - ty: infcx.resolve_vars_if_possible(&predicate.projection_ty), - }) +impl ProjectionCacheKey<'tcx> { + pub fn new(ty: ty::ProjectionTy<'tcx>) -> Self { + Self { ty } } } #[derive(Clone, Debug)] -enum ProjectionCacheEntry<'tcx> { +pub enum ProjectionCacheEntry<'tcx> { InProgress, Ambiguous, Error, @@ -1596,7 +111,7 @@ impl<'tcx> ProjectionCache<'tcx> { /// Try to start normalize `key`; returns an error if /// normalization already occurred (this error corresponds to a /// cache hit, so it's actually a good thing). - fn try_start( + pub fn try_start( &mut self, key: ProjectionCacheKey<'tcx>, ) -> Result<(), ProjectionCacheEntry<'tcx>> { @@ -1609,7 +124,7 @@ impl<'tcx> ProjectionCache<'tcx> { } /// Indicates that `key` was normalized to `value`. - fn insert_ty(&mut self, key: ProjectionCacheKey<'tcx>, value: NormalizedTy<'tcx>) { + pub fn insert_ty(&mut self, key: ProjectionCacheKey<'tcx>, value: NormalizedTy<'tcx>) { debug!( "ProjectionCacheEntry::insert_ty: adding cache entry: key={:?}, value={:?}", key, value @@ -1662,14 +177,14 @@ impl<'tcx> ProjectionCache<'tcx> { /// ambiguity. No point in trying it again then until we gain more /// type information (in which case, the "fully resolved" key will /// be different). - fn ambiguous(&mut self, key: ProjectionCacheKey<'tcx>) { + pub fn ambiguous(&mut self, key: ProjectionCacheKey<'tcx>) { let fresh = self.map.insert(key, ProjectionCacheEntry::Ambiguous); assert!(!fresh, "never started projecting `{:?}`", key); } /// Indicates that trying to normalize `key` resulted in /// error. - fn error(&mut self, key: ProjectionCacheKey<'tcx>) { + pub fn error(&mut self, key: ProjectionCacheKey<'tcx>) { let fresh = self.map.insert(key, ProjectionCacheEntry::Error); assert!(!fresh, "never started projecting `{:?}`", key); } diff --git a/src/librustc_infer/traits/util.rs b/src/librustc_infer/traits/util.rs index cd4595e76ccec..90f3cb1d24ccc 100644 --- a/src/librustc_infer/traits/util.rs +++ b/src/librustc_infer/traits/util.rs @@ -1,16 +1,8 @@ -use rustc_errors::DiagnosticBuilder; -use rustc_span::Span; use smallvec::smallvec; -use smallvec::SmallVec; use rustc::ty::outlives::Component; -use rustc::ty::subst::{GenericArg, Subst, SubstsRef}; -use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness}; +use rustc::ty::{self, ToPolyTraitRef, TyCtxt}; use rustc_data_structures::fx::FxHashSet; -use rustc_hir as hir; -use rustc_hir::def_id::DefId; - -use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext}; fn anonymize_predicate<'tcx>(tcx: TyCtxt<'tcx>, pred: &ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { match *pred { @@ -96,21 +88,6 @@ pub struct Elaborator<'tcx> { visited: PredicateSet<'tcx>, } -pub fn elaborate_trait_ref<'tcx>( - tcx: TyCtxt<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, -) -> Elaborator<'tcx> { - elaborate_predicates(tcx, vec![trait_ref.without_const().to_predicate()]) -} - -pub fn elaborate_trait_refs<'tcx>( - tcx: TyCtxt<'tcx>, - trait_refs: impl Iterator>, -) -> Elaborator<'tcx> { - let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate()).collect(); - elaborate_predicates(tcx, predicates) -} - pub fn elaborate_predicates<'tcx>( tcx: TyCtxt<'tcx>, mut predicates: Vec>, @@ -121,10 +98,6 @@ pub fn elaborate_predicates<'tcx>( } impl Elaborator<'tcx> { - pub fn filter_to_traits(self) -> FilterToTraits { - FilterToTraits::new(self) - } - fn elaborate(&mut self, predicate: &ty::Predicate<'tcx>) { let tcx = self.visited.tcx; match *predicate { @@ -250,426 +223,3 @@ impl Iterator for Elaborator<'tcx> { } } } - -/////////////////////////////////////////////////////////////////////////// -// Supertrait iterator -/////////////////////////////////////////////////////////////////////////// - -pub type Supertraits<'tcx> = FilterToTraits>; - -pub fn supertraits<'tcx>( - tcx: TyCtxt<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, -) -> Supertraits<'tcx> { - elaborate_trait_ref(tcx, trait_ref).filter_to_traits() -} - -pub fn transitive_bounds<'tcx>( - tcx: TyCtxt<'tcx>, - bounds: impl Iterator>, -) -> Supertraits<'tcx> { - elaborate_trait_refs(tcx, bounds).filter_to_traits() -} - -/////////////////////////////////////////////////////////////////////////// -// `TraitAliasExpander` iterator -/////////////////////////////////////////////////////////////////////////// - -/// "Trait alias expansion" is the process of expanding a sequence of trait -/// references into another sequence by transitively following all trait -/// aliases. e.g. If you have bounds like `Foo + Send`, a trait alias -/// `trait Foo = Bar + Sync;`, and another trait alias -/// `trait Bar = Read + Write`, then the bounds would expand to -/// `Read + Write + Sync + Send`. -/// Expansion is done via a DFS (depth-first search), and the `visited` field -/// is used to avoid cycles. -pub struct TraitAliasExpander<'tcx> { - tcx: TyCtxt<'tcx>, - stack: Vec>, -} - -/// Stores information about the expansion of a trait via a path of zero or more trait aliases. -#[derive(Debug, Clone)] -pub struct TraitAliasExpansionInfo<'tcx> { - pub path: SmallVec<[(ty::PolyTraitRef<'tcx>, Span); 4]>, -} - -impl<'tcx> TraitAliasExpansionInfo<'tcx> { - fn new(trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self { - Self { path: smallvec![(trait_ref, span)] } - } - - /// Adds diagnostic labels to `diag` for the expansion path of a trait through all intermediate - /// trait aliases. - pub fn label_with_exp_info( - &self, - diag: &mut DiagnosticBuilder<'_>, - top_label: &str, - use_desc: &str, - ) { - diag.span_label(self.top().1, top_label); - if self.path.len() > 1 { - for (_, sp) in self.path.iter().rev().skip(1).take(self.path.len() - 2) { - diag.span_label(*sp, format!("referenced here ({})", use_desc)); - } - } - diag.span_label( - self.bottom().1, - format!("trait alias used in trait object type ({})", use_desc), - ); - } - - pub fn trait_ref(&self) -> &ty::PolyTraitRef<'tcx> { - &self.top().0 - } - - pub fn top(&self) -> &(ty::PolyTraitRef<'tcx>, Span) { - self.path.last().unwrap() - } - - pub fn bottom(&self) -> &(ty::PolyTraitRef<'tcx>, Span) { - self.path.first().unwrap() - } - - fn clone_and_push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self { - let mut path = self.path.clone(); - path.push((trait_ref, span)); - - Self { path } - } -} - -pub fn expand_trait_aliases<'tcx>( - tcx: TyCtxt<'tcx>, - trait_refs: impl IntoIterator, Span)>, -) -> TraitAliasExpander<'tcx> { - let items: Vec<_> = trait_refs - .into_iter() - .map(|(trait_ref, span)| TraitAliasExpansionInfo::new(trait_ref, span)) - .collect(); - TraitAliasExpander { tcx, stack: items } -} - -impl<'tcx> TraitAliasExpander<'tcx> { - /// If `item` is a trait alias and its predicate has not yet been visited, then expands `item` - /// to the definition, pushes the resulting expansion onto `self.stack`, and returns `false`. - /// Otherwise, immediately returns `true` if `item` is a regular trait, or `false` if it is a - /// trait alias. - /// The return value indicates whether `item` should be yielded to the user. - fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool { - let tcx = self.tcx; - let trait_ref = item.trait_ref(); - let pred = trait_ref.without_const().to_predicate(); - - debug!("expand_trait_aliases: trait_ref={:?}", trait_ref); - - // Don't recurse if this bound is not a trait alias. - let is_alias = tcx.is_trait_alias(trait_ref.def_id()); - if !is_alias { - return true; - } - - // 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.without_const().to_predicate()) == anon_pred - }) { - return false; - } - - // Get components of trait alias. - let predicates = tcx.super_predicates_of(trait_ref.def_id()); - - let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| { - pred.subst_supertrait(tcx, &trait_ref) - .to_opt_poly_trait_ref() - .map(|trait_ref| item.clone_and_push(trait_ref, *span)) - }); - debug!("expand_trait_aliases: items={:?}", items.clone()); - - self.stack.extend(items); - - false - } -} - -impl<'tcx> Iterator for TraitAliasExpander<'tcx> { - type Item = TraitAliasExpansionInfo<'tcx>; - - fn size_hint(&self) -> (usize, Option) { - (self.stack.len(), None) - } - - fn next(&mut self) -> Option> { - while let Some(item) = self.stack.pop() { - if self.expand(&item) { - return Some(item); - } - } - None - } -} - -/////////////////////////////////////////////////////////////////////////// -// Iterator over def-IDs of supertraits -/////////////////////////////////////////////////////////////////////////// - -pub struct SupertraitDefIds<'tcx> { - tcx: TyCtxt<'tcx>, - stack: Vec, - visited: FxHashSet, -} - -pub fn supertrait_def_ids(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SupertraitDefIds<'_> { - SupertraitDefIds { - tcx, - stack: vec![trait_def_id], - visited: Some(trait_def_id).into_iter().collect(), - } -} - -impl Iterator for SupertraitDefIds<'tcx> { - type Item = DefId; - - fn next(&mut self) -> Option { - let def_id = self.stack.pop()?; - let predicates = self.tcx.super_predicates_of(def_id); - let visited = &mut self.visited; - self.stack.extend( - predicates - .predicates - .iter() - .filter_map(|(pred, _)| pred.to_opt_poly_trait_ref()) - .map(|trait_ref| trait_ref.def_id()) - .filter(|&super_def_id| visited.insert(super_def_id)), - ); - Some(def_id) - } -} - -/////////////////////////////////////////////////////////////////////////// -// Other -/////////////////////////////////////////////////////////////////////////// - -/// A filter around an iterator of predicates that makes it yield up -/// just trait references. -pub struct FilterToTraits { - base_iterator: I, -} - -impl FilterToTraits { - fn new(base: I) -> FilterToTraits { - FilterToTraits { base_iterator: base } - } -} - -impl<'tcx, I: Iterator>> Iterator for FilterToTraits { - type Item = ty::PolyTraitRef<'tcx>; - - fn next(&mut self) -> Option> { - while let Some(pred) = self.base_iterator.next() { - if let ty::Predicate::Trait(data, _) = pred { - return Some(data.to_poly_trait_ref()); - } - } - None - } - - fn size_hint(&self) -> (usize, Option) { - let (_, upper) = self.base_iterator.size_hint(); - (0, upper) - } -} - -/////////////////////////////////////////////////////////////////////////// -// Other -/////////////////////////////////////////////////////////////////////////// - -/// Instantiate all bound parameters of the impl with the given substs, -/// returning the resulting trait ref and all obligations that arise. -/// The obligations are closed under normalization. -pub fn impl_trait_ref_and_oblig<'a, 'tcx>( - selcx: &mut SelectionContext<'a, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - impl_def_id: DefId, - impl_substs: SubstsRef<'tcx>, -) -> (ty::TraitRef<'tcx>, Vec>) { - let impl_trait_ref = selcx.tcx().impl_trait_ref(impl_def_id).unwrap(); - let impl_trait_ref = impl_trait_ref.subst(selcx.tcx(), impl_substs); - let Normalized { value: impl_trait_ref, obligations: normalization_obligations1 } = - super::normalize(selcx, param_env, ObligationCause::dummy(), &impl_trait_ref); - - let predicates = selcx.tcx().predicates_of(impl_def_id); - let predicates = predicates.instantiate(selcx.tcx(), impl_substs); - let Normalized { value: predicates, obligations: normalization_obligations2 } = - super::normalize(selcx, param_env, ObligationCause::dummy(), &predicates); - let impl_obligations = - predicates_for_generics(ObligationCause::dummy(), 0, param_env, &predicates); - - let impl_obligations: Vec<_> = impl_obligations - .into_iter() - .chain(normalization_obligations1) - .chain(normalization_obligations2) - .collect(); - - (impl_trait_ref, impl_obligations) -} - -/// See [`super::obligations_for_generics`]. -pub fn predicates_for_generics<'tcx>( - cause: ObligationCause<'tcx>, - recursion_depth: usize, - param_env: ty::ParamEnv<'tcx>, - generic_bounds: &ty::InstantiatedPredicates<'tcx>, -) -> Vec> { - debug!("predicates_for_generics(generic_bounds={:?})", generic_bounds); - - generic_bounds - .predicates - .iter() - .map(|&predicate| Obligation { - cause: cause.clone(), - recursion_depth, - param_env, - predicate, - }) - .collect() -} - -pub fn predicate_for_trait_ref<'tcx>( - cause: ObligationCause<'tcx>, - param_env: ty::ParamEnv<'tcx>, - trait_ref: ty::TraitRef<'tcx>, - recursion_depth: usize, -) -> PredicateObligation<'tcx> { - Obligation { - cause, - param_env, - recursion_depth, - predicate: trait_ref.without_const().to_predicate(), - } -} - -pub fn predicate_for_trait_def( - tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - cause: ObligationCause<'tcx>, - trait_def_id: DefId, - recursion_depth: usize, - self_ty: Ty<'tcx>, - params: &[GenericArg<'tcx>], -) -> PredicateObligation<'tcx> { - let trait_ref = - ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(self_ty, params) }; - predicate_for_trait_ref(cause, param_env, trait_ref, recursion_depth) -} - -/// Casts a trait reference into a reference to one of its super -/// traits; returns `None` if `target_trait_def_id` is not a -/// supertrait. -pub fn upcast_choices( - tcx: TyCtxt<'tcx>, - source_trait_ref: ty::PolyTraitRef<'tcx>, - target_trait_def_id: DefId, -) -> Vec> { - if source_trait_ref.def_id() == target_trait_def_id { - return vec![source_trait_ref]; // Shortcut the most common case. - } - - supertraits(tcx, source_trait_ref).filter(|r| r.def_id() == target_trait_def_id).collect() -} - -/// Given a trait `trait_ref`, returns the number of vtable entries -/// that come from `trait_ref`, excluding its supertraits. Used in -/// computing the vtable base for an upcast trait of a trait object. -pub fn count_own_vtable_entries(tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> usize { - let mut entries = 0; - // Count number of methods and add them to the total offset. - // Skip over associated types and constants. - for trait_item in tcx.associated_items(trait_ref.def_id()).in_definition_order() { - if trait_item.kind == ty::AssocKind::Method { - entries += 1; - } - } - entries -} - -/// Given an upcast trait object described by `object`, returns the -/// index of the method `method_def_id` (which should be part of -/// `object.upcast_trait_ref`) within the vtable for `object`. -pub fn get_vtable_index_of_object_method( - tcx: TyCtxt<'tcx>, - object: &super::VtableObjectData<'tcx, N>, - method_def_id: DefId, -) -> usize { - // Count number of methods preceding the one we are selecting and - // add them to the total offset. - // Skip over associated types and constants. - let mut entries = object.vtable_base; - for trait_item in tcx.associated_items(object.upcast_trait_ref.def_id()).in_definition_order() { - if trait_item.def_id == method_def_id { - // The item with the ID we were given really ought to be a method. - assert_eq!(trait_item.kind, ty::AssocKind::Method); - return entries; - } - if trait_item.kind == ty::AssocKind::Method { - entries += 1; - } - } - - bug!("get_vtable_index_of_object_method: {:?} was not found", method_def_id); -} - -pub fn closure_trait_ref_and_return_type( - tcx: TyCtxt<'tcx>, - fn_trait_def_id: DefId, - self_ty: Ty<'tcx>, - sig: ty::PolyFnSig<'tcx>, - tuple_arguments: TupleArgumentsFlag, -) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>)> { - let arguments_tuple = match tuple_arguments { - TupleArgumentsFlag::No => sig.skip_binder().inputs()[0], - TupleArgumentsFlag::Yes => tcx.intern_tup(sig.skip_binder().inputs()), - }; - let trait_ref = ty::TraitRef { - def_id: fn_trait_def_id, - substs: tcx.mk_substs_trait(self_ty, &[arguments_tuple.into()]), - }; - ty::Binder::bind((trait_ref, sig.skip_binder().output())) -} - -pub fn generator_trait_ref_and_outputs( - tcx: TyCtxt<'tcx>, - fn_trait_def_id: DefId, - self_ty: Ty<'tcx>, - sig: ty::PolyGenSig<'tcx>, -) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> { - let trait_ref = ty::TraitRef { - def_id: fn_trait_def_id, - substs: tcx.mk_substs_trait(self_ty, &[sig.skip_binder().resume_ty.into()]), - }; - ty::Binder::bind((trait_ref, sig.skip_binder().yield_ty, sig.skip_binder().return_ty)) -} - -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 { - defaultness.is_default() - } else { - false - } - } - None => tcx.impl_defaultness(node_item_def_id).is_default(), - } -} - -pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool { - assoc_item.defaultness.is_final() && !impl_is_default(tcx, assoc_item.container.id()) -} - -pub enum TupleArgumentsFlag { - Yes, - No, -} diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml index b29480a88109f..2e055ff183f2c 100644 --- a/src/librustc_interface/Cargo.toml +++ b/src/librustc_interface/Cargo.toml @@ -28,7 +28,7 @@ rustc_incremental = { path = "../librustc_incremental" } rustc_traits = { path = "../librustc_traits" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_codegen_ssa = { path = "../librustc_codegen_ssa" } -rustc_codegen_utils = { path = "../librustc_codegen_utils" } +rustc_symbol_mangling = { path = "../librustc_symbol_mangling" } rustc_codegen_llvm = { path = "../librustc_codegen_llvm", optional = true } rustc_hir = { path = "../librustc_hir" } rustc_infer = { path = "../librustc_infer" } @@ -42,6 +42,7 @@ rustc_errors = { path = "../librustc_errors" } rustc_plugin_impl = { path = "../librustc_plugin_impl" } rustc_privacy = { path = "../librustc_privacy" } rustc_resolve = { path = "../librustc_resolve" } +rustc_trait_selection = { path = "../librustc_trait_selection" } rustc_ty = { path = "../librustc_ty" } tempfile = "3.0.5" once_cell = "1" diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs index e15217dfa67e6..65a7a48d440bd 100644 --- a/src/librustc_interface/interface.rs +++ b/src/librustc_interface/interface.rs @@ -1,22 +1,22 @@ pub use crate::passes::BoxedResolver; use crate::util; -use rustc::lint; -use rustc::session::config::{self, ErrorOutputType, Input, OutputFilenames}; -use rustc::session::early_error; -use rustc::session::{DiagnosticOutput, Session}; use rustc::ty; use rustc::util::common::ErrorReported; use rustc_ast::ast::{self, MetaItemKind}; use rustc_ast::token; -use rustc_codegen_utils::codegen_backend::CodegenBackend; +use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::OnDrop; use rustc_errors::registry::Registry; use rustc_lint::LintStore; use rustc_parse::new_parser_from_source_str; +use rustc_session::config::{self, ErrorOutputType, Input, OutputFilenames}; +use rustc_session::early_error; +use rustc_session::lint; use rustc_session::parse::{CrateConfig, ParseSess}; +use rustc_session::{DiagnosticOutput, Session}; use rustc_span::edition; use rustc_span::source_map::{FileLoader, FileName, SourceMap}; use std::path::PathBuf; diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 29e9ea1833f8e..7cf0b4c44a6aa 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -5,29 +5,22 @@ use crate::util; use log::{info, log_enabled, warn}; use rustc::arena::Arena; use rustc::dep_graph::DepGraph; -use rustc::hir::map; -use rustc::lint; use rustc::middle; use rustc::middle::cstore::{CrateStore, MetadataLoader, MetadataLoaderDyn}; -use rustc::session::config::{self, CrateType, Input, OutputFilenames, OutputType}; -use rustc::session::config::{PpMode, PpSourceMode}; -use rustc::session::search_paths::PathKind; -use rustc::session::Session; use rustc::ty::steal::Steal; use rustc::ty::{self, GlobalCtxt, ResolverOutputs, TyCtxt}; use rustc::util::common::ErrorReported; use rustc_ast::mut_visit::MutVisitor; use rustc_ast::{self, ast, visit}; use rustc_codegen_ssa::back::link::emit_metadata; -use rustc_codegen_utils::codegen_backend::CodegenBackend; -use rustc_codegen_utils::link::filename_for_metadata; +use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::sync::{par_iter, Lrc, Once, ParallelIterator, WorkerLocal}; use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel}; use rustc_errors::PResult; use rustc_expand::base::ExtCtxt; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; +use rustc_hir::definitions::Definitions; use rustc_hir::Crate; -use rustc_infer::traits; use rustc_lint::LintStore; use rustc_mir as mir; use rustc_mir_build as mir_build; @@ -35,8 +28,16 @@ use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str}; use rustc_passes::{self, hir_stats, layout_test}; use rustc_plugin_impl as plugin; use rustc_resolve::{Resolver, ResolverArenas}; +use rustc_session::config::{ + self, CrateType, Input, OutputFilenames, OutputType, PpMode, PpSourceMode, +}; +use rustc_session::lint; +use rustc_session::output::{filename_for_input, filename_for_metadata}; +use rustc_session::search_paths::PathKind; +use rustc_session::Session; use rustc_span::symbol::Symbol; use rustc_span::FileName; +use rustc_trait_selection::traits; use rustc_typeck as typeck; use rustc_serialize::json; @@ -210,14 +211,7 @@ pub fn register_plugins<'a>( Ok((krate, Lrc::new(lint_store))) } -fn configure_and_expand_inner<'a>( - sess: &'a Session, - lint_store: &'a LintStore, - mut krate: ast::Crate, - crate_name: &str, - resolver_arenas: &'a ResolverArenas<'a>, - metadata_loader: &'a MetadataLoaderDyn, -) -> Result<(ast::Crate, Resolver<'a>)> { +fn pre_expansion_lint(sess: &Session, lint_store: &LintStore, krate: &ast::Crate) { sess.time("pre_AST_expansion_lint_checks", || { rustc_lint::check_ast_crate( sess, @@ -228,6 +222,17 @@ fn configure_and_expand_inner<'a>( rustc_lint::BuiltinCombinedPreExpansionLintPass::new(), ); }); +} + +fn configure_and_expand_inner<'a>( + sess: &'a Session, + lint_store: &'a LintStore, + mut krate: ast::Crate, + crate_name: &str, + resolver_arenas: &'a ResolverArenas<'a>, + metadata_loader: &'a MetadataLoaderDyn, +) -> Result<(ast::Crate, Resolver<'a>)> { + pre_expansion_lint(sess, lint_store, &krate); let mut resolver = Resolver::new(sess, &krate, crate_name, metadata_loader, &resolver_arenas); rustc_builtin_macros::register_builtin_macros(&mut resolver, sess.edition()); @@ -291,7 +296,8 @@ fn configure_and_expand_inner<'a>( ..rustc_expand::expand::ExpansionConfig::default(crate_name.to_string()) }; - let mut ecx = ExtCtxt::new(&sess.parse_sess, cfg, &mut resolver); + let extern_mod_loaded = |k: &ast::Crate| pre_expansion_lint(sess, lint_store, k); + let mut ecx = ExtCtxt::new(&sess.parse_sess, cfg, &mut resolver, Some(&extern_mod_loaded)); // Expand macros now! let krate = sess.time("expand_crate", || ecx.monotonic_expander().expand_crate(krate)); @@ -306,6 +312,8 @@ fn configure_and_expand_inner<'a>( ecx.parse_sess.missing_fragment_specifiers.borrow().iter().cloned().collect(); missing_fragment_specifiers.sort(); + let recursion_limit_hit = ecx.reduced_recursion_limit.is_some(); + for span in missing_fragment_specifiers { let lint = lint::builtin::MISSING_FRAGMENT_SPECIFIER; let msg = "missing fragment specifier"; @@ -314,8 +322,15 @@ fn configure_and_expand_inner<'a>( if cfg!(windows) { env::set_var("PATH", &old_path); } - krate - }); + + if recursion_limit_hit { + // If we hit a recursion limit, exit early to avoid later passes getting overwhelmed + // with a large AST + Err(ErrorReported) + } else { + Ok(krate) + } + })?; sess.time("maybe_building_test_harness", || { rustc_builtin_macros::test_harness::inject( @@ -422,12 +437,16 @@ pub fn lower_to_hir<'res, 'tcx>( resolver: &'res mut Resolver<'_>, dep_graph: &'res DepGraph, krate: &'res ast::Crate, - arena: &'tcx Arena<'tcx>, + arena: &'tcx rustc_ast_lowering::Arena<'tcx>, ) -> Crate<'tcx> { + // We're constructing the HIR here; we don't care what we will + // read, since we haven't even constructed the *input* to + // incr. comp. yet. + dep_graph.assert_ignored(); + // Lower AST to HIR. let hir_crate = rustc_ast_lowering::lower_crate( sess, - &dep_graph, &krate, resolver, rustc_parse::nt_to_tokenstream, @@ -472,12 +491,7 @@ fn generated_output_paths( // by appending `.rlib`, `.exe`, etc., so we can skip this transformation. OutputType::Exe if !exact_name => { for crate_type in sess.crate_types.borrow().iter() { - let p = ::rustc_codegen_utils::link::filename_for_input( - sess, - *crate_type, - crate_name, - outputs, - ); + let p = filename_for_input(sess, *crate_type, crate_name, outputs); out_filenames.push(p); } } @@ -677,7 +691,7 @@ pub fn default_provide(providers: &mut ty::query::Providers<'_>) { rustc_ty::provide(providers); rustc_metadata::provide(providers); rustc_lint::provide(providers); - rustc_codegen_utils::provide(providers); + rustc_symbol_mangling::provide(providers); rustc_codegen_ssa::provide(providers); } @@ -693,7 +707,7 @@ impl<'tcx> QueryContext<'tcx> { where F: FnOnce(TyCtxt<'tcx>) -> R, { - ty::tls::enter_global(self.0, |tcx| f(tcx)) + ty::tls::enter_global(self.0, f) } pub fn print_stats(&mut self) { @@ -713,10 +727,7 @@ pub fn create_global_ctxt<'tcx>( arena: &'tcx WorkerLocal>, ) -> QueryContext<'tcx> { let sess = &compiler.session(); - let defs = mem::take(&mut resolver_outputs.definitions); - - // Construct the HIR map. - let hir_map = map::map_crate(sess, &*resolver_outputs.cstore, krate, dep_graph, defs); + let defs: &'tcx Definitions = arena.alloc(mem::take(&mut resolver_outputs.definitions)); let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess); @@ -742,7 +753,9 @@ pub fn create_global_ctxt<'tcx>( extern_providers, arena, resolver_outputs, - hir_map, + krate, + defs, + dep_graph, query_result_on_disk_cache, &crate_name, &outputs, @@ -763,6 +776,8 @@ pub fn create_global_ctxt<'tcx>( fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { assert_eq!(cnum, LOCAL_CRATE); + rustc_passes::hir_id_validator::check_crate(tcx); + let sess = tcx.sess; let mut entry_point = None; diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index 426d97cc09b92..b0eeb57173fa3 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -3,18 +3,19 @@ use crate::passes::{self, BoxedResolver, QueryContext}; use rustc::arena::Arena; use rustc::dep_graph::DepGraph; -use rustc::session::config::{OutputFilenames, OutputType}; -use rustc::session::Session; use rustc::ty::steal::Steal; -use rustc::ty::{GlobalCtxt, ResolverOutputs}; +use rustc::ty::{GlobalCtxt, ResolverOutputs, TyCtxt}; use rustc::util::common::ErrorReported; use rustc_ast::{self, ast}; -use rustc_codegen_utils::codegen_backend::CodegenBackend; +use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::sync::{Lrc, Once, WorkerLocal}; use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::Crate; use rustc_incremental::DepGraphFuture; use rustc_lint::LintStore; +use rustc_session::config::{OutputFilenames, OutputType}; +use rustc_session::{output::find_crate_name, Session}; +use rustc_span::symbol::sym; use std::any::Any; use std::cell::{Ref, RefCell, RefMut}; use std::mem; @@ -67,6 +68,7 @@ pub struct Queries<'tcx> { gcx: Once>, arena: WorkerLocal>, + hir_arena: WorkerLocal>, dep_graph_future: Query>, parse: Query, @@ -86,6 +88,7 @@ impl<'tcx> Queries<'tcx> { compiler, gcx: Once::new(), arena: WorkerLocal::new(|_| Arena::default()), + hir_arena: WorkerLocal::new(|_| rustc_ast_lowering::Arena::default()), dep_graph_future: Default::default(), parse: Default::default(), crate_name: Default::default(), @@ -157,11 +160,7 @@ impl<'tcx> Queries<'tcx> { None => { let parse_result = self.parse()?; let krate = parse_result.peek(); - rustc_codegen_utils::link::find_crate_name( - Some(self.session()), - &krate.attrs, - &self.compiler.input, - ) + find_crate_name(Some(self.session()), &krate.attrs, &self.compiler.input) } }) }) @@ -221,10 +220,10 @@ impl<'tcx> Queries<'tcx> { resolver, &*self.dep_graph()?.peek(), &krate, - &self.arena, + &self.hir_arena, )) })?; - let hir = self.arena.alloc(hir); + let hir = self.hir_arena.alloc(hir); Ok((hir, Steal::new(BoxedResolver::to_resolver_outputs(resolver)))) }) } @@ -277,11 +276,58 @@ impl<'tcx> Queries<'tcx> { // Don't do code generation if there were any errors self.session().compile_status()?; + // Hook for compile-fail tests. + Self::check_for_rustc_errors_attr(tcx); + Ok(passes::start_codegen(&***self.codegen_backend(), tcx, &*outputs.peek())) }) }) } + /// Check for the `#[rustc_error]` annotation, which forces an error in codegen. This is used + /// to write compile-fail tests that actually test that compilation succeeds without reporting + /// an error. + fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) { + let def_id = match tcx.entry_fn(LOCAL_CRATE) { + Some((def_id, _)) => def_id, + _ => return, + }; + + let attrs = &*tcx.get_attrs(def_id); + let attrs = attrs.iter().filter(|attr| attr.check_name(sym::rustc_error)); + for attr in attrs { + match attr.meta_item_list() { + // Check if there is a `#[rustc_error(delay_span_bug_from_inside_query)]`. + Some(list) + if list.iter().any(|list_item| { + matches!( + list_item.ident().map(|i| i.name), + Some(sym::delay_span_bug_from_inside_query) + ) + }) => + { + tcx.ensure().trigger_delay_span_bug(def_id); + } + + // Bare `#[rustc_error]`. + None => { + tcx.sess.span_fatal( + tcx.def_span(def_id), + "fatal error triggered by #[rustc_error]", + ); + } + + // Some other attribute. + Some(_) => { + tcx.sess.span_warn( + tcx.def_span(def_id), + "unexpected annotation used with `#[rustc_error(...)]!", + ); + } + } + } + } + pub fn linker(&'tcx self) -> Result { let dep_graph = self.dep_graph()?; let prepare_outputs = self.prepare_outputs()?; diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs index 1b80cf4e3dbc2..6a6d0a8f061eb 100644 --- a/src/librustc_interface/tests.rs +++ b/src/librustc_interface/tests.rs @@ -2,16 +2,16 @@ extern crate getopts; use crate::interface::parse_cfgspecs; -use rustc::lint::Level; use rustc::middle::cstore; -use rustc::session::config::{build_configuration, build_session_options, to_crate_config}; -use rustc::session::config::{rustc_optgroups, ErrorOutputType, ExternLocation, Options, Passes}; -use rustc::session::config::{ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath}; -use rustc::session::config::{Externs, OutputType, OutputTypes, SymbolManglingVersion}; -use rustc::session::search_paths::SearchPath; -use rustc::session::{build_session, Session}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; +use rustc_session::config::{build_configuration, build_session_options, to_crate_config}; +use rustc_session::config::{rustc_optgroups, ErrorOutputType, ExternLocation, Options, Passes}; +use rustc_session::config::{ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath}; +use rustc_session::config::{Externs, OutputType, OutputTypes, SymbolManglingVersion}; +use rustc_session::lint::Level; +use rustc_session::search_paths::SearchPath; +use rustc_session::{build_session, Session}; use rustc_span::edition::{Edition, DEFAULT_EDITION}; use rustc_span::symbol::sym; use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel}; @@ -546,8 +546,6 @@ fn test_debugging_options_tracking_hash() { assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.debugging_opts.parse_only = true; assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.incremental = Some(String::from("abc")); - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.debugging_opts.dump_dep_graph = true; assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.debugging_opts.query_dep_graph = true; @@ -560,8 +558,6 @@ fn test_debugging_options_tracking_hash() { assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.debugging_opts.keep_hygiene_data = true; assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.keep_ast = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.debugging_opts.print_mono_items = Some(String::from("abc")); assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.debugging_opts.dump_mir = Some(String::from("abc")); diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 7866ddbd4ccd8..c6f2d1b82fcf4 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -1,12 +1,11 @@ use log::info; -use rustc::lint; use rustc::ty; use rustc_ast::ast::{AttrVec, BlockCheckMode}; use rustc_ast::mut_visit::{visit_clobber, MutVisitor, *}; use rustc_ast::ptr::P; use rustc_ast::util::lev_distance::find_best_match_for_name; use rustc_ast::{self, ast}; -use rustc_codegen_utils::codegen_backend::CodegenBackend; +use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; #[cfg(parallel_compiler)] @@ -18,10 +17,10 @@ use rustc_metadata::dynamic_lib::DynamicLibrary; use rustc_resolve::{self, Resolver}; use rustc_session as session; use rustc_session::config::{ErrorOutputType, Input, OutputFilenames}; -use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; +use rustc_session::lint::{self, BuiltinLintDiagnostics, LintBuffer}; use rustc_session::parse::CrateConfig; use rustc_session::CrateDisambiguator; -use rustc_session::{config, early_error, filesearch, DiagnosticOutput, Session}; +use rustc_session::{config, early_error, filesearch, output, DiagnosticOutput, Session}; use rustc_span::edition::Edition; use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMap}; use rustc_span::symbol::{sym, Symbol}; @@ -49,7 +48,7 @@ pub fn add_configuration( cfg.extend(codegen_backend.target_features(sess).into_iter().map(|feat| (tf, Some(feat)))); - if sess.crt_static_feature() { + if sess.crt_static_feature(None) { cfg.insert((tf, Some(Symbol::intern("crt-static")))); } } @@ -506,7 +505,7 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec Vec MutVisitor for ReplaceBodyWithLoop<'a, '_> { // in general the pretty printer processes unexpanded code, so // we override the default `visit_mac` method which panics. - fn visit_mac(&mut self, mac: &mut ast::Mac) { + fn visit_mac(&mut self, mac: &mut ast::MacCall) { noop_visit_mac(mac, self) } } diff --git a/src/librustc_lexer/src/lib.rs b/src/librustc_lexer/src/lib.rs index 25334461a113b..d3ac58a49c8d5 100644 --- a/src/librustc_lexer/src/lib.rs +++ b/src/librustc_lexer/src/lib.rs @@ -527,10 +527,10 @@ impl Cursor<'_> { if self.first() == '\'' { self.bump(); let kind = Char { terminated: true }; - return Literal { kind, suffix_start: self.len_consumed() }; + Literal { kind, suffix_start: self.len_consumed() } + } else { + Lifetime { starts_with_number } } - - return Lifetime { starts_with_number }; } fn single_quoted_string(&mut self) -> bool { diff --git a/src/librustc_lint/Cargo.toml b/src/librustc_lint/Cargo.toml index 6470d25fe0a2e..9785af5eab2fd 100644 --- a/src/librustc_lint/Cargo.toml +++ b/src/librustc_lint/Cargo.toml @@ -24,3 +24,4 @@ rustc_feature = { path = "../librustc_feature" } rustc_index = { path = "../librustc_index" } rustc_session = { path = "../librustc_session" } rustc_infer = { path = "../librustc_infer" } +rustc_trait_selection = { path = "../librustc_trait_selection" } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 249c9af3d4801..906e46edfe7ff 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -22,7 +22,6 @@ //! `late_lint_methods!` invocation in `lib.rs`. use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; -use rustc::hir::map::Map; use rustc::lint::LintDiagnosticBuilder; use rustc::ty::{self, layout::VariantIdx, Ty, TyCtxt}; use rustc_ast::ast::{self, Expr}; @@ -39,12 +38,12 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{GenericParamKind, PatKind}; use rustc_hir::{HirIdSet, Node}; -use rustc_infer::traits::misc::can_type_implement_copy; use rustc_session::lint::FutureIncompatibleInfo; use rustc_span::edition::Edition; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{BytePos, Span}; +use rustc_trait_selection::traits::misc::can_type_implement_copy; use crate::nonstandard_style::{method_context, MethodLateContext}; @@ -77,7 +76,7 @@ impl EarlyLintPass for WhileTrue { if let ast::LitKind::Bool(true) = lit.kind { if !lit.span.from_expansion() { let msg = "denote infinite loops with `loop { ... }`"; - let condition_span = cx.sess.source_map().def_span(e.span); + let condition_span = cx.sess.source_map().guess_head_span(e.span); cx.struct_span_lint(WHILE_TRUE, condition_span, |lint| { lint.build(msg) .span_suggestion_short( @@ -270,7 +269,7 @@ impl EarlyLintPass for UnsafeCode { }) } - _ => return, + _ => {} } } @@ -350,6 +349,7 @@ impl MissingDoc { id: Option, attrs: &[ast::Attribute], sp: Span, + article: &'static str, desc: &'static str, ) { // If we're building a test harness, then warning about @@ -374,9 +374,13 @@ impl MissingDoc { let has_doc = attrs.iter().any(|a| has_doc(a)); if !has_doc { - cx.struct_span_lint(MISSING_DOCS, cx.tcx.sess.source_map().def_span(sp), |lint| { - lint.build(&format!("missing documentation for {}", desc)).emit() - }); + cx.struct_span_lint( + MISSING_DOCS, + cx.tcx.sess.source_map().guess_head_span(sp), + |lint| { + lint.build(&format!("missing documentation for {} {}", article, desc)).emit() + }, + ); } } } @@ -399,14 +403,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { } fn check_crate(&mut self, cx: &LateContext<'_, '_>, krate: &hir::Crate<'_>) { - self.check_missing_docs_attrs(cx, None, &krate.attrs, krate.span, "crate"); + self.check_missing_docs_attrs(cx, None, &krate.item.attrs, krate.item.span, "the", "crate"); for macro_def in krate.exported_macros { let has_doc = macro_def.attrs.iter().any(|a| has_doc(a)); if !has_doc { cx.struct_span_lint( MISSING_DOCS, - cx.tcx.sess.source_map().def_span(macro_def.span), + cx.tcx.sess.source_map().guess_head_span(macro_def.span), |lint| lint.build("missing documentation for macro").emit(), ); } @@ -414,12 +418,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { } fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item<'_>) { - let desc = match it.kind { - hir::ItemKind::Fn(..) => "a function", - hir::ItemKind::Mod(..) => "a module", - hir::ItemKind::Enum(..) => "an enum", - hir::ItemKind::Struct(..) => "a struct", - hir::ItemKind::Union(..) => "a union", + match it.kind { hir::ItemKind::Trait(.., trait_item_refs) => { // Issue #11592: traits are always considered exported, even when private. if let hir::VisibilityKind::Inherited = it.vis.node { @@ -429,33 +428,39 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { } return; } - "a trait" } - hir::ItemKind::TyAlias(..) => "a type alias", 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(); if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(real_trait) { - match cx.tcx.hir().find(hir_id) { - Some(Node::Item(item)) => { - if let hir::VisibilityKind::Inherited = item.vis.node { - for impl_item_ref in items { - self.private_traits.insert(impl_item_ref.id.hir_id); - } + if let Some(Node::Item(item)) = cx.tcx.hir().find(hir_id) { + if let hir::VisibilityKind::Inherited = item.vis.node { + for impl_item_ref in items { + self.private_traits.insert(impl_item_ref.id.hir_id); } } - _ => {} } } return; } - hir::ItemKind::Const(..) => "a constant", - hir::ItemKind::Static(..) => "a static", + + hir::ItemKind::TyAlias(..) + | hir::ItemKind::Fn(..) + | hir::ItemKind::Mod(..) + | hir::ItemKind::Enum(..) + | hir::ItemKind::Struct(..) + | hir::ItemKind::Union(..) + | hir::ItemKind::Const(..) + | hir::ItemKind::Static(..) => {} + _ => return, }; - self.check_missing_docs_attrs(cx, Some(it.hir_id), &it.attrs, it.span, desc); + let def_id = cx.tcx.hir().local_def_id(it.hir_id); + let (article, desc) = cx.tcx.article_and_description(def_id); + + self.check_missing_docs_attrs(cx, Some(it.hir_id), &it.attrs, it.span, article, desc); } fn check_trait_item(&mut self, cx: &LateContext<'_, '_>, trait_item: &hir::TraitItem<'_>) { @@ -463,17 +468,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { return; } - let desc = match trait_item.kind { - hir::TraitItemKind::Const(..) => "an associated constant", - hir::TraitItemKind::Fn(..) => "a trait method", - hir::TraitItemKind::Type(..) => "an associated type", - }; + let def_id = cx.tcx.hir().local_def_id(trait_item.hir_id); + let (article, desc) = cx.tcx.article_and_description(def_id); self.check_missing_docs_attrs( cx, Some(trait_item.hir_id), &trait_item.attrs, trait_item.span, + article, desc, ); } @@ -484,29 +487,33 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { return; } - let desc = match impl_item.kind { - hir::ImplItemKind::Const(..) => "an associated constant", - hir::ImplItemKind::Method(..) => "a method", - hir::ImplItemKind::TyAlias(_) => "an associated type", - hir::ImplItemKind::OpaqueTy(_) => "an associated `impl Trait` type", - }; + let def_id = cx.tcx.hir().local_def_id(impl_item.hir_id); + let (article, desc) = cx.tcx.article_and_description(def_id); self.check_missing_docs_attrs( cx, Some(impl_item.hir_id), &impl_item.attrs, impl_item.span, + article, desc, ); } fn check_struct_field(&mut self, cx: &LateContext<'_, '_>, sf: &hir::StructField<'_>) { if !sf.is_positional() { - self.check_missing_docs_attrs(cx, Some(sf.hir_id), &sf.attrs, sf.span, "a struct field") + self.check_missing_docs_attrs( + cx, + Some(sf.hir_id), + &sf.attrs, + sf.span, + "a", + "struct field", + ) } } fn check_variant(&mut self, cx: &LateContext<'_, '_>, v: &hir::Variant<'_>) { - self.check_missing_docs_attrs(cx, Some(v.id), &v.attrs, v.span, "a variant"); + self.check_missing_docs_attrs(cx, Some(v.id), &v.attrs, v.span, "a", "variant"); } } @@ -778,7 +785,7 @@ impl EarlyLintPass for UnusedDocComment { ast::StmtKind::Empty | ast::StmtKind::Semi(_) | ast::StmtKind::Expr(_) - | ast::StmtKind::Mac(_) => return, + | ast::StmtKind::MacCall(_) => return, }; warn_if_doc(cx, stmt.span, kind, stmt.kind.attrs()); @@ -975,7 +982,7 @@ impl UnreachablePub { if span.from_expansion() { applicability = Applicability::MaybeIncorrect; } - let def_span = cx.tcx.sess.source_map().def_span(span); + let def_span = cx.tcx.sess.source_map().guess_head_span(span); cx.struct_span_lint(UNREACHABLE_PUB, def_span, |lint| { let mut err = lint.build(&format!("unreachable `pub` {}", what)); let replacement = if cx.tcx.features().crate_visibility_modifier { @@ -1071,9 +1078,9 @@ impl TypeAliasBounds { err: &'a mut DiagnosticBuilder<'db>, } impl<'a, 'db, 'v> Visitor<'v> for WalkAssocTypes<'a, 'db> { - type Map = Map<'v>; + type Map = intravisit::ErasedMap<'v>; - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { intravisit::NestedVisitorMap::None } @@ -1478,7 +1485,7 @@ impl EarlyLintPass for KeywordIdents { fn check_mac_def(&mut self, cx: &EarlyContext<'_>, mac_def: &ast::MacroDef, _id: ast::NodeId) { self.check_tokens(cx, mac_def.body.inner_tokens()); } - fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::Mac) { + fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::MacCall) { self.check_tokens(cx, mac.args.inner_tokens()); } fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: ast::Ident) { diff --git a/src/librustc_lint/context.rs b/src/librustc_lint/context.rs index 5b7b73b48ec5b..257b179d6ba6d 100644 --- a/src/librustc_lint/context.rs +++ b/src/librustc_lint/context.rs @@ -18,8 +18,6 @@ use self::TargetLint::*; use crate::levels::LintLevelsBuilder; use crate::passes::{EarlyLintPassObject, LateLintPassObject}; -use rustc::hir::map::definitions::{DefPathData, DisambiguatedDefPathData}; -use rustc::lint::add_elided_lifetime_in_path_suggestion; use rustc::lint::LintDiagnosticBuilder; use rustc::middle::privacy::AccessLevels; use rustc::middle::stability; @@ -32,7 +30,8 @@ use rustc_data_structures::sync; use rustc_errors::{struct_span_err, Applicability}; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId}; -use rustc_session::lint::BuiltinLintDiagnostics; +use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; +use rustc_session::lint::{add_elided_lifetime_in_path_suggestion, BuiltinLintDiagnostics}; use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId}; use rustc_session::Session; use rustc_span::{symbol::Symbol, MultiSpan, Span, DUMMY_SP}; diff --git a/src/librustc_lint/early.rs b/src/librustc_lint/early.rs index ff6e9e000b097..34da29c974777 100644 --- a/src/librustc_lint/early.rs +++ b/src/librustc_lint/early.rs @@ -18,7 +18,7 @@ use crate::context::{EarlyContext, LintContext, LintStore}; use crate::passes::{EarlyLintPass, EarlyLintPassObject}; use rustc_ast::ast; use rustc_ast::visit as ast_visit; -use rustc_session::lint::{LintBuffer, LintPass}; +use rustc_session::lint::{BufferedEarlyLint, LintBuffer, LintPass}; use rustc_session::Session; use rustc_span::Span; @@ -37,13 +37,7 @@ struct EarlyContextAndPass<'a, T: EarlyLintPass> { impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> { fn check_id(&mut self, id: ast::NodeId) { for early_lint in self.context.buffered.take(id) { - let rustc_session::lint::BufferedEarlyLint { - span, - msg, - node_id: _, - lint_id, - diagnostic, - } = early_lint; + let BufferedEarlyLint { span, msg, node_id: _, lint_id, diagnostic } = early_lint; self.context.lookup_with_diagnostics( lint_id.lint, Some(span), @@ -249,7 +243,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> self.check_id(id); } - fn visit_mac(&mut self, mac: &'a ast::Mac) { + fn visit_mac(&mut self, mac: &'a ast::MacCall) { // FIXME(#54110): So, this setup isn't really right. I think // that (a) the librustc_ast visitor ought to be doing this as // part of `walk_mac`, and (b) we should be calling @@ -326,11 +320,9 @@ pub fn check_ast_crate( lint_buffer: Option, builtin_lints: T, ) { - let mut passes: Vec<_> = if pre_expansion { - lint_store.pre_expansion_passes.iter().map(|p| (p)()).collect() - } else { - lint_store.early_passes.iter().map(|p| (p)()).collect() - }; + let passes = + if pre_expansion { &lint_store.pre_expansion_passes } else { &lint_store.early_passes }; + let mut passes: Vec<_> = passes.iter().map(|p| (p)()).collect(); let mut buffered = lint_buffer.unwrap_or_default(); if !sess.opts.debugging_opts.no_interleave_lints { diff --git a/src/librustc_lint/internal.rs b/src/librustc_lint/internal.rs index db109aef6eb8f..d8c685f2b22ff 100644 --- a/src/librustc_lint/internal.rs +++ b/src/librustc_lint/internal.rs @@ -140,7 +140,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind { } } TyKind::Rptr(_, MutTy { ty: inner_ty, mutbl: Mutability::Not }) => { - if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner_def_id()) { + if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner.to_def_id()) { if cx.tcx.impl_trait_ref(impl_did).is_some() { return; } diff --git a/src/librustc_lint/late.rs b/src/librustc_lint/late.rs index ee03232a0ce4c..d2cc551060357 100644 --- a/src/librustc_lint/late.rs +++ b/src/librustc_lint/late.rs @@ -33,7 +33,7 @@ use std::slice; /// Extract the `LintStore` from the query context. /// This function exists because we've erased `LintStore` as `dyn Any` in the context. -crate fn unerased_lint_store<'tcx>(tcx: TyCtxt<'tcx>) -> &'tcx LintStore { +crate fn unerased_lint_store(tcx: TyCtxt<'_>) -> &LintStore { let store: &dyn Any = &*tcx.lint_store; store.downcast_ref().unwrap() } @@ -99,8 +99,8 @@ impl<'a, 'tcx, T: LateLintPass<'a, 'tcx>> hir_visit::Visitor<'tcx> /// Because lints are scoped lexically, we want to walk nested /// items in the context of the outer item, so enable /// deep-walking. - fn nested_visit_map<'this>(&'this mut self) -> hir_visit::NestedVisitorMap<'this, Self::Map> { - hir_visit::NestedVisitorMap::All(&self.context.tcx.hir()) + fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap { + hir_visit::NestedVisitorMap::All(self.context.tcx.hir()) } fn visit_nested_body(&mut self, body: hir::BodyId) { @@ -419,7 +419,7 @@ fn late_lint_pass_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tc let mut cx = LateContextAndPass { context, pass }; // Visit the whole crate. - cx.with_lint_attrs(hir::CRATE_HIR_ID, &krate.attrs, |cx| { + cx.with_lint_attrs(hir::CRATE_HIR_ID, &krate.item.attrs, |cx| { // since the root module isn't visited as an item (because it isn't an // item), warn for it here. lint_callback!(cx, check_crate, krate); diff --git a/src/librustc_lint/levels.rs b/src/librustc_lint/levels.rs index e0db2ae64ff21..2062f9499aeb9 100644 --- a/src/librustc_lint/levels.rs +++ b/src/librustc_lint/levels.rs @@ -29,7 +29,7 @@ fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> &LintLevelMap { let mut builder = LintLevelMapBuilder { levels, tcx, store }; let krate = tcx.hir().krate(); - let push = builder.levels.push(&krate.attrs, &store); + let push = builder.levels.push(&krate.item.attrs, &store); builder.levels.register_id(hir::CRATE_HIR_ID); for macro_def in krate.exported_macros { builder.levels.register_id(macro_def.hir_id); @@ -438,8 +438,8 @@ impl LintLevelMapBuilder<'_, '_> { impl<'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'_, 'tcx> { type Map = Map<'tcx>; - fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, Self::Map> { - intravisit::NestedVisitorMap::All(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { + intravisit::NestedVisitorMap::All(self.tcx.hir()) } fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs index 37fefe680d7d2..afab55358d938 100644 --- a/src/librustc_lint/nonstandard_style.rs +++ b/src/librustc_lint/nonstandard_style.rs @@ -343,7 +343,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { } fn check_trait_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::TraitItem<'_>) { - if let hir::TraitItemKind::Fn(_, hir::TraitMethod::Required(pnames)) = item.kind { + if let hir::TraitItemKind::Fn(_, hir::TraitFn::Required(pnames)) = item.kind { self.check_snake_case(cx, "trait method", &item.ident); for param_name in pnames { self.check_snake_case(cx, "variable", param_name); diff --git a/src/librustc_lint/passes.rs b/src/librustc_lint/passes.rs index 813be2a032f8b..ace154714458e 100644 --- a/src/librustc_lint/passes.rs +++ b/src/librustc_lint/passes.rs @@ -198,7 +198,7 @@ macro_rules! early_lint_methods { fn check_path(a: &ast::Path, b: ast::NodeId); fn check_attribute(a: &ast::Attribute); fn check_mac_def(a: &ast::MacroDef, b: ast::NodeId); - fn check_mac(a: &ast::Mac); + fn check_mac(a: &ast::MacCall); /// Called when entering a syntax node that can have lint attributes such /// as `#[allow(...)]`. Called with *all* the attributes of that node. diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 86d93612e993b..fcd50001cb3a9 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -165,7 +165,7 @@ fn report_bin_hex_error( let mut err = lint.build(&format!("literal out of range for {}", t)); err.note(&format!( "the literal `{}` (decimal `{}`) does not fit into \ - an `{}` and will become `{}{}`", + the type `{}` and will become `{}{}`", repr_str, val, t, actually, t )); if let Some(sugg_ty) = get_type_suggestion(&cx.tables.node_type(expr.hir_id), val, negative) @@ -242,7 +242,7 @@ fn lint_int_literal<'a, 'tcx>( v: u128, ) { let int_type = t.normalize(cx.sess().target.ptr_width); - let (_, max) = int_ty_range(int_type); + let (min, max) = int_ty_range(int_type); let max = max as u128; let negative = type_limits.negated_expr_id == e.hir_id; @@ -267,7 +267,18 @@ fn lint_int_literal<'a, 'tcx>( } cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| { - lint.build(&format!("literal out of range for `{}`", t.name_str())).emit() + lint.build(&format!("literal out of range for `{}`", t.name_str())) + .note(&format!( + "the literal `{}` does not fit into the type `{}` whose range is `{}..={}`", + cx.sess() + .source_map() + .span_to_snippet(lit.span) + .expect("must get snippet from literal"), + t.name_str(), + min, + max, + )) + .emit(); }); } } @@ -320,7 +331,18 @@ fn lint_uint_literal<'a, 'tcx>( return; } cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| { - lint.build(&format!("literal out of range for `{}`", t.name_str())).emit() + lint.build(&format!("literal out of range for `{}`", t.name_str())) + .note(&format!( + "the literal `{}` does not fit into the type `{}` whose range is `{}..={}`", + cx.sess() + .source_map() + .span_to_snippet(lit.span) + .expect("must get snippet from literal"), + t.name_str(), + min, + max, + )) + .emit() }); } } @@ -352,7 +374,17 @@ fn lint_literal<'a, 'tcx>( }; if is_infinite == Ok(true) { cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| { - lint.build(&format!("literal out of range for `{}`", t.name_str())).emit() + lint.build(&format!("literal out of range for `{}`", t.name_str())) + .note(&format!( + "the literal `{}` does not fit into the type `{}` and will be converted to `std::{}::INFINITY`", + cx.sess() + .source_map() + .span_to_snippet(lit.span) + .expect("must get snippet from literal"), + t.name_str(), + t.name_str(), + )) + .emit(); }); } } @@ -998,10 +1030,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences { let ty = cx.tcx.erase_regions(&t); let layout = match cx.layout_of(ty) { Ok(layout) => layout, - Err(ty::layout::LayoutError::Unknown(_)) => return, - Err(err @ ty::layout::LayoutError::SizeOverflow(_)) => { - bug!("failed to get layout for `{}`: {}", t, err); - } + Err(ty::layout::LayoutError::Unknown(_)) + | Err(ty::layout::LayoutError::SizeOverflow(_)) => return, }; let (variants, tag) = match layout.variants { layout::Variants::Multiple { diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 49d05819c5ec9..b5826d6a5efa6 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -124,7 +124,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { descr_post: &str, plural_len: usize, ) -> bool { - if ty.is_unit() || cx.tcx.is_ty_uninhabited_from(cx.tcx.parent_module(expr.hir_id), ty) + if ty.is_unit() + || cx.tcx.is_ty_uninhabited_from( + cx.tcx.parent_module(expr.hir_id).to_def_id(), + ty, + cx.param_env, + ) { return true; } @@ -538,7 +543,7 @@ impl EarlyLintPass for UnusedParens { // Do not lint on `(..)` as that will result in the other arms being useless. Paren(_) // The other cases do not contain sub-patterns. - | Wild | Rest | Lit(..) | Mac(..) | Range(..) | Ident(.., None) | Path(..) => return, + | Wild | Rest | Lit(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) => {}, // These are list-like patterns; parens can always be removed. TupleStruct(_, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps { self.check_unused_parens_pat(cx, p, false, false); diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 9b4f03b3fb64b..fcaeaf2e4b07d 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -151,6 +151,7 @@ fn main() { if env::var_os("LLVM_NDEBUG").is_some() { cfg.define("NDEBUG", None); + cfg.debug(false); } build_helper::rerun_if_changed_anything_in_dir(Path::new("../rustllvm")); diff --git a/src/librustc_macros/src/query.rs b/src/librustc_macros/src/query.rs index 56b7be2f7e2d5..e7005f2f5ba77 100644 --- a/src/librustc_macros/src/query.rs +++ b/src/librustc_macros/src/query.rs @@ -429,14 +429,14 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { }); try_load_from_on_disk_cache_stream.extend(quote! { - DepKind::#name => { - if <#arg as DepNodeParams>::CAN_RECONSTRUCT_QUERY_KEY { + ::rustc::dep_graph::DepKind::#name => { + if <#arg as DepNodeParams>>::CAN_RECONSTRUCT_QUERY_KEY { debug_assert!($tcx.dep_graph .node_color($dep_node) .map(|c| c.is_green()) .unwrap_or(false)); - let key = <#arg as DepNodeParams>::recover($tcx, $dep_node).unwrap(); + let key = <#arg as DepNodeParams>>::recover($tcx, $dep_node).unwrap(); if queries::#name::cache_on_disk($tcx, key, None) { let _ = $tcx.#name(key); } @@ -486,9 +486,9 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { // Add a match arm to force the query given the dep node dep_node_force_stream.extend(quote! { - DepKind::#name => { - if <#arg as DepNodeParams>::CAN_RECONSTRUCT_QUERY_KEY { - if let Some(key) = <#arg as DepNodeParams>::recover($tcx, $dep_node) { + ::rustc::dep_graph::DepKind::#name => { + if <#arg as DepNodeParams>>::CAN_RECONSTRUCT_QUERY_KEY { + if let Some(key) = <#arg as DepNodeParams>>::recover($tcx, $dep_node) { $tcx.force_query::>( key, DUMMY_SP, @@ -509,7 +509,7 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { } dep_node_force_stream.extend(quote! { - DepKind::Null => { + ::rustc::dep_graph::DepKind::Null => { bug!("Cannot force dep node: {:?}", $dep_node) } }); diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml index a8e308c5c9e87..088cba83ef998 100644 --- a/src/librustc_metadata/Cargo.toml +++ b/src/librustc_metadata/Cargo.toml @@ -26,6 +26,7 @@ stable_deref_trait = "1.0.0" rustc_ast = { path = "../librustc_ast" } rustc_expand = { path = "../librustc_expand" } rustc_span = { path = "../librustc_span" } +rustc_session = { path = "../librustc_session" } [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 18b4c9ad5044c..a807fa6b8d466 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -3,22 +3,22 @@ use crate::locator::{CrateLocator, CratePaths}; use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob}; -use rustc::hir::map::Definitions; use rustc::middle::cstore::DepKind; use rustc::middle::cstore::{CrateSource, ExternCrate, ExternCrateSource, MetadataLoaderDyn}; -use rustc::session::config; -use rustc::session::search_paths::PathKind; -use rustc::session::{CrateDisambiguator, Session}; use rustc::ty::TyCtxt; -use rustc_ast::ast; -use rustc_ast::attr; use rustc_ast::expand::allocator::{global_allocator_spans, AllocatorKind}; +use rustc_ast::{ast, attr}; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::Lrc; use rustc_errors::struct_span_err; use rustc_expand::base::SyntaxExtension; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; +use rustc_hir::definitions::Definitions; use rustc_index::vec::IndexVec; +use rustc_session::config; +use rustc_session::output::validate_crate_name; +use rustc_session::search_paths::PathKind; +use rustc_session::{CrateDisambiguator, Session}; use rustc_span::edition::Edition; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -265,7 +265,7 @@ impl<'a> CrateLoader<'a> { ret = Some(cnum); } }); - return ret; + ret } fn verify_no_symbol_conflicts(&self, span: Span, root: &CrateRoot<'_>) { @@ -853,11 +853,7 @@ impl<'a> CrateLoader<'a> { ); let name = match orig_name { Some(orig_name) => { - crate::validate_crate_name( - Some(self.sess), - &orig_name.as_str(), - Some(item.span), - ); + validate_crate_name(Some(self.sess), &orig_name.as_str(), Some(item.span)); orig_name } None => item.ident.name, @@ -871,11 +867,11 @@ impl<'a> CrateLoader<'a> { let cnum = self.resolve_crate(name, item.span, dep_kind, None); let def_id = definitions.opt_local_def_id(item.id).unwrap(); - let path_len = definitions.def_path(def_id.index).data.len(); + let path_len = definitions.def_path(def_id).data.len(); self.update_extern_crate( cnum, ExternCrate { - src: ExternCrateSource::Extern(def_id), + src: ExternCrateSource::Extern(def_id.to_def_id()), span: item.span, path_len, dependency_of: LOCAL_CRATE, diff --git a/src/librustc_metadata/dependency_format.rs b/src/librustc_metadata/dependency_format.rs index 9e71839dbfde6..4cfaf03b7a5f6 100644 --- a/src/librustc_metadata/dependency_format.rs +++ b/src/librustc_metadata/dependency_format.rs @@ -56,10 +56,10 @@ use crate::creader::CStore; use rustc::middle::cstore::LinkagePreference::{self, RequireDynamic, RequireStatic}; use rustc::middle::cstore::{self, DepKind}; use rustc::middle::dependency_format::{Dependencies, DependencyList, Linkage}; -use rustc::session::config; use rustc::ty::TyCtxt; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::CrateNum; +use rustc_session::config; use rustc_target::spec::PanicStrategy; crate fn calculate(tcx: TyCtxt<'_>) -> Dependencies { @@ -97,7 +97,9 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: config::CrateType) -> DependencyList { // If the global prefer_dynamic switch is turned off, or the final // executable will be statically linked, prefer static crate linkage. - config::CrateType::Executable if !sess.opts.cg.prefer_dynamic || sess.crt_static() => { + config::CrateType::Executable + if !sess.opts.cg.prefer_dynamic || sess.crt_static(Some(ty)) => + { Linkage::Static } config::CrateType::Executable => Linkage::Dynamic, @@ -129,7 +131,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: config::CrateType) -> DependencyList { // If any are not found, generate some nice pretty errors. if ty == config::CrateType::Staticlib || (ty == config::CrateType::Executable - && sess.crt_static() + && sess.crt_static(Some(ty)) && !sess.target.target.options.crt_static_allows_dylibs) { for &cnum in tcx.crates().iter() { diff --git a/src/librustc_metadata/dynamic_lib.rs b/src/librustc_metadata/dynamic_lib.rs index f04d0239d4923..3e78a5852354f 100644 --- a/src/librustc_metadata/dynamic_lib.rs +++ b/src/librustc_metadata/dynamic_lib.rs @@ -94,14 +94,12 @@ mod dl { let result = f(); let last_error = libc::dlerror() as *const _; - let ret = if ptr::null() == last_error { + if ptr::null() == last_error { Ok(result) } else { let s = CStr::from_ptr(last_error).to_bytes(); Err(str::from_utf8(s).unwrap().to_owned()) - }; - - ret + } } } diff --git a/src/librustc_metadata/foreign_modules.rs b/src/librustc_metadata/foreign_modules.rs index fc988ec15cee9..60b8239a82155 100644 --- a/src/librustc_metadata/foreign_modules.rs +++ b/src/librustc_metadata/foreign_modules.rs @@ -6,7 +6,7 @@ use rustc_hir::itemlikevisit::ItemLikeVisitor; crate fn collect(tcx: TyCtxt<'_>) -> Vec { let mut collector = Collector { tcx, modules: Vec::new() }; tcx.hir().krate().visit_all_item_likes(&mut collector); - return collector.modules; + collector.modules } struct Collector<'tcx> { diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index d4cc3c32616ac..2993aed2f8ab4 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -29,37 +29,3 @@ mod rmeta; pub mod creader; pub mod dynamic_lib; pub mod locator; - -pub fn validate_crate_name( - sess: Option<&rustc::session::Session>, - s: &str, - sp: Option, -) { - let mut err_count = 0; - { - let mut say = |s: &str| { - match (sp, sess) { - (_, None) => bug!("{}", s), - (Some(sp), Some(sess)) => sess.span_err(sp, s), - (None, Some(sess)) => sess.err(s), - } - err_count += 1; - }; - if s.is_empty() { - say("crate name must not be empty"); - } - for c in s.chars() { - if c.is_alphanumeric() { - continue; - } - if c == '_' { - continue; - } - say(&format!("invalid character `{}` in crate name: `{}`", c, s)); - } - } - - if err_count > 0 { - sess.unwrap().abort_if_errors(); - } -} diff --git a/src/librustc_metadata/link_args.rs b/src/librustc_metadata/link_args.rs index 8d018b9bb94dd..56b26efe5bf1e 100644 --- a/src/librustc_metadata/link_args.rs +++ b/src/librustc_metadata/link_args.rs @@ -8,7 +8,7 @@ crate fn collect(tcx: TyCtxt<'_>) -> Vec { let mut collector = Collector { args: Vec::new() }; tcx.hir().krate().visit_all_item_likes(&mut collector); - for attr in tcx.hir().krate().attrs.iter() { + for attr in tcx.hir().krate().item.attrs.iter() { if attr.has_name(sym::link_args) { if let Some(linkarg) = attr.value_str() { collector.add_link_args(&linkarg.as_str()); @@ -16,7 +16,7 @@ crate fn collect(tcx: TyCtxt<'_>) -> Vec { } } - return collector.args; + collector.args } struct Collector { diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index efa259d0c4e0d..c1a95c094b10c 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -216,13 +216,13 @@ use crate::creader::Library; use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER}; use rustc::middle::cstore::{CrateSource, MetadataLoader}; -use rustc::session::filesearch::{FileDoesntMatch, FileMatches, FileSearch}; -use rustc::session::search_paths::PathKind; -use rustc::session::{config, CrateDisambiguator, Session}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::MetadataRef; use rustc_errors::{struct_span_err, DiagnosticBuilder}; +use rustc_session::filesearch::{FileDoesntMatch, FileMatches, FileSearch}; +use rustc_session::search_paths::PathKind; +use rustc_session::{config, CrateDisambiguator, Session}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use rustc_target::spec::{Target, TargetTriple}; @@ -327,7 +327,7 @@ impl<'a> CrateLocator<'a> { .into_iter() .filter_map(|entry| entry.files()) .flatten() - .map(|location| PathBuf::from(location)) + .map(PathBuf::from) .collect() } else { // SVH being specified means this is a transitive dependency, @@ -949,7 +949,7 @@ fn get_metadata_section( let start = Instant::now(); let ret = get_metadata_section_imp(target, flavor, filename, loader); info!("reading {:?} => {:?}", filename.file_name().unwrap(), start.elapsed()); - return ret; + ret } /// A trivial wrapper for `Mmap` that implements `StableDeref`. diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs index 2fa9cb099dd51..19d2d620f58a7 100644 --- a/src/librustc_metadata/native_libs.rs +++ b/src/librustc_metadata/native_libs.rs @@ -1,12 +1,12 @@ use rustc::middle::cstore::{self, NativeLibrary}; -use rustc::session::parse::feature_err; -use rustc::session::Session; use rustc::ty::TyCtxt; use rustc_attr as attr; use rustc_data_structures::fx::FxHashSet; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::itemlikevisit::ItemLikeVisitor; +use rustc_session::parse::feature_err; +use rustc_session::Session; use rustc_span::source_map::Span; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_target::spec::abi::Abi; @@ -15,7 +15,7 @@ crate fn collect(tcx: TyCtxt<'_>) -> Vec { let mut collector = Collector { tcx, libs: Vec::new() }; tcx.hir().krate().visit_all_item_likes(&mut collector); collector.process_command_line(); - return collector.libs; + collector.libs } crate fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool { diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index 1d8eb0cde468a..4520df588996e 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -4,46 +4,45 @@ use crate::creader::CrateMetadataRef; use crate::rmeta::table::{FixedSizeEncoding, Table}; use crate::rmeta::*; -use rustc::dep_graph::{self, DepNodeIndex}; +use rustc::dep_graph::{self, DepNode, DepNodeExt, DepNodeIndex}; use rustc::hir::exports::Export; -use rustc::hir::map::definitions::DefPathTable; -use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash}; use rustc::middle::cstore::{CrateSource, ExternCrate}; use rustc::middle::cstore::{ForeignModule, LinkagePreference, NativeLibrary}; use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc::middle::lang_items; use rustc::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use rustc::mir::{self, interpret, BodyAndCache, Promoted}; -use rustc::session::Session; use rustc::ty::codec::TyDecoder; use rustc::ty::{self, Ty, TyCtxt}; use rustc::util::common::record_time; +use rustc_ast::ast::{self, Ident}; +use rustc_attr as attr; use rustc_data_structures::captures::Captures; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{AtomicCell, Lock, LockGuard, Lrc, Once}; +use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; +use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, ProcMacroDerive}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::definitions::DefPathTable; +use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash}; use rustc_index::vec::{Idx, IndexVec}; +use rustc_serialize::{opaque, Decodable, Decoder, SpecializedDecoder}; +use rustc_session::Session; +use rustc_span::source_map::{self, respan, Spanned}; +use rustc_span::symbol::{sym, Symbol}; +use rustc_span::{self, hygiene::MacroKind, BytePos, Pos, Span, DUMMY_SP}; +use log::debug; +use proc_macro::bridge::client::ProcMacro; use std::io; use std::mem; use std::num::NonZeroUsize; use std::u32; -use log::debug; -use proc_macro::bridge::client::ProcMacro; -use rustc_ast::ast::{self, Ident}; -use rustc_attr as attr; -use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; -use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, ProcMacroDerive}; -use rustc_serialize::{opaque, Decodable, Decoder, SpecializedDecoder}; -use rustc_span::source_map::{self, respan, Spanned}; -use rustc_span::symbol::{sym, Symbol}; -use rustc_span::{self, hygiene::MacroKind, BytePos, Pos, Span, DUMMY_SP}; - pub use cstore_impl::{provide, provide_extern}; mod cstore_impl; @@ -365,7 +364,7 @@ impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { #[inline] fn specialized_decode(&mut self) -> Result { - self.specialized_decode().map(|i| LocalDefId::from_def_id(i)) + Ok(DefId::decode(self)?.expect_local()) } } @@ -387,7 +386,7 @@ impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { return Ok(DUMMY_SP); } - debug_assert_eq!(tag, TAG_VALID_SPAN); + debug_assert!(tag == TAG_VALID_SPAN_LOCAL || tag == TAG_VALID_SPAN_FOREIGN); let lo = BytePos::decode(self)?; let len = BytePos::decode(self)?; @@ -399,7 +398,68 @@ impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { bug!("Cannot decode Span without Session.") }; - let imported_source_files = self.cdata().imported_source_files(&sess.source_map()); + // There are two possibilities here: + // 1. This is a 'local span', which is located inside a `SourceFile` + // that came from this crate. In this case, we use the source map data + // encoded in this crate. This branch should be taken nearly all of the time. + // 2. This is a 'foreign span', which is located inside a `SourceFile` + // that came from a *different* crate (some crate upstream of the one + // whose metadata we're looking at). For example, consider this dependency graph: + // + // A -> B -> C + // + // Suppose that we're currently compiling crate A, and start deserializing + // metadata from crate B. When we deserialize a Span from crate B's metadata, + // there are two posibilites: + // + // 1. The span references a file from crate B. This makes it a 'local' span, + // which means that we can use crate B's serialized source map information. + // 2. The span references a file from crate C. This makes it a 'foreign' span, + // which means we need to use Crate *C* (not crate B) to determine the source + // map information. We only record source map information for a file in the + // crate that 'owns' it, so deserializing a Span may require us to look at + // a transitive dependency. + // + // When we encode a foreign span, we adjust its 'lo' and 'high' values + // to be based on the *foreign* crate (e.g. crate C), not the crate + // we are writing metadata for (e.g. crate B). This allows us to + // treat the 'local' and 'foreign' cases almost identically during deserialization: + // we can call `imported_source_files` for the proper crate, and binary search + // through the returned slice using our span. + let imported_source_files = if tag == TAG_VALID_SPAN_LOCAL { + self.cdata().imported_source_files(sess.source_map()) + } else { + // FIXME: We don't decode dependencies of proc-macros. + // Remove this once #69976 is merged + if self.cdata().root.is_proc_macro_crate() { + debug!( + "SpecializedDecoder::specialized_decode: skipping span for proc-macro crate {:?}", + self.cdata().cnum + ); + // Decode `CrateNum` as u32 - using `CrateNum::decode` will ICE + // since we don't have `cnum_map` populated. + // This advances the decoder position so that we can continue + // to read metadata. + let _ = u32::decode(self)?; + return Ok(DUMMY_SP); + } + // tag is TAG_VALID_SPAN_FOREIGN, checked by `debug_assert` above + let cnum = CrateNum::decode(self)?; + debug!( + "SpecializedDecoder::specialized_decode: loading source files from cnum {:?}", + cnum + ); + + // Decoding 'foreign' spans should be rare enough that it's + // not worth it to maintain a per-CrateNum cache for `last_source_file_index`. + // We just set it to 0, to ensure that we don't try to access something out + // of bounds for our initial 'guess' + self.last_source_file_index = 0; + + let foreign_data = self.cdata().cstore.get_crate_data(cnum); + foreign_data.imported_source_files(sess.source_map()) + }; + let source_file = { // Optimize for the case that most spans within a translated item // originate from the same source_file. @@ -413,16 +473,32 @@ impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { .binary_search_by_key(&lo, |source_file| source_file.original_start_pos) .unwrap_or_else(|index| index - 1); - self.last_source_file_index = index; + // Don't try to cache the index for foreign spans, + // as this would require a map from CrateNums to indices + if tag == TAG_VALID_SPAN_LOCAL { + self.last_source_file_index = index; + } &imported_source_files[index] } }; // Make sure our binary search above is correct. - debug_assert!(lo >= source_file.original_start_pos && lo <= source_file.original_end_pos); + debug_assert!( + lo >= source_file.original_start_pos && lo <= source_file.original_end_pos, + "Bad binary search: lo={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}", + lo, + source_file.original_start_pos, + source_file.original_end_pos + ); // Make sure we correctly filtered out invalid spans during encoding - debug_assert!(hi >= source_file.original_start_pos && hi <= source_file.original_end_pos); + debug_assert!( + hi >= source_file.original_start_pos && hi <= source_file.original_end_pos, + "Bad binary search: hi={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}", + hi, + source_file.original_start_pos, + source_file.original_end_pos + ); let lo = (lo + source_file.translated_source_file.start_pos) - source_file.original_start_pos; @@ -433,14 +509,6 @@ impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { } } -impl SpecializedDecoder for DecodeContext<'_, '_> { - fn specialized_decode(&mut self) -> Result { - // FIXME(jseyfried): intercrate hygiene - - Ok(Ident::with_dummy_span(Symbol::decode(self)?)) - } -} - impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result { Fingerprint::decode_opaque(&mut self.opaque) @@ -505,7 +573,7 @@ impl EntryKind { EntryKind::Struct(_, _) => DefKind::Struct, EntryKind::Union(_, _) => DefKind::Union, EntryKind::Fn(_) | EntryKind::ForeignFn(_) => DefKind::Fn, - EntryKind::Method(_) => DefKind::AssocFn, + EntryKind::AssocFn(_) => DefKind::AssocFn, EntryKind::Type => DefKind::TyAlias, EntryKind::TypeParam => DefKind::TyParam, EntryKind::ConstParam => DefKind::ConstParam, @@ -587,15 +655,27 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { &self.raw_proc_macros.unwrap()[pos] } - fn item_name(&self, item_index: DefIndex) -> Symbol { + fn item_ident(&self, item_index: DefIndex, sess: &Session) -> Ident { if !self.is_proc_macro(item_index) { - self.def_key(item_index) + let name = self + .def_key(item_index) .disambiguated_data .data .get_opt_name() - .expect("no name in item_name") + .expect("no name in item_ident"); + let span = self + .root + .per_def + .ident_span + .get(self, item_index) + .map(|data| data.decode((self, sess))) + .unwrap_or_else(|| panic!("Missing ident span for {:?} ({:?})", name, item_index)); + Ident::new(name, span) } else { - Symbol::intern(self.raw_proc_macro(item_index).name()) + Ident::new( + Symbol::intern(self.raw_proc_macro(item_index).name()), + self.get_span(item_index, sess), + ) } } @@ -651,6 +731,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { data.paren_sugar, data.has_auto_impl, data.is_marker, + data.specialization_kind, self.def_path_table.def_path_hash(item_id), ) } @@ -660,6 +741,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { false, false, false, + ty::trait_def::TraitSpecializationKind::None, self.def_path_table.def_path_hash(item_id), ), _ => bug!("def-index does not refer to trait or trait alias"), @@ -672,6 +754,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { kind: &EntryKind, index: DefIndex, parent_did: DefId, + sess: &Session, ) -> ty::VariantDef { let data = match kind { EntryKind::Variant(data) | EntryKind::Struct(data, _) | EntryKind::Union(data, _) => { @@ -693,7 +776,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { ty::VariantDef::new( tcx, - Ident::with_dummy_span(self.item_name(index)), + self.item_ident(index, sess), variant_did, ctor_did, data.discr, @@ -705,7 +788,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .decode(self) .map(|index| ty::FieldDef { did: self.local_def_id(index), - ident: Ident::with_dummy_span(self.item_name(index)), + ident: self.item_ident(index, sess), vis: self.get_visibility(index), }) .collect(), @@ -734,10 +817,10 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .get(self, item_id) .unwrap_or(Lazy::empty()) .decode(self) - .map(|index| self.get_variant(tcx, &self.kind(index), index, did)) + .map(|index| self.get_variant(tcx, &self.kind(index), index, did, tcx.sess)) .collect() } else { - std::iter::once(self.get_variant(tcx, &kind, item_id, did)).collect() + std::iter::once(self.get_variant(tcx, &kind, item_id, did, tcx.sess)).collect() }; tcx.alloc_adt_def(did, adt_kind, variants, repr) @@ -929,7 +1012,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { if let Some(kind) = self.def_kind(child_index) { callback(Export { res: Res::Def(kind, self.local_def_id(child_index)), - ident: Ident::with_dummy_span(self.item_name(child_index)), + ident: self.item_ident(child_index, sess), vis: self.get_visibility(child_index), span: self .root @@ -950,10 +1033,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { let def_key = self.def_key(child_index); let span = self.get_span(child_index, sess); - if let (Some(kind), Some(name)) = - (self.def_kind(child_index), def_key.disambiguated_data.data.get_opt_name()) - { - let ident = Ident::with_dummy_span(name); + if let (Some(kind), true) = ( + self.def_kind(child_index), + def_key.disambiguated_data.data.get_opt_name().is_some(), + ) { + let ident = self.item_ident(child_index, sess); let vis = self.get_visibility(child_index); let def_id = self.local_def_id(child_index); let res = Res::Def(kind, def_id); @@ -1060,14 +1144,14 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } } - fn get_associated_item(&self, id: DefIndex) -> ty::AssocItem { + fn get_associated_item(&self, id: DefIndex, sess: &Session) -> ty::AssocItem { let def_key = self.def_key(id); let parent = self.local_def_id(def_key.parent.unwrap()); - let name = def_key.disambiguated_data.data.get_opt_name().unwrap(); + let ident = self.item_ident(id, sess); let (kind, container, has_self) = match self.kind(id) { EntryKind::AssocConst(container, _, _) => (ty::AssocKind::Const, container, false), - EntryKind::Method(data) => { + EntryKind::AssocFn(data) => { let data = data.decode(self); (ty::AssocKind::Method, data.container, data.has_self) } @@ -1077,7 +1161,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { }; ty::AssocItem { - ident: Ident::with_dummy_span(name), + ident, kind, vis: self.get_visibility(id), defaultness: container.defaultness(), @@ -1141,7 +1225,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .get(self, id) .unwrap_or(Lazy::empty()) .decode(self) - .map(|index| respan(self.get_span(index, sess), self.item_name(index))) + .map(|index| respan(self.get_span(index, sess), self.item_ident(index, sess).name)) .collect() } @@ -1249,7 +1333,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { fn get_fn_param_names(&self, id: DefIndex) -> Vec { let param_names = match self.kind(id) { EntryKind::Fn(data) | EntryKind::ForeignFn(data) => data.decode(self).param_names, - EntryKind::Method(data) => data.decode(self).fn_data.param_names, + EntryKind::AssocFn(data) => data.decode(self).fn_data.param_names, _ => Lazy::empty(), }; param_names.decode(self).collect() @@ -1286,7 +1370,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { // don't serialize constness for tuple variant and tuple struct constructors. fn is_const_fn_raw(&self, id: DefIndex) -> bool { let constness = match self.kind(id) { - EntryKind::Method(data) => data.decode(self).fn_data.constness, + EntryKind::AssocFn(data) => data.decode(self).fn_data.constness, EntryKind::Fn(data) => data.decode(self).constness, // Some intrinsics can be const fn. While we could recompute this (at least until we // stop having hardcoded whitelists and move to stability attributes), it seems cleaner @@ -1301,7 +1385,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { fn asyncness(&self, id: DefIndex) -> hir::IsAsync { match self.kind(id) { EntryKind::Fn(data) => data.decode(self).asyncness, - EntryKind::Method(data) => data.decode(self).fn_data.asyncness, + EntryKind::AssocFn(data) => data.decode(self).fn_data.asyncness, EntryKind::ForeignFn(data) => data.decode(self).asyncness, _ => bug!("asyncness: expected function kind"), } @@ -1424,14 +1508,16 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { let local_version = local_source_map.new_imported_source_file( name, name_was_remapped, - self.cnum.as_u32(), src_hash, name_hash, source_length, + self.cnum, lines, multibyte_chars, non_narrow_chars, normalized_pos, + start_pos, + end_pos, ); debug!( "CrateMetaData::imported_source_files alloc \ @@ -1607,7 +1693,8 @@ impl CrateMetadata { // would always write the same value. let def_path_hash = self.def_path_hash(CRATE_DEF_INDEX); - let dep_node = def_path_hash.to_dep_node(dep_graph::DepKind::CrateMetadata); + let dep_node = + DepNode::from_def_path_hash(def_path_hash, dep_graph::DepKind::CrateMetadata); dep_node_index = tcx.dep_graph.dep_node_index_of(&dep_node); assert!(dep_node_index != DepNodeIndex::INVALID); diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs index dcbfed8972c42..b9f1dd1663eee 100644 --- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs +++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs @@ -5,23 +5,21 @@ use crate::native_libs; use crate::rmeta::{self, encoder}; use rustc::hir::exports::Export; -use rustc::hir::map::definitions::DefPathTable; -use rustc::hir::map::{DefKey, DefPath, DefPathHash}; use rustc::middle::cstore::{CrateSource, CrateStore, EncodedMetadata, NativeLibraryKind}; use rustc::middle::exported_symbols::ExportedSymbol; use rustc::middle::stability::DeprecationEntry; -use rustc::session::{CrateDisambiguator, Session}; use rustc::ty::query::Providers; use rustc::ty::query::QueryConfig; use rustc::ty::{self, TyCtxt}; use rustc_ast::ast; use rustc_ast::attr; use rustc_ast::expand::allocator::AllocatorKind; -use rustc_ast::ptr::P; -use rustc_ast::tokenstream::DelimSpan; use rustc_data_structures::svh::Svh; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::definitions::DefPathTable; +use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; +use rustc_session::{CrateDisambiguator, Session}; use rustc_span::source_map::{self, Span, Spanned}; use rustc_span::symbol::Symbol; @@ -112,7 +110,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, |child| result.push(child.res.def_id()), tcx.sess); tcx.arena.alloc_slice(&result) } - associated_item => { cdata.get_associated_item(def_id.index) } + associated_item => { cdata.get_associated_item(def_id.index, tcx.sess) } impl_trait_ref => { cdata.get_impl_trait(def_id.index, tcx) } impl_polarity => { cdata.get_impl_polarity(def_id.index) } coerce_unsized_info => { @@ -142,7 +140,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, cdata.get_deprecation(def_id.index).map(DeprecationEntry::external) } item_attrs => { cdata.get_item_attrs(def_id.index, tcx.sess) } - // FIXME(#38501) We've skipped a `read` on the `HirBody` of + // FIXME(#38501) We've skipped a `read` on the `hir_owner_nodes` of // a `fn` when encoding, so the dep-tracking wouldn't work. // This is only used by rustdoc anyway, which shouldn't have // incremental recompilation ever enabled. @@ -172,7 +170,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, .iter() .filter_map(|&(exported_symbol, export_level)| { if let ExportedSymbol::NonGeneric(def_id) = exported_symbol { - return Some((def_id, export_level)) + Some((def_id, export_level)) } else { None } @@ -415,8 +413,6 @@ impl CStore { } let span = data.get_span(id.index, sess); - let dspan = DelimSpan::from_single(span); - let rmeta::MacroDef { body, legacy } = data.get_macro(id.index, sess); // Mark the attrs as used let attrs = data.get_item_attrs(id.index, sess); @@ -424,25 +420,21 @@ impl CStore { attr::mark_used(attr); } - let name = data + let ident = data .def_key(id.index) .disambiguated_data .data .get_opt_name() + .map(ast::Ident::with_dummy_span) // FIXME: cross-crate hygiene .expect("no name in load_macro"); - sess.imported_macro_spans.borrow_mut().insert(span, (name.to_string(), span)); LoadedMacro::MacroDef( ast::Item { - // FIXME: cross-crate hygiene - ident: ast::Ident::with_dummy_span(name), + ident, id: ast::DUMMY_NODE_ID, span, attrs: attrs.iter().cloned().collect(), - kind: ast::ItemKind::MacroDef(ast::MacroDef { - body: P(ast::MacArgs::Delimited(dspan, ast::MacDelimiter::Brace, body)), - legacy, - }), + kind: ast::ItemKind::MacroDef(data.get_macro(id.index, sess)), vis: source_map::respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited), tokens: None, }, @@ -450,8 +442,8 @@ impl CStore { ) } - pub fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssocItem { - self.get_crate_data(def.krate).get_associated_item(def.index) + pub fn associated_item_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::AssocItem { + self.get_crate_data(def.krate).get_associated_item(def.index, sess) } pub fn crate_source_untracked(&self, cnum: CrateNum) -> CrateSource { diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index ce62f15f85d93..9718d19281620 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -1,7 +1,7 @@ use crate::rmeta::table::FixedSizeEncoding; use crate::rmeta::*; -use rustc::hir::map::definitions::DefPathTable; +use log::{debug, trace}; use rustc::hir::map::Map; use rustc::middle::cstore::{EncodedMetadata, ForeignModule, LinkagePreference, NativeLibrary}; use rustc::middle::dependency_format::Linkage; @@ -12,33 +12,31 @@ use rustc::traits::specialization_graph; use rustc::ty::codec::{self as ty_codec, TyEncoder}; use rustc::ty::layout::VariantIdx; use rustc::ty::{self, SymbolName, Ty, TyCtxt}; +use rustc_ast::ast::{self, Ident}; +use rustc_ast::attr; use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::stable_hasher::StableHasher; +use rustc_data_structures::sync::{join, Lrc}; +use rustc_hir as hir; use rustc_hir::def::CtorKind; +use rustc_hir::def_id::DefIdSet; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::definitions::DefPathTable; +use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; +use rustc_hir::itemlikevisit::{ItemLikeVisitor, ParItemLikeVisitor}; use rustc_hir::{AnonConst, GenericParamKind}; use rustc_index::vec::Idx; - -use rustc::session::config::{self, CrateType}; -use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::stable_hasher::StableHasher; -use rustc_data_structures::sync::Lrc; use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder}; - -use log::{debug, trace}; -use rustc_ast::ast; -use rustc_ast::attr; +use rustc_session::config::{self, CrateType}; use rustc_span::source_map::Spanned; -use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{self, FileName, SourceFile, Span}; +use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::{self, ExternalSource, FileName, SourceFile, Span}; use std::hash::Hash; use std::num::NonZeroUsize; use std::path::Path; use std::u32; -use rustc_hir as hir; -use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; -use rustc_hir::itemlikevisit::ItemLikeVisitor; - struct EncodeContext<'tcx> { opaque: opaque::Encoder, tcx: TyCtxt<'tcx>, @@ -167,32 +165,61 @@ impl<'tcx> SpecializedEncoder for EncodeContext<'tcx> { return TAG_INVALID_SPAN.encode(self); } - // HACK(eddyb) there's no way to indicate which crate a Span is coming - // from right now, so decoding would fail to find the SourceFile if - // it's not local to the crate the Span is found in. - if self.source_file_cache.is_imported() { - return TAG_INVALID_SPAN.encode(self); - } + // There are two possible cases here: + // 1. This span comes from a 'foreign' crate - e.g. some crate upstream of the + // crate we are writing metadata for. When the metadata for *this* crate gets + // deserialized, the deserializer will need to know which crate it originally came + // from. We use `TAG_VALID_SPAN_FOREIGN` to indicate that a `CrateNum` should + // be deserialized after the rest of the span data, which tells the deserializer + // which crate contains the source map information. + // 2. This span comes from our own crate. No special hamdling is needed - we just + // write `TAG_VALID_SPAN_LOCAL` to let the deserializer know that it should use + // our own source map information. + let (tag, lo, hi) = if self.source_file_cache.is_imported() { + // To simplify deserialization, we 'rebase' this span onto the crate it originally came from + // (the crate that 'owns' the file it references. These rebased 'lo' and 'hi' values + // are relative to the source map information for the 'foreign' crate whose CrateNum + // we write into the metadata. This allows `imported_source_files` to binary + // search through the 'foreign' crate's source map information, using the + // deserialized 'lo' and 'hi' values directly. + // + // All of this logic ensures that the final result of deserialization is a 'normal' + // Span that can be used without any additional trouble. + let external_start_pos = { + // Introduce a new scope so that we drop the 'lock()' temporary + match &*self.source_file_cache.external_src.lock() { + ExternalSource::Foreign { original_start_pos, .. } => *original_start_pos, + src => panic!("Unexpected external source {:?}", src), + } + }; + let lo = (span.lo - self.source_file_cache.start_pos) + external_start_pos; + let hi = (span.hi - self.source_file_cache.start_pos) + external_start_pos; - TAG_VALID_SPAN.encode(self)?; - span.lo.encode(self)?; + (TAG_VALID_SPAN_FOREIGN, lo, hi) + } else { + (TAG_VALID_SPAN_LOCAL, span.lo, span.hi) + }; + + tag.encode(self)?; + lo.encode(self)?; // Encode length which is usually less than span.hi and profits more // from the variable-length integer encoding that we use. - let len = span.hi - span.lo; - len.encode(self) + let len = hi - lo; + len.encode(self)?; + + if tag == TAG_VALID_SPAN_FOREIGN { + // This needs to be two lines to avoid holding the `self.source_file_cache` + // while calling `cnum.encode(self)` + let cnum = self.source_file_cache.cnum; + cnum.encode(self)?; + } + Ok(()) // Don't encode the expansion context. } } -impl SpecializedEncoder for EncodeContext<'tcx> { - fn specialized_encode(&mut self, ident: &Ident) -> Result<(), Self::Error> { - // FIXME(jseyfried): intercrate hygiene - ident.name.encode(self) - } -} - impl<'tcx> SpecializedEncoder for EncodeContext<'tcx> { #[inline] fn specialized_encode(&mut self, def_id: &LocalDefId) -> Result<(), Self::Error> { @@ -331,7 +358,7 @@ impl<'tcx> EncodeContext<'tcx> { fn encode_info_for_items(&mut self) { let krate = self.tcx.hir().krate(); let vis = Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public }; - self.encode_info_for_mod(hir::CRATE_HIR_ID, &krate.module, &krate.attrs, &vis); + self.encode_info_for_mod(hir::CRATE_HIR_ID, &krate.item.module, &krate.item.attrs, &vis); krate.visit_all_item_likes(&mut self.as_deep_visitor()); for macro_def in krate.exported_macros { self.visit_macro_def(macro_def); @@ -434,12 +461,6 @@ impl<'tcx> EncodeContext<'tcx> { let impls = self.encode_impls(); let impl_bytes = self.position() - i; - // Encode exported symbols info. - i = self.position(); - let exported_symbols = self.tcx.exported_symbols(LOCAL_CRATE); - let exported_symbols = self.encode_exported_symbols(&exported_symbols); - let exported_symbols_bytes = self.position() - i; - let tcx = self.tcx; // Encode the items. @@ -480,6 +501,13 @@ impl<'tcx> EncodeContext<'tcx> { let proc_macro_data = self.encode_proc_macros(); let proc_macro_data_bytes = self.position() - i; + // Encode exported symbols info. This is prefetched in `encode_metadata` so we encode + // this last to give the prefetching as much time as possible to complete. + i = self.position(); + let exported_symbols = self.tcx.exported_symbols(LOCAL_CRATE); + let exported_symbols = self.encode_exported_symbols(&exported_symbols); + let exported_symbols_bytes = self.position() - i; + let attrs = tcx.hir().krate_attrs(); let has_default_lib_allocator = attr::contains_name(&attrs, sym::default_lib_allocator); @@ -598,6 +626,7 @@ impl EncodeContext<'tcx> { assert!(f.did.is_local()); f.did.index })); + self.encode_ident_span(def_id, variant.ident); self.encode_stability(def_id); self.encode_deprecation(def_id); self.encode_item_type(def_id); @@ -700,6 +729,7 @@ impl EncodeContext<'tcx> { record!(self.per_def.visibility[def_id] <- field.vis); record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); record!(self.per_def.attributes[def_id] <- variant_data.fields()[field_index].attrs); + self.encode_ident_span(def_id, field.ident); self.encode_stability(def_id); self.encode_deprecation(def_id); self.encode_item_type(def_id); @@ -807,10 +837,10 @@ impl EncodeContext<'tcx> { ty::AssocKind::Method => { let fn_data = if let hir::TraitItemKind::Fn(m_sig, m) = &ast_item.kind { let param_names = match *m { - hir::TraitMethod::Required(ref names) => { + hir::TraitFn::Required(ref names) => { self.encode_fn_param_names(names) } - hir::TraitMethod::Provided(body) => { + hir::TraitFn::Provided(body) => { self.encode_fn_param_names_for_body(body) } }; @@ -822,7 +852,7 @@ impl EncodeContext<'tcx> { } else { bug!() }; - EntryKind::Method(self.lazy(MethodData { + EntryKind::AssocFn(self.lazy(AssocFnData { fn_data, container, has_self: trait_item.method_has_self_argument, @@ -834,6 +864,7 @@ impl EncodeContext<'tcx> { record!(self.per_def.visibility[def_id] <- trait_item.vis); record!(self.per_def.span[def_id] <- ast_item.span); record!(self.per_def.attributes[def_id] <- ast_item.attrs); + self.encode_ident_span(def_id, ast_item.ident); self.encode_stability(def_id); self.encode_const_stability(def_id); self.encode_deprecation(def_id); @@ -855,6 +886,8 @@ impl EncodeContext<'tcx> { self.encode_generics(def_id); self.encode_explicit_predicates(def_id); self.encode_inferred_outlives(def_id); + + // This should be kept in sync with `PrefetchVisitor.visit_trait_item`. self.encode_optimized_mir(def_id); self.encode_promoted_mir(def_id); } @@ -894,7 +927,7 @@ impl EncodeContext<'tcx> { } } ty::AssocKind::Method => { - let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.kind { + let fn_data = if let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind { FnData { asyncness: sig.header.asyncness, constness: sig.header.constness, @@ -903,7 +936,7 @@ impl EncodeContext<'tcx> { } else { bug!() }; - EntryKind::Method(self.lazy(MethodData { + EntryKind::AssocFn(self.lazy(AssocFnData { fn_data, container, has_self: impl_item.method_has_self_argument, @@ -915,6 +948,7 @@ impl EncodeContext<'tcx> { record!(self.per_def.visibility[def_id] <- impl_item.vis); record!(self.per_def.span[def_id] <- ast_item.span); record!(self.per_def.attributes[def_id] <- ast_item.attrs); + self.encode_ident_span(def_id, impl_item.ident); self.encode_stability(def_id); self.encode_const_stability(def_id); self.encode_deprecation(def_id); @@ -926,9 +960,12 @@ impl EncodeContext<'tcx> { self.encode_generics(def_id); self.encode_explicit_predicates(def_id); self.encode_inferred_outlives(def_id); + + // The following part should be kept in sync with `PrefetchVisitor.visit_impl_item`. + let mir = match ast_item.kind { hir::ImplItemKind::Const(..) => true, - hir::ImplItemKind::Method(ref sig, _) => { + hir::ImplItemKind::Fn(ref sig, _) => { let generics = self.tcx.generics_of(def_id); let needs_inline = (generics.requires_monomorphization(self.tcx) || tcx.codegen_fn_attrs(def_id).requests_inline()) @@ -1018,6 +1055,8 @@ impl EncodeContext<'tcx> { debug!("EncodeContext::encode_info_for_item({:?})", def_id); + self.encode_ident_span(def_id, item.ident); + record!(self.per_def.kind[def_id] <- match item.kind { hir::ItemKind::Static(_, hir::Mutability::Mut, _) => EntryKind::MutStatic, hir::ItemKind::Static(_, hir::Mutability::Not, _) => EntryKind::ImmStatic, @@ -1077,12 +1116,13 @@ impl EncodeContext<'tcx> { let polarity = self.tcx.impl_polarity(def_id); let parent = if let Some(trait_ref) = trait_ref { let trait_def = self.tcx.trait_def(trait_ref.def_id); - trait_def.ancestors(self.tcx, def_id).nth(1).and_then(|node| { - match node { - specialization_graph::Node::Impl(parent) => Some(parent), - _ => None, - } - }) + trait_def.ancestors(self.tcx, def_id).ok() + .and_then(|mut an| an.nth(1).and_then(|node| { + match node { + specialization_graph::Node::Impl(parent) => Some(parent), + _ => None, + } + })) } else { None }; @@ -1114,6 +1154,7 @@ impl EncodeContext<'tcx> { paren_sugar: trait_def.paren_sugar, has_auto_impl: self.tcx.trait_is_auto(def_id), is_marker: trait_def.is_marker, + specialization_kind: trait_def.specialization_kind, }; EntryKind::Trait(self.lazy(data)) @@ -1215,6 +1256,8 @@ impl EncodeContext<'tcx> { _ => {} } + // The following part should be kept in sync with `PrefetchVisitor.visit_item`. + let mir = match item.kind { hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => true, hir::ItemKind::Fn(ref sig, ..) => { @@ -1236,13 +1279,11 @@ impl EncodeContext<'tcx> { /// Serialize the text of exported macros fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef<'_>) { let def_id = self.tcx.hir().local_def_id(macro_def.hir_id); - record!(self.per_def.kind[def_id] <- EntryKind::MacroDef(self.lazy(MacroDef { - body: macro_def.body.clone(), - legacy: macro_def.legacy, - }))); + record!(self.per_def.kind[def_id] <- EntryKind::MacroDef(self.lazy(macro_def.ast.clone()))); record!(self.per_def.visibility[def_id] <- ty::Visibility::Public); record!(self.per_def.span[def_id] <- macro_def.span); record!(self.per_def.attributes[def_id] <- macro_def.attrs); + self.encode_ident_span(def_id, macro_def.ident); self.encode_stability(def_id); self.encode_deprecation(def_id); } @@ -1279,7 +1320,7 @@ impl EncodeContext<'tcx> { record!(self.per_def.attributes[def_id] <- &self.tcx.get_attrs(def_id)[..]); self.encode_item_type(def_id); if let ty::Closure(def_id, substs) = ty.kind { - record!(self.per_def.fn_sig[def_id] <- substs.as_closure().sig(def_id, self.tcx)); + record!(self.per_def.fn_sig[def_id] <- substs.as_closure().sig()); } self.encode_generics(def_id); self.encode_optimized_mir(def_id); @@ -1318,7 +1359,7 @@ impl EncodeContext<'tcx> { let is_proc_macro = self.tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro); if is_proc_macro { let tcx = self.tcx; - Some(self.lazy(tcx.hir().krate().proc_macros.iter().map(|p| p.owner))) + Some(self.lazy(tcx.hir().krate().proc_macros.iter().map(|p| p.owner.local_def_index))) } else { None } @@ -1406,8 +1447,8 @@ impl EncodeContext<'tcx> { .into_iter() .map(|(trait_def_id, mut impls)| { // Bring everything into deterministic order for hashing - impls.sort_by_cached_key(|&def_index| { - tcx.hir().definitions().def_path_hash(def_index) + impls.sort_by_cached_key(|&index| { + tcx.hir().definitions().def_path_hash(LocalDefId { local_def_index: index }) }); TraitImpls { @@ -1487,6 +1528,7 @@ impl EncodeContext<'tcx> { ty::Visibility::from_hir(&nitem.vis, nitem.hir_id, self.tcx)); record!(self.per_def.span[def_id] <- nitem.span); record!(self.per_def.attributes[def_id] <- nitem.attrs); + self.encode_ident_span(def_id, nitem.ident); self.encode_stability(def_id); self.encode_const_stability(def_id); self.encode_deprecation(def_id); @@ -1505,8 +1547,8 @@ impl EncodeContext<'tcx> { impl Visitor<'tcx> for EncodeContext<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.tcx.hir()) } fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) { intravisit::walk_expr(self, ex); @@ -1581,6 +1623,10 @@ impl EncodeContext<'tcx> { } } + fn encode_ident_span(&mut self, def_id: DefId, ident: Ident) { + record!(self.per_def.ident_span[def_id] <- ident.span); + } + /// In some cases, along with the item itself, we also /// encode some sub-items. Usually we want some info from the item /// so it's easier to do that here then to wait until we would encounter @@ -1665,6 +1711,70 @@ impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> { } } +/// Used to prefetch queries which will be needed later by metadata encoding. +/// Only a subset of the queries are actually prefetched to keep this code smaller. +struct PrefetchVisitor<'tcx> { + tcx: TyCtxt<'tcx>, + mir_keys: &'tcx DefIdSet, +} + +impl<'tcx> PrefetchVisitor<'tcx> { + fn prefetch_mir(&self, def_id: DefId) { + if self.mir_keys.contains(&def_id) { + self.tcx.optimized_mir(def_id); + self.tcx.promoted_mir(def_id); + } + } +} + +impl<'tcx, 'v> ParItemLikeVisitor<'v> for PrefetchVisitor<'tcx> { + fn visit_item(&self, item: &hir::Item<'_>) { + // This should be kept in sync with `encode_info_for_item`. + let tcx = self.tcx; + match item.kind { + hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => { + self.prefetch_mir(tcx.hir().local_def_id(item.hir_id)) + } + hir::ItemKind::Fn(ref sig, ..) => { + let def_id = tcx.hir().local_def_id(item.hir_id); + let generics = tcx.generics_of(def_id); + let needs_inline = generics.requires_monomorphization(tcx) + || tcx.codegen_fn_attrs(def_id).requests_inline(); + if needs_inline || sig.header.constness == hir::Constness::Const { + self.prefetch_mir(def_id) + } + } + _ => (), + } + } + + fn visit_trait_item(&self, trait_item: &'v hir::TraitItem<'v>) { + // This should be kept in sync with `encode_info_for_trait_item`. + self.prefetch_mir(self.tcx.hir().local_def_id(trait_item.hir_id)); + } + + fn visit_impl_item(&self, impl_item: &'v hir::ImplItem<'v>) { + // This should be kept in sync with `encode_info_for_impl_item`. + let tcx = self.tcx; + match impl_item.kind { + hir::ImplItemKind::Const(..) => { + self.prefetch_mir(tcx.hir().local_def_id(impl_item.hir_id)) + } + hir::ImplItemKind::Fn(ref sig, _) => { + let def_id = tcx.hir().local_def_id(impl_item.hir_id); + let generics = tcx.generics_of(def_id); + let needs_inline = generics.requires_monomorphization(tcx) + || tcx.codegen_fn_attrs(def_id).requests_inline(); + let is_const_fn = sig.header.constness == hir::Constness::Const; + if needs_inline || is_const_fn { + self.prefetch_mir(def_id) + } + } + hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(..) => (), + } + } +} + // NOTE(eddyb) The following comment was preserved for posterity, even // though it's no longer relevant as EBML (which uses nested & tagged // "documents") was replaced with a scheme that can't go out of bounds. @@ -1689,35 +1799,64 @@ impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> { // generated regardless of trailing bytes that end up in it. pub(super) fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { + // Since encoding metadata is not in a query, and nothing is cached, + // there's no need to do dep-graph tracking for any of it. + tcx.dep_graph.assert_ignored(); + + join( + || encode_metadata_impl(tcx), + || { + if tcx.sess.threads() == 1 { + return; + } + // Prefetch some queries used by metadata encoding. + // This is not necessary for correctness, but is only done for performance reasons. + // It can be removed if it turns out to cause trouble or be detrimental to performance. + join( + || { + if !tcx.sess.opts.output_types.should_codegen() { + // We won't emit MIR, so don't prefetch it. + return; + } + tcx.hir().krate().par_visit_all_item_likes(&PrefetchVisitor { + tcx, + mir_keys: tcx.mir_keys(LOCAL_CRATE), + }); + }, + || tcx.exported_symbols(LOCAL_CRATE), + ); + }, + ) + .0 +} + +fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata { let mut encoder = opaque::Encoder::new(vec![]); encoder.emit_raw_bytes(METADATA_HEADER); // Will be filled with the root position after encoding everything. encoder.emit_raw_bytes(&[0, 0, 0, 0]); - // Since encoding metadata is not in a query, and nothing is cached, - // there's no need to do dep-graph tracking for any of it. - let (root, mut result) = tcx.dep_graph.with_ignore(move || { - let mut ecx = EncodeContext { - opaque: encoder, - tcx, - per_def: Default::default(), - lazy_state: LazyState::NoNode, - type_shorthands: Default::default(), - predicate_shorthands: Default::default(), - source_file_cache: tcx.sess.source_map().files()[0].clone(), - interpret_allocs: Default::default(), - interpret_allocs_inverse: Default::default(), - }; - - // Encode the rustc version string in a predictable location. - rustc_version().encode(&mut ecx).unwrap(); - - // Encode all the entries and extra information in the crate, - // culminating in the `CrateRoot` which points to all of it. - let root = ecx.encode_crate_root(); - (root, ecx.opaque.into_inner()) - }); + let mut ecx = EncodeContext { + opaque: encoder, + tcx, + per_def: Default::default(), + lazy_state: LazyState::NoNode, + type_shorthands: Default::default(), + predicate_shorthands: Default::default(), + source_file_cache: tcx.sess.source_map().files()[0].clone(), + interpret_allocs: Default::default(), + interpret_allocs_inverse: Default::default(), + }; + + // Encode the rustc version string in a predictable location. + rustc_version().encode(&mut ecx).unwrap(); + + // Encode all the entries and extra information in the crate, + // culminating in the `CrateRoot` which points to all of it. + let root = ecx.encode_crate_root(); + + let mut result = ecx.opaque.into_inner(); // Encode the root position. let header = METADATA_HEADER.len(); diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs index 89e26b15d502b..57415c0a6070d 100644 --- a/src/librustc_metadata/rmeta/mod.rs +++ b/src/librustc_metadata/rmeta/mod.rs @@ -2,16 +2,12 @@ use decoder::Metadata; use table::{Table, TableBuilder}; use rustc::hir::exports::Export; -use rustc::hir::map; use rustc::middle::cstore::{DepKind, ForeignModule, LinkagePreference, NativeLibrary}; use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc::middle::lang_items; use rustc::mir; -use rustc::session::config::SymbolManglingVersion; -use rustc::session::CrateDisambiguator; use rustc::ty::{self, ReprOptions, Ty}; -use rustc_ast::ast; -use rustc_ast::tokenstream::TokenStream; +use rustc_ast::ast::{self, MacroDef}; use rustc_attr as attr; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::MetadataRef; @@ -20,6 +16,8 @@ use rustc_hir::def::CtorKind; use rustc_hir::def_id::{DefId, DefIndex}; use rustc_index::vec::IndexVec; use rustc_serialize::opaque::Encoder; +use rustc_session::config::SymbolManglingVersion; +use rustc_session::CrateDisambiguator; use rustc_span::edition::Edition; use rustc_span::symbol::Symbol; use rustc_span::{self, Span}; @@ -195,9 +193,8 @@ crate struct CrateRoot<'tcx> { native_libraries: Lazy<[NativeLibrary]>, foreign_modules: Lazy<[ForeignModule]>, source_map: Lazy<[rustc_span::SourceFile]>, - def_path_table: Lazy, + def_path_table: Lazy, impls: Lazy<[TraitImpls]>, - exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]), interpret_alloc_index: Lazy<[u32]>, per_def: LazyPerDefTables<'tcx>, @@ -205,6 +202,8 @@ crate struct CrateRoot<'tcx> { /// The DefIndex's of any proc macros declared by this crate. proc_macro_data: Option>, + exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]), + compiler_builtins: bool, needs_allocator: bool, needs_panic_runtime: bool, @@ -256,6 +255,7 @@ define_per_def_tables! { kind: Table>, visibility: Table>, span: Table>, + ident_span: Table>, attributes: Table>, children: Table>, stability: Table>, @@ -306,7 +306,7 @@ enum EntryKind { Generator(hir::GeneratorKind), Trait(Lazy), Impl(Lazy), - Method(Lazy), + AssocFn(Lazy), AssocType(AssocContainer), AssocOpaqueTy(AssocContainer), AssocConst(AssocContainer, mir::ConstQualifs, Lazy), @@ -323,12 +323,6 @@ struct ModData { reexports: Lazy<[Export]>, } -#[derive(RustcEncodable, RustcDecodable)] -struct MacroDef { - body: TokenStream, - legacy: bool, -} - #[derive(RustcEncodable, RustcDecodable)] struct FnData { asyncness: hir::IsAsync, @@ -350,6 +344,7 @@ struct TraitData { paren_sugar: bool, has_auto_impl: bool, is_marker: bool, + specialization_kind: ty::trait_def::TraitSpecializationKind, } #[derive(RustcEncodable, RustcDecodable)] @@ -399,7 +394,7 @@ impl AssocContainer { } #[derive(RustcEncodable, RustcDecodable)] -struct MethodData { +struct AssocFnData { fn_data: FnData, container: AssocContainer, has_self: bool, @@ -411,5 +406,6 @@ struct GeneratorData<'tcx> { } // Tags used for encoding Spans: -const TAG_VALID_SPAN: u8 = 0; -const TAG_INVALID_SPAN: u8 = 1; +const TAG_VALID_SPAN_LOCAL: u8 = 0; +const TAG_VALID_SPAN_FOREIGN: u8 = 1; +const TAG_INVALID_SPAN: u8 = 2; diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index 1ee581e64aa7e..256a80076b923 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -27,7 +27,9 @@ rustc_infer = { path = "../librustc_infer" } rustc_lexer = { path = "../librustc_lexer" } rustc_macros = { path = "../librustc_macros" } rustc_serialize = { path = "../libserialize", package = "serialize" } +rustc_session = { path = "../librustc_session" } rustc_target = { path = "../librustc_target" } +rustc_trait_selection = { path = "../librustc_trait_selection" } rustc_ast = { path = "../librustc_ast" } rustc_span = { path = "../librustc_span" } rustc_apfloat = { path = "../librustc_apfloat" } diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs index 9d5cf3ec4bec0..9f4f0ce5620b5 100644 --- a/src/librustc_mir/borrow_check/borrow_set.rs +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -273,7 +273,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> { assert_eq!(borrow_data.borrowed_place, *place); } - return self.super_rvalue(rvalue, location); + self.super_rvalue(rvalue, location) } } diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs index 8d4afd2c3b3af..8f18fb4a30ed3 100644 --- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs @@ -10,9 +10,9 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::{AsyncGeneratorKind, GeneratorKind}; use rustc_index::vec::Idx; -use rustc_infer::traits::error_reporting::suggest_constraining_type_param; use rustc_span::source_map::DesugaringKind; use rustc_span::Span; +use rustc_trait_selection::traits::error_reporting::suggest_constraining_type_param; use crate::dataflow::drop_flag_effects; use crate::dataflow::indexes::{MoveOutIndex, MovePathIndex}; @@ -256,14 +256,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { "report_move_out_while_borrowed: location={:?} place={:?} span={:?} borrow={:?}", location, place, span, borrow ); - let value_msg = match self.describe_place(place.as_ref()) { - Some(name) => format!("`{}`", name), - None => "value".to_owned(), - }; - let borrow_msg = match self.describe_place(borrow.borrowed_place.as_ref()) { - Some(name) => format!("`{}`", name), - None => "value".to_owned(), - }; + let value_msg = self.describe_any_place(place.as_ref()); + let borrow_msg = self.describe_any_place(borrow.borrowed_place.as_ref()); let borrow_spans = self.retrieve_borrow_spans(borrow); let borrow_span = borrow_spans.args_or_use(); @@ -271,10 +265,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let move_spans = self.move_spans(place.as_ref(), location); let span = move_spans.args_or_use(); - let mut err = self.cannot_move_when_borrowed( - span, - &self.describe_place(place.as_ref()).unwrap_or_else(|| "_".to_owned()), - ); + let mut err = + self.cannot_move_when_borrowed(span, &self.describe_any_place(place.as_ref())); err.span_label(borrow_span, format!("borrow of {} occurs here", borrow_msg)); err.span_label(span, format!("move out of {} occurs here", value_msg)); @@ -314,16 +306,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut err = self.cannot_use_when_mutably_borrowed( span, - &self.describe_place(place.as_ref()).unwrap_or_else(|| "_".to_owned()), + &self.describe_any_place(place.as_ref()), borrow_span, - &self.describe_place(borrow.borrowed_place.as_ref()).unwrap_or_else(|| "_".to_owned()), + &self.describe_any_place(borrow.borrowed_place.as_ref()), ); borrow_spans.var_span_label(&mut err, { let place = &borrow.borrowed_place; - let desc_place = self.describe_place(place.as_ref()).unwrap_or_else(|| "_".to_owned()); - - format!("borrow occurs due to use of `{}`{}", desc_place, borrow_spans.describe()) + let desc_place = self.describe_any_place(place.as_ref()); + format!("borrow occurs due to use of {}{}", desc_place, borrow_spans.describe()) }); self.explain_why_borrow_contains_point(location, borrow, None) @@ -433,7 +424,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow_spans.var_span_label( &mut err, format!( - "borrow occurs due to use of `{}`{}", + "borrow occurs due to use of {}{}", desc_place, borrow_spans.describe(), ), @@ -511,16 +502,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if issued_spans == borrow_spans { borrow_spans.var_span_label( &mut err, - format!("borrows occur due to use of `{}`{}", desc_place, borrow_spans.describe()), + format!("borrows occur due to use of {}{}", desc_place, borrow_spans.describe()), ); } else { let borrow_place = &issued_borrow.borrowed_place; - let borrow_place_desc = - self.describe_place(borrow_place.as_ref()).unwrap_or_else(|| "_".to_owned()); + let borrow_place_desc = self.describe_any_place(borrow_place.as_ref()); issued_spans.var_span_label( &mut err, format!( - "first borrow occurs due to use of `{}`{}", + "first borrow occurs due to use of {}{}", borrow_place_desc, issued_spans.describe(), ), @@ -529,7 +519,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow_spans.var_span_label( &mut err, format!( - "second borrow occurs due to use of `{}`{}", + "second borrow occurs due to use of {}{}", desc_place, borrow_spans.describe(), ), @@ -538,7 +528,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if union_type_name != "" { err.note(&format!( - "`{}` is a field of the union `{}`, so it overlaps the field `{}`", + "{} is a field of the union `{}`, so it overlaps the field {}", msg_place, union_type_name, msg_borrow, )); } @@ -606,7 +596,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let ty = Place::ty_from(place_base, place_projection, *self.body, self.infcx.tcx).ty; ty.ty_adt_def().filter(|adt| adt.is_union()).map(|_| ty) }; - let describe_place = |place| self.describe_place(place).unwrap_or_else(|| "_".to_owned()); // Start with an empty tuple, so we can use the functions on `Option` to reduce some // code duplication (particularly around returning an empty description in the failure @@ -645,30 +634,25 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .and_then(|(target_base, target_field)| { // With the place of a union and a field access into it, we traverse the second // borrowed place and look for a access to a different field of the same union. - let Place { local, projection } = second_borrowed_place; + let Place { local, ref projection } = *second_borrowed_place; let mut cursor = &projection[..]; while let [proj_base @ .., elem] = cursor { cursor = proj_base; if let ProjectionElem::Field(field, _) = elem { - if let Some(union_ty) = union_ty(*local, proj_base) { + if let Some(union_ty) = union_ty(local, proj_base) { if field != target_field - && *local == target_base.local + && local == target_base.local && proj_base == target_base.projection { - // FIXME when we avoid clone reuse describe_place closure - let describe_base_place = self - .describe_place(PlaceRef { - local: *local, - projection: proj_base, - }) - .unwrap_or_else(|| "_".to_owned()); - return Some(( - describe_base_place, - describe_place(first_borrowed_place.as_ref()), - describe_place(second_borrowed_place.as_ref()), + self.describe_any_place(PlaceRef { + local, + projection: proj_base, + }), + self.describe_any_place(first_borrowed_place.as_ref()), + self.describe_any_place(second_borrowed_place.as_ref()), union_ty.to_string(), )); } @@ -681,7 +665,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // If we didn't find a field access into a union, or both places match, then // only return the description of the first place. ( - describe_place(first_borrowed_place.as_ref()), + self.describe_any_place(first_borrowed_place.as_ref()), "".to_string(), "".to_string(), "".to_string(), @@ -1404,12 +1388,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let loan_spans = self.retrieve_borrow_spans(loan); let loan_span = loan_spans.args_or_use(); + let descr_place = self.describe_any_place(place.as_ref()); if loan.kind == BorrowKind::Shallow { if let Some(section) = self.classify_immutable_section(&loan.assigned_place) { let mut err = self.cannot_mutate_in_immutable_section( span, loan_span, - &self.describe_place(place.as_ref()).unwrap_or_else(|| "_".to_owned()), + &descr_place, section, "assign", ); @@ -1424,11 +1409,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - let mut err = self.cannot_assign_to_borrowed( - span, - loan_span, - &self.describe_place(place.as_ref()).unwrap_or_else(|| "_".to_owned()), - ); + let mut err = self.cannot_assign_to_borrowed(span, loan_span, &descr_place); loan_spans .var_span_label(&mut err, format!("borrow occurs due to use{}", loan_spans.describe())); @@ -1482,15 +1463,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }) | Some(LocalDecl { local_info: LocalInfo::StaticRef { .. }, .. }) | Some(LocalDecl { local_info: LocalInfo::Other, .. }) - | None => (self.describe_place(place.as_ref()), assigned_span), - Some(decl) => (self.describe_place(err_place.as_ref()), decl.source_info.span), + | None => (self.describe_any_place(place.as_ref()), assigned_span), + Some(decl) => (self.describe_any_place(err_place.as_ref()), decl.source_info.span), }; - let mut err = self.cannot_reassign_immutable( - span, - place_description.as_ref().map(AsRef::as_ref).unwrap_or("_"), - from_arg, - ); + let mut err = self.cannot_reassign_immutable(span, &place_description, from_arg); let msg = if from_arg { "cannot assign to immutable argument" } else { @@ -1498,11 +1475,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }; if span != assigned_span { if !from_arg { - let value_msg = match place_description { - Some(name) => format!("`{}`", name), - None => "value".to_owned(), - }; - err.span_label(assigned_span, format!("first assignment to {}", value_msg)); + err.span_label(assigned_span, format!("first assignment to {}", place_description)); } } if let Some(decl) = local_decl { @@ -1682,10 +1655,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // If a closure captured our `target` and then assigned // into a place then we should annotate the closure in // case it ends up being assigned into the return place. - annotated_closure = self.annotate_fn_sig( - *def_id, - self.infcx.closure_sig(*def_id, *substs), - ); + annotated_closure = + self.annotate_fn_sig(*def_id, substs.as_closure().sig()); debug!( "annotate_argument_and_return_for_borrow: \ annotated_closure={:?} assigned_from_local={:?} \ diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs index 7110a4a3058a6..605093d8acad2 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mod.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs @@ -137,8 +137,23 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - /// End-user visible description of `place` if one can be found. If the - /// place is a temporary for instance, None will be returned. + /// End-user visible description of `place` if one can be found. + /// If the place is a temporary for instance, `"value"` will be returned. + pub(super) fn describe_any_place(&self, place_ref: PlaceRef<'tcx>) -> String { + match self.describe_place(place_ref) { + Some(mut descr) => { + // Surround descr with `backticks`. + descr.reserve(2); + descr.insert_str(0, "`"); + descr.push_str("`"); + descr + } + None => "value".to_string(), + } + } + + /// End-user visible description of `place` if one can be found. + /// If the place is a temporary for instance, None will be returned. pub(super) fn describe_place(&self, place_ref: PlaceRef<'tcx>) -> Option { self.describe_place_with_options(place_ref, IncludingDowncast(false)) } diff --git a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs index 9451fee499d36..2cdc1ced0bbea 100644 --- a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs @@ -272,14 +272,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { span: Span, ) -> DiagnosticBuilder<'a> { let description = if place.projection.len() == 1 { - format!("static item `{}`", self.describe_place(place.as_ref()).unwrap()) + format!("static item {}", self.describe_any_place(place.as_ref())) } else { let base_static = PlaceRef { local: place.local, projection: &[ProjectionElem::Deref] }; format!( - "`{:?}` as `{:?}` is a static item", - self.describe_place(place.as_ref()).unwrap(), - self.describe_place(base_static).unwrap(), + "{} as {} is a static item", + self.describe_any_place(place.as_ref()), + self.describe_any_place(base_static), ) }; @@ -333,7 +333,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ty::Closure(def_id, closure_substs) if def_id == self.mir_def_id && upvar_field.is_some() => { - let closure_kind_ty = closure_substs.as_closure().kind_ty(def_id, self.infcx.tcx); + let closure_kind_ty = closure_substs.as_closure().kind_ty(); let closure_kind = closure_kind_ty.to_opt_closure_kind(); let capture_description = match closure_kind { Some(ty::ClosureKind::Fn) => "captured variable in an `Fn` closure", @@ -349,16 +349,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let upvar_name = upvar.name; let upvar_span = self.infcx.tcx.hir().span(upvar_hir_id); - let place_name = self.describe_place(move_place.as_ref()).unwrap(); + let place_name = self.describe_any_place(move_place.as_ref()); - let place_description = if self - .is_upvar_field_projection(move_place.as_ref()) - .is_some() - { - format!("`{}`, a {}", place_name, capture_description) - } else { - format!("`{}`, as `{}` is a {}", place_name, upvar_name, capture_description,) - }; + let place_description = + if self.is_upvar_field_projection(move_place.as_ref()).is_some() { + format!("{}, a {}", place_name, capture_description) + } else { + format!("{}, as `{}` is a {}", place_name, upvar_name, capture_description) + }; debug!( "report: closure_kind_ty={:?} closure_kind={:?} place_description={:?}", @@ -490,17 +488,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { { if pat_snippet.starts_with('&') { let pat_snippet = pat_snippet[1..].trim_start(); - let suggestion; - let to_remove; - if pat_snippet.starts_with("mut") + let (suggestion, to_remove) = if pat_snippet.starts_with("mut") && pat_snippet["mut".len()..].starts_with(rustc_lexer::is_whitespace) { - suggestion = pat_snippet["mut".len()..].trim_start(); - to_remove = "&mut"; + (pat_snippet["mut".len()..].trim_start(), "&mut") } else { - suggestion = pat_snippet; - to_remove = "&"; - } + (pat_snippet, "&") + }; suggestions.push((pat_span, to_remove, suggestion.to_owned())); } } diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs index 5d22ef46c41b1..f224041270dcc 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs @@ -1,9 +1,10 @@ -use rustc::mir::{self, ClearCrossCrate, Local, LocalInfo, Location, ReadOnlyBodyAndCache}; +use rustc::mir::{self, ClearCrossCrate, Local, LocalInfo, Location}; use rustc::mir::{Mutability, Place, PlaceRef, ProjectionElem}; use rustc::ty::{self, Ty, TyCtxt}; use rustc_hir as hir; use rustc_hir::Node; use rustc_index::vec::Idx; +use rustc_span::source_map::DesugaringKind; use rustc_span::symbol::kw; use rustc_span::Span; @@ -168,9 +169,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { borrow_spans.var_span_label( &mut err, format!( - "mutable borrow occurs due to use of `{}` in closure", - // always Some() if the message is printed. - self.describe_place(access_place.as_ref()).unwrap_or_default(), + "mutable borrow occurs due to use of {} in closure", + self.describe_any_place(access_place.as_ref()), ), ); borrow_span @@ -338,10 +338,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { match self.local_names[local] { Some(name) if !local_decl.from_compiler_desugaring() => { - let suggestion = match local_decl.local_info { + let label = match local_decl.local_info { LocalInfo::User(ClearCrossCrate::Set( mir::BindingForm::ImplicitSelf(_), - )) => Some(suggest_ampmut_self(self.infcx.tcx, local_decl)), + )) => { + let (span, suggestion) = + suggest_ampmut_self(self.infcx.tcx, local_decl); + Some((true, span, suggestion)) + } LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var( mir::VarBindingForm { @@ -349,13 +353,38 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { opt_ty_info, .. }, - ))) => Some(suggest_ampmut( - self.infcx.tcx, - self.body, - local, - local_decl, - opt_ty_info, - )), + ))) => { + // check if the RHS is from desugaring + let locations = self.body.find_assignments(local); + let opt_assignment_rhs_span = locations + .first() + .map(|&location| self.body.source_info(location).span); + let opt_desugaring_kind = + opt_assignment_rhs_span.and_then(|span| span.desugaring_kind()); + match opt_desugaring_kind { + // on for loops, RHS points to the iterator part + Some(DesugaringKind::ForLoop) => Some(( + false, + opt_assignment_rhs_span.unwrap(), + format!( + "this iterator yields `{SIGIL}` {DESC}s", + SIGIL = pointer_sigil, + DESC = pointer_desc + ), + )), + // don't create labels for compiler-generated spans + Some(_) => None, + None => { + let (span, suggestion) = suggest_ampmut( + self.infcx.tcx, + local_decl, + opt_assignment_rhs_span, + opt_ty_info, + ); + Some((true, span, suggestion)) + } + } + } LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var( mir::VarBindingForm { @@ -365,7 +394,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ))) => { let pattern_span = local_decl.source_info.span; suggest_ref_mut(self.infcx.tcx, pattern_span) - .map(|replacement| (pattern_span, replacement)) + .map(|replacement| (true, pattern_span, replacement)) } LocalInfo::User(ClearCrossCrate::Clear) => { @@ -375,13 +404,22 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { _ => unreachable!(), }; - if let Some((err_help_span, suggested_code)) = suggestion { - err.span_suggestion( - err_help_span, - &format!("consider changing this to be a mutable {}", pointer_desc), - suggested_code, - Applicability::MachineApplicable, - ); + match label { + Some((true, err_help_span, suggested_code)) => { + err.span_suggestion( + err_help_span, + &format!( + "consider changing this to be a mutable {}", + pointer_desc + ), + suggested_code, + Applicability::MachineApplicable, + ); + } + Some((false, err_label_span, message)) => { + err.span_label(err_label_span, &message); + } + None => {} } err.span_label( span, @@ -485,7 +523,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { })) | Some(hir::Node::ImplItem(hir::ImplItem { ident, - kind: hir::ImplItemKind::Method(sig, _), + kind: hir::ImplItemKind::Fn(sig, _), .. })) => Some( arg_pos @@ -527,7 +565,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }) | hir::Node::ImplItem(hir::ImplItem { ident, - kind: hir::ImplItemKind::Method(sig, _), + kind: hir::ImplItemKind::Fn(sig, _), .. }) => { err.span_label(ident.span, ""); @@ -581,14 +619,11 @@ fn suggest_ampmut_self<'tcx>( // by trying (3.), then (2.) and finally falling back on (1.). fn suggest_ampmut<'tcx>( tcx: TyCtxt<'tcx>, - body: ReadOnlyBodyAndCache<'_, 'tcx>, - local: Local, local_decl: &mir::LocalDecl<'tcx>, + opt_assignment_rhs_span: Option, opt_ty_info: Option, ) -> (Span, String) { - let locations = body.find_assignments(local); - if !locations.is_empty() { - let assignment_rhs_span = body.source_info(locations[0]).span; + if let Some(assignment_rhs_span) = opt_assignment_rhs_span { if let Ok(src) = tcx.sess.source_map().span_to_snippet(assignment_rhs_span) { if let (true, Some(ws_pos)) = (src.starts_with("&'"), src.find(|c: char| -> bool { c.is_whitespace() })) diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs index 8cd75d4a2fd27..93800d2a2b38d 100644 --- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs @@ -4,7 +4,8 @@ use rustc::mir::ConstraintCategory; use rustc::ty::{self, RegionVid, Ty}; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_infer::infer::{ - error_reporting::nice_region_error::NiceRegionError, opaque_types, NLLRegionVariableOrigin, + error_reporting::nice_region_error::NiceRegionError, + error_reporting::unexpected_hidden_region_diagnostic, NLLRegionVariableOrigin, }; use rustc_span::symbol::kw; use rustc_span::Span; @@ -134,11 +135,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { 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) = + if let DefiningTy::Closure(_, substs) = self.regioncx.universal_regions().defining_ty { - return substs.as_closure().kind(def_id, self.infcx.tcx) - == ty::ClosureKind::FnMut; + return substs.as_closure().kind() == ty::ClosureKind::FnMut; } } } @@ -197,7 +197,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id); let named_ty = self.regioncx.name_regions(self.infcx.tcx, hidden_ty); let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region); - opaque_types::unexpected_hidden_region_diagnostic( + unexpected_hidden_region_diagnostic( self.infcx.tcx, Some(region_scope_tree), span, @@ -283,8 +283,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { 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 = self.infcx.tcx.typeck_tables_of(self.mir_def_id); - let nice = NiceRegionError::new_from_span(self.infcx, span, o, f, Some(tables)); + let nice = NiceRegionError::new_from_span(self.infcx, span, o, f); if let Some(diag) = nice.try_report_from_nll() { diag.buffer(&mut self.errors_buffer); return; diff --git a/src/librustc_mir/borrow_check/diagnostics/region_name.rs b/src/librustc_mir/borrow_check/diagnostics/region_name.rs index 01ace74287622..6756f476f6155 100644 --- a/src/librustc_mir/borrow_check/diagnostics/region_name.rs +++ b/src/librustc_mir/borrow_check/diagnostics/region_name.rs @@ -245,7 +245,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { .expect("non-local mir"); let def_ty = self.regioncx.universal_regions().defining_ty; - if let DefiningTy::Closure(def_id, substs) = def_ty { + if let DefiningTy::Closure(_, substs) = def_ty { let args_span = if let hir::ExprKind::Closure(_, _, _, span, _) = tcx.hir().expect_expr(mir_hir_id).kind { @@ -255,7 +255,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { }; let region_name = self.synthesize_region_name(); - let closure_kind_ty = substs.as_closure().kind_ty(def_id, tcx); + let closure_kind_ty = substs.as_closure().kind_ty(); let note = match closure_kind_ty.to_opt_closure_kind() { Some(ty::ClosureKind::Fn) => { "closure implements `Fn`, so references to captured variables \ @@ -292,8 +292,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReEmpty(_) - | ty::ReErased - | ty::ReClosureBound(..) => None, + | ty::ReErased => None, } } @@ -500,7 +499,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { } } - return None; + None } /// We've found an enum/struct/union type with the substitutions @@ -651,7 +650,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { if gen_move.is_some() { " of generator" } else { " of closure" }, ), hir::Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Method(method_sig, _), + kind: hir::ImplItemKind::Fn(method_sig, _), .. }) => (method_sig.decl.output.span(), ""), _ => (self.body.span, ""), diff --git a/src/librustc_mir/borrow_check/diagnostics/var_name.rs b/src/librustc_mir/borrow_check/diagnostics/var_name.rs index 5f3585ce8b119..c4933bedc2271 100644 --- a/src/librustc_mir/borrow_check/diagnostics/var_name.rs +++ b/src/librustc_mir/borrow_check/diagnostics/var_name.rs @@ -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 { let upvar_index = - self.universal_regions().defining_ty.upvar_tys(tcx).position(|upvar_ty| { + self.universal_regions().defining_ty.upvar_tys().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().nth(upvar_index); debug!( "get_upvar_index_for_region: found {:?} in upvar {} which has type {:?}", diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index a61d00b0120cb..6c1901455fda9 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1,7 +1,5 @@ //! This query borrow-checks the MIR to (further) ensure it is not broken. -use rustc::lint::builtin::MUTABLE_BORROW_RESERVATION_CONFLICT; -use rustc::lint::builtin::UNUSED_MUT; use rustc::mir::{ read_only, traversal, Body, BodyAndCache, ClearCrossCrate, Local, Location, Mutability, Operand, Place, PlaceElem, PlaceRef, ReadOnlyBodyAndCache, @@ -11,7 +9,7 @@ use rustc::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKi use rustc::mir::{Terminator, TerminatorKind}; use rustc::ty::query::Providers; use rustc::ty::{self, RegionVid, TyCtxt}; - +use rustc_ast::ast::Name; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::graph::dominators::Dominators; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder}; @@ -20,6 +18,8 @@ use rustc_hir::{def_id::DefId, HirId, Node}; use rustc_index::bit_set::BitSet; use rustc_index::vec::IndexVec; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_session::lint::builtin::{MUTABLE_BORROW_RESERVATION_CONFLICT, UNUSED_MUT}; +use rustc_span::{Span, DUMMY_SP}; use either::Either; use smallvec::SmallVec; @@ -28,9 +28,6 @@ use std::collections::BTreeMap; use std::mem; use std::rc::Rc; -use rustc_ast::ast::Name; -use rustc_span::{Span, DUMMY_SP}; - use crate::dataflow; use crate::dataflow::generic::{Analysis, BorrowckFlowState as Flows, BorrowckResults}; use crate::dataflow::indexes::{BorrowIndex, InitIndex, MoveOutIndex, MovePathIndex}; diff --git a/src/librustc_mir/borrow_check/nll.rs b/src/librustc_mir/borrow_check/nll.rs index ba1b322524e87..077ed49ed2cac 100644 --- a/src/librustc_mir/borrow_check/nll.rs +++ b/src/librustc_mir/borrow_check/nll.rs @@ -272,7 +272,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( // Dump facts if requested. let polonius_output = all_facts.and_then(|all_facts| { if infcx.tcx.sess.opts.debugging_opts.nll_facts { - let def_path = infcx.tcx.hir().def_path(def_id); + let def_path = infcx.tcx.def_path(def_id); let dir_path = PathBuf::from("nll-facts").join(def_path.to_filename_friendly_no_crate()); all_facts.write_to_dir(dir_path, location_table).unwrap(); diff --git a/src/librustc_mir/borrow_check/region_infer/mod.rs b/src/librustc_mir/borrow_check/region_infer/mod.rs index 144f655420b36..c8b0e59ebb117 100644 --- a/src/librustc_mir/borrow_check/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/region_infer/mod.rs @@ -7,6 +7,7 @@ use rustc::mir::{ }; use rustc::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable}; use rustc_data_structures::binary_search_util; +use rustc_data_structures::frozen::Frozen; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::graph::scc::Sccs; use rustc_hir::def_id::DefId; @@ -54,12 +55,12 @@ pub struct RegionInferenceContext<'tcx> { liveness_constraints: LivenessValues, /// The outlives constraints computed by the type-check. - constraints: Rc, + constraints: Frozen, /// 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. - constraint_graph: Rc, + constraint_graph: Frozen, /// The SCC computed from `constraints` and the constraint /// graph. We have an edge from SCC A to SCC B if `A: B`. Used to @@ -112,7 +113,7 @@ pub struct RegionInferenceContext<'tcx> { /// Information about how the universally quantified regions in /// scope on this function relate to one another. - universal_region_relations: Rc>, + universal_region_relations: Frozen>, } /// Each time that `apply_member_constraint` is successful, it appends @@ -242,11 +243,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// /// The `outlives_constraints` and `type_tests` are an initial set /// of constraints produced by the MIR type check. - pub(crate) fn new( + pub(in crate::borrow_check) fn new( var_infos: VarInfos, universal_regions: Rc>, placeholder_indices: Rc, - universal_region_relations: Rc>, + universal_region_relations: Frozen>, outlives_constraints: OutlivesConstraintSet, member_constraints_in: MemberConstraintSet<'tcx, RegionVid>, closure_bounds_mapping: FxHashMap< @@ -263,8 +264,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { .map(|info| RegionDefinition::new(info.universe, info.origin)) .collect(); - let constraints = Rc::new(outlives_constraints); // freeze constraints - let constraint_graph = Rc::new(constraints.graph(definitions.len())); + let constraints = Frozen::freeze(outlives_constraints); + let constraint_graph = Frozen::freeze(constraints.graph(definitions.len())); let fr_static = universal_regions.fr_static; let constraint_sccs = Rc::new(constraints.compute_sccs(&constraint_graph, fr_static)); @@ -939,8 +940,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// inference variables with some region from the closure /// signature -- this is not always possible, so this is a /// fallible process. Presuming we do find a suitable region, we - /// will represent it with a `ReClosureBound`, which is a - /// `RegionKind` variant that can be allocated in the gcx. + /// will use it's *external name*, which will be a `RegionKind` + /// variant that can be used in query responses such as + /// `ReEarlyBound`. fn try_promote_type_test_subject( &self, infcx: &InferCtxt<'_, 'tcx>, @@ -990,14 +992,14 @@ impl<'tcx> RegionInferenceContext<'tcx> { // find an equivalent. let upper_bound = self.non_local_universal_upper_bound(region_vid); if self.region_contains(region_vid, upper_bound) { - tcx.mk_region(ty::ReClosureBound(upper_bound)) + self.definitions[upper_bound].external_name.unwrap_or(r) } else { - // In the case of a failure, use a `ReVar` - // result. This will cause the `lift` later on to - // fail. + // In the case of a failure, use a `ReVar` result. This will + // cause the `has_local_value` later on to return `None`. r } }); + debug!("try_promote_type_test_subject: folded ty = {:?}", ty); // `has_local_value` will only be true if we failed to promote some region. @@ -2028,15 +2030,6 @@ pub trait ClosureRegionRequirementsExt<'tcx> { closure_def_id: DefId, closure_substs: SubstsRef<'tcx>, ) -> Vec>; - - fn subst_closure_mapping( - &self, - tcx: TyCtxt<'tcx>, - closure_mapping: &IndexVec>, - value: &T, - ) -> T - where - T: TypeFoldable<'tcx>; } impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx> { @@ -2093,7 +2086,6 @@ impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx } ClosureOutlivesSubject::Ty(ty) => { - let ty = self.subst_closure_mapping(tcx, closure_mapping, &ty); debug!( "apply_requirements: ty={:?} \ outlived_region={:?} \ @@ -2106,22 +2098,4 @@ impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx }) .collect() } - - fn subst_closure_mapping( - &self, - tcx: TyCtxt<'tcx>, - closure_mapping: &IndexVec>, - value: &T, - ) -> T - where - T: TypeFoldable<'tcx>, - { - tcx.fold_regions(value, &mut false, |r, _depth| { - if let ty::ReClosureBound(vid) = r { - closure_mapping[*vid] - } else { - bug!("subst_closure_mapping: encountered non-closure bound free region {:?}", r) - } - }) - } } diff --git a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs index 15bbc5677dadd..49b4943732847 100644 --- a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs +++ b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs @@ -3,6 +3,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::DefId; use rustc_infer::infer::InferCtxt; use rustc_span::Span; +use rustc_trait_selection::opaque_types::InferCtxtExt; use super::RegionInferenceContext; diff --git a/src/librustc_mir/borrow_check/type_check/free_region_relations.rs b/src/librustc_mir/borrow_check/type_check/free_region_relations.rs index 137216531a369..86951f93f0e7e 100644 --- a/src/librustc_mir/borrow_check/type_check/free_region_relations.rs +++ b/src/librustc_mir/borrow_check/type_check/free_region_relations.rs @@ -1,13 +1,15 @@ use rustc::mir::ConstraintCategory; +use rustc::traits::query::OutlivesBound; use rustc::ty::free_region_map::FreeRegionRelations; use rustc::ty::{self, RegionVid, Ty, TyCtxt}; +use rustc_data_structures::frozen::Frozen; use rustc_data_structures::transitive_relation::TransitiveRelation; use rustc_infer::infer::canonical::QueryRegionConstraints; +use rustc_infer::infer::outlives; use rustc_infer::infer::region_constraints::GenericKind; use rustc_infer::infer::InferCtxt; -use rustc_infer::traits::query::outlives_bounds::{self, OutlivesBound}; -use rustc_infer::traits::query::type_op::{self, TypeOp}; use rustc_span::DUMMY_SP; +use rustc_trait_selection::traits::query::type_op::{self, TypeOp}; use std::rc::Rc; use crate::borrow_check::{ @@ -52,7 +54,7 @@ type RegionBoundPairs<'tcx> = Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>; type NormalizedInputsAndOutput<'tcx> = Vec>; crate struct CreateResult<'tcx> { - crate universal_region_relations: Rc>, + pub(in crate::borrow_check) universal_region_relations: Frozen>, crate region_bound_pairs: RegionBoundPairs<'tcx>, crate normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>, } @@ -266,7 +268,7 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> { // Insert the facts we know from the predicates. Why? Why not. let param_env = self.param_env; - self.add_outlives_bounds(outlives_bounds::explicit_outlives_bounds(param_env)); + self.add_outlives_bounds(outlives::explicit_outlives_bounds(param_env)); // Finally: // - outlives is reflexive, so `'r: 'r` for every region `'r` @@ -297,7 +299,7 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> { } CreateResult { - universal_region_relations: Rc::new(self.relations), + universal_region_relations: Frozen::freeze(self.relations), region_bound_pairs: self.region_bound_pairs, normalized_inputs_and_output, } diff --git a/src/librustc_mir/borrow_check/type_check/input_output.rs b/src/librustc_mir/borrow_check/type_check/input_output.rs index 37cf77b7095c6..f2194c77c8991 100644 --- a/src/librustc_mir/borrow_check/type_check/input_output.rs +++ b/src/librustc_mir/borrow_check/type_check/input_output.rs @@ -64,13 +64,16 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } }; + debug!( + "equate_inputs_and_outputs: normalized_input_tys = {:?}, local_decls = {:?}", + normalized_input_tys, body.local_decls + ); + // Equate expected input tys with those in the MIR. for (&normalized_input_ty, argument_index) in normalized_input_tys.iter().zip(0..) { // In MIR, argument N is stored in local N+1. let local = Local::new(argument_index + 1); - debug!("equate_inputs_and_outputs: normalized_input_ty = {:?}", normalized_input_ty); - let mir_input_ty = body.local_decls[local].ty; let mir_input_span = body.local_decls[local].source_info.span; self.equate_normalized_input_or_output( diff --git a/src/librustc_mir/borrow_check/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/type_check/liveness/trace.rs index baa9d1d212ea7..0c49ee44f9a50 100644 --- a/src/librustc_mir/borrow_check/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/type_check/liveness/trace.rs @@ -3,9 +3,9 @@ use rustc::ty::{Ty, TypeFoldable}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_index::bit_set::HybridBitSet; use rustc_infer::infer::canonical::QueryRegionConstraints; -use rustc_infer::traits::query::dropck_outlives::DropckOutlivesResult; -use rustc_infer::traits::query::type_op::outlives::DropckOutlives; -use rustc_infer::traits::query::type_op::TypeOp; +use rustc_trait_selection::traits::query::dropck_outlives::DropckOutlivesResult; +use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives; +use rustc_trait_selection::traits::query::type_op::TypeOp; use std::rc::Rc; use crate::dataflow::generic::ResultsCursor; diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index ace92949814a7..f94160cc08a19 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -18,23 +18,26 @@ use rustc::ty::{ self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, RegionVid, ToPolyTraitRef, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, }; +use rustc_data_structures::frozen::Frozen; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; 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_infer::infer::canonical::QueryRegionConstraints; -use rustc_infer::infer::opaque_types::GenerateMemberConstraints; use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{ InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin, }; -use rustc_infer::traits::query::type_op; -use rustc_infer::traits::query::type_op::custom::CustomTypeOp; -use rustc_infer::traits::query::{Fallible, NoSolution}; -use rustc_infer::traits::{self, ObligationCause, PredicateObligations}; use rustc_span::{Span, DUMMY_SP}; +use rustc_trait_selection::infer::InferCtxtExt as _; +use rustc_trait_selection::opaque_types::{GenerateMemberConstraints, InferCtxtExt}; +use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; +use rustc_trait_selection::traits::query::type_op; +use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; +use rustc_trait_selection::traits::query::{Fallible, NoSolution}; +use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligations}; use crate::dataflow::generic::ResultsCursor; use crate::dataflow::move_paths::MoveData; @@ -754,21 +757,21 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { ty::Adt(adt_def, substs) if !adt_def.is_enum() => { (&adt_def.variants[VariantIdx::new(0)], substs) } - ty::Closure(def_id, substs) => { - return match substs.as_closure().upvar_tys(def_id, tcx).nth(field.index()) { + ty::Closure(_, substs) => { + return match substs.as_closure().upvar_tys().nth(field.index()) { Some(ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { - field_count: substs.as_closure().upvar_tys(def_id, tcx).count(), + field_count: substs.as_closure().upvar_tys().count(), }), }; } - ty::Generator(def_id, substs, _) => { + ty::Generator(_, substs, _) => { // Only prefix fields (upvars and current state) are // accessible without a variant index. - return match substs.as_generator().prefix_tys(def_id, tcx).nth(field.index()) { + return match substs.as_generator().prefix_tys().nth(field.index()) { Some(ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { - field_count: substs.as_generator().prefix_tys(def_id, tcx).count(), + field_count: substs.as_generator().prefix_tys().count(), }), }; } @@ -828,7 +831,7 @@ struct BorrowCheckContext<'a, 'tcx> { crate struct MirTypeckResults<'tcx> { crate constraints: MirTypeckRegionConstraints<'tcx>, - crate universal_region_relations: Rc>, + pub(in crate::borrow_check) universal_region_relations: Frozen>, crate opaque_type_values: FxHashMap>, } @@ -1943,22 +1946,22 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Err(FieldAccessError::OutOfRange { field_count: variant.fields.len() }) } } - AggregateKind::Closure(def_id, substs) => { - match substs.as_closure().upvar_tys(def_id, tcx).nth(field_index) { + AggregateKind::Closure(_, substs) => { + match substs.as_closure().upvar_tys().nth(field_index) { Some(ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { - field_count: substs.as_closure().upvar_tys(def_id, tcx).count(), + field_count: substs.as_closure().upvar_tys().count(), }), } } - AggregateKind::Generator(def_id, substs, _) => { + AggregateKind::Generator(_, substs, _) => { // It doesn't make sense to look at a field beyond the prefix; // these require a variant index, and are not initialized in // aggregate rvalues. - match substs.as_generator().prefix_tys(def_id, tcx).nth(field_index) { + match substs.as_generator().prefix_tys().nth(field_index) { Some(ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { - field_count: substs.as_generator().prefix_tys(def_id, tcx).count(), + field_count: substs.as_generator().prefix_tys().count(), }), } } @@ -1983,7 +1986,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } Rvalue::Repeat(operand, len) => { - if *len > 1 { + // If the length cannot be evaluated we must assume that the length can be larger + // than 1. + // If the length is larger than 1, the repeat expression will need to copy the + // element, so we require the `Copy` trait. + if len.try_eval_usize(tcx, self.param_env).map_or(true, |len| len > 1) { if let Operand::Move(_) = operand { // While this is located in `nll::typeck` this error is not an NLL error, it's // a required check to make sure that repeated elements implement `Copy`. @@ -2005,7 +2012,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { &traits::Obligation::new( ObligationCause::new( span, - self.tcx().hir().def_index_to_hir_id(self.mir_def_id.index), + self.tcx() + .hir() + .local_def_id_to_hir_id(self.mir_def_id.expect_local()), traits::ObligationCauseCode::RepeatVec(should_suggest), ), self.param_env, @@ -2080,9 +2089,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { CastKind::Pointer(PointerCast::ClosureFnPointer(unsafety)) => { let sig = match op.ty(*body, tcx).kind { - ty::Closure(def_id, substs) => { - substs.as_closure().sig_ty(def_id, tcx).fn_sig(tcx) - } + ty::Closure(_, substs) => substs.as_closure().sig(), _ => bug!(), }; let ty_fn_ptr_from = tcx.coerce_closure_fn_ty(sig, *unsafety); diff --git a/src/librustc_mir/borrow_check/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/type_check/relate_tys.rs index b0f048ff1a6fd..ebaafd4026270 100644 --- a/src/librustc_mir/borrow_check/type_check/relate_tys.rs +++ b/src/librustc_mir/borrow_check/type_check/relate_tys.rs @@ -3,8 +3,8 @@ use rustc::ty::relate::TypeRelation; use rustc::ty::{self, Ty}; use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate}; use rustc_infer::infer::{InferCtxt, NLLRegionVariableOrigin}; -use rustc_infer::traits::query::Fallible; -use rustc_infer::traits::DomainGoal; +use rustc_trait_selection::traits::query::Fallible; +use rustc_trait_selection::traits::DomainGoal; use crate::borrow_check::constraints::OutlivesConstraint; use crate::borrow_check::type_check::{BorrowCheckContext, Locations}; diff --git a/src/librustc_mir/borrow_check/universal_regions.rs b/src/librustc_mir/borrow_check/universal_regions.rs index 67b00e9ffdd5f..825931cf8922f 100644 --- a/src/librustc_mir/borrow_check/universal_regions.rs +++ b/src/librustc_mir/borrow_check/universal_regions.rs @@ -108,13 +108,11 @@ impl<'tcx> DefiningTy<'tcx> { /// not a closure or generator, there are no upvars, and hence it /// will be an empty list. The order of types in this list will /// match up with the upvar order in the HIR, typesystem, and MIR. - pub fn upvar_tys(self, tcx: TyCtxt<'tcx>) -> impl Iterator> + 'tcx { + pub fn upvar_tys(self) -> impl Iterator> + 'tcx { match self { - DefiningTy::Closure(def_id, substs) => { - Either::Left(substs.as_closure().upvar_tys(def_id, tcx)) - } - DefiningTy::Generator(def_id, substs, _) => { - Either::Right(Either::Left(substs.as_generator().upvar_tys(def_id, tcx))) + DefiningTy::Closure(_, substs) => Either::Left(substs.as_closure().upvar_tys()), + DefiningTy::Generator(_, substs, _) => { + Either::Right(Either::Left(substs.as_generator().upvar_tys())) } DefiningTy::FnDef(..) | DefiningTy::Const(..) => { Either::Right(Either::Right(iter::empty())) @@ -470,9 +468,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { debug!("build: local regions = {}..{}", first_local_index, num_universals); let yield_ty = match defining_ty { - DefiningTy::Generator(def_id, substs, _) => { - Some(substs.as_generator().yield_ty(def_id, self.infcx.tcx)) - } + DefiningTy::Generator(_, substs, _) => Some(substs.as_generator().yield_ty()), _ => None, }; @@ -580,7 +576,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { match defining_ty { DefiningTy::Closure(def_id, substs) => { assert_eq!(self.mir_def_id, def_id); - let closure_sig = substs.as_closure().sig_ty(def_id, tcx).fn_sig(tcx); + let closure_sig = substs.as_closure().sig(); let inputs_and_output = closure_sig.inputs_and_output(); let closure_ty = tcx.closure_env_ty(def_id, substs).unwrap(); ty::Binder::fuse(closure_ty, inputs_and_output, |closure_ty, inputs_and_output| { @@ -604,8 +600,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { DefiningTy::Generator(def_id, substs, movability) => { assert_eq!(self.mir_def_id, def_id); - let resume_ty = substs.as_generator().resume_ty(def_id, tcx); - let output = substs.as_generator().return_ty(def_id, tcx); + let resume_ty = substs.as_generator().resume_ty(); + let output = substs.as_generator().return_ty(); let generator_ty = tcx.mk_generator(def_id, substs, movability); let inputs_and_output = self.infcx.tcx.intern_type_list(&[generator_ty, resume_ty, output]); @@ -774,9 +770,9 @@ fn for_each_late_bound_region_defined_on<'tcx>( fn_def_id: DefId, mut f: impl FnMut(ty::Region<'tcx>), ) { - if let Some(late_bounds) = tcx.is_late_bound_map(fn_def_id.index) { + if let Some(late_bounds) = tcx.is_late_bound_map(fn_def_id.expect_local()) { for late_bound in late_bounds.iter() { - let hir_id = HirId { owner: fn_def_id.index, local_id: *late_bound }; + let hir_id = HirId { owner: fn_def_id.expect_local(), local_id: *late_bound }; let name = tcx.hir().name(hir_id); let region_def_id = tcx.hir().local_def_id(hir_id); let liberated_region = tcx.mk_region(ty::ReFree(ty::FreeRegion { diff --git a/src/librustc_mir/const_eval/error.rs b/src/librustc_mir/const_eval/error.rs index 63ad9ec8cae9e..aa30f43df9350 100644 --- a/src/librustc_mir/const_eval/error.rs +++ b/src/librustc_mir/const_eval/error.rs @@ -5,13 +5,14 @@ use rustc::mir::AssertKind; use rustc_span::Symbol; use super::InterpCx; -use crate::interpret::{ConstEvalErr, InterpError, InterpErrorInfo, Machine}; +use crate::interpret::{ConstEvalErr, InterpErrorInfo, Machine}; /// The CTFE machine has some custom error kinds. #[derive(Clone, Debug)] pub enum ConstEvalErrKind { NeedsRfc(String), ConstAccessesStatic, + ModifiedGlobal, AssertFailure(AssertKind), Panic { msg: Symbol, line: u32, col: u32, file: Symbol }, } @@ -21,7 +22,7 @@ pub enum ConstEvalErrKind { // handle these. impl<'tcx> Into> for ConstEvalErrKind { fn into(self) -> InterpErrorInfo<'tcx> { - InterpError::MachineStop(Box::new(self.to_string())).into() + err_machine_stop!(self.to_string()).into() } } @@ -33,6 +34,9 @@ impl fmt::Display for ConstEvalErrKind { write!(f, "\"{}\" needs an rfc before being allowed inside constants", msg) } ConstAccessesStatic => write!(f, "constant accesses static"), + ModifiedGlobal => { + write!(f, "modifying a static's initial value from another static's initializer") + } AssertFailure(ref msg) => write!(f, "{:?}", msg), Panic { msg, line, col, file } => { write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col) diff --git a/src/librustc_mir/const_eval/fn_queries.rs b/src/librustc_mir/const_eval/fn_queries.rs index 27efcd508414a..470e4e7ed25c1 100644 --- a/src/librustc_mir/const_eval/fn_queries.rs +++ b/src/librustc_mir/const_eval/fn_queries.rs @@ -85,7 +85,7 @@ pub fn is_min_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { let parent_id = tcx.hir().get_parent_did(hir_id); if !parent_id.is_top_level_module() { - is_const_impl_raw(tcx, LocalDefId::from_def_id(parent_id)) + is_const_impl_raw(tcx, parent_id.expect_local()) } else { false } @@ -171,7 +171,7 @@ fn const_fn_is_allowed_fn_ptr(tcx: TyCtxt<'_>, def_id: DefId) -> bool { pub fn provide(providers: &mut Providers<'_>) { *providers = Providers { is_const_fn_raw, - is_const_impl_raw: |tcx, def_id| is_const_impl_raw(tcx, LocalDefId::from_def_id(def_id)), + is_const_impl_raw: |tcx, def_id| is_const_impl_raw(tcx, def_id.expect_local()), is_promotable_const_fn, const_fn_is_allowed_fn_ptr, ..*providers diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index bb661d3d2a30a..0970e09791999 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -3,23 +3,23 @@ use rustc::ty::layout::HasTyCtxt; use rustc::ty::{self, Ty}; use std::borrow::{Borrow, Cow}; use std::collections::hash_map::Entry; -use std::convert::TryFrom; use std::hash::Hash; use rustc_data_structures::fx::FxHashMap; use rustc::mir::AssertMessage; -use rustc_span::source_map::Span; +use rustc_ast::ast::Mutability; use rustc_span::symbol::Symbol; +use rustc_span::{def_id::DefId, Span}; use crate::interpret::{ - self, snapshot, AllocId, Allocation, GlobalId, ImmTy, InterpCx, InterpResult, Memory, - MemoryKind, OpTy, PlaceTy, Pointer, Scalar, + self, AllocId, Allocation, GlobalId, ImmTy, InterpCx, InterpResult, Memory, MemoryKind, OpTy, + PlaceTy, Pointer, Scalar, }; use super::error::*; -impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> { +impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter> { /// Evaluate a const function where all arguments (if any) are zero-sized types. /// The evaluation is memoized thanks to the query system. /// @@ -56,7 +56,7 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> { self.return_to_block(ret.map(|r| r.1))?; self.dump_place(*dest); - return Ok(true); + Ok(true) } /// "Intercept" a function call to a panic-related function @@ -86,22 +86,13 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> { } } -/// The number of steps between loop detector snapshots. -/// Should be a power of two for performance reasons. -const DETECTOR_SNAPSHOT_PERIOD: isize = 256; - -// Extra machine state for CTFE, and the Machine instance -pub struct CompileTimeInterpreter<'mir, 'tcx> { - /// When this value is negative, it indicates the number of interpreter - /// steps *until* the loop detector is enabled. When it is positive, it is - /// the number of steps after the detector has been enabled modulo the loop - /// detector period. - pub(super) steps_since_detector_enabled: isize, - - pub(super) is_detector_enabled: bool, - - /// Extra state to detect loops. - pub(super) loop_detector: snapshot::InfiniteLoopDetector<'mir, 'tcx>, +/// Extra machine state for CTFE, and the Machine instance +pub struct CompileTimeInterpreter { + /// For now, the number of terminators that can be evaluated before we throw a resource + /// exhuastion error. + /// + /// Setting this to `0` disables the limit and allows the interpreter to run forever. + pub steps_remaining: usize, } #[derive(Copy, Clone, Debug)] @@ -110,16 +101,9 @@ pub struct MemoryExtra { pub(super) can_access_statics: bool, } -impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> { +impl CompileTimeInterpreter { pub(super) fn new(const_eval_limit: usize) -> Self { - let steps_until_detector_enabled = - isize::try_from(const_eval_limit).unwrap_or(std::isize::MAX); - - CompileTimeInterpreter { - loop_detector: Default::default(), - steps_since_detector_enabled: -steps_until_detector_enabled, - is_detector_enabled: const_eval_limit != 0, - } + CompileTimeInterpreter { steps_remaining: const_eval_limit } } } @@ -173,8 +157,7 @@ impl interpret::AllocMap for FxHashMap { } } -crate type CompileTimeEvalContext<'mir, 'tcx> = - InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>; +crate type CompileTimeEvalContext<'mir, 'tcx> = InterpCx<'mir, 'tcx, CompileTimeInterpreter>; impl interpret::MayLeak for ! { #[inline(always)] @@ -184,8 +167,8 @@ impl interpret::MayLeak for ! { } } -impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, 'tcx> { - type MemoryKinds = !; +impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter { + type MemoryKind = !; type PointerTag = (); type ExtraFnVal = !; @@ -195,7 +178,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, type MemoryMap = FxHashMap, Allocation)>; - const STATIC_KIND: Option = None; // no copying of statics allowed + const GLOBAL_KIND: Option = None; // no copying of globals from `tcx` to machine memory // We do not check for alignment to avoid having to carry an `Align` // in `ConstValue::ByRef`. @@ -240,7 +223,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, Ok(Some(match ecx.load_mir(instance.def, None) { Ok(body) => *body, Err(err) => { - if let err_unsup!(NoMirFor(ref path)) = err.kind { + if let err_unsup!(NoMirFor(did)) = err.kind { + let path = ecx.tcx.def_path_str(did); return Err(ConstEvalErrKind::NeedsRfc(format!( "calling extern function `{}`", path @@ -334,9 +318,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } #[inline(always)] - fn tag_static_base_pointer(_memory_extra: &MemoryExtra, _id: AllocId) -> Self::PointerTag { - () - } + fn tag_global_base_pointer(_memory_extra: &MemoryExtra, _id: AllocId) -> Self::PointerTag {} fn box_alloc( _ecx: &mut InterpCx<'mir, 'tcx, Self>, @@ -346,26 +328,17 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } fn before_terminator(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { - if !ecx.machine.is_detector_enabled { + // The step limit has already been hit in a previous call to `before_terminator`. + if ecx.machine.steps_remaining == 0 { return Ok(()); } - { - let steps = &mut ecx.machine.steps_since_detector_enabled; - - *steps += 1; - if *steps < 0 { - return Ok(()); - } - - *steps %= DETECTOR_SNAPSHOT_PERIOD; - if *steps != 0 { - return Ok(()); - } + ecx.machine.steps_remaining -= 1; + if ecx.machine.steps_remaining == 0 { + throw_exhaust!(StepLimitReached) } - let span = ecx.frame().span; - ecx.machine.loop_detector.observe_and_analyze(*ecx.tcx, span, &ecx.memory, &ecx.stack[..]) + Ok(()) } #[inline(always)] @@ -373,11 +346,19 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, Ok(()) } - fn before_access_static( + fn before_access_global( memory_extra: &MemoryExtra, - _allocation: &Allocation, + alloc_id: AllocId, + allocation: &Allocation, + static_def_id: Option, + is_write: bool, ) -> InterpResult<'tcx> { - if memory_extra.can_access_statics { + if is_write && allocation.mutability == Mutability::Not { + Err(err_ub!(WriteToReadOnly(alloc_id)).into()) + } else if is_write { + Err(ConstEvalErrKind::ModifiedGlobal.into()) + } else if memory_extra.can_access_statics || static_def_id.is_none() { + // `static_def_id.is_none()` indicates this is not a static, but a const or so. Ok(()) } else { Err(ConstEvalErrKind::ConstAccessesStatic.into()) diff --git a/src/librustc_mir/const_eval/mod.rs b/src/librustc_mir/const_eval/mod.rs index cb6583976258b..6e7e6f9d34526 100644 --- a/src/librustc_mir/const_eval/mod.rs +++ b/src/librustc_mir/const_eval/mod.rs @@ -1,5 +1,7 @@ // Not in interpret to make sure we do not use private implementation details +use std::convert::TryFrom; + use rustc::mir; use rustc::ty::layout::VariantIdx; use rustc::ty::{self, TyCtxt}; @@ -37,13 +39,13 @@ pub(crate) fn const_field<'tcx>( Some(variant) => ecx.operand_downcast(op, variant).unwrap(), }; // then project - let field = ecx.operand_field(down, field.index() as u64).unwrap(); + let field = ecx.operand_field(down, field.index()).unwrap(); // and finally move back to the const world, always normalizing because // this is not called for statics. op_to_const(&ecx, field) } -pub(crate) fn const_caller_location<'tcx>( +pub(crate) fn const_caller_location( tcx: TyCtxt<'tcx>, (file, line, col): (Symbol, u32, u32), ) -> ConstValue<'tcx> { @@ -68,10 +70,11 @@ pub(crate) fn destructure_const<'tcx>( let variant = ecx.read_discriminant(op).unwrap().1; + // We go to `usize` as we cannot allocate anything bigger anyway. let field_count = match val.ty.kind { - ty::Array(_, len) => len.eval_usize(tcx, param_env), - ty::Adt(def, _) => def.variants[variant].fields.len() as u64, - ty::Tuple(substs) => substs.len() as u64, + ty::Array(_, len) => usize::try_from(len.eval_usize(tcx, param_env)).unwrap(), + ty::Adt(def, _) => def.variants[variant].fields.len(), + ty::Tuple(substs) => substs.len(), _ => bug!("cannot destructure constant {:?}", val), }; diff --git a/src/librustc_mir/dataflow/generic/cursor.rs b/src/librustc_mir/dataflow/generic/cursor.rs index 8c0ab1505284a..170157aca5ddd 100644 --- a/src/librustc_mir/dataflow/generic/cursor.rs +++ b/src/librustc_mir/dataflow/generic/cursor.rs @@ -2,7 +2,7 @@ use std::borrow::Borrow; -use rustc::mir::{self, BasicBlock, Location}; +use rustc::mir::{self, BasicBlock, Location, TerminatorKind}; use rustc_index::bit_set::BitSet; use super::{Analysis, Results}; @@ -29,14 +29,14 @@ where pos: CursorPosition, - /// When this flag is set, the cursor is pointing at a `Call` terminator whose call return - /// effect has been applied to `state`. + /// When this flag is set, the cursor is pointing at a `Call` or `Yield` terminator whose call + /// return or resume effect has been applied to `state`. /// - /// This flag helps to ensure that multiple calls to `seek_after_assume_call_returns` with the + /// This flag helps to ensure that multiple calls to `seek_after_assume_success` with the /// same target will result in exactly one invocation of `apply_call_return_effect`. It is /// sufficient to clear this only in `seek_to_block_start`, since seeking away from a /// terminator will always require a cursor reset. - call_return_effect_applied: bool, + success_effect_applied: bool, } impl<'mir, 'tcx, A, R> ResultsCursor<'mir, 'tcx, A, R> @@ -50,7 +50,7 @@ where body, pos: CursorPosition::BlockStart(mir::START_BLOCK), state: results.borrow().entry_sets[mir::START_BLOCK].clone(), - call_return_effect_applied: false, + success_effect_applied: false, results, } } @@ -76,14 +76,14 @@ where pub fn seek_to_block_start(&mut self, block: BasicBlock) { self.state.overwrite(&self.results.borrow().entry_sets[block]); self.pos = CursorPosition::BlockStart(block); - self.call_return_effect_applied = false; + self.success_effect_applied = false; } /// Advances the cursor to hold all effects up to and including to the "before" effect of the /// statement (or terminator) at the given location. /// /// If you wish to observe the full effect of a statement or terminator, not just the "before" - /// effect, use `seek_after` or `seek_after_assume_call_returns`. + /// effect, use `seek_after` or `seek_after_assume_success`. pub fn seek_before(&mut self, target: Location) { assert!(target <= self.body.terminator_loc(target.block)); self.seek_(target, false); @@ -93,7 +93,7 @@ where /// terminators) up to and including the `target`. /// /// If the `target` is a `Call` terminator, any call return effect for that terminator will - /// **not** be observed. Use `seek_after_assume_call_returns` if you wish to observe the call + /// **not** be observed. Use `seek_after_assume_success` if you wish to observe the call /// return effect. pub fn seek_after(&mut self, target: Location) { assert!(target <= self.body.terminator_loc(target.block)); @@ -101,7 +101,7 @@ where // If we have already applied the call return effect, we are currently pointing at a `Call` // terminator. Unconditionally reset the dataflow cursor, since there is no way to "undo" // the call return effect. - if self.call_return_effect_applied { + if self.success_effect_applied { self.seek_to_block_start(target.block); } @@ -111,25 +111,25 @@ where /// Advances the cursor to hold all effects up to and including of the statement (or /// terminator) at the given location. /// - /// If the `target` is a `Call` terminator, any call return effect for that terminator will - /// be observed. Use `seek_after` if you do **not** wish to observe the call return effect. - pub fn seek_after_assume_call_returns(&mut self, target: Location) { + /// If the `target` is a `Call` or `Yield` terminator, any call return or resume effect for that + /// terminator will be observed. Use `seek_after` if you do **not** wish to observe the + /// "success" effect. + pub fn seek_after_assume_success(&mut self, target: Location) { let terminator_loc = self.body.terminator_loc(target.block); assert!(target.statement_index <= terminator_loc.statement_index); self.seek_(target, true); - if target != terminator_loc { + if target != terminator_loc || self.success_effect_applied { return; } + // Apply the effect of the "success" path of the terminator. + + self.success_effect_applied = true; let terminator = self.body.basic_blocks()[target.block].terminator(); - if let mir::TerminatorKind::Call { - destination: Some((return_place, _)), func, args, .. - } = &terminator.kind - { - if !self.call_return_effect_applied { - self.call_return_effect_applied = true; + match &terminator.kind { + TerminatorKind::Call { destination: Some((return_place, _)), func, args, .. } => { self.results.borrow().analysis.apply_call_return_effect( &mut self.state, target.block, @@ -138,6 +138,14 @@ where return_place, ); } + TerminatorKind::Yield { resume, resume_arg, .. } => { + self.results.borrow().analysis.apply_yield_resume_effect( + &mut self.state, + *resume, + resume_arg, + ); + } + _ => {} } } @@ -172,7 +180,7 @@ where self.seek_to_block_start(target.block) } - // N.B., `call_return_effect_applied` is checked in `seek_after`, not here. + // N.B., `success_effect_applied` is checked in `seek_after`, not here. _ => (), } diff --git a/src/librustc_mir/dataflow/generic/engine.rs b/src/librustc_mir/dataflow/generic/engine.rs index 8d800f2d0ba05..d32072125b3b9 100644 --- a/src/librustc_mir/dataflow/generic/engine.rs +++ b/src/librustc_mir/dataflow/generic/engine.rs @@ -218,15 +218,18 @@ where Goto { target } | Assert { target, cleanup: None, .. } - | Yield { resume: target, drop: None, .. } | Drop { target, location: _, unwind: None } | DropAndReplace { target, value: _, location: _, unwind: None } => { self.propagate_bits_into_entry_set_for(in_out, target, dirty_list) } - Yield { resume: target, drop: Some(drop), .. } => { + Yield { resume: target, drop, resume_arg, .. } => { + if let Some(drop) = drop { + self.propagate_bits_into_entry_set_for(in_out, drop, dirty_list); + } + + self.analysis.apply_yield_resume_effect(in_out, target, &resume_arg); self.propagate_bits_into_entry_set_for(in_out, target, dirty_list); - self.propagate_bits_into_entry_set_for(in_out, drop, dirty_list); } Assert { target, cleanup: Some(unwind), .. } diff --git a/src/librustc_mir/dataflow/generic/graphviz.rs b/src/librustc_mir/dataflow/generic/graphviz.rs index f8e1d3e9fe8c6..c15f2a726ee70 100644 --- a/src/librustc_mir/dataflow/generic/graphviz.rs +++ b/src/librustc_mir/dataflow/generic/graphviz.rs @@ -241,7 +241,7 @@ where )?; let state_on_unwind = this.results.get().clone(); - this.results.seek_after_assume_call_returns(terminator_loc); + this.results.seek_after_assume_success(terminator_loc); write_diff(w, this.results.analysis(), &state_on_unwind, this.results.get())?; write!(w, "") @@ -577,7 +577,7 @@ fn write_diff>( let mut clear = HybridBitSet::new_empty(len); // FIXME: Implement a lazy iterator over the symmetric difference of two bitsets. - for i in (0..len).map(|i| A::Idx::new(i)) { + for i in (0..len).map(A::Idx::new) { match (from.contains(i), to.contains(i)) { (false, true) => set.insert(i), (true, false) => clear.insert(i), diff --git a/src/librustc_mir/dataflow/generic/mod.rs b/src/librustc_mir/dataflow/generic/mod.rs index 9a102c9a3d06f..fb4b7b9c5be31 100644 --- a/src/librustc_mir/dataflow/generic/mod.rs +++ b/src/librustc_mir/dataflow/generic/mod.rs @@ -191,6 +191,20 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> { return_place: &mir::Place<'tcx>, ); + /// Updates the current dataflow state with the effect of resuming from a `Yield` terminator. + /// + /// This is similar to `apply_call_return_effect` in that it only takes place after the + /// generator is resumed, not when it is dropped. + /// + /// By default, no effects happen. + fn apply_yield_resume_effect( + &self, + _state: &mut BitSet, + _resume_block: BasicBlock, + _resume_place: &mir::Place<'tcx>, + ) { + } + /// Updates the current dataflow state with the effect of taking a particular branch in a /// `SwitchInt` terminator. /// @@ -284,6 +298,15 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> { return_place: &mir::Place<'tcx>, ); + /// See `Analysis::apply_yield_resume_effect`. + fn yield_resume_effect( + &self, + _trans: &mut BitSet, + _resume_block: BasicBlock, + _resume_place: &mir::Place<'tcx>, + ) { + } + /// See `Analysis::apply_discriminant_switch_effect`. fn discriminant_switch_effect( &self, @@ -347,6 +370,15 @@ where self.call_return_effect(state, block, func, args, return_place); } + fn apply_yield_resume_effect( + &self, + state: &mut BitSet, + resume_block: BasicBlock, + resume_place: &mir::Place<'tcx>, + ) { + self.yield_resume_effect(state, resume_block, resume_place); + } + fn apply_discriminant_switch_effect( &self, state: &mut BitSet, diff --git a/src/librustc_mir/dataflow/generic/tests.rs b/src/librustc_mir/dataflow/generic/tests.rs index 50d4bdb67f755..8f07a10e1b01c 100644 --- a/src/librustc_mir/dataflow/generic/tests.rs +++ b/src/librustc_mir/dataflow/generic/tests.rs @@ -294,7 +294,7 @@ fn cursor_seek() { cursor.seek_after(call_terminator_loc); assert!(!cursor.get().contains(call_return_effect)); - cursor.seek_after_assume_call_returns(call_terminator_loc); + cursor.seek_after_assume_success(call_terminator_loc); assert!(cursor.get().contains(call_return_effect)); let every_target = || { @@ -310,7 +310,7 @@ fn cursor_seek() { BlockStart(block) => cursor.seek_to_block_start(block), Before(loc) => cursor.seek_before(loc), After(loc) => cursor.seek_after(loc), - AfterAssumeCallReturns(loc) => cursor.seek_after_assume_call_returns(loc), + AfterAssumeCallReturns(loc) => cursor.seek_after_assume_success(loc), } assert_eq!(cursor.get(), &cursor.analysis().expected_state_at_target(targ)); diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs index fabe562e68a59..5341d661b1db6 100644 --- a/src/librustc_mir/dataflow/impls/storage_liveness.rs +++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs @@ -161,11 +161,16 @@ impl<'mir, 'tcx> dataflow::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, self.borrowed_locals.borrow().analysis().terminator_effect(trans, terminator, loc); match &terminator.kind { - TerminatorKind::Call { destination: Some((place, _)), .. } - | TerminatorKind::Yield { resume_arg: place, .. } => { + TerminatorKind::Call { destination: Some((place, _)), .. } => { trans.gen(place.local); } + // Note that we do *not* gen the `resume_arg` of `Yield` terminators. The reason for + // that is that a `yield` will return from the function, and `resume_arg` is written + // only when the generator is later resumed. Unlike `Call`, this doesn't require the + // place to have storage *before* the yield, only after. + TerminatorKind::Yield { .. } => {} + // Nothing to do for these. Match exhaustively so this fails to compile when new // variants are added. TerminatorKind::Call { destination: None, .. } @@ -230,6 +235,15 @@ impl<'mir, 'tcx> dataflow::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, ) { trans.gen(return_place.local); } + + fn yield_resume_effect( + &self, + trans: &mut BitSet, + _resume_block: BasicBlock, + resume_place: &mir::Place<'tcx>, + ) { + trans.gen(resume_place.local); + } } impl<'mir, 'tcx> MaybeRequiresStorage<'mir, 'tcx> { diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index b4e33b9502e69..c98a5e84729ab 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -1,16 +1,14 @@ +use rustc::mir::traversal; +use rustc::mir::{self, BasicBlock, BasicBlockData, Body, Location, Statement, Terminator}; +use rustc::ty::{self, TyCtxt}; use rustc_ast::ast::{self, MetaItem}; use rustc_ast_pretty::pprust; -use rustc_span::symbol::{sym, Symbol}; - use rustc_data_structures::work_queue::WorkQueue; +use rustc_hir::def_id::DefId; use rustc_index::bit_set::{BitSet, HybridBitSet}; use rustc_index::vec::Idx; - -use rustc::mir::traversal; -use rustc::mir::{self, BasicBlock, BasicBlockData, Body, Location, Statement, Terminator}; -use rustc::session::Session; -use rustc::ty::{self, TyCtxt}; -use rustc_hir::def_id::DefId; +use rustc_session::Session; +use rustc_span::symbol::{sym, Symbol}; use std::borrow::Borrow; use std::fmt; @@ -124,7 +122,7 @@ pub(crate) fn has_rustc_mir_with(attrs: &[ast::Attribute], name: Symbol) -> Opti } } } - return None; + None } pub struct MoveDataParamEnv<'tcx> { @@ -173,7 +171,7 @@ where return None; } } - return None; + None }; let print_preflow_to = name_found(tcx.sess, attributes, sym::borrowck_graphviz_preflow); diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 7c449ad119796..276aabec13da0 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -184,14 +184,13 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { .. } = self.builder; *rev_lookup.projections.entry((base, elem.lift())).or_insert_with(move || { - let path = MoveDataBuilder::new_move_path( + MoveDataBuilder::new_move_path( move_paths, path_map, init_path_map, Some(base), mk_place(*tcx), - ); - path + ) }) } diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 3cbb0667ff392..f7327825ca4b7 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -1,8 +1,11 @@ +use std::convert::TryFrom; + use rustc::ty::adjustment::PointerCast; use rustc::ty::layout::{self, Size, TyLayout}; use rustc::ty::{self, Ty, TypeAndMut, TypeFoldable}; use rustc_ast::ast::FloatTy; use rustc_span::symbol::sym; +use rustc_target::abi::LayoutOf; use rustc::mir::interpret::{InterpResult, PointerArithmetic, Scalar}; use rustc::mir::CastKind; @@ -134,7 +137,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { layout::Variants::Single { index } => { if let Some(discr) = src.layout.ty.discriminant_for_variant(*self.tcx, index) { assert!(src.layout.is_zst()); - return Ok(Scalar::from_uint(discr.val, dest_layout.size).into()); + let discr_layout = self.layout_of(discr.ty)?; + return Ok(self + .cast_from_int_like(discr.val, discr_layout, dest_layout)? + .into()); } } layout::Variants::Multiple { .. } => {} @@ -171,10 +177,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // (b) cast from an integer-like (including bool, char, enums). // In both cases we want the bits. let bits = self.force_bits(src.to_scalar()?, src.layout.size)?; - Ok(self.cast_from_int(bits, src.layout, dest_layout)?.into()) + Ok(self.cast_from_int_like(bits, src.layout, dest_layout)?.into()) } - fn cast_from_int( + fn cast_from_int_like( &self, v: u128, // raw bits src_layout: TyLayout<'tcx>, @@ -202,8 +208,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Char => { // `u8` to `char` cast - assert_eq!(v as u8 as u128, v); - Ok(Scalar::from_uint(v, Size::from_bytes(4))) + Ok(Scalar::from_uint(u8::try_from(v).unwrap(), Size::from_bytes(4))) } // Casts to bool are not permitted by rustc, no need to handle them here. @@ -223,16 +228,16 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { match dest_ty.kind { // float -> uint Uint(t) => { - let width = t.bit_width().unwrap_or_else(|| self.pointer_size().bits() as usize); - let v = f.to_u128(width).value; + let width = t.bit_width().unwrap_or_else(|| self.pointer_size().bits()); + let v = f.to_u128(usize::try_from(width).unwrap()).value; // This should already fit the bit width - Ok(Scalar::from_uint(v, Size::from_bits(width as u64))) + Ok(Scalar::from_uint(v, Size::from_bits(width))) } // float -> int Int(t) => { - let width = t.bit_width().unwrap_or_else(|| self.pointer_size().bits() as usize); - let v = f.to_i128(width).value; - Ok(Scalar::from_int(v, Size::from_bits(width as u64))) + let width = t.bit_width().unwrap_or_else(|| self.pointer_size().bits()); + let v = f.to_i128(usize::try_from(width).unwrap()).value; + Ok(Scalar::from_int(v, Size::from_bits(width))) } // float -> f32 Float(FloatTy::F32) => Ok(Scalar::from_f32(f.convert(&mut false).value)), @@ -315,11 +320,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Example: `Arc` -> `Arc` // here we need to increase the size of every &T thin ptr field to a fat ptr for i in 0..src.layout.fields.count() { - let dst_field = self.place_field(dest, i as u64)?; + let dst_field = self.place_field(dest, i)?; if dst_field.layout.is_zst() { continue; } - let src_field = self.operand_field(src, i as u64)?; + let src_field = self.operand_field(src, i)?; if src_field.layout.ty == dst_field.layout.ty { self.copy_op(src_field, dst_field)?; } else { diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 9b28b7a20c044..c2baabf4233ce 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -21,7 +21,7 @@ use rustc_span::source_map::{self, Span, DUMMY_SP}; use super::{ Immediate, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory, OpTy, Operand, Place, PlaceTy, - ScalarMaybeUndef, StackPopInfo, + ScalarMaybeUndef, StackPopJump, }; pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> { @@ -98,10 +98,10 @@ pub enum StackPopCleanup { /// Jump to the next block in the caller, or cause UB if None (that's a function /// that may never return). Also store layout of return place so /// we can validate it at that layout. - /// `ret` stores the block we jump to on a normal return, while 'unwind' - /// stores the block used for cleanup during unwinding + /// `ret` stores the block we jump to on a normal return, while `unwind` + /// stores the block used for cleanup during unwinding. Goto { ret: Option, unwind: Option }, - /// Just do nohing: Used by Main and for the box_alloc hook in miri. + /// Just do nothing: Used by Main and for the `box_alloc` hook in miri. /// `cleanup` says whether locals are deallocated. Static computation /// wants them leaked to intern what they need (and just throw away /// the entire `ecx` when it is done). @@ -138,7 +138,7 @@ pub enum LocalValue { impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> { pub fn access(&self) -> InterpResult<'tcx, Operand> { match self.value { - LocalValue::Dead => throw_unsup!(DeadLocal), + LocalValue::Dead => throw_ub!(DeadLocal), LocalValue::Uninitialized => { bug!("The type checker should prevent reading from a never-written local") } @@ -152,7 +152,7 @@ impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> { &mut self, ) -> InterpResult<'tcx, Result<&mut LocalValue, MemPlace>> { match self.value { - LocalValue::Dead => throw_unsup!(DeadLocal), + LocalValue::Dead => throw_ub!(DeadLocal), LocalValue::Live(Operand::Indirect(mplace)) => Ok(Err(mplace)), ref mut local @ LocalValue::Live(Operand::Immediate(_)) | ref mut local @ LocalValue::Uninitialized => Ok(Ok(local)), @@ -253,8 +253,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// This represents a *direct* access to that memory, as opposed to access /// through a pointer that was created by the program. #[inline(always)] - pub fn tag_static_base_pointer(&self, ptr: Pointer) -> Pointer { - self.memory.tag_static_base_pointer(ptr) + pub fn tag_global_base_pointer(&self, ptr: Pointer) -> Pointer { + self.memory.tag_global_base_pointer(ptr) } #[inline(always)] @@ -326,7 +326,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if self.tcx.is_mir_available(did) { Ok(self.tcx.optimized_mir(did).unwrap_read_only()) } else { - throw_unsup!(NoMirFor(self.tcx.def_path_str(def_id))) + throw_unsup!(NoMirFor(def_id)) } } _ => Ok(self.tcx.instance_mir(instance)), @@ -335,15 +335,25 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Call this on things you got out of the MIR (so it is as generic as the current /// stack frame), to bring it into the proper environment for this interpreter. + pub(super) fn subst_from_current_frame_and_normalize_erasing_regions>( + &self, + value: T, + ) -> T { + self.subst_from_frame_and_normalize_erasing_regions(self.frame(), value) + } + + /// Call this on things you got out of the MIR (so it is as generic as the provided + /// stack frame), to bring it into the proper environment for this interpreter. pub(super) fn subst_from_frame_and_normalize_erasing_regions>( &self, + frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>, value: T, ) -> T { - self.tcx.subst_and_normalize_erasing_regions( - self.frame().instance.substs, - self.param_env, - &value, - ) + if let Some(substs) = frame.instance.substs_for_mir_body() { + self.tcx.subst_and_normalize_erasing_regions(substs, self.param_env, &value) + } else { + self.tcx.normalize_erasing_regions(self.param_env, value) + } } /// The `substs` are assumed to already be in our interpreter "universe" (param_env). @@ -371,11 +381,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { None => { let layout = crate::interpret::operand::from_known_layout(layout, || { let local_ty = frame.body.local_decls[local].ty; - let local_ty = self.tcx.subst_and_normalize_erasing_regions( - frame.instance.substs, - self.param_env, - &local_ty, - ); + let local_ty = + self.subst_from_frame_and_normalize_erasing_regions(frame, local_ty); self.layout_of(local_ty) })?; if let Some(state) = frame.locals.get(local) { @@ -406,6 +413,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // and it also rounds up to alignment, which we want to avoid, // as the unsized field's alignment could be smaller. assert!(!layout.ty.is_simd()); + assert!(layout.fields.count() > 0); trace!("DST layout: {:?}", layout); let sized_size = layout.fields.offset(layout.fields.count() - 1); @@ -445,7 +453,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // here. But this is where the add would go.) // Return the sum of sizes and max of aligns. - let size = sized_size + unsized_size; + let size = sized_size + unsized_size; // `Size` addition // Choose max of two known alignments (combined value must // be aligned according to more restrictive of the two). @@ -574,7 +582,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// If `target` is `None`, that indicates the function cannot return, so we raise UB. pub fn return_to_block(&mut self, target: Option) -> InterpResult<'tcx> { if let Some(target) = target { - Ok(self.go_to_block(target)) + self.go_to_block(target); + Ok(()) } else { throw_ub!(Unreachable) } @@ -623,23 +632,15 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ::log_settings::settings().indentation -= 1; let frame = self.stack.pop().expect("tried to pop a stack frame, but there were none"); - let stack_pop_info = M::stack_pop(self, frame.extra, unwinding)?; - if let (false, StackPopInfo::StopUnwinding) = (unwinding, stack_pop_info) { - bug!("Attempted to stop unwinding while there is no unwinding!"); - } // Now where do we jump next? - // Determine if we leave this function normally or via unwinding. - let cur_unwinding = - if let StackPopInfo::StopUnwinding = stack_pop_info { false } else { unwinding }; - // Usually we want to clean up (deallocate locals), but in a few rare cases we don't. // In that case, we return early. We also avoid validation in that case, // because this is CTFE and the final value will be thoroughly validated anyway. let (cleanup, next_block) = match frame.return_to_block { StackPopCleanup::Goto { ret, unwind } => { - (true, Some(if cur_unwinding { unwind } else { ret })) + (true, Some(if unwinding { unwind } else { ret })) } StackPopCleanup::None { cleanup, .. } => (cleanup, None), }; @@ -647,7 +648,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if !cleanup { assert!(self.stack.is_empty(), "only the topmost frame should ever be leaked"); assert!(next_block.is_none(), "tried to skip cleanup when we have a next block!"); - // Leak the locals, skip validation. + assert!(!unwinding, "tried to skip cleanup during unwinding"); + // Leak the locals, skip validation, skip machine hook. return Ok(()); } @@ -656,13 +658,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.deallocate_local(local.value)?; } - trace!( - "StackPopCleanup: {:?} StackPopInfo: {:?} cur_unwinding = {:?}", - frame.return_to_block, - stack_pop_info, - cur_unwinding - ); - if cur_unwinding { + if M::stack_pop(self, frame.extra, unwinding)? == StackPopJump::NoJump { + // The hook already did everything. + // We want to skip the `info!` below, hence early return. + return Ok(()); + } + // Normal return. + if unwinding { // Follow the unwind edge. let unwind = next_block.expect("Encountered StackPopCleanup::None when unwinding!"); self.unwind_to_block(unwind); @@ -697,7 +699,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { "CONTINUING({}) {} (unwinding = {})", self.cur_frame(), self.frame().instance, - cur_unwinding + unwinding ); } diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index 9b13db2289e7e..b9ed69842f1a9 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -16,7 +16,7 @@ use super::{AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, Scalar pub trait CompileTimeMachine<'mir, 'tcx> = Machine< 'mir, 'tcx, - MemoryKinds = !, + MemoryKind = !, PointerTag = (), ExtraFnVal = !, FrameExtra = (), @@ -104,7 +104,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>( MemoryKind::Stack | MemoryKind::Vtable | MemoryKind::CallerLocation => {} } // Set allocation mutability as appropriate. This is used by LLVM to put things into - // read-only memory, and also by Miri when evluating other constants/statics that + // read-only memory, and also by Miri when evaluating other globals that // access this one. if mode == InternMode::Static { // When `ty` is `None`, we assume no interior mutability. @@ -327,7 +327,7 @@ pub fn intern_const_alloc_recursive>( if let Err(error) = interned { // This can happen when e.g. the tag of an enum is not a valid discriminant. We do have // to read enum discriminants in order to find references in enum variant fields. - if let err_unsup!(ValidationFailure(_)) = error.kind { + if let err_ub!(ValidationFailure(_)) = error.kind { let err = crate::const_eval::error_to_const_error(&ecx, error); match err.struct_error( ecx.tcx, @@ -390,7 +390,7 @@ pub fn intern_const_alloc_recursive>( } } else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) { // dangling pointer - throw_unsup!(ValidationFailure("encountered dangling pointer in final constant".into())) + throw_ub_format!("encountered dangling pointer in final constant") } else if ecx.tcx.alloc_map.lock().get(alloc_id).is_none() { // We have hit an `AllocId` that is neither in local or global memory and isn't marked // as dangling by local memory. diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 869eb1227f23b..e5f89b10e76ed 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -29,11 +29,11 @@ fn numeric_intrinsic<'tcx, Tag>( Primitive::Int(integer, _) => integer.size(), _ => bug!("invalid `{}` argument: {:?}", name, bits), }; - let extra = 128 - size.bits() as u128; + let extra = 128 - u128::from(size.bits()); let bits_out = match name { - sym::ctpop => bits.count_ones() as u128, - sym::ctlz => bits.leading_zeros() as u128 - extra, - sym::cttz => (bits << extra).trailing_zeros() as u128 - extra, + sym::ctpop => u128::from(bits.count_ones()), + sym::ctlz => u128::from(bits.leading_zeros()) - extra, + sym::cttz => u128::from((bits << extra).trailing_zeros()) - extra, sym::bswap => (bits << extra).swap_bytes(), sym::bitreverse => (bits << extra).reverse_bits(), _ => bug!("not a numeric intrinsic: {}", name), @@ -84,14 +84,15 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let substs = instance.substs; let intrinsic_name = self.tcx.item_name(instance.def_id()); - // We currently do not handle any intrinsics that are *allowed* to diverge, - // but `transmute` could lack a return place in case of UB. + // First handle intrinsics without return place. let (dest, ret) = match ret { - Some(p) => p, None => match intrinsic_name { - sym::transmute => throw_ub!(Unreachable), + sym::transmute => throw_ub_format!("transmuting to uninhabited type"), + sym::abort => M::abort(self)?, + // Unsupported diverging intrinsic. _ => return Ok(false), }, + Some(p) => p, }; // Keep the patterns in this match ordered the same as the list in @@ -103,10 +104,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.write_scalar(location.ptr, dest)?; } - sym::abort => { - M::abort(self)?; - } - sym::min_align_of | sym::pref_align_of | sym::needs_drop @@ -138,7 +135,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let bits = self.force_bits(val, layout_of.size)?; let kind = match layout_of.abi { ty::layout::Abi::Scalar(ref scalar) => scalar.value, - _ => throw_unsup!(TypeNotPrimitive(ty)), + _ => bug!("{} called on invalid type {:?}", intrinsic_name, ty), }; let (nonzero, intrinsic_name) = match intrinsic_name { sym::cttz_nonzero => (true, sym::cttz), @@ -249,9 +246,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let layout = self.layout_of(substs.type_at(0))?; let r_val = self.force_bits(r.to_scalar()?, layout.size)?; if let sym::unchecked_shl | sym::unchecked_shr = intrinsic_name { - throw_ub_format!("Overflowing shift by {} in `{}`", r_val, intrinsic_name); + throw_ub_format!("overflowing shift by {} in `{}`", r_val, intrinsic_name); } else { - throw_ub_format!("Overflow executing `{}`", intrinsic_name); + throw_ub_format!("overflow executing `{}`", intrinsic_name); } } self.write_scalar(val, dest)?; @@ -264,7 +261,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let val_bits = self.force_bits(val, layout.size)?; let raw_shift = self.read_scalar(args[1])?.not_undef()?; let raw_shift_bits = self.force_bits(raw_shift, layout.size)?; - let width_bits = layout.size.bits() as u128; + let width_bits = u128::from(layout.size.bits()); let shift_bits = raw_shift_bits % width_bits; let inv_shift_bits = (width_bits - shift_bits) % width_bits; let result_bits = if intrinsic_name == sym::rotate_left { @@ -353,8 +350,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ); for i in 0..len { - let place = self.place_field(dest, i)?; - let value = if i == index { elem } else { self.operand_field(input, i)? }; + let place = self.place_index(dest, i)?; + let value = if i == index { elem } else { self.operand_index(input, i)? }; self.copy_op(value, place)?; } } @@ -373,7 +370,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { "Return type `{}` must match vector element type `{}`", dest.layout.ty, e_ty ); - self.copy_op(self.operand_field(args[0], index)?, dest)?; + self.copy_op(self.operand_index(args[0], index)?, dest)?; } _ => return Ok(false), } diff --git a/src/librustc_mir/interpret/intrinsics/caller_location.rs b/src/librustc_mir/interpret/intrinsics/caller_location.rs index 566601f0cae28..01f9cdea0f0d3 100644 --- a/src/librustc_mir/interpret/intrinsics/caller_location.rs +++ b/src/librustc_mir/interpret/intrinsics/caller_location.rs @@ -1,3 +1,5 @@ +use std::convert::TryFrom; + use rustc::middle::lang_items::PanicLocationLangItem; use rustc::ty::subst::Subst; use rustc_span::{Span, Symbol}; @@ -39,7 +41,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let loc_ty = self .tcx .type_of(self.tcx.require_lang_item(PanicLocationLangItem, None)) - .subst(*self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_static.into()].iter())); + .subst(*self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_erased.into()].iter())); let loc_layout = self.layout_of(loc_ty).unwrap(); let location = self.allocate(loc_layout, MemoryKind::CallerLocation); @@ -59,8 +61,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo()); ( Symbol::intern(&caller.file.name.to_string()), - caller.line as u32, - caller.col_display as u32 + 1, + u32::try_from(caller.line).unwrap(), + u32::try_from(caller.col_display).unwrap().checked_add(1).unwrap(), ) } diff --git a/src/librustc_mir/interpret/intrinsics/type_name.rs b/src/librustc_mir/interpret/intrinsics/type_name.rs index cd8bf7085d1b1..0d9582c7323cb 100644 --- a/src/librustc_mir/interpret/intrinsics/type_name.rs +++ b/src/librustc_mir/interpret/intrinsics/type_name.rs @@ -1,4 +1,3 @@ -use rustc::hir::map::{DefPathData, DisambiguatedDefPathData}; use rustc::mir::interpret::Allocation; use rustc::ty::{ self, @@ -7,6 +6,7 @@ use rustc::ty::{ Ty, TyCtxt, }; use rustc_hir::def_id::CrateNum; +use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; use std::fmt::Write; struct AbsolutePathPrinter<'tcx> { @@ -157,6 +157,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { } } } + impl PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> { fn region_should_not_be_omitted(&self, _region: ty::Region<'_>) -> bool { false @@ -191,7 +192,8 @@ impl PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> { impl Write for AbsolutePathPrinter<'_> { fn write_str(&mut self, s: &str) -> std::fmt::Result { - Ok(self.path.push_str(s)) + self.path.push_str(s); + Ok(()) } } diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 366de6e55612a..74933bed8f89e 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -7,7 +7,7 @@ use std::hash::Hash; use rustc::mir; use rustc::ty::{self, Ty}; -use rustc_span::Span; +use rustc_span::{def_id::DefId, Span}; use super::{ AllocId, Allocation, AllocationExtra, Frame, ImmTy, InterpCx, InterpResult, Memory, MemoryKind, @@ -17,16 +17,16 @@ use super::{ /// Data returned by Machine::stack_pop, /// to provide further control over the popping of the stack frame #[derive(Eq, PartialEq, Debug, Copy, Clone)] -pub enum StackPopInfo { +pub enum StackPopJump { /// Indicates that no special handling should be /// done - we'll either return normally or unwind /// based on the terminator for the function /// we're leaving. Normal, - /// Indicates that we should stop unwinding, - /// as we've reached a catch frame - StopUnwinding, + /// Indicates that we should *not* jump to the return/unwind address, as the callback already + /// took care of everything. + NoJump, } /// Whether this kind of memory is allowed to leak @@ -79,7 +79,7 @@ pub trait AllocMap { /// and some use case dependent behaviour can instead be applied. pub trait Machine<'mir, 'tcx>: Sized { /// Additional memory kinds a machine wishes to distinguish from the builtin ones - type MemoryKinds: ::std::fmt::Debug + MayLeak + Eq + 'static; + type MemoryKind: ::std::fmt::Debug + MayLeak + Eq + 'static; /// Tag tracked alongside every pointer. This is used to implement "Stacked Borrows" /// . @@ -105,16 +105,17 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Memory's allocation map type MemoryMap: AllocMap< AllocId, - (MemoryKind, Allocation), + (MemoryKind, Allocation), > + Default + Clone; - /// The memory kind to use for copied statics -- or None if statics should not be mutated - /// and thus any such attempt will cause a `ModifiedStatic` error to be raised. + /// The memory kind to use for copied global memory (held in `tcx`) -- + /// or None if such memory should not be mutated and thus any such attempt will cause + /// a `ModifiedStatic` error to be raised. /// Statics are copied under two circumstances: When they are mutated, and when - /// `tag_allocation` or `find_foreign_static` (see below) returns an owned allocation + /// `tag_allocation` (see below) returns an owned allocation /// that is added to the memory so that the work is not done twice. - const STATIC_KIND: Option; + const GLOBAL_KIND: Option; /// Whether memory accesses should be alignment-checked. const CHECK_ALIGN: bool; @@ -171,7 +172,7 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Called to evaluate `Abort` MIR terminator. fn abort(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx, !> { - throw_unsup_format!("aborting execution is not supported"); + throw_unsup_format!("aborting execution is not supported") } /// Called for all binary operations where the LHS has pointer type. @@ -207,11 +208,15 @@ pub trait Machine<'mir, 'tcx>: Sized { Ok(()) } - /// Called before a `Static` value is accessed. + /// Called before a global allocation is accessed. + /// `def_id` is `Some` if this is the "lazy" allocation of a static. #[inline] - fn before_access_static( + fn before_access_global( _memory_extra: &Self::MemoryExtra, + _alloc_id: AllocId, _allocation: &Allocation, + _static_def_id: Option, + _is_write: bool, ) -> InterpResult<'tcx> { Ok(()) } @@ -231,10 +236,10 @@ pub trait Machine<'mir, 'tcx>: Sized { /// it contains (in relocations) tagged. The way we construct allocations is /// to always first construct it without extra and then add the extra. /// This keeps uniform code paths for handling both allocations created by CTFE - /// for statics, and allocations created by Miri during evaluation. + /// for globals, and allocations created by Miri during evaluation. /// /// `kind` is the kind of the allocation being tagged; it can be `None` when - /// it's a static and `STATIC_KIND` is `None`. + /// it's a global and `GLOBAL_KIND` is `None`. /// /// This should avoid copying if no work has to be done! If this returns an owned /// allocation (because a copy had to be done to add tags or metadata), machine memory will @@ -243,20 +248,20 @@ pub trait Machine<'mir, 'tcx>: Sized { /// /// Also return the "base" tag to use for this allocation: the one that is used for direct /// accesses to this allocation. If `kind == STATIC_KIND`, this tag must be consistent - /// with `tag_static_base_pointer`. + /// with `tag_global_base_pointer`. fn init_allocation_extra<'b>( memory_extra: &Self::MemoryExtra, id: AllocId, alloc: Cow<'b, Allocation>, - kind: Option>, + kind: Option>, ) -> (Cow<'b, Allocation>, Self::PointerTag); - /// Return the "base" tag for the given *static* allocation: the one that is used for direct - /// accesses to this static/const/fn allocation. If `id` is not a static allocation, + /// Return the "base" tag for the given *global* allocation: the one that is used for direct + /// accesses to this static/const/fn allocation. If `id` is not a global allocation, /// this will return an unusable tag (i.e., accesses will be UB)! /// /// Expects `id` to be already canonical, if needed. - fn tag_static_base_pointer(memory_extra: &Self::MemoryExtra, id: AllocId) -> Self::PointerTag; + fn tag_global_base_pointer(memory_extra: &Self::MemoryExtra, id: AllocId) -> Self::PointerTag; /// Executes a retagging operation #[inline] @@ -276,9 +281,9 @@ pub trait Machine<'mir, 'tcx>: Sized { _ecx: &mut InterpCx<'mir, 'tcx, Self>, _extra: Self::FrameExtra, _unwinding: bool, - ) -> InterpResult<'tcx, StackPopInfo> { + ) -> InterpResult<'tcx, StackPopJump> { // By default, we do not support unwinding from panics - Ok(StackPopInfo::Normal) + Ok(StackPopJump::Normal) } fn int_to_ptr( @@ -286,8 +291,10 @@ pub trait Machine<'mir, 'tcx>: Sized { int: u64, ) -> InterpResult<'tcx, Pointer> { Err((if int == 0 { - err_unsup!(InvalidNullPointerUsage) + // This is UB, seriously. + err_ub!(InvalidIntPointerUsage(0)) } else { + // This is just something we cannot support during const-eval. err_unsup!(ReadBytesAsPointer) }) .into()) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 82a467c7ba92c..8437399752e29 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -8,6 +8,7 @@ use std::borrow::Cow; use std::collections::VecDeque; +use std::convert::TryFrom; use std::ptr; use rustc::ty::layout::{Align, HasDataLayout, Size, TargetDataLayout}; @@ -80,12 +81,12 @@ pub struct Memory<'mir, 'tcx, M: Machine<'mir, 'tcx>> { /// Allocations local to this instance of the miri engine. The kind /// helps ensure that the same mechanism is used for allocation and /// deallocation. When an allocation is not found here, it is a - /// static and looked up in the `tcx` for read access. Some machines may - /// have to mutate this map even on a read-only access to a static (because + /// global and looked up in the `tcx` for read access. Some machines may + /// have to mutate this map even on a read-only access to a global (because /// they do pointer provenance tracking and the allocations in `tcx` have /// the wrong type), so we let the machine override this type. - /// Either way, if the machine allows writing to a static, doing so will - /// create a copy of the static allocation here. + /// Either way, if the machine allows writing to a global, doing so will + /// create a copy of the global allocation here. // FIXME: this should not be public, but interning currently needs access to it pub(super) alloc_map: M::MemoryMap, @@ -112,25 +113,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for Memory<'mir, 'tcx, M> } } -// FIXME: Really we shouldn't clone memory, ever. Snapshot machinery should instead -// carefully copy only the reachable parts. -impl<'mir, 'tcx, M> Clone for Memory<'mir, 'tcx, M> -where - M: Machine<'mir, 'tcx, PointerTag = (), AllocExtra = ()>, - M::MemoryExtra: Copy, - M::MemoryMap: AllocMap, Allocation)>, -{ - fn clone(&self) -> Self { - Memory { - alloc_map: self.alloc_map.clone(), - extra_fn_ptr_map: self.extra_fn_ptr_map.clone(), - dead_alloc_map: self.dead_alloc_map.clone(), - extra: self.extra, - tcx: self.tcx, - } - } -} - impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { pub fn new(tcx: TyCtxtAt<'tcx>, extra: M::MemoryExtra) -> Self { Memory { @@ -149,9 +131,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { /// This represents a *direct* access to that memory, as opposed to access /// through a pointer that was created by the program. #[inline] - pub fn tag_static_base_pointer(&self, ptr: Pointer) -> Pointer { + pub fn tag_global_base_pointer(&self, ptr: Pointer) -> Pointer { let id = M::canonical_alloc_id(self, ptr.alloc_id); - ptr.with_tag(M::tag_static_base_pointer(&self.extra, id)) + ptr.with_tag(M::tag_global_base_pointer(&self.extra, id)) } pub fn create_fn_alloc( @@ -168,23 +150,23 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { id } }; - self.tag_static_base_pointer(Pointer::from(id)) + self.tag_global_base_pointer(Pointer::from(id)) } pub fn allocate( &mut self, size: Size, align: Align, - kind: MemoryKind, + kind: MemoryKind, ) -> Pointer { let alloc = Allocation::undef(size, align); self.allocate_with(alloc, kind) } - pub fn allocate_static_bytes( + pub fn allocate_bytes( &mut self, bytes: &[u8], - kind: MemoryKind, + kind: MemoryKind, ) -> Pointer { let alloc = Allocation::from_byte_aligned_bytes(bytes); self.allocate_with(alloc, kind) @@ -193,13 +175,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { pub fn allocate_with( &mut self, alloc: Allocation, - kind: MemoryKind, + kind: MemoryKind, ) -> Pointer { let id = self.tcx.alloc_map.lock().reserve(); debug_assert_ne!( Some(kind), - M::STATIC_KIND.map(MemoryKind::Machine), - "dynamically allocating static memory" + M::GLOBAL_KIND.map(MemoryKind::Machine), + "dynamically allocating global memory" ); let (alloc, tag) = M::init_allocation_extra(&self.extra, id, Cow::Owned(alloc), Some(kind)); self.alloc_map.insert(id, (kind, alloc.into_owned())); @@ -212,10 +194,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { old_size_and_align: Option<(Size, Align)>, new_size: Size, new_align: Align, - kind: MemoryKind, + kind: MemoryKind, ) -> InterpResult<'tcx, Pointer> { if ptr.offset.bytes() != 0 { - throw_unsup!(ReallocateNonBasePtr) + throw_ub_format!( + "reallocating {:?} which does not point to the beginning of an object", + ptr + ); } // For simplicities' sake, we implement reallocate as "alloc, copy, dealloc". @@ -231,9 +216,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { Ok(new_ptr) } - /// Deallocate a local, or do nothing if that local has been made into a static + /// Deallocate a local, or do nothing if that local has been made into a global. pub fn deallocate_local(&mut self, ptr: Pointer) -> InterpResult<'tcx> { - // The allocation might be already removed by static interning. + // The allocation might be already removed by global interning. // This can only really happen in the CTFE instance, not in miri. if self.alloc_map.contains_key(&ptr.alloc_id) { self.deallocate(ptr, None, MemoryKind::Stack) @@ -246,42 +231,48 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { &mut self, ptr: Pointer, old_size_and_align: Option<(Size, Align)>, - kind: MemoryKind, + kind: MemoryKind, ) -> InterpResult<'tcx> { trace!("deallocating: {}", ptr.alloc_id); if ptr.offset.bytes() != 0 { - throw_unsup!(DeallocateNonBasePtr) + throw_ub_format!( + "deallocating {:?} which does not point to the beginning of an object", + ptr + ); } let (alloc_kind, mut alloc) = match self.alloc_map.remove(&ptr.alloc_id) { Some(alloc) => alloc, None => { - // Deallocating static memory -- always an error + // Deallocating global memory -- always an error return Err(match self.tcx.alloc_map.lock().get(ptr.alloc_id) { - Some(GlobalAlloc::Function(..)) => err_unsup!(DeallocatedWrongMemoryKind( - "function".to_string(), - format!("{:?}", kind), - )), - Some(GlobalAlloc::Static(..)) | Some(GlobalAlloc::Memory(..)) => err_unsup!( - DeallocatedWrongMemoryKind("static".to_string(), format!("{:?}", kind)) - ), - None => err_unsup!(DoubleFree), + Some(GlobalAlloc::Function(..)) => err_ub_format!("deallocating a function"), + Some(GlobalAlloc::Static(..)) | Some(GlobalAlloc::Memory(..)) => { + err_ub_format!("deallocating static memory") + } + None => err_ub!(PointerUseAfterFree(ptr.alloc_id)), } .into()); } }; if alloc_kind != kind { - throw_unsup!(DeallocatedWrongMemoryKind( - format!("{:?}", alloc_kind), - format!("{:?}", kind), - )) + throw_ub_format!( + "deallocating `{:?}` memory using `{:?}` deallocation operation", + alloc_kind, + kind + ); } if let Some((size, align)) = old_size_and_align { if size != alloc.size || align != alloc.align { - let bytes = alloc.size; - throw_unsup!(IncorrectAllocationInformation(size, bytes, align, alloc.align)) + throw_ub_format!( + "incorrect layout on deallocation: allocation has size {} and alignment {}, but gave size {} and alignment {}", + alloc.size.bytes(), + alloc.align.bytes(), + size.bytes(), + align.bytes(), + ) } } @@ -338,7 +329,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } else { // The biggest power of two through which `offset` is divisible. let offset_pow2 = 1 << offset.trailing_zeros(); - throw_unsup!(AlignmentCheckFailed { + throw_ub!(AlignmentCheckFailed { has: Align::from_bytes(offset_pow2).unwrap(), required: align, }) @@ -356,11 +347,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { }; Ok(match normalized.to_bits_or_ptr(self.pointer_size(), self) { Ok(bits) => { - let bits = bits as u64; // it's ptr-sized + let bits = u64::try_from(bits).unwrap(); // it's ptr-sized assert!(size.bytes() == 0); // Must be non-NULL. if bits == 0 { - throw_unsup!(InvalidNullPointerUsage) + throw_ub!(InvalidIntPointerUsage(0)) } // Must be aligned. if let Some(align) = align { @@ -375,7 +366,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // It is sufficient to check this for the end pointer. The addition // checks for overflow. let end_ptr = ptr.offset(size, self)?; - end_ptr.check_inbounds_alloc(allocation_size, msg)?; + if end_ptr.offset > allocation_size { + // equal is okay! + throw_ub!(PointerOutOfBounds { ptr: end_ptr.erase_tag(), msg, allocation_size }) + } // Test align. Check this last; if both bounds and alignment are violated // we want the error to be about the bounds. if let Some(align) = align { @@ -385,7 +379,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // got picked we might be aligned even if this check fails. // We instead have to fall back to converting to an integer and checking // the "real" alignment. - throw_unsup!(AlignmentCheckFailed { has: alloc_align, required: align }); + throw_ub!(AlignmentCheckFailed { has: alloc_align, required: align }); } check_offset_align(ptr.offset.bytes(), align)?; } @@ -402,49 +396,53 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { let (size, _align) = self .get_size_and_align(ptr.alloc_id, AllocCheck::MaybeDead) .expect("alloc info with MaybeDead cannot fail"); - ptr.check_inbounds_alloc(size, CheckInAllocMsg::NullPointerTest).is_err() + // If the pointer is out-of-bounds, it may be null. + // Note that one-past-the-end (offset == size) is still inbounds, and never null. + ptr.offset > size } } /// Allocation accessors impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { - /// Helper function to obtain the global (tcx) allocation for a static. + /// Helper function to obtain a global (tcx) allocation. /// This attempts to return a reference to an existing allocation if /// one can be found in `tcx`. That, however, is only possible if `tcx` and /// this machine use the same pointer tag, so it is indirected through /// `M::tag_allocation`. - /// - /// Notice that every static has two `AllocId` that will resolve to the same - /// thing here: one maps to `GlobalAlloc::Static`, this is the "lazy" ID, - /// and the other one is maps to `GlobalAlloc::Memory`, this is returned by - /// `const_eval_raw` and it is the "resolved" ID. - /// The resolved ID is never used by the interpreted progrma, it is hidden. - /// The `GlobalAlloc::Memory` branch here is still reachable though; when a static - /// contains a reference to memory that was created during its evaluation (i.e., not to - /// another static), those inner references only exist in "resolved" form. - /// - /// Assumes `id` is already canonical. - fn get_static_alloc( + fn get_global_alloc( memory_extra: &M::MemoryExtra, tcx: TyCtxtAt<'tcx>, id: AllocId, + is_write: bool, ) -> InterpResult<'tcx, Cow<'tcx, Allocation>> { let alloc = tcx.alloc_map.lock().get(id); - let alloc = match alloc { - Some(GlobalAlloc::Memory(mem)) => Cow::Borrowed(mem), - Some(GlobalAlloc::Function(..)) => throw_unsup!(DerefFunctionPointer), - None => throw_unsup!(DanglingPointerDeref), + let (alloc, def_id) = match alloc { + Some(GlobalAlloc::Memory(mem)) => { + // Memory of a constant or promoted or anonymous memory referenced by a static. + (mem, None) + } + Some(GlobalAlloc::Function(..)) => throw_ub!(DerefFunctionPointer(id)), + None => throw_ub!(PointerUseAfterFree(id)), Some(GlobalAlloc::Static(def_id)) => { - // We got a "lazy" static that has not been computed yet. + // Notice that every static has two `AllocId` that will resolve to the same + // thing here: one maps to `GlobalAlloc::Static`, this is the "lazy" ID, + // and the other one is maps to `GlobalAlloc::Memory`, this is returned by + // `const_eval_raw` and it is the "resolved" ID. + // The resolved ID is never used by the interpreted progrma, it is hidden. + // The `GlobalAlloc::Memory` branch here is still reachable though; when a static + // contains a reference to memory that was created during its evaluation (i.e., not + // to another static), those inner references only exist in "resolved" form. + // + // Assumes `id` is already canonical. if tcx.is_foreign_item(def_id) { - trace!("get_static_alloc: foreign item {:?}", def_id); - throw_unsup!(ReadForeignStatic) + trace!("get_global_alloc: foreign item {:?}", def_id); + throw_unsup!(ReadForeignStatic(def_id)) } - trace!("get_static_alloc: Need to compute {:?}", def_id); + trace!("get_global_alloc: Need to compute {:?}", def_id); let instance = Instance::mono(tcx.tcx, def_id); let gid = GlobalId { instance, promoted: None }; - // use the raw query here to break validation cycles. Later uses of the static - // will call the full query anyway + // Use the raw query here to break validation cycles. Later uses of the static + // will call the full query anyway. let raw_const = tcx.const_eval_raw(ty::ParamEnv::reveal_all().and(gid)).map_err(|err| { // no need to report anything, the const_eval call takes care of that @@ -459,23 +457,24 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { let id = raw_const.alloc_id; let allocation = tcx.alloc_map.lock().unwrap_memory(id); - M::before_access_static(memory_extra, allocation)?; - Cow::Borrowed(allocation) + (allocation, Some(def_id)) } }; + M::before_access_global(memory_extra, id, alloc, def_id, is_write)?; + let alloc = Cow::Borrowed(alloc); // We got tcx memory. Let the machine initialize its "extra" stuff. let (alloc, tag) = M::init_allocation_extra( memory_extra, id, // always use the ID we got as input, not the "hidden" one. alloc, - M::STATIC_KIND.map(MemoryKind::Machine), + M::GLOBAL_KIND.map(MemoryKind::Machine), ); - debug_assert_eq!(tag, M::tag_static_base_pointer(memory_extra, id)); + debug_assert_eq!(tag, M::tag_global_base_pointer(memory_extra, id)); Ok(alloc) } /// Gives raw access to the `Allocation`, without bounds or alignment checks. - /// Use the higher-level, `PlaceTy`- and `OpTy`-based APIs in `InterpCtx` instead! + /// Use the higher-level, `PlaceTy`- and `OpTy`-based APIs in `InterpCx` instead! pub fn get_raw( &self, id: AllocId, @@ -483,10 +482,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { let id = M::canonical_alloc_id(self, id); // The error type of the inner closure here is somewhat funny. We have two // ways of "erroring": An actual error, or because we got a reference from - // `get_static_alloc` that we can actually use directly without inserting anything anywhere. + // `get_global_alloc` that we can actually use directly without inserting anything anywhere. // So the error type is `InterpResult<'tcx, &Allocation>`. let a = self.alloc_map.get_or(id, || { - let alloc = Self::get_static_alloc(&self.extra, self.tcx, id).map_err(Err)?; + let alloc = Self::get_global_alloc(&self.extra, self.tcx, id, /*is_write*/ false) + .map_err(Err)?; match alloc { Cow::Borrowed(alloc) => { // We got a ref, cheaply return that as an "error" so that the @@ -495,8 +495,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } Cow::Owned(alloc) => { // Need to put it into the map and return a ref to that - let kind = M::STATIC_KIND.expect( - "I got an owned allocation that I have to copy but the machine does \ + let kind = M::GLOBAL_KIND.expect( + "I got a global allocation that I have to copy but the machine does \ not expect that to happen", ); Ok((MemoryKind::Machine(kind), alloc)) @@ -511,7 +511,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } /// Gives raw mutable access to the `Allocation`, without bounds or alignment checks. - /// Use the higher-level, `PlaceTy`- and `OpTy`-based APIs in `InterpCtx` instead! + /// Use the higher-level, `PlaceTy`- and `OpTy`-based APIs in `InterpCx` instead! pub fn get_raw_mut( &mut self, id: AllocId, @@ -520,16 +520,17 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { let tcx = self.tcx; let memory_extra = &self.extra; let a = self.alloc_map.get_mut_or(id, || { - // Need to make a copy, even if `get_static_alloc` is able + // Need to make a copy, even if `get_global_alloc` is able // to give us a cheap reference. - let alloc = Self::get_static_alloc(memory_extra, tcx, id)?; + let alloc = Self::get_global_alloc(memory_extra, tcx, id, /*is_write*/ true)?; if alloc.mutability == Mutability::Not { - throw_unsup!(ModifiedConstantMemory) - } - match M::STATIC_KIND { - Some(kind) => Ok((MemoryKind::Machine(kind), alloc.into_owned())), - None => throw_unsup!(ModifiedStatic), + throw_ub!(WriteToReadOnly(id)) } + let kind = M::GLOBAL_KIND.expect( + "I got a global allocation that I have to copy but the machine does \ + not expect that to happen", + ); + Ok((MemoryKind::Machine(kind), alloc.into_owned())) }); // Unpack the error type manually because type inference doesn't // work otherwise (and we cannot help it because `impl Trait`) @@ -538,7 +539,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { Ok(a) => { let a = &mut a.1; if a.mutability == Mutability::Not { - throw_unsup!(ModifiedConstantMemory) + throw_ub!(WriteToReadOnly(id)) } Ok(a) } @@ -558,7 +559,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // # Regular allocations // Don't use `self.get_raw` here as that will // a) cause cycles in case `id` refers to a static - // b) duplicate a static's allocation in miri + // b) duplicate a global's allocation in miri if let Some((_, alloc)) = self.alloc_map.get(id) { return Ok((alloc.size, alloc.align)); } @@ -568,7 +569,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { if self.get_fn_alloc(id).is_some() { return if let AllocCheck::Dereferenceable = liveness { // The caller requested no function pointers. - throw_unsup!(DerefFunctionPointer) + throw_ub!(DerefFunctionPointer(id)) } else { Ok((Size::ZERO, Align::from_bytes(1).unwrap())) }; @@ -596,12 +597,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { if let AllocCheck::MaybeDead = liveness { // Deallocated pointers are allowed, we should be able to find // them in the map. - Ok(*self.dead_alloc_map.get(&id).expect( - "deallocated pointers should all be recorded in \ - `dead_alloc_map`", - )) + Ok(*self + .dead_alloc_map + .get(&id) + .expect("deallocated pointers should all be recorded in `dead_alloc_map`")) } else { - throw_unsup!(DanglingPointerDeref) + throw_ub!(PointerUseAfterFree(id)) } } } @@ -626,10 +627,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { ) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> { let ptr = self.force_ptr(ptr)?; // We definitely need a pointer value. if ptr.offset.bytes() != 0 { - throw_unsup!(InvalidFunctionPointer) + throw_ub!(InvalidFunctionPointer(ptr.erase_tag())) } let id = M::canonical_alloc_id(self, ptr.alloc_id); - self.get_fn_alloc(id).ok_or_else(|| err_unsup!(ExecuteMemory).into()) + self.get_fn_alloc(id).ok_or_else(|| err_ub!(InvalidFunctionPointer(ptr.erase_tag())).into()) } pub fn mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx> { @@ -667,7 +668,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } if alloc.undef_mask().is_range_defined(i, i + Size::from_bytes(1)).is_ok() { // this `as usize` is fine, since `i` came from a `usize` - let i = i.bytes() as usize; + let i = i.bytes_usize(); // Checked definedness (and thus range) and relocations. This access also doesn't // influence interpreter execution but is only for debugging. @@ -692,8 +693,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { let mut pos = Size::ZERO; let relocation_width = (self.pointer_size().bytes() - 1) * 3; for (i, target_id) in relocations { - // this `as usize` is fine, since we can't print more chars than `usize::MAX` - write!(msg, "{:1$}", "", ((i - pos) * 3).bytes() as usize).unwrap(); + write!(msg, "{:1$}", "", ((i - pos) * 3).bytes_usize()).unwrap(); let target = format!("({})", target_id); // this `as usize` is fine, since we can't print more chars than `usize::MAX` write!(msg, "└{0:─^1$}┘ ", target, relocation_width as usize).unwrap(); @@ -733,7 +733,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { ); } Err(()) => { - // static alloc? + // global alloc? match self.tcx.alloc_map.lock().get(id) { Some(GlobalAlloc::Memory(alloc)) => { self.dump_alloc_helper( @@ -834,8 +834,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { src: impl IntoIterator, ) -> InterpResult<'tcx> { let src = src.into_iter(); - let size = Size::from_bytes(src.size_hint().0 as u64); - // `write_bytes` checks that this lower bound matches the upper bound matches reality. + let size = Size::from_bytes(src.size_hint().0); + // `write_bytes` checks that this lower bound `size` matches the upper bound and reality. let ptr = match self.check_ptr_access(ptr, size, Align::from_bytes(1).unwrap())? { Some(ptr) => ptr, None => return Ok(()), // zero-sized access @@ -874,14 +874,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { let tcx = self.tcx.tcx; - // The bits have to be saved locally before writing to dest in case src and dest overlap. - assert_eq!(size.bytes() as usize as u64, size.bytes()); - // This checks relocation edges on the src. let src_bytes = self.get_raw(src.alloc_id)?.get_bytes_with_undef_and_ptr(&tcx, src, size)?.as_ptr(); let dest_bytes = - self.get_raw_mut(dest.alloc_id)?.get_bytes_mut(&tcx, dest, size * length)?; + self.get_raw_mut(dest.alloc_id)?.get_bytes_mut(&tcx, dest, size * length)?; // `Size` multiplication // If `dest_bytes` is empty we just optimize to not run anything for zsts. // See #67539 @@ -902,7 +899,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // touched if the bytes stay undef for the whole interpreter execution. On contemporary // operating system this can avoid physically allocating the page. let dest_alloc = self.get_raw_mut(dest.alloc_id)?; - dest_alloc.mark_definedness(dest, size * length, false); + dest_alloc.mark_definedness(dest, size * length, false); // `Size` multiplication dest_alloc.mark_relocation_range(relocations); return Ok(()); } @@ -913,9 +910,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // The pointers above remain valid even if the `HashMap` table is moved around because they // point into the `Vec` storing the bytes. unsafe { - assert_eq!(size.bytes() as usize as u64, size.bytes()); if src.alloc_id == dest.alloc_id { if nonoverlapping { + // `Size` additions if (src.offset <= dest.offset && src.offset + size > dest.offset) || (dest.offset <= src.offset && dest.offset + size > src.offset) { @@ -926,16 +923,16 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { for i in 0..length { ptr::copy( src_bytes, - dest_bytes.offset((size.bytes() * i) as isize), - size.bytes() as usize, + dest_bytes.add((size * i).bytes_usize()), // `Size` multiplication + size.bytes_usize(), ); } } else { for i in 0..length { ptr::copy_nonoverlapping( src_bytes, - dest_bytes.offset((size.bytes() * i) as isize), - size.bytes() as usize, + dest_bytes.add((size * i).bytes_usize()), // `Size` multiplication + size.bytes_usize(), ); } } @@ -975,7 +972,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { ) -> InterpResult<'tcx, u128> { match scalar.to_bits_or_ptr(size, self) { Ok(bits) => Ok(bits), - Err(ptr) => Ok(M::ptr_to_int(&self, ptr)? as u128), + Err(ptr) => Ok(M::ptr_to_int(&self, ptr)?.into()), } } } diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs index a519f38e71208..3063a99886b7b 100644 --- a/src/librustc_mir/interpret/mod.rs +++ b/src/librustc_mir/interpret/mod.rs @@ -9,7 +9,6 @@ mod memory; mod operand; mod operator; mod place; -pub(crate) mod snapshot; // for const_eval mod step; mod terminator; mod traits; @@ -24,7 +23,7 @@ pub use self::place::{MPlaceTy, MemPlace, MemPlaceMeta, Place, PlaceTy}; pub use self::memory::{AllocCheck, FnVal, Memory, MemoryKind}; -pub use self::machine::{AllocMap, Machine, MayLeak, StackPopInfo}; +pub use self::machine::{AllocMap, Machine, MayLeak, StackPopJump}; pub use self::operand::{ImmTy, Immediate, OpTy, Operand, ScalarMaybeUndef}; diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 22b1a7b7137d9..8e2a0ca9b0214 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -1,20 +1,22 @@ //! Functions concerning immediate values and operands, and reading from operands. //! All high-level functions to read from memory work on operands as sources. -use std::convert::{TryFrom, TryInto}; - -use rustc::ty::layout::{ - self, HasDataLayout, IntegerExt, LayoutOf, PrimitiveExt, Size, TyLayout, VariantIdx, -}; -use rustc::{mir, ty}; +use std::convert::TryFrom; use super::{InterpCx, MPlaceTy, Machine, MemPlace, Place, PlaceTy}; pub use rustc::mir::interpret::ScalarMaybeUndef; use rustc::mir::interpret::{ sign_extend, truncate, AllocId, ConstValue, GlobalId, InterpResult, Pointer, Scalar, }; -use rustc_ast::ast; +use rustc::ty::layout::{ + self, HasDataLayout, IntegerExt, LayoutOf, PrimitiveExt, Size, TyLayout, VariantIdx, +}; +use rustc::ty::print::{FmtPrinter, PrettyPrinter, Printer}; +use rustc::ty::Ty; +use rustc::{mir, ty}; +use rustc_hir::def::Namespace; use rustc_macros::HashStable; +use std::fmt::Write; /// An `Immediate` represents a single immediate self-contained Rust value. /// @@ -92,47 +94,44 @@ pub struct ImmTy<'tcx, Tag = ()> { pub layout: TyLayout<'tcx>, } -// `Tag: Copy` because some methods on `Scalar` consume them by value impl std::fmt::Display for ImmTy<'tcx, Tag> { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match &self.imm { - // We cannot use `to_bits_or_ptr` as we do not have a `tcx`. - // So we use `is_bits` and circumvent a bunch of sanity checking -- but - // this is anyway only for printing. - Immediate::Scalar(ScalarMaybeUndef::Scalar(s)) if s.is_ptr() => { - fmt.write_str("{pointer}") + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + /// Helper function for printing a scalar to a FmtPrinter + fn p<'a, 'tcx, F: std::fmt::Write, Tag>( + cx: FmtPrinter<'a, 'tcx, F>, + s: ScalarMaybeUndef, + ty: Ty<'tcx>, + ) -> Result, std::fmt::Error> { + match s { + ScalarMaybeUndef::Scalar(s) => { + cx.pretty_print_const_scalar(s.erase_tag(), ty, true) + } + ScalarMaybeUndef::Undef => cx.typed_value( + |mut this| { + this.write_str("{undef ")?; + Ok(this) + }, + |this| this.print_type(ty), + " ", + ), } - Immediate::Scalar(ScalarMaybeUndef::Scalar(s)) => { - let s = s.assert_bits(self.layout.size); - match self.layout.ty.kind { - ty::Int(_) => { - return write!(fmt, "{}", super::sign_extend(s, self.layout.size) as i128,); - } - ty::Uint(_) => return write!(fmt, "{}", s), - ty::Bool if s == 0 => return fmt.write_str("false"), - ty::Bool if s == 1 => return fmt.write_str("true"), - ty::Char => { - if let Some(c) = u32::try_from(s).ok().and_then(std::char::from_u32) { - return write!(fmt, "{}", c); - } - } - ty::Float(ast::FloatTy::F32) => { - if let Ok(u) = u32::try_from(s) { - return write!(fmt, "{}", f32::from_bits(u)); - } - } - ty::Float(ast::FloatTy::F64) => { - if let Ok(u) = u64::try_from(s) { - return write!(fmt, "{}", f64::from_bits(u)); - } + } + ty::tls::with(|tcx| { + match self.imm { + Immediate::Scalar(s) => { + if let Some(ty) = tcx.lift(&self.layout.ty) { + let cx = FmtPrinter::new(tcx, f, Namespace::ValueNS); + p(cx, s, ty)?; + return Ok(()); } - _ => {} + write!(f, "{:?}: {}", s.erase_tag(), self.layout.ty) + } + Immediate::ScalarPair(a, b) => { + // FIXME(oli-obk): at least print tuples and slices nicely + write!(f, "({:?}, {:?}): {}", a.erase_tag(), b.erase_tag(), self.layout.ty,) } - write!(fmt, "{:x}", s) } - Immediate::Scalar(ScalarMaybeUndef::Undef) => fmt.write_str("{undef}"), - Immediate::ScalarPair(..) => fmt.write_str("{wide pointer or tuple}"), - } + }) } } @@ -220,7 +219,7 @@ pub(super) fn from_known_layout<'tcx>( if cfg!(debug_assertions) { let layout2 = compute()?; assert_eq!( - layout.details, layout2.details, + layout.layout, layout2.layout, "mismatch in layout of supposedly equal-layout types {:?} and {:?}", layout.ty, layout2.ty ); @@ -342,9 +341,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Turn the wide MPlace into a string (must already be dereferenced!) pub fn read_str(&self, mplace: MPlaceTy<'tcx, M::PointerTag>) -> InterpResult<'tcx, &str> { let len = mplace.len(self)?; - let bytes = self.memory.read_bytes(mplace.ptr, Size::from_bytes(len as u64))?; + let bytes = self.memory.read_bytes(mplace.ptr, Size::from_bytes(len))?; let str = ::std::str::from_utf8(bytes) - .map_err(|err| err_unsup!(ValidationFailure(err.to_string())))?; + .map_err(|err| err_ub_format!("this string is not valid UTF-8: {}", err))?; Ok(str) } @@ -352,18 +351,17 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { pub fn operand_field( &self, op: OpTy<'tcx, M::PointerTag>, - field: u64, + field: usize, ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { let base = match op.try_as_mplace(self) { Ok(mplace) => { - // The easy case + // We can reuse the mplace field computation logic for indirect operands. let field = self.mplace_field(mplace, field)?; return Ok(field.into()); } Err(value) => value, }; - let field = field.try_into().unwrap(); let field_layout = op.layout.field(self, field)?; if field_layout.is_zst() { let immediate = Scalar::zst().into(); @@ -385,6 +383,21 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(OpTy { op: Operand::Immediate(immediate), layout: field_layout }) } + pub fn operand_index( + &self, + op: OpTy<'tcx, M::PointerTag>, + index: u64, + ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { + if let Ok(index) = usize::try_from(index) { + // We can just treat this as a field. + self.operand_field(op, index) + } else { + // Indexing into a big array. This must be an mplace. + let mplace = op.assert_mem_place(self); + Ok(self.mplace_index(mplace, index)?.into()) + } + } + pub fn operand_downcast( &self, op: OpTy<'tcx, M::PointerTag>, @@ -407,7 +420,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { use rustc::mir::ProjectionElem::*; Ok(match *proj_elem { - Field(field, _) => self.operand_field(base, field.index() as u64)?, + Field(field, _) => self.operand_field(base, field.index())?, Downcast(_, variant) => self.operand_downcast(base, variant)?, Deref => self.deref_operand(base)?.into(), Subslice { .. } | ConstantIndex { .. } | Index(_) => { @@ -458,7 +471,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { layout: Option>, ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { let base_op = match place.local { - mir::RETURN_PLACE => throw_unsup!(ReadFromReturnPointer), + mir::RETURN_PLACE => throw_ub!(ReadFromReturnPlace), local => { // Do not use the layout passed in as argument if the base we are looking at // here is not the entire place. @@ -491,7 +504,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Copy(ref place) | Move(ref place) => self.eval_place_to_op(place, layout)?, Constant(ref constant) => { - let val = self.subst_from_frame_and_normalize_erasing_regions(constant.literal); + let val = + self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal); self.eval_const_to_op(val, layout)? } }; @@ -517,7 +531,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { layout: Option>, ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { let tag_scalar = |scalar| match scalar { - Scalar::Ptr(ptr) => Scalar::Ptr(self.tag_static_base_pointer(ptr)), + Scalar::Ptr(ptr) => Scalar::Ptr(self.tag_global_base_pointer(ptr)), Scalar::Raw { data, size } => Scalar::Raw { data, size }, }; // Early-return cases. @@ -547,7 +561,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let id = self.tcx.alloc_map.lock().create_memory_alloc(alloc); // We rely on mutability being set correctly in that allocation to prevent writes // where none should happen. - let ptr = self.tag_static_base_pointer(Pointer::new(id, offset)); + let ptr = self.tag_global_base_pointer(Pointer::new(id, offset)); Operand::Indirect(MemPlace::from_ptr(ptr, layout.align.abi)) } ConstValue::Scalar(x) => Operand::Immediate(tag_scalar(x).into()), @@ -556,11 +570,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // where none should happen. let ptr = Pointer::new( self.tcx.alloc_map.lock().create_memory_alloc(data), - Size::from_bytes(start as u64), // offset: `start` + Size::from_bytes(start), // offset: `start` ); Operand::Immediate(Immediate::new_slice( - self.tag_static_base_pointer(ptr).into(), - (end - start) as u64, // len: `end - start` + self.tag_global_base_pointer(ptr).into(), + u64::try_from(end.checked_sub(start).unwrap()).unwrap(), // len: `end - start` self, )) } @@ -581,7 +595,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .layout .ty .discriminant_for_variant(*self.tcx, index) - .map_or(index.as_u32() as u128, |discr| discr.val); + .map_or(u128::from(index.as_u32()), |discr| discr.val); return Ok((discr_val, index)); } layout::Variants::Multiple { @@ -593,7 +607,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; // read raw discriminant value - let discr_op = self.operand_field(rval, discr_index as u64)?; + let discr_op = self.operand_field(rval, discr_index)?; let discr_val = self.read_immediate(discr_op)?; let raw_discr = discr_val.to_scalar_or_undef(); trace!("discr value: {:?}", raw_discr); @@ -604,7 +618,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .not_undef() .and_then(|raw_discr| self.force_bits(raw_discr, discr_val.layout.size)) .map_err(|_| err_ub!(InvalidDiscriminant(raw_discr.erase_tag())))?; - let real_discr = if discr_val.layout.ty.is_signed() { + let real_discr = if discr_val.layout.abi.is_signed() { // going from layout tag type to typeck discriminant type // requires first sign extending with the discriminant layout let sexted = sign_extend(bits_discr, discr_val.layout.size) as i128; @@ -657,7 +671,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if !ptr_valid { throw_ub!(InvalidDiscriminant(raw_discr.erase_tag().into())) } - (dataful_variant.as_u32() as u128, dataful_variant) + (u128::from(dataful_variant.as_u32()), dataful_variant) } Ok(raw_discr) => { // We need to use machine arithmetic to get the relative variant idx: @@ -686,7 +700,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .expect("tagged layout for non adt") .variants .len(); - assert!((variant_index as usize) < variants_len); + assert!(usize::try_from(variant_index).unwrap() < variants_len); (u128::from(variant_index), VariantIdx::from_u32(variant_index)) } else { (u128::from(dataful_variant.as_u32()), dataful_variant) diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index f2ee5e047a88e..cb0aaa4d40d3e 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -1,3 +1,5 @@ +use std::convert::TryFrom; + use rustc::mir; use rustc::mir::interpret::{InterpResult, Scalar}; use rustc::ty::{ @@ -64,7 +66,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ge => l >= r, _ => bug!("Invalid operation on char: {:?}", bin_op), }; - return (Scalar::from_bool(res), false, self.tcx.types.bool); + (Scalar::from_bool(res), false, self.tcx.types.bool) } fn binary_bool_op( @@ -87,7 +89,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { BitXor => l ^ r, _ => bug!("Invalid operation on bool: {:?}", bin_op), }; - return (Scalar::from_bool(res), false, self.tcx.types.bool); + (Scalar::from_bool(res), false, self.tcx.types.bool) } fn binary_float_op>>( @@ -113,7 +115,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Rem => ((l % r).value.into(), ty), _ => bug!("invalid float op: `{:?}`", bin_op), }; - return (val, false, ty); + (val, false, ty) } fn binary_int_op( @@ -130,28 +132,27 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Shift ops can have an RHS with a different numeric type. if bin_op == Shl || bin_op == Shr { let signed = left_layout.abi.is_signed(); - let mut oflo = (r as u32 as u128) != r; - let mut r = r as u32; - let size = left_layout.size; - oflo |= r >= size.bits() as u32; - r %= size.bits() as u32; + let size = u128::from(left_layout.size.bits()); + let overflow = r >= size; + let r = r % size; // mask to type size + let r = u32::try_from(r).unwrap(); // we masked so this will always fit let result = if signed { let l = self.sign_extend(l, left_layout) as i128; let result = match bin_op { - Shl => l << r, - Shr => l >> r, + Shl => l.checked_shl(r).unwrap(), + Shr => l.checked_shr(r).unwrap(), _ => bug!("it has already been checked that this is a shift op"), }; result as u128 } else { match bin_op { - Shl => l << r, - Shr => l >> r, + Shl => l.checked_shl(r).unwrap(), + Shr => l.checked_shr(r).unwrap(), _ => bug!("it has already been checked that this is a shift op"), } }; let truncated = self.truncate(result, left_layout); - return Ok((Scalar::from_uint(truncated, size), oflo, left_layout.ty)); + return Ok((Scalar::from_uint(truncated, left_layout.size), overflow, left_layout.ty)); } // For the remaining ops, the types must be the same on both sides @@ -193,7 +194,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { _ => None, }; if let Some(op) = op { - let l128 = self.sign_extend(l, left_layout) as i128; let r = self.sign_extend(r, right_layout) as i128; // We need a special check for overflowing remainder: // "int_min % -1" overflows and returns 0, but after casting things to a larger int @@ -206,8 +206,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } _ => {} } + let l = self.sign_extend(l, left_layout) as i128; - let (result, oflo) = op(l128, r); + let (result, oflo) = op(l, r); // This may be out-of-bounds for the result type, so we have to truncate ourselves. // If that truncation loses any information, we have an overflow. let result = result as u128; diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index a4815b9696ebb..94c9a8b2a6d59 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -212,9 +212,7 @@ impl<'tcx, Tag> MPlaceTy<'tcx, Tag> { if self.layout.is_unsized() { // We need to consult `meta` metadata match self.layout.ty.kind { - ty::Slice(..) | ty::Str => { - return self.mplace.meta.unwrap_meta().to_machine_usize(cx); - } + ty::Slice(..) | ty::Str => self.mplace.meta.unwrap_meta().to_machine_usize(cx), _ => bug!("len not supported on unsized type {:?}", self.layout.ty), } } else { @@ -292,7 +290,7 @@ where Tag: ::std::fmt::Debug + Copy + Eq + Hash + 'static, M: Machine<'mir, 'tcx, PointerTag = Tag>, // FIXME: Working around https://github.com/rust-lang/rust/issues/24159 - M::MemoryMap: AllocMap, Allocation)>, + M::MemoryMap: AllocMap, Allocation)>, M::AllocExtra: AllocationExtra, { /// Take a value, which represents a (thin or wide) reference, and make it a place. @@ -387,51 +385,20 @@ where Ok(place) } - /// Offset a pointer to project to a field. Unlike `place_field`, this is always - /// possible without allocating, so it can take `&self`. Also return the field's layout. + /// Offset a pointer to project to a field of a struct/union. Unlike `place_field`, this is + /// always possible without allocating, so it can take `&self`. Also return the field's layout. /// This supports both struct and array fields. + /// + /// This also works for arrays, but then the `usize` index type is restricting. + /// For indexing into arrays, use `mplace_index`. #[inline(always)] pub fn mplace_field( &self, base: MPlaceTy<'tcx, M::PointerTag>, - field: u64, + field: usize, ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { - // Not using the layout method because we want to compute on u64 - let offset = match base.layout.fields { - layout::FieldPlacement::Arbitrary { ref offsets, .. } => { - offsets[usize::try_from(field).unwrap()] - } - layout::FieldPlacement::Array { stride, .. } => { - let len = base.len(self)?; - if field >= len { - // This can only be reached in ConstProp and non-rustc-MIR. - throw_ub!(BoundsCheckFailed { len, index: field }); - } - stride * field - } - layout::FieldPlacement::Union(count) => { - // This is a narrow bug-fix for rust-lang/rust#69191: if we are - // trying to access absent field of uninhabited variant, then - // signal UB (but don't ICE the compiler). - // FIXME temporary hack to work around incoherence between - // layout computation and MIR building - if field >= count as u64 && base.layout.abi == layout::Abi::Uninhabited { - throw_ub!(Unreachable); - } - assert!( - field < count as u64, - "Tried to access field {} of union {:#?} with {} fields", - field, - base.layout, - count - ); - // Offset is always 0 - Size::from_bytes(0) - } - }; - // the only way conversion can fail if is this is an array (otherwise we already panicked - // above). In that case, all fields are equal. - let field_layout = base.layout.field(self, usize::try_from(field).unwrap_or(0))?; + let offset = base.layout.fields.offset(field); + let field_layout = base.layout.field(self, field)?; // Offset may need adjustment for unsized fields. let (meta, offset) = if field_layout.is_unsized() { @@ -461,6 +428,32 @@ where base.offset(offset, meta, field_layout, self) } + /// Index into an array. + #[inline(always)] + pub fn mplace_index( + &self, + base: MPlaceTy<'tcx, M::PointerTag>, + index: u64, + ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { + // Not using the layout method because we want to compute on u64 + match base.layout.fields { + layout::FieldPlacement::Array { stride, .. } => { + let len = base.len(self)?; + if index >= len { + // This can only be reached in ConstProp and non-rustc-MIR. + throw_ub!(BoundsCheckFailed { len, index }); + } + let offset = stride * index; // `Size` multiplication + // All fields have the same layout. + let field_layout = base.layout.field(self, 0)?; + + assert!(!field_layout.is_unsized()); + base.offset(offset, MemPlaceMeta::None, field_layout, self) + } + _ => bug!("`mplace_index` called on non-array type {:?}", base.layout.ty), + } + } + // Iterates over all fields of an array. Much more efficient than doing the // same by repeatedly calling `mplace_array`. pub(super) fn mplace_array_fields( @@ -475,7 +468,8 @@ where }; let layout = base.layout.field(self, 0)?; let dl = &self.tcx.data_layout; - Ok((0..len).map(move |i| base.offset(i * stride, MemPlaceMeta::None, layout, dl))) + // `Size` multiplication + Ok((0..len).map(move |i| base.offset(stride * i, MemPlaceMeta::None, layout, dl))) } fn mplace_subslice( @@ -487,11 +481,11 @@ where ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { let len = base.len(self)?; // also asserts that we have a type where this makes sense let actual_to = if from_end { - if from + to > len { + if from.checked_add(to).map_or(true, |to| to > len) { // This can only be reached in ConstProp and non-rustc-MIR. - throw_ub!(BoundsCheckFailed { len: len as u64, index: from as u64 + to as u64 }); + throw_ub!(BoundsCheckFailed { len: len, index: from.saturating_add(to) }); } - len - to + len.checked_sub(to).unwrap() } else { to }; @@ -499,12 +493,12 @@ where // Not using layout method because that works with usize, and does not work with slices // (that have count 0 in their layout). let from_offset = match base.layout.fields { - layout::FieldPlacement::Array { stride, .. } => stride * from, + layout::FieldPlacement::Array { stride, .. } => stride * from, // `Size` multiplication is checked _ => bug!("Unexpected layout of index access: {:#?}", base.layout), }; // Compute meta and new layout - let inner_len = actual_to - from; + let inner_len = actual_to.checked_sub(from).unwrap(); let (meta, ty) = match base.layout.ty.kind { // It is not nice to match on the type, but that seems to be the only way to // implement this. @@ -537,7 +531,7 @@ where ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { use rustc::mir::ProjectionElem::*; Ok(match *proj_elem { - Field(field, _) => self.mplace_field(base, field.index() as u64)?, + Field(field, _) => self.mplace_field(base, field.index())?, Downcast(_, variant) => self.mplace_downcast(base, variant)?, Deref => self.deref_operand(base.into())?, @@ -545,26 +539,29 @@ where let layout = self.layout_of(self.tcx.types.usize)?; let n = self.access_local(self.frame(), local, Some(layout))?; let n = self.read_scalar(n)?; - let n = self.force_bits(n.not_undef()?, self.tcx.data_layout.pointer_size)?; - self.mplace_field(base, u64::try_from(n).unwrap())? + let n = u64::try_from( + self.force_bits(n.not_undef()?, self.tcx.data_layout.pointer_size)?, + ) + .unwrap(); + self.mplace_index(base, n)? } ConstantIndex { offset, min_length, from_end } => { let n = base.len(self)?; - if n < min_length as u64 { + if n < u64::from(min_length) { // This can only be reached in ConstProp and non-rustc-MIR. - throw_ub!(BoundsCheckFailed { len: min_length as u64, index: n as u64 }); + throw_ub!(BoundsCheckFailed { len: min_length.into(), index: n.into() }); } let index = if from_end { - assert!(0 < offset && offset - 1 < min_length); - n - u64::from(offset) + assert!(0 < offset && offset <= min_length); + n.checked_sub(u64::from(offset)).unwrap() } else { assert!(offset < min_length); u64::from(offset) }; - self.mplace_field(base, index)? + self.mplace_index(base, index)? } Subslice { from, to, from_end } => { @@ -580,7 +577,7 @@ where pub fn place_field( &mut self, base: PlaceTy<'tcx, M::PointerTag>, - field: u64, + field: usize, ) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> { // FIXME: We could try to be smarter and avoid allocation for fields that span the // entire place. @@ -588,6 +585,15 @@ where Ok(self.mplace_field(mplace, field)?.into()) } + pub fn place_index( + &mut self, + base: PlaceTy<'tcx, M::PointerTag>, + index: u64, + ) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> { + let mplace = self.force_allocation(base)?; + Ok(self.mplace_index(mplace, index)?.into()) + } + pub fn place_downcast( &self, base: PlaceTy<'tcx, M::PointerTag>, @@ -613,7 +619,7 @@ where ) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> { use rustc::mir::ProjectionElem::*; Ok(match *proj_elem { - Field(field, _) => self.place_field(base, field.index() as u64)?, + Field(field, _) => self.place_field(base, field.index())?, Downcast(_, variant) => self.place_downcast(base, variant)?, Deref => self.deref_operand(self.place_to_op(base)?)?.into(), // For the other variants, we have to force an allocation. @@ -648,9 +654,11 @@ where // bail out. None => Place::null(&*self), }, - layout: self.layout_of(self.subst_from_frame_and_normalize_erasing_regions( - self.frame().body.return_ty(), - ))?, + layout: self.layout_of( + self.subst_from_current_frame_and_normalize_erasing_regions( + self.frame().body.return_ty(), + ), + )?, } } local => PlaceTy { @@ -731,7 +739,7 @@ where ), Immediate::Scalar(ScalarMaybeUndef::Scalar(Scalar::Raw { size, .. })) => { assert_eq!( - Size::from_bytes(size.into()), + Size::from_bytes(size), dest.layout.size, "Size mismatch when writing bits" ) @@ -861,7 +869,7 @@ where // We do NOT compare the types for equality, because well-typed code can // actually "transmute" `&mut T` to `&T` in an assignment without a cast. assert!( - src.layout.details == dest.layout.details, + src.layout.layout == dest.layout.layout, "Layout mismatch when copying!\nsrc: {:#?}\ndest: {:#?}", src, dest @@ -915,7 +923,7 @@ where src: OpTy<'tcx, M::PointerTag>, dest: PlaceTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx> { - if src.layout.details == dest.layout.details { + if src.layout.layout == dest.layout.layout { // Fast path: Just use normal `copy_op` return self.copy_op(src, dest); } @@ -926,7 +934,11 @@ where // most likey we *are* running `typeck` right now. Investigate whether we can bail out // on `typeck_tables().has_errors` at all const eval entry points. debug!("Size mismatch when transmuting!\nsrc: {:#?}\ndest: {:#?}", src, dest); - throw_unsup!(TransmuteSizeDiff(src.layout.ty, dest.layout.ty)); + self.tcx.sess.delay_span_bug( + self.tcx.span, + "size-changing transmute, should have been caught by transmute checking", + ); + throw_inval!(TransmuteSizeDiff(src.layout.ty, dest.layout.ty)); } // Unsized copies rely on interpreting `src.meta` with `dest.layout`, we want // to avoid that here. @@ -1019,7 +1031,7 @@ where pub fn allocate( &mut self, layout: TyLayout<'tcx>, - kind: MemoryKind, + kind: MemoryKind, ) -> MPlaceTy<'tcx, M::PointerTag> { let ptr = self.memory.allocate(layout.size, layout.align.abi, kind); MPlaceTy::from_aligned_ptr(ptr, layout) @@ -1029,10 +1041,10 @@ where pub fn allocate_str( &mut self, str: &str, - kind: MemoryKind, + kind: MemoryKind, ) -> MPlaceTy<'tcx, M::PointerTag> { - let ptr = self.memory.allocate_static_bytes(str.as_bytes(), kind); - let meta = Scalar::from_uint(str.len() as u128, self.pointer_size()); + let ptr = self.memory.allocate_bytes(str.as_bytes(), kind); + let meta = Scalar::from_uint(u128::try_from(str.len()).unwrap(), self.pointer_size()); let mplace = MemPlace { ptr: ptr.into(), align: Align::from_bytes(1).unwrap(), @@ -1076,7 +1088,7 @@ where let size = discr_layout.value.size(self); let discr_val = truncate(discr_val, size); - let discr_dest = self.place_field(dest, discr_index as u64)?; + let discr_dest = self.place_field(dest, discr_index)?; self.write_scalar(Scalar::from_uint(discr_val, size), discr_dest)?; } layout::Variants::Multiple { @@ -1107,7 +1119,7 @@ where niche_start_val, )?; // Write result. - let niche_dest = self.place_field(dest, discr_index as u64)?; + let niche_dest = self.place_field(dest, discr_index)?; self.write_immediate(*discr_val, niche_dest)?; } } @@ -1122,7 +1134,7 @@ where ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { // This must be an allocation in `tcx` assert!(self.tcx.alloc_map.lock().get(raw.alloc_id).is_some()); - let ptr = self.tag_static_base_pointer(Pointer::from(raw.alloc_id)); + let ptr = self.tag_global_base_pointer(Pointer::from(raw.alloc_id)); let layout = self.layout_of(raw.ty)?; Ok(MPlaceTy::from_aligned_ptr(ptr, layout)) } diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs deleted file mode 100644 index ee45179fd8b31..0000000000000 --- a/src/librustc_mir/interpret/snapshot.rs +++ /dev/null @@ -1,420 +0,0 @@ -//! This module contains the machinery necessary to detect infinite loops -//! during const-evaluation by taking snapshots of the state of the interpreter -//! at regular intervals. - -// This lives in `interpret` because it needs access to all sots of private state. However, -// it is not used by the general miri engine, just by CTFE. - -use std::hash::{Hash, Hasher}; - -use rustc::ich::StableHashingContextProvider; -use rustc::mir; -use rustc::mir::interpret::{ - AllocId, Allocation, InterpResult, Pointer, Relocations, Scalar, UndefMask, -}; - -use rustc::ty::layout::{Align, Size}; -use rustc::ty::{self, TyCtxt}; -use rustc_ast::ast::Mutability; -use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_index::vec::IndexVec; -use rustc_macros::HashStable; -use rustc_span::source_map::Span; - -use super::eval_context::{LocalState, StackPopCleanup}; -use super::{ - Frame, Immediate, LocalValue, MemPlace, MemPlaceMeta, Memory, Operand, Place, ScalarMaybeUndef, -}; -use crate::const_eval::CompileTimeInterpreter; - -#[derive(Default)] -pub(crate) struct InfiniteLoopDetector<'mir, 'tcx> { - /// The set of all `InterpSnapshot` *hashes* observed by this detector. - /// - /// When a collision occurs in this table, we store the full snapshot in - /// `snapshots`. - hashes: FxHashSet, - - /// The set of all `InterpSnapshot`s observed by this detector. - /// - /// An `InterpSnapshot` will only be fully cloned once it has caused a - /// collision in `hashes`. As a result, the detector must observe at least - /// *two* full cycles of an infinite loop before it triggers. - snapshots: FxHashSet>, -} - -impl<'mir, 'tcx> InfiniteLoopDetector<'mir, 'tcx> { - pub fn observe_and_analyze( - &mut self, - tcx: TyCtxt<'tcx>, - span: Span, - memory: &Memory<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>, - stack: &[Frame<'mir, 'tcx>], - ) -> InterpResult<'tcx, ()> { - // Compute stack's hash before copying anything - let mut hcx = tcx.get_stable_hashing_context(); - let mut hasher = StableHasher::new(); - stack.hash_stable(&mut hcx, &mut hasher); - let hash = hasher.finish::(); - - // Check if we know that hash already - if self.hashes.is_empty() { - // FIXME(#49980): make this warning a lint - tcx.sess.span_warn( - span, - "Constant evaluating a complex constant, this might take some time", - ); - } - if self.hashes.insert(hash) { - // No collision - return Ok(()); - } - - // We need to make a full copy. NOW things that to get really expensive. - info!("snapshotting the state of the interpreter"); - - if self.snapshots.insert(InterpSnapshot::new(memory, stack)) { - // Spurious collision or first cycle - return Ok(()); - } - - // Second cycle - throw_exhaust!(InfiniteLoop) - } -} - -trait SnapshotContext<'a> { - fn resolve(&'a self, id: &AllocId) -> Option<&'a Allocation>; -} - -/// Taking a snapshot of the evaluation context produces a view of -/// the state of the interpreter that is invariant to `AllocId`s. -trait Snapshot<'a, Ctx: SnapshotContext<'a>> { - type Item; - fn snapshot(&self, ctx: &'a Ctx) -> Self::Item; -} - -macro_rules! __impl_snapshot_field { - ($field:ident, $ctx:expr) => { - $field.snapshot($ctx) - }; - ($field:ident, $ctx:expr, $delegate:expr) => { - $delegate - }; -} - -// This assumes the type has two type parameters, first for the tag (set to `()`), -// then for the id -macro_rules! impl_snapshot_for { - (enum $enum_name:ident { - $( $variant:ident $( ( $($field:ident $(-> $delegate:expr)?),* ) )? ),* $(,)? - }) => { - - impl<'a, Ctx> self::Snapshot<'a, Ctx> for $enum_name - where Ctx: self::SnapshotContext<'a>, - { - type Item = $enum_name<(), AllocIdSnapshot<'a>>; - - #[inline] - fn snapshot(&self, __ctx: &'a Ctx) -> Self::Item { - match *self { - $( - $enum_name::$variant $( ( $(ref $field),* ) )? => { - $enum_name::$variant $( - ( $( __impl_snapshot_field!($field, __ctx $(, $delegate)?) ),* ) - )? - } - )* - } - } - } - }; - - (struct $struct_name:ident { $($field:ident $(-> $delegate:expr)?),* $(,)? }) => { - impl<'a, Ctx> self::Snapshot<'a, Ctx> for $struct_name - where Ctx: self::SnapshotContext<'a>, - { - type Item = $struct_name<(), AllocIdSnapshot<'a>>; - - #[inline] - fn snapshot(&self, __ctx: &'a Ctx) -> Self::Item { - let $struct_name { - $(ref $field),* - } = *self; - - $struct_name { - $( $field: __impl_snapshot_field!($field, __ctx $(, $delegate)?) ),* - } - } - } - }; -} - -impl<'a, Ctx, T> Snapshot<'a, Ctx> for Option -where - Ctx: SnapshotContext<'a>, - T: Snapshot<'a, Ctx>, -{ - type Item = Option<>::Item>; - - fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { - match self { - Some(x) => Some(x.snapshot(ctx)), - None => None, - } - } -} - -#[derive(Eq, PartialEq)] -struct AllocIdSnapshot<'a>(Option>); - -impl<'a, Ctx> Snapshot<'a, Ctx> for AllocId -where - Ctx: SnapshotContext<'a>, -{ - type Item = AllocIdSnapshot<'a>; - - fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { - AllocIdSnapshot(ctx.resolve(self).map(|alloc| alloc.snapshot(ctx))) - } -} - -impl_snapshot_for!(struct Pointer { - alloc_id, - offset -> *offset, // just copy offset verbatim - tag -> *tag, // just copy tag -}); - -impl<'a, Ctx> Snapshot<'a, Ctx> for Scalar -where - Ctx: SnapshotContext<'a>, -{ - type Item = Scalar<(), AllocIdSnapshot<'a>>; - - fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { - match self { - Scalar::Ptr(p) => Scalar::Ptr(p.snapshot(ctx)), - Scalar::Raw { size, data } => Scalar::Raw { data: *data, size: *size }, - } - } -} - -impl_snapshot_for!( - enum ScalarMaybeUndef { - Scalar(s), - Undef, - } -); - -impl_snapshot_for!( - enum MemPlaceMeta { - Meta(s), - None, - Poison, - } -); - -impl_snapshot_for!(struct MemPlace { - ptr, - meta, - align -> *align, // just copy alignment verbatim -}); - -impl<'a, Ctx> Snapshot<'a, Ctx> for Place -where - Ctx: SnapshotContext<'a>, -{ - type Item = Place<(), AllocIdSnapshot<'a>>; - - fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { - match self { - Place::Ptr(p) => Place::Ptr(p.snapshot(ctx)), - - Place::Local { frame, local } => Place::Local { frame: *frame, local: *local }, - } - } -} - -impl_snapshot_for!( - enum Immediate { - Scalar(s), - ScalarPair(s, t), - } -); - -impl_snapshot_for!( - enum Operand { - Immediate(v), - Indirect(m), - } -); - -impl_snapshot_for!( - enum LocalValue { - Dead, - Uninitialized, - Live(v), - } -); - -impl<'a, Ctx> Snapshot<'a, Ctx> for Relocations -where - Ctx: SnapshotContext<'a>, -{ - type Item = Relocations<(), AllocIdSnapshot<'a>>; - - fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { - Relocations::from_presorted( - self.iter().map(|(size, ((), id))| (*size, ((), id.snapshot(ctx)))).collect(), - ) - } -} - -#[derive(Eq, PartialEq)] -struct AllocationSnapshot<'a> { - bytes: &'a [u8], - relocations: Relocations<(), AllocIdSnapshot<'a>>, - undef_mask: &'a UndefMask, - align: &'a Align, - size: &'a Size, - mutability: &'a Mutability, -} - -impl<'a, Ctx> Snapshot<'a, Ctx> for &'a Allocation -where - Ctx: SnapshotContext<'a>, -{ - type Item = AllocationSnapshot<'a>; - - fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { - let Allocation { size, align, mutability, extra: (), .. } = self; - - let all_bytes = 0..self.len(); - // This 'inspect' is okay since following access respects undef and relocations. This does - // influence interpreter exeuction, but only to detect the error of cycles in evaluation - // dependencies. - let bytes = self.inspect_with_undef_and_ptr_outside_interpreter(all_bytes); - - let undef_mask = self.undef_mask(); - let relocations = self.relocations(); - - AllocationSnapshot { - bytes, - undef_mask, - align, - size, - mutability, - relocations: relocations.snapshot(ctx), - } - } -} - -#[derive(Eq, PartialEq)] -struct FrameSnapshot<'a, 'tcx> { - instance: ty::Instance<'tcx>, - span: Span, - return_to_block: &'a StackPopCleanup, - return_place: Option>>, - locals: IndexVec>>, - block: Option, - stmt: usize, -} - -impl<'a, 'mir, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a Frame<'mir, 'tcx> -where - Ctx: SnapshotContext<'a>, -{ - type Item = FrameSnapshot<'a, 'tcx>; - - fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { - let Frame { - body: _, - instance, - span, - return_to_block, - return_place, - locals, - block, - stmt, - extra: _, - } = self; - - FrameSnapshot { - instance: *instance, - span: *span, - return_to_block, - block: *block, - stmt: *stmt, - return_place: return_place.map(|r| r.snapshot(ctx)), - locals: locals.iter().map(|local| local.snapshot(ctx)).collect(), - } - } -} - -impl<'a, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a LocalState<'tcx> -where - Ctx: SnapshotContext<'a>, -{ - type Item = LocalValue<(), AllocIdSnapshot<'a>>; - - fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { - let LocalState { value, layout: _ } = self; - value.snapshot(ctx) - } -} - -impl<'b, 'mir, 'tcx> SnapshotContext<'b> - for Memory<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> -{ - fn resolve(&'b self, id: &AllocId) -> Option<&'b Allocation> { - self.get_raw(*id).ok() - } -} - -/// The virtual machine state during const-evaluation at a given point in time. -/// We assume the `CompileTimeInterpreter` has no interesting extra state that -/// is worth considering here. -#[derive(HashStable)] -struct InterpSnapshot<'mir, 'tcx> { - // Not hashing memory: Avoid hashing memory all the time during execution - #[stable_hasher(ignore)] - memory: Memory<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>, - stack: Vec>, -} - -impl InterpSnapshot<'mir, 'tcx> { - fn new( - memory: &Memory<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>, - stack: &[Frame<'mir, 'tcx>], - ) -> Self { - InterpSnapshot { memory: memory.clone(), stack: stack.into() } - } - - // Used to compare two snapshots - fn snapshot(&'b self) -> Vec> { - // Start with the stack, iterate and recursively snapshot - self.stack.iter().map(|frame| frame.snapshot(&self.memory)).collect() - } -} - -impl<'mir, 'tcx> Hash for InterpSnapshot<'mir, 'tcx> { - fn hash(&self, state: &mut H) { - // Implement in terms of hash stable, so that k1 == k2 -> hash(k1) == hash(k2) - let mut hcx = self.memory.tcx.get_stable_hashing_context(); - let mut hasher = StableHasher::new(); - self.hash_stable(&mut hcx, &mut hasher); - hasher.finish::().hash(state) - } -} - -impl<'mir, 'tcx> Eq for InterpSnapshot<'mir, 'tcx> {} - -impl<'mir, 'tcx> PartialEq for InterpSnapshot<'mir, 'tcx> { - fn eq(&self, other: &Self) -> bool { - // FIXME: This looks to be a *ridiculously expensive* comparison operation. - // Doesn't this make tons of copies? Either `snapshot` is very badly named, - // or it does! - self.snapshot() == other.snapshot() - } -} diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index f298a6677d6dc..6ec11d42f52d2 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -192,7 +192,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Ignore zero-sized fields. if !op.layout.is_zst() { let field_index = active_field_index.unwrap_or(i); - let field_dest = self.place_field(dest, field_index as u64)?; + let field_dest = self.place_field(dest, field_index)?; self.copy_op(op, field_dest)?; } } @@ -248,7 +248,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } NullaryOp(mir::NullOp::SizeOf, ty) => { - let ty = self.subst_from_frame_and_normalize_erasing_regions(ty); + let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty); let layout = self.layout_of(ty)?; assert!( !layout.is_unsized(), diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 473ed9d13ecfb..5ce5ba31a0987 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -1,4 +1,5 @@ use std::borrow::Cow; +use std::convert::TryFrom; use rustc::ty::layout::{self, LayoutOf, TyLayout}; use rustc::ty::Instance; @@ -29,6 +30,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { trace!("SwitchInt({:?})", *discr); // Branch to the `otherwise` case by default, if no match is found. + assert!(targets.len() > 0); let mut target_block = targets[targets.len() - 1]; for (index, &const_int) in values.iter().enumerate() { @@ -172,13 +174,19 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { trace!("Skipping callee ZST"); return Ok(()); } - let caller_arg = caller_arg.next().ok_or_else(|| err_unsup!(FunctionArgCountMismatch))?; + let caller_arg = caller_arg.next().ok_or_else(|| { + err_ub_format!("calling a function with fewer arguments than it requires") + })?; if rust_abi { assert!(!caller_arg.layout.is_zst(), "ZSTs must have been already filtered out"); } // Now, check if !Self::check_argument_compat(rust_abi, caller_arg.layout, callee_arg.layout) { - throw_unsup!(FunctionArgMismatch(caller_arg.layout.ty, callee_arg.layout.ty)) + throw_ub_format!( + "calling a function with argument of type {:?} passing data of type {:?}", + callee_arg.layout.ty, + caller_arg.layout.ty + ) } // We allow some transmutes here self.copy_op_transmute(caller_arg, callee_arg) @@ -223,14 +231,18 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { abi => abi, }; if normalize_abi(caller_abi) != normalize_abi(callee_abi) { - throw_unsup!(FunctionAbiMismatch(caller_abi, callee_abi)) + throw_ub_format!( + "calling a function with ABI {:?} using caller ABI {:?}", + callee_abi, + caller_abi + ) } } match instance.def { ty::InstanceDef::Intrinsic(..) => { assert!(caller_abi == Abi::RustIntrinsic || caller_abi == Abi::PlatformIntrinsic); - return M::call_intrinsic(self, span, instance, args, ret, unwind); + M::call_intrinsic(self, span, instance, args, ret, unwind) } ty::InstanceDef::VtableShim(..) | ty::InstanceDef::ReifyShim(..) @@ -253,116 +265,114 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { StackPopCleanup::Goto { ret: ret.map(|p| p.1), unwind }, )?; - // We want to pop this frame again in case there was an error, to put - // the blame in the right location. Until the 2018 edition is used in - // the compiler, we have to do this with an immediately invoked function. - let res = - (|| { - trace!( - "caller ABI: {:?}, args: {:#?}", - caller_abi, - args.iter() - .map(|arg| (arg.layout.ty, format!("{:?}", **arg))) - .collect::>() - ); - trace!( - "spread_arg: {:?}, locals: {:#?}", - body.spread_arg, - body.args_iter() - .map(|local| ( - local, - self.layout_of_local(self.frame(), local, None).unwrap().ty - )) - .collect::>() - ); - - // Figure out how to pass which arguments. - // The Rust ABI is special: ZST get skipped. - let rust_abi = match caller_abi { - Abi::Rust | Abi::RustCall => true, - _ => false, + // If an error is raised here, pop the frame again to get an accurate backtrace. + // To this end, we wrap it all in a `try` block. + let res: InterpResult<'tcx> = try { + trace!( + "caller ABI: {:?}, args: {:#?}", + caller_abi, + args.iter() + .map(|arg| (arg.layout.ty, format!("{:?}", **arg))) + .collect::>() + ); + trace!( + "spread_arg: {:?}, locals: {:#?}", + body.spread_arg, + body.args_iter() + .map(|local| ( + local, + self.layout_of_local(self.frame(), local, None).unwrap().ty + )) + .collect::>() + ); + + // Figure out how to pass which arguments. + // The Rust ABI is special: ZST get skipped. + let rust_abi = match caller_abi { + Abi::Rust | Abi::RustCall => true, + _ => false, + }; + // We have two iterators: Where the arguments come from, + // and where they go to. + + // For where they come from: If the ABI is RustCall, we untuple the + // last incoming argument. These two iterators do not have the same type, + // so to keep the code paths uniform we accept an allocation + // (for RustCall ABI only). + let caller_args: Cow<'_, [OpTy<'tcx, M::PointerTag>]> = + if caller_abi == Abi::RustCall && !args.is_empty() { + // Untuple + let (&untuple_arg, args) = args.split_last().unwrap(); + trace!("eval_fn_call: Will pass last argument by untupling"); + Cow::from( + args.iter() + .map(|&a| Ok(a)) + .chain( + (0..untuple_arg.layout.fields.count()) + .map(|i| self.operand_field(untuple_arg, i)), + ) + .collect::>>>( + )?, + ) + } else { + // Plain arg passing + Cow::from(args) }; - // We have two iterators: Where the arguments come from, - // and where they go to. - - // For where they come from: If the ABI is RustCall, we untuple the - // last incoming argument. These two iterators do not have the same type, - // so to keep the code paths uniform we accept an allocation - // (for RustCall ABI only). - let caller_args: Cow<'_, [OpTy<'tcx, M::PointerTag>]> = - if caller_abi == Abi::RustCall && !args.is_empty() { - // Untuple - let (&untuple_arg, args) = args.split_last().unwrap(); - trace!("eval_fn_call: Will pass last argument by untupling"); - Cow::from(args.iter().map(|&a| Ok(a)) - .chain((0..untuple_arg.layout.fields.count()) - .map(|i| self.operand_field(untuple_arg, i as u64)) - ) - .collect::>>>()?) - } else { - // Plain arg passing - Cow::from(args) - }; - // Skip ZSTs - let mut caller_iter = caller_args - .iter() - .filter(|op| !rust_abi || !op.layout.is_zst()) - .copied(); - - // Now we have to spread them out across the callee's locals, - // taking into account the `spread_arg`. If we could write - // this is a single iterator (that handles `spread_arg`), then - // `pass_argument` would be the loop body. It takes care to - // not advance `caller_iter` for ZSTs - for local in body.args_iter() { - let dest = self.eval_place(&mir::Place::from(local))?; - if Some(local) == body.spread_arg { - // Must be a tuple - for i in 0..dest.layout.fields.count() { - let dest = self.place_field(dest, i as u64)?; - self.pass_argument(rust_abi, &mut caller_iter, dest)?; - } - } else { - // Normal argument + // Skip ZSTs + let mut caller_iter = + caller_args.iter().filter(|op| !rust_abi || !op.layout.is_zst()).copied(); + + // Now we have to spread them out across the callee's locals, + // taking into account the `spread_arg`. If we could write + // this is a single iterator (that handles `spread_arg`), then + // `pass_argument` would be the loop body. It takes care to + // not advance `caller_iter` for ZSTs. + for local in body.args_iter() { + let dest = self.eval_place(&mir::Place::from(local))?; + if Some(local) == body.spread_arg { + // Must be a tuple + for i in 0..dest.layout.fields.count() { + let dest = self.place_field(dest, i)?; self.pass_argument(rust_abi, &mut caller_iter, dest)?; } + } else { + // Normal argument + self.pass_argument(rust_abi, &mut caller_iter, dest)?; } - // Now we should have no more caller args - if caller_iter.next().is_some() { - trace!("Caller has passed too many args"); - throw_unsup!(FunctionArgCountMismatch) + } + // Now we should have no more caller args + if caller_iter.next().is_some() { + throw_ub_format!("calling a function with more arguments than it expected") + } + // Don't forget to check the return type! + if let Some((caller_ret, _)) = ret { + let callee_ret = self.eval_place(&mir::Place::return_place())?; + if !Self::check_argument_compat( + rust_abi, + caller_ret.layout, + callee_ret.layout, + ) { + throw_ub_format!( + "calling a function with return type {:?} passing \ + return place of type {:?}", + callee_ret.layout.ty, + caller_ret.layout.ty + ) } - // Don't forget to check the return type! - if let Some((caller_ret, _)) = ret { - let callee_ret = self.eval_place(&mir::Place::return_place())?; - if !Self::check_argument_compat( - rust_abi, - caller_ret.layout, - callee_ret.layout, - ) { - throw_unsup!(FunctionRetMismatch( - caller_ret.layout.ty, - callee_ret.layout.ty - )) - } - } else { - let local = mir::RETURN_PLACE; - let callee_layout = self.layout_of_local(self.frame(), local, None)?; - if !callee_layout.abi.is_uninhabited() { - throw_unsup!(FunctionRetMismatch( - self.tcx.types.never, - callee_layout.ty - )) - } + } else { + let local = mir::RETURN_PLACE; + let callee_layout = self.layout_of_local(self.frame(), local, None)?; + if !callee_layout.abi.is_uninhabited() { + throw_ub_format!("calling a returning function without a return place") } - Ok(()) - })(); + } + }; match res { Err(err) => { self.stack.pop(); Err(err) } - Ok(v) => Ok(v), + Ok(()) => Ok(()), } } // cannot use the shim here, because that will only result in infinite recursion @@ -384,7 +394,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; // Find and consult vtable let vtable = receiver_place.vtable(); - let drop_fn = self.get_vtable_slot(vtable, idx)?; + let drop_fn = self.get_vtable_slot(vtable, u64::try_from(idx).unwrap())?; // `*mut receiver_place.layout.ty` is almost the layout that we // want for args[0]: We have to project to field 0 because we want diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index efbbca534856a..1e63766b85d42 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -1,9 +1,11 @@ -use super::{FnVal, InterpCx, Machine, MemoryKind}; +use std::convert::TryFrom; use rustc::mir::interpret::{InterpResult, Pointer, PointerArithmetic, Scalar}; use rustc::ty::layout::{Align, HasDataLayout, LayoutOf, Size}; use rustc::ty::{self, Instance, Ty, TypeFoldable}; +use super::{FnVal, InterpCx, Machine, MemoryKind}; + impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Creates a dynamic vtable for the given type and vtable origin. This is used only for /// objects. @@ -54,7 +56,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // `get_vtable` in `rust_codegen_llvm/meth.rs`. // ///////////////////////////////////////////////////////////////////////////////////////// let vtable = self.memory.allocate( - ptr_size * (3 + methods.len() as u64), + ptr_size * u64::try_from(methods.len()).unwrap().checked_add(3).unwrap(), ptr_align, MemoryKind::Vtable, ); @@ -103,11 +105,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { pub fn get_vtable_slot( &self, vtable: Scalar, - idx: usize, + idx: u64, ) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> { let ptr_size = self.pointer_size(); // Skip over the 'drop_ptr', 'size', and 'align' fields. - let vtable_slot = vtable.ptr_offset(ptr_size * (idx as u64 + 3), self)?; + let vtable_slot = vtable.ptr_offset(ptr_size * idx.checked_add(3).unwrap(), self)?; let vtable_slot = self .memory .check_ptr_access(vtable_slot, ptr_size, self.tcx.data_layout.pointer_align.abi)? @@ -169,10 +171,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .expect("cannot be a ZST"); let alloc = self.memory.get_raw(vtable.alloc_id)?; let size = alloc.read_ptr_sized(self, vtable.offset(pointer_size, self)?)?.not_undef()?; - let size = self.force_bits(size, pointer_size)? as u64; + let size = u64::try_from(self.force_bits(size, pointer_size)?).unwrap(); let align = alloc.read_ptr_sized(self, vtable.offset(pointer_size * 2, self)?)?.not_undef()?; - let align = self.force_bits(align, pointer_size)? as u64; + let align = u64::try_from(self.force_bits(align, pointer_size)?).unwrap(); if size >= self.tcx.data_layout().obj_size_bound() { throw_ub_format!( diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 05bb010959b32..a355a22748010 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -4,6 +4,7 @@ //! That's useful because it means other passes (e.g. promotion) can rely on `const`s //! to be const-safe. +use std::convert::TryFrom; use std::fmt::Write; use std::ops::RangeInclusive; @@ -29,7 +30,7 @@ macro_rules! throw_validation_failure { write_path(&mut msg, where_); } write!(&mut msg, ", but expected {}", $details).unwrap(); - throw_unsup!(ValidationFailure(msg)) + throw_ub!(ValidationFailure(msg)) }}; ($what:expr, $where:expr) => {{ let mut msg = format!("encountered {}", $what); @@ -38,7 +39,7 @@ macro_rules! throw_validation_failure { msg.push_str(" at "); write_path(&mut msg, where_); } - throw_unsup!(ValidationFailure(msg)) + throw_ub!(ValidationFailure(msg)) }}; } @@ -353,31 +354,39 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M place.ptr, size, align ); match err.kind { - err_unsup!(InvalidNullPointerUsage) => { + err_ub!(InvalidIntPointerUsage(0)) => { throw_validation_failure!(format_args!("a NULL {}", kind), self.path) } - err_unsup!(AlignmentCheckFailed { required, has }) => { - throw_validation_failure!( - format_args!( - "an unaligned {} \ - (required {} byte alignment but found {})", - kind, - required.bytes(), - has.bytes() - ), - self.path - ) - } + err_ub!(InvalidIntPointerUsage(i)) => throw_validation_failure!( + format_args!("a {} to unallocated address {}", kind, i), + self.path + ), + err_ub!(AlignmentCheckFailed { required, has }) => throw_validation_failure!( + format_args!( + "an unaligned {} (required {} byte alignment but found {})", + kind, + required.bytes(), + has.bytes() + ), + self.path + ), err_unsup!(ReadBytesAsPointer) => throw_validation_failure!( format_args!("a dangling {} (created from integer)", kind), self.path ), - err_unsup!(PointerOutOfBounds { .. }) | err_unsup!(DanglingPointerDeref) => { - throw_validation_failure!( - format_args!("a dangling {} (not entirely in bounds)", kind), - self.path - ) - } + err_ub!(PointerOutOfBounds { .. }) => throw_validation_failure!( + format_args!( + "a dangling {} (going beyond the bounds of its allocation)", + kind + ), + self.path + ), + // This cannot happen during const-eval (because interning already detects + // dangling pointers), but it can happen in Miri. + err_ub!(PointerUseAfterFree(_)) => throw_validation_failure!( + format_args!("a dangling {} (use-after-free)", kind), + self.path + ), _ => bug!("Unexpected error during ptr inbounds test: {}", err), } } @@ -738,7 +747,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> } // This is the element type size. let layout = self.ecx.layout_of(tys)?; - // This is the size in bytes of the whole array. + // This is the size in bytes of the whole array. (This checks for overflow.) let size = layout.size * len; // Size is not 0, get a pointer. let ptr = self.ecx.force_ptr(mplace.ptr)?; @@ -765,11 +774,12 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> Err(err) => { // For some errors we might be able to provide extra information match err.kind { - err_unsup!(ReadUndefBytes(offset)) => { + err_ub!(InvalidUndefBytes(Some(ptr))) => { // Some byte was undefined, determine which // element that byte belongs to so we can // provide an index. - let i = (offset.bytes() / layout.size.bytes()) as usize; + let i = usize::try_from(ptr.offset.bytes() / layout.size.bytes()) + .unwrap(); self.path.push(PathElem::ArrayElem(i)); throw_validation_failure!("undefined bytes", self.path) @@ -817,11 +827,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Run it. match visitor.visit_value(op) { Ok(()) => Ok(()), - Err(err) if matches!(err.kind, err_unsup!(ValidationFailure { .. })) => Err(err), - Err(err) if cfg!(debug_assertions) => { - bug!("Unexpected error during validation: {}", err) - } - Err(err) => Err(err), + // We should only get validation errors here. Avoid other errors as + // those do not show *where* in the value the issue lies. + Err(err) if matches!(err.kind, err_ub!(ValidationFailure { .. })) => Err(err), + Err(err) => bug!("Unexpected error during validation: {}", err), } } diff --git a/src/librustc_mir/interpret/visitor.rs b/src/librustc_mir/interpret/visitor.rs index 8808fc70cf76b..e8a7626406413 100644 --- a/src/librustc_mir/interpret/visitor.rs +++ b/src/librustc_mir/interpret/visitor.rs @@ -28,7 +28,8 @@ pub trait Value<'mir, 'tcx, M: Machine<'mir, 'tcx>>: Copy { ) -> InterpResult<'tcx, Self>; /// Projects to the n-th field. - fn project_field(self, ecx: &InterpCx<'mir, 'tcx, M>, field: u64) -> InterpResult<'tcx, Self>; + fn project_field(self, ecx: &InterpCx<'mir, 'tcx, M>, field: usize) + -> InterpResult<'tcx, Self>; } // Operands and memory-places are both values. @@ -62,7 +63,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Value<'mir, 'tcx, M> for OpTy<'tcx, M:: } #[inline(always)] - fn project_field(self, ecx: &InterpCx<'mir, 'tcx, M>, field: u64) -> InterpResult<'tcx, Self> { + fn project_field( + self, + ecx: &InterpCx<'mir, 'tcx, M>, + field: usize, + ) -> InterpResult<'tcx, Self> { ecx.operand_field(self, field) } } @@ -96,7 +101,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Value<'mir, 'tcx, M> for MPlaceTy<'tcx, } #[inline(always)] - fn project_field(self, ecx: &InterpCx<'mir, 'tcx, M>, field: u64) -> InterpResult<'tcx, Self> { + fn project_field( + self, + ecx: &InterpCx<'mir, 'tcx, M>, + field: usize, + ) -> InterpResult<'tcx, Self> { ecx.mplace_field(self, field) } } @@ -206,7 +215,7 @@ macro_rules! make_value_visitor { // errors: Projecting to a field needs access to `ecx`. let fields: Vec> = (0..offsets.len()).map(|i| { - v.project_field(self.ecx(), i as u64) + v.project_field(self.ecx(), i) }) .collect(); self.visit_aggregate(v, fields.into_iter())?; diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 284dd74ce99d4..7d3aba3ff034e 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -9,6 +9,9 @@ Rust MIR: a lowered representation of Rust. #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(const_if_match)] +#![feature(const_fn)] +#![feature(const_panic)] #![feature(crate_visibility_modifier)] #![feature(drain_filter)] #![feature(exhaustive_patterns)] diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 862a7ef1e73c0..cbd19f080eb9e 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -183,10 +183,9 @@ use rustc::mir::interpret::{ErrorHandled, GlobalAlloc, Scalar}; use rustc::mir::mono::{InstantiationMode, MonoItem}; use rustc::mir::visit::Visitor as MirVisitor; use rustc::mir::{self, Local, Location}; -use rustc::session::config::EntryFnType; use rustc::ty::adjustment::{CustomCoerceUnsized, PointerCast}; use rustc::ty::print::obsolete::DefPathBasedNames; -use rustc::ty::subst::{InternalSubsts, SubstsRef}; +use rustc::ty::subst::InternalSubsts; use rustc::ty::{self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator}; @@ -194,6 +193,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, DefIdMap, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_index::bit_set::GrowableBitSet; +use rustc_session::config::EntryFnType; use smallvec::SmallVec; use std::iter; @@ -493,7 +493,21 @@ struct MirNeighborCollector<'a, 'tcx> { tcx: TyCtxt<'tcx>, body: &'a mir::Body<'tcx>, output: &'a mut Vec>, - param_substs: SubstsRef<'tcx>, + instance: Instance<'tcx>, +} + +impl<'a, 'tcx> MirNeighborCollector<'a, 'tcx> { + pub fn monomorphize(&self, value: T) -> T + where + T: TypeFoldable<'tcx>, + { + debug!("monomorphize: self.instance={:?}", self.instance); + if let Some(substs) = self.instance.substs_for_mir_body() { + self.tcx.subst_and_normalize_erasing_regions(substs, ty::ParamEnv::reveal_all(), &value) + } else { + self.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), value) + } + } } impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { @@ -509,17 +523,9 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { ref operand, target_ty, ) => { - let target_ty = self.tcx.subst_and_normalize_erasing_regions( - self.param_substs, - ty::ParamEnv::reveal_all(), - &target_ty, - ); + let target_ty = self.monomorphize(target_ty); let source_ty = operand.ty(self.body, self.tcx); - let source_ty = self.tcx.subst_and_normalize_erasing_regions( - self.param_substs, - ty::ParamEnv::reveal_all(), - &source_ty, - ); + let source_ty = self.monomorphize(source_ty); let (source_ty, target_ty) = find_vtable_types_for_unsizing(self.tcx, source_ty, target_ty); // This could also be a different Unsize instruction, like @@ -540,11 +546,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { _, ) => { let fn_ty = operand.ty(self.body, self.tcx); - let fn_ty = self.tcx.subst_and_normalize_erasing_regions( - self.param_substs, - ty::ParamEnv::reveal_all(), - &fn_ty, - ); + let fn_ty = self.monomorphize(fn_ty); visit_fn_use(self.tcx, fn_ty, false, &mut self.output); } mir::Rvalue::Cast( @@ -553,11 +555,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { _, ) => { let source_ty = operand.ty(self.body, self.tcx); - let source_ty = self.tcx.subst_and_normalize_erasing_regions( - self.param_substs, - ty::ParamEnv::reveal_all(), - &source_ty, - ); + let source_ty = self.monomorphize(source_ty); match source_ty.kind { ty::Closure(def_id, substs) => { let instance = Instance::resolve_closure( @@ -593,7 +591,23 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, location: Location) { debug!("visiting const {:?} @ {:?}", *constant, location); - collect_const(self.tcx, *constant, self.param_substs, self.output); + let substituted_constant = self.monomorphize(*constant); + let param_env = ty::ParamEnv::reveal_all(); + + match substituted_constant.val { + ty::ConstKind::Value(val) => collect_const_value(self.tcx, val, self.output), + ty::ConstKind::Unevaluated(def_id, substs, promoted) => { + match self.tcx.const_eval_resolve(param_env, def_id, substs, promoted, None) { + Ok(val) => collect_const_value(self.tcx, val, self.output), + Err(ErrorHandled::Reported) => {} + Err(ErrorHandled::TooGeneric) => span_bug!( + self.tcx.def_span(def_id), + "collection encountered polymorphic constant", + ), + } + } + _ => {} + } self.super_const(constant); } @@ -605,21 +619,13 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { match *kind { mir::TerminatorKind::Call { ref func, .. } => { let callee_ty = func.ty(self.body, tcx); - let callee_ty = tcx.subst_and_normalize_erasing_regions( - self.param_substs, - ty::ParamEnv::reveal_all(), - &callee_ty, - ); + let callee_ty = self.monomorphize(callee_ty); visit_fn_use(self.tcx, callee_ty, true, &mut self.output); } mir::TerminatorKind::Drop { ref location, .. } | mir::TerminatorKind::DropAndReplace { ref location, .. } => { let ty = location.ty(self.body, self.tcx).ty; - let ty = tcx.subst_and_normalize_erasing_regions( - self.param_substs, - ty::ParamEnv::reveal_all(), - &ty, - ); + let ty = self.monomorphize(ty); visit_drop_use(self.tcx, ty, true, self.output); } mir::TerminatorKind::Goto { .. } @@ -745,7 +751,7 @@ fn should_monomorphize_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx bug!("cannot create local mono-item for {:?}", def_id) } - return true; + true } /// For a given pair of source and target type that occur in an unsizing coercion, @@ -889,7 +895,7 @@ fn create_mono_items_for_vtable_methods<'tcx>( .unwrap() }) .filter(|&instance| should_monomorphize_locally(tcx, &instance)) - .map(|instance| create_fn_mono_item(instance)); + .map(create_fn_mono_item); output.extend(methods); } @@ -983,7 +989,7 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> { fn visit_impl_item(&mut self, ii: &'v hir::ImplItem<'v>) { match ii.kind { - hir::ImplItemKind::Method(hir::FnSig { .. }, _) => { + hir::ImplItemKind::Fn(hir::FnSig { .. }, _) => { let def_id = self.tcx.hir().local_def_id(ii.hir_id); self.push_if_root(def_id); } @@ -1088,9 +1094,9 @@ 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<_> = - items.iter().map(|iiref| iiref.ident.modern()).collect(); + items.iter().map(|iiref| iiref.ident.normalize_to_macros_2_0()).collect(); for method in tcx.provided_trait_methods(trait_ref.def_id) { - if overridden_methods.contains(&method.ident.modern()) { + if overridden_methods.contains(&method.ident.normalize_to_macros_2_0()) { continue; } @@ -1156,8 +1162,7 @@ fn collect_neighbours<'tcx>( debug!("collect_neighbours: {:?}", instance.def_id()); let body = tcx.instance_mir(instance.def); - MirNeighborCollector { tcx, body: &body, output, param_substs: instance.substs } - .visit_body(body); + MirNeighborCollector { tcx, body: &body, output, instance }.visit_body(body); } fn def_id_to_string(tcx: TyCtxt<'_>, def_id: DefId) -> String { @@ -1167,33 +1172,6 @@ fn def_id_to_string(tcx: TyCtxt<'_>, def_id: DefId) -> String { output } -fn collect_const<'tcx>( - tcx: TyCtxt<'tcx>, - constant: &'tcx ty::Const<'tcx>, - param_substs: SubstsRef<'tcx>, - output: &mut Vec>, -) { - debug!("visiting const {:?}", constant); - - let param_env = ty::ParamEnv::reveal_all(); - let substituted_constant = - tcx.subst_and_normalize_erasing_regions(param_substs, param_env, &constant); - - match substituted_constant.val { - ty::ConstKind::Value(val) => collect_const_value(tcx, val, output), - ty::ConstKind::Unevaluated(def_id, substs, promoted) => { - match tcx.const_eval_resolve(param_env, def_id, substs, promoted, None) { - Ok(val) => collect_const_value(tcx, val, output), - Err(ErrorHandled::Reported) => {} - Err(ErrorHandled::TooGeneric) => { - span_bug!(tcx.def_span(def_id), "collection encountered polymorphic constant",) - } - } - } - _ => {} - } -} - fn collect_const_value<'tcx>( tcx: TyCtxt<'tcx>, value: ConstValue<'tcx>, diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 1f7db2861a2eb..eeb9d5f5a1fcc 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -2,13 +2,13 @@ use rustc::mir::*; use rustc::ty::layout::VariantIdx; use rustc::ty::query::Providers; use rustc::ty::subst::{InternalSubsts, Subst}; -use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_index::vec::{Idx, IndexVec}; -use rustc_span::{sym, Span}; +use rustc_span::Span; use rustc_target::spec::abi::Abi; use std::fmt; @@ -39,6 +39,11 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx None, ), ty::InstanceDef::FnPtrShim(def_id, ty) => { + // FIXME(eddyb) support generating shims for a "shallow type", + // e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic + // `Foo` or `[String]` etc. + assert!(!ty.needs_subst()); + let trait_ = tcx.trait_of_item(def_id).unwrap(); let adjustment = match tcx.fn_trait_kind_from_lang_item(trait_) { Some(ty::ClosureKind::FnOnce) => Adjustment::Identity, @@ -81,17 +86,21 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx None, ) } - ty::InstanceDef::DropGlue(def_id, ty) => build_drop_shim(tcx, def_id, ty), + ty::InstanceDef::DropGlue(def_id, ty) => { + // FIXME(eddyb) support generating shims for a "shallow type", + // e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic + // `Foo` or `[String]` etc. + assert!(!ty.needs_subst()); + + build_drop_shim(tcx, def_id, ty) + } ty::InstanceDef::CloneShim(def_id, ty) => { - let name = tcx.item_name(def_id); - if name == sym::clone { - build_clone_shim(tcx, def_id, ty) - } else if name == sym::clone_from { - debug!("make_shim({:?}: using default trait implementation", instance); - return tcx.optimized_mir(def_id); - } else { - bug!("builtin clone shim {:?} not supported", instance) - } + // FIXME(eddyb) support generating shims for a "shallow type", + // e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic + // `Foo` or `[String]` etc. + assert!(!ty.needs_subst()); + + build_clone_shim(tcx, def_id, ty) } ty::InstanceDef::Virtual(..) => { bug!("InstanceDef::Virtual ({:?}) is for direct calls only", instance) @@ -332,8 +341,8 @@ fn build_clone_shim<'tcx>( let len = len.eval_usize(tcx, param_env); builder.array_shim(dest, src, ty, len) } - ty::Closure(def_id, substs) => { - builder.tuple_like_shim(dest, src, substs.as_closure().upvar_tys(def_id, tcx)) + ty::Closure(_, substs) => { + builder.tuple_like_shim(dest, src, substs.as_closure().upvar_tys()) } ty::Tuple(..) => builder.tuple_like_shim(dest, src, self_ty.tuple_fields()), _ => bug!("clone shim for `{:?}` which is not `Copy` and is not an aggregate", self_ty), diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs index 2306177c14b8a..aa9cad7ffc19f 100644 --- a/src/librustc_mir/transform/add_retag.rs +++ b/src/librustc_mir/transform/add_retag.rs @@ -34,7 +34,7 @@ fn is_stable(place: PlaceRef<'_>) -> bool { } /// Determine whether this type may be a reference (or box), and thus needs retagging. -fn may_be_reference<'tcx>(ty: Ty<'tcx>) -> bool { +fn may_be_reference(ty: Ty<'tcx>) -> bool { match ty.kind { // Primitive types that are not references ty::Bool diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs index 9ba44a4d18e58..af7af7388bd28 100644 --- a/src/librustc_mir/transform/check_consts/ops.rs +++ b/src/librustc_mir/transform/check_consts/ops.rs @@ -1,10 +1,9 @@ //! Concrete error types for all operations which may be invalid in a certain const context. -use rustc::session::config::nightly_options; -use rustc::session::parse::feature_err; -use rustc::ty::TyCtxt; use rustc_errors::struct_span_err; use rustc_hir::def_id::DefId; +use rustc_session::config::nightly_options; +use rustc_session::parse::feature_err; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol}; @@ -15,9 +14,9 @@ pub trait NonConstOp: std::fmt::Debug { /// Whether this operation can be evaluated by miri. const IS_SUPPORTED_IN_MIRI: bool = true; - /// Returns a boolean indicating whether the feature gate that would allow this operation is - /// enabled, or `None` if such a feature gate does not exist. - fn feature_gate(_tcx: TyCtxt<'tcx>) -> Option { + /// Returns the `Symbol` corresponding to the feature gate that would enable this operation, + /// or `None` if such a feature gate does not exist. + fn feature_gate() -> Option { None } @@ -25,8 +24,11 @@ pub trait NonConstOp: std::fmt::Debug { /// /// This check should assume that we are not in a non-const `fn`, where all operations are /// legal. + /// + /// By default, it returns `true` if and only if this operation has a corresponding feature + /// gate and that gate is enabled. fn is_allowed_in_item(&self, item: &Item<'_, '_>) -> bool { - Self::feature_gate(item.tcx).unwrap_or(false) + Self::feature_gate().map_or(false, |gate| item.tcx.features().enabled(gate)) } fn emit_error(&self, item: &Item<'_, '_>, span: Span) { @@ -55,8 +57,8 @@ pub trait NonConstOp: std::fmt::Debug { #[derive(Debug)] pub struct Downcast; impl NonConstOp for Downcast { - fn feature_gate(tcx: TyCtxt<'_>) -> Option { - Some(tcx.features().const_if_match) + fn feature_gate() -> Option { + Some(sym::const_if_match) } } @@ -147,8 +149,8 @@ impl NonConstOp for HeapAllocation { #[derive(Debug)] pub struct IfOrMatch; impl NonConstOp for IfOrMatch { - fn feature_gate(tcx: TyCtxt<'_>) -> Option { - Some(tcx.features().const_if_match) + fn feature_gate() -> Option { + Some(sym::const_if_match) } fn emit_error(&self, item: &Item<'_, '_>, span: Span) { @@ -175,8 +177,8 @@ impl NonConstOp for LiveDrop { #[derive(Debug)] pub struct Loop; impl NonConstOp for Loop { - fn feature_gate(tcx: TyCtxt<'_>) -> Option { - Some(tcx.features().const_loop) + fn feature_gate() -> Option { + Some(sym::const_loop) } fn emit_error(&self, item: &Item<'_, '_>, span: Span) { @@ -203,8 +205,8 @@ impl NonConstOp for CellBorrow { #[derive(Debug)] pub struct MutBorrow; impl NonConstOp for MutBorrow { - fn feature_gate(tcx: TyCtxt<'_>) -> Option { - Some(tcx.features().const_mut_refs) + fn feature_gate() -> Option { + Some(sym::const_mut_refs) } fn emit_error(&self, item: &Item<'_, '_>, span: Span) { @@ -238,8 +240,8 @@ impl NonConstOp for MutBorrow { #[derive(Debug)] pub struct MutAddressOf; impl NonConstOp for MutAddressOf { - fn feature_gate(tcx: TyCtxt<'_>) -> Option { - Some(tcx.features().const_mut_refs) + fn feature_gate() -> Option { + Some(sym::const_mut_refs) } fn emit_error(&self, item: &Item<'_, '_>, span: Span) { @@ -256,16 +258,16 @@ impl NonConstOp for MutAddressOf { #[derive(Debug)] pub struct MutDeref; impl NonConstOp for MutDeref { - fn feature_gate(tcx: TyCtxt<'_>) -> Option { - Some(tcx.features().const_mut_refs) + fn feature_gate() -> Option { + Some(sym::const_mut_refs) } } #[derive(Debug)] pub struct Panic; impl NonConstOp for Panic { - fn feature_gate(tcx: TyCtxt<'_>) -> Option { - Some(tcx.features().const_panic) + fn feature_gate() -> Option { + Some(sym::const_panic) } fn emit_error(&self, item: &Item<'_, '_>, span: Span) { @@ -282,8 +284,8 @@ impl NonConstOp for Panic { #[derive(Debug)] pub struct RawPtrComparison; impl NonConstOp for RawPtrComparison { - fn feature_gate(tcx: TyCtxt<'_>) -> Option { - Some(tcx.features().const_compare_raw_pointers) + fn feature_gate() -> Option { + Some(sym::const_compare_raw_pointers) } fn emit_error(&self, item: &Item<'_, '_>, span: Span) { @@ -300,8 +302,8 @@ impl NonConstOp for RawPtrComparison { #[derive(Debug)] pub struct RawPtrDeref; impl NonConstOp for RawPtrDeref { - fn feature_gate(tcx: TyCtxt<'_>) -> Option { - Some(tcx.features().const_raw_ptr_deref) + fn feature_gate() -> Option { + Some(sym::const_raw_ptr_deref) } fn emit_error(&self, item: &Item<'_, '_>, span: Span) { @@ -318,8 +320,8 @@ impl NonConstOp for RawPtrDeref { #[derive(Debug)] pub struct RawPtrToIntCast; impl NonConstOp for RawPtrToIntCast { - fn feature_gate(tcx: TyCtxt<'_>) -> Option { - Some(tcx.features().const_raw_ptr_to_usize_cast) + fn feature_gate() -> Option { + Some(sym::const_raw_ptr_to_usize_cast) } fn emit_error(&self, item: &Item<'_, '_>, span: Span) { @@ -386,11 +388,12 @@ pub struct UnionAccess; impl NonConstOp for UnionAccess { fn is_allowed_in_item(&self, item: &Item<'_, '_>) -> bool { // Union accesses are stable in all contexts except `const fn`. - item.const_kind() != ConstKind::ConstFn || Self::feature_gate(item.tcx).unwrap() + item.const_kind() != ConstKind::ConstFn + || item.tcx.features().enabled(Self::feature_gate().unwrap()) } - fn feature_gate(tcx: TyCtxt<'_>) -> Option { - Some(tcx.features().const_fn_union) + fn feature_gate() -> Option { + Some(sym::const_fn_union) } fn emit_error(&self, item: &Item<'_, '_>, span: Span) { diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs index baff8383c20a4..9359ec16533a5 100644 --- a/src/librustc_mir/transform/check_consts/qualifs.rs +++ b/src/librustc_mir/transform/check_consts/qualifs.rs @@ -1,7 +1,9 @@ -//! A copy of the `Qualif` trait in `qualify_consts.rs` that is suitable for the new validator. +//! Structural const qualification. +//! +//! See the `Qualif` trait for more info. use rustc::mir::*; -use rustc::ty::{self, Ty}; +use rustc::ty::{self, AdtDef, Ty}; use rustc_span::DUMMY_SP; use super::Item as ConstCx; @@ -14,11 +16,16 @@ pub fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> ConstQualifs } /// A "qualif"(-ication) is a way to look for something "bad" in the MIR that would disqualify some -/// code for promotion or prevent it from evaluating at compile time. So `return true` means -/// "I found something bad, no reason to go on searching". `false` is only returned if we -/// definitely cannot find anything bad anywhere. +/// code for promotion or prevent it from evaluating at compile time. /// -/// The default implementations proceed structurally. +/// Normally, we would determine what qualifications apply to each type and error when an illegal +/// operation is performed on such a type. However, this was found to be too imprecise, especially +/// in the presence of `enum`s. If only a single variant of an enum has a certain qualification, we +/// needn't reject code unless it actually constructs and operates on the qualifed variant. +/// +/// To accomplish this, const-checking and promotion use a value-based analysis (as opposed to a +/// type-based one). Qualifications propagate structurally across variables: If a local (or a +/// projection of a local) is assigned a qualifed value, that local itself becomes qualifed. pub trait Qualif { /// The name of the file used to debug the dataflow analysis that computes this qualif. const ANALYSIS_NAME: &'static str; @@ -26,157 +33,27 @@ pub trait Qualif { /// Whether this `Qualif` is cleared when a local is moved from. const IS_CLEARED_ON_MOVE: bool = false; + /// Extracts the field of `ConstQualifs` that corresponds to this `Qualif`. fn in_qualifs(qualifs: &ConstQualifs) -> bool; - /// Return the qualification that is (conservatively) correct for any value - /// of the type. - fn in_any_value_of_ty(_cx: &ConstCx<'_, 'tcx>, _ty: Ty<'tcx>) -> bool; - - fn in_projection_structurally( - cx: &ConstCx<'_, 'tcx>, - per_local: &mut impl FnMut(Local) -> bool, - place: PlaceRef<'tcx>, - ) -> bool { - if let [proj_base @ .., elem] = place.projection { - let base_qualif = Self::in_place( - cx, - per_local, - PlaceRef { local: place.local, projection: proj_base }, - ); - let qualif = base_qualif - && Self::in_any_value_of_ty( - cx, - Place::ty_from(place.local, proj_base, *cx.body, cx.tcx) - .projection_ty(cx.tcx, elem) - .ty, - ); - match elem { - ProjectionElem::Deref - | ProjectionElem::Subslice { .. } - | ProjectionElem::Field(..) - | ProjectionElem::ConstantIndex { .. } - | ProjectionElem::Downcast(..) => qualif, - - ProjectionElem::Index(local) => qualif || per_local(*local), - } - } else { - bug!("This should be called if projection is not empty"); - } - } - - fn in_projection( - cx: &ConstCx<'_, 'tcx>, - per_local: &mut impl FnMut(Local) -> bool, - place: PlaceRef<'tcx>, - ) -> bool { - Self::in_projection_structurally(cx, per_local, place) - } - - fn in_place( - cx: &ConstCx<'_, 'tcx>, - per_local: &mut impl FnMut(Local) -> bool, - place: PlaceRef<'tcx>, - ) -> bool { - match place { - PlaceRef { local, projection: [] } => per_local(local), - PlaceRef { local: _, projection: [.., _] } => Self::in_projection(cx, per_local, place), - } - } - - fn in_operand( - cx: &ConstCx<'_, 'tcx>, - per_local: &mut impl FnMut(Local) -> bool, - operand: &Operand<'tcx>, - ) -> bool { - match *operand { - Operand::Copy(ref place) | Operand::Move(ref place) => { - Self::in_place(cx, per_local, place.as_ref()) - } - - Operand::Constant(ref constant) => { - // Check the qualifs of the value of `const` items. - if let ty::ConstKind::Unevaluated(def_id, _, promoted) = constant.literal.val { - assert!(promoted.is_none()); - // Don't peek inside trait associated constants. - if cx.tcx.trait_of_item(def_id).is_none() { - let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def_id); - if !Self::in_qualifs(&qualifs) { - return false; - } - - // Just in case the type is more specific than - // the definition, e.g., impl associated const - // with type parameters, take it into account. - } - } - // Otherwise use the qualifs of the type. - Self::in_any_value_of_ty(cx, constant.literal.ty) - } - } - } - - fn in_rvalue_structurally( - cx: &ConstCx<'_, 'tcx>, - per_local: &mut impl FnMut(Local) -> bool, - rvalue: &Rvalue<'tcx>, - ) -> bool { - match *rvalue { - Rvalue::NullaryOp(..) => false, - - Rvalue::Discriminant(ref place) | Rvalue::Len(ref place) => { - Self::in_place(cx, per_local, place.as_ref()) - } - - Rvalue::Use(ref operand) - | Rvalue::Repeat(ref operand, _) - | Rvalue::UnaryOp(_, ref operand) - | Rvalue::Cast(_, ref operand, _) => Self::in_operand(cx, per_local, operand), - - Rvalue::BinaryOp(_, ref lhs, ref rhs) - | Rvalue::CheckedBinaryOp(_, ref lhs, ref rhs) => { - Self::in_operand(cx, per_local, lhs) || Self::in_operand(cx, per_local, rhs) - } - - Rvalue::Ref(_, _, ref place) | Rvalue::AddressOf(_, ref place) => { - // Special-case reborrows to be more like a copy of the reference. - if let [proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() { - let base_ty = Place::ty_from(place.local, proj_base, *cx.body, cx.tcx).ty; - if let ty::Ref(..) = base_ty.kind { - return Self::in_place( - cx, - per_local, - PlaceRef { local: place.local, projection: proj_base }, - ); - } - } - - Self::in_place(cx, per_local, place.as_ref()) - } - - Rvalue::Aggregate(_, ref operands) => { - operands.iter().any(|o| Self::in_operand(cx, per_local, o)) - } - } - } - - fn in_rvalue( - cx: &ConstCx<'_, 'tcx>, - per_local: &mut impl FnMut(Local) -> bool, - rvalue: &Rvalue<'tcx>, - ) -> bool { - Self::in_rvalue_structurally(cx, per_local, rvalue) - } - - fn in_call( - cx: &ConstCx<'_, 'tcx>, - _per_local: &mut impl FnMut(Local) -> bool, - _callee: &Operand<'tcx>, - _args: &[Operand<'tcx>], - return_ty: Ty<'tcx>, - ) -> bool { - // Be conservative about the returned value of a const fn. - Self::in_any_value_of_ty(cx, return_ty) - } + /// Returns `true` if *any* value of the given type could possibly have this `Qualif`. + /// + /// This function determines `Qualif`s when we cannot do a value-based analysis. Since qualif + /// propagation is context-insenstive, this includes function arguments and values returned + /// from a call to another function. + /// + /// It also determines the `Qualif`s for primitive types. + fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool; + + /// Returns `true` if this `Qualif` is inherent to the given struct or enum. + /// + /// By default, `Qualif`s propagate into ADTs in a structural way: An ADT only becomes + /// qualified if part of it is assigned a value with that `Qualif`. However, some ADTs *always* + /// have a certain `Qualif`, regardless of whether their fields have it. For example, a type + /// with a custom `Drop` impl is inherently `NeedsDrop`. + /// + /// Returning `true` for `in_adt_inherently` but `false` for `in_any_value_of_ty` is unsound. + fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &AdtDef) -> bool; } /// Constant containing interior mutability (`UnsafeCell`). @@ -197,26 +74,10 @@ impl Qualif for HasMutInterior { !ty.is_freeze(cx.tcx, cx.param_env, DUMMY_SP) } - fn in_rvalue( - cx: &ConstCx<'_, 'tcx>, - per_local: &mut impl FnMut(Local) -> bool, - rvalue: &Rvalue<'tcx>, - ) -> bool { - match *rvalue { - Rvalue::Aggregate(ref kind, _) => { - if let AggregateKind::Adt(def, ..) = **kind { - if Some(def.did) == cx.tcx.lang_items().unsafe_cell_type() { - let ty = rvalue.ty(*cx.body, cx.tcx); - assert_eq!(Self::in_any_value_of_ty(cx, ty), true); - return true; - } - } - } - - _ => {} - } - - Self::in_rvalue_structurally(cx, per_local, rvalue) + fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &AdtDef) -> bool { + // Exactly one type, `UnsafeCell`, has the `HasMutInterior` qualif inherently. + // It arises structurally for all other types. + Some(adt.did) == cx.tcx.lang_items().unsafe_cell_type() } } @@ -238,19 +99,127 @@ impl Qualif for NeedsDrop { ty.needs_drop(cx.tcx, cx.param_env) } - fn in_rvalue( - cx: &ConstCx<'_, 'tcx>, - per_local: &mut impl FnMut(Local) -> bool, - rvalue: &Rvalue<'tcx>, - ) -> bool { - if let Rvalue::Aggregate(ref kind, _) = *rvalue { + fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &AdtDef) -> bool { + adt.has_dtor(cx.tcx) + } +} + +// FIXME: Use `mir::visit::Visitor` for the `in_*` functions if/when it supports early return. + +/// Returns `true` if this `Rvalue` contains qualif `Q`. +pub fn in_rvalue(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, rvalue: &Rvalue<'tcx>) -> bool +where + Q: Qualif, + F: FnMut(Local) -> bool, +{ + match rvalue { + Rvalue::NullaryOp(..) => Q::in_any_value_of_ty(cx, rvalue.ty(*cx.body, cx.tcx)), + + Rvalue::Discriminant(place) | Rvalue::Len(place) => { + in_place::(cx, in_local, place.as_ref()) + } + + Rvalue::Use(operand) + | Rvalue::Repeat(operand, _) + | Rvalue::UnaryOp(_, operand) + | Rvalue::Cast(_, operand, _) => in_operand::(cx, in_local, operand), + + Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => { + in_operand::(cx, in_local, lhs) || in_operand::(cx, in_local, rhs) + } + + Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => { + // Special-case reborrows to be more like a copy of the reference. + if let &[ref proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() { + let base_ty = Place::ty_from(place.local, proj_base, *cx.body, cx.tcx).ty; + if let ty::Ref(..) = base_ty.kind { + return in_place::( + cx, + in_local, + PlaceRef { local: place.local, projection: proj_base }, + ); + } + } + + in_place::(cx, in_local, place.as_ref()) + } + + Rvalue::Aggregate(kind, operands) => { + // Return early if we know that the struct or enum being constructed is always + // qualified. if let AggregateKind::Adt(def, ..) = **kind { - if def.has_dtor(cx.tcx) { + if Q::in_adt_inherently(cx, def) { return true; } } + + // Otherwise, proceed structurally... + operands.iter().any(|o| in_operand::(cx, in_local, o)) } + } +} - Self::in_rvalue_structurally(cx, per_local, rvalue) +/// Returns `true` if this `Place` contains qualif `Q`. +pub fn in_place(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, place: PlaceRef<'tcx>) -> bool +where + Q: Qualif, + F: FnMut(Local) -> bool, +{ + let mut projection = place.projection; + while let [ref proj_base @ .., proj_elem] = projection { + match *proj_elem { + ProjectionElem::Index(index) if in_local(index) => return true, + + ProjectionElem::Deref + | ProjectionElem::Field(_, _) + | ProjectionElem::ConstantIndex { .. } + | ProjectionElem::Subslice { .. } + | ProjectionElem::Downcast(_, _) + | ProjectionElem::Index(_) => {} + } + + let base_ty = Place::ty_from(place.local, proj_base, *cx.body, cx.tcx); + let proj_ty = base_ty.projection_ty(cx.tcx, proj_elem).ty; + if !Q::in_any_value_of_ty(cx, proj_ty) { + return false; + } + + projection = proj_base; + } + + assert!(projection.is_empty()); + in_local(place.local) +} + +/// Returns `true` if this `Operand` contains qualif `Q`. +pub fn in_operand(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, operand: &Operand<'tcx>) -> bool +where + Q: Qualif, + F: FnMut(Local) -> bool, +{ + let constant = match operand { + Operand::Copy(place) | Operand::Move(place) => { + return in_place::(cx, in_local, place.as_ref()); + } + + Operand::Constant(c) => c, + }; + + // Check the qualifs of the value of `const` items. + if let ty::ConstKind::Unevaluated(def_id, _, promoted) = constant.literal.val { + assert!(promoted.is_none()); + // Don't peek inside trait associated constants. + if cx.tcx.trait_of_item(def_id).is_none() { + let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def_id); + if !Q::in_qualifs(&qualifs) { + return false; + } + + // Just in case the type is more specific than + // the definition, e.g., impl associated const + // with type parameters, take it into account. + } } + // Otherwise use the qualifs of the type. + Q::in_any_value_of_ty(cx, constant.literal.ty) } diff --git a/src/librustc_mir/transform/check_consts/resolver.rs b/src/librustc_mir/transform/check_consts/resolver.rs index 3e14cc6d32a67..e42f64b5c7384 100644 --- a/src/librustc_mir/transform/check_consts/resolver.rs +++ b/src/librustc_mir/transform/check_consts/resolver.rs @@ -8,7 +8,7 @@ use rustc_index::bit_set::BitSet; use std::marker::PhantomData; -use super::{Item, Qualif}; +use super::{qualifs, Item, Qualif}; use crate::dataflow::{self as old_dataflow, generic as dataflow}; /// A `Visitor` that propagates qualifs between locals. This defines the transfer function of @@ -66,18 +66,15 @@ where fn apply_call_return_effect( &mut self, _block: BasicBlock, - func: &mir::Operand<'tcx>, - args: &[mir::Operand<'tcx>], + _func: &mir::Operand<'tcx>, + _args: &[mir::Operand<'tcx>], return_place: &mir::Place<'tcx>, ) { + // We cannot reason about another function's internals, so use conservative type-based + // qualification for the result of a function call. let return_ty = return_place.ty(*self.item.body, self.item.tcx).ty; - let qualif = Q::in_call( - self.item, - &mut |l| self.qualifs_per_local.contains(l), - func, - args, - return_ty, - ); + let qualif = Q::in_any_value_of_ty(self.item, return_ty); + if !return_place.is_indirect() { self.assign_qualif_direct(return_place, qualif); } @@ -110,7 +107,11 @@ where rvalue: &mir::Rvalue<'tcx>, location: Location, ) { - let qualif = Q::in_rvalue(self.item, &mut |l| self.qualifs_per_local.contains(l), rvalue); + let qualif = qualifs::in_rvalue::( + self.item, + &mut |l| self.qualifs_per_local.contains(l), + rvalue, + ); if !place.is_indirect() { self.assign_qualif_direct(place, qualif); } @@ -125,8 +126,12 @@ where // here; that occurs in `apply_call_return_effect`. if let mir::TerminatorKind::DropAndReplace { value, location: dest, .. } = kind { - let qualif = - Q::in_operand(self.item, &mut |l| self.qualifs_per_local.contains(l), value); + let qualif = qualifs::in_operand::( + self.item, + &mut |l| self.qualifs_per_local.contains(l), + value, + ); + if !dest.is_indirect() { self.assign_qualif_direct(dest, qualif); } diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index 133772407c5dd..be461c0e03d86 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -9,9 +9,10 @@ use rustc_errors::struct_span_err; use rustc_hir::{def_id::DefId, HirId}; use rustc_index::bit_set::BitSet; use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits::{self, TraitEngine}; use rustc_span::symbol::sym; use rustc_span::Span; +use rustc_trait_selection::traits::error_reporting::InferCtxtExt; +use rustc_trait_selection::traits::{self, TraitEngine}; use std::borrow::Cow; use std::ops::Deref; @@ -212,7 +213,7 @@ impl Validator<'a, 'mir, 'tcx> { // If an operation is supported in miri (and is not already controlled by a feature gate) it // can be turned on with `-Zunleash-the-miri-inside-of-you`. - let is_unleashable = O::IS_SUPPORTED_IN_MIRI && O::feature_gate(self.tcx).is_none(); + let is_unleashable = O::IS_SUPPORTED_IN_MIRI && O::feature_gate().is_none(); if is_unleashable && self.tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you { self.tcx.sess.span_warn(span, "skipping const checks"); @@ -343,7 +344,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { Rvalue::Ref(_, BorrowKind::Shared, ref place) | Rvalue::Ref(_, BorrowKind::Shallow, ref place) | Rvalue::AddressOf(Mutability::Not, ref place) => { - let borrowed_place_has_mut_interior = HasMutInterior::in_place( + let borrowed_place_has_mut_interior = qualifs::in_place::( &self.item, &mut |local| self.qualifs.has_mut_interior(local, location), place.as_ref(), diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 4dcbcdcbae4a6..3ba60e69041e7 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -1,5 +1,3 @@ -use rustc::hir::map::Map; -use rustc::lint::builtin::{SAFE_PACKED_BORROWS, UNUSED_UNSAFE}; use rustc::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; use rustc::mir::*; use rustc::ty::cast::CastTy; @@ -11,6 +9,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit; use rustc_hir::Node; +use rustc_session::lint::builtin::{SAFE_PACKED_BORROWS, UNUSED_UNSAFE}; use rustc_span::symbol::{sym, Symbol}; use std::ops::Bound; @@ -451,9 +450,9 @@ struct UnusedUnsafeVisitor<'a> { } impl<'a, 'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'a> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; - fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, Self::Map> { + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { intravisit::NestedVisitorMap::None } @@ -566,14 +565,14 @@ fn is_enclosed( } fn report_unused_unsafe(tcx: TyCtxt<'_>, used_unsafe: &FxHashSet, id: hir::HirId) { - let span = tcx.sess.source_map().def_span(tcx.hir().span(id)); + let span = tcx.sess.source_map().guess_head_span(tcx.hir().span(id)); tcx.struct_span_lint_hir(UNUSED_UNSAFE, id, span, |lint| { let msg = "unnecessary `unsafe` block"; let mut db = lint.build(msg); db.span_label(span, msg); if let Some((kind, id)) = is_enclosed(tcx, used_unsafe, id) { db.span_label( - tcx.sess.source_map().def_span(tcx.hir().span(id)), + tcx.sess.source_map().guess_head_span(tcx.hir().span(id)), format!("because it's nested under this `unsafe` {}", kind), ); } diff --git a/src/librustc_mir/transform/cleanup_post_borrowck.rs b/src/librustc_mir/transform/cleanup_post_borrowck.rs index 5288b6b370ddb..3d219ac2c01ec 100644 --- a/src/librustc_mir/transform/cleanup_post_borrowck.rs +++ b/src/librustc_mir/transform/cleanup_post_borrowck.rs @@ -32,6 +32,7 @@ impl<'tcx> MirPass<'tcx> for CleanupNonCodegenStatements { fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) { let mut delete = DeleteNonCodegenStatements { tcx }; delete.visit_body(body); + body.user_type_annotations.raw.clear(); } } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index f9682a77173f5..5fe8f9f3771b3 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -4,7 +4,6 @@ use std::borrow::Cow; use std::cell::Cell; -use rustc::lint; use rustc::mir::interpret::{InterpResult, Scalar}; use rustc::mir::visit::{ MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor, @@ -25,8 +24,9 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; use rustc_hir::HirId; use rustc_index::vec::IndexVec; -use rustc_infer::traits; -use rustc_span::Span; +use rustc_session::lint; +use rustc_span::{def_id::DefId, Span}; +use rustc_trait_selection::traits; use crate::const_eval::error_to_const_error; use crate::interpret::{ @@ -39,6 +39,24 @@ use crate::transform::{MirPass, MirSource}; /// The maximum number of bytes that we'll allocate space for a return value. const MAX_ALLOC_LIMIT: u64 = 1024; +/// Macro for machine-specific `InterpError` without allocation. +/// (These will never be shown to the user, but they help diagnose ICEs.) +macro_rules! throw_machine_stop_str { + ($($tt:tt)*) => {{ + // We make a new local type for it. The type itself does not carry any information, + // but its vtable (for the `MachineStopType` trait) does. + struct Zst; + // Debug-printing this type shows the desired string. + impl std::fmt::Debug for Zst { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, $($tt)*) + } + } + impl rustc::mir::interpret::MachineStopType for Zst {} + throw_machine_stop!(Zst) + }}; +} + pub struct ConstProp; impl<'tcx> MirPass<'tcx> for ConstProp { @@ -144,7 +162,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp { struct ConstPropMachine; impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { - type MemoryKinds = !; + type MemoryKind = !; type PointerTag = (); type ExtraFnVal = !; @@ -154,7 +172,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { type MemoryMap = FxHashMap, Allocation)>; - const STATIC_KIND: Option = None; + const GLOBAL_KIND: Option = None; // no copying of globals from `tcx` to machine memory const CHECK_ALIGN: bool = false; @@ -192,7 +210,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { _ret: Option<(PlaceTy<'tcx>, BasicBlock)>, _unwind: Option, ) -> InterpResult<'tcx> { - throw_unsup!(ConstPropUnsupported("calling intrinsics isn't supported in ConstProp")); + throw_machine_stop_str!("calling intrinsics isn't supported in ConstProp") } fn assert_panic( @@ -200,11 +218,11 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { _msg: &rustc::mir::AssertMessage<'tcx>, _unwind: Option, ) -> InterpResult<'tcx> { - bug!("panics terminators are not evaluated in ConstProp"); + bug!("panics terminators are not evaluated in ConstProp") } fn ptr_to_int(_mem: &Memory<'mir, 'tcx, Self>, _ptr: Pointer) -> InterpResult<'tcx, u64> { - throw_unsup!(ConstPropUnsupported("ptr-to-int casts aren't supported in ConstProp")); + throw_unsup!(ReadPointerAsBytes) } fn binary_ptr_op( @@ -214,10 +232,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { _right: ImmTy<'tcx>, ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> { // We can't do this because aliasing of memory can differ between const eval and llvm - throw_unsup!(ConstPropUnsupported( - "pointer arithmetic or comparisons aren't supported \ - in ConstProp" - )); + throw_machine_stop_str!("pointer arithmetic or comparisons aren't supported in ConstProp") } #[inline(always)] @@ -232,15 +247,13 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { } #[inline(always)] - fn tag_static_base_pointer(_memory_extra: &(), _id: AllocId) -> Self::PointerTag { - () - } + fn tag_global_base_pointer(_memory_extra: &(), _id: AllocId) -> Self::PointerTag {} fn box_alloc( _ecx: &mut InterpCx<'mir, 'tcx, Self>, _dest: PlaceTy<'tcx>, ) -> InterpResult<'tcx> { - throw_unsup!(ConstPropUnsupported("can't const prop `box` keyword")); + throw_machine_stop_str!("can't const prop heap allocations") } fn access_local( @@ -251,20 +264,29 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { let l = &frame.locals[local]; if l.value == LocalValue::Uninitialized { - throw_unsup!(ConstPropUnsupported("tried to access an uninitialized local")); + throw_machine_stop_str!("tried to access an uninitialized local") } l.access() } - fn before_access_static( + fn before_access_global( _memory_extra: &(), + _alloc_id: AllocId, allocation: &Allocation, + static_def_id: Option, + is_write: bool, ) -> InterpResult<'tcx> { - // if the static allocation is mutable or if it has relocations (it may be legal to mutate - // the memory behind that in the future), then we can't const prop it - if allocation.mutability == Mutability::Mut || allocation.relocations().len() > 0 { - throw_unsup!(ConstPropUnsupported("can't eval mutable statics in ConstProp")); + if is_write { + throw_machine_stop_str!("can't write to global"); + } + // If the static allocation is mutable or if it has relocations (it may be legal to mutate + // the memory behind that in the future), then we can't const prop it. + if allocation.mutability == Mutability::Mut { + throw_machine_stop_str!("can't eval mutable globals in ConstProp"); + } + if static_def_id.is_some() && allocation.relocations().len() > 0 { + throw_machine_stop_str!("can't eval statics with pointers in ConstProp"); } Ok(()) @@ -324,14 +346,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { ) -> ConstPropagator<'mir, 'tcx> { let def_id = source.def_id(); let substs = &InternalSubsts::identity_for_item(tcx, def_id); - let mut param_env = tcx.param_env(def_id); - - // If we're evaluating inside a monomorphic function, then use `Reveal::All` because - // we want to see the same instances that codegen will see. This allows us to `resolve()` - // specializations. - if !substs.needs_subst() { - param_env = param_env.with_reveal_all(); - } + let param_env = tcx.param_env(def_id).with_reveal_all(); let span = tcx.def_span(def_id); let mut ecx = InterpCx::new(tcx.at(span), param_env, ConstPropMachine, ()); @@ -400,22 +415,20 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { where F: FnOnce(&mut Self) -> InterpResult<'tcx, T>, { - let r = match f(self) { + match f(self) { Ok(val) => Some(val), Err(error) => { // Some errors shouldn't come up because creating them causes // an allocation, which we should avoid. When that happens, // dedicated error variants should be introduced instead. - // Only test this in debug builds though to avoid disruptions. - debug_assert!( + assert!( !error.kind.allocates(), "const-prop encountered allocating error: {}", error ); None } - }; - r + } } fn eval_constant(&mut self, c: &Constant<'tcx>, source_info: SourceInfo) -> Option> { @@ -483,7 +496,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { err.span_label(source_info.span, format!("{:?}", panic)); err.emit() }); - return None; + None } fn check_unary_op( @@ -675,7 +688,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let ty1 = substs[0].expect_ty(); let ty2 = substs[1].expect_ty(); let ty_is_scalar = |ty| { - this.ecx.layout_of(ty).ok().map(|ty| ty.details.abi.is_scalar()) + this.ecx.layout_of(ty).ok().map(|layout| layout.abi.is_scalar()) == Some(true) }; if ty_is_scalar(ty1) && ty_is_scalar(ty2) { diff --git a/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs index 5dec2c6df99dc..795bcb57d0678 100644 --- a/src/librustc_mir/transform/dump_mir.rs +++ b/src/librustc_mir/transform/dump_mir.rs @@ -8,8 +8,8 @@ use std::io; use crate::transform::{MirPass, MirSource}; use crate::util as mir_util; use rustc::mir::{Body, BodyAndCache}; -use rustc::session::config::{OutputFilenames, OutputType}; use rustc::ty::TyCtxt; +use rustc_session::config::{OutputFilenames, OutputType}; pub struct Marker(pub &'static str); diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs deleted file mode 100644 index 996b97c03b14e..0000000000000 --- a/src/librustc_mir/transform/erase_regions.rs +++ /dev/null @@ -1,63 +0,0 @@ -//! This pass erases all early-bound regions from the types occurring in the MIR. -//! We want to do this once just before codegen, so codegen does not have to take -//! care erasing regions all over the place. -//! N.B., we do _not_ erase regions of statements that are relevant for -//! "types-as-contracts"-validation, namely, `AcquireValid` and `ReleaseValid`. - -use crate::transform::{MirPass, MirSource}; -use rustc::mir::visit::{MutVisitor, TyContext}; -use rustc::mir::*; -use rustc::ty::subst::SubstsRef; -use rustc::ty::{self, Ty, TyCtxt}; - -struct EraseRegionsVisitor<'tcx> { - tcx: TyCtxt<'tcx>, -} - -impl EraseRegionsVisitor<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>) -> Self { - EraseRegionsVisitor { tcx } - } -} - -impl MutVisitor<'tcx> for EraseRegionsVisitor<'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) { - *ty = self.tcx.erase_regions(ty); - } - - fn visit_region(&mut self, region: &mut ty::Region<'tcx>, _: Location) { - *region = self.tcx.lifetimes.re_erased; - } - - fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _: Location) { - *constant = self.tcx.erase_regions(constant); - } - - fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, _: Location) { - *substs = self.tcx.erase_regions(substs); - } - - fn process_projection_elem(&mut self, elem: &PlaceElem<'tcx>) -> Option> { - if let PlaceElem::Field(field, ty) = elem { - let new_ty = self.tcx.erase_regions(ty); - - if new_ty != *ty { - return Some(PlaceElem::Field(*field, new_ty)); - } - } - - None - } -} - -pub struct EraseRegions; - -impl<'tcx> MirPass<'tcx> for EraseRegions { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) { - EraseRegionsVisitor::new(tcx).visit_body(body); - } -} diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index d060a0eab3db0..349cda831053f 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -107,15 +107,15 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor<'tcx> { } fn visit_local(&mut self, local: &mut Local, _: PlaceContext, _: Location) { - assert_ne!(*local, self_arg()); + assert_ne!(*local, SELF_ARG); } fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) { - if place.local == self_arg() { + if place.local == SELF_ARG { replace_base( place, Place { - local: self_arg(), + local: SELF_ARG, projection: self.tcx().intern_place_elems(&[ProjectionElem::Deref]), }, self.tcx, @@ -125,7 +125,7 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor<'tcx> { for elem in place.projection.iter() { if let PlaceElem::Index(local) = elem { - assert_ne!(*local, self_arg()); + assert_ne!(*local, SELF_ARG); } } } @@ -143,15 +143,15 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> { } fn visit_local(&mut self, local: &mut Local, _: PlaceContext, _: Location) { - assert_ne!(*local, self_arg()); + assert_ne!(*local, SELF_ARG); } fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) { - if place.local == self_arg() { + if place.local == SELF_ARG { replace_base( place, Place { - local: self_arg(), + local: SELF_ARG, projection: self.tcx().intern_place_elems(&[ProjectionElem::Field( Field::new(0), self.ref_gen_ty, @@ -164,7 +164,7 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> { for elem in place.projection.iter() { if let PlaceElem::Index(local) = elem { - assert_ne!(*local, self_arg()); + assert_ne!(*local, SELF_ARG); } } } @@ -180,9 +180,7 @@ fn replace_base<'tcx>(place: &mut Place<'tcx>, new_base: Place<'tcx>, tcx: TyCtx place.projection = tcx.intern_place_elems(&new_projection); } -fn self_arg() -> Local { - Local::new(1) -} +const SELF_ARG: Local = Local::from_u32(1); /// Generator has not been resumed yet. const UNRESUMED: usize = GeneratorSubsts::UNRESUMED; @@ -237,7 +235,7 @@ impl TransformVisitor<'tcx> { // Create a Place referencing a generator struct field fn make_field(&self, variant_index: VariantIdx, idx: usize, ty: Ty<'tcx>) -> Place<'tcx> { - let self_place = Place::from(self_arg()); + let self_place = Place::from(SELF_ARG); let base = self.tcx.mk_place_downcast_unnamed(self_place, variant_index); let mut projection = base.projection.to_vec(); projection.push(ProjectionElem::Field(Field::new(idx), ty)); @@ -247,7 +245,7 @@ impl TransformVisitor<'tcx> { // Create a statement which changes the discriminant fn set_discr(&self, state_disc: VariantIdx, source_info: SourceInfo) -> Statement<'tcx> { - let self_place = Place::from(self_arg()); + let self_place = Place::from(SELF_ARG); Statement { source_info, kind: StatementKind::SetDiscriminant { @@ -263,7 +261,7 @@ impl TransformVisitor<'tcx> { let local_decls_len = body.local_decls.push(temp_decl); let temp = Place::from(local_decls_len); - let self_place = Place::from(self_arg()); + let self_place = Place::from(SELF_ARG); let assign = Statement { source_info: source_info(body), kind: StatementKind::Assign(box (temp, Rvalue::Discriminant(self_place))), @@ -359,18 +357,11 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> { } } -fn make_generator_state_argument_indirect<'tcx>( - tcx: TyCtxt<'tcx>, - def_id: DefId, - body: &mut BodyAndCache<'tcx>, -) { +fn make_generator_state_argument_indirect<'tcx>(tcx: TyCtxt<'tcx>, body: &mut BodyAndCache<'tcx>) { let gen_ty = body.local_decls.raw[1].ty; - let region = ty::ReFree(ty::FreeRegion { scope: def_id, bound_region: ty::BoundRegion::BrEnv }); - - let region = tcx.mk_region(region); - - let ref_gen_ty = tcx.mk_ref(region, ty::TypeAndMut { ty: gen_ty, mutbl: hir::Mutability::Mut }); + let ref_gen_ty = + tcx.mk_ref(tcx.lifetimes.re_erased, ty::TypeAndMut { ty: gen_ty, mutbl: Mutability::Mut }); // Replace the by value generator argument body.local_decls.raw[1].ty = ref_gen_ty; @@ -539,8 +530,8 @@ fn locals_live_across_suspend_points( let mut live_locals_here = storage_required; live_locals_here.intersect(&liveness.outs[block]); - // The generator argument is ignored - live_locals_here.remove(self_arg()); + // The generator argument is ignored. + live_locals_here.remove(SELF_ARG); debug!("loc = {:?}, live_locals_here = {:?}", loc, live_locals_here); @@ -837,7 +828,6 @@ fn elaborate_generator_drops<'tcx>( // generator's resume function. let param_env = tcx.param_env(def_id); - let gen = self_arg(); let mut elaborator = DropShimElaborator { body, patch: MirPatch::new(body), tcx, param_env }; @@ -845,7 +835,7 @@ fn elaborate_generator_drops<'tcx>( let (target, unwind, source_info) = match block_data.terminator() { Terminator { source_info, kind: TerminatorKind::Drop { location, target, unwind } } => { if let Some(local) = location.as_local() { - if local == gen { + if local == SELF_ARG { (target, unwind, source_info) } else { continue; @@ -864,7 +854,7 @@ fn elaborate_generator_drops<'tcx>( elaborate_drop( &mut elaborator, *source_info, - &Place::from(gen), + &Place::from(SELF_ARG), (), *target, unwind, @@ -877,7 +867,6 @@ fn elaborate_generator_drops<'tcx>( fn create_generator_drop_shim<'tcx>( tcx: TyCtxt<'tcx>, transform: &TransformVisitor<'tcx>, - def_id: DefId, source: MirSource<'tcx>, gen_ty: Ty<'tcx>, body: &mut BodyAndCache<'tcx>, @@ -915,10 +904,10 @@ fn create_generator_drop_shim<'tcx>( local_info: LocalInfo::Other, }; - make_generator_state_argument_indirect(tcx, def_id, &mut body); + make_generator_state_argument_indirect(tcx, &mut body); // Change the generator argument from &mut to *mut - body.local_decls[self_arg()] = LocalDecl { + body.local_decls[SELF_ARG] = LocalDecl { mutability: Mutability::Mut, ty: tcx.mk_ptr(ty::TypeAndMut { ty: gen_ty, mutbl: hir::Mutability::Mut }), user_ty: UserTypeProjections::none(), @@ -933,7 +922,7 @@ fn create_generator_drop_shim<'tcx>( 0, Statement { source_info, - kind: StatementKind::Retag(RetagKind::Raw, box Place::from(self_arg())), + kind: StatementKind::Retag(RetagKind::Raw, box Place::from(SELF_ARG)), }, ) } @@ -944,7 +933,7 @@ fn create_generator_drop_shim<'tcx>( // unrelated code from the resume part of the function simplify::remove_dead_blocks(&mut body); - dump_mir(tcx, None, "generator_drop", &0, source, &mut body, |_, _| Ok(())); + dump_mir(tcx, None, "generator_drop", &0, source, &body, |_, _| Ok(())); body } @@ -991,18 +980,100 @@ fn insert_panic_block<'tcx>( assert_block } +fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool { + // Returning from a function with an uninhabited return type is undefined behavior. + if body.return_ty().conservative_is_privately_uninhabited(tcx) { + return false; + } + + // If there's a return terminator the function may return. + for block in body.basic_blocks() { + if let TerminatorKind::Return = block.terminator().kind { + return true; + } + } + + // Otherwise the function can't return. + false +} + +fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool { + // Nothing can unwind when landing pads are off. + if tcx.sess.no_landing_pads() { + return false; + } + + // Unwinds can only start at certain terminators. + for block in body.basic_blocks() { + match block.terminator().kind { + // These never unwind. + TerminatorKind::Goto { .. } + | TerminatorKind::SwitchInt { .. } + | TerminatorKind::Abort + | TerminatorKind::Return + | TerminatorKind::Unreachable + | TerminatorKind::GeneratorDrop + | TerminatorKind::FalseEdges { .. } + | TerminatorKind::FalseUnwind { .. } => {} + + // Resume will *continue* unwinding, but if there's no other unwinding terminator it + // will never be reached. + TerminatorKind::Resume => {} + + TerminatorKind::Yield { .. } => { + unreachable!("`can_unwind` called before generator transform") + } + + // These may unwind. + TerminatorKind::Drop { .. } + | TerminatorKind::DropAndReplace { .. } + | TerminatorKind::Call { .. } + | TerminatorKind::Assert { .. } => return true, + } + } + + // If we didn't find an unwinding terminator, the function cannot unwind. + false +} + fn create_generator_resume_function<'tcx>( tcx: TyCtxt<'tcx>, transform: TransformVisitor<'tcx>, - def_id: DefId, source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>, + can_return: bool, ) { + let can_unwind = can_unwind(tcx, body); + // Poison the generator when it unwinds - for block in body.basic_blocks_mut() { - let source_info = block.terminator().source_info; - if let &TerminatorKind::Resume = &block.terminator().kind { - block.statements.push(transform.set_discr(VariantIdx::new(POISONED), source_info)); + if can_unwind { + let poison_block = BasicBlock::new(body.basic_blocks().len()); + let source_info = source_info(body); + body.basic_blocks_mut().push(BasicBlockData { + statements: vec![transform.set_discr(VariantIdx::new(POISONED), source_info)], + terminator: Some(Terminator { source_info, kind: TerminatorKind::Resume }), + is_cleanup: true, + }); + + for (idx, block) in body.basic_blocks_mut().iter_enumerated_mut() { + let source_info = block.terminator().source_info; + + if let TerminatorKind::Resume = block.terminator().kind { + // An existing `Resume` terminator is redirected to jump to our dedicated + // "poisoning block" above. + if idx != poison_block { + *block.terminator_mut() = Terminator { + source_info, + kind: TerminatorKind::Goto { target: poison_block }, + }; + } + } else if !block.is_cleanup { + // Any terminators that *can* unwind but don't have an unwind target set are also + // pointed at our poisoning block (unless they're part of the cleanup path). + if let Some(unwind @ None) = block.terminator_mut().unwind_mut() { + *unwind = Some(poison_block); + } + } } } @@ -1015,12 +1086,24 @@ fn create_generator_resume_function<'tcx>( // Panic when resumed on the returned or poisoned state let generator_kind = body.generator_kind.unwrap(); - cases.insert(1, (RETURNED, insert_panic_block(tcx, body, ResumedAfterReturn(generator_kind)))); - cases.insert(2, (POISONED, insert_panic_block(tcx, body, ResumedAfterPanic(generator_kind)))); + + if can_unwind { + cases.insert( + 1, + (POISONED, insert_panic_block(tcx, body, ResumedAfterPanic(generator_kind))), + ); + } + + if can_return { + cases.insert( + 1, + (RETURNED, insert_panic_block(tcx, body, ResumedAfterReturn(generator_kind))), + ); + } insert_switch(body, cases, &transform, TerminatorKind::Unreachable); - make_generator_state_argument_indirect(tcx, def_id, body); + make_generator_state_argument_indirect(tcx, body); make_generator_state_argument_pinned(tcx, body); no_landing_pads(tcx, body); @@ -1042,7 +1125,7 @@ fn insert_clean_drop(body: &mut BodyAndCache<'_>) -> BasicBlock { // Create a block to destroy an unresumed generators. This can only destroy upvars. let drop_clean = BasicBlock::new(body.basic_blocks().len()); let term = TerminatorKind::Drop { - location: Place::from(self_arg()), + location: Place::from(SELF_ARG), target: return_block, unwind: None, }; @@ -1153,8 +1236,8 @@ impl<'tcx> MirPass<'tcx> for StateTransform { ty::Generator(_, substs, movability) => { let substs = substs.as_generator(); ( - substs.upvar_tys(def_id, tcx).collect(), - substs.witness(def_id, tcx), + substs.upvar_tys().collect(), + substs.witness(), substs.discr_ty(tcx), movability == hir::Movability::Movable, ) @@ -1200,6 +1283,8 @@ impl<'tcx> MirPass<'tcx> for StateTransform { let (remap, layout, storage_liveness) = compute_layout(tcx, source, &upvars, interior, movable, body); + let can_return = can_return(tcx, body); + // Run the transformation which converts Places from Local to generator struct // accesses for locals in `remap`. // It also rewrites `return x` and `yield y` as writing a new generator state and returning @@ -1238,11 +1323,11 @@ impl<'tcx> MirPass<'tcx> for StateTransform { // Create a copy of our MIR and use it to create the drop shim for the generator let drop_shim = - create_generator_drop_shim(tcx, &transform, def_id, source, gen_ty, body, drop_clean); + create_generator_drop_shim(tcx, &transform, source, gen_ty, body, drop_clean); body.generator_drop = Some(box drop_shim); // Create the Generator::resume function - create_generator_resume_function(tcx, transform, def_id, source, body); + create_generator_resume_function(tcx, transform, source, body, can_return); } } diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index b6802505df73f..16c32e138fdf0 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -1,30 +1,29 @@ //! Inlining pass for MIR functions -use rustc_hir::def_id::DefId; - -use rustc_index::bit_set::BitSet; -use rustc_index::vec::{Idx, IndexVec}; - use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc::mir::visit::*; use rustc::mir::*; -use rustc::session::config::Sanitizer; -use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef}; -use rustc::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt, TypeFoldable}; +use rustc::ty::subst::{Subst, SubstsRef}; +use rustc::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt}; +use rustc_attr as attr; +use rustc_hir::def_id::DefId; +use rustc_index::bit_set::BitSet; +use rustc_index::vec::{Idx, IndexVec}; +use rustc_session::config::Sanitizer; +use rustc_target::spec::abi::Abi; use super::simplify::{remove_dead_blocks, CfgSimplifier}; use crate::transform::{MirPass, MirSource}; use std::collections::VecDeque; use std::iter; -use rustc_attr as attr; -use rustc_target::spec::abi::Abi; - const DEFAULT_THRESHOLD: usize = 50; const HINT_THRESHOLD: usize = 100; const INSTR_COST: usize = 5; const CALL_PENALTY: usize = 25; +const LANDINGPAD_PENALTY: usize = 50; +const RESUME_PENALTY: usize = 45; const UNKNOWN_SIZE_COST: usize = 10; @@ -67,14 +66,7 @@ impl Inliner<'tcx> { let mut callsites = VecDeque::new(); - let mut param_env = self.tcx.param_env(self.source.def_id()); - - let substs = &InternalSubsts::identity_for_item(self.tcx, self.source.def_id()); - - // For monomorphic functions, we can use `Reveal::All` to resolve specialized instances. - if !substs.needs_subst() { - param_env = param_env.with_reveal_all(); - } + let param_env = self.tcx.param_env(self.source.def_id()).with_reveal_all(); // Only do inlining into fn bodies. let id = self.tcx.hir().as_local_hir_id(self.source.def_id()).unwrap(); @@ -328,6 +320,7 @@ impl Inliner<'tcx> { if ty.needs_drop(tcx, param_env) { cost += CALL_PENALTY; if let Some(unwind) = unwind { + cost += LANDINGPAD_PENALTY; work_list.push(unwind); } } else { @@ -343,7 +336,7 @@ impl Inliner<'tcx> { threshold = 0; } - TerminatorKind::Call { func: Operand::Constant(ref f), .. } => { + TerminatorKind::Call { func: Operand::Constant(ref f), cleanup, .. } => { if let ty::FnDef(def_id, _) = f.literal.ty.kind { // Don't give intrinsics the extra penalty for calls let f = tcx.fn_sig(def_id); @@ -352,9 +345,21 @@ impl Inliner<'tcx> { } else { cost += CALL_PENALTY; } + } else { + cost += CALL_PENALTY; + } + if cleanup.is_some() { + cost += LANDINGPAD_PENALTY; + } + } + TerminatorKind::Assert { cleanup, .. } => { + cost += CALL_PENALTY; + + if cleanup.is_some() { + cost += LANDINGPAD_PENALTY; } } - TerminatorKind::Assert { .. } => cost += CALL_PENALTY, + TerminatorKind::Resume => cost += RESUME_PENALTY, _ => cost += INSTR_COST, } diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 57e002bf3f3d6..50868434baa32 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -1,5 +1,4 @@ use crate::{shim, util}; -use rustc::hir::map::Map; use rustc::mir::{BodyAndCache, ConstQualifs, MirPhase, Promoted}; use rustc::ty::query::Providers; use rustc::ty::steal::Steal; @@ -23,7 +22,6 @@ pub mod copy_prop; pub mod deaggregator; pub mod dump_mir; pub mod elaborate_drops; -pub mod erase_regions; pub mod generator; pub mod inline; pub mod instcombine; @@ -86,8 +84,8 @@ fn mir_keys(tcx: TyCtxt<'_>, krate: CrateNum) -> &DefIdSet { } intravisit::walk_struct_def(self, v) } - type Map = Map<'tcx>; - fn nested_visit_map<'b>(&'b mut self) -> NestedVisitorMap<'b, Self::Map> { + type Map = intravisit::ErasedMap<'tcx>; + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } @@ -297,8 +295,6 @@ fn run_optimization_passes<'tcx>( &simplify::SimplifyCfg::new("elaborate-drops"), // No lifetime analysis based on borrowing can be done from here on out. - // From here on out, regions are gone. - &erase_regions::EraseRegions, // Optimizations begin. &unreachable_prop::UnreachablePropagation, &uninhabited_enum_branching::UninhabitedEnumBranching, @@ -342,6 +338,9 @@ fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &BodyAndCache<'_> { let mut body = body.steal(); run_optimization_passes(tcx, &mut body, def_id, None); body.ensure_predecessors(); + + debug_assert!(!body.has_free_regions(), "Free regions in optimized MIR"); + tcx.arena.alloc(body) } @@ -359,5 +358,7 @@ fn promoted_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &IndexVec Validator<'_, 'tcx> { // FIXME(eddyb) maybe cache this? fn qualif_local(&self, local: Local) -> bool { - let per_local = &mut |l| self.qualif_local::(l); - if let TempState::Defined { location: loc, .. } = self.temps[local] { let num_stmts = self.body[loc.block].statements.len(); if loc.statement_index < num_stmts { let statement = &self.body[loc.block].statements[loc.statement_index]; match &statement.kind { - StatementKind::Assign(box (_, rhs)) => Q::in_rvalue(&self.item, per_local, rhs), + StatementKind::Assign(box (_, rhs)) => qualifs::in_rvalue::( + &self.item, + &mut |l| self.qualif_local::(l), + rhs, + ), _ => { span_bug!( statement.source_info.span, @@ -427,9 +429,9 @@ impl<'tcx> Validator<'_, 'tcx> { } else { let terminator = self.body[loc.block].terminator(); match &terminator.kind { - TerminatorKind::Call { func, args, .. } => { + TerminatorKind::Call { .. } => { let return_ty = self.body.local_decls[local].ty; - Q::in_call(&self.item, per_local, func, args, return_ty) + Q::in_any_value_of_ty(&self.item, return_ty) } kind => { span_bug!(terminator.source_info.span, "{:?} not promotable", kind); @@ -911,7 +913,13 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { ty, val: ty::ConstKind::Unevaluated( def_id, - InternalSubsts::identity_for_item(tcx, def_id), + InternalSubsts::for_item(tcx, def_id, |param, _| { + if let ty::GenericParamDefKind::Lifetime = param.kind { + tcx.lifetimes.re_erased.into() + } else { + tcx.mk_param_from_def(param) + } + }), Some(promoted_id), ), }), diff --git a/src/librustc_mir/transform/uninhabited_enum_branching.rs b/src/librustc_mir/transform/uninhabited_enum_branching.rs index bbaa66f5954cb..7178e614f0a97 100644 --- a/src/librustc_mir/transform/uninhabited_enum_branching.rs +++ b/src/librustc_mir/transform/uninhabited_enum_branching.rs @@ -53,7 +53,7 @@ fn variant_discriminants<'tcx>( ty: Ty<'tcx>, tcx: TyCtxt<'tcx>, ) -> Vec { - match &layout.details.variants { + match &layout.variants { Variants::Single { index } => vec![index.as_u32() as u128], Variants::Multiple { variants, .. } => variants .iter_enumerated() diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index d8ee059f1a6b6..6e6bbabd35b3c 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -4,7 +4,7 @@ use rustc_span::{MultiSpan, Span}; impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { crate fn cannot_move_when_borrowed(&self, span: Span, desc: &str) -> DiagnosticBuilder<'cx> { - struct_span_err!(self, span, E0505, "cannot move out of `{}` because it is borrowed", desc,) + struct_span_err!(self, span, E0505, "cannot move out of {} because it is borrowed", desc,) } crate fn cannot_use_when_mutably_borrowed( @@ -18,12 +18,12 @@ impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { self, span, E0503, - "cannot use `{}` because it was mutably borrowed", + "cannot use {} because it was mutably borrowed", desc, ); - err.span_label(borrow_span, format!("borrow of `{}` occurs here", borrow_desc)); - err.span_label(span, format!("use of borrowed `{}`", borrow_desc)); + err.span_label(borrow_span, format!("borrow of {} occurs here", borrow_desc)); + err.span_label(span, format!("use of borrowed {}", borrow_desc)); err } @@ -53,12 +53,12 @@ impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { old_load_end_span: Option, ) -> DiagnosticBuilder<'cx> { let via = - |msg: &str| if msg.is_empty() { msg.to_string() } else { format!(" (via `{}`)", msg) }; + |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {})", msg) }; let mut err = struct_span_err!( self, new_loan_span, E0499, - "cannot borrow `{}`{} as mutable more than once at a time", + "cannot borrow {}{} as mutable more than once at a time", desc, via(opt_via), ); @@ -103,7 +103,7 @@ impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { self, new_loan_span, E0524, - "two closures require unique access to `{}` at the same time", + "two closures require unique access to {} at the same time", desc, ); if old_loan_span == new_loan_span { @@ -136,7 +136,7 @@ impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { self, new_loan_span, E0500, - "closure requires unique access to `{}` but {} is already borrowed{}", + "closure requires unique access to {} but {} is already borrowed{}", desc_new, noun_old, old_opt_via, @@ -168,7 +168,7 @@ impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { self, new_loan_span, E0501, - "cannot borrow `{}`{} as {} because previous closure \ + "cannot borrow {}{} as {} because previous closure \ requires unique access", desc_new, opt_via, @@ -201,13 +201,12 @@ impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { old_load_end_span: Option, ) -> DiagnosticBuilder<'cx> { let via = - |msg: &str| if msg.is_empty() { msg.to_string() } else { format!(" (via `{}`)", msg) }; + |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {})", msg) }; let mut err = struct_span_err!( self, span, E0502, - "cannot borrow `{}`{} as {} because {} is also borrowed \ - as {}{}", + "cannot borrow {}{} as {} because {} is also borrowed as {}{}", desc_new, via(msg_new), kind_new, @@ -225,7 +224,7 @@ impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { err.span_label( span, format!( - "{} borrow of `{}` -- which overlaps with `{}` -- occurs here", + "{} borrow of {} -- which overlaps with {} -- occurs here", kind_new, msg_new, msg_old, ), ); @@ -248,12 +247,12 @@ impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { self, span, E0506, - "cannot assign to `{}` because it is borrowed", + "cannot assign to {} because it is borrowed", desc, ); - err.span_label(borrow_span, format!("borrow of `{}` occurs here", desc)); - err.span_label(span, format!("assignment to borrowed `{}` occurs here", desc)); + err.span_label(borrow_span, format!("borrow of {} occurs here", desc)); + err.span_label(span, format!("assignment to borrowed {} occurs here", desc)); err } @@ -264,7 +263,7 @@ impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { is_arg: bool, ) -> DiagnosticBuilder<'cx> { let msg = if is_arg { "to immutable argument" } else { "twice to immutable variable" }; - struct_span_err!(self, span, E0384, "cannot assign {} `{}`", msg, desc,) + struct_span_err!(self, span, E0384, "cannot assign {} {}", msg, desc) } crate fn cannot_assign(&self, span: Span, desc: &str) -> DiagnosticBuilder<'cx> { @@ -362,7 +361,7 @@ impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { self, mutate_span, E0510, - "cannot {} `{}` in {}", + "cannot {} {} in {}", action, immutable_place, immutable_section, diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index ecf0a8ea83ca3..14895ddfbe44f 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -798,8 +798,8 @@ where fn open_drop(&mut self) -> BasicBlock { let ty = self.place_ty(self.place); match ty.kind { - ty::Closure(def_id, substs) => { - let tys: Vec<_> = substs.as_closure().upvar_tys(def_id, self.tcx()).collect(); + ty::Closure(_, substs) => { + let tys: Vec<_> = substs.as_closure().upvar_tys().collect(); self.open_drop_for_tuple(&tys) } // Note that `elaborate_drops` only drops the upvars of a generator, @@ -808,8 +808,8 @@ where // This should only happen for the self argument on the resume function. // It effetively only contains upvars until the generator transformation runs. // See librustc_body/transform/generator.rs for more details. - ty::Generator(def_id, substs, _) => { - let tys: Vec<_> = substs.as_generator().upvar_tys(def_id, self.tcx()).collect(); + ty::Generator(_, substs, _) => { + let tys: Vec<_> = substs.as_generator().upvar_tys().collect(); self.open_drop_for_tuple(&tys) } ty::Tuple(..) => { diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index b12ad1e4c15cc..f6c6f55549593 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -293,7 +293,7 @@ fn dump_matched_mir_node<'tcx>( writeln!(file, "// MIR local liveness analysis for `{}`", node_path)?; writeln!(file, "// source = {:?}", source)?; writeln!(file, "// pass_name = {}", pass_name)?; - writeln!(file, "")?; + writeln!(file)?; write_mir_fn(tcx, source, body, &mut file, result)?; Ok(()) }); @@ -316,7 +316,7 @@ pub fn write_mir_fn<'tcx>( write_basic_block(tcx, block, body, &mut |_, _| Ok(()), w)?; print(w, " ", &result.outs)?; if block.index() + 1 != body.basic_blocks().len() { - writeln!(w, "")?; + writeln!(w)?; } } diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index e7ca8b0be78c4..4c380d1141806 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -134,7 +134,7 @@ fn dump_matched_mir_node<'tcx, F>( if let Some(ref layout) = body.generator_layout { writeln!(file, "// generator_layout = {:?}", layout)?; } - writeln!(file, "")?; + writeln!(file)?; extra_data(PassWhere::BeforeCFG, &mut file)?; write_user_type_annotations(body, &mut file)?; write_mir_fn(tcx, source, body, &mut extra_data, &mut file)?; @@ -242,13 +242,13 @@ pub fn write_mir_pretty<'tcx>( first = false; } else { // Put empty lines between all items - writeln!(w, "")?; + writeln!(w)?; } write_mir_fn(tcx, MirSource::item(def_id), body, &mut |_, _| Ok(()), w)?; for (i, body) in tcx.promoted_mir(def_id).iter_enumerated() { - writeln!(w, "")?; + writeln!(w)?; let src = MirSource { instance: ty::InstanceDef::Item(def_id), promoted: Some(i) }; write_mir_fn(tcx, src, body, &mut |_, _| Ok(()), w)?; } @@ -271,7 +271,7 @@ where extra_data(PassWhere::BeforeBlock(block), w)?; write_basic_block(tcx, block, body, extra_data, w)?; if block.index() + 1 != body.basic_blocks().len() { - writeln!(w, "")?; + writeln!(w)?; } } @@ -529,7 +529,7 @@ pub fn write_mir_intro<'tcx>( write_scope_tree(tcx, body, &scope_tree, w, OUTERMOST_SOURCE_SCOPE, 1)?; // Add an empty line before the first block is printed. - writeln!(w, "")?; + writeln!(w)?; Ok(()) } @@ -561,7 +561,7 @@ fn write_mir_sig( ty::print::with_forced_impl_filename_line(|| { // see notes on #41697 elsewhere - write!(w, " {}", tcx.def_path_str(src.def_id())) + write!(w, "{}", tcx.def_path_str(src.def_id())) })?; if src.promoted.is_none() && is_function { diff --git a/src/librustc_mir_build/Cargo.toml b/src/librustc_mir_build/Cargo.toml index d53188a39e5e0..96716dbd604d5 100644 --- a/src/librustc_mir_build/Cargo.toml +++ b/src/librustc_mir_build/Cargo.toml @@ -25,5 +25,6 @@ rustc_serialize = { path = "../libserialize", package = "serialize" } rustc_session = { path = "../librustc_session" } rustc_span = { path = "../librustc_span" } rustc_target = { path = "../librustc_target" } +rustc_trait_selection = { path = "../librustc_trait_selection" } rustc_ast = { path = "../librustc_ast" } smallvec = { version = "1.0", features = ["union", "may_dangle"] } diff --git a/src/librustc_mir_build/build/expr/as_temp.rs b/src/librustc_mir_build/build/expr/as_temp.rs index 34dd10cbc0fc8..82183e6c96e9f 100644 --- a/src/librustc_mir_build/build/expr/as_temp.rs +++ b/src/librustc_mir_build/build/expr/as_temp.rs @@ -73,10 +73,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // they are never assigned. ExprKind::Break { .. } | ExprKind::Continue { .. } | ExprKind::Return { .. } => (), ExprKind::Block { body: hir::Block { expr: None, targeted_by_break: false, .. } } - if expr_ty.is_never() => - { - () - } + if expr_ty.is_never() => {} _ => { this.cfg .push(block, Statement { source_info, kind: StatementKind::StorageLive(temp) }); diff --git a/src/librustc_mir_build/build/matches/simplify.rs b/src/librustc_mir_build/build/matches/simplify.rs index 80fa0c44860e4..aea4f5f1b3ac9 100644 --- a/src/librustc_mir_build/build/matches/simplify.rs +++ b/src/librustc_mir_build/build/matches/simplify.rs @@ -209,7 +209,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { i == variant_index || { self.hir.tcx().features().exhaustive_patterns && !v - .uninhabited_from(self.hir.tcx(), substs, adt_def.adt_kind()) + .uninhabited_from( + self.hir.tcx(), + substs, + adt_def.adt_kind(), + self.hir.param_env, + ) .is_empty() } }) && (adt_def.did.is_local() diff --git a/src/librustc_mir_build/build/mod.rs b/src/librustc_mir_build/build/mod.rs index c6bc86942957c..a7ec4f501ae76 100644 --- a/src/librustc_mir_build/build/mod.rs +++ b/src/librustc_mir_build/build/mod.rs @@ -6,7 +6,7 @@ use rustc::middle::lang_items; use rustc::middle::region; use rustc::mir::*; use rustc::ty::subst::Subst; -use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_attr::{self as attr, UnwindAttr}; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -39,12 +39,11 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> { .. }) | Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Method(hir::FnSig { decl, .. }, body_id), + kind: hir::ImplItemKind::Fn(hir::FnSig { decl, .. }, body_id), .. }) | Node::TraitItem(hir::TraitItem { - kind: - hir::TraitItemKind::Fn(hir::FnSig { decl, .. }, hir::TraitMethod::Provided(body_id)), + kind: hir::TraitItemKind::Fn(hir::FnSig { decl, .. }, hir::TraitFn::Provided(body_id)), .. }) => (*body_id, decl.output.span()), Node::Item(hir::Item { kind: hir::ItemKind::Static(ty, _, body_id), .. }) @@ -128,12 +127,8 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> { let ty = if fn_sig.c_variadic && index == fn_sig.inputs().len() { let va_list_did = tcx.require_lang_item(lang_items::VaListTypeLangItem, Some(arg.span)); - let region = tcx.mk_region(ty::ReScope(region::Scope { - id: body.value.hir_id.local_id, - data: region::ScopeData::CallSite, - })); - tcx.type_of(va_list_did).subst(tcx, &[region.into()]) + tcx.type_of(va_list_did).subst(tcx, &[tcx.lifetimes.re_erased.into()]) } else { fn_sig.inputs()[index] }; @@ -144,10 +139,9 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> { let arguments = implicit_argument.into_iter().chain(explicit_arguments); let (yield_ty, return_ty) = if body.generator_kind.is_some() { - let gen_sig = match ty.kind { - ty::Generator(gen_def_id, gen_substs, ..) => { - gen_substs.as_generator().sig(gen_def_id, tcx) - } + let gen_ty = tcx.body_tables(body_id).node_type(id); + let gen_sig = match gen_ty.kind { + ty::Generator(_, gen_substs, ..) => gen_substs.as_generator().sig(), _ => span_bug!(tcx.hir().span(id), "generator w/o generator type: {:?}", ty), }; (Some(gen_sig.yield_ty), gen_sig.return_ty) @@ -189,6 +183,20 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> { let mut body = BodyAndCache::new(body); body.ensure_predecessors(); + + // The borrow checker will replace all the regions here with its own + // inference variables. There's no point having non-erased regions here. + // The exception is `body.user_type_annotations`, which is used unmodified + // by borrow checking. + debug_assert!( + !(body.local_decls.has_free_regions() + || body.basic_blocks().has_free_regions() + || body.var_debug_info.has_free_regions() + || body.yield_ty.has_free_regions()), + "Unexpected free regions in MIR: {:?}", + body, + ); + body }) } @@ -209,7 +217,7 @@ fn liberated_closure_env_ty( }; let closure_env_ty = tcx.closure_env_ty(closure_def_id, closure_substs).unwrap(); - tcx.liberate_late_bound_regions(closure_def_id, &closure_env_ty) + tcx.erase_late_bound_regions(&closure_env_ty) } #[derive(Debug, PartialEq, Eq)] @@ -368,7 +376,7 @@ impl BlockContext { } } - return None; + None } /// Looks at the topmost frame on the BlockContext and reports @@ -628,11 +636,12 @@ where ); assert_eq!(block, builder.return_block()); - let mut spread_arg = None; - if abi == Abi::RustCall { + let spread_arg = if abi == Abi::RustCall { // RustCall pseudo-ABI untuples the last argument. - spread_arg = Some(Local::new(arguments.len())); - } + Some(Local::new(arguments.len())) + } else { + None + }; debug!("fn_id {:?} has attrs {:?}", fn_def_id, tcx.get_attrs(fn_def_id)); let mut body = builder.finish(); @@ -839,12 +848,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { closure_env_projs.push(ProjectionElem::Deref); closure_ty = ty; } - let (def_id, upvar_substs) = match closure_ty.kind { - ty::Closure(def_id, substs) => (def_id, ty::UpvarSubsts::Closure(substs)), - ty::Generator(def_id, substs, _) => (def_id, ty::UpvarSubsts::Generator(substs)), + let upvar_substs = match closure_ty.kind { + ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs), + ty::Generator(_, substs, _) => ty::UpvarSubsts::Generator(substs), _ => span_bug!(self.fn_span, "upvars with non-closure env ty {:?}", closure_ty), }; - let upvar_tys = upvar_substs.upvar_tys(def_id, tcx); + let upvar_tys = upvar_substs.upvar_tys(); let upvars_with_tys = upvars.iter().zip(upvar_tys); self.upvar_mutbls = upvars_with_tys .enumerate() diff --git a/src/librustc_mir_build/hair/cx/block.rs b/src/librustc_mir_build/hair/cx/block.rs index 8d7225c8c7b51..07a9d91cd746d 100644 --- a/src/librustc_mir_build/hair/cx/block.rs +++ b/src/librustc_mir_build/hair/cx/block.rs @@ -98,7 +98,7 @@ fn mirror_stmts<'a, 'tcx>( } } } - return result; + result } crate fn to_expr_ref<'a, 'tcx>( diff --git a/src/librustc_mir_build/hair/cx/expr.rs b/src/librustc_mir_build/hair/cx/expr.rs index 9f04bc1dc7697..9f93b817e38d8 100644 --- a/src/librustc_mir_build/hair/cx/expr.rs +++ b/src/librustc_mir_build/hair/cx/expr.rs @@ -3,14 +3,13 @@ use crate::hair::cx::to_ref::ToRef; use crate::hair::cx::Cx; use crate::hair::util::UserAnnotatedTyHelpers; use crate::hair::*; -use rustc::mir::interpret::{ErrorHandled, Scalar}; +use rustc::mir::interpret::Scalar; use rustc::mir::BorrowKind; use rustc::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, PointerCast}; use rustc::ty::subst::{InternalSubsts, SubstsRef}; use rustc::ty::{self, AdtKind, Ty}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; -use rustc_hir::def_id::LocalDefId; use rustc_index::vec::Idx; use rustc_span::Span; @@ -388,7 +387,7 @@ fn make_mirror_unadjusted<'a, 'tcx>( .upvars(def_id) .iter() .flat_map(|upvars| upvars.iter()) - .zip(substs.upvar_tys(def_id, cx.tcx)) + .zip(substs.upvar_tys()) .map(|((&var_hir_id, _), ty)| capture_upvar(cx, expr, var_hir_id, ty)) .collect(); ExprKind::Closure { closure_id: def_id, substs, upvars, movability } @@ -407,34 +406,8 @@ fn make_mirror_unadjusted<'a, 'tcx>( // Now comes the rote stuff: hir::ExprKind::Repeat(ref v, ref count) => { - 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( - ty::ParamEnv::reveal_all(), - def_id, - substs, - None, - Some(span), - ) { - Ok(cv) => { - if let Some(count) = cv.try_to_bits_for_ty( - cx.tcx, - ty::ParamEnv::reveal_all(), - cx.tcx.types.usize, - ) { - count as u64 - } else { - bug!("repeat count constant value can't be converted to usize"); - } - } - 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_def_id = cx.tcx.hir().local_def_id(count.hir_id).expect_local(); + let count = ty::Const::from_anon_const(cx.tcx, count_def_id); ExprKind::Repeat { value: v.to_ref(), count } } @@ -812,7 +785,7 @@ fn convert_var<'tcx>( let closure_def_id = cx.body_owner; let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { hir_id: var_hir_id }, - closure_expr_id: LocalDefId::from_def_id(closure_def_id), + closure_expr_id: closure_def_id.expect_local(), }; let var_ty = cx.tables().node_type(var_hir_id); @@ -831,7 +804,7 @@ fn convert_var<'tcx>( let region = cx.tcx.mk_region(region); let self_expr = if let ty::Closure(_, closure_substs) = closure_ty.kind { - match cx.infcx.closure_kind(closure_def_id, closure_substs).unwrap() { + match cx.infcx.closure_kind(closure_substs).unwrap() { ty::ClosureKind::Fn => { let ref_closure_ty = cx.tcx.mk_ref( region, @@ -987,7 +960,7 @@ fn capture_upvar<'tcx>( ) -> ExprRef<'tcx> { let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { hir_id: var_hir_id }, - closure_expr_id: cx.tcx.hir().local_def_id(closure_expr.hir_id).to_local(), + closure_expr_id: cx.tcx.hir().local_def_id(closure_expr.hir_id).expect_local(), }; let upvar_capture = cx.tables().upvar_capture(upvar_id); let temp_lifetime = cx.region_scope_tree.temporary_scope(closure_expr.hir_id.local_id); diff --git a/src/librustc_mir_build/hair/cx/mod.rs b/src/librustc_mir_build/hair/cx/mod.rs index 449e2e7494697..99caa6a0f95b4 100644 --- a/src/librustc_mir_build/hair/cx/mod.rs +++ b/src/librustc_mir_build/hair/cx/mod.rs @@ -19,6 +19,7 @@ use rustc_hir::Node; use rustc_index::vec::Idx; use rustc_infer::infer::InferCtxt; use rustc_span::symbol::{sym, Symbol}; +use rustc_trait_selection::infer::InferCtxtExt; #[derive(Clone)] crate struct Cx<'a, 'tcx> { diff --git a/src/librustc_mir_build/hair/mod.rs b/src/librustc_mir_build/hair/mod.rs index cb93ba7c9250f..77042240acf32 100644 --- a/src/librustc_mir_build/hair/mod.rs +++ b/src/librustc_mir_build/hair/mod.rs @@ -229,7 +229,7 @@ crate enum ExprKind<'tcx> { }, Repeat { value: ExprRef<'tcx>, - count: u64, + count: &'tcx Const<'tcx>, }, Array { fields: Vec>, diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index 37ad5f5ea4e38..76fcbf326fa78 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -235,17 +235,15 @@ use rustc_index::vec::Idx; use super::{compare_const_vals, PatternFoldable, PatternFolder}; use super::{FieldPat, Pat, PatKind, PatRange}; -use rustc::ty::layout::{Integer, IntegerExt, Size, VariantIdx}; -use rustc::ty::{self, Const, Ty, TyCtxt, TypeFoldable, VariantDef}; -use rustc_hir::def_id::DefId; -use rustc_hir::{HirId, RangeEnd}; - -use rustc::lint; use rustc::mir::interpret::{truncate, AllocId, ConstValue, Pointer, Scalar}; use rustc::mir::Field; +use rustc::ty::layout::{Integer, IntegerExt, Size, VariantIdx}; +use rustc::ty::{self, Const, Ty, TyCtxt, TypeFoldable, VariantDef}; use rustc::util::common::ErrorReported; - use rustc_attr::{SignedInt, UnsignedInt}; +use rustc_hir::def_id::DefId; +use rustc_hir::{HirId, RangeEnd}; +use rustc_session::lint; use rustc_span::{Span, DUMMY_SP}; use arena::TypedArena; @@ -598,7 +596,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool { if self.tcx.features().exhaustive_patterns { - self.tcx.is_ty_uninhabited_from(self.module, ty) + self.tcx.is_ty_uninhabited_from(self.module, ty, self.param_env) } else { false } @@ -1267,7 +1265,7 @@ fn all_constructors<'a, 'tcx>( def.variants .iter() .filter(|v| { - !v.uninhabited_from(cx.tcx, substs, def.adt_kind()) + !v.uninhabited_from(cx.tcx, substs, def.adt_kind(), cx.param_env) .contains(cx.tcx, cx.module) }) .map(|v| Variant(v.def_id)) @@ -1922,8 +1920,8 @@ fn slice_pat_covered_by_const<'tcx>( } (ConstValue::Slice { data, start, end }, ty::Slice(t)) => { assert_eq!(*t, tcx.types.u8); - let ptr = Pointer::new(AllocId(0), Size::from_bytes(start as u64)); - data.get_bytes(&tcx, ptr, Size::from_bytes((end - start) as u64)).unwrap() + let ptr = Pointer::new(AllocId(0), Size::from_bytes(start)); + data.get_bytes(&tcx, ptr, Size::from_bytes(end - start)).unwrap() } // FIXME(oli-obk): create a way to extract fat pointers from ByRef (_, ty::Slice(_)) => return Ok(false), @@ -2068,7 +2066,7 @@ fn split_grouped_constructors<'p, 'tcx>( } intersection }) - .flat_map(|range| range_borders(range)); + .flat_map(range_borders); let ctor_borders = range_borders(ctor_range.clone()); let mut borders: Vec<_> = row_borders.chain(ctor_borders).collect(); borders.sort_unstable(); @@ -2377,7 +2375,7 @@ fn specialize_one_pattern<'p, 'tcx>( ty::Slice(t) => { match value.val { ty::ConstKind::Value(ConstValue::Slice { data, start, end }) => { - let offset = Size::from_bytes(start as u64); + let offset = Size::from_bytes(start); let n = (end - start) as u64; (Cow::Borrowed(data), offset, n, t) } diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs index d0eefb2e4d14f..9c86669cf9d92 100644 --- a/src/librustc_mir_build/hair/pattern/check_match.rs +++ b/src/librustc_mir_build/hair/pattern/check_match.rs @@ -4,7 +4,6 @@ use super::_match::{expand_pattern, is_useful, MatchCheckCtxt, Matrix, PatStack} use super::{PatCtxt, PatKind, PatternError}; -use rustc::hir::map::Map; use rustc::ty::{self, Ty, TyCtxt}; use rustc_ast::ast::Mutability; use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder}; @@ -43,9 +42,9 @@ struct MatchVisitor<'a, 'tcx> { } impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } @@ -87,6 +86,9 @@ impl PatCtxt<'_, '_> { PatternError::AssocConstInPattern(span) => { self.span_e0158(span, "associated consts cannot be referenced in patterns") } + PatternError::ConstParamInPattern(span) => { + self.span_e0158(span, "const parameters cannot be referenced in patterns") + } PatternError::FloatBug => { // FIXME(#31407) this is only necessary because float parsing is buggy ::rustc::mir::interpret::struct_error( @@ -143,7 +145,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { fn check_in_cx(&self, hir_id: HirId, f: impl FnOnce(MatchCheckCtxt<'_, 'tcx>)) { let module = self.tcx.parent_module(hir_id); - MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module, |cx| f(cx)); + MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module.to_def_id(), |cx| f(cx)); } fn check_match( @@ -750,9 +752,9 @@ fn check_legality_of_bindings_in_at_patterns(cx: &MatchVisitor<'_, '_>, pat: &Pa } impl<'v> Visitor<'v> for AtBindingPatternVisitor<'_, '_, '_> { - type Map = Map<'v>; + type Map = intravisit::ErasedMap<'v>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } diff --git a/src/librustc_mir_build/hair/pattern/const_to_pat.rs b/src/librustc_mir_build/hair/pattern/const_to_pat.rs index 27d1bce76edc5..ae951e810e32e 100644 --- a/src/librustc_mir_build/hair/pattern/const_to_pat.rs +++ b/src/librustc_mir_build/hair/pattern/const_to_pat.rs @@ -1,14 +1,13 @@ -use rustc::lint; use rustc::mir::Field; use rustc::ty::{self, Ty, TyCtxt}; use rustc_hir as hir; -use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; -use rustc_infer::traits::predicate_for_trait_def; -use rustc_infer::traits::{self, ObligationCause, PredicateObligation}; - use rustc_index::vec::Idx; - +use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_session::lint; use rustc_span::Span; +use rustc_trait_selection::traits::predicate_for_trait_def; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; +use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligation}; use std::cell::Cell; @@ -181,7 +180,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { let kind = match cv.ty.kind { ty::Float(_) => { tcx.struct_span_lint_hir( - ::rustc::lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, + lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, id, span, |lint| lint.build("floating-point types cannot be used in patterns").emit(), diff --git a/src/librustc_mir_build/hair/pattern/mod.rs b/src/librustc_mir_build/hair/pattern/mod.rs index f58216fbb4e76..6786c35629308 100644 --- a/src/librustc_mir_build/hair/pattern/mod.rs +++ b/src/librustc_mir_build/hair/pattern/mod.rs @@ -31,6 +31,7 @@ use std::fmt; #[derive(Clone, Debug)] crate enum PatternError { AssocConstInPattern(Span), + ConstParamInPattern(Span), StaticInPattern(Span), FloatBug, NonConstPath(Span), @@ -727,7 +728,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { | Res::SelfCtor(..) => PatKind::Leaf { subpatterns }, _ => { - self.errors.push(PatternError::NonConstPath(span)); + let pattern_error = match res { + Res::Def(DefKind::ConstParam, _) => PatternError::ConstParamInPattern(span), + _ => PatternError::NonConstPath(span), + }; + self.errors.push(pattern_error); PatKind::Wild } }; diff --git a/src/librustc_mir_build/lib.rs b/src/librustc_mir_build/lib.rs index 3c35827d15d3e..5a8b5a329634d 100644 --- a/src/librustc_mir_build/lib.rs +++ b/src/librustc_mir_build/lib.rs @@ -4,6 +4,9 @@ #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(const_if_match)] +#![feature(const_fn)] +#![feature(const_panic)] #![feature(crate_visibility_modifier)] #![feature(bool_to_option)] #![recursion_limit = "256"] diff --git a/src/librustc_mir_build/lints.rs b/src/librustc_mir_build/lints.rs index 0017f800de702..3f92742261636 100644 --- a/src/librustc_mir_build/lints.rs +++ b/src/librustc_mir_build/lints.rs @@ -1,11 +1,11 @@ use rustc::hir::map::blocks::FnLikeNode; -use rustc::lint::builtin::UNCONDITIONAL_RECURSION; use rustc::mir::{self, Body, TerminatorKind}; use rustc::ty::subst::InternalSubsts; use rustc::ty::{self, AssocItem, AssocItemContainer, Instance, TyCtxt}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::FnKind; use rustc_index::bit_set::BitSet; +use rustc_session::lint::builtin::UNCONDITIONAL_RECURSION; crate fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId) { let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); @@ -123,7 +123,7 @@ fn check_fn_for_unconditional_recursion<'tcx>( // recurs. if !reached_exit_without_self_call && !self_call_locations.is_empty() { let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); - let sp = tcx.sess.source_map().def_span(tcx.hir().span(hir_id)); + let sp = tcx.sess.source_map().guess_head_span(tcx.hir().span(hir_id)); tcx.struct_span_lint_hir(UNCONDITIONAL_RECURSION, hir_id, sp, |lint| { let mut db = lint.build("function cannot return without recursing"); db.span_label(sp, "cannot return without recursing"); diff --git a/src/librustc_parse/lexer/mod.rs b/src/librustc_parse/lexer/mod.rs index f7fb704fcbc2c..ac58cbb9e8dae 100644 --- a/src/librustc_parse/lexer/mod.rs +++ b/src/librustc_parse/lexer/mod.rs @@ -46,12 +46,20 @@ impl<'a> StringReader<'a> { source_file: Lrc, override_span: Option, ) -> Self { - if source_file.src.is_none() { + // Make sure external source is loaded first, before accessing it. + // While this can't show up during normal parsing, `retokenize` may + // be called with a source file from an external crate. + sess.source_map().ensure_source_file_source_present(source_file.clone()); + + // FIXME(eddyb) use `Lrc` or similar to avoid cloning the `String`. + let src = if let Some(src) = &source_file.src { + src.clone() + } else if let Some(src) = source_file.external_src.borrow().get_source() { + src.clone() + } else { sess.span_diagnostic .bug(&format!("cannot lex `source_file` without source: {}", source_file.name)); - } - - let src = (*source_file.src.as_ref().unwrap()).clone(); + }; StringReader { sess, @@ -179,14 +187,12 @@ impl<'a> StringReader<'a> { rustc_lexer::TokenKind::LineComment => { let string = self.str_from(start); // comments with only more "/"s are not doc comments - let tok = if comments::is_line_doc_comment(string) { + if comments::is_line_doc_comment(string) { self.forbid_bare_cr(start, string, "bare CR not allowed in doc-comment"); token::DocComment(Symbol::intern(string)) } else { token::Comment - }; - - tok + } } rustc_lexer::TokenKind::BlockComment { terminated } => { let string = self.str_from(start); @@ -204,14 +210,12 @@ impl<'a> StringReader<'a> { self.fatal_span_(start, last_bpos, msg).raise(); } - let tok = if is_doc_comment { + if is_doc_comment { self.forbid_bare_cr(start, string, "bare CR not allowed in block doc-comment"); token::DocComment(Symbol::intern(string)) } else { token::Comment - }; - - tok + } } rustc_lexer::TokenKind::Whitespace => token::Whitespace, rustc_lexer::TokenKind::Ident | rustc_lexer::TokenKind::RawIdent => { diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs index fe75062ee503c..13fb85db84779 100644 --- a/src/librustc_parse/lib.rs +++ b/src/librustc_parse/lib.rs @@ -3,6 +3,7 @@ #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] #![feature(bindings_after_at)] +#![feature(try_blocks)] use rustc_ast::ast; use rustc_ast::token::{self, Nonterminal}; @@ -13,7 +14,7 @@ use rustc_errors::{Diagnostic, FatalError, Level, PResult}; use rustc_session::parse::ParseSess; use rustc_span::{FileName, SourceFile, Span}; -use std::path::{Path, PathBuf}; +use std::path::Path; use std::str; use log::info; @@ -25,24 +26,6 @@ pub mod parser; use parser::{emit_unclosed_delims, make_unclosed_delims_error, Parser}; pub mod lexer; pub mod validate_attr; -#[macro_use] -pub mod config; - -#[derive(Clone)] -pub struct Directory { - pub path: PathBuf, - pub ownership: DirectoryOwnership, -} - -#[derive(Copy, Clone)] -pub enum DirectoryOwnership { - Owned { - // None if `mod.rs`, `Some("foo")` if we're in `foo.rs`. - relative: Option, - }, - UnownedViaBlock, - UnownedViaMod, -} // A bunch of utility functions of the form `parse__from_` // where includes crate, expr, item, stmt, tts, and one that @@ -67,7 +50,7 @@ macro_rules! panictry_buffer { } pub fn parse_crate_from_file<'a>(input: &Path, sess: &'a ParseSess) -> PResult<'a, ast::Crate> { - let mut parser = new_parser_from_file(sess, input); + let mut parser = new_parser_from_file(sess, input, None); parser.parse_crate_mod() } @@ -75,7 +58,7 @@ pub fn parse_crate_attrs_from_file<'a>( input: &Path, sess: &'a ParseSess, ) -> PResult<'a, Vec> { - let mut parser = new_parser_from_file(sess, input); + let mut parser = new_parser_from_file(sess, input, None); parser.parse_inner_attributes() } @@ -119,15 +102,13 @@ pub fn maybe_new_parser_from_source_str( name: FileName, source: String, ) -> Result, Vec> { - let mut parser = - maybe_source_file_to_parser(sess, sess.source_map().new_source_file(name, source))?; - parser.recurse_into_file_modules = false; - Ok(parser) + maybe_source_file_to_parser(sess, sess.source_map().new_source_file(name, source)) } /// Creates a new parser, handling errors as appropriate if the file doesn't exist. -pub fn new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path) -> Parser<'a> { - source_file_to_parser(sess, file_to_source_file(sess, path, None)) +/// If a span is given, that is used on an error as the as the source of the problem. +pub fn new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path, sp: Option) -> Parser<'a> { + source_file_to_parser(sess, file_to_source_file(sess, path, sp)) } /// Creates a new parser, returning buffered diagnostics if the file doesn't exist, @@ -140,22 +121,6 @@ pub fn maybe_new_parser_from_file<'a>( maybe_source_file_to_parser(sess, file) } -/// Given a session, a crate config, a path, and a span, add -/// the file at the given path to the `source_map`, and returns a parser. -/// On an error, uses the given span as the source of the problem. -pub fn new_sub_parser_from_file<'a>( - sess: &'a ParseSess, - path: &Path, - directory_ownership: DirectoryOwnership, - module_name: Option, - sp: Span, -) -> Parser<'a> { - let mut p = source_file_to_parser(sess, file_to_source_file(sess, path, Some(sp))); - p.directory.ownership = directory_ownership; - p.root_module_name = module_name; - p -} - /// Given a `source_file` and config, returns a parser. fn source_file_to_parser(sess: &ParseSess, source_file: Lrc) -> Parser<'_> { panictry_buffer!(&sess.span_diagnostic, maybe_source_file_to_parser(sess, source_file)) @@ -257,26 +222,7 @@ pub fn stream_to_parser<'a>( stream: TokenStream, subparser_name: Option<&'static str>, ) -> Parser<'a> { - Parser::new(sess, stream, None, true, false, subparser_name) -} - -/// Given a stream, the `ParseSess` and the base directory, produces a parser. -/// -/// Use this function when you are creating a parser from the token stream -/// and also care about the current working directory of the parser (e.g., -/// you are trying to resolve modules defined inside a macro invocation). -/// -/// # Note -/// -/// The main usage of this function is outside of rustc, for those who uses -/// librustc_ast as a library. Please do not remove this function while refactoring -/// just because it is not used in rustc codebase! -pub fn stream_to_parser_with_base_dir<'a>( - sess: &'a ParseSess, - stream: TokenStream, - base_dir: Directory, -) -> Parser<'a> { - Parser::new(sess, stream, Some(base_dir), true, false, None) + Parser::new(sess, stream, false, subparser_name) } /// Runs the given subparser `f` on the tokens of the given `attr`'s item. @@ -286,7 +232,7 @@ pub fn parse_in<'a, T>( name: &'static str, mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, ) -> PResult<'a, T> { - let mut parser = Parser::new(sess, tts, None, false, false, Some(name)); + let mut parser = Parser::new(sess, tts, false, Some(name)); let result = f(&mut parser)?; if parser.token != token::Eof { parser.unexpected()?; @@ -361,7 +307,7 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke going with stringified version" ); } - return tokens_for_real; + tokens_for_real } fn prepend_attrs( diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index 7c1df531ad16e..c4546dedfcdd4 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -17,7 +17,6 @@ use rustc_span::symbol::kw; use rustc_span::{MultiSpan, Span, SpanSnippetError, DUMMY_SP}; use log::{debug, trace}; -use std::mem; const TURBOFISH: &str = "use `::<...>` instead of `<...>` to specify type arguments"; @@ -40,55 +39,12 @@ pub(super) fn dummy_arg(ident: Ident) -> Param { } pub enum Error { - FileNotFoundForModule { - mod_name: String, - default_path: String, - secondary_path: String, - dir_path: String, - }, - DuplicatePaths { - mod_name: String, - default_path: String, - secondary_path: String, - }, UselessDocComment, } impl Error { fn span_err(self, sp: impl Into, handler: &Handler) -> DiagnosticBuilder<'_> { match self { - Error::FileNotFoundForModule { - ref mod_name, - ref default_path, - ref secondary_path, - ref dir_path, - } => { - let mut err = struct_span_err!( - handler, - sp, - E0583, - "file not found for module `{}`", - mod_name, - ); - err.help(&format!( - "name the file either {} or {} inside the directory \"{}\"", - default_path, secondary_path, dir_path, - )); - err - } - Error::DuplicatePaths { ref mod_name, ref default_path, ref secondary_path } => { - let mut err = struct_span_err!( - handler, - sp, - E0584, - "file for module `{}` found at both {} and {}", - mod_name, - default_path, - secondary_path, - ); - err.help("delete or rename one of them to remove the ambiguity"); - err - } Error::UselessDocComment => { let mut err = struct_span_err!( handler, @@ -502,9 +458,28 @@ impl<'a> Parser<'a> { err: &mut DiagnosticBuilder<'_>, inner_op: &Expr, outer_op: &Spanned, - ) { + ) -> bool /* advanced the cursor */ { if let ExprKind::Binary(op, ref l1, ref r1) = inner_op.kind { - match (op.node, &outer_op.node) { + if let ExprKind::Field(_, ident) = l1.kind { + if ident.as_str().parse::().is_err() && !matches!(r1.kind, ExprKind::Lit(_)) { + // The parser has encountered `foo.bar Parser<'a> { self.span_to_snippet(e.span) .unwrap_or_else(|_| pprust::expr_to_string(&e)) }; - err.span_suggestion( - inner_op.span.to(outer_op.span), - "split the comparison into two...", - format!( - "{} {} {} && {} {}", - expr_to_str(&l1), - op.node.to_string(), - expr_to_str(&r1), - expr_to_str(&r1), - outer_op.node.to_ast_binop().unwrap().to_string(), - ), - Applicability::MaybeIncorrect, - ); - err.span_suggestion( - inner_op.span.to(outer_op.span), - "...or parenthesize one of the comparisons", - format!( - "({} {} {}) {}", - expr_to_str(&l1), - op.node.to_string(), - expr_to_str(&r1), - outer_op.node.to_ast_binop().unwrap().to_string(), - ), + err.span_suggestion_verbose( + inner_op.span.shrink_to_hi(), + "split the comparison into two", + format!(" && {}", expr_to_str(&r1)), Applicability::MaybeIncorrect, ); + false // Keep the current parse behavior, where the AST is `(x < y) < z`. } - _ => {} - } + // `x == y < z` + (BinOpKind::Eq, AssocOp::Less) | (BinOpKind::Eq, AssocOp::LessEqual) | + (BinOpKind::Eq, AssocOp::Greater) | (BinOpKind::Eq, AssocOp::GreaterEqual) => { + // Consume `z`/outer-op-rhs. + let snapshot = self.clone(); + match self.parse_expr() { + Ok(r2) => { + // We are sure that outer-op-rhs could be consumed, the suggestion is + // likely correct. + enclose(r1.span, r2.span); + true + } + Err(mut expr_err) => { + expr_err.cancel(); + *self = snapshot; + false + } + } + } + // `x > y == z` + (BinOpKind::Lt, AssocOp::Equal) | (BinOpKind::Le, AssocOp::Equal) | + (BinOpKind::Gt, AssocOp::Equal) | (BinOpKind::Ge, AssocOp::Equal) => { + let snapshot = self.clone(); + // At this point it is always valid to enclose the lhs in parentheses, no + // further checks are necessary. + match self.parse_expr() { + Ok(_) => { + enclose(l1.span, r1.span); + true + } + Err(mut expr_err) => { + expr_err.cancel(); + *self = snapshot; + false + } + } + } + _ => false, + }; } + false } /// Produces an error if comparison operators are chained (RFC #558). @@ -577,31 +572,26 @@ impl<'a> Parser<'a> { |this: &Self, span| Ok(Some(this.mk_expr(span, ExprKind::Err, AttrVec::new()))); match inner_op.kind { - ExprKind::Binary(op, _, _) if op.node.is_comparison() => { - // Respan to include both operators. - let op_span = op.span.to(self.prev_token.span); - let mut err = - self.struct_span_err(op_span, "comparison operators cannot be chained"); - - // If it looks like a genuine attempt to chain operators (as opposed to a - // misformatted turbofish, for instance), suggest a correct form. - self.attempt_chained_comparison_suggestion(&mut err, inner_op, outer_op); + ExprKind::Binary(op, ref l1, ref r1) if op.node.is_comparison() => { + let mut err = self.struct_span_err( + vec![op.span, self.prev_token.span], + "comparison operators cannot be chained", + ); let suggest = |err: &mut DiagnosticBuilder<'_>| { err.span_suggestion_verbose( - op_span.shrink_to_lo(), + op.span.shrink_to_lo(), TURBOFISH, "::".to_string(), Applicability::MaybeIncorrect, ); }; - if op.node == BinOpKind::Lt && - outer_op.node == AssocOp::Less || // Include `<` to provide this recommendation - outer_op.node == AssocOp::Greater - // even in a case like the following: + // Include `<` to provide this recommendation even in a case like + // `Foo>>` + if op.node == BinOpKind::Lt && outer_op.node == AssocOp::Less + || outer_op.node == AssocOp::Greater { - // Foo>> if outer_op.node == AssocOp::Less { let snapshot = self.clone(); self.bump(); @@ -615,7 +605,7 @@ impl<'a> Parser<'a> { { // We don't have `foo< bar >(` or `foo< bar >::`, so we rewind the // parser and bail out. - mem::replace(self, snapshot.clone()); + *self = snapshot.clone(); } } return if token::ModSep == self.token.kind { @@ -640,7 +630,7 @@ impl<'a> Parser<'a> { expr_err.cancel(); // Not entirely sure now, but we bubble the error up with the // suggestion. - mem::replace(self, snapshot); + *self = snapshot; Err(err) } } @@ -660,15 +650,33 @@ impl<'a> Parser<'a> { } } } else { - // All we know is that this is `foo < bar >` and *nothing* else. Try to - // be helpful, but don't attempt to recover. - err.help(TURBOFISH); - err.help("or use `(...)` if you meant to specify fn arguments"); - // These cases cause too many knock-down errors, bail out (#61329). - Err(err) + if !matches!(l1.kind, ExprKind::Lit(_)) + && !matches!(r1.kind, ExprKind::Lit(_)) + { + // All we know is that this is `foo < bar >` and *nothing* else. Try to + // be helpful, but don't attempt to recover. + err.help(TURBOFISH); + err.help("or use `(...)` if you meant to specify fn arguments"); + } + + // If it looks like a genuine attempt to chain operators (as opposed to a + // misformatted turbofish, for instance), suggest a correct form. + if self.attempt_chained_comparison_suggestion(&mut err, inner_op, outer_op) + { + err.emit(); + mk_err_expr(self, inner_op.span.to(self.prev_token.span)) + } else { + // These cases cause too many knock-down errors, bail out (#61329). + Err(err) + } }; } + let recover = + self.attempt_chained_comparison_suggestion(&mut err, inner_op, outer_op); err.emit(); + if recover { + return mk_err_expr(self, inner_op.span.to(self.prev_token.span)); + } } _ => {} } @@ -686,7 +694,7 @@ impl<'a> Parser<'a> { if self.token.kind == token::Eof { // Not entirely sure that what we consumed were fn arguments, rollback. - mem::replace(self, snapshot); + *self = snapshot; Err(()) } else { // 99% certain that the suggestion is correct, continue parsing. diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 7f6f90431fc94..b205a4b322229 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -4,8 +4,8 @@ use super::{BlockMode, Parser, PathStyle, Restrictions, TokenType}; use super::{SemiColonMode, SeqSep, TokenExpectType}; use crate::maybe_recover_from_interpolated_ty_qpath; -use rustc_ast::ast::{self, AttrStyle, AttrVec, CaptureBy, Field, Ident, Lit, DUMMY_NODE_ID}; -use rustc_ast::ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, Mac, Param, Ty, TyKind, UnOp}; +use rustc_ast::ast::{self, AttrStyle, AttrVec, CaptureBy, Field, Ident, Lit, UnOp, DUMMY_NODE_ID}; +use rustc_ast::ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty, TyKind}; use rustc_ast::ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits}; use rustc_ast::ptr::P; use rustc_ast::token::{self, Token, TokenKind}; @@ -925,8 +925,17 @@ impl<'a> Parser<'a> { self.parse_closure_expr(attrs) } else if self.eat_keyword(kw::If) { self.parse_if_expr(attrs) - } else if self.eat_keyword(kw::For) { - self.parse_for_expr(None, self.prev_token.span, attrs) + } else if self.check_keyword(kw::For) { + if self.choose_generics_over_qpath(1) { + // NOTE(Centril, eddyb): DO NOT REMOVE! Beyond providing parser recovery, + // this is an insurance policy in case we allow qpaths in (tuple-)struct patterns. + // When `for ::Proj in $expr $block` is wanted, + // you can disambiguate in favor of a pattern with `(...)`. + self.recover_quantified_closure_expr(attrs) + } else { + assert!(self.eat_keyword(kw::For)); + self.parse_for_expr(None, self.prev_token.span, attrs) + } } else if self.eat_keyword(kw::While) { self.parse_while_expr(None, self.prev_token.span, attrs) } else if let Some(label) = self.eat_label() { @@ -996,7 +1005,7 @@ impl<'a> Parser<'a> { let expr = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Lit(literal), attrs); self.maybe_recover_from_bad_qpath(expr, true) } - None => return Err(self.expected_expression_found()), + None => Err(self.expected_expression_found()), } } @@ -1065,12 +1074,12 @@ impl<'a> Parser<'a> { // `!`, as an operator, is prefix, so we know this isn't that. let (hi, kind) = if self.eat(&token::Not) { // MACRO INVOCATION expression - let mac = Mac { + let mac = MacCall { path, args: self.parse_mac_args()?, prior_type_ascription: self.last_type_ascription, }; - (self.prev_token.span, ExprKind::Mac(mac)) + (self.prev_token.span, ExprKind::MacCall(mac)) } else if self.check(&token::OpenDelim(token::Brace)) { if let Some(expr) = self.maybe_parse_struct_expr(lo, &path, &attrs) { return expr; @@ -1374,6 +1383,7 @@ impl<'a> Parser<'a> { } /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`). + /// Keep this in sync with `Token::can_begin_literal_maybe_minus`. pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P> { maybe_whole_expr!(self); @@ -1416,6 +1426,26 @@ impl<'a> Parser<'a> { Ok(self.mk_expr(blk.span, ExprKind::Block(blk, opt_label), attrs)) } + /// Recover on an explicitly quantified closure expression, e.g., `for<'a> |x: &'a u8| *x + 1`. + fn recover_quantified_closure_expr(&mut self, attrs: AttrVec) -> PResult<'a, P> { + let lo = self.token.span; + let _ = self.parse_late_bound_lifetime_defs()?; + let span_for = lo.to(self.prev_token.span); + let closure = self.parse_closure_expr(attrs)?; + + self.struct_span_err(span_for, "cannot introduce explicit parameters for a closure") + .span_label(closure.span, "the parameters are attached to this closure") + .span_suggestion( + span_for, + "remove the parameters", + String::new(), + Applicability::MachineApplicable, + ) + .emit(); + + Ok(self.mk_expr_err(lo.to(closure.span))) + } + /// Parses a closure expression (e.g., `move |args| expr`). fn parse_closure_expr(&mut self, attrs: AttrVec) -> PResult<'a, P> { let lo = self.token.span; @@ -1713,7 +1743,7 @@ impl<'a> Parser<'a> { } let hi = self.token.span; self.bump(); - return Ok(self.mk_expr(lo.to(hi), ExprKind::Match(scrutinee, arms), attrs)); + Ok(self.mk_expr(lo.to(hi), ExprKind::Match(scrutinee, arms), attrs)) } pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> { diff --git a/src/librustc_parse/parser/generics.rs b/src/librustc_parse/parser/generics.rs index 59fd5f7c4be1f..3442c5081c18f 100644 --- a/src/librustc_parse/parser/generics.rs +++ b/src/librustc_parse/parser/generics.rs @@ -181,7 +181,7 @@ impl<'a> Parser<'a> { // We are considering adding generics to the `where` keyword as an alternative higher-rank // parameter syntax (as in `where<'a>` or `where`. To avoid that being a breaking // change we parse those generics now, but report an error. - if self.choose_generics_over_qpath() { + if self.choose_generics_over_qpath(0) { let generics = self.parse_generics()?; self.struct_span_err( generics.span, @@ -257,7 +257,7 @@ impl<'a> Parser<'a> { } } - pub(super) fn choose_generics_over_qpath(&self) -> bool { + pub(super) fn choose_generics_over_qpath(&self, start: usize) -> bool { // There's an ambiguity between generic parameters and qualified paths in impls. // If we see `<` it may start both, so we have to inspect some following tokens. // The following combinations can only start generics, @@ -274,15 +274,12 @@ impl<'a> Parser<'a> { // we disambiguate it in favor of generics (`impl ::absolute::Path { ... }`) // because this is what almost always expected in practice, qualified paths in impls // (`impl ::AssocTy { ... }`) aren't even allowed by type checker at the moment. - self.token == token::Lt - && (self.look_ahead(1, |t| t == &token::Pound || t == &token::Gt) - || self.look_ahead(1, |t| t.is_lifetime() || t.is_ident()) - && self.look_ahead(2, |t| { - t == &token::Gt - || t == &token::Comma - || t == &token::Colon - || t == &token::Eq + self.look_ahead(start, |t| t == &token::Lt) + && (self.look_ahead(start + 1, |t| t == &token::Pound || t == &token::Gt) + || self.look_ahead(start + 1, |t| t.is_lifetime() || t.is_ident()) + && self.look_ahead(start + 2, |t| { + matches!(t.kind, token::Gt | token::Comma | token::Colon | token::Eq) }) - || self.is_keyword_ahead(1, &[kw::Const])) + || self.is_keyword_ahead(start + 1, &[kw::Const])) } } diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 513507f9bb833..cc88464d774e8 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -5,17 +5,14 @@ use super::{FollowedByType, Parser, PathStyle}; use crate::maybe_whole; use rustc_ast::ast::{self, AttrStyle, AttrVec, Attribute, Ident, DUMMY_NODE_ID}; -use rustc_ast::ast::{AssocItem, AssocItemKind, ForeignItemKind, Item, ItemKind}; -use rustc_ast::ast::{ - Async, Const, Defaultness, IsAuto, PathSegment, Unsafe, UseTree, UseTreeKind, -}; -use rustc_ast::ast::{ - BindingMode, Block, FnDecl, FnSig, Mac, MacArgs, MacDelimiter, Param, SelfKind, -}; +use rustc_ast::ast::{AssocItem, AssocItemKind, ForeignItemKind, Item, ItemKind, Mod}; +use rustc_ast::ast::{Async, Const, Defaultness, IsAuto, Mutability, Unsafe, UseTree, UseTreeKind}; +use rustc_ast::ast::{BindingMode, Block, FnDecl, FnSig, Param, SelfKind}; use rustc_ast::ast::{EnumDef, Generics, StructField, TraitRef, Ty, TyKind, Variant, VariantData}; -use rustc_ast::ast::{FnHeader, ForeignItem, Mutability, Visibility, VisibilityKind}; +use rustc_ast::ast::{FnHeader, ForeignItem, PathSegment, Visibility, VisibilityKind}; +use rustc_ast::ast::{MacArgs, MacCall, MacDelimiter}; use rustc_ast::ptr::P; -use rustc_ast::token; +use rustc_ast::token::{self, TokenKind}; use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; use rustc_ast_pretty::pprust; use rustc_errors::{struct_span_err, Applicability, PResult, StashKey}; @@ -27,6 +24,61 @@ use log::debug; use std::convert::TryFrom; use std::mem; +impl<'a> Parser<'a> { + /// Parses a source module as a crate. This is the main entry point for the parser. + pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> { + let lo = self.token.span; + let (module, attrs) = self.parse_mod(&token::Eof)?; + let span = lo.to(self.token.span); + let proc_macros = Vec::new(); // Filled in by `proc_macro_harness::inject()`. + Ok(ast::Crate { attrs, module, span, proc_macros }) + } + + /// Parses a `mod { ... }` or `mod ;` item. + fn parse_item_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { + let id = self.parse_ident()?; + let (module, mut inner_attrs) = if self.eat(&token::Semi) { + Default::default() + } else { + self.expect(&token::OpenDelim(token::Brace))?; + self.parse_mod(&token::CloseDelim(token::Brace))? + }; + attrs.append(&mut inner_attrs); + Ok((id, ItemKind::Mod(module))) + } + + /// Parses the contents of a module (inner attributes followed by module items). + pub fn parse_mod(&mut self, term: &TokenKind) -> PResult<'a, (Mod, Vec)> { + let lo = self.token.span; + let attrs = self.parse_inner_attributes()?; + let module = self.parse_mod_items(term, lo)?; + Ok((module, attrs)) + } + + /// Given a termination token, parses all of the items in a module. + fn parse_mod_items(&mut self, term: &TokenKind, inner_lo: Span) -> PResult<'a, Mod> { + let mut items = vec![]; + while let Some(item) = self.parse_item()? { + items.push(item); + self.maybe_consume_incorrect_semicolon(&items); + } + + if !self.eat(term) { + let token_str = super::token_descr(&self.token); + if !self.maybe_consume_incorrect_semicolon(&items) { + let msg = &format!("expected item, found {}", token_str); + let mut err = self.struct_span_err(self.token.span, msg); + err.span_label(self.token.span, "expected item"); + return Err(err); + } + } + + let hi = if self.token.span.is_dummy() { inner_lo } else { self.prev_token.span }; + + Ok(Mod { inner: inner_lo.to(hi), items, inline: true }) + } +} + pub(super) type ItemInfo = (Ident, ItemKind); impl<'a> Parser<'a> { @@ -220,7 +272,7 @@ impl<'a> Parser<'a> { return Ok(None); } else if macros_allowed && self.check_path() { // MACRO INVOCATION ITEM - (Ident::invalid(), ItemKind::Mac(self.parse_item_macro(vis)?)) + (Ident::invalid(), ItemKind::MacCall(self.parse_item_macro(vis)?)) } else { return Ok(None); }; @@ -262,7 +314,7 @@ impl<'a> Parser<'a> { " struct ".into(), Applicability::MaybeIncorrect, // speculative ); - return Err(err); + Err(err) } else if self.look_ahead(1, |t| *t == token::OpenDelim(token::Paren)) { let ident = self.parse_ident().unwrap(); self.bump(); // `(` @@ -310,7 +362,7 @@ impl<'a> Parser<'a> { ); } } - return Err(err); + Err(err) } else if self.look_ahead(1, |t| *t == token::Lt) { let ident = self.parse_ident().unwrap(); self.eat_to_tokens(&[&token::Gt]); @@ -332,20 +384,20 @@ impl<'a> Parser<'a> { Applicability::MachineApplicable, ); } - return Err(err); + Err(err) } else { Ok(()) } } /// Parses an item macro, e.g., `item!();`. - fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, Mac> { + fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> { let path = self.parse_path(PathStyle::Mod)?; // `foo::bar` self.expect(&token::Not)?; // `!` let args = self.parse_mac_args()?; // `( .. )` or `[ .. ]` (followed by `;`), or `{ .. }`. self.eat_semi_for_macro_if_needed(&args); self.complain_if_pub_macro(vis, false); - Ok(Mac { path, args, prior_type_ascription: self.last_type_ascription }) + Ok(MacCall { path, args, prior_type_ascription: self.last_type_ascription }) } /// Recover if we parsed attributes and expected an item but there was none. @@ -406,7 +458,7 @@ impl<'a> Parser<'a> { self.expect_keyword(kw::Impl)?; // First, parse generic parameters if necessary. - let mut generics = if self.choose_generics_over_qpath() { + let mut generics = if self.choose_generics_over_qpath(0) { self.parse_generics()? } else { let mut generics = Generics::default(); @@ -855,10 +907,10 @@ impl<'a> Parser<'a> { } fn error_bad_item_kind(&self, span: Span, kind: &ItemKind, ctx: &str) -> Option { - let span = self.sess.source_map().def_span(span); + let span = self.sess.source_map().guess_head_span(span); let msg = format!("{} is not supported in {}", kind.descr(), ctx); self.struct_span_err(span, &msg).emit(); - return None; + None } fn error_on_foreign_const(&self, span: Span, ident: Ident) { @@ -1264,7 +1316,7 @@ impl<'a> Parser<'a> { }; self.sess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_token.span)); - Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: false }))) + Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, macro_rules: false }))) } /// Is this unambiguously the start of a `macro_rules! foo` item defnition? @@ -1274,7 +1326,7 @@ impl<'a> Parser<'a> { && self.look_ahead(2, |t| t.is_ident()) } - /// Parses a legacy `macro_rules! foo { ... }` declarative macro. + /// Parses a `macro_rules! foo { ... }` declarative macro. fn parse_item_macro_rules(&mut self, vis: &Visibility) -> PResult<'a, ItemInfo> { self.expect_keyword(kw::MacroRules)?; // `macro_rules` self.expect(&token::Not)?; // `!` @@ -1284,7 +1336,7 @@ impl<'a> Parser<'a> { self.eat_semi_for_macro_if_needed(&body); self.complain_if_pub_macro(vis, true); - Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: true }))) + Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, macro_rules: true }))) } /// Item macro invocations or `macro_rules!` definitions need inherited visibility. @@ -1457,7 +1509,7 @@ impl<'a> Parser<'a> { }) // `extern ABI fn` || self.check_keyword(kw::Extern) - && self.look_ahead(1, |t| t.can_begin_literal_or_bool()) + && self.look_ahead(1, |t| t.can_begin_literal_maybe_minus()) && self.look_ahead(2, |t| t.is_keyword(kw::Fn)) } diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 9376c7c1c724d..b987813e38d98 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -1,8 +1,6 @@ pub mod attr; mod expr; mod item; -mod module; -pub use module::{ModulePath, ModulePathSuccess}; mod pat; mod path; mod ty; @@ -13,7 +11,6 @@ mod stmt; use diagnostics::Error; use crate::lexer::UnmatchedBrace; -use crate::{Directory, DirectoryOwnership}; use log::debug; use rustc_ast::ast::DUMMY_NODE_ID; @@ -28,11 +25,9 @@ use rustc_ast::util::comments::{doc_comment_style, strip_doc_comment_decoration} use rustc_ast_pretty::pprust; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, FatalError, PResult}; use rustc_session::parse::ParseSess; -use rustc_span::source_map::respan; +use rustc_span::source_map::{respan, Span, DUMMY_SP}; use rustc_span::symbol::{kw, sym, Symbol}; -use rustc_span::{FileName, Span, DUMMY_SP}; -use std::path::PathBuf; use std::{cmp, mem, slice}; bitflags::bitflags! { @@ -93,21 +88,9 @@ pub struct Parser<'a> { /// The previous token. pub prev_token: Token, restrictions: Restrictions, - /// Used to determine the path to externally loaded source files. - pub(super) directory: Directory, - /// `true` to parse sub-modules in other files. - // Public for rustfmt usage. - pub recurse_into_file_modules: bool, - /// Name of the root module this parser originated from. If `None`, then the - /// name is not known. This does not change while the parser is descending - /// into modules, and sub-parsers have new values for this name. - pub root_module_name: Option, expected_tokens: Vec, token_cursor: TokenCursor, desugar_doc_comments: bool, - /// `true` we should configure out of line modules as we parse. - // Public for rustfmt usage. - pub cfg_mods: bool, /// This field is used to keep track of how many left angle brackets we have seen. This is /// required in order to detect extra leading left angle brackets (`<` characters) and error /// appropriately. @@ -355,8 +338,6 @@ impl<'a> Parser<'a> { pub fn new( sess: &'a ParseSess, tokens: TokenStream, - directory: Option, - recurse_into_file_modules: bool, desugar_doc_comments: bool, subparser_name: Option<&'static str>, ) -> Self { @@ -365,19 +346,12 @@ impl<'a> Parser<'a> { token: Token::dummy(), prev_token: Token::dummy(), restrictions: Restrictions::empty(), - recurse_into_file_modules, - directory: Directory { - path: PathBuf::new(), - ownership: DirectoryOwnership::Owned { relative: None }, - }, - root_module_name: None, expected_tokens: Vec::new(), token_cursor: TokenCursor { frame: TokenCursorFrame::new(DelimSpan::dummy(), token::NoDelim, &tokens), stack: Vec::new(), }, desugar_doc_comments, - cfg_mods: true, unmatched_angle_bracket_count: 0, max_angle_bracket_count: 0, unclosed_delims: Vec::new(), @@ -389,18 +363,6 @@ impl<'a> Parser<'a> { // Make parser point to the first token. parser.bump(); - if let Some(directory) = directory { - parser.directory = directory; - } else if !parser.token.span.is_dummy() { - if let Some(FileName::Real(path)) = - &sess.source_map().lookup_char_pos(parser.token.span.lo()).file.unmapped_path - { - if let Some(directory_path) = path.parent() { - parser.directory.path = directory_path.to_path_buf(); - } - } - } - parser } diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs deleted file mode 100644 index b436f1969bb48..0000000000000 --- a/src/librustc_parse/parser/module.rs +++ /dev/null @@ -1,306 +0,0 @@ -use super::diagnostics::Error; -use super::item::ItemInfo; -use super::Parser; - -use crate::{new_sub_parser_from_file, DirectoryOwnership}; - -use rustc_ast::ast::{self, Attribute, Crate, Ident, ItemKind, Mod}; -use rustc_ast::attr; -use rustc_ast::token::{self, TokenKind}; -use rustc_errors::PResult; -use rustc_span::source_map::{FileName, SourceMap, Span, DUMMY_SP}; -use rustc_span::symbol::sym; - -use std::path::{self, Path, PathBuf}; - -/// Information about the path to a module. -// Public for rustfmt usage. -pub struct ModulePath { - name: String, - path_exists: bool, - pub result: Result, -} - -// Public for rustfmt usage. -pub struct ModulePathSuccess { - pub path: PathBuf, - pub directory_ownership: DirectoryOwnership, -} - -impl<'a> Parser<'a> { - /// Parses a source module as a crate. This is the main entry point for the parser. - pub fn parse_crate_mod(&mut self) -> PResult<'a, Crate> { - let lo = self.token.span; - let krate = Ok(ast::Crate { - attrs: self.parse_inner_attributes()?, - module: self.parse_mod_items(&token::Eof, lo)?, - span: lo.to(self.token.span), - // Filled in by proc_macro_harness::inject() - proc_macros: Vec::new(), - }); - krate - } - - /// Parses a `mod { ... }` or `mod ;` item. - pub(super) fn parse_item_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { - let in_cfg = crate::config::process_configure_mod(self.sess, self.cfg_mods, attrs); - - let id_span = self.token.span; - let id = self.parse_ident()?; - let (module, mut inner_attrs) = if self.eat(&token::Semi) { - if in_cfg && self.recurse_into_file_modules { - // This mod is in an external file. Let's go get it! - let ModulePathSuccess { path, directory_ownership } = - self.submod_path(id, &attrs, id_span)?; - self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)? - } else { - (ast::Mod { inner: DUMMY_SP, items: Vec::new(), inline: false }, Vec::new()) - } - } else { - let old_directory = self.directory.clone(); - self.push_directory(id, &attrs); - - self.expect(&token::OpenDelim(token::Brace))?; - let mod_inner_lo = self.token.span; - let inner_attrs = self.parse_inner_attributes()?; - let module = self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo)?; - - self.directory = old_directory; - (module, inner_attrs) - }; - attrs.append(&mut inner_attrs); - Ok((id, ItemKind::Mod(module))) - } - - /// Given a termination token, parses all of the items in a module. - fn parse_mod_items(&mut self, term: &TokenKind, inner_lo: Span) -> PResult<'a, Mod> { - let mut items = vec![]; - while let Some(item) = self.parse_item()? { - items.push(item); - self.maybe_consume_incorrect_semicolon(&items); - } - - if !self.eat(term) { - let token_str = super::token_descr(&self.token); - if !self.maybe_consume_incorrect_semicolon(&items) { - let msg = &format!("expected item, found {}", token_str); - let mut err = self.struct_span_err(self.token.span, msg); - err.span_label(self.token.span, "expected item"); - return Err(err); - } - } - - let hi = if self.token.span.is_dummy() { inner_lo } else { self.prev_token.span }; - - Ok(Mod { inner: inner_lo.to(hi), items, inline: true }) - } - - fn submod_path( - &mut self, - id: ast::Ident, - outer_attrs: &[Attribute], - id_sp: Span, - ) -> PResult<'a, ModulePathSuccess> { - if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) { - return Ok(ModulePathSuccess { - directory_ownership: match path.file_name().and_then(|s| s.to_str()) { - // All `#[path]` files are treated as though they are a `mod.rs` file. - // This means that `mod foo;` declarations inside `#[path]`-included - // files are siblings, - // - // Note that this will produce weirdness when a file named `foo.rs` is - // `#[path]` included and contains a `mod foo;` declaration. - // If you encounter this, it's your own darn fault :P - Some(_) => DirectoryOwnership::Owned { relative: None }, - _ => DirectoryOwnership::UnownedViaMod, - }, - path, - }); - } - - let relative = match self.directory.ownership { - DirectoryOwnership::Owned { relative } => relative, - DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod => None, - }; - let paths = - Parser::default_submod_path(id, relative, &self.directory.path, self.sess.source_map()); - - match self.directory.ownership { - DirectoryOwnership::Owned { .. } => { - paths.result.map_err(|err| self.span_fatal_err(id_sp, err)) - } - DirectoryOwnership::UnownedViaBlock => { - let msg = "Cannot declare a non-inline module inside a block \ - unless it has a path attribute"; - let mut err = self.struct_span_err(id_sp, msg); - if paths.path_exists { - let msg = format!( - "Maybe `use` the module `{}` instead of redeclaring it", - paths.name - ); - err.span_note(id_sp, &msg); - } - Err(err) - } - DirectoryOwnership::UnownedViaMod => { - let mut err = - self.struct_span_err(id_sp, "cannot declare a new module at this location"); - if !id_sp.is_dummy() { - let src_path = self.sess.source_map().span_to_filename(id_sp); - if let FileName::Real(src_path) = src_path { - if let Some(stem) = src_path.file_stem() { - let mut dest_path = src_path.clone(); - dest_path.set_file_name(stem); - dest_path.push("mod.rs"); - err.span_note( - id_sp, - &format!( - "maybe move this module `{}` to its own \ - directory via `{}`", - src_path.display(), - dest_path.display() - ), - ); - } - } - } - if paths.path_exists { - err.span_note( - id_sp, - &format!( - "... or maybe `use` the module `{}` instead \ - of possibly redeclaring it", - paths.name - ), - ); - } - Err(err) - } - } - } - - // Public for rustfmt usage. - pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option { - if let Some(s) = attr::first_attr_value_str_by_name(attrs, sym::path) { - let s = s.as_str(); - - // On windows, the base path might have the form - // `\\?\foo\bar` in which case it does not tolerate - // mixed `/` and `\` separators, so canonicalize - // `/` to `\`. - #[cfg(windows)] - let s = s.replace("/", "\\"); - Some(dir_path.join(&*s)) - } else { - None - } - } - - /// Returns a path to a module. - // Public for rustfmt usage. - pub fn default_submod_path( - id: ast::Ident, - relative: Option, - dir_path: &Path, - source_map: &SourceMap, - ) -> ModulePath { - // If we're in a foo.rs file instead of a mod.rs file, - // we need to look for submodules in - // `./foo/.rs` and `./foo//mod.rs` rather than - // `./.rs` and `.//mod.rs`. - let relative_prefix_string; - let relative_prefix = if let Some(ident) = relative { - relative_prefix_string = format!("{}{}", ident.name, path::MAIN_SEPARATOR); - &relative_prefix_string - } else { - "" - }; - - let mod_name = id.name.to_string(); - let default_path_str = format!("{}{}.rs", relative_prefix, mod_name); - let secondary_path_str = - format!("{}{}{}mod.rs", relative_prefix, mod_name, path::MAIN_SEPARATOR); - let default_path = dir_path.join(&default_path_str); - let secondary_path = dir_path.join(&secondary_path_str); - let default_exists = source_map.file_exists(&default_path); - let secondary_exists = source_map.file_exists(&secondary_path); - - let result = match (default_exists, secondary_exists) { - (true, false) => Ok(ModulePathSuccess { - path: default_path, - directory_ownership: DirectoryOwnership::Owned { relative: Some(id) }, - }), - (false, true) => Ok(ModulePathSuccess { - path: secondary_path, - directory_ownership: DirectoryOwnership::Owned { relative: None }, - }), - (false, false) => Err(Error::FileNotFoundForModule { - mod_name: mod_name.clone(), - default_path: default_path_str, - secondary_path: secondary_path_str, - dir_path: dir_path.display().to_string(), - }), - (true, true) => Err(Error::DuplicatePaths { - mod_name: mod_name.clone(), - default_path: default_path_str, - secondary_path: secondary_path_str, - }), - }; - - ModulePath { name: mod_name, path_exists: default_exists || secondary_exists, result } - } - - /// Reads a module from a source file. - fn eval_src_mod( - &mut self, - path: PathBuf, - directory_ownership: DirectoryOwnership, - name: String, - id_sp: Span, - ) -> PResult<'a, (Mod, Vec)> { - let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut(); - if let Some(i) = included_mod_stack.iter().position(|p| *p == path) { - let mut err = String::from("circular modules: "); - let len = included_mod_stack.len(); - for p in &included_mod_stack[i..len] { - err.push_str(&p.to_string_lossy()); - err.push_str(" -> "); - } - err.push_str(&path.to_string_lossy()); - return Err(self.struct_span_err(id_sp, &err[..])); - } - included_mod_stack.push(path.clone()); - drop(included_mod_stack); - - let mut p0 = - new_sub_parser_from_file(self.sess, &path, directory_ownership, Some(name), id_sp); - p0.cfg_mods = self.cfg_mods; - let mod_inner_lo = p0.token.span; - let mod_attrs = p0.parse_inner_attributes()?; - let mut m0 = p0.parse_mod_items(&token::Eof, mod_inner_lo)?; - m0.inline = false; - self.sess.included_mod_stack.borrow_mut().pop(); - Ok((m0, mod_attrs)) - } - - fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) { - if let Some(path) = attr::first_attr_value_str_by_name(attrs, sym::path) { - self.directory.path.push(&*path.as_str()); - self.directory.ownership = DirectoryOwnership::Owned { relative: None }; - } else { - // We have to push on the current module name in the case of relative - // paths in order to ensure that any additional module paths from inline - // `mod x { ... }` come after the relative extension. - // - // For example, a `mod z { ... }` inside `x/y.rs` should set the current - // directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`. - if let DirectoryOwnership::Owned { relative } = &mut self.directory.ownership { - if let Some(ident) = relative.take() { - // remove the relative offset - self.directory.path.push(&*ident.as_str()); - } - } - self.directory.path.push(&*id.as_str()); - } - } -} diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs index 5f2b3b03488b4..983aa43916fa8 100644 --- a/src/librustc_parse/parser/pat.rs +++ b/src/librustc_parse/parser/pat.rs @@ -1,9 +1,7 @@ use super::{Parser, PathStyle}; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; -use rustc_ast::ast::{ - self, AttrVec, Attribute, FieldPat, Mac, Pat, PatKind, RangeEnd, RangeSyntax, -}; -use rustc_ast::ast::{BindingMode, Expr, ExprKind, Ident, Mutability, Path, QSelf}; +use rustc_ast::ast::{self, AttrVec, Attribute, FieldPat, MacCall, Pat, PatKind, RangeEnd}; +use rustc_ast::ast::{BindingMode, Expr, ExprKind, Ident, Mutability, Path, QSelf, RangeSyntax}; use rustc_ast::mut_visit::{noop_visit_mac, noop_visit_pat, MutVisitor}; use rustc_ast::ptr::P; use rustc_ast::token; @@ -297,6 +295,8 @@ impl<'a> Parser<'a> { // A rest pattern `..`. self.bump(); // `..` PatKind::Rest + } else if self.check(&token::DotDotDot) && !self.is_pat_range_end_start(1) { + self.recover_dotdotdot_rest_pat(lo) } else if let Some(form) = self.parse_range_end() { self.parse_pat_range_to(form)? // `..=X`, `...X`, or `..X`. } else if self.eat_keyword(kw::Underscore) { @@ -364,6 +364,25 @@ impl<'a> Parser<'a> { Ok(pat) } + /// Recover from a typoed `...` pattern that was encountered + /// Ref: Issue #70388 + fn recover_dotdotdot_rest_pat(&mut self, lo: Span) -> PatKind { + // A typoed rest pattern `...`. + self.bump(); // `...` + + // The user probably mistook `...` for a rest pattern `..`. + self.struct_span_err(lo, "unexpected `...`") + .span_label(lo, "not a valid pattern") + .span_suggestion_short( + lo, + "for a rest pattern, use `..` instead of `...`", + "..".to_owned(), + Applicability::MachineApplicable, + ) + .emit(); + PatKind::Rest + } + /// Try to recover the more general form `intersect ::= $pat_lhs @ $pat_rhs`. /// /// Allowed binding patterns generated by `binding ::= ref? mut? $ident @ $pat_rhs` @@ -540,7 +559,7 @@ impl<'a> Parser<'a> { fn make_all_value_bindings_mutable(pat: &mut P) -> bool { struct AddMut(bool); impl MutVisitor for AddMut { - fn visit_mac(&mut self, mac: &mut Mac) { + fn visit_mac(&mut self, mac: &mut MacCall) { noop_visit_mac(mac, self); } @@ -597,8 +616,8 @@ impl<'a> Parser<'a> { fn parse_pat_mac_invoc(&mut self, path: Path) -> PResult<'a, PatKind> { self.bump(); let args = self.parse_mac_args()?; - let mac = Mac { path, args, prior_type_ascription: self.last_type_ascription }; - Ok(PatKind::Mac(mac)) + let mac = MacCall { path, args, prior_type_ascription: self.last_type_ascription }; + Ok(PatKind::MacCall(mac)) } fn fatal_unexpected_non_pat( @@ -698,7 +717,7 @@ impl<'a> Parser<'a> { self.look_ahead(dist, |t| { t.is_path_start() // e.g. `MY_CONST`; || t.kind == token::Dot // e.g. `.5` for recovery; - || t.can_begin_literal_or_bool() // e.g. `42`. + || t.can_begin_literal_maybe_minus() // e.g. `42`. || t.is_whole_expr() }) } @@ -920,7 +939,7 @@ impl<'a> Parser<'a> { } err.emit(); } - return Ok((fields, etc)); + Ok((fields, etc)) } /// Recover on `...` as if it were `..` to avoid further errors. diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index 489549a57505f..fddfe48bf8670 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -5,10 +5,9 @@ use super::pat::GateOr; use super::path::PathStyle; use super::{BlockMode, Parser, Restrictions, SemiColonMode}; use crate::maybe_whole; -use crate::DirectoryOwnership; use rustc_ast::ast; -use rustc_ast::ast::{AttrStyle, AttrVec, Attribute, Mac, MacStmtStyle}; +use rustc_ast::ast::{AttrStyle, AttrVec, Attribute, MacCall, MacStmtStyle}; use rustc_ast::ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt, StmtKind, DUMMY_NODE_ID}; use rustc_ast::ptr::P; use rustc_ast::token::{self, TokenKind}; @@ -54,7 +53,7 @@ impl<'a> Parser<'a> { // that starts like a path (1 token), but it fact not a path. // Also, we avoid stealing syntax from `parse_item_`. self.parse_stmt_path_start(lo, attrs)? - } else if let Some(item) = self.parse_stmt_item(attrs.clone())? { + } else if let Some(item) = self.parse_item_common(attrs.clone(), false, true, |_| true)? { // FIXME: Bad copy of attrs self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item))) } else if self.eat(&token::Semi) { @@ -72,13 +71,6 @@ impl<'a> Parser<'a> { Ok(Some(stmt)) } - fn parse_stmt_item(&mut self, attrs: Vec) -> PResult<'a, Option> { - let old = mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock); - let item = self.parse_item_common(attrs, false, true, |_| true)?; - self.directory.ownership = old; - Ok(item) - } - fn parse_stmt_path_start(&mut self, lo: Span, attrs: Vec) -> PResult<'a, Stmt> { let path = self.parse_path(PathStyle::Expr)?; @@ -110,14 +102,14 @@ impl<'a> Parser<'a> { let style = if delim == token::Brace { MacStmtStyle::Braces } else { MacStmtStyle::NoBraces }; - let mac = Mac { path, args, prior_type_ascription: self.last_type_ascription }; + let mac = MacCall { path, args, prior_type_ascription: self.last_type_ascription }; let kind = if delim == token::Brace || self.token == token::Semi || self.token == token::Eof { - StmtKind::Mac(P((mac, style, attrs))) + StmtKind::MacCall(P((mac, style, attrs))) } else { // Since none of the above applied, this is an expression statement macro. - let e = self.mk_expr(lo.to(hi), ExprKind::Mac(mac), AttrVec::new()); + let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac), AttrVec::new()); let e = self.maybe_recover_from_bad_qpath(e, true)?; let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?; let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?; @@ -225,13 +217,7 @@ impl<'a> Parser<'a> { /// Parses the RHS of a local variable declaration (e.g., '= 14;'). fn parse_initializer(&mut self, skip_eq: bool) -> PResult<'a, Option>> { - if self.eat(&token::Eq) { - Ok(Some(self.parse_expr()?)) - } else if skip_eq { - Ok(Some(self.parse_expr()?)) - } else { - Ok(None) - } + if self.eat(&token::Eq) || skip_eq { Ok(Some(self.parse_expr()?)) } else { Ok(None) } } /// Parses a block. No inner attributes are allowed. @@ -286,7 +272,7 @@ impl<'a> Parser<'a> { _ => {} } e.span_label(sp, "expected `{`"); - return Err(e); + Err(e) } /// Parses a block. Inner attributes are allowed. diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index 3dd415bf37289..c21ac8d04f194 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -3,10 +3,8 @@ use super::{Parser, PathStyle, TokenType}; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; use rustc_ast::ast::{self, BareFnTy, FnRetTy, GenericParam, Lifetime, MutTy, Ty, TyKind}; -use rustc_ast::ast::{ - GenericBound, GenericBounds, PolyTraitRef, TraitBoundModifier, TraitObjectSyntax, -}; -use rustc_ast::ast::{Mac, Mutability}; +use rustc_ast::ast::{GenericBound, GenericBounds, MacCall, Mutability}; +use rustc_ast::ast::{PolyTraitRef, TraitBoundModifier, TraitObjectSyntax}; use rustc_ast::ptr::P; use rustc_ast::token::{self, Token, TokenKind}; use rustc_errors::{pluralize, struct_span_err, Applicability, PResult}; @@ -355,7 +353,7 @@ impl<'a> Parser<'a> { let path = self.parse_path(PathStyle::Type)?; if self.eat(&token::Not) { // Macro invocation in type position - Ok(TyKind::Mac(Mac { + Ok(TyKind::MacCall(MacCall { path, args: self.parse_mac_args()?, prior_type_ascription: self.last_type_ascription, diff --git a/src/librustc_parse/validate_attr.rs b/src/librustc_parse/validate_attr.rs index 029aa5ed2baea..2512878ec65be 100644 --- a/src/librustc_parse/validate_attr.rs +++ b/src/librustc_parse/validate_attr.rs @@ -57,7 +57,7 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta }) } -crate fn check_meta_bad_delim(sess: &ParseSess, span: DelimSpan, delim: MacDelimiter, msg: &str) { +pub fn check_meta_bad_delim(sess: &ParseSess, span: DelimSpan, delim: MacDelimiter, msg: &str) { if let ast::MacDelimiter::Parenthesis = delim { return; } diff --git a/src/librustc_passes/Cargo.toml b/src/librustc_passes/Cargo.toml index af8e7a5b71e46..8acb88f58d379 100644 --- a/src/librustc_passes/Cargo.toml +++ b/src/librustc_passes/Cargo.toml @@ -22,3 +22,4 @@ rustc_session = { path = "../librustc_session" } rustc_target = { path = "../librustc_target" } rustc_ast = { path = "../librustc_ast" } rustc_span = { path = "../librustc_span" } +rustc_trait_selection = { path = "../librustc_trait_selection" } diff --git a/src/librustc_passes/check_attr.rs b/src/librustc_passes/check_attr.rs index f1ed074d6ab77..583e1fdc1f05f 100644 --- a/src/librustc_passes/check_attr.rs +++ b/src/librustc_passes/check_attr.rs @@ -25,7 +25,7 @@ use rustc_span::Span; fn target_from_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item: &hir::ImplItem<'_>) -> Target { match impl_item.kind { hir::ImplItemKind::Const(..) => Target::AssocConst, - hir::ImplItemKind::Method(..) => { + hir::ImplItemKind::Fn(..) => { 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 { @@ -151,17 +151,17 @@ impl CheckAttrVisitor<'tcx> { .emit(); false } - Target::Fn | Target::Method(MethodKind::Inherent) => true, - Target::Method(_) => { + Target::ForeignFn => { struct_span_err!( self.tcx.sess, *attr_span, E0738, - "`#[track_caller]` may not be used on trait methods", + "`#[track_caller]` is not supported on foreign functions", ) .emit(); false } + Target::Fn | Target::Method(..) => true, _ => { struct_span_err!( self.tcx.sess, @@ -418,8 +418,8 @@ impl CheckAttrVisitor<'tcx> { impl Visitor<'tcx> for CheckAttrVisitor<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx Item<'tcx>) { diff --git a/src/librustc_passes/check_const.rs b/src/librustc_passes/check_const.rs index 53e8213ae4807..30737360b9c20 100644 --- a/src/librustc_passes/check_const.rs +++ b/src/librustc_passes/check_const.rs @@ -8,9 +8,6 @@ //! through, but errors for structured control flow in a `const` should be emitted here. use rustc::hir::map::Map; -use rustc::hir::Hir; -use rustc::session::config::nightly_options; -use rustc::session::parse::feature_err; use rustc::ty::query::Providers; use rustc::ty::TyCtxt; use rustc_ast::ast::Mutability; @@ -18,6 +15,8 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; +use rustc_session::config::nightly_options; +use rustc_session::parse::feature_err; use rustc_span::{sym, Span, Symbol}; use std::fmt; @@ -75,7 +74,7 @@ enum ConstKind { } impl ConstKind { - fn for_body(body: &hir::Body<'_>, hir_map: Hir<'_>) -> Option { + fn for_body(body: &hir::Body<'_>, hir_map: Map<'_>) -> Option { let is_const_fn = |id| hir_map.fn_sig_by_hir_id(id).unwrap().header.is_const(); let owner = hir_map.body_owner(body.id()); @@ -202,8 +201,8 @@ impl<'tcx> CheckConstVisitor<'tcx> { impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.tcx.hir()) } fn visit_anon_const(&mut self, anon: &'tcx hir::AnonConst) { diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs index 4a0ffc23365da..2781c5c125d9f 100644 --- a/src/librustc_passes/dead.rs +++ b/src/librustc_passes/dead.rs @@ -210,9 +210,9 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { NestedVisitorMap::None } @@ -391,7 +391,7 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> { let trait_item = self.krate.trait_item(trait_item_ref.id); match trait_item.kind { hir::TraitItemKind::Const(_, Some(_)) - | hir::TraitItemKind::Fn(_, hir::TraitMethod::Provided(_)) => { + | hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => { if has_allow_dead_code_or_lang_attr( self.tcx, trait_item.hir_id, @@ -568,8 +568,8 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { /// on inner functions when the outer function is already getting /// an error. We could do this also by checking the parents, but /// this is how the code is setup and it seems harmless enough. - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::All(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::All(self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { @@ -590,7 +590,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { // We should probably annotate ident.span with the macro // context, but that's a larger change. if item.span.source_callee().is_some() { - self.tcx.sess.source_map().def_span(item.span) + self.tcx.sess.source_map().guess_head_span(item.span) } else { item.ident.span } @@ -661,9 +661,9 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { } self.visit_nested_body(body_id) } - hir::ImplItemKind::Method(_, body_id) => { + hir::ImplItemKind::Fn(_, body_id) => { if !self.symbol_is_live(impl_item.hir_id) { - let span = self.tcx.sess.source_map().def_span(impl_item.span); + let span = self.tcx.sess.source_map().guess_head_span(impl_item.span); self.warn_dead_code( impl_item.hir_id, span, @@ -682,11 +682,11 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) { match trait_item.kind { hir::TraitItemKind::Const(_, Some(body_id)) - | hir::TraitItemKind::Fn(_, hir::TraitMethod::Provided(body_id)) => { + | hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)) => { self.visit_nested_body(body_id) } hir::TraitItemKind::Const(_, None) - | hir::TraitItemKind::Fn(_, hir::TraitMethod::Required(_)) + | hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) | hir::TraitItemKind::Type(..) => {} } } diff --git a/src/librustc_passes/entry.rs b/src/librustc_passes/entry.rs index 86596e205562e..7e0d0bfe9aba4 100644 --- a/src/librustc_passes/entry.rs +++ b/src/librustc_passes/entry.rs @@ -1,6 +1,4 @@ -use rustc::hir::Hir; -use rustc::session::config::EntryFnType; -use rustc::session::{config, Session}; +use rustc::hir::map::Map; use rustc::ty::query::Providers; use rustc::ty::TyCtxt; use rustc_ast::attr; @@ -9,13 +7,15 @@ use rustc_errors::struct_span_err; use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{HirId, ImplItem, Item, ItemKind, TraitItem}; +use rustc_session::config::EntryFnType; +use rustc_session::{config, Session}; use rustc_span::symbol::sym; use rustc_span::{Span, DUMMY_SP}; struct EntryContext<'a, 'tcx> { session: &'a Session, - map: Hir<'tcx>, + map: Map<'tcx>, /// The top-level function called `main`. main_fn: Option<(HirId, Span)>, @@ -34,7 +34,7 @@ struct EntryContext<'a, 'tcx> { impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> { fn visit_item(&mut self, item: &'tcx Item<'tcx>) { let def_id = self.map.local_def_id(item.hir_id); - let def_key = self.map.def_key(def_id); + let def_key = self.map.def_key(def_id.expect_local()); let at_root = def_key.parent == Some(CRATE_DEF_INDEX); find_item(item, self, at_root); } @@ -59,7 +59,7 @@ fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(DefId, EntryFnType)> { } // If the user wants no main function at all, then stop here. - if attr::contains_name(&tcx.hir().krate().attrs, sym::no_main) { + if attr::contains_name(&tcx.hir().krate().item.attrs, sym::no_main) { return None; } @@ -157,7 +157,7 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(De } fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) { - let sp = tcx.hir().krate().span; + let sp = tcx.hir().krate().item.span; if *tcx.sess.parse_sess.reached_eof.borrow() { // There's an unclosed brace that made the parser reach `Eof`, we shouldn't complain about // the missing `fn main()` then as it might have been hidden inside an unclosed block. diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc_passes/hir_id_validator.rs similarity index 75% rename from src/librustc/hir/map/hir_id_validator.rs rename to src/librustc_passes/hir_id_validator.rs index a4f9193c0eb64..a78e45eebbed4 100644 --- a/src/librustc/hir/map/hir_id_validator.rs +++ b/src/librustc_passes/hir_id_validator.rs @@ -1,18 +1,20 @@ -use crate::hir::map::Map; +use rustc::hir::map::Map; +use rustc::ty::TyCtxt; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator}; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; +use rustc_hir::def_id::{LocalDefId, CRATE_DEF_INDEX}; use rustc_hir::intravisit; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{HirId, ItemLocalId}; -pub fn check_crate(hir_map: &Map<'_>, sess: &rustc_session::Session) { - hir_map.dep_graph.assert_ignored(); +pub fn check_crate(tcx: TyCtxt<'_>) { + tcx.dep_graph.assert_ignored(); let errors = Lock::new(Vec::new()); + let hir_map = tcx.hir(); - par_iter(&hir_map.krate.modules).for_each(|(module_id, _)| { + par_iter(&hir_map.krate().modules).for_each(|(module_id, _)| { let local_def_id = hir_map.local_def_id(*module_id); hir_map.visit_item_likes_in_module( local_def_id, @@ -24,27 +26,27 @@ pub fn check_crate(hir_map: &Map<'_>, sess: &rustc_session::Session) { if !errors.is_empty() { let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2); - sess.delay_span_bug(rustc_span::DUMMY_SP, &message); + tcx.sess.delay_span_bug(rustc_span::DUMMY_SP, &message); } } struct HirIdValidator<'a, 'hir> { - hir_map: &'a Map<'hir>, - owner_def_index: Option, + hir_map: Map<'hir>, + owner: Option, hir_ids_seen: FxHashSet, errors: &'a Lock>, } struct OuterVisitor<'a, 'hir> { - hir_map: &'a Map<'hir>, + hir_map: Map<'hir>, errors: &'a Lock>, } impl<'a, 'hir> OuterVisitor<'a, 'hir> { - fn new_inner_visitor(&self, hir_map: &'a Map<'hir>) -> HirIdValidator<'a, 'hir> { + fn new_inner_visitor(&self, hir_map: Map<'hir>) -> HirIdValidator<'a, 'hir> { HirIdValidator { hir_map, - owner_def_index: None, + owner: None, hir_ids_seen: Default::default(), errors: self.errors, } @@ -76,12 +78,12 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { } fn check)>(&mut self, hir_id: HirId, walk: F) { - assert!(self.owner_def_index.is_none()); - let owner_def_index = self.hir_map.local_def_id(hir_id).index; - self.owner_def_index = Some(owner_def_index); + assert!(self.owner.is_none()); + let owner = self.hir_map.local_def_id(hir_id).expect_local(); + self.owner = Some(owner); walk(self); - if owner_def_index == CRATE_DEF_INDEX { + if owner.local_def_index == CRATE_DEF_INDEX { return; } @@ -103,27 +105,26 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { let mut missing_items = Vec::with_capacity(missing.len()); for local_id in missing { - let hir_id = - HirId { owner: owner_def_index, local_id: ItemLocalId::from_u32(local_id) }; + let hir_id = HirId { owner, local_id: ItemLocalId::from_u32(local_id) }; trace!("missing hir id {:#?}", hir_id); missing_items.push(format!( - "[local_id: {}, node:{}]", + "[local_id: {}, owner: {}]", local_id, - self.hir_map.node_to_string(hir_id) + self.hir_map.def_path(owner).to_string_no_crate() )); } self.error(|| { format!( "ItemLocalIds not assigned densely in {}. \ Max ItemLocalId = {}, missing IDs = {:?}; seens IDs = {:?}", - self.hir_map.def_path(DefId::local(owner_def_index)).to_string_no_crate(), + self.hir_map.def_path(owner).to_string_no_crate(), max, missing_items, self.hir_ids_seen .iter() - .map(|&local_id| HirId { owner: owner_def_index, local_id }) + .map(|&local_id| HirId { owner, local_id }) .map(|h| format!("({:?} {})", h, self.hir_map.node_to_string(h))) .collect::>() ) @@ -135,12 +136,12 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { type Map = Map<'hir>; - fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, Self::Map> { + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { intravisit::NestedVisitorMap::OnlyBodies(self.hir_map) } fn visit_id(&mut self, hir_id: HirId) { - let owner = self.owner_def_index.expect("no owner_def_index"); + let owner = self.owner.expect("no owner"); if hir_id == hir::DUMMY_HIR_ID { self.error(|| { @@ -157,8 +158,8 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { format!( "HirIdValidator: The recorded owner of {} is {} instead of {}", self.hir_map.node_to_string(hir_id), - self.hir_map.def_path(DefId::local(hir_id.owner)).to_string_no_crate(), - self.hir_map.def_path(DefId::local(owner)).to_string_no_crate() + self.hir_map.def_path(hir_id.owner).to_string_no_crate(), + self.hir_map.def_path(owner).to_string_no_crate() ) }); } diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs index c819809041f28..8bfe58da78f6e 100644 --- a/src/librustc_passes/hir_stats.rs +++ b/src/librustc_passes/hir_stats.rs @@ -95,7 +95,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { type Map = Map<'v>; - fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap { panic!("visit_nested_xxx must be manually implemented in this visitor") } @@ -336,8 +336,8 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { ast_visit::walk_lifetime(self, lifetime) } - fn visit_mac(&mut self, mac: &'v ast::Mac) { - self.record("Mac", Id::None, mac); + fn visit_mac(&mut self, mac: &'v ast::MacCall) { + self.record("MacCall", Id::None, mac); } fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v ast::PathSegment) { diff --git a/src/librustc_passes/intrinsicck.rs b/src/librustc_passes/intrinsicck.rs index 782199003c72a..1b46aaeefcb18 100644 --- a/src/librustc_passes/intrinsicck.rs +++ b/src/librustc_passes/intrinsicck.rs @@ -1,4 +1,3 @@ -use rustc::hir::map::Map; use rustc::ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx}; use rustc::ty::query::Providers; use rustc::ty::{self, Ty, TyCtxt}; @@ -122,9 +121,9 @@ impl ExprVisitor<'tcx> { } impl Visitor<'tcx> for ItemVisitor<'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } @@ -139,9 +138,9 @@ impl Visitor<'tcx> for ItemVisitor<'tcx> { } impl Visitor<'tcx> for ExprVisitor<'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } diff --git a/src/librustc_passes/lang_items.rs b/src/librustc_passes/lang_items.rs index 5f5acc7fdf815..88e92bbdba1aa 100644 --- a/src/librustc_passes/lang_items.rs +++ b/src/librustc_passes/lang_items.rs @@ -143,7 +143,7 @@ impl LanguageItemCollector<'tcx> { } /// Traverses and collects all the lang items in all crates. -fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> LanguageItems { +fn collect(tcx: TyCtxt<'_>) -> LanguageItems { // Initialize the collector. let mut collector = LanguageItemCollector::new(tcx); diff --git a/src/librustc_passes/layout_test.rs b/src/librustc_passes/layout_test.rs index 9f6598a0ec1fe..9d8b1422bdf24 100644 --- a/src/librustc_passes/layout_test.rs +++ b/src/librustc_passes/layout_test.rs @@ -17,24 +17,30 @@ use rustc_span::symbol::sym; pub fn test_layout(tcx: TyCtxt<'_>) { if tcx.features().rustc_attrs { // if the `rustc_attrs` feature is not enabled, don't bother testing layout - tcx.hir().krate().visit_all_item_likes(&mut VarianceTest { tcx }); + tcx.hir().krate().visit_all_item_likes(&mut LayoutTest { tcx }); } } -struct VarianceTest<'tcx> { +struct LayoutTest<'tcx> { tcx: TyCtxt<'tcx>, } -impl ItemLikeVisitor<'tcx> for VarianceTest<'tcx> { +impl ItemLikeVisitor<'tcx> for LayoutTest<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { let item_def_id = self.tcx.hir().local_def_id(item.hir_id); - if let ItemKind::TyAlias(..) = item.kind { - for attr in self.tcx.get_attrs(item_def_id).iter() { - if attr.check_name(sym::rustc_layout) { - self.dump_layout_of(item_def_id, item, attr); + match item.kind { + ItemKind::TyAlias(..) + | ItemKind::Enum(..) + | ItemKind::Struct(..) + | ItemKind::Union(..) => { + for attr in self.tcx.get_attrs(item_def_id).iter() { + if attr.check_name(sym::rustc_layout) { + self.dump_layout_of(item_def_id, item, attr); + } } } + _ => {} } } @@ -42,7 +48,7 @@ impl ItemLikeVisitor<'tcx> for VarianceTest<'tcx> { fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem<'tcx>) {} } -impl VarianceTest<'tcx> { +impl LayoutTest<'tcx> { fn dump_layout_of(&self, item_def_id: DefId, item: &hir::Item<'tcx>, attr: &Attribute) { let tcx = self.tcx; let param_env = self.tcx.param_env(item_def_id); @@ -81,6 +87,13 @@ impl VarianceTest<'tcx> { ); } + sym::debug => { + self.tcx.sess.span_err( + item.span, + &format!("layout debugging: {:#?}", *ty_layout), + ); + } + name => { self.tcx.sess.span_err( meta_item.span(), diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index afafbacb8fa88..ab978edb8c3de 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -21,6 +21,7 @@ mod check_const; pub mod dead; mod diagnostic_items; pub mod entry; +pub mod hir_id_validator; pub mod hir_stats; mod intrinsicck; mod lang_items; diff --git a/src/librustc_passes/lib_features.rs b/src/librustc_passes/lib_features.rs index 172d7e7628e21..133e30f6ff01a 100644 --- a/src/librustc_passes/lib_features.rs +++ b/src/librustc_passes/lib_features.rs @@ -114,8 +114,8 @@ impl LibFeatureCollector<'tcx> { impl Visitor<'tcx> for LibFeatureCollector<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::All(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::All(self.tcx.hir()) } fn visit_attribute(&mut self, attr: &'tcx Attribute) { diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs index 5b6d0fc74e80f..97f6457d39736 100644 --- a/src/librustc_passes/liveness.rs +++ b/src/librustc_passes/liveness.rs @@ -97,7 +97,6 @@ use self::LiveNodeKind::*; use self::VarKind::*; use rustc::hir::map::Map; -use rustc::lint; use rustc::ty::query::Providers; use rustc::ty::{self, TyCtxt}; use rustc_ast::ast; @@ -108,6 +107,7 @@ use rustc_hir::def::*; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, FnKind, NestedVisitorMap, Visitor}; use rustc_hir::{Expr, HirId, HirIdMap, HirIdSet, Node}; +use rustc_session::lint; use rustc_span::symbol::sym; use rustc_span::Span; @@ -156,8 +156,8 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_>) -> String { impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.tcx.hir()) } fn visit_fn( @@ -398,7 +398,7 @@ fn visit_fn<'tcx>( intravisit::walk_fn(&mut fn_maps, fk, decl, body_id, sp, id); // compute liveness - let mut lsets = Liveness::new(&mut fn_maps, body_id); + let mut lsets = Liveness::new(&mut fn_maps, def_id); let entry_ln = lsets.compute(&body.value); // check for various error conditions @@ -658,6 +658,7 @@ const ACC_USE: u32 = 4; struct Liveness<'a, 'tcx> { ir: &'a mut IrMaps<'tcx>, tables: &'a ty::TypeckTables<'tcx>, + param_env: ty::ParamEnv<'tcx>, s: Specials, successors: Vec, rwu_table: RWUTable, @@ -670,7 +671,7 @@ struct Liveness<'a, 'tcx> { } impl<'a, 'tcx> Liveness<'a, 'tcx> { - fn new(ir: &'a mut IrMaps<'tcx>, body: hir::BodyId) -> Liveness<'a, 'tcx> { + fn new(ir: &'a mut IrMaps<'tcx>, def_id: DefId) -> Liveness<'a, 'tcx> { // Special nodes and variables: // - exit_ln represents the end of the fn, either by return or panic // - implicit_ret_var is a pseudo-variable that represents @@ -681,7 +682,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { clean_exit_var: ir.add_variable(CleanExit), }; - let tables = ir.tcx.body_tables(body); + let tables = ir.tcx.typeck_tables_of(def_id); + let param_env = ir.tcx.param_env(def_id); let num_live_nodes = ir.num_live_nodes; let num_vars = ir.num_vars; @@ -689,6 +691,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { Liveness { ir, tables, + param_env, s: specials, successors: vec![invalid_node(); num_live_nodes], rwu_table: RWUTable::new(num_live_nodes * num_vars), @@ -861,7 +864,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { first_merge, any_changed ); - return any_changed; + any_changed } // Indicates that a local variable was *defined*; we know that no @@ -1125,8 +1128,12 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } hir::ExprKind::Call(ref f, ref args) => { - let m = self.ir.tcx.parent_module(expr.hir_id); - let succ = if self.ir.tcx.is_ty_uninhabited_from(m, self.tables.expr_ty(expr)) { + let m = self.ir.tcx.parent_module(expr.hir_id).to_def_id(); + let succ = if self.ir.tcx.is_ty_uninhabited_from( + m, + self.tables.expr_ty(expr), + self.param_env, + ) { self.s.exit_ln } else { succ @@ -1136,8 +1143,12 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } hir::ExprKind::MethodCall(.., ref args) => { - let m = self.ir.tcx.parent_module(expr.hir_id); - let succ = if self.ir.tcx.is_ty_uninhabited_from(m, self.tables.expr_ty(expr)) { + let m = self.ir.tcx.parent_module(expr.hir_id).to_def_id(); + let succ = if self.ir.tcx.is_ty_uninhabited_from( + m, + self.tables.expr_ty(expr), + self.param_env, + ) { self.s.exit_ln } else { succ @@ -1359,9 +1370,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // Checking for error conditions impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } @@ -1554,7 +1565,7 @@ impl<'tcx> Liveness<'_, 'tcx> { } } else { err.multipart_suggestion( - "consider prefixing with an underscore", + "if this is intentional, prefix it with an underscore", spans.iter().map(|span| (*span, format!("_{}", name))).collect(), Applicability::MachineApplicable, ); diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs index 2719057fb5351..fa2afae469c04 100644 --- a/src/librustc_passes/loops.rs +++ b/src/librustc_passes/loops.rs @@ -24,15 +24,14 @@ enum Context { #[derive(Copy, Clone)] struct CheckLoopVisitor<'a, 'hir> { sess: &'a Session, - hir_map: &'a Map<'hir>, + hir_map: Map<'hir>, cx: Context, } fn check_mod_loops(tcx: TyCtxt<'_>, module_def_id: DefId) { tcx.hir().visit_item_likes_in_module( module_def_id, - &mut CheckLoopVisitor { sess: &tcx.sess, hir_map: &tcx.hir(), cx: Normal } - .as_deep_visitor(), + &mut CheckLoopVisitor { sess: &tcx.sess, hir_map: tcx.hir(), cx: Normal }.as_deep_visitor(), ); } @@ -43,8 +42,8 @@ pub(crate) fn provide(providers: &mut Providers<'_>) { impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { type Map = Map<'hir>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.hir_map) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.hir_map) } fn visit_anon_const(&mut self, c: &'hir hir::AnonConst) { @@ -223,7 +222,7 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { return true; } } - return false; + false } fn emit_unlabled_cf_in_while_condition(&mut self, span: Span, cf_type: &str) { struct_span_err!( diff --git a/src/librustc_passes/reachable.rs b/src/librustc_passes/reachable.rs index 79a9f22603042..1e9c6c91d385f 100644 --- a/src/librustc_passes/reachable.rs +++ b/src/librustc_passes/reachable.rs @@ -5,10 +5,8 @@ // makes all other generics or inline functions that it references // reachable as well. -use rustc::hir::map::Map; use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc::middle::privacy; -use rustc::session::config; use rustc::ty::query::Providers; use rustc::ty::{self, TyCtxt}; use rustc_data_structures::fx::FxHashSet; @@ -17,10 +15,10 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::def_id::{CrateNum, DefId}; -use rustc_hir::intravisit; -use rustc_hir::intravisit::{NestedVisitorMap, Visitor}; +use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{HirIdSet, Node}; +use rustc_session::config; use rustc_target::spec::abi::Abi; // Returns true if the given item must be inlined because it may be @@ -32,9 +30,7 @@ fn item_might_be_inlined(tcx: TyCtxt<'tcx>, item: &hir::Item<'_>, attrs: Codegen } match item.kind { - hir::ItemKind::Fn(ref sig, ..) if sig.header.is_const() => { - return true; - } + hir::ItemKind::Fn(ref sig, ..) if sig.header.is_const() => true, hir::ItemKind::Impl { .. } | hir::ItemKind::Fn(..) => { let generics = tcx.generics_of(tcx.hir().local_def_id(item.hir_id)); generics.requires_monomorphization(tcx) @@ -48,12 +44,12 @@ fn method_might_be_inlined( impl_item: &hir::ImplItem<'_>, impl_src: DefId, ) -> bool { - let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id.owner_def_id()); + let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id.owner.to_def_id()); let generics = tcx.generics_of(tcx.hir().local_def_id(impl_item.hir_id)); if codegen_fn_attrs.requests_inline() || generics.requires_monomorphization(tcx) { return true; } - if let hir::ImplItemKind::Method(method_sig, _) = &impl_item.kind { + if let hir::ImplItemKind::Fn(method_sig, _) = &impl_item.kind { if method_sig.header.is_const() { return true; } @@ -83,9 +79,9 @@ struct ReachableContext<'a, 'tcx> { } impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } @@ -162,14 +158,14 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { }, Some(Node::TraitItem(trait_method)) => match trait_method.kind { hir::TraitItemKind::Const(_, ref default) => default.is_some(), - hir::TraitItemKind::Fn(_, hir::TraitMethod::Provided(_)) => true, - hir::TraitItemKind::Fn(_, hir::TraitMethod::Required(_)) + hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => true, + hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) | hir::TraitItemKind::Type(..) => false, }, Some(Node::ImplItem(impl_item)) => { match impl_item.kind { hir::ImplItemKind::Const(..) => true, - hir::ImplItemKind::Method(..) => { + hir::ImplItemKind::Fn(..) => { let attrs = self.tcx.codegen_fn_attrs(def_id); let generics = self.tcx.generics_of(def_id); if generics.requires_monomorphization(self.tcx) || attrs.requests_inline() { @@ -278,11 +274,11 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { Node::TraitItem(trait_method) => { match trait_method.kind { hir::TraitItemKind::Const(_, None) - | hir::TraitItemKind::Fn(_, hir::TraitMethod::Required(_)) => { + | hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) => { // Keep going, nothing to get exported } hir::TraitItemKind::Const(_, Some(body_id)) - | hir::TraitItemKind::Fn(_, hir::TraitMethod::Provided(body_id)) => { + | hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)) => { self.visit_nested_body(body_id); } hir::TraitItemKind::Type(..) => {} @@ -292,7 +288,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { hir::ImplItemKind::Const(_, body) => { self.visit_nested_body(body); } - hir::ImplItemKind::Method(_, body) => { + hir::ImplItemKind::Fn(_, body) => { let did = self.tcx.hir().get_parent_did(search_item); if method_might_be_inlined(self.tcx, impl_item, did) { self.visit_nested_body(body) diff --git a/src/librustc_passes/region.rs b/src/librustc_passes/region.rs index 908785faff073..e771696a5b6bf 100644 --- a/src/librustc_passes/region.rs +++ b/src/librustc_passes/region.rs @@ -6,7 +6,6 @@ //! //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html -use rustc::hir::map::Map; use rustc::middle::region::*; use rustc::ty::query::Providers; use rustc::ty::TyCtxt; @@ -696,9 +695,9 @@ impl<'tcx> RegionResolutionVisitor<'tcx> { } impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index 7ea9ab5335db3..8fa5a4fbc61f4 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -2,11 +2,8 @@ //! propagating default levels lexically from parent to children ast nodes. use rustc::hir::map::Map; -use rustc::lint; use rustc::middle::privacy::AccessLevels; use rustc::middle::stability::{DeprecationEntry, Index}; -use rustc::session::parse::feature_err; -use rustc::session::Session; use rustc::ty::query::Providers; use rustc::ty::TyCtxt; use rustc_ast::ast::Attribute; @@ -18,9 +15,12 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{Generics, HirId, Item, StructField, Variant}; -use rustc_infer::traits::misc::can_type_implement_copy; +use rustc_session::lint; +use rustc_session::parse::feature_err; +use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; +use rustc_trait_selection::traits::misc::can_type_implement_copy; use std::cmp::Ordering; use std::mem::replace; @@ -259,8 +259,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { /// deep-walking. type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::All(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::All(self.tcx.hir()) } fn visit_item(&mut self, i: &'tcx Item<'tcx>) { @@ -350,8 +350,8 @@ impl<'a, 'tcx> MissingStabilityAnnotations<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.tcx.hir()) } fn visit_item(&mut self, i: &'tcx Item<'tcx>) { @@ -459,13 +459,13 @@ fn new_index(tcx: TyCtxt<'tcx>) -> Index<'tcx> { annotator.annotate( hir::CRATE_HIR_ID, - &krate.attrs, - krate.span, + &krate.item.attrs, + krate.item.span, AnnotationKind::Required, |v| intravisit::walk_crate(v, krate), ); } - return index; + index } /// Cross-references the feature names of unstable APIs with enabled @@ -492,8 +492,8 @@ impl Visitor<'tcx> for Checker<'tcx> { /// Because stability levels are scoped lexically, we want to walk /// nested items in the context of the outer item, so enable /// deep-walking. - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { @@ -585,7 +585,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { if tcx.stability().staged_api[&LOCAL_CRATE] { let krate = tcx.hir().krate(); let mut missing = MissingStabilityAnnotations { tcx, access_levels }; - missing.check_missing_stability(hir::CRATE_HIR_ID, krate.span, "crate"); + missing.check_missing_stability(hir::CRATE_HIR_ID, krate.item.span, "crate"); intravisit::walk_crate(&mut missing, krate); krate.visit_all_item_likes(&mut missing.as_deep_visitor()); } diff --git a/src/librustc_passes/upvars.rs b/src/librustc_passes/upvars.rs index a2397f273385a..43f39e6c610c8 100644 --- a/src/librustc_passes/upvars.rs +++ b/src/librustc_passes/upvars.rs @@ -1,6 +1,5 @@ //! Upvar (closure capture) collection from cross-body HIR uses of `Res::Local`s. -use rustc::hir::map::Map; use rustc::ty::query::Providers; use rustc::ty::TyCtxt; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; @@ -44,9 +43,9 @@ struct LocalCollector { } impl Visitor<'tcx> for LocalCollector { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } @@ -73,9 +72,9 @@ impl CaptureCollector<'_, '_> { } impl Visitor<'tcx> for CaptureCollector<'a, 'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } diff --git a/src/librustc_passes/weak_lang_items.rs b/src/librustc_passes/weak_lang_items.rs index 1511742446b6e..cde489e8d2c1e 100644 --- a/src/librustc_passes/weak_lang_items.rs +++ b/src/librustc_passes/weak_lang_items.rs @@ -2,15 +2,13 @@ use rustc::middle::lang_items; use rustc::middle::lang_items::whitelisted; -use rustc::session::config; - -use rustc::hir::map::Map; use rustc::ty::TyCtxt; use rustc_data_structures::fx::FxHashSet; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::weak_lang_items::WEAK_ITEMS_REFS; +use rustc_session::config; use rustc_span::symbol::Symbol; use rustc_span::Span; @@ -28,9 +26,6 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItem if items.eh_personality().is_none() { items.missing.push(lang_items::EhPersonalityLangItem); } - if tcx.sess.target.target.options.custom_unwind_resume & items.eh_unwind_resume().is_none() { - items.missing.push(lang_items::EhUnwindResumeLangItem); - } { let mut cx = Context { tcx, items }; @@ -88,9 +83,9 @@ impl<'a, 'tcx> Context<'a, 'tcx> { } impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { - type Map = Map<'v>; + type Map = intravisit::ErasedMap<'v>; - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Map<'v>> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } diff --git a/src/librustc_plugin_impl/Cargo.toml b/src/librustc_plugin_impl/Cargo.toml index 8931307259021..372d6a534c8d4 100644 --- a/src/librustc_plugin_impl/Cargo.toml +++ b/src/librustc_plugin_impl/Cargo.toml @@ -17,4 +17,5 @@ rustc_hir = { path = "../librustc_hir" } rustc_lint = { path = "../librustc_lint" } rustc_metadata = { path = "../librustc_metadata" } rustc_ast = { path = "../librustc_ast" } +rustc_session = { path = "../librustc_session" } rustc_span = { path = "../librustc_span" } diff --git a/src/librustc_plugin_impl/load.rs b/src/librustc_plugin_impl/load.rs index 9bd9bcb25ba88..0810cf56d1783 100644 --- a/src/librustc_plugin_impl/load.rs +++ b/src/librustc_plugin_impl/load.rs @@ -2,10 +2,10 @@ use crate::Registry; use rustc::middle::cstore::MetadataLoader; -use rustc::session::Session; use rustc_ast::ast::{Crate, Ident}; use rustc_errors::struct_span_err; use rustc_metadata::locator; +use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::Span; diff --git a/src/librustc_privacy/Cargo.toml b/src/librustc_privacy/Cargo.toml index 6d1272c117b4d..9854e0f6c53f3 100644 --- a/src/librustc_privacy/Cargo.toml +++ b/src/librustc_privacy/Cargo.toml @@ -14,6 +14,7 @@ rustc_attr = { path = "../librustc_attr" } rustc_errors = { path = "../librustc_errors" } rustc_hir = { path = "../librustc_hir" } rustc_typeck = { path = "../librustc_typeck" } +rustc_session = { path = "../librustc_session" } rustc_ast = { path = "../librustc_ast" } rustc_span = { path = "../librustc_span" } rustc_data_structures = { path = "../librustc_data_structures" } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 175b2390d3083..8734cee366abf 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -5,7 +5,6 @@ use rustc::bug; use rustc::hir::map::Map; -use rustc::lint; use rustc::middle::privacy::{AccessLevel, AccessLevels}; use rustc::ty::fold::TypeVisitor; use rustc::ty::query::Providers; @@ -20,6 +19,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::intravisit::{self, DeepVisitor, NestedVisitorMap, Visitor}; use rustc_hir::{AssocItemKind, HirIdSet, Node, PatKind}; +use rustc_session::lint; use rustc_span::hygiene::Transparency; use rustc_span::symbol::{kw, sym}; use rustc_span::Span; @@ -327,7 +327,7 @@ fn def_id_visibility<'tcx>( } Node::Expr(expr) => { return ( - ty::Visibility::Restricted(tcx.parent_module(expr.hir_id)), + ty::Visibility::Restricted(tcx.parent_module(expr.hir_id).to_def_id()), expr.span, "private", ); @@ -373,8 +373,8 @@ struct PubRestrictedVisitor<'tcx> { impl Visitor<'tcx> for PubRestrictedVisitor<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::All(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::All(self.tcx.hir()) } fn visit_vis(&mut self, vis: &'tcx hir::Visibility<'tcx>) { self.has_pub_restricted = self.has_pub_restricted || vis.node.is_pub_restricted(); @@ -678,8 +678,8 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { /// We want to visit items in the context of their containing /// module and so forth, so supply a crate for doing a deep walk. - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::All(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::All(self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { @@ -920,7 +920,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { } fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) { - if attr::find_transparency(&md.attrs, md.legacy).0 != Transparency::Opaque { + if attr::find_transparency(&md.attrs, md.ast.macro_rules).0 != Transparency::Opaque { self.update(md.hir_id, Some(AccessLevel::Public)); return; } @@ -1023,12 +1023,19 @@ impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> { span: Span, // span of the field pattern, e.g., `x: 0` def: &'tcx ty::AdtDef, // definition of the struct or enum field: &'tcx ty::FieldDef, + in_update_syntax: bool, ) { // definition of the field let ident = Ident::new(kw::Invalid, use_ctxt); let current_hir = self.current_item; let def_id = self.tcx.adjust_ident_and_get_scope(ident, def.did, current_hir).1; if !def.is_enum() && !field.vis.is_accessible_from(def_id, self.tcx) { + let label = if in_update_syntax { + format!("field `{}` is private", field.ident) + } else { + "private field".to_string() + }; + struct_span_err!( self.tcx.sess, span, @@ -1038,7 +1045,7 @@ impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> { def.variant_descr(), self.tcx.def_path_str(def.did) ) - .span_label(span, format!("field `{}` is private", field.ident)) + .span_label(span, label) .emit(); } } @@ -1049,8 +1056,8 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { /// We want to visit items in the context of their containing /// module and so forth, so supply a crate for doing a deep walk. - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::All(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::All(self.tcx.hir()) } fn visit_mod(&mut self, _m: &'tcx hir::Mod<'tcx>, _s: Span, _n: hir::HirId) { @@ -1106,13 +1113,13 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { Some(field) => (field.ident.span, field.span), None => (base.span, base.span), }; - self.check_field(use_ctxt, span, adt, variant_field); + self.check_field(use_ctxt, span, adt, variant_field, true); } } else { for field in fields { let use_ctxt = field.ident.span; let index = self.tcx.field_index(field.hir_id, self.tables); - self.check_field(use_ctxt, field.span, adt, &variant.fields[index]); + self.check_field(use_ctxt, field.span, adt, &variant.fields[index], false); } } } @@ -1131,7 +1138,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { for field in fields { let use_ctxt = field.ident.span; let index = self.tcx.field_index(field.hir_id, self.tables); - self.check_field(use_ctxt, field.span, adt, &variant.fields[index]); + self.check_field(use_ctxt, field.span, adt, &variant.fields[index], false); } } _ => {} @@ -1180,7 +1187,11 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> { fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool { let is_error = !self.item_is_accessible(def_id); if is_error { - self.tcx.sess.span_err(self.span, &format!("{} `{}` is private", kind, descr)); + self.tcx + .sess + .struct_span_err(self.span, &format!("{} `{}` is private", kind, descr)) + .span_label(self.span, &format!("private {}", kind)) + .emit(); } is_error } @@ -1191,8 +1202,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { /// We want to visit items in the context of their containing /// module and so forth, so supply a crate for doing a deep walk. - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::All(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::All(self.tcx.hir()) } fn visit_mod(&mut self, _m: &'tcx hir::Mod<'tcx>, _s: Span, _n: hir::HirId) { @@ -1313,8 +1324,12 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { hir::QPath::Resolved(_, ref path) => path.to_string(), hir::QPath::TypeRelative(_, ref segment) => segment.ident.to_string(), }; - let msg = format!("{} `{}` is private", kind.descr(def_id), name); - self.tcx.sess.span_err(span, &msg); + let kind = kind.descr(def_id); + self.tcx + .sess + .struct_span_err(span, &format!("{} `{}` is private", kind, name)) + .span_label(span, &format!("private {}", kind)) + .emit(); return; } } @@ -1423,7 +1438,7 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { Some(_) | None => false, } } else { - return false; + false } } @@ -1447,9 +1462,9 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } impl<'a, 'b, 'tcx, 'v> Visitor<'v> for ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> { - type Map = Map<'v>; + type Map = intravisit::ErasedMap<'v>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } @@ -1479,8 +1494,8 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { /// We want to visit items in the context of their containing /// module and so forth, so supply a crate for doing a deep walk. - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::All(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::All(self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { @@ -1556,7 +1571,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { || 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(..) => { + hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..) => { self.access_levels.is_reachable(impl_item_ref.id.hir_id) } hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(_) => { @@ -1578,8 +1593,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { // types in private items. let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); match impl_item.kind { - hir::ImplItemKind::Const(..) - | hir::ImplItemKind::Method(..) + hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..) if self .item_is_public(&impl_item.hir_id, &impl_item.vis) => { @@ -1838,7 +1852,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'tcx> { && self.tcx.is_private_dep(item_id.krate); log::debug!("leaks_private_dep(item_id={:?})={}", item_id, ret); - return ret; + ret } } @@ -1925,8 +1939,8 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { diff --git a/src/librustc_query_system/Cargo.toml b/src/librustc_query_system/Cargo.toml new file mode 100644 index 0000000000000..a01bb5e5ea30d --- /dev/null +++ b/src/librustc_query_system/Cargo.toml @@ -0,0 +1,22 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustc_query_system" +version = "0.0.0" +edition = "2018" + +[lib] +name = "rustc_query_system" +path = "lib.rs" +doctest = false + +[dependencies] +log = { version = "0.4", features = ["release_max_level_info", "std"] } +rustc_ast = { path = "../librustc_ast" } +rustc_data_structures = { path = "../librustc_data_structures" } +rustc_errors = { path = "../librustc_errors" } +rustc_hir = { path = "../librustc_hir" } +rustc_index = { path = "../librustc_index" } +rustc_macros = { path = "../librustc_macros" } +rustc_serialize = { path = "../libserialize", package = "serialize" } +parking_lot = "0.9" +smallvec = { version = "1.0", features = ["union", "may_dangle"] } diff --git a/src/librustc/dep_graph/README.md b/src/librustc_query_system/dep_graph/README.md similarity index 100% rename from src/librustc/dep_graph/README.md rename to src/librustc_query_system/dep_graph/README.md diff --git a/src/librustc/dep_graph/debug.rs b/src/librustc_query_system/dep_graph/debug.rs similarity index 89% rename from src/librustc/dep_graph/debug.rs rename to src/librustc_query_system/dep_graph/debug.rs index d44c54593a627..718a2f1039a4d 100644 --- a/src/librustc/dep_graph/debug.rs +++ b/src/librustc_query_system/dep_graph/debug.rs @@ -1,6 +1,6 @@ //! Code for debugging the dep-graph. -use super::dep_node::DepNode; +use super::{DepKind, DepNode}; use std::error::Error; /// A dep-node filter goes from a user-defined string to a query over @@ -26,7 +26,7 @@ impl DepNodeFilter { } /// Tests whether `node` meets the filter, returning true if so. - pub fn test(&self, node: &DepNode) -> bool { + pub fn test(&self, node: &DepNode) -> bool { let debug_str = format!("{:?}", node); self.text.split('&').map(|s| s.trim()).all(|f| debug_str.contains(f)) } @@ -52,7 +52,7 @@ impl EdgeFilter { } } - pub fn test(&self, source: &DepNode, target: &DepNode) -> bool { + pub fn test(&self, source: &DepNode, target: &DepNode) -> bool { self.source.test(source) && self.target.test(target) } } diff --git a/src/librustc_query_system/dep_graph/dep_node.rs b/src/librustc_query_system/dep_graph/dep_node.rs new file mode 100644 index 0000000000000..c6fff2f01643a --- /dev/null +++ b/src/librustc_query_system/dep_graph/dep_node.rs @@ -0,0 +1,146 @@ +//! This module defines the `DepNode` type which the compiler uses to represent +//! nodes in the dependency graph. A `DepNode` consists of a `DepKind` (which +//! specifies the kind of thing it represents, like a piece of HIR, MIR, etc) +//! and a `Fingerprint`, a 128 bit hash value the exact meaning of which +//! depends on the node's `DepKind`. Together, the kind and the fingerprint +//! fully identify a dependency node, even across multiple compilation sessions. +//! In other words, the value of the fingerprint does not depend on anything +//! that is specific to a given compilation session, like an unpredictable +//! interning key (e.g., NodeId, DefId, Symbol) or the numeric value of a +//! pointer. The concept behind this could be compared to how git commit hashes +//! uniquely identify a given commit and has a few advantages: +//! +//! * A `DepNode` can simply be serialized to disk and loaded in another session +//! without the need to do any "rebasing (like we have to do for Spans and +//! NodeIds) or "retracing" like we had to do for `DefId` in earlier +//! implementations of the dependency graph. +//! * A `Fingerprint` is just a bunch of bits, which allows `DepNode` to +//! implement `Copy`, `Sync`, `Send`, `Freeze`, etc. +//! * Since we just have a bit pattern, `DepNode` can be mapped from disk into +//! memory without any post-processing (e.g., "abomination-style" pointer +//! reconstruction). +//! * Because a `DepNode` is self-contained, we can instantiate `DepNodes` that +//! refer to things that do not exist anymore. In previous implementations +//! `DepNode` contained a `DefId`. A `DepNode` referring to something that +//! had been removed between the previous and the current compilation session +//! could not be instantiated because the current compilation session +//! contained no `DefId` for thing that had been removed. +//! +//! `DepNode` definition happens in `librustc` with the `define_dep_nodes!()` macro. +//! This macro defines the `DepKind` enum and a corresponding `DepConstructor` enum. The +//! `DepConstructor` enum links a `DepKind` to the parameters that are needed at runtime in order +//! to construct a valid `DepNode` fingerprint. +//! +//! Because the macro sees what parameters a given `DepKind` requires, it can +//! "infer" some properties for each kind of `DepNode`: +//! +//! * Whether a `DepNode` of a given kind has any parameters at all. Some +//! `DepNode`s could represent global concepts with only one value. +//! * Whether it is possible, in principle, to reconstruct a query key from a +//! given `DepNode`. Many `DepKind`s only require a single `DefId` parameter, +//! in which case it is possible to map the node's fingerprint back to the +//! `DefId` it was computed from. In other cases, too much information gets +//! lost during fingerprint computation. + +use super::{DepContext, DepKind}; + +use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_macros::HashStable_Generic; + +use std::fmt; +use std::hash::Hash; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] +pub struct DepNode { + pub kind: K, + pub hash: Fingerprint, +} + +impl DepNode { + /// Creates a new, parameterless DepNode. This method will assert + /// that the DepNode corresponding to the given DepKind actually + /// does not require any parameters. + pub fn new_no_params(kind: K) -> DepNode { + debug_assert!(!kind.has_params()); + DepNode { kind, hash: Fingerprint::ZERO } + } +} + +impl fmt::Debug for DepNode { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + K::debug_node(self, f) + } +} + +pub trait DepNodeParams: fmt::Debug + Sized { + const CAN_RECONSTRUCT_QUERY_KEY: bool; + + /// This method turns the parameters of a DepNodeConstructor into an opaque + /// Fingerprint to be used in DepNode. + /// Not all DepNodeParams support being turned into a Fingerprint (they + /// don't need to if the corresponding DepNode is anonymous). + fn to_fingerprint(&self, _: Ctxt) -> Fingerprint { + panic!("Not implemented. Accidentally called on anonymous node?") + } + + fn to_debug_str(&self, _: Ctxt) -> String { + format!("{:?}", self) + } + + /// This method tries to recover the query key from the given `DepNode`, + /// something which is needed when forcing `DepNode`s during red-green + /// evaluation. The query system will only call this method if + /// `CAN_RECONSTRUCT_QUERY_KEY` is `true`. + /// It is always valid to return `None` here, in which case incremental + /// compilation will treat the query as having changed instead of forcing it. + fn recover(tcx: Ctxt, dep_node: &DepNode) -> Option; +} + +impl DepNodeParams for T +where + T: HashStable + fmt::Debug, +{ + default const CAN_RECONSTRUCT_QUERY_KEY: bool = false; + + default fn to_fingerprint(&self, tcx: Ctxt) -> Fingerprint { + let mut hcx = tcx.create_stable_hashing_context(); + let mut hasher = StableHasher::new(); + + self.hash_stable(&mut hcx, &mut hasher); + + hasher.finish() + } + + default fn to_debug_str(&self, _: Ctxt) -> String { + format!("{:?}", *self) + } + + default fn recover(_: Ctxt, _: &DepNode) -> Option { + None + } +} + +/// A "work product" corresponds to a `.o` (or other) file that we +/// save in between runs. These IDs do not have a `DefId` but rather +/// some independent path or string that persists between runs without +/// the need to be mapped or unmapped. (This ensures we can serialize +/// them even in the absence of a tcx.) +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] +#[derive(HashStable_Generic)] +pub struct WorkProductId { + hash: Fingerprint, +} + +impl WorkProductId { + pub fn from_cgu_name(cgu_name: &str) -> WorkProductId { + let mut hasher = StableHasher::new(); + cgu_name.len().hash(&mut hasher); + cgu_name.hash(&mut hasher); + WorkProductId { hash: hasher.finish() } + } + + pub fn from_fingerprint(fingerprint: Fingerprint) -> WorkProductId { + WorkProductId { hash: fingerprint } + } +} diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc_query_system/dep_graph/graph.rs similarity index 81% rename from src/librustc/dep_graph/graph.rs rename to src/librustc_query_system/dep_graph/graph.rs index a2dc1fdb34b78..7352551559cf4 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc_query_system/dep_graph/graph.rs @@ -1,32 +1,33 @@ -use crate::ty::{self, TyCtxt}; -use parking_lot::{Condvar, Mutex}; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::profiling::QueryInvocationId; use rustc_data_structures::sharded::{self, Sharded}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, Lrc, Ordering}; +use rustc_data_structures::unlikely; use rustc_errors::Diagnostic; -use rustc_hir::def_id::DefId; use rustc_index::vec::{Idx, IndexVec}; -use smallvec::SmallVec; + +use parking_lot::{Condvar, Mutex}; +use smallvec::{smallvec, SmallVec}; use std::collections::hash_map::Entry; use std::env; use std::hash::Hash; +use std::marker::PhantomData; use std::mem; use std::sync::atomic::Ordering::Relaxed; -use crate::ich::{Fingerprint, StableHashingContext, StableHashingContextProvider}; - use super::debug::EdgeFilter; -use super::dep_node::{DepKind, DepNode, WorkProductId}; use super::prev::PreviousDepGraph; use super::query::DepGraphQuery; use super::safe::DepGraphSafe; use super::serialized::{SerializedDepGraph, SerializedDepNodeIndex}; +use super::{DepContext, DepKind, DepNode, WorkProductId}; +use crate::{HashStableContext, HashStableContextProvider}; #[derive(Clone)] -pub struct DepGraph { - data: Option>, +pub struct DepGraph { + data: Option>>, /// This field is used for assigning DepNodeIndices when running in /// non-incremental mode. Even in non-incremental mode we make sure that @@ -65,16 +66,16 @@ impl DepNodeColor { } } -struct DepGraphData { +struct DepGraphData { /// The new encoding of the dependency graph, optimized for red/green /// tracking. The `current` field is the dependency graph of only the /// current compilation session: We don't merge the previous dep-graph into /// current one anymore. - current: CurrentDepGraph, + current: CurrentDepGraph, /// The dep-graph from the previous compilation session. It contains all /// nodes and edges as well as all fingerprints of nodes that have them. - previous: PreviousDepGraph, + previous: PreviousDepGraph, colors: DepNodeColorMap, @@ -90,12 +91,12 @@ struct DepGraphData { /// this map. We can later look for and extract that data. previous_work_products: FxHashMap, - dep_node_debug: Lock>, + dep_node_debug: Lock, String>>, } -pub fn hash_result(hcx: &mut StableHashingContext<'_>, result: &R) -> Option +pub fn hash_result(hcx: &mut HashCtxt, result: &R) -> Option where - R: for<'a> HashStable>, + R: HashStable, { let mut stable_hasher = StableHasher::new(); result.hash_stable(hcx, &mut stable_hasher); @@ -103,11 +104,11 @@ where Some(stable_hasher.finish()) } -impl DepGraph { +impl DepGraph { pub fn new( - prev_graph: PreviousDepGraph, + prev_graph: PreviousDepGraph, prev_work_products: FxHashMap, - ) -> DepGraph { + ) -> DepGraph { let prev_graph_node_count = prev_graph.node_count(); DepGraph { @@ -124,7 +125,7 @@ impl DepGraph { } } - pub fn new_disabled() -> DepGraph { + pub fn new_disabled() -> DepGraph { DepGraph { data: None, virtual_dep_node_index: Lrc::new(AtomicU32::new(0)) } } @@ -134,7 +135,7 @@ impl DepGraph { self.data.is_some() } - pub fn query(&self) -> DepGraphQuery { + pub fn query(&self) -> DepGraphQuery { let data = self.data.as_ref().unwrap().current.data.lock(); let nodes: Vec<_> = data.iter().map(|n| n.node).collect(); let mut edges = Vec::new(); @@ -150,9 +151,8 @@ impl DepGraph { pub fn assert_ignored(&self) { if let Some(..) = self.data { - ty::tls::with_context_opt(|icx| { - let icx = if let Some(icx) = icx { icx } else { return }; - assert!(icx.task_deps.is_none(), "expected no task dependency tracking"); + K::read_deps(|task_deps| { + assert!(task_deps.is_none(), "expected no task dependency tracking"); }) } } @@ -161,11 +161,7 @@ impl DepGraph { where OP: FnOnce() -> R, { - ty::tls::with_context(|icx| { - let icx = ty::tls::ImplicitCtxt { task_deps: None, ..icx.clone() }; - - ty::tls::enter_context(&icx, |_| op()) - }) + K::with_deps(None, op) } /// Starts a new dep-graph task. Dep-graph tasks are specified @@ -195,16 +191,17 @@ impl DepGraph { /// `arg` parameter. /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/incremental-compilation.html - pub fn with_task<'a, C, A, R>( + pub fn with_task( &self, - key: DepNode, + key: DepNode, cx: C, arg: A, task: fn(C, A) -> R, - hash_result: impl FnOnce(&mut StableHashingContext<'_>, &R) -> Option, + hash_result: impl FnOnce(&mut H, &R) -> Option, ) -> (R, DepNodeIndex) where - C: DepGraphSafe + StableHashingContextProvider<'a>, + C: DepGraphSafe + HashStableContextProvider, + H: HashStableContext, { self.with_task_impl( key, @@ -218,6 +215,7 @@ impl DepGraph { node: Some(_key), reads: SmallVec::new(), read_set: Default::default(), + phantom_data: PhantomData, }) }, |data, key, fingerprint, task| data.complete_task(key, task.unwrap(), fingerprint), @@ -225,49 +223,28 @@ impl DepGraph { ) } - /// Creates a new dep-graph input with value `input` - pub fn input_task<'a, C, R>(&self, key: DepNode, cx: C, input: R) -> (R, DepNodeIndex) - where - C: DepGraphSafe + StableHashingContextProvider<'a>, - R: for<'b> HashStable>, - { - fn identity_fn(_: C, arg: A) -> A { - arg - } - - self.with_task_impl( - key, - cx, - input, - true, - identity_fn, - |_| None, - |data, key, fingerprint, _| data.alloc_node(key, SmallVec::new(), fingerprint), - hash_result::, - ) - } - - fn with_task_impl<'a, C, A, R>( + fn with_task_impl( &self, - key: DepNode, + key: DepNode, cx: C, arg: A, no_tcx: bool, task: fn(C, A) -> R, - create_task: fn(DepNode) -> Option, + create_task: fn(DepNode) -> Option>, finish_task_and_alloc_depnode: fn( - &CurrentDepGraph, - DepNode, + &CurrentDepGraph, + DepNode, Fingerprint, - Option, + Option>, ) -> DepNodeIndex, - hash_result: impl FnOnce(&mut StableHashingContext<'_>, &R) -> Option, + hash_result: impl FnOnce(&mut H, &R) -> Option, ) -> (R, DepNodeIndex) where - C: DepGraphSafe + StableHashingContextProvider<'a>, + C: DepGraphSafe + HashStableContextProvider, + H: HashStableContext, { if let Some(ref data) = self.data { - let task_deps = create_task(key).map(|deps| Lock::new(deps)); + let task_deps = create_task(key).map(Lock::new); // In incremental mode, hash the result of the task. We don't // do anything with the hash yet, but we are computing it @@ -279,12 +256,7 @@ impl DepGraph { let result = if no_tcx { task(cx, arg) } else { - ty::tls::with_context(|icx| { - let icx = - ty::tls::ImplicitCtxt { task_deps: task_deps.as_ref(), ..icx.clone() }; - - ty::tls::enter_context(&icx, |_| task(cx, arg)) - }) + K::with_deps(task_deps.as_ref(), || task(cx, arg)) }; let current_fingerprint = hash_result(&mut hcx, &result); @@ -296,7 +268,7 @@ impl DepGraph { task_deps.map(|lock| lock.into_inner()), ); - let print_status = cfg!(debug_assertions) && hcx.sess().opts.debugging_opts.dep_tasks; + let print_status = cfg!(debug_assertions) && hcx.debug_dep_tasks(); // Determine the color of the new DepNode. if let Some(prev_index) = data.previous.node_to_index_opt(&key) { @@ -344,27 +316,16 @@ impl DepGraph { /// Executes something within an "anonymous" task, that is, a task the /// `DepNode` of which is determined by the list of inputs it read from. - pub fn with_anon_task(&self, dep_kind: DepKind, op: OP) -> (R, DepNodeIndex) + pub fn with_anon_task(&self, dep_kind: K, op: OP) -> (R, DepNodeIndex) where OP: FnOnce() -> R, { if let Some(ref data) = self.data { - let (result, task_deps) = ty::tls::with_context(|icx| { - let task_deps = Lock::new(TaskDeps { - #[cfg(debug_assertions)] - node: None, - reads: SmallVec::new(), - read_set: Default::default(), - }); - - let r = { - let icx = ty::tls::ImplicitCtxt { task_deps: Some(&task_deps), ..icx.clone() }; + let task_deps = Lock::new(TaskDeps::default()); - ty::tls::enter_context(&icx, |_| op()) - }; + let result = K::with_deps(Some(&task_deps), op); + let task_deps = task_deps.into_inner(); - (r, task_deps.into_inner()) - }); let dep_node_index = data.current.complete_anon_task(dep_kind, task_deps); (result, dep_node_index) } else { @@ -374,16 +335,17 @@ impl DepGraph { /// Executes something within an "eval-always" task which is a task /// that runs whenever anything changes. - pub fn with_eval_always_task<'a, C, A, R>( + pub fn with_eval_always_task( &self, - key: DepNode, + key: DepNode, cx: C, arg: A, task: fn(C, A) -> R, - hash_result: impl FnOnce(&mut StableHashingContext<'_>, &R) -> Option, + hash_result: impl FnOnce(&mut H, &R) -> Option, ) -> (R, DepNodeIndex) where - C: DepGraphSafe + StableHashingContextProvider<'a>, + C: DepGraphSafe + HashStableContextProvider, + H: HashStableContext, { self.with_task_impl( key, @@ -398,14 +360,14 @@ impl DepGraph { } #[inline] - pub fn read(&self, v: DepNode) { + pub fn read(&self, v: DepNode) { if let Some(ref data) = self.data { let map = data.current.node_to_node_index.get_shard_by_value(&v).lock(); if let Some(dep_node_index) = map.get(&v).copied() { std::mem::drop(map); data.read_index(dep_node_index); } else { - bug!("DepKind {:?} should be pre-allocated but isn't.", v.kind) + panic!("DepKind {:?} should be pre-allocated but isn't.", v.kind) } } } @@ -418,7 +380,7 @@ impl DepGraph { } #[inline] - pub fn dep_node_index_of(&self, dep_node: &DepNode) -> DepNodeIndex { + pub fn dep_node_index_of(&self, dep_node: &DepNode) -> DepNodeIndex { self.data .as_ref() .unwrap() @@ -432,7 +394,7 @@ impl DepGraph { } #[inline] - pub fn dep_node_exists(&self, dep_node: &DepNode) -> bool { + pub fn dep_node_exists(&self, dep_node: &DepNode) -> bool { if let Some(ref data) = self.data { data.current .node_to_node_index @@ -450,12 +412,12 @@ impl DepGraph { data[dep_node_index].fingerprint } - pub fn prev_fingerprint_of(&self, dep_node: &DepNode) -> Option { + pub fn prev_fingerprint_of(&self, dep_node: &DepNode) -> Option { self.data.as_ref().unwrap().previous.fingerprint_of(dep_node) } #[inline] - pub fn prev_dep_node_index_of(&self, dep_node: &DepNode) -> SerializedDepNodeIndex { + pub fn prev_dep_node_index_of(&self, dep_node: &DepNode) -> SerializedDepNodeIndex { self.data.as_ref().unwrap().previous.node_to_index(dep_node) } @@ -472,7 +434,7 @@ impl DepGraph { } #[inline(always)] - pub fn register_dep_node_debug_str(&self, dep_node: DepNode, debug_str_gen: F) + pub fn register_dep_node_debug_str(&self, dep_node: DepNode, debug_str_gen: F) where F: FnOnce() -> String, { @@ -485,7 +447,7 @@ impl DepGraph { dep_node_debug.borrow_mut().insert(dep_node, debug_str); } - pub(super) fn dep_node_debug_str(&self, dep_node: DepNode) -> Option { + pub fn dep_node_debug_str(&self, dep_node: DepNode) -> Option { self.data.as_ref()?.dep_node_debug.borrow().get(&dep_node).cloned() } @@ -502,7 +464,7 @@ impl DepGraph { } } - pub fn serialize(&self) -> SerializedDepGraph { + pub fn serialize(&self) -> SerializedDepGraph { let data = self.data.as_ref().unwrap().current.data.lock(); let fingerprints: IndexVec = @@ -530,7 +492,7 @@ impl DepGraph { SerializedDepGraph { nodes, fingerprints, edge_list_indices, edge_list_data } } - pub fn node_color(&self, dep_node: &DepNode) -> Option { + pub fn node_color(&self, dep_node: &DepNode) -> Option { if let Some(ref data) = self.data { if let Some(prev_index) = data.previous.node_to_index_opt(dep_node) { return data.colors.get(prev_index); @@ -548,10 +510,10 @@ impl DepGraph { /// A node will have an index, when it's already been marked green, or when we can mark it /// green. This function will mark the current task as a reader of the specified node, when /// a node index can be found for that node. - pub fn try_mark_green_and_read( + pub fn try_mark_green_and_read>( &self, - tcx: TyCtxt<'_>, - dep_node: &DepNode, + tcx: Ctxt, + dep_node: &DepNode, ) -> Option<(SerializedDepNodeIndex, DepNodeIndex)> { self.try_mark_green(tcx, dep_node).map(|(prev_index, dep_node_index)| { debug_assert!(self.is_green(&dep_node)); @@ -560,10 +522,10 @@ impl DepGraph { }) } - pub fn try_mark_green( + pub fn try_mark_green>( &self, - tcx: TyCtxt<'_>, - dep_node: &DepNode, + tcx: Ctxt, + dep_node: &DepNode, ) -> Option<(SerializedDepNodeIndex, DepNodeIndex)> { debug_assert!(!dep_node.kind.is_eval_always()); @@ -588,12 +550,12 @@ impl DepGraph { } /// Try to mark a dep-node which existed in the previous compilation session as green. - fn try_mark_previous_green<'tcx>( + fn try_mark_previous_green>( &self, - tcx: TyCtxt<'tcx>, - data: &DepGraphData, + tcx: Ctxt, + data: &DepGraphData, prev_dep_node_index: SerializedDepNodeIndex, - dep_node: &DepNode, + dep_node: &DepNode, ) -> Option { debug!("try_mark_previous_green({:?}) - BEGIN", dep_node); @@ -675,43 +637,6 @@ impl DepGraph { current_deps.push(node_index); continue; } - } else { - match dep_dep_node.kind { - DepKind::Hir | DepKind::HirBody | DepKind::CrateMetadata => { - if let Some(def_id) = dep_dep_node.extract_def_id(tcx) { - if def_id_corresponds_to_hir_dep_node(tcx, def_id) { - // The `DefPath` has corresponding node, - // and that node should have been marked - // either red or green in `data.colors`. - bug!( - "DepNode {:?} should have been \ - pre-marked as red or green but wasn't.", - dep_dep_node - ); - } else { - // This `DefPath` does not have a - // corresponding `DepNode` (e.g. a - // struct field), and the ` DefPath` - // collided with the `DefPath` of a - // proper item that existed in the - // previous compilation session. - // - // Since the given `DefPath` does not - // denote the item that previously - // existed, we just fail to mark green. - return None; - } - } else { - // If the node does not exist anymore, we - // just fail to mark green. - return None; - } - } - _ => { - // For other kinds of nodes it's OK to be - // forced. - } - } } // We failed to mark it green, so we try to force the query. @@ -720,7 +645,7 @@ impl DepGraph { dependency {:?}", dep_node, dep_dep_node ); - if crate::ty::query::force_from_dep_node(tcx, dep_dep_node) { + if tcx.try_force_from_dep_node(dep_dep_node) { let dep_dep_node_color = data.colors.get(dep_dep_node_index); match dep_dep_node_color { @@ -741,8 +666,8 @@ impl DepGraph { return None; } None => { - if !tcx.sess.has_errors_or_delayed_span_bugs() { - bug!( + if !tcx.has_errors_or_delayed_span_bugs() { + panic!( "try_mark_previous_green() - Forcing the DepNode \ should have set its color" ) @@ -799,7 +724,7 @@ impl DepGraph { // FIXME: Store the fact that a node has diagnostics in a bit in the dep graph somewhere // Maybe store a list on disk and encode this fact in the DepNodeState - let diagnostics = tcx.queries.on_disk_cache.load_diagnostics(tcx, prev_dep_node_index); + let diagnostics = tcx.load_diagnostics(prev_dep_node_index); #[cfg(not(parallel_compiler))] debug_assert!( @@ -825,10 +750,10 @@ impl DepGraph { /// This may be called concurrently on multiple threads for the same dep node. #[cold] #[inline(never)] - fn emit_diagnostics<'tcx>( + fn emit_diagnostics>( &self, - tcx: TyCtxt<'tcx>, - data: &DepGraphData, + tcx: Ctxt, + data: &DepGraphData, dep_node_index: DepNodeIndex, prev_dep_node_index: SerializedDepNodeIndex, diagnostics: Vec, @@ -847,9 +772,9 @@ impl DepGraph { mem::drop(emitting); // Promote the previous diagnostics to the current session. - tcx.queries.on_disk_cache.store_diagnostics(dep_node_index, diagnostics.clone().into()); + tcx.store_diagnostics(dep_node_index, diagnostics.clone().into()); - let handle = tcx.sess.diagnostic(); + let handle = tcx.diagnostic(); for diagnostic in diagnostics { handle.emit_diagnostic(&diagnostic); @@ -878,7 +803,7 @@ impl DepGraph { // Returns true if the given node has been marked as green during the // current compilation session. Used in various assertions - pub fn is_green(&self, dep_node: &DepNode) -> bool { + pub fn is_green(&self, dep_node: &DepNode) -> bool { self.node_color(dep_node).map(|c| c.is_green()).unwrap_or(false) } @@ -890,15 +815,15 @@ impl DepGraph { // // This method will only load queries that will end up in the disk cache. // Other queries will not be executed. - pub fn exec_cache_promotions(&self, tcx: TyCtxt<'_>) { - let _prof_timer = tcx.prof.generic_activity("incr_comp_query_cache_promotion"); + pub fn exec_cache_promotions>(&self, tcx: Ctxt) { + let _prof_timer = tcx.profiler().generic_activity("incr_comp_query_cache_promotion"); let data = self.data.as_ref().unwrap(); for prev_index in data.colors.values.indices() { match data.colors.get(prev_index) { Some(DepNodeColor::Green(_)) => { let dep_node = data.previous.index_to_node(prev_index); - dep_node.try_load_from_on_disk_cache(tcx); + tcx.try_load_from_on_disk_cache(&dep_node); } None | Some(DepNodeColor::Red) => { // We can skip red nodes because a node can only be marked @@ -915,11 +840,6 @@ impl DepGraph { } } -fn def_id_corresponds_to_hir_dep_node(tcx: TyCtxt<'_>, def_id: DefId) -> bool { - let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); - def_id.index == hir_id.owner -} - /// A "work product" is an intermediate result that we save into the /// incremental directory for later re-use. The primary example are /// the object files that we save for each partition at code @@ -966,9 +886,9 @@ pub enum WorkProductFileKind { } #[derive(Clone)] -struct DepNodeData { - node: DepNode, - edges: SmallVec<[DepNodeIndex; 8]>, +struct DepNodeData { + node: DepNode, + edges: EdgesVec, fingerprint: Fingerprint, } @@ -987,9 +907,9 @@ struct DepNodeData { /// The only operation that must manipulate both locks is adding new nodes, in which case /// we first acquire the `node_to_node_index` lock and then, once a new node is to be inserted, /// acquire the lock on `data.` -pub(super) struct CurrentDepGraph { - data: Lock>, - node_to_node_index: Sharded>, +pub(super) struct CurrentDepGraph { + data: Lock>>, + node_to_node_index: Sharded, DepNodeIndex>>, /// Used to trap when a specific edge is added to the graph. /// This is used for debug purposes and is only active with `debug_assertions`. @@ -1015,8 +935,8 @@ pub(super) struct CurrentDepGraph { total_duplicate_read_count: AtomicU64, } -impl CurrentDepGraph { - fn new(prev_graph_node_count: usize) -> CurrentDepGraph { +impl CurrentDepGraph { + fn new(prev_graph_node_count: usize) -> CurrentDepGraph { use std::time::{SystemTime, UNIX_EPOCH}; let duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); @@ -1028,7 +948,7 @@ impl CurrentDepGraph { match env::var("RUST_FORBID_DEP_GRAPH_EDGE") { Ok(s) => match EdgeFilter::new(&s) { Ok(f) => Some(f), - Err(err) => bug!("RUST_FORBID_DEP_GRAPH_EDGE invalid: {}", err), + Err(err) => panic!("RUST_FORBID_DEP_GRAPH_EDGE invalid: {}", err), }, Err(_) => None, } @@ -1059,14 +979,14 @@ impl CurrentDepGraph { fn complete_task( &self, - node: DepNode, - task_deps: TaskDeps, + node: DepNode, + task_deps: TaskDeps, fingerprint: Fingerprint, ) -> DepNodeIndex { self.alloc_node(node, task_deps.reads, fingerprint) } - fn complete_anon_task(&self, kind: DepKind, task_deps: TaskDeps) -> DepNodeIndex { + fn complete_anon_task(&self, kind: K, task_deps: TaskDeps) -> DepNodeIndex { debug_assert!(!kind.is_eval_always()); let mut hasher = StableHasher::new(); @@ -1092,8 +1012,8 @@ impl CurrentDepGraph { fn alloc_node( &self, - dep_node: DepNode, - edges: SmallVec<[DepNodeIndex; 8]>, + dep_node: DepNode, + edges: EdgesVec, fingerprint: Fingerprint, ) -> DepNodeIndex { debug_assert!( @@ -1104,8 +1024,8 @@ impl CurrentDepGraph { fn intern_node( &self, - dep_node: DepNode, - edges: SmallVec<[DepNodeIndex; 8]>, + dep_node: DepNode, + edges: EdgesVec, fingerprint: Fingerprint, ) -> DepNodeIndex { match self.node_to_node_index.get_shard_by_value(&dep_node).lock().entry(dep_node) { @@ -1121,18 +1041,31 @@ impl CurrentDepGraph { } } -impl DepGraphData { +impl DepGraphData { #[inline(never)] fn read_index(&self, source: DepNodeIndex) { - ty::tls::with_context_opt(|icx| { - let icx = if let Some(icx) = icx { icx } else { return }; - if let Some(task_deps) = icx.task_deps { + K::read_deps(|task_deps| { + if let Some(task_deps) = task_deps { let mut task_deps = task_deps.lock(); + let task_deps = &mut *task_deps; if cfg!(debug_assertions) { self.current.total_read_count.fetch_add(1, Relaxed); } - if task_deps.read_set.insert(source) { + + // As long as we only have a low number of reads we can avoid doing a hash + // insert and potentially allocating/reallocating the hashmap + let new_read = if task_deps.reads.len() < TASK_DEPS_READS_CAP { + task_deps.reads.iter().all(|other| *other != source) + } else { + task_deps.read_set.insert(source) + }; + if new_read { task_deps.reads.push(source); + if task_deps.reads.len() == TASK_DEPS_READS_CAP { + // Fill `read_set` with what we have so far so we can use the hashset next + // time + task_deps.read_set.extend(task_deps.reads.iter().copied()); + } #[cfg(debug_assertions)] { @@ -1141,7 +1074,7 @@ impl DepGraphData { if let Some(ref forbidden_edge) = self.current.forbidden_edge { let source = data[source].node; if forbidden_edge.test(&source, &target) { - bug!("forbidden edge {:?} -> {:?} created", source, target) + panic!("forbidden edge {:?} -> {:?} created", source, target) } } } @@ -1154,11 +1087,28 @@ impl DepGraphData { } } -pub struct TaskDeps { +/// The capacity of the `reads` field `SmallVec` +const TASK_DEPS_READS_CAP: usize = 8; +type EdgesVec = SmallVec<[DepNodeIndex; TASK_DEPS_READS_CAP]>; + +pub struct TaskDeps { #[cfg(debug_assertions)] - node: Option, - reads: SmallVec<[DepNodeIndex; 8]>, + node: Option>, + reads: EdgesVec, read_set: FxHashSet, + phantom_data: PhantomData>, +} + +impl Default for TaskDeps { + fn default() -> Self { + Self { + #[cfg(debug_assertions)] + node: None, + reads: EdgesVec::new(), + read_set: FxHashSet::default(), + phantom_data: PhantomData, + } + } } // A data structure that stores Option values as a contiguous diff --git a/src/librustc_query_system/dep_graph/mod.rs b/src/librustc_query_system/dep_graph/mod.rs new file mode 100644 index 0000000000000..825b341cd146d --- /dev/null +++ b/src/librustc_query_system/dep_graph/mod.rs @@ -0,0 +1,75 @@ +pub mod debug; +mod dep_node; +mod graph; +mod prev; +mod query; +mod safe; +mod serialized; + +pub use dep_node::{DepNode, DepNodeParams, WorkProductId}; +pub use graph::WorkProductFileKind; +pub use graph::{hash_result, DepGraph, DepNodeColor, DepNodeIndex, TaskDeps, WorkProduct}; +pub use prev::PreviousDepGraph; +pub use query::DepGraphQuery; +pub use safe::AssertDepGraphSafe; +pub use safe::DepGraphSafe; +pub use serialized::{SerializedDepGraph, SerializedDepNodeIndex}; + +use rustc_data_structures::profiling::SelfProfilerRef; +use rustc_data_structures::sync::Lock; +use rustc_data_structures::thin_vec::ThinVec; +use rustc_errors::Diagnostic; + +use std::fmt; +use std::hash::Hash; + +pub trait DepContext: Copy { + type DepKind: self::DepKind; + type StableHashingContext: crate::HashStableContext; + + /// Create a hashing context for hashing new results. + fn create_stable_hashing_context(&self) -> Self::StableHashingContext; + + /// Try to force a dep node to execute and see if it's green. + fn try_force_from_dep_node(&self, dep_node: &DepNode) -> bool; + + /// Return whether the current session is tainted by errors. + fn has_errors_or_delayed_span_bugs(&self) -> bool; + + /// Return the diagnostic handler. + fn diagnostic(&self) -> &rustc_errors::Handler; + + /// Load data from the on-disk cache. + fn try_load_from_on_disk_cache(&self, dep_node: &DepNode); + + /// Load diagnostics associated to the node in the previous session. + fn load_diagnostics(&self, prev_dep_node_index: SerializedDepNodeIndex) -> Vec; + + /// Register diagnostics for the given node, for use in next session. + fn store_diagnostics(&self, dep_node_index: DepNodeIndex, diagnostics: ThinVec); + + /// Access the profiler. + fn profiler(&self) -> &SelfProfilerRef; +} + +/// Describe the different families of dependency nodes. +pub trait DepKind: Copy + fmt::Debug + Eq + Ord + Hash { + /// Return whether this kind always require evaluation. + fn is_eval_always(&self) -> bool; + + /// Return whether this kind requires additional parameters to be executed. + fn has_params(&self) -> bool; + + /// Implementation of `std::fmt::Debug` for `DepNode`. + fn debug_node(node: &DepNode, f: &mut fmt::Formatter<'_>) -> fmt::Result; + + /// Execute the operation with provided dependencies. + fn with_deps(deps: Option<&Lock>>, op: OP) -> R + where + OP: FnOnce() -> R; + + /// Access dependencies from current implicit context. + fn read_deps(op: OP) -> () + where + OP: for<'a> FnOnce(Option<&'a Lock>>) -> (); +} diff --git a/src/librustc/dep_graph/prev.rs b/src/librustc_query_system/dep_graph/prev.rs similarity index 56% rename from src/librustc/dep_graph/prev.rs rename to src/librustc_query_system/dep_graph/prev.rs index fbc8f7bc997e0..5cba64cac4b34 100644 --- a/src/librustc/dep_graph/prev.rs +++ b/src/librustc_query_system/dep_graph/prev.rs @@ -1,16 +1,22 @@ -use super::dep_node::DepNode; use super::serialized::{SerializedDepGraph, SerializedDepNodeIndex}; -use crate::ich::Fingerprint; +use super::{DepKind, DepNode}; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; -#[derive(Debug, RustcEncodable, RustcDecodable, Default)] -pub struct PreviousDepGraph { - data: SerializedDepGraph, - index: FxHashMap, +#[derive(Debug, RustcEncodable, RustcDecodable)] +pub struct PreviousDepGraph { + data: SerializedDepGraph, + index: FxHashMap, SerializedDepNodeIndex>, } -impl PreviousDepGraph { - pub fn new(data: SerializedDepGraph) -> PreviousDepGraph { +impl Default for PreviousDepGraph { + fn default() -> Self { + PreviousDepGraph { data: Default::default(), index: Default::default() } + } +} + +impl PreviousDepGraph { + pub fn new(data: SerializedDepGraph) -> PreviousDepGraph { let index: FxHashMap<_, _> = data.nodes.iter_enumerated().map(|(idx, &dep_node)| (dep_node, idx)).collect(); PreviousDepGraph { data, index } @@ -25,22 +31,22 @@ impl PreviousDepGraph { } #[inline] - pub fn index_to_node(&self, dep_node_index: SerializedDepNodeIndex) -> DepNode { + pub fn index_to_node(&self, dep_node_index: SerializedDepNodeIndex) -> DepNode { self.data.nodes[dep_node_index] } #[inline] - pub fn node_to_index(&self, dep_node: &DepNode) -> SerializedDepNodeIndex { + pub fn node_to_index(&self, dep_node: &DepNode) -> SerializedDepNodeIndex { self.index[dep_node] } #[inline] - pub fn node_to_index_opt(&self, dep_node: &DepNode) -> Option { + pub fn node_to_index_opt(&self, dep_node: &DepNode) -> Option { self.index.get(dep_node).cloned() } #[inline] - pub fn fingerprint_of(&self, dep_node: &DepNode) -> Option { + pub fn fingerprint_of(&self, dep_node: &DepNode) -> Option { self.index.get(dep_node).map(|&node_index| self.data.fingerprints[node_index]) } diff --git a/src/librustc/dep_graph/query.rs b/src/librustc_query_system/dep_graph/query.rs similarity index 68% rename from src/librustc/dep_graph/query.rs rename to src/librustc_query_system/dep_graph/query.rs index c71c11ed0ebdf..4a4283b2a0cbb 100644 --- a/src/librustc/dep_graph/query.rs +++ b/src/librustc_query_system/dep_graph/query.rs @@ -3,15 +3,15 @@ use rustc_data_structures::graph::implementation::{ Direction, Graph, NodeIndex, INCOMING, OUTGOING, }; -use super::DepNode; +use super::{DepKind, DepNode}; -pub struct DepGraphQuery { - pub graph: Graph, - pub indices: FxHashMap, +pub struct DepGraphQuery { + pub graph: Graph, ()>, + pub indices: FxHashMap, NodeIndex>, } -impl DepGraphQuery { - pub fn new(nodes: &[DepNode], edges: &[(DepNode, DepNode)]) -> DepGraphQuery { +impl DepGraphQuery { + pub fn new(nodes: &[DepNode], edges: &[(DepNode, DepNode)]) -> DepGraphQuery { let mut graph = Graph::with_capacity(nodes.len(), edges.len()); let mut indices = FxHashMap::default(); for node in nodes { @@ -27,15 +27,15 @@ impl DepGraphQuery { DepGraphQuery { graph, indices } } - pub fn contains_node(&self, node: &DepNode) -> bool { + pub fn contains_node(&self, node: &DepNode) -> bool { self.indices.contains_key(&node) } - pub fn nodes(&self) -> Vec<&DepNode> { + pub fn nodes(&self) -> Vec<&DepNode> { self.graph.all_nodes().iter().map(|n| &n.data).collect() } - pub fn edges(&self) -> Vec<(&DepNode, &DepNode)> { + pub fn edges(&self) -> Vec<(&DepNode, &DepNode)> { self.graph .all_edges() .iter() @@ -44,7 +44,7 @@ impl DepGraphQuery { .collect() } - fn reachable_nodes(&self, node: &DepNode, direction: Direction) -> Vec<&DepNode> { + fn reachable_nodes(&self, node: &DepNode, direction: Direction) -> Vec<&DepNode> { if let Some(&index) = self.indices.get(node) { self.graph.depth_traverse(index, direction).map(|s| self.graph.node_data(s)).collect() } else { @@ -54,17 +54,17 @@ impl DepGraphQuery { /// All nodes reachable from `node`. In other words, things that /// will have to be recomputed if `node` changes. - pub fn transitive_successors(&self, node: &DepNode) -> Vec<&DepNode> { + pub fn transitive_successors(&self, node: &DepNode) -> Vec<&DepNode> { self.reachable_nodes(node, OUTGOING) } /// All nodes that can reach `node`. - pub fn transitive_predecessors(&self, node: &DepNode) -> Vec<&DepNode> { + pub fn transitive_predecessors(&self, node: &DepNode) -> Vec<&DepNode> { self.reachable_nodes(node, INCOMING) } /// Just the outgoing edges from `node`. - pub fn immediate_successors(&self, node: &DepNode) -> Vec<&DepNode> { + pub fn immediate_successors(&self, node: &DepNode) -> Vec<&DepNode> { if let Some(&index) = self.indices.get(&node) { self.graph.successor_nodes(index).map(|s| self.graph.node_data(s)).collect() } else { diff --git a/src/librustc_query_system/dep_graph/safe.rs b/src/librustc_query_system/dep_graph/safe.rs new file mode 100644 index 0000000000000..7bba348f8841f --- /dev/null +++ b/src/librustc_query_system/dep_graph/safe.rs @@ -0,0 +1,51 @@ +//! The `DepGraphSafe` trait + +use rustc_ast::ast::NodeId; +use rustc_hir::def_id::DefId; +use rustc_hir::BodyId; + +/// The `DepGraphSafe` trait is used to specify what kinds of values +/// are safe to "leak" into a task. The idea is that this should be +/// only be implemented for things like the tcx as well as various id +/// types, which will create reads in the dep-graph whenever the trait +/// loads anything that might depend on the input program. +pub trait DepGraphSafe {} + +/// A `BodyId` on its own doesn't give access to any particular state. +/// You must fetch the state from the various maps or generate +/// on-demand queries, all of which create reads. +impl DepGraphSafe for BodyId {} + +/// A `NodeId` on its own doesn't give access to any particular state. +/// You must fetch the state from the various maps or generate +/// on-demand queries, all of which create reads. +impl DepGraphSafe for NodeId {} + +/// A `DefId` on its own doesn't give access to any particular state. +/// You must fetch the state from the various maps or generate +/// on-demand queries, all of which create reads. +impl DepGraphSafe for DefId {} + +/// Tuples make it easy to build up state. +impl DepGraphSafe for (A, B) +where + A: DepGraphSafe, + B: DepGraphSafe, +{ +} + +/// Shared ref to dep-graph-safe stuff should still be dep-graph-safe. +impl<'a, A> DepGraphSafe for &'a A where A: DepGraphSafe {} + +/// Mut ref to dep-graph-safe stuff should still be dep-graph-safe. +impl<'a, A> DepGraphSafe for &'a mut A where A: DepGraphSafe {} + +/// No data here! :) +impl DepGraphSafe for () {} + +/// A convenient override that lets you pass arbitrary state into a +/// task. Every use should be accompanied by a comment explaining why +/// it makes sense (or how it could be refactored away in the future). +pub struct AssertDepGraphSafe(pub T); + +impl DepGraphSafe for AssertDepGraphSafe {} diff --git a/src/librustc/dep_graph/serialized.rs b/src/librustc_query_system/dep_graph/serialized.rs similarity index 66% rename from src/librustc/dep_graph/serialized.rs rename to src/librustc_query_system/dep_graph/serialized.rs index 45ef52dbf39c2..4a89da23ea6a5 100644 --- a/src/librustc/dep_graph/serialized.rs +++ b/src/librustc_query_system/dep_graph/serialized.rs @@ -1,7 +1,7 @@ //! The data that we will serialize and deserialize. -use crate::dep_graph::DepNode; -use crate::ich::Fingerprint; +use super::{DepKind, DepNode}; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_index::vec::IndexVec; rustc_index::newtype_index! { @@ -9,10 +9,10 @@ rustc_index::newtype_index! { } /// Data for use when recompiling the **current crate**. -#[derive(Debug, RustcEncodable, RustcDecodable, Default)] -pub struct SerializedDepGraph { +#[derive(Debug, RustcEncodable, RustcDecodable)] +pub struct SerializedDepGraph { /// The set of all DepNodes in the graph - pub nodes: IndexVec, + pub nodes: IndexVec>, /// The set of all Fingerprints in the graph. Each Fingerprint corresponds to /// the DepNode at the same index in the nodes vector. pub fingerprints: IndexVec, @@ -25,7 +25,18 @@ pub struct SerializedDepGraph { pub edge_list_data: Vec, } -impl SerializedDepGraph { +impl Default for SerializedDepGraph { + fn default() -> Self { + SerializedDepGraph { + nodes: Default::default(), + fingerprints: Default::default(), + edge_list_indices: Default::default(), + edge_list_data: Default::default(), + } + } +} + +impl SerializedDepGraph { #[inline] pub fn edge_targets_from(&self, source: SerializedDepNodeIndex) -> &[SerializedDepNodeIndex] { let targets = self.edge_list_indices[source]; diff --git a/src/librustc_query_system/lib.rs b/src/librustc_query_system/lib.rs new file mode 100644 index 0000000000000..ef4886828c411 --- /dev/null +++ b/src/librustc_query_system/lib.rs @@ -0,0 +1,32 @@ +#![feature(const_fn)] +#![feature(const_if_match)] +#![feature(const_panic)] +#![feature(core_intrinsics)] +#![feature(specialization)] +#![feature(stmt_expr_attributes)] + +#[macro_use] +extern crate log; + +pub mod dep_graph; + +pub trait HashStableContext { + fn debug_dep_tasks(&self) -> bool; +} + +/// Something that can provide a stable hashing context. +pub trait HashStableContextProvider { + fn get_stable_hashing_context(&self) -> Ctxt; +} + +impl> HashStableContextProvider for &T { + fn get_stable_hashing_context(&self) -> Ctxt { + (**self).get_stable_hashing_context() + } +} + +impl> HashStableContextProvider for &mut T { + fn get_stable_hashing_context(&self) -> Ctxt { + (**self).get_stable_hashing_context() + } +} diff --git a/src/librustc_resolve/Cargo.toml b/src/librustc_resolve/Cargo.toml index 11a3cedcc74e9..49f079ad27070 100644 --- a/src/librustc_resolve/Cargo.toml +++ b/src/librustc_resolve/Cargo.toml @@ -24,7 +24,6 @@ rustc_errors = { path = "../librustc_errors" } rustc_expand = { path = "../librustc_expand" } rustc_feature = { path = "../librustc_feature" } rustc_hir = { path = "../librustc_hir" } -rustc_infer = { path = "../librustc_infer" } rustc_metadata = { path = "../librustc_metadata" } rustc_session = { path = "../librustc_session" } rustc_span = { path = "../librustc_span" } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 61f511c22e6a1..5408c85a4d006 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -7,7 +7,7 @@ use crate::def_collector::collect_definitions; use crate::imports::{Import, ImportKind}; -use crate::macros::{LegacyBinding, LegacyScope}; +use crate::macros::{MacroRulesBinding, MacroRulesScope}; use crate::Namespace::{self, MacroNS, TypeNS, ValueNS}; use crate::{CrateLint, Determinacy, PathResult, ResolutionError, VisResolutionError}; use crate::{ @@ -165,11 +165,11 @@ impl<'a> Resolver<'a> { &mut self, fragment: &AstFragment, parent_scope: ParentScope<'a>, - ) -> LegacyScope<'a> { + ) -> MacroRulesScope<'a> { collect_definitions(&mut self.definitions, fragment, parent_scope.expansion); let mut visitor = BuildReducedGraphVisitor { r: self, parent_scope }; fragment.visit_with(&mut visitor); - visitor.parent_scope.legacy + visitor.parent_scope.macro_rules } crate fn build_reduced_graph_external(&mut self, module: Module<'a>) { @@ -302,7 +302,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { fn block_needs_anonymous_module(&mut self, block: &Block) -> bool { // If any statements are items, we need to create an anonymous module block.stmts.iter().any(|statement| match statement.kind { - StmtKind::Item(_) | StmtKind::Mac(_) => true, + StmtKind::Item(_) | StmtKind::MacCall(_) => true, _ => false, }) } @@ -624,7 +624,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.r.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }) }; - let used = self.process_legacy_macro_imports(item, module); + let used = self.process_macro_use_imports(item, module); let binding = (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.r.arenas); let import = self.r.arenas.alloc_import(Import { @@ -645,7 +645,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.r.potentially_unused_imports.push(import); let imported_binding = self.r.import(binding, import); if ptr::eq(parent, self.r.graph_root) { - if let Some(entry) = self.r.extern_prelude.get(&ident.modern()) { + if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0()) + { if expansion != ExpnId::root() && orig_name.is_some() && entry.extern_crate_item.is_none() @@ -656,10 +657,12 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } } let entry = - self.r.extern_prelude.entry(ident.modern()).or_insert(ExternPreludeEntry { - extern_crate_item: None, - introduced_by_item: true, - }); + self.r.extern_prelude.entry(ident.normalize_to_macros_2_0()).or_insert( + ExternPreludeEntry { + extern_crate_item: None, + introduced_by_item: true, + }, + ); entry.extern_crate_item = Some(imported_binding); if orig_name.is_some() { entry.introduced_by_item = true; @@ -747,14 +750,16 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { // If this is a tuple or unit struct, define a name // in the value namespace as well. if let Some(ctor_node_id) = vdata.ctor_id() { - let mut ctor_vis = vis; // If the structure is marked as non_exhaustive then lower the visibility // to within the crate. - if vis == ty::Visibility::Public + let mut ctor_vis = if vis == ty::Visibility::Public && attr::contains_name(&item.attrs, sym::non_exhaustive) { - ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); - } + ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)) + } else { + vis + }; + for field in vdata.fields() { // NOTE: The field may be an expansion placeholder, but expansion sets // correct visibilities for unnamed field placeholders specifically, so the @@ -803,7 +808,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { // These items do not add names to modules. ItemKind::Impl { .. } | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {} - ItemKind::MacroDef(..) | ItemKind::Mac(_) => unreachable!(), + ItemKind::MacroDef(..) | ItemKind::MacCall(_) => unreachable!(), } } @@ -819,7 +824,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { ForeignItemKind::TyAlias(..) => { (Res::Def(DefKind::ForeignTy, self.r.definitions.local_def_id(item.id)), TypeNS) } - ForeignItemKind::Macro(_) => unreachable!(), + ForeignItemKind::MacCall(_) => unreachable!(), }; let parent = self.parent_scope.module; let expansion = self.parent_scope.expansion; @@ -899,7 +904,10 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.insert_field_names(def_id, field_names); } Res::Def(DefKind::AssocFn, def_id) => { - if cstore.associated_item_cloned_untracked(def_id).method_has_self_argument { + if cstore + .associated_item_cloned_untracked(def_id, self.r.session) + .method_has_self_argument + { self.r.has_self.insert(def_id); } } @@ -913,7 +921,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } } - fn legacy_import_macro( + fn add_macro_use_binding( &mut self, name: ast::Name, binding: &'a NameBinding<'a>, @@ -929,7 +937,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } /// Returns `true` if we should consider the underlying `extern crate` to be used. - fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>) -> bool { + fn process_macro_use_imports(&mut self, item: &Item, module: Module<'a>) -> bool { let mut import_all = None; let mut single_imports = Vec::new(); for attr in &item.attrs { @@ -1004,7 +1012,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { module.for_each_child(self, |this, ident, ns, binding| { if ns == MacroNS { let imported_binding = this.r.import(binding, import); - this.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing); + this.add_macro_use_binding(ident.name, imported_binding, span, allow_shadowing); } }); } else { @@ -1021,7 +1029,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let import = macro_use_import(self, ident.span); self.r.potentially_unused_imports.push(import); let imported_binding = self.r.import(binding, import); - self.legacy_import_macro( + self.add_macro_use_binding( ident.name, imported_binding, ident.span, @@ -1060,7 +1068,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { false } - fn visit_invoc(&mut self, id: NodeId) -> LegacyScope<'a> { + fn visit_invoc(&mut self, id: NodeId) -> MacroRulesScope<'a> { let invoc_id = id.placeholder_to_expn_id(); self.parent_scope.module.unexpanded_invocations.borrow_mut().insert(invoc_id); @@ -1068,7 +1076,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let old_parent_scope = self.r.invocation_parent_scopes.insert(invoc_id, self.parent_scope); assert!(old_parent_scope.is_none(), "invocation data is reset for an invocation"); - LegacyScope::Invocation(invoc_id) + MacroRulesScope::Invocation(invoc_id) } fn proc_macro_stub(item: &ast::Item) -> Option<(MacroKind, Ident, Span)> { @@ -1095,20 +1103,20 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } } - fn define_macro(&mut self, item: &ast::Item) -> LegacyScope<'a> { + fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScope<'a> { let parent_scope = self.parent_scope; let expansion = parent_scope.expansion; - let (ext, ident, span, is_legacy) = match &item.kind { + let (ext, ident, span, macro_rules) = match &item.kind { ItemKind::MacroDef(def) => { let ext = Lrc::new(self.r.compile_macro(item, self.r.session.edition())); - (ext, item.ident, item.span, def.legacy) + (ext, item.ident, item.span, def.macro_rules) } ItemKind::Fn(..) => match Self::proc_macro_stub(item) { Some((macro_kind, ident, span)) => { self.r.proc_macro_stubs.insert(item.id); (self.r.dummy_ext(macro_kind), ident, span, false) } - None => return parent_scope.legacy, + None => return parent_scope.macro_rules, }, _ => unreachable!(), }; @@ -1118,8 +1126,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.r.macro_map.insert(def_id, ext); self.r.local_macro_def_scopes.insert(item.id, parent_scope.module); - if is_legacy { - let ident = ident.modern(); + if macro_rules { + let ident = ident.normalize_to_macros_2_0(); self.r.macro_names.insert(ident); let is_macro_export = attr::contains_name(&item.attrs, sym::macro_export); let vis = if is_macro_export { @@ -1137,19 +1145,26 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.r.check_reserved_macro_name(ident, res); self.insert_unused_macro(ident, item.id, span); } - LegacyScope::Binding(self.r.arenas.alloc_legacy_binding(LegacyBinding { - parent_legacy_scope: parent_scope.legacy, + MacroRulesScope::Binding(self.r.arenas.alloc_macro_rules_binding(MacroRulesBinding { + parent_macro_rules_scope: parent_scope.macro_rules, binding, ident, })) } else { let module = parent_scope.module; - let vis = self.resolve_visibility(&item.vis); + let vis = match item.kind { + // Visibilities must not be resolved non-speculatively twice + // and we already resolved this one as a `fn` item visibility. + ItemKind::Fn(..) => self + .resolve_visibility_speculative(&item.vis, true) + .unwrap_or(ty::Visibility::Public), + _ => self.resolve_visibility(&item.vis), + }; if vis != ty::Visibility::Public { self.insert_unused_macro(ident, item.id, span); } self.r.define(module, ident, MacroNS, (res, vis, span, expansion)); - self.parent_scope.legacy + self.parent_scope.macro_rules } } } @@ -1163,47 +1178,47 @@ macro_rules! method { visit::$walk(self, node); } } - } + }; } impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { - method!(visit_expr: ast::Expr, ast::ExprKind::Mac, walk_expr); - method!(visit_pat: ast::Pat, ast::PatKind::Mac, walk_pat); - method!(visit_ty: ast::Ty, ast::TyKind::Mac, walk_ty); + method!(visit_expr: ast::Expr, ast::ExprKind::MacCall, walk_expr); + method!(visit_pat: ast::Pat, ast::PatKind::MacCall, walk_pat); + method!(visit_ty: ast::Ty, ast::TyKind::MacCall, walk_ty); fn visit_item(&mut self, item: &'b Item) { let macro_use = match item.kind { ItemKind::MacroDef(..) => { - self.parent_scope.legacy = self.define_macro(item); + self.parent_scope.macro_rules = self.define_macro(item); return; } - ItemKind::Mac(..) => { - self.parent_scope.legacy = self.visit_invoc(item.id); + ItemKind::MacCall(..) => { + self.parent_scope.macro_rules = self.visit_invoc(item.id); return; } ItemKind::Mod(..) => self.contains_macro_use(&item.attrs), _ => false, }; let orig_current_module = self.parent_scope.module; - let orig_current_legacy_scope = self.parent_scope.legacy; + let orig_current_macro_rules_scope = self.parent_scope.macro_rules; self.build_reduced_graph_for_item(item); visit::walk_item(self, item); self.parent_scope.module = orig_current_module; if !macro_use { - self.parent_scope.legacy = orig_current_legacy_scope; + self.parent_scope.macro_rules = orig_current_macro_rules_scope; } } fn visit_stmt(&mut self, stmt: &'b ast::Stmt) { - if let ast::StmtKind::Mac(..) = stmt.kind { - self.parent_scope.legacy = self.visit_invoc(stmt.id); + if let ast::StmtKind::MacCall(..) = stmt.kind { + self.parent_scope.macro_rules = self.visit_invoc(stmt.id); } else { visit::walk_stmt(self, stmt); } } fn visit_foreign_item(&mut self, foreign_item: &'b ForeignItem) { - if let ForeignItemKind::Macro(_) = foreign_item.kind { + if let ForeignItemKind::MacCall(_) = foreign_item.kind { self.visit_invoc(foreign_item.id); return; } @@ -1214,17 +1229,17 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { fn visit_block(&mut self, block: &'b Block) { let orig_current_module = self.parent_scope.module; - let orig_current_legacy_scope = self.parent_scope.legacy; + let orig_current_macro_rules_scope = self.parent_scope.macro_rules; self.build_reduced_graph_for_block(block); visit::walk_block(self, block); self.parent_scope.module = orig_current_module; - self.parent_scope.legacy = orig_current_legacy_scope; + self.parent_scope.macro_rules = orig_current_macro_rules_scope; } fn visit_assoc_item(&mut self, item: &'b AssocItem, ctxt: AssocCtxt) { let parent = self.parent_scope.module; - if let AssocItemKind::Macro(_) = item.kind { + if let AssocItemKind::MacCall(_) = item.kind { self.visit_invoc(item.id); return; } @@ -1246,7 +1261,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { (Res::Def(DefKind::AssocFn, item_def_id), ValueNS) } AssocItemKind::TyAlias(..) => (Res::Def(DefKind::AssocTy, item_def_id), TypeNS), - AssocItemKind::Macro(_) => bug!(), // handled above + AssocItemKind::MacCall(_) => bug!(), // handled above }; let vis = ty::Visibility::Public; @@ -1259,7 +1274,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { fn visit_token(&mut self, t: Token) { if let token::Interpolated(nt) = t.kind { if let token::NtExpr(ref expr) = *nt { - if let ast::ExprKind::Mac(..) = expr.kind { + if let ast::ExprKind::MacCall(..) = expr.kind { self.visit_invoc(expr.id); } } diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index 722f843ab6e7e..35876176e3e4b 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -26,12 +26,13 @@ use crate::imports::ImportKind; use crate::Resolver; -use rustc::{lint, ty}; +use rustc::ty; use rustc_ast::ast; use rustc_ast::node_id::NodeMap; use rustc_ast::visit::{self, Visitor}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::pluralize; +use rustc_session::lint::builtin::{MACRO_USE_EXTERN_CRATE, UNUSED_IMPORTS}; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_span::{MultiSpan, Span, DUMMY_SP}; @@ -232,7 +233,7 @@ impl Resolver<'_> { if let ImportKind::MacroUse = import.kind { if !import.span.is_dummy() { self.lint_buffer.buffer_lint( - lint::builtin::MACRO_USE_EXTERN_CRATE, + MACRO_USE_EXTERN_CRATE, import.id, import.span, "deprecated `#[macro_use]` attribute used to \ @@ -247,9 +248,8 @@ impl Resolver<'_> { self.maybe_unused_extern_crates.push((import.id, import.span)); } ImportKind::MacroUse => { - let lint = lint::builtin::UNUSED_IMPORTS; let msg = "unused `#[macro_use]` import"; - self.lint_buffer.buffer_lint(lint, import.id, import.span, msg); + self.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.id, import.span, msg); } _ => {} } @@ -314,7 +314,7 @@ impl Resolver<'_> { }; visitor.r.lint_buffer.buffer_lint_with_diagnostic( - lint::builtin::UNUSED_IMPORTS, + UNUSED_IMPORTS, unused.use_tree_id, ms, &msg, diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs index 0d276e6861452..6253f183cc444 100644 --- a/src/librustc_resolve/def_collector.rs +++ b/src/librustc_resolve/def_collector.rs @@ -1,10 +1,10 @@ use log::debug; -use rustc::hir::map::definitions::*; use rustc_ast::ast::*; use rustc_ast::token::{self, Token}; -use rustc_ast::visit; +use rustc_ast::visit::{self, FnKind}; use rustc_expand::expand::AstFragment; -use rustc_hir::def_id::DefIndex; +use rustc_hir::def_id::LocalDefId; +use rustc_hir::definitions::*; use rustc_span::hygiene::ExpnId; use rustc_span::symbol::{kw, sym}; use rustc_span::Span; @@ -21,59 +21,23 @@ crate fn collect_definitions( /// Creates `DefId`s for nodes in the AST. struct DefCollector<'a> { definitions: &'a mut Definitions, - parent_def: DefIndex, + parent_def: LocalDefId, expansion: ExpnId, } impl<'a> DefCollector<'a> { - fn create_def(&mut self, node_id: NodeId, data: DefPathData, span: Span) -> DefIndex { + fn create_def(&mut self, node_id: NodeId, data: DefPathData, span: Span) -> LocalDefId { let parent_def = self.parent_def; debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def); self.definitions.create_def_with_parent(parent_def, node_id, data, self.expansion, span) } - fn with_parent(&mut self, parent_def: DefIndex, f: F) { + fn with_parent(&mut self, parent_def: LocalDefId, f: F) { let orig_parent_def = std::mem::replace(&mut self.parent_def, parent_def); f(self); self.parent_def = orig_parent_def; } - fn visit_async_fn( - &mut self, - id: NodeId, - name: Name, - span: Span, - header: &FnHeader, - generics: &'a Generics, - decl: &'a FnDecl, - body: Option<&'a Block>, - ) { - let (closure_id, return_impl_trait_id) = match header.asyncness { - Async::Yes { span: _, closure_id, return_impl_trait_id } => { - (closure_id, return_impl_trait_id) - } - _ => unreachable!(), - }; - - // For async functions, we need to create their inner defs inside of a - // closure to match their desugared representation. - let fn_def_data = DefPathData::ValueNs(name); - let fn_def = self.create_def(id, fn_def_data, span); - return self.with_parent(fn_def, |this| { - this.create_def(return_impl_trait_id, DefPathData::ImplTrait, span); - - visit::walk_generics(this, generics); - visit::walk_fn_decl(this, decl); - - let closure_def = this.create_def(closure_id, DefPathData::ClosureExpr, span); - this.with_parent(closure_def, |this| { - if let Some(body) = body { - visit::walk_block(this, body); - } - }) - }); - } - fn collect_field(&mut self, field: &'a StructField, index: Option) { let index = |this: &Self| { index.unwrap_or_else(|| { @@ -117,22 +81,11 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name), - ItemKind::Fn(_, sig, generics, body) if sig.header.asyncness.is_async() => { - return self.visit_async_fn( - i.id, - i.ident.name, - i.span, - &sig.header, - generics, - &sig.decl, - body.as_deref(), - ); - } ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => { DefPathData::ValueNs(i.ident.name) } ItemKind::MacroDef(..) => DefPathData::MacroNs(i.ident.name), - ItemKind::Mac(..) => return self.visit_macro_invoc(i.id), + ItemKind::MacCall(..) => return self.visit_macro_invoc(i.id), ItemKind::GlobalAsm(..) => DefPathData::Misc, ItemKind::Use(..) => { return visit::walk_item(self, i); @@ -154,13 +107,34 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { }); } + fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) { + if let FnKind::Fn(_, _, sig, _, body) = fn_kind { + if let Async::Yes { closure_id, return_impl_trait_id, .. } = sig.header.asyncness { + self.create_def(return_impl_trait_id, DefPathData::ImplTrait, span); + + // For async functions, we need to create their inner defs inside of a + // closure to match their desugared representation. Besides that, + // we must mirror everything that `visit::walk_fn` below does. + self.visit_fn_header(&sig.header); + visit::walk_fn_decl(self, &sig.decl); + if let Some(body) = body { + let closure_def = self.create_def(closure_id, DefPathData::ClosureExpr, span); + self.with_parent(closure_def, |this| this.visit_block(body)); + } + return; + } + } + + visit::walk_fn(self, fn_kind, span); + } + fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) { self.create_def(id, DefPathData::Misc, use_tree.span); visit::walk_use_tree(self, use_tree, id); } fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) { - if let ForeignItemKind::Macro(_) = foreign_item.kind { + if let ForeignItemKind::MacCall(_) = foreign_item.kind { return self.visit_macro_invoc(foreign_item.id); } @@ -215,22 +189,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) { let def_data = match &i.kind { - AssocItemKind::Fn(_, FnSig { header, decl }, generics, body) - if header.asyncness.is_async() => - { - return self.visit_async_fn( - i.id, - i.ident.name, - i.span, - header, - generics, - decl, - body.as_deref(), - ); - } AssocItemKind::Fn(..) | AssocItemKind::Const(..) => DefPathData::ValueNs(i.ident.name), AssocItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name), - AssocItemKind::Macro(..) => return self.visit_macro_invoc(i.id), + AssocItemKind::MacCall(..) => return self.visit_macro_invoc(i.id), }; let def = self.create_def(i.id, def_data, i.span); @@ -239,7 +200,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_pat(&mut self, pat: &'a Pat) { match pat.kind { - PatKind::Mac(..) => return self.visit_macro_invoc(pat.id), + PatKind::MacCall(..) => self.visit_macro_invoc(pat.id), _ => visit::walk_pat(self, pat), } } @@ -251,7 +212,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_expr(&mut self, expr: &'a Expr) { let parent_def = match expr.kind { - ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id), + ExprKind::MacCall(..) => return self.visit_macro_invoc(expr.id), ExprKind::Closure(_, asyncness, ..) => { // Async closures desugar to closures inside of closures, so // we must create two defs. @@ -274,7 +235,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_ty(&mut self, ty: &'a Ty) { match ty.kind { - TyKind::Mac(..) => return self.visit_macro_invoc(ty.id), + TyKind::MacCall(..) => return self.visit_macro_invoc(ty.id), TyKind::ImplTrait(node_id, _) => { self.create_def(node_id, DefPathData::ImplTrait, ty.span); } @@ -285,7 +246,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_stmt(&mut self, stmt: &'a Stmt) { match stmt.kind { - StmtKind::Mac(..) => self.visit_macro_invoc(stmt.id), + StmtKind::MacCall(..) => self.visit_macro_invoc(stmt.id), _ => visit::walk_stmt(self, stmt), } } @@ -293,7 +254,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_token(&mut self, t: Token) { if let token::Interpolated(nt) = t.kind { if let token::NtExpr(ref expr) = *nt { - if let ExprKind::Mac(..) = expr.kind { + if let ExprKind::MacCall(..) = expr.kind { self.visit_macro_invoc(expr.id); } } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 47a05ec90d42f..78b7e256de217 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -1,8 +1,8 @@ use std::cmp::Reverse; +use std::ptr; use log::debug; use rustc::bug; -use rustc::session::Session; use rustc::ty::{self, DefIdTree}; use rustc_ast::ast::{self, Ident, Path}; use rustc_ast::util::lev_distance::find_best_match_for_name; @@ -13,6 +13,7 @@ use rustc_feature::BUILTIN_ATTRIBUTES; 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}; +use rustc_session::Session; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::SourceMap; use rustc_span::symbol::{kw, Symbol}; @@ -21,7 +22,9 @@ use rustc_span::{BytePos, MultiSpan, Span}; use crate::imports::{Import, ImportKind, ImportResolver}; use crate::path_names_to_string; use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind}; -use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot}; +use crate::{ + BindingError, CrateLint, HasGenericParams, MacroRulesScope, Module, ModuleOrUniformRoot, +}; use crate::{NameBinding, NameBindingKind, PrivacyError, VisResolutionError}; use crate::{ParentScope, PathResult, ResolutionError, Resolver, Scope, ScopeSet, Segment}; @@ -56,8 +59,7 @@ crate struct ImportSuggestion { /// `source_map` functions and this function to something more robust. fn reduce_impl_span_to_impl_keyword(sm: &SourceMap, impl_span: Span) -> Span { let impl_span = sm.span_until_char(impl_span, '<'); - let impl_span = sm.span_until_whitespace(impl_span); - impl_span + sm.span_until_whitespace(impl_span) } impl<'a> Resolver<'a> { @@ -498,12 +500,12 @@ impl<'a> Resolver<'a> { } } } - Scope::MacroRules(legacy_scope) => { - if let LegacyScope::Binding(legacy_binding) = legacy_scope { - let res = legacy_binding.binding.res(); + Scope::MacroRules(macro_rules_scope) => { + if let MacroRulesScope::Binding(macro_rules_binding) = macro_rules_scope { + let res = macro_rules_binding.binding.res(); if filter_fn(res) { suggestions - .push(TypoSuggestion::from_res(legacy_binding.ident.name, res)) + .push(TypoSuggestion::from_res(macro_rules_binding.ident.name, res)) } } } @@ -756,7 +758,7 @@ impl<'a> Resolver<'a> { let msg = format!("unsafe traits like `{}` should be implemented explicitly", ident); err.span_note(ident.span, &msg); } - if self.macro_names.contains(&ident.modern()) { + if self.macro_names.contains(&ident.normalize_to_macros_2_0()) { err.help("have you added the `#[macro_use]` on the module/import?"); } } @@ -789,12 +791,12 @@ impl<'a> Resolver<'a> { _ => Some( self.session .source_map() - .def_span(self.cstore().get_span_untracked(def_id, self.session)), + .guess_head_span(self.cstore().get_span_untracked(def_id, self.session)), ), }); if let Some(span) = def_span { err.span_label( - span, + self.session.source_map().guess_head_span(span), &format!( "similarly named {} `{}` defined here", suggestion.res.descr(), @@ -916,50 +918,81 @@ impl<'a> Resolver<'a> { err.emit(); } - crate fn report_privacy_error(&self, privacy_error: &PrivacyError<'_>) { - let PrivacyError { ident, binding, .. } = *privacy_error; - let session = &self.session; - let mk_struct_span_error = |is_constructor| { - let mut descr = binding.res().descr().to_string(); - if is_constructor { - descr += " constructor"; - } - if binding.is_import() { - descr += " import"; - } - - let mut err = - struct_span_err!(session, ident.span, E0603, "{} `{}` is private", descr, ident); - - err.span_label(ident.span, &format!("this {} is private", descr)); - err.span_note( - session.source_map().def_span(binding.span), - &format!("the {} `{}` is defined here", descr, ident), - ); - - err - }; - - let mut err = if let NameBindingKind::Res( + /// If the binding refers to a tuple struct constructor with fields, + /// returns the span of its fields. + fn ctor_fields_span(&self, binding: &NameBinding<'_>) -> Option { + if let NameBindingKind::Res( Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id), _, ) = binding.kind { let def_id = (&*self).parent(ctor_def_id).expect("no parent for a constructor"); if let Some(fields) = self.field_names.get(&def_id) { - let mut err = mk_struct_span_error(true); let first_field = fields.first().expect("empty field list in the map"); - err.span_label( - fields.iter().fold(first_field.span, |acc, field| acc.to(field.span)), - "a constructor is private if any of the fields is private", - ); - err - } else { - mk_struct_span_error(false) + return Some(fields.iter().fold(first_field.span, |acc, field| acc.to(field.span))); } - } else { - mk_struct_span_error(false) - }; + } + None + } + + crate fn report_privacy_error(&self, privacy_error: &PrivacyError<'_>) { + let PrivacyError { ident, binding, .. } = *privacy_error; + + let res = binding.res(); + let ctor_fields_span = self.ctor_fields_span(binding); + let plain_descr = res.descr().to_string(); + let nonimport_descr = + if ctor_fields_span.is_some() { plain_descr + " constructor" } else { plain_descr }; + let import_descr = nonimport_descr.clone() + " import"; + let get_descr = + |b: &NameBinding<'_>| if b.is_import() { &import_descr } else { &nonimport_descr }; + + // Print the primary message. + let descr = get_descr(binding); + let mut err = + struct_span_err!(self.session, ident.span, E0603, "{} `{}` is private", descr, ident); + err.span_label(ident.span, &format!("private {}", descr)); + if let Some(span) = ctor_fields_span { + err.span_label(span, "a constructor is private if any of the fields is private"); + } + + // Print the whole import chain to make it easier to see what happens. + let first_binding = binding; + let mut next_binding = Some(binding); + let mut next_ident = ident; + while let Some(binding) = next_binding { + let name = next_ident; + next_binding = match binding.kind { + _ if res == Res::Err => None, + NameBindingKind::Import { binding, import, .. } => match import.kind { + _ if binding.span.is_dummy() => None, + ImportKind::Single { source, .. } => { + next_ident = source; + Some(binding) + } + ImportKind::Glob { .. } | ImportKind::MacroUse => Some(binding), + ImportKind::ExternCrate { .. } => None, + }, + _ => None, + }; + + let first = ptr::eq(binding, first_binding); + let descr = get_descr(binding); + let msg = format!( + "{and_refers_to}the {item} `{name}`{which} is defined here{dots}", + and_refers_to = if first { "" } else { "...and refers to " }, + item = descr, + name = name, + which = if first { "" } else { " which" }, + dots = if next_binding.is_some() { "..." } else { "" }, + ); + let def_span = self.session.source_map().guess_head_span(binding.span); + let mut note_span = MultiSpan::from_span(def_span); + if !first && binding.vis == ty::Visibility::Public { + note_span.push_span_label(def_span, "consider importing it directly".into()); + } + err.span_note(note_span, &msg); + } err.emit(); } diff --git a/src/librustc_resolve/imports.rs b/src/librustc_resolve/imports.rs index 485b86636a0ba..8c7ab8f5b1a5a 100644 --- a/src/librustc_resolve/imports.rs +++ b/src/librustc_resolve/imports.rs @@ -10,7 +10,6 @@ use crate::{CrateLint, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet use crate::{NameBinding, NameBindingKind, PathResult, PrivacyError, ToNameBinding}; use rustc::hir::exports::Export; -use rustc::lint::builtin::{PUB_USE_OF_PRIVATE_EXTERN_CRATE, UNUSED_IMPORTS}; use rustc::ty; use rustc::{bug, span_bug}; use rustc_ast::ast::{Ident, Name, NodeId}; @@ -21,6 +20,7 @@ use rustc_data_structures::ptr_key::PtrKey; use rustc_errors::{pluralize, struct_span_err, Applicability}; use rustc_hir::def::{self, PartialRes}; use rustc_hir::def_id::DefId; +use rustc_session::lint::builtin::{PUB_USE_OF_PRIVATE_EXTERN_CRATE, UNUSED_IMPORTS}; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::DiagnosticMessageId; use rustc_span::hygiene::ExpnId; @@ -416,7 +416,8 @@ impl<'a> Resolver<'a> { None => return Err((Undetermined, Weak::Yes)), }; let tmp_parent_scope; - let (mut adjusted_parent_scope, mut ident) = (parent_scope, ident.modern()); + let (mut adjusted_parent_scope, mut ident) = + (parent_scope, ident.normalize_to_macros_2_0()); match ident.span.glob_adjust(module.expansion, glob_import.span) { Some(Some(def)) => { tmp_parent_scope = @@ -873,6 +874,12 @@ impl<'a, 'b> ImportResolver<'a, 'b> { /// consolidate multiple unresolved import errors into a single diagnostic. fn finalize_import(&mut self, import: &'b Import<'b>) -> Option { let orig_vis = import.vis.replace(ty::Visibility::Invisible); + let orig_blacklisted_binding = match &import.kind { + ImportKind::Single { target_bindings, .. } => { + Some(mem::replace(&mut self.r.blacklisted_binding, target_bindings[TypeNS].get())) + } + _ => None, + }; let prev_ambiguity_errors_len = self.r.ambiguity_errors.len(); let path_res = self.r.resolve_path( &import.module_path, @@ -883,6 +890,9 @@ impl<'a, 'b> ImportResolver<'a, 'b> { import.crate_lint(), ); let no_ambiguity = self.r.ambiguity_errors.len() == prev_ambiguity_errors_len; + if let Some(orig_blacklisted_binding) = orig_blacklisted_binding { + self.r.blacklisted_binding = orig_blacklisted_binding; + } import.vis.set(orig_vis); if let PathResult::Failed { .. } | PathResult::NonModule(..) = path_res { // Consider erroneous imports used to avoid duplicate diagnostics. @@ -1107,7 +1117,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { match binding.kind { // Never suggest the name that has binding error // i.e., the name that cannot be previously resolved - NameBindingKind::Res(Res::Err, _) => return None, + NameBindingKind::Res(Res::Err, _) => None, _ => Some(&i.name), } } @@ -1431,7 +1441,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let enum_resolution = resolutions.get(&key).expect("resolution should exist"); let enum_span = enum_resolution.borrow().binding.expect("binding should exist").span; - let enum_def_span = this.session.source_map().def_span(enum_span); + let enum_def_span = this.session.source_map().guess_head_span(enum_span); let enum_def_snippet = this .session .source_map() diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 97f3ad72ee37f..4a3c9f338d903 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -11,7 +11,7 @@ use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding}; use crate::{Module, ModuleOrUniformRoot, NameBindingKind, ParentScope, PathResult}; use crate::{ResolutionError, Resolver, Segment, UseError}; -use rustc::{bug, lint, span_bug}; +use rustc::{bug, span_bug}; use rustc_ast::ast::*; use rustc_ast::ptr::P; use rustc_ast::util::lev_distance::find_best_match_for_name; @@ -23,6 +23,7 @@ use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, PartialRes, PerNS}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_hir::TraitCandidate; +use rustc_session::lint; use rustc_span::symbol::{kw, sym}; use rustc_span::Span; use smallvec::{smallvec, SmallVec}; @@ -449,7 +450,7 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { visit::walk_foreign_item(this, foreign_item); }); } - ForeignItemKind::Macro(..) => { + ForeignItemKind::MacCall(..) => { visit::walk_foreign_item(self, foreign_item); } } @@ -852,7 +853,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { AssocItemKind::TyAlias(_, generics, _, _) => { walk_assoc_item(this, generics, item); } - AssocItemKind::Macro(_) => { + AssocItemKind::MacCall(_) => { panic!("unexpanded macro in resolve!") } }; @@ -897,7 +898,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // do nothing, these are just around to be encoded } - ItemKind::Mac(_) => panic!("unexpanded macro in resolve!"), + ItemKind::MacCall(_) => panic!("unexpanded macro in resolve!"), } } @@ -935,7 +936,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { _ => unreachable!(), }; - let ident = param.ident.modern(); + let ident = param.ident.normalize_to_macros_2_0(); debug!("with_generic_param_rib: {}", param.id); if seen_bindings.contains_key(&ident) { @@ -1174,7 +1175,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { }, ); } - AssocItemKind::Macro(_) => { + AssocItemKind::MacCall(_) => { panic!("unexpanded macro in resolve!") } } @@ -1464,7 +1465,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // Add the binding to the local ribs, if it doesn't already exist in the bindings map. // (We must not add it if it's in the bindings map because that breaks the assumptions // later passes make about or-patterns.) - let ident = ident.modern_and_legacy(); + let ident = ident.normalize_to_macro_rules(); let mut bound_iter = bindings.iter().filter(|(_, set)| set.contains(&ident)); // Already bound in a product pattern? e.g. `(a, a)` which is not allowed. @@ -1517,9 +1518,17 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ident: Ident, has_sub: bool, ) -> Option { - let binding = - self.resolve_ident_in_lexical_scope(ident, ValueNS, None, pat.span)?.item()?; - let res = binding.res(); + let ls_binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None, pat.span)?; + let (res, binding) = match ls_binding { + LexicalScopeBinding::Item(binding) if binding.is_ambiguity() => { + // For ambiguous bindings we don't know all their definitions and cannot check + // whether they can be shadowed by fresh bindings or not, so force an error. + self.r.record_use(ident, ValueNS, binding, false); + return None; + } + LexicalScopeBinding::Item(binding) => (binding.res(), Some(binding)), + LexicalScopeBinding::Res(res) => (res, None), + }; // An immutable (no `mut`) by-value (no `ref`) binding pattern without // a sub pattern (no `@ $pat`) is syntactically ambiguous as it could @@ -1527,11 +1536,15 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { let is_syntactic_ambiguity = !has_sub && bm == BindingMode::ByValue(Mutability::Not); match res { - Res::Def(DefKind::Ctor(_, CtorKind::Const), _) | Res::Def(DefKind::Const, _) + Res::Def(DefKind::Ctor(_, CtorKind::Const), _) + | Res::Def(DefKind::Const, _) + | Res::Def(DefKind::ConstParam, _) if is_syntactic_ambiguity => { // Disambiguate in favor of a unit struct/variant or constant pattern. - self.r.record_use(ident, ValueNS, binding, false); + if let Some(binding) = binding { + self.r.record_use(ident, ValueNS, binding, false); + } Some(res) } Res::Def(DefKind::Ctor(..), _) @@ -1547,23 +1560,20 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ResolutionError::BindingShadowsSomethingUnacceptable( pat_src.descr(), ident.name, - binding, + binding.expect("no binding for a ctor or static"), ), ); None } - Res::Def(DefKind::Fn, _) | Res::Err => { + Res::Def(DefKind::Fn, _) | Res::Local(..) | Res::Err => { // These entities are explicitly allowed to be shadowed by fresh bindings. None } - res => { - span_bug!( - ident.span, - "unexpected resolution for an \ - identifier in pattern: {:?}", - res - ); - } + _ => span_bug!( + ident.span, + "unexpected resolution for an identifier in pattern: {:?}", + res + ), } } @@ -1864,7 +1874,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { self.diagnostic_metadata.unused_labels.insert(id, label.ident.span); } self.with_label_rib(NormalRibKind, |this| { - let ident = label.ident.modern_and_legacy(); + let ident = label.ident.normalize_to_macro_rules(); this.label_ribs.last_mut().unwrap().bindings.insert(ident, id); f(this); }); @@ -1940,7 +1950,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ExprKind::Break(Some(label), _) | ExprKind::Continue(Some(label)) => { let node_id = self.search_label(label.ident, |rib, ident| { - rib.bindings.get(&ident.modern_and_legacy()).cloned() + rib.bindings.get(&ident.normalize_to_macro_rules()).cloned() }); match node_id { None => { @@ -2106,7 +2116,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } } - ident.span = ident.span.modern(); + ident.span = ident.span.normalize_to_macros_2_0(); let mut search_module = self.parent_scope.module; loop { self.get_traits_in_module_containing_item(ident, ns, search_module, &mut found_traits); diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index d1c2c194fca53..a8d4e7ce5f6ba 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -5,7 +5,6 @@ use crate::path_names_to_string; use crate::{CrateLint, Module, ModuleKind, ModuleOrUniformRoot}; use crate::{PathResult, PathSource, Segment}; -use rustc::session::config::nightly_options; use rustc_ast::ast::{self, Expr, ExprKind, Ident, Item, ItemKind, NodeId, Path, Ty, TyKind}; use rustc_ast::util::lev_distance::find_best_match_for_name; use rustc_data_structures::fx::FxHashSet; @@ -15,6 +14,7 @@ use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_hir::PrimTy; +use rustc_session::config::nightly_options; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym}; use rustc_span::Span; @@ -380,7 +380,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { _ => (), } }; - return has_self_arg; + has_self_arg } fn followed_by_brace(&self, span: Span) -> (bool, Option<(Span, String)>) { @@ -430,7 +430,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { break; } } - return (followed_by_brace, closing_brace); + (followed_by_brace, closing_brace) } /// Provides context-dependent help for errors reported by the `smart_resolve_path_fragment` @@ -506,10 +506,10 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { match (res, source) { (Res::Def(DefKind::Macro(MacroKind::Bang), _), _) => { - err.span_suggestion( - span, + err.span_suggestion_verbose( + span.shrink_to_hi(), "use `!` to invoke the macro", - format!("{}!", path_str), + "!".to_string(), Applicability::MaybeIncorrect, ); if path_str == "try" && span.rust_2015() { @@ -1107,11 +1107,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { } }; - match ( - lifetime_names.len(), - lifetime_names.iter().next(), - snippet.as_ref().map(|s| s.as_str()), - ) { + match (lifetime_names.len(), lifetime_names.iter().next(), snippet.as_deref()) { (1, Some(name), Some("&")) => { suggest_existing(err, format!("&{} ", name)); } diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs index 5c0748797f04b..bc843fccc4c71 100644 --- a/src/librustc_resolve/late/lifetimes.rs +++ b/src/librustc_resolve/late/lifetimes.rs @@ -7,7 +7,6 @@ use crate::late::diagnostics::{ForLifetimeSpanType, MissingLifetimeSpot}; use rustc::hir::map::Map; -use rustc::lint; use rustc::middle::resolve_lifetime::*; use rustc::ty::{self, DefIdTree, GenericParamDefKind, TyCtxt}; use rustc::{bug, span_bug}; @@ -18,10 +17,11 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; 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}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{GenericArg, GenericParam, LifetimeName, Node, ParamName, QPath}; use rustc_hir::{GenericParamKind, HirIdMap, HirIdSet, LifetimeParamKind}; +use rustc_session::lint; use rustc_span::symbol::{kw, sym}; use rustc_span::Span; use std::borrow::Cow; @@ -62,7 +62,7 @@ impl RegionExt for Region { let def_id = hir_map.local_def_id(param.hir_id); let origin = LifetimeDefOrigin::from_param(param); debug!("Region::early: index={} def_id={:?}", i, def_id); - (param.name.modern(), Region::EarlyBound(i, def_id, origin)) + (param.name.normalize_to_macros_2_0(), Region::EarlyBound(i, def_id, origin)) } fn late(hir_map: &Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region) { @@ -73,7 +73,7 @@ impl RegionExt for Region { "Region::late: param={:?} depth={:?} def_id={:?} origin={:?}", param, depth, def_id, origin, ); - (param.name.modern(), Region::LateBound(depth, def_id, origin)) + (param.name.normalize_to_macros_2_0(), Region::LateBound(depth, def_id, origin)) } fn late_anon(index: &Cell) -> Region { @@ -133,7 +133,7 @@ impl RegionExt for Region { /// that it corresponds to. /// /// FIXME. This struct gets converted to a `ResolveLifetimes` for -/// actual use. It has the same data, but indexed by `DefIndex`. This +/// actual use. It has the same data, but indexed by `LocalDefId`. This /// is silly. #[derive(Default)] struct NamedRegionMap { @@ -280,25 +280,14 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { *providers = ty::query::Providers { resolve_lifetimes, - named_region_map: |tcx, id| { - let id = LocalDefId::from_def_id(DefId::local(id)); // (*) - tcx.resolve_lifetimes(LOCAL_CRATE).defs.get(&id) - }, - - is_late_bound_map: |tcx, id| { - let id = LocalDefId::from_def_id(DefId::local(id)); // (*) - tcx.resolve_lifetimes(LOCAL_CRATE).late_bound.get(&id) - }, - + named_region_map: |tcx, id| tcx.resolve_lifetimes(LOCAL_CRATE).defs.get(&id), + is_late_bound_map: |tcx, id| tcx.resolve_lifetimes(LOCAL_CRATE).late_bound.get(&id), object_lifetime_defaults_map: |tcx, id| { - let id = LocalDefId::from_def_id(DefId::local(id)); // (*) tcx.resolve_lifetimes(LOCAL_CRATE).object_lifetime_defaults.get(&id) }, ..*providers }; - - // (*) FIXME the query should be defined to take a LocalDefId } /// Computes the `ResolveLifetimes` map that contains data for the @@ -313,15 +302,15 @@ fn resolve_lifetimes(tcx: TyCtxt<'_>, for_krate: CrateNum) -> &ResolveLifetimes let mut rl = ResolveLifetimes::default(); for (hir_id, v) in named_region_map.defs { - let map = rl.defs.entry(hir_id.owner_local_def_id()).or_default(); + let map = rl.defs.entry(hir_id.owner).or_default(); map.insert(hir_id.local_id, v); } for hir_id in named_region_map.late_bound { - let map = rl.late_bound.entry(hir_id.owner_local_def_id()).or_default(); + let map = rl.late_bound.entry(hir_id.owner).or_default(); map.insert(hir_id.local_id); } for (hir_id, v) in named_region_map.object_lifetime_defaults { - let map = rl.object_lifetime_defaults.entry(hir_id.owner_local_def_id()).or_default(); + let map = rl.object_lifetime_defaults.entry(hir_id.owner).or_default(); map.insert(hir_id.local_id, v); } @@ -367,8 +356,8 @@ fn sub_items_have_self_param(node: &hir::ItemKind<'_>) -> bool { impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::All(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::All(self.tcx.hir()) } // We want to nest trait/impl items in their parent, but nothing else. @@ -771,7 +760,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { use self::hir::ImplItemKind::*; self.missing_named_lifetime_spots.push((&impl_item.generics).into()); match impl_item.kind { - Method(ref sig, _) => { + Fn(ref sig, _) => { let tcx = self.tcx; self.visit_early_late( Some(tcx.hir().get_parent_item(impl_item.hir_id)), @@ -1123,9 +1112,9 @@ fn extract_labels(ctxt: &mut LifetimeContext<'_, '_>, body: &hir::Body<'_>) { gather.visit_body(body); impl<'v, 'a, 'tcx> Visitor<'v> for GatherLabels<'a, 'tcx> { - type Map = Map<'v>; + type Map = intravisit::ErasedMap<'v>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } @@ -1174,7 +1163,9 @@ fn extract_labels(ctxt: &mut LifetimeContext<'_, '_>, body: &hir::Body<'_>) { Scope::Binder { ref lifetimes, s, .. } => { // FIXME (#24278): non-hygienic comparison - if let Some(def) = lifetimes.get(&hir::ParamName::Plain(label.modern())) { + if let Some(def) = + lifetimes.get(&hir::ParamName::Plain(label.normalize_to_macros_2_0())) + { let hir_id = tcx.hir().as_local_hir_id(def.id().unwrap()).unwrap(); signal_shadowing_problem( @@ -1253,7 +1244,7 @@ fn object_lifetime_defaults_for_item( fn add_bounds(set: &mut Set1, bounds: &[hir::GenericBound<'_>]) { for bound in bounds { if let hir::GenericBound::Outlives(ref lifetime) = *bound { - set.insert(lifetime.name.modern()); + set.insert(lifetime.name.normalize_to_macros_2_0()); } } } @@ -1466,7 +1457,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } } Node::ImplItem(impl_item) => { - if let hir::ImplItemKind::Method(sig, _) = &impl_item.kind { + if let hir::ImplItemKind::Fn(sig, _) = &impl_item.kind { find_arg_use_span(sig.decl.inputs); } } @@ -1791,7 +1782,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Scope::Binder { ref lifetimes, s, .. } => { match lifetime_ref.name { LifetimeName::Param(param_name) => { - if let Some(&def) = lifetimes.get(¶m_name.modern()) { + if let Some(&def) = lifetimes.get(¶m_name.normalize_to_macros_2_0()) + { break Some(def.shifted(late_depth)); } } @@ -1818,9 +1810,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { | Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) - | Node::ImplItem(&hir::ImplItem { - kind: hir::ImplItemKind::Method(..), .. - }) => { + | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => { let scope = self.tcx.hir().local_def_id(fn_id); def = Region::Free(scope, def.id().unwrap()); } @@ -2100,12 +2090,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { trait_items.iter().find(|ti| ti.id.hir_id == parent).map(|ti| ti.kind); } match *m { - hir::TraitMethod::Required(_) => None, - hir::TraitMethod::Provided(body) => Some(body), + hir::TraitFn::Required(_) => None, + hir::TraitFn::Provided(body) => Some(body), } } - Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Method(_, body), .. }) => { + Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body), .. }) => { if let hir::ItemKind::Impl { ref self_ty, ref items, .. } = self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind { @@ -2172,9 +2162,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } impl<'a> Visitor<'a> for SelfVisitor<'a> { - type Map = Map<'a>; + type Map = intravisit::ErasedMap<'a>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } @@ -2263,9 +2253,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } impl<'v, 'a> Visitor<'v> for GatherLifetimes<'a> { - type Map = Map<'v>; + type Map = intravisit::ErasedMap<'v>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } @@ -2544,7 +2534,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let lifetimes: Vec<_> = params .iter() .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => Some((param, param.name.modern())), + GenericParamKind::Lifetime { .. } => { + Some((param, param.name.normalize_to_macros_2_0())) + } _ => None, }) .collect(); @@ -2661,7 +2653,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } Scope::Binder { ref lifetimes, s, .. } => { - if let Some(&def) = lifetimes.get(¶m.name.modern()) { + if let Some(&def) = lifetimes.get(¶m.name.normalize_to_macros_2_0()) { let hir_id = self.tcx.hir().as_local_hir_id(def.id().unwrap()).unwrap(); signal_shadowing_problem( @@ -2799,7 +2791,7 @@ fn insert_late_bound_lifetimes( // `'a: 'b` means both `'a` and `'b` are referenced appears_in_where_clause .regions - .insert(hir::LifetimeName::Param(param.name.modern())); + .insert(hir::LifetimeName::Param(param.name.normalize_to_macros_2_0())); } } } @@ -2821,7 +2813,7 @@ fn insert_late_bound_lifetimes( hir::GenericParamKind::Type { .. } | hir::GenericParamKind::Const { .. } => continue, } - let lt_name = hir::LifetimeName::Param(param.name.modern()); + let lt_name = hir::LifetimeName::Param(param.name.normalize_to_macros_2_0()); // appears in the where clauses? early-bound. if appears_in_where_clause.regions.contains(<_name) { continue; @@ -2852,9 +2844,9 @@ fn insert_late_bound_lifetimes( } impl<'v> Visitor<'v> for ConstrainedCollector { - type Map = Map<'v>; + type Map = intravisit::ErasedMap<'v>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } @@ -2885,7 +2877,7 @@ fn insert_late_bound_lifetimes( } fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) { - self.regions.insert(lifetime_ref.name.modern()); + self.regions.insert(lifetime_ref.name.normalize_to_macros_2_0()); } } @@ -2895,14 +2887,14 @@ fn insert_late_bound_lifetimes( } impl<'v> Visitor<'v> for AllCollector { - type Map = Map<'v>; + type Map = intravisit::ErasedMap<'v>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) { - self.regions.insert(lifetime_ref.name.modern()); + self.regions.insert(lifetime_ref.name.normalize_to_macros_2_0()); } } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index f035df3c34d3a..9d5121cbad562 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -17,8 +17,6 @@ pub use rustc_hir::def::{Namespace, PerNS}; use Determinacy::*; use rustc::hir::exports::ExportMap; -use rustc::hir::map::{DefKey, Definitions}; -use rustc::lint; use rustc::middle::cstore::{CrateStore, MetadataLoaderDyn}; use rustc::span_bug; use rustc::ty::query::Providers; @@ -38,10 +36,12 @@ use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_expand::base::SyntaxExtension; use rustc_hir::def::Namespace::*; use rustc_hir::def::{self, CtorOf, DefKind, NonMacroAttrKind, PartialRes}; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX}; +use rustc_hir::definitions::{DefKey, Definitions}; use rustc_hir::PrimTy::{self, Bool, Char, Float, Int, Str, Uint}; use rustc_hir::{GlobMap, TraitMap}; use rustc_metadata::creader::{CStore, CrateLoader}; +use rustc_session::lint; use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; use rustc_session::Session; use rustc_span::hygiene::{ExpnId, ExpnKind, MacroKind, SyntaxContext, Transparency}; @@ -58,7 +58,7 @@ use diagnostics::{extend_span_to_previous_binding, find_span_of_binding_until_ne use diagnostics::{ImportSuggestion, Suggestion}; use imports::{Import, ImportKind, ImportResolver, NameResolution}; use late::{HasGenericParams, PathSource, Rib, RibKind::*}; -use macros::{LegacyBinding, LegacyScope}; +use macros::{MacroRulesBinding, MacroRulesScope}; type Res = def::Res; @@ -94,7 +94,7 @@ impl Determinacy { enum Scope<'a> { DeriveHelpers(ExpnId), DeriveHelpersCompat, - MacroRules(LegacyScope<'a>), + MacroRules(MacroRulesScope<'a>), CrateRoot, Module(Module<'a>), RegisteredAttrs, @@ -127,7 +127,7 @@ enum ScopeSet { pub struct ParentScope<'a> { module: Module<'a>, expansion: ExpnId, - legacy: LegacyScope<'a>, + macro_rules: MacroRulesScope<'a>, derives: &'a [ast::Path], } @@ -135,7 +135,12 @@ impl<'a> ParentScope<'a> { /// Creates a parent scope with the passed argument used as the module scope component, /// and other scope components set to default empty values. pub fn module(module: Module<'a>) -> ParentScope<'a> { - ParentScope { module, expansion: ExpnId::root(), legacy: LegacyScope::Empty, derives: &[] } + ParentScope { + module, + expansion: ExpnId::root(), + macro_rules: MacroRulesScope::Empty, + derives: &[], + } } } @@ -323,13 +328,6 @@ enum LexicalScopeBinding<'a> { } impl<'a> LexicalScopeBinding<'a> { - fn item(self) -> Option<&'a NameBinding<'a>> { - match self { - LexicalScopeBinding::Item(binding) => Some(binding), - _ => None, - } - } - fn res(self) -> Res { match self { LexicalScopeBinding::Item(binding) => binding.res(), @@ -426,7 +424,7 @@ impl ModuleKind { /// program) if all but one of them come from glob imports. #[derive(Copy, Clone, PartialEq, Eq, Hash)] struct BindingKey { - /// The identifier for the binding, aways the `modern` version of the + /// The identifier for the binding, aways the `normalize_to_macros_2_0` version of the /// identifier. ident: Ident, ns: Namespace, @@ -620,7 +618,7 @@ enum AmbiguityKind { Import, BuiltinAttr, DeriveHelper, - LegacyVsModern, + MacroRulesVsModularized, GlobVsOuter, GlobVsGlob, GlobVsExpanded, @@ -633,7 +631,9 @@ impl AmbiguityKind { AmbiguityKind::Import => "name vs any other name during import resolution", AmbiguityKind::BuiltinAttr => "built-in attribute vs any other name", AmbiguityKind::DeriveHelper => "derive helper attribute vs any other name", - AmbiguityKind::LegacyVsModern => "`macro_rules` vs non-`macro_rules` from other module", + AmbiguityKind::MacroRulesVsModularized => { + "`macro_rules` vs non-`macro_rules` from other module" + } AmbiguityKind::GlobVsOuter => { "glob import vs any other name from outer scope during import/macro resolution" } @@ -937,9 +937,9 @@ pub struct Resolver<'a> { /// Parent scopes in which the macros were invoked. /// FIXME: `derives` are missing in these parent scopes and need to be taken from elsewhere. invocation_parent_scopes: FxHashMap>, - /// Legacy scopes *produced* by expanding the macro invocations, + /// `macro_rules` scopes *produced* by expanding the macro invocations, /// include all the `macro_rules` items and other invocations generated by them. - output_legacy_scopes: FxHashMap>, + output_macro_rules_scopes: FxHashMap>, /// Helper attributes that are in scope for the given expansion. helper_attrs: FxHashMap>, @@ -972,7 +972,7 @@ pub struct ResolverArenas<'a> { name_bindings: arena::TypedArena>, imports: arena::TypedArena>, name_resolutions: arena::TypedArena>>, - legacy_bindings: arena::TypedArena>, + macro_rules_bindings: arena::TypedArena>, ast_paths: arena::TypedArena, } @@ -996,8 +996,11 @@ impl<'a> ResolverArenas<'a> { fn alloc_name_resolution(&'a self) -> &'a RefCell> { self.name_resolutions.alloc(Default::default()) } - fn alloc_legacy_binding(&'a self, binding: LegacyBinding<'a>) -> &'a LegacyBinding<'a> { - self.legacy_bindings.alloc(binding) + fn alloc_macro_rules_binding( + &'a self, + binding: MacroRulesBinding<'a>, + ) -> &'a MacroRulesBinding<'a> { + self.macro_rules_bindings.alloc(binding) } fn alloc_ast_paths(&'a self, paths: &[ast::Path]) -> &'a [ast::Path] { self.ast_paths.alloc_from_iter(paths.iter().cloned()) @@ -1012,9 +1015,9 @@ impl<'a> AsMut> for Resolver<'a> { impl<'a, 'b> DefIdTree for &'a Resolver<'b> { fn parent(self, id: DefId) -> Option { - match id.krate { - LOCAL_CRATE => self.definitions.def_key(id.index).parent, - _ => self.cstore().def_key(id).parent, + match id.as_local() { + Some(id) => self.definitions.def_key(id).parent, + None => self.cstore().def_key(id).parent, } .map(|index| DefId { index, ..id }) } @@ -1024,7 +1027,11 @@ impl<'a, 'b> DefIdTree for &'a Resolver<'b> { /// the resolver is no longer needed as all the relevant information is inline. impl rustc_ast_lowering::Resolver for Resolver<'_> { fn def_key(&mut self, id: DefId) -> DefKey { - if id.is_local() { self.definitions().def_key(id.index) } else { self.cstore().def_key(id) } + if let Some(id) = id.as_local() { + self.definitions().def_key(id) + } else { + self.cstore().def_key(id) + } } fn item_generics_num_lifetimes(&self, def_id: DefId, sess: &Session) -> usize { @@ -1217,7 +1224,7 @@ impl<'a> Resolver<'a> { dummy_ext_derive: Lrc::new(SyntaxExtension::dummy_derive(session.edition())), non_macro_attrs: [non_macro_attr(false), non_macro_attr(true)], invocation_parent_scopes, - output_legacy_scopes: Default::default(), + output_macro_rules_scopes: Default::default(), helper_attrs: Default::default(), macro_defs, local_macro_def_scopes: FxHashMap::default(), @@ -1359,7 +1366,7 @@ impl<'a> Resolver<'a> { } fn new_key(&mut self, ident: Ident, ns: Namespace) -> BindingKey { - let ident = ident.modern(); + let ident = ident.normalize_to_macros_2_0(); let disambiguator = if ident.name == kw::Underscore { self.underscore_disambiguator += 1; self.underscore_disambiguator @@ -1410,7 +1417,7 @@ impl<'a> Resolver<'a> { // Avoid marking `extern crate` items that refer to a name from extern prelude, // but not introduce it, as used if they are accessed from lexical scope. if is_lexical_scope { - if let Some(entry) = self.extern_prelude.get(&ident.modern()) { + if let Some(entry) = self.extern_prelude.get(&ident.normalize_to_macros_2_0()) { if let Some(crate_item) = entry.extern_crate_item { if ptr::eq(used_binding, crate_item) && !entry.introduced_by_item { return; @@ -1472,7 +1479,7 @@ impl<'a> Resolver<'a> { // derives (you need to resolve the derive first to add helpers into scope), but they // should be available before the derive is expanded for compatibility. // It's mess in general, so we are being conservative for now. - // 1-3. `macro_rules` (open, not controlled), loop through legacy scopes. Have higher + // 1-3. `macro_rules` (open, not controlled), loop through `macro_rules` scopes. Have higher // priority than prelude macros, but create ambiguities with macros in modules. // 1-3. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents // (open, not controlled). Have higher priority than prelude macros, but create @@ -1497,7 +1504,7 @@ impl<'a> Resolver<'a> { TypeNS | ValueNS => Scope::Module(module), MacroNS => Scope::DeriveHelpers(parent_scope.expansion), }; - let mut ident = ident.modern(); + let mut ident = ident.normalize_to_macros_2_0(); let mut use_prelude = !module.no_implicit_prelude; loop { @@ -1537,16 +1544,18 @@ impl<'a> Resolver<'a> { } } Scope::DeriveHelpers(..) => Scope::DeriveHelpersCompat, - Scope::DeriveHelpersCompat => Scope::MacroRules(parent_scope.legacy), - Scope::MacroRules(legacy_scope) => match legacy_scope { - LegacyScope::Binding(binding) => Scope::MacroRules(binding.parent_legacy_scope), - LegacyScope::Invocation(invoc_id) => Scope::MacroRules( - self.output_legacy_scopes + Scope::DeriveHelpersCompat => Scope::MacroRules(parent_scope.macro_rules), + Scope::MacroRules(macro_rules_scope) => match macro_rules_scope { + MacroRulesScope::Binding(binding) => { + Scope::MacroRules(binding.parent_macro_rules_scope) + } + MacroRulesScope::Invocation(invoc_id) => Scope::MacroRules( + self.output_macro_rules_scopes .get(&invoc_id) .cloned() - .unwrap_or(self.invocation_parent_scopes[&invoc_id].legacy), + .unwrap_or(self.invocation_parent_scopes[&invoc_id].macro_rules), ), - LegacyScope::Empty => Scope::Module(module), + MacroRulesScope::Empty => Scope::Module(module), }, Scope::CrateRoot => match ns { TypeNS => { @@ -1617,18 +1626,18 @@ impl<'a> Resolver<'a> { if ident.name == kw::Invalid { return Some(LexicalScopeBinding::Res(Res::Err)); } - let (general_span, modern_span) = if ident.name == kw::SelfUpper { + let (general_span, normalized_span) = if ident.name == kw::SelfUpper { // FIXME(jseyfried) improve `Self` hygiene let empty_span = ident.span.with_ctxt(SyntaxContext::root()); (empty_span, empty_span) } else if ns == TypeNS { - let modern_span = ident.span.modern(); - (modern_span, modern_span) + let normalized_span = ident.span.normalize_to_macros_2_0(); + (normalized_span, normalized_span) } else { - (ident.span.modern_and_legacy(), ident.span.modern()) + (ident.span.normalize_to_macro_rules(), ident.span.normalize_to_macros_2_0()) }; ident.span = general_span; - let modern_ident = Ident { span: modern_span, ..ident }; + let normalized_ident = Ident { span: normalized_span, ..ident }; // Walk backwards up the ribs in scope. let record_used = record_used_id.is_some(); @@ -1636,8 +1645,8 @@ impl<'a> Resolver<'a> { for i in (0..ribs.len()).rev() { debug!("walk rib\n{:?}", ribs[i].bindings); // Use the rib kind to determine whether we are resolving parameters - // (modern hygiene) or local variables (legacy hygiene). - let rib_ident = if ribs[i].kind.contains_params() { modern_ident } else { ident }; + // (macro 2.0 hygiene) or local variables (`macro_rules` hygiene). + let rib_ident = if ribs[i].kind.contains_params() { normalized_ident } else { ident }; if let Some(res) = ribs[i].bindings.get(&rib_ident).cloned() { // The ident resolves to a type parameter or local variable. return Some(LexicalScopeBinding::Res(self.validate_res_from_ribs( @@ -1680,7 +1689,7 @@ impl<'a> Resolver<'a> { } } - ident = modern_ident; + ident = normalized_ident; let mut poisoned = None; loop { let opt_module = if let Some(node_id) = record_used_id { @@ -1849,20 +1858,20 @@ impl<'a> Resolver<'a> { let mut adjusted_parent_scope = parent_scope; match module { ModuleOrUniformRoot::Module(m) => { - if let Some(def) = ident.span.modernize_and_adjust(m.expansion) { + if let Some(def) = ident.span.normalize_to_macros_2_0_and_adjust(m.expansion) { tmp_parent_scope = ParentScope { module: self.macro_def_scope(def), ..*parent_scope }; adjusted_parent_scope = &tmp_parent_scope; } } ModuleOrUniformRoot::ExternPrelude => { - ident.span.modernize_and_adjust(ExpnId::root()); + ident.span.normalize_to_macros_2_0_and_adjust(ExpnId::root()); } ModuleOrUniformRoot::CrateRootAndExternPrelude | ModuleOrUniformRoot::CurrentScope => { // No adjustments } } - let result = self.resolve_ident_in_module_unadjusted_ext( + self.resolve_ident_in_module_unadjusted_ext( module, ident, ns, @@ -1870,8 +1879,7 @@ impl<'a> Resolver<'a> { false, record_used, path_span, - ); - result + ) } fn resolve_crate_root(&mut self, ident: Ident) -> Module<'a> { @@ -1879,14 +1887,14 @@ impl<'a> Resolver<'a> { let mark = if ident.name == kw::DollarCrate { // When resolving `$crate` from a `macro_rules!` invoked in a `macro`, // we don't want to pretend that the `macro_rules!` definition is in the `macro` - // as described in `SyntaxContext::apply_mark`, so we ignore prepended modern marks. + // as described in `SyntaxContext::apply_mark`, so we ignore prepended opaque marks. // FIXME: This is only a guess and it doesn't work correctly for `macro_rules!` // definitions actually produced by `macro` and `macro` definitions produced by // `macro_rules!`, but at least such configurations are not stable yet. - ctxt = ctxt.modern_and_legacy(); + ctxt = ctxt.normalize_to_macro_rules(); let mut iter = ctxt.marks().into_iter().rev().peekable(); let mut result = None; - // Find the last modern mark from the end if it exists. + // Find the last opaque mark from the end if it exists. while let Some(&(mark, transparency)) = iter.peek() { if transparency == Transparency::Opaque { result = Some(mark); @@ -1895,7 +1903,7 @@ impl<'a> Resolver<'a> { break; } } - // Then find the last legacy mark from the end if it exists. + // Then find the last semi-transparent mark from the end if it exists. for (mark, transparency) in iter { if transparency == Transparency::SemiTransparent { result = Some(mark); @@ -1905,7 +1913,7 @@ impl<'a> Resolver<'a> { } result } else { - ctxt = ctxt.modern(); + ctxt = ctxt.normalize_to_macros_2_0(); ctxt.adjust(ExpnId::root()) }; let module = match mark { @@ -1917,7 +1925,7 @@ impl<'a> Resolver<'a> { fn resolve_self(&mut self, ctxt: &mut SyntaxContext, module: Module<'a>) -> Module<'a> { let mut module = self.get_module(module.normal_ancestor_id); - while module.span.ctxt().modern() != *ctxt { + while module.span.ctxt().normalize_to_macros_2_0() != *ctxt { let parent = module.parent.unwrap_or_else(|| self.macro_def_scope(ctxt.remove_mark())); module = self.get_module(parent.normal_ancestor_id); } @@ -1985,7 +1993,7 @@ impl<'a> Resolver<'a> { if ns == TypeNS { if allow_super && name == kw::Super { - let mut ctxt = ident.span.ctxt().modern(); + let mut ctxt = ident.span.ctxt().normalize_to_macros_2_0(); let self_module = match i { 0 => Some(self.resolve_self(&mut ctxt, parent_scope.module)), _ => match module { @@ -2011,7 +2019,7 @@ impl<'a> Resolver<'a> { } if i == 0 { if name == kw::SelfLower { - let mut ctxt = ident.span.ctxt().modern(); + let mut ctxt = ident.span.ctxt().normalize_to_macros_2_0(); module = Some(ModuleOrUniformRoot::Module( self.resolve_self(&mut ctxt, parent_scope.module), )); @@ -2183,11 +2191,8 @@ impl<'a> Resolver<'a> { Applicability::MaybeIncorrect, )), ) - } else if !ident.is_reserved() { - (format!("maybe a missing crate `{}`?", ident), None) } else { - // the parser will already have complained about the keyword being used - return PathResult::NonModule(PartialRes::new(Res::Err)); + (format!("maybe a missing crate `{}`?", ident), None) } } else if i == 0 { (format!("use of undeclared type or module `{}`", ident), None) @@ -2420,21 +2425,21 @@ impl<'a> Resolver<'a> { } } - fn disambiguate_legacy_vs_modern( + fn disambiguate_macro_rules_vs_modularized( &self, - legacy: &'a NameBinding<'a>, - modern: &'a NameBinding<'a>, + macro_rules: &'a NameBinding<'a>, + modularized: &'a NameBinding<'a>, ) -> bool { - // Some non-controversial subset of ambiguities "modern macro name" vs "macro_rules" + // Some non-controversial subset of ambiguities "modularized macro name" vs "macro_rules" // is disambiguated to mitigate regressions from macro modularization. // Scoping for `macro_rules` behaves like scoping for `let` at module level, in general. match ( - self.binding_parent_modules.get(&PtrKey(legacy)), - self.binding_parent_modules.get(&PtrKey(modern)), + self.binding_parent_modules.get(&PtrKey(macro_rules)), + self.binding_parent_modules.get(&PtrKey(modularized)), ) { - (Some(legacy), Some(modern)) => { - legacy.normal_ancestor_id == modern.normal_ancestor_id - && modern.is_ancestor_of(legacy) + (Some(macro_rules), Some(modularized)) => { + macro_rules.normal_ancestor_id == modularized.normal_ancestor_id + && modularized.is_ancestor_of(macro_rules) } _ => false, } @@ -2512,7 +2517,8 @@ impl<'a> Resolver<'a> { false => "defined", }; - let (name, span) = (ident.name, self.session.source_map().def_span(new_binding.span)); + let (name, span) = + (ident.name, self.session.source_map().guess_head_span(new_binding.span)); if let Some(s) = self.name_already_seen.get(&name) { if s == &span { @@ -2553,7 +2559,7 @@ impl<'a> Resolver<'a> { err.span_label(span, format!("`{}` re{} here", name, new_participle)); err.span_label( - self.session.source_map().def_span(old_binding.span), + self.session.source_map().guess_head_span(old_binding.span), format!("previous {} of the {} `{}` here", old_noun, old_kind, name), ); @@ -2764,7 +2770,7 @@ impl<'a> Resolver<'a> { // Make sure `self`, `super` etc produce an error when passed to here. return None; } - self.extern_prelude.get(&ident.modern()).cloned().and_then(|entry| { + self.extern_prelude.get(&ident.normalize_to_macros_2_0()).cloned().and_then(|entry| { if let Some(binding) = entry.extern_crate_item { if !speculative && entry.introduced_by_item { self.record_use(ident, TypeNS, binding, false); @@ -2773,12 +2779,8 @@ impl<'a> Resolver<'a> { } else { let crate_id = if !speculative { self.crate_loader.process_path_extern(ident.name, ident.span) - } else if let Some(crate_id) = - self.crate_loader.maybe_process_path_extern(ident.name, ident.span) - { - crate_id } else { - return None; + self.crate_loader.maybe_process_path_extern(ident.name, ident.span)? }; let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); Some( diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index e11aec906693e..a783cfa4811fd 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -7,9 +7,7 @@ use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy}; use crate::{CrateLint, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Weak}; use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding}; use rustc::middle::stability; -use rustc::session::parse::feature_err; -use rustc::session::Session; -use rustc::{lint, span_bug, ty}; +use rustc::{span_bug, ty}; use rustc_ast::ast::{self, Ident, NodeId}; use rustc_ast_pretty::pprust; use rustc_attr::{self as attr, StabilityLevel}; @@ -21,6 +19,8 @@ use rustc_expand::expand::{AstFragment, AstFragmentKind, Invocation, InvocationK use rustc_feature::is_builtin_attr_name; use rustc_hir::def::{self, DefKind, NonMacroAttrKind}; use rustc_hir::def_id; +use rustc_session::lint::builtin::UNUSED_MACROS; +use rustc_session::Session; use rustc_span::edition::Edition; use rustc_span::hygiene::{self, ExpnData, ExpnId, ExpnKind}; use rustc_span::symbol::{kw, sym, Symbol}; @@ -33,26 +33,26 @@ use std::{mem, ptr}; type Res = def::Res; /// Binding produced by a `macro_rules` item. -/// Not modularized, can shadow previous legacy bindings, etc. +/// Not modularized, can shadow previous `macro_rules` bindings, etc. #[derive(Debug)] -pub struct LegacyBinding<'a> { +pub struct MacroRulesBinding<'a> { crate binding: &'a NameBinding<'a>, - /// Legacy scope into which the `macro_rules` item was planted. - crate parent_legacy_scope: LegacyScope<'a>, + /// `macro_rules` scope into which the `macro_rules` item was planted. + crate parent_macro_rules_scope: MacroRulesScope<'a>, crate ident: Ident, } /// The scope introduced by a `macro_rules!` macro. /// This starts at the macro's definition and ends at the end of the macro's parent /// module (named or unnamed), or even further if it escapes with `#[macro_use]`. -/// Some macro invocations need to introduce legacy scopes too because they +/// Some macro invocations need to introduce `macro_rules` scopes too because they /// can potentially expand into macro definitions. #[derive(Copy, Clone, Debug)] -pub enum LegacyScope<'a> { +pub enum MacroRulesScope<'a> { /// Empty "root" scope at the crate start containing no names. Empty, /// The scope introduced by a `macro_rules!` macro definition. - Binding(&'a LegacyBinding<'a>), + Binding(&'a MacroRulesBinding<'a>), /// The scope introduced by a macro invocation that can potentially /// create a `macro_rules!` macro definition. Invocation(ExpnId), @@ -82,7 +82,7 @@ fn sub_namespace_match(candidate: Option, requirement: Option Symbol { if path.segments.len() == 1 { - return path.segments[0].ident.name; + path.segments[0].ident.name } else { let mut path_str = String::with_capacity(64); for (i, segment) in path.segments.iter().enumerate() { @@ -159,8 +159,8 @@ impl<'a> base::Resolver for Resolver<'a> { // Integrate the new AST fragment into all the definition and module structures. // We are inside the `expansion` now, but other parent scope components are still the same. let parent_scope = ParentScope { expansion, ..self.invocation_parent_scopes[&expansion] }; - let output_legacy_scope = self.build_reduced_graph(fragment, parent_scope); - self.output_legacy_scopes.insert(expansion, output_legacy_scope); + let output_macro_rules_scope = self.build_reduced_graph(fragment, parent_scope); + self.output_macro_rules_scopes.insert(expansion, output_macro_rules_scope); parent_scope.module.unexpanded_invocations.borrow_mut().remove(&expansion); } @@ -258,7 +258,13 @@ impl<'a> base::Resolver for Resolver<'a> { force, ) { Ok((Some(ext), _)) => { - let span = path.segments.last().unwrap().ident.span.modern(); + let span = path + .segments + .last() + .unwrap() + .ident + .span + .normalize_to_macros_2_0(); helper_attrs.extend( ext.helper_attrs.iter().map(|name| Ident::new(*name, span)), ); @@ -323,12 +329,7 @@ impl<'a> base::Resolver for Resolver<'a> { fn check_unused_macros(&mut self) { for (&node_id, &span) in self.unused_macros.iter() { - self.lint_buffer.buffer_lint( - lint::builtin::UNUSED_MACROS, - node_id, - span, - "unused macro definition", - ); + self.lint_buffer.buffer_lint(UNUSED_MACROS, node_id, span, "unused macro definition"); } } @@ -339,6 +340,42 @@ impl<'a> base::Resolver for Resolver<'a> { fn add_derive_copy(&mut self, expn_id: ExpnId) { self.containers_deriving_copy.insert(expn_id); } + + // The function that implements the resolution logic of `#[cfg_accessible(path)]`. + // Returns true if the path can certainly be resolved in one of three namespaces, + // returns false if the path certainly cannot be resolved in any of the three namespaces. + // Returns `Indeterminate` if we cannot give a certain answer yet. + fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result { + let span = path.span; + let path = &Segment::from_path(path); + let parent_scope = self.invocation_parent_scopes[&expn_id]; + + let mut indeterminate = false; + for ns in [TypeNS, ValueNS, MacroNS].iter().copied() { + match self.resolve_path(path, Some(ns), &parent_scope, false, span, CrateLint::No) { + PathResult::Module(ModuleOrUniformRoot::Module(_)) => return Ok(true), + PathResult::NonModule(partial_res) if partial_res.unresolved_segments() == 0 => { + return Ok(true); + } + PathResult::Indeterminate => indeterminate = true, + // FIXME: `resolve_path` is not ready to report partially resolved paths + // correctly, so we just report an error if the path was reported as unresolved. + // This needs to be fixed for `cfg_accessible` to be useful. + PathResult::NonModule(..) | PathResult::Failed { .. } => {} + PathResult::Module(_) => panic!("unexpected path resolution"), + } + } + + if indeterminate { + return Err(Indeterminate); + } + + self.session + .struct_span_err(span, "not sure whether the path is accessible or not") + .span_note(span, "`cfg_accessible` is not fully implemented") + .emit(); + Ok(false) + } } impl<'a> Resolver<'a> { @@ -359,20 +396,16 @@ impl<'a> Resolver<'a> { Err(Determinacy::Undetermined) => return Err(Indeterminate), }; - // Report errors and enforce feature gates for the resolved macro. - let features = self.session.features_untracked(); + // Report errors for the resolved macro. for segment in &path.segments { if let Some(args) = &segment.args { self.session.span_err(args.span(), "generic arguments in macro path"); } - if kind == MacroKind::Attr - && !features.rustc_attrs - && segment.ident.as_str().starts_with("rustc") - { - let msg = - "attributes starting with `rustc` are reserved for use by the `rustc` compiler"; - feature_err(&self.session.parse_sess, sym::rustc_attrs, segment.ident.span, msg) - .emit(); + if kind == MacroKind::Attr && segment.ident.as_str().starts_with("rustc") { + self.session.span_err( + segment.ident.span, + "attributes starting with `rustc` are reserved for use by the `rustc` compiler", + ); } } @@ -608,12 +641,14 @@ impl<'a> Resolver<'a> { } result } - Scope::MacroRules(legacy_scope) => match legacy_scope { - LegacyScope::Binding(legacy_binding) if ident == legacy_binding.ident => { - Ok((legacy_binding.binding, Flags::MACRO_RULES)) + Scope::MacroRules(macro_rules_scope) => match macro_rules_scope { + MacroRulesScope::Binding(macro_rules_binding) + if ident == macro_rules_binding.ident => + { + Ok((macro_rules_binding.binding, Flags::MACRO_RULES)) } - LegacyScope::Invocation(invoc_id) - if !this.output_legacy_scopes.contains_key(&invoc_id) => + MacroRulesScope::Invocation(invoc_id) + if !this.output_macro_rules_scopes.contains_key(&invoc_id) => { Err(Determinacy::Undetermined) } @@ -759,16 +794,18 @@ impl<'a> Resolver<'a> { Some(AmbiguityKind::DeriveHelper) } else if innermost_flags.contains(Flags::MACRO_RULES) && flags.contains(Flags::MODULE) - && !this - .disambiguate_legacy_vs_modern(innermost_binding, binding) + && !this.disambiguate_macro_rules_vs_modularized( + innermost_binding, + binding, + ) || flags.contains(Flags::MACRO_RULES) && innermost_flags.contains(Flags::MODULE) - && !this.disambiguate_legacy_vs_modern( + && !this.disambiguate_macro_rules_vs_modularized( binding, innermost_binding, ) { - Some(AmbiguityKind::LegacyVsModern) + Some(AmbiguityKind::MacroRulesVsModularized) } else if innermost_binding.is_glob_import() { Some(AmbiguityKind::GlobVsOuter) } else if innermost_binding diff --git a/src/librustc_save_analysis/Cargo.toml b/src/librustc_save_analysis/Cargo.toml index 0f4cc4192b626..de851d9772727 100644 --- a/src/librustc_save_analysis/Cargo.toml +++ b/src/librustc_save_analysis/Cargo.toml @@ -13,7 +13,7 @@ log = "0.4" rustc = { path = "../librustc" } rustc_ast_pretty = { path = "../librustc_ast_pretty" } rustc_data_structures = { path = "../librustc_data_structures" } -rustc_codegen_utils = { path = "../librustc_codegen_utils" } +rustc_session = { path = "../librustc_session" } rustc_hir = { path = "../librustc_hir" } rustc_parse = { path = "../librustc_parse" } serde_json = "1" diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 72c962749c8be..a80c3b72044ef 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -13,7 +13,6 @@ //! DumpVisitor walks the AST and processes it, and Dumper is used for //! recording the output. -use rustc::session::config::Input; use rustc::span_bug; use rustc::ty::{self, DefIdTree, TyCtxt}; use rustc_ast::ast::{self, Attribute, NodeId, PatKind}; @@ -25,6 +24,7 @@ use rustc_ast_pretty::pprust::{bounds_to_string, generic_params_to_string, ty_to use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::{DefKind as HirDefKind, Res}; use rustc_hir::def_id::DefId; +use rustc_session::config::Input; use rustc_span::source_map::{respan, DUMMY_SP}; use rustc_span::*; @@ -1067,7 +1067,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { self.visit_ty(default_ty) } } - ast::AssocItemKind::Macro(_) => {} + ast::AssocItemKind::MacCall(_) => {} } } @@ -1103,7 +1103,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { // trait. self.visit_ty(ty) } - ast::AssocItemKind::Macro(_) => {} + ast::AssocItemKind::MacCall(_) => {} } } @@ -1148,7 +1148,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { let sub_span = path.segments.last().unwrap().ident.span; if !self.span.filter_generated(sub_span) { - let ref_id = self.lookup_def_id(id).map(|id| id_from_def_id(id)); + let ref_id = self.lookup_def_id(id).map(id_from_def_id); let alias_span = alias.map(|i| self.span_from_span(i.span)); let span = self.span_from_span(sub_span); self.dumper.import( @@ -1345,7 +1345,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { walk_list!(self, visit_ty, ty); self.process_generic_params(ty_params, &qualname, item.id); } - Mac(_) => (), + MacCall(_) => (), _ => visit::walk_item(self, item), } } @@ -1549,7 +1549,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { self.dumper.dump_def(&access, var_data); } } - ast::ForeignItemKind::Macro(..) => {} + ast::ForeignItemKind::MacCall(..) => {} } } } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index e4949ea5b4b0a..024633c3b3dec 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -10,18 +10,18 @@ mod sig; use rustc::middle::cstore::ExternCrate; use rustc::middle::privacy::AccessLevels; -use rustc::session::config::{CrateType, Input, OutputType}; use rustc::ty::{self, DefIdTree, TyCtxt}; use rustc::{bug, span_bug}; use rustc_ast::ast::{self, Attribute, NodeId, PatKind, DUMMY_NODE_ID}; use rustc_ast::util::comments::strip_doc_comment_decoration; use rustc_ast::visit::{self, Visitor}; use rustc_ast_pretty::pprust::{self, param_to_string, ty_to_string}; -use rustc_codegen_utils::link::{filename_for_metadata, out_filename}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind as HirDefKind, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::Node; +use rustc_session::config::{CrateType, Input, OutputType}; +use rustc_session::output::{filename_for_metadata, out_filename}; use rustc_span::source_map::Spanned; use rustc_span::*; @@ -174,7 +174,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { } // FIXME(plietar): needs a new DefKind in rls-data ast::ForeignItemKind::TyAlias(..) => None, - ast::ForeignItemKind::Macro(..) => None, + ast::ForeignItemKind::MacCall(..) => None, } } @@ -326,7 +326,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { .as_ref() .and_then(|t| self.lookup_def_id(t.ref_id)) .map(id_from_def_id) - .unwrap_or_else(|| null_id()), + .unwrap_or_else(null_id), }, Impl { id: impl_id, @@ -487,9 +487,9 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { qualname, // FIXME you get better data here by using the visitor. value: String::new(), - parent: parent_scope.map(|id| id_from_def_id(id)), + parent: parent_scope.map(id_from_def_id), children: vec![], - decl_id: decl_id.map(|id| id_from_def_id(id)), + decl_id: decl_id.map(id_from_def_id), docs, sig: None, attributes: lower_attributes(attributes, self), @@ -534,15 +534,15 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { let variant = &def.non_enum_variant(); filter!(self.span_utils, ident.span); let span = self.span_from_span(ident.span); - return Some(Data::RefData(Ref { + Some(Data::RefData(Ref { kind: RefKind::Variable, span, ref_id: self .tcx .find_field_index(ident, variant) .map(|index| id_from_def_id(variant.fields[index].did)) - .unwrap_or_else(|| null_id()), - })); + .unwrap_or_else(null_id), + })) } ty::Tuple(..) => None, _ => { @@ -590,14 +590,11 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { Some(Data::RefData(Ref { kind: RefKind::Function, span, - ref_id: def_id - .or(decl_id) - .map(|id| id_from_def_id(id)) - .unwrap_or_else(|| null_id()), + ref_id: def_id.or(decl_id).map(id_from_def_id).unwrap_or_else(|| null_id()), })) } ast::ExprKind::Path(_, ref path) => { - self.get_path_data(expr.id, path).map(|d| Data::RefData(d)) + self.get_path_data(expr.id, path).map(Data::RefData) } _ => { // FIXME @@ -794,19 +791,6 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { ExpnKind::Root | ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => return None, }; - // If the callee is an imported macro from an external crate, need to get - // the source span and name from the session, as their spans are localized - // when read in, and no longer correspond to the source. - if let Some(mac) = self.tcx.sess.imported_macro_spans.borrow().get(&callee.def_site) { - let &(ref mac_name, mac_span) = mac; - let mac_span = self.span_from_span(mac_span); - return Some(MacroRef { - span: callsite_span, - qualname: mac_name.clone(), // FIXME: generate the real qualname - callee_span: mac_span, - }); - } - let callee_span = self.span_from_span(callee.def_site); Some(MacroRef { span: callsite_span, @@ -1088,7 +1072,7 @@ fn id_from_def_id(id: DefId) -> rls_data::Id { fn id_from_node_id(id: NodeId, scx: &SaveContext<'_, '_>) -> rls_data::Id { let def_id = scx.tcx.hir().opt_local_def_id_from_node_id(id); - def_id.map(|id| id_from_def_id(id)).unwrap_or_else(|| { + def_id.map(id_from_def_id).unwrap_or_else(|| { // Create a *fake* `DefId` out of a `NodeId` by subtracting the `NodeId` // out of the maximum u32 value. This will work unless you have *billions* // of definitions in a single crate (very unlikely to actually happen). diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 2cffd7f365d82..51434e9333049 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -308,7 +308,7 @@ impl Sig for ast::Ty { | ast::TyKind::Infer | ast::TyKind::Err | ast::TyKind::ImplicitSelf - | ast::TyKind::Mac(_) => Err("Ty"), + | ast::TyKind::MacCall(_) => Err("Ty"), } } } @@ -544,7 +544,7 @@ impl Sig for ast::Item { ast::ItemKind::ExternCrate(_) => Err("extern crate"), // FIXME should implement this (e.g., pub use). ast::ItemKind::Use(_) => Err("import"), - ast::ItemKind::Mac(..) | ast::ItemKind::MacroDef(_) => Err("Macro"), + ast::ItemKind::MacCall(..) | ast::ItemKind::MacroDef(_) => Err("Macro"), } } } @@ -795,7 +795,7 @@ impl Sig for ast::ForeignItem { Ok(Signature { text, defs, refs: vec![] }) } - ast::ForeignItemKind::Macro(..) => Err("macro"), + ast::ForeignItemKind::MacCall(..) => Err("macro"), } } } diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs index 152435206fec4..6620941c44046 100644 --- a/src/librustc_save_analysis/span_utils.rs +++ b/src/librustc_save_analysis/span_utils.rs @@ -1,7 +1,7 @@ use crate::generated_code; -use rustc::session::Session; use rustc_ast::token::{self, TokenKind}; use rustc_parse::lexer::{self, StringReader}; +use rustc_session::Session; use rustc_span::*; #[derive(Clone)] diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs index c273e7fdbf916..663cfa223c7a8 100644 --- a/src/librustc_session/config.rs +++ b/src/librustc_session/config.rs @@ -1140,7 +1140,7 @@ pub fn parse_error_format( _ => {} } - return error_format; + error_format } fn parse_crate_edition(matches: &getopts::Matches) -> Edition { @@ -1286,33 +1286,6 @@ fn check_thread_count(debugging_opts: &DebuggingOptions, error_format: ErrorOutp } } -fn select_incremental_path( - debugging_opts: &DebuggingOptions, - cg: &CodegenOptions, - error_format: ErrorOutputType, -) -> Option { - match (&debugging_opts.incremental, &cg.incremental) { - (Some(path1), Some(path2)) => { - if path1 != path2 { - early_error( - error_format, - &format!( - "conflicting paths for `-Z incremental` and \ - `-C incremental` specified: {} versus {}", - path1, path2 - ), - ); - } else { - Some(path1) - } - } - (Some(path), None) => Some(path), - (None, Some(path)) => Some(path), - (None, None) => None, - } - .map(|m| PathBuf::from(m)) -} - fn collect_print_requests( cg: &mut CodegenOptions, dopts: &mut DebuggingOptions, @@ -1677,7 +1650,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { check_thread_count(&debugging_opts, error_format); - let incremental = select_incremental_path(&debugging_opts, &cg, error_format); + let incremental = cg.incremental.as_ref().map(|m| PathBuf::from(m)); if debugging_opts.profile && incremental.is_some() { early_error( diff --git a/src/librustc_session/lib.rs b/src/librustc_session/lib.rs index 4101c32d547aa..cc4d525d62887 100644 --- a/src/librustc_session/lib.rs +++ b/src/librustc_session/lib.rs @@ -21,3 +21,5 @@ pub mod search_paths; mod session; pub use session::*; + +pub mod output; diff --git a/src/librustc_session/lint.rs b/src/librustc_session/lint.rs index 3b79972ccbf5b..1162cff4e0b2b 100644 --- a/src/librustc_session/lint.rs +++ b/src/librustc_session/lint.rs @@ -1,6 +1,7 @@ pub use self::Level::*; use rustc_ast::node_id::{NodeId, NodeMap}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; +use rustc_errors::{pluralize, Applicability, DiagnosticBuilder}; use rustc_span::edition::Edition; use rustc_span::{sym, symbol::Ident, MultiSpan, Span, Symbol}; @@ -367,3 +368,45 @@ macro_rules! declare_lint_pass { $crate::impl_lint_pass!($name => [$($lint),*]); }; } + +pub fn add_elided_lifetime_in_path_suggestion( + sess: &crate::Session, + db: &mut DiagnosticBuilder<'_>, + n: usize, + path_span: Span, + incl_angl_brckt: bool, + insertion_span: Span, + anon_lts: String, +) { + let (replace_span, suggestion) = if incl_angl_brckt { + (insertion_span, anon_lts) + } else { + // When possible, prefer a suggestion that replaces the whole + // `Path` expression with `Path<'_, T>`, rather than inserting `'_, ` + // at a point (which makes for an ugly/confusing label) + if let Ok(snippet) = sess.source_map().span_to_snippet(path_span) { + // But our spans can get out of whack due to macros; if the place we think + // we want to insert `'_` isn't even within the path expression's span, we + // should bail out of making any suggestion rather than panicking on a + // subtract-with-overflow or string-slice-out-out-bounds (!) + // FIXME: can we do better? + if insertion_span.lo().0 < path_span.lo().0 { + return; + } + let insertion_index = (insertion_span.lo().0 - path_span.lo().0) as usize; + if insertion_index > snippet.len() { + return; + } + let (before, after) = snippet.split_at(insertion_index); + (path_span, format!("{}{}{}", before, anon_lts, after)) + } else { + (insertion_span, anon_lts) + } + }; + db.span_suggestion( + replace_span, + &format!("indicate the anonymous lifetime{}", pluralize!(n)), + suggestion, + Applicability::MachineApplicable, + ); +} diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs index a1ecf4e8528be..72c720d09b0bf 100644 --- a/src/librustc_session/options.rs +++ b/src/librustc_session/options.rs @@ -299,6 +299,9 @@ macro_rules! options { } )* + /// Set a flag to true. Note that it cannot set the flag to false, so + /// using this parser in combination with a flag that defaults to true + /// is useless; the flag will always be true. fn parse_bool(slot: &mut bool, v: Option<&str>) -> bool { match v { Some(..) => false, @@ -786,14 +789,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "support compiling tests with panic=abort"), dep_tasks: bool = (false, parse_bool, [UNTRACKED], "print tasks that execute and the color their dep node gets (requires debug build)"), - incremental: Option = (None, parse_opt_string, [UNTRACKED], - "enable incremental compilation (experimental)"), - incremental_queries: bool = (true, parse_bool, [UNTRACKED], - "enable incremental compilation support for queries (experimental)"), incremental_info: bool = (false, parse_bool, [UNTRACKED], "print high-level information about incremental reuse (or the lack thereof)"), - incremental_dump_hash: bool = (false, parse_bool, [UNTRACKED], - "dump hash information in textual format to stdout"), incremental_verify_ich: bool = (false, parse_bool, [UNTRACKED], "verify incr. comp. hashes of green query instances"), incremental_ignore_spans: bool = (false, parse_bool, [UNTRACKED], @@ -814,12 +811,10 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "for every macro invocation, print its name and arguments"), debug_macros: bool = (false, parse_bool, [TRACKED], "emit line numbers debug info inside macros"), - generate_arange_section: bool = (true, parse_bool, [TRACKED], - "generate DWARF address ranges for faster lookups"), + no_generate_arange_section: bool = (false, parse_bool, [TRACKED], + "don't generate DWARF address ranges that give faster lookups"), keep_hygiene_data: bool = (false, parse_bool, [UNTRACKED], "don't clear the hygiene data after analysis"), - keep_ast: bool = (false, parse_bool, [UNTRACKED], - "keep the AST after lowering it to HIR"), show_span: Option = (None, parse_opt_string, [TRACKED], "show spans for compiler debugging (expr|pat|ty)"), print_type_sizes: bool = (false, parse_bool, [UNTRACKED], @@ -854,8 +849,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "print some statistics about AST and HIR"), always_encode_mir: bool = (false, parse_bool, [TRACKED], "encode MIR of all functions into the crate metadata"), - json_rendered: Option = (None, parse_opt_string, [UNTRACKED], - "describes how to render the `rendered` field of json diagnostics"), unleash_the_miri_inside_of_you: bool = (false, parse_bool, [TRACKED], "take the breaks off const evaluation. NOTE: this is unsound"), osx_rpath_install_name: bool = (false, parse_bool, [TRACKED], @@ -886,8 +879,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "emit diagnostics rather than buffering (breaks NLL error downgrading, sorting)."), polonius: bool = (false, parse_bool, [UNTRACKED], "enable polonius-based borrow-checker"), - codegen_time_graph: bool = (false, parse_bool, [UNTRACKED], - "generate a graphical HTML report of time spent in codegen and LLVM"), thinlto: Option = (None, parse_opt_bool, [TRACKED], "enable ThinLTO when possible"), inline_in_all_cgus: Option = (None, parse_opt_bool, [TRACKED], diff --git a/src/librustc_codegen_utils/link.rs b/src/librustc_session/output.rs similarity index 81% rename from src/librustc_codegen_utils/link.rs rename to src/librustc_session/output.rs index 524fb0a59c2f1..ba3d08cfc7c14 100644 --- a/src/librustc_codegen_utils/link.rs +++ b/src/librustc_session/output.rs @@ -1,5 +1,6 @@ -use rustc::session::config::{self, Input, OutputFilenames, OutputType}; -use rustc::session::Session; +//! Related to out filenames of compilation (e.g. save analysis, binaries). +use crate::config::{self, Input, OutputFilenames, OutputType}; +use crate::Session; use rustc_ast::{ast, attr}; use rustc_span::symbol::sym; use rustc_span::Span; @@ -24,9 +25,9 @@ pub fn out_filename( out_filename } -// Make sure files are writeable. Mac, FreeBSD, and Windows system linkers -// check this already -- however, the Linux linker will happily overwrite a -// read-only file. We should be consistent. +/// Make sure files are writeable. Mac, FreeBSD, and Windows system linkers +/// check this already -- however, the Linux linker will happily overwrite a +/// read-only file. We should be consistent. pub fn check_file_is_writeable(file: &Path, sess: &Session) { if !is_writeable(file) { sess.fatal(&format!( @@ -46,7 +47,7 @@ fn is_writeable(p: &Path) -> bool { pub fn find_crate_name(sess: Option<&Session>, attrs: &[ast::Attribute], input: &Input) -> String { let validate = |s: String, span: Option| { - rustc_metadata::validate_crate_name(sess, &s, span); + validate_crate_name(sess, &s, span); s }; @@ -96,6 +97,36 @@ pub fn find_crate_name(sess: Option<&Session>, attrs: &[ast::Attribute], input: "rust_out".to_string() } +pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option) { + let mut err_count = 0; + { + let mut say = |s: &str| { + match (sp, sess) { + (_, None) => panic!("{}", s), + (Some(sp), Some(sess)) => sess.span_err(sp, s), + (None, Some(sess)) => sess.err(s), + } + err_count += 1; + }; + if s.is_empty() { + say("crate name must not be empty"); + } + for c in s.chars() { + if c.is_alphanumeric() { + continue; + } + if c == '_' { + continue; + } + say(&format!("invalid character `{}` in crate name: `{}`", c, s)); + } + } + + if err_count > 0 { + sess.unwrap().abort_if_errors(); + } +} + pub fn filename_for_metadata( sess: &Session, crate_name: &str, @@ -167,7 +198,9 @@ pub fn invalid_output_for_target(sess: &Session, crate_type: config::CrateType) if !sess.target.target.options.dynamic_linking { return true; } - if sess.crt_static() && !sess.target.target.options.crt_static_allows_dylibs { + if sess.crt_static(Some(crate_type)) + && !sess.target.target.options.crt_static_allows_dylibs + { return true; } } diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs index 8cda95783a8a9..b3d75143c5639 100644 --- a/src/librustc_session/session.rs +++ b/src/librustc_session/session.rs @@ -1,41 +1,30 @@ +use crate::cgu_reuse_tracker::CguReuseTracker; use crate::code_stats::CodeStats; pub use crate::code_stats::{DataTypeKind, FieldInfo, SizeKind, VariantInfo}; - -use crate::cgu_reuse_tracker::CguReuseTracker; -use rustc_data_structures::fingerprint::Fingerprint; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; - use crate::config::{self, OutputType, PrintRequest, Sanitizer, SwitchWithOptPath}; use crate::filesearch; use crate::lint; +use crate::parse::ParseSess; use crate::search_paths::{PathKind, SearchPath}; -use rustc_data_structures::profiling::duration_to_secs_str; -use rustc_errors::ErrorReported; -use rustc_data_structures::base_n; -use rustc_data_structures::impl_stable_hash_via_hash; +pub use rustc_ast::crate_disambiguator::CrateDisambiguator; +use rustc_data_structures::flock; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::jobserver::{self, Client}; +use rustc_data_structures::profiling::{duration_to_secs_str, SelfProfiler, SelfProfilerRef}; use rustc_data_structures::sync::{ self, AtomicU64, AtomicUsize, Lock, Lrc, Once, OneThread, Ordering, Ordering::SeqCst, }; - -use crate::parse::ParseSess; use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitterWriter; -use rustc_errors::emitter::HumanReadableErrorType; -use rustc_errors::emitter::{Emitter, EmitterWriter}; +use rustc_errors::emitter::{Emitter, EmitterWriter, HumanReadableErrorType}; use rustc_errors::json::JsonEmitter; -use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId}; +use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId, ErrorReported}; use rustc_span::edition::Edition; -use rustc_span::source_map; -use rustc_span::{MultiSpan, Span}; - -use rustc_data_structures::flock; -use rustc_data_structures::jobserver::{self, Client}; -use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef}; +use rustc_span::source_map::{self, MultiSpan, Span}; use rustc_target::spec::{PanicStrategy, RelroLevel, Target, TargetTriple}; use std::cell::{self, RefCell}; use std::env; -use std::fmt; use std::io::Write; use std::num::NonZeroU32; use std::path::PathBuf; @@ -103,11 +92,6 @@ pub struct Session { /// The maximum blocks a const expression can evaluate. pub const_eval_limit: Once, - /// Map from imported macro spans (which consist of - /// the localized span for the macro body) to the - /// macro name and definition span in the source crate. - pub imported_macro_spans: OneThread>>, - incr_comp_session: OneThread>, /// Used for incremental compilation tests. Will only be populated if /// `-Zquery-dep-graph` is specified. @@ -166,7 +150,7 @@ pub struct PerfStats { /// Total number of values canonicalized queries constructed. pub queries_canonicalized: AtomicUsize, /// Number of times this query is invoked. - pub normalize_ty_after_erasing_regions: AtomicUsize, + pub normalize_generic_arg_after_erasing_regions: AtomicUsize, /// Number of times this query is invoked. pub normalize_projection_ty: AtomicUsize, } @@ -560,25 +544,34 @@ impl Session { .unwrap_or(self.opts.debug_assertions) } - pub fn crt_static(&self) -> bool { + /// Check whether this compile session and crate type use static crt. + pub fn crt_static(&self, crate_type: Option) -> bool { // If the target does not opt in to crt-static support, use its default. if self.target.target.options.crt_static_respected { - self.crt_static_feature() + self.crt_static_feature(crate_type) } else { self.target.target.options.crt_static_default } } - pub fn crt_static_feature(&self) -> bool { + /// Check whether this compile session and crate type use `crt-static` feature. + pub fn crt_static_feature(&self, crate_type: Option) -> bool { let requested_features = self.opts.cg.target_feature.split(','); let found_negative = requested_features.clone().any(|r| r == "-crt-static"); let found_positive = requested_features.clone().any(|r| r == "+crt-static"); - // If the target we're compiling for requests a static crt by default, - // then see if the `-crt-static` feature was passed to disable that. - // Otherwise if we don't have a static crt by default then see if the - // `+crt-static` feature was passed. - if self.target.target.options.crt_static_default { !found_negative } else { found_positive } + if found_positive || found_negative { + found_positive + } else if crate_type == Some(config::CrateType::ProcMacro) + || crate_type == None && self.opts.crate_types.contains(&config::CrateType::ProcMacro) + { + // FIXME: When crate_type is not available, + // we use compiler options to determine the crate_type. + // We can't check `#![crate_type = "proc-macro"]` here. + false + } else { + self.target.target.options.crt_static_default + } } pub fn must_not_eliminate_frame_pointers(&self) -> bool { @@ -714,8 +707,8 @@ impl Session { self.perf_stats.queries_canonicalized.load(Ordering::Relaxed) ); println!( - "normalize_ty_after_erasing_regions: {}", - self.perf_stats.normalize_ty_after_erasing_regions.load(Ordering::Relaxed) + "normalize_generic_arg_after_erasing_regions: {}", + self.perf_stats.normalize_generic_arg_after_erasing_regions.load(Ordering::Relaxed) ); println!( "normalize_projection_ty: {}", @@ -1080,7 +1073,6 @@ fn build_session_( recursion_limit: Once::new(), type_length_limit: Once::new(), const_eval_limit: Once::new(), - imported_macro_spans: OneThread::new(RefCell::new(FxHashMap::default())), incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)), cgu_reuse_tracker, prof, @@ -1088,7 +1080,7 @@ fn build_session_( symbol_hash_time: Lock::new(Duration::from_secs(0)), decode_def_path_tables_time: Lock::new(Duration::from_secs(0)), queries_canonicalized: AtomicUsize::new(0), - normalize_ty_after_erasing_regions: AtomicUsize::new(0), + normalize_generic_arg_after_erasing_regions: AtomicUsize::new(0), normalize_projection_ty: AtomicUsize::new(0), }, code_stats: Default::default(), @@ -1190,34 +1182,6 @@ fn validate_commandline_args_with_session_available(sess: &Session) { } } -/// Hash value constructed out of all the `-C metadata` arguments passed to the -/// compiler. Together with the crate-name forms a unique global identifier for -/// the crate. -#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy, RustcEncodable, RustcDecodable)] -pub struct CrateDisambiguator(Fingerprint); - -impl CrateDisambiguator { - pub fn to_fingerprint(self) -> Fingerprint { - self.0 - } -} - -impl fmt::Display for CrateDisambiguator { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - let (a, b) = self.0.as_value(); - let as_u128 = a as u128 | ((b as u128) << 64); - f.write_str(&base_n::encode(as_u128, base_n::CASE_INSENSITIVE)) - } -} - -impl From for CrateDisambiguator { - fn from(fingerprint: Fingerprint) -> CrateDisambiguator { - CrateDisambiguator(fingerprint) - } -} - -impl_stable_hash_via_hash!(CrateDisambiguator); - /// Holds data on the current incremental compilation session, if there is one. #[derive(Debug)] pub enum IncrCompSession { diff --git a/src/librustc_span/caching_source_map_view.rs b/src/librustc_span/caching_source_map_view.rs index d6725160a5d02..68b0bd1a57418 100644 --- a/src/librustc_span/caching_source_map_view.rs +++ b/src/librustc_span/caching_source_map_view.rs @@ -99,10 +99,6 @@ impl<'sm> CachingSourceMapView<'sm> { cache_entry.line_end = line_bounds.1; cache_entry.time_stamp = self.time_stamp; - return Some(( - cache_entry.file.clone(), - cache_entry.line_number, - pos - cache_entry.line_start, - )); + Some((cache_entry.file.clone(), cache_entry.line_number, pos - cache_entry.line_start)) } } diff --git a/src/librustc_span/def_id.rs b/src/librustc_span/def_id.rs index 66cdf46bd4e5f..3551220c5c54a 100644 --- a/src/librustc_span/def_id.rs +++ b/src/librustc_span/def_id.rs @@ -1,8 +1,11 @@ use crate::HashStableContext; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::AtomicRef; use rustc_index::vec::Idx; +use rustc_macros::HashStable_Generic; use rustc_serialize::{Decoder, Encoder}; +use std::borrow::Borrow; use std::fmt; use std::{u32, u64}; @@ -22,7 +25,7 @@ pub enum CrateNum { /// Item definitions in the currently-compiled crate would have the `CrateNum` /// `LOCAL_CRATE` in their `DefId`. -pub const LOCAL_CRATE: CrateNum = CrateNum::Index(CrateId::from_u32_const(0)); +pub const LOCAL_CRATE: CrateNum = CrateNum::Index(CrateId::from_u32(0)); impl Idx for CrateNum { #[inline] @@ -102,6 +105,17 @@ impl ::std::fmt::Debug for CrateNum { } } +#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, RustcEncodable, RustcDecodable)] +#[derive(HashStable_Generic)] +pub struct DefPathHash(pub Fingerprint); + +impl Borrow for DefPathHash { + #[inline] + fn borrow(&self) -> &Fingerprint { + &self.0 + } +} + rustc_index::newtype_index! { /// A DefIndex is an index into the hir-map for a crate, identifying a /// particular definition. It should really be considered an interned @@ -139,8 +153,13 @@ impl DefId { } #[inline] - pub fn to_local(self) -> LocalDefId { - LocalDefId::from_def_id(self) + pub fn as_local(self) -> Option { + if self.is_local() { Some(LocalDefId { local_def_index: self.index }) } else { None } + } + + #[inline] + pub fn expect_local(self) -> LocalDefId { + self.as_local().unwrap_or_else(|| panic!("DefId::expect_local: `{:?}` isn't local", self)) } pub fn is_top_level_module(self) -> bool { @@ -185,19 +204,26 @@ rustc_data_structures::define_id_collections!(DefIdMap, DefIdSet, DefId); /// few cases where we know that only DefIds from the local crate are expected /// and a DefId from a different crate would signify a bug somewhere. This /// is when LocalDefId comes in handy. -#[derive(Clone, Copy, PartialEq, Eq, Hash)] -pub struct LocalDefId(DefIndex); +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct LocalDefId { + pub local_def_index: DefIndex, +} -impl LocalDefId { +impl Idx for LocalDefId { #[inline] - pub fn from_def_id(def_id: DefId) -> LocalDefId { - assert!(def_id.is_local()); - LocalDefId(def_id.index) + fn new(idx: usize) -> Self { + LocalDefId { local_def_index: Idx::new(idx) } } + #[inline] + fn index(self) -> usize { + self.local_def_index.index() + } +} +impl LocalDefId { #[inline] pub fn to_def_id(self) -> DefId { - DefId { krate: LOCAL_CRATE, index: self.0 } + DefId { krate: LOCAL_CRATE, index: self.local_def_index } } } diff --git a/src/librustc_span/edition.rs b/src/librustc_span/edition.rs index 3017191563b0a..b1ac7f04321eb 100644 --- a/src/librustc_span/edition.rs +++ b/src/librustc_span/edition.rs @@ -5,18 +5,8 @@ use std::str::FromStr; use rustc_macros::HashStable_Generic; /// The edition of the compiler (RFC 2052) -#[derive( - Clone, - Copy, - Hash, - PartialEq, - PartialOrd, - Debug, - RustcEncodable, - RustcDecodable, - Eq, - HashStable_Generic -)] +#[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Debug, RustcEncodable, RustcDecodable, Eq)] +#[derive(HashStable_Generic)] pub enum Edition { // editions must be kept in order, oldest to newest /// The 2015 edition diff --git a/src/librustc_span/hygiene.rs b/src/librustc_span/hygiene.rs index a368a881674d8..0afa2333e0615 100644 --- a/src/librustc_span/hygiene.rs +++ b/src/librustc_span/hygiene.rs @@ -59,18 +59,8 @@ pub struct ExpnId(u32); /// A property of a macro expansion that determines how identifiers /// produced by that expansion are resolved. -#[derive( - Copy, - Clone, - PartialEq, - Eq, - PartialOrd, - Hash, - Debug, - RustcEncodable, - RustcDecodable, - HashStable_Generic -)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Hash, Debug, RustcEncodable, RustcDecodable)] +#[derive(HashStable_Generic)] pub enum Transparency { /// Identifier produced by a transparent expansion is always resolved at call-site. /// Call-site spans in procedural macros, hygiene opt-out in `macro` should use this. @@ -201,11 +191,11 @@ impl HygieneData { true } - fn modern(&self, ctxt: SyntaxContext) -> SyntaxContext { + fn normalize_to_macros_2_0(&self, ctxt: SyntaxContext) -> SyntaxContext { self.syntax_context_data[ctxt.0 as usize].opaque } - fn modern_and_legacy(&self, ctxt: SyntaxContext) -> SyntaxContext { + fn normalize_to_macro_rules(&self, ctxt: SyntaxContext) -> SyntaxContext { self.syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent } @@ -266,9 +256,9 @@ impl HygieneData { let call_site_ctxt = self.expn_data(expn_id).call_site.ctxt(); let mut call_site_ctxt = if transparency == Transparency::SemiTransparent { - self.modern(call_site_ctxt) + self.normalize_to_macros_2_0(call_site_ctxt) } else { - self.modern_and_legacy(call_site_ctxt) + self.normalize_to_macro_rules(call_site_ctxt) }; if call_site_ctxt == SyntaxContext::root() { @@ -491,10 +481,10 @@ impl SyntaxContext { HygieneData::with(|data| data.adjust(self, expn_id)) } - /// Like `SyntaxContext::adjust`, but also modernizes `self`. - pub fn modernize_and_adjust(&mut self, expn_id: ExpnId) -> Option { + /// Like `SyntaxContext::adjust`, but also normalizes `self` to macros 2.0. + pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option { HygieneData::with(|data| { - *self = data.modern(*self); + *self = data.normalize_to_macros_2_0(*self); data.adjust(self, expn_id) }) } @@ -527,7 +517,7 @@ impl SyntaxContext { pub fn glob_adjust(&mut self, expn_id: ExpnId, glob_span: Span) -> Option> { HygieneData::with(|data| { let mut scope = None; - let mut glob_ctxt = data.modern(glob_span.ctxt()); + let mut glob_ctxt = data.normalize_to_macros_2_0(glob_span.ctxt()); while !data.is_descendant_of(expn_id, data.outer_expn(glob_ctxt)) { scope = Some(data.remove_mark(&mut glob_ctxt).0); if data.remove_mark(self).0 != scope.unwrap() { @@ -558,7 +548,7 @@ impl SyntaxContext { return None; } - let mut glob_ctxt = data.modern(glob_span.ctxt()); + let mut glob_ctxt = data.normalize_to_macros_2_0(glob_span.ctxt()); let mut marks = Vec::new(); while !data.is_descendant_of(expn_id, data.outer_expn(glob_ctxt)) { marks.push(data.remove_mark(&mut glob_ctxt)); @@ -574,20 +564,20 @@ impl SyntaxContext { pub fn hygienic_eq(self, other: SyntaxContext, expn_id: ExpnId) -> bool { HygieneData::with(|data| { - let mut self_modern = data.modern(self); - data.adjust(&mut self_modern, expn_id); - self_modern == data.modern(other) + let mut self_normalized = data.normalize_to_macros_2_0(self); + data.adjust(&mut self_normalized, expn_id); + self_normalized == data.normalize_to_macros_2_0(other) }) } #[inline] - pub fn modern(self) -> SyntaxContext { - HygieneData::with(|data| data.modern(self)) + pub fn normalize_to_macros_2_0(self) -> SyntaxContext { + HygieneData::with(|data| data.normalize_to_macros_2_0(self)) } #[inline] - pub fn modern_and_legacy(self) -> SyntaxContext { - HygieneData::with(|data| data.modern_and_legacy(self)) + pub fn normalize_to_macro_rules(self) -> SyntaxContext { + HygieneData::with(|data| data.normalize_to_macro_rules(self)) } #[inline] @@ -747,17 +737,8 @@ impl ExpnKind { } /// The kind of macro invocation or definition. -#[derive( - Clone, - Copy, - PartialEq, - Eq, - RustcEncodable, - RustcDecodable, - Hash, - Debug, - HashStable_Generic -)] +#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +#[derive(HashStable_Generic)] pub enum MacroKind { /// A bang macro `foo!()`. Bang, diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs index 1d493da9e5b11..a0c4c90722d25 100644 --- a/src/librustc_span/lib.rs +++ b/src/librustc_span/lib.rs @@ -6,6 +6,10 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(crate_visibility_modifier)] +#![feature(const_if_match)] +#![feature(const_fn)] +#![feature(const_panic)] +#![cfg_attr(not(bootstrap), feature(negative_impls))] #![feature(nll)] #![feature(optin_builtin_traits)] #![feature(specialization)] @@ -24,7 +28,7 @@ pub mod hygiene; use hygiene::Transparency; pub use hygiene::{DesugaringKind, ExpnData, ExpnId, ExpnKind, MacroKind, SyntaxContext}; pub mod def_id; -use def_id::DefId; +use def_id::{CrateNum, DefId, LOCAL_CRATE}; mod span_encoding; pub use span_encoding::{Span, DUMMY_SP}; @@ -69,18 +73,8 @@ impl Globals { scoped_tls::scoped_thread_local!(pub static GLOBALS: Globals); /// Differentiates between real files and common virtual files. -#[derive( - Debug, - Eq, - PartialEq, - Clone, - Ord, - PartialOrd, - Hash, - RustcDecodable, - RustcEncodable, - HashStable_Generic -)] +#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, RustcDecodable, RustcEncodable)] +#[derive(HashStable_Generic)] pub enum FileName { Real(PathBuf), /// Call to `quote!`. @@ -548,9 +542,9 @@ impl Span { } #[inline] - pub fn modernize_and_adjust(&mut self, expn_id: ExpnId) -> Option { + pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option { let mut span = self.data(); - let mark = span.ctxt.modernize_and_adjust(expn_id); + let mark = span.ctxt.normalize_to_macros_2_0_and_adjust(expn_id); *self = Span::new(span.lo, span.hi, span.ctxt); mark } @@ -576,15 +570,15 @@ impl Span { } #[inline] - pub fn modern(self) -> Span { + pub fn normalize_to_macros_2_0(self) -> Span { let span = self.data(); - span.with_ctxt(span.ctxt.modern()) + span.with_ctxt(span.ctxt.normalize_to_macros_2_0()) } #[inline] - pub fn modern_and_legacy(self) -> Span { + pub fn normalize_to_macro_rules(self) -> Span { let span = self.data(); - span.with_ctxt(span.ctxt.modern_and_legacy()) + span.with_ctxt(span.ctxt.normalize_to_macro_rules()) } } @@ -836,30 +830,42 @@ pub struct NormalizedPos { pub diff: u32, } -/// The state of the lazy external source loading mechanism of a `SourceFile`. -#[derive(PartialEq, Eq, Clone)] +#[derive(PartialEq, Eq, Clone, Debug)] pub enum ExternalSource { + /// No external source has to be loaded, since the `SourceFile` represents a local crate. + Unneeded, + Foreign { + kind: ExternalSourceKind, + /// This SourceFile's byte-offset within the source_map of its original crate + original_start_pos: BytePos, + /// The end of this SourceFile within the source_map of its original crate + original_end_pos: BytePos, + }, +} + +/// The state of the lazy external source loading mechanism of a `SourceFile`. +#[derive(PartialEq, Eq, Clone, Debug)] +pub enum ExternalSourceKind { /// The external source has been loaded already. - Present(String), + Present(Lrc), /// No attempt has been made to load the external source. AbsentOk, /// A failed attempt has been made to load the external source. AbsentErr, - /// No external source has to be loaded, since the `SourceFile` represents a local crate. Unneeded, } impl ExternalSource { pub fn is_absent(&self) -> bool { - match *self { - ExternalSource::Present(_) => false, + match self { + ExternalSource::Foreign { kind: ExternalSourceKind::Present(_), .. } => false, _ => true, } } - pub fn get_source(&self) -> Option<&str> { - match *self { - ExternalSource::Present(ref src) => Some(src), + pub fn get_source(&self) -> Option<&Lrc> { + match self { + ExternalSource::Foreign { kind: ExternalSourceKind::Present(ref src), .. } => Some(src), _ => None, } } @@ -880,8 +886,6 @@ pub struct SourceFile { /// The unmapped path of the file that the source came from. /// Set to `None` if the `SourceFile` was imported from an external crate. pub unmapped_path: Option, - /// Indicates which crate this `SourceFile` was imported from. - pub crate_of_origin: u32, /// The complete source code. pub src: Option>, /// The source code's hash. @@ -903,6 +907,8 @@ pub struct SourceFile { pub normalized_pos: Vec, /// A hash of the filename, used for speeding up hashing in incremental compilation. pub name_hash: u128, + /// Indicates which crate this `SourceFile` was imported from. + pub cnum: CrateNum, } impl Encodable for SourceFile { @@ -969,7 +975,8 @@ impl Encodable for SourceFile { s.emit_struct_field("multibyte_chars", 6, |s| self.multibyte_chars.encode(s))?; s.emit_struct_field("non_narrow_chars", 7, |s| self.non_narrow_chars.encode(s))?; s.emit_struct_field("name_hash", 8, |s| self.name_hash.encode(s))?; - s.emit_struct_field("normalized_pos", 9, |s| self.normalized_pos.encode(s)) + s.emit_struct_field("normalized_pos", 9, |s| self.normalized_pos.encode(s))?; + s.emit_struct_field("cnum", 10, |s| self.cnum.encode(s)) }) } } @@ -1019,24 +1026,24 @@ impl Decodable for SourceFile { let name_hash: u128 = d.read_struct_field("name_hash", 8, |d| Decodable::decode(d))?; let normalized_pos: Vec = d.read_struct_field("normalized_pos", 9, |d| Decodable::decode(d))?; + let cnum: CrateNum = d.read_struct_field("cnum", 10, |d| Decodable::decode(d))?; Ok(SourceFile { name, name_was_remapped, unmapped_path: None, - // `crate_of_origin` has to be set by the importer. - // This value matches up with `rustc_hir::def_id::INVALID_CRATE`. - // That constant is not available here, unfortunately. - crate_of_origin: std::u32::MAX - 1, start_pos, end_pos, src: None, src_hash, - external_src: Lock::new(ExternalSource::AbsentOk), + // Unused - the metadata decoder will construct + // a new SourceFile, filling in `external_src` properly + external_src: Lock::new(ExternalSource::Unneeded), lines, multibyte_chars, non_narrow_chars, normalized_pos, name_hash, + cnum, }) }) } @@ -1078,7 +1085,6 @@ impl SourceFile { name, name_was_remapped, unmapped_path: Some(unmapped_path), - crate_of_origin: 0, src: Some(Lrc::new(src)), src_hash, external_src: Lock::new(ExternalSource::Unneeded), @@ -1089,6 +1095,7 @@ impl SourceFile { non_narrow_chars, normalized_pos, name_hash, + cnum: LOCAL_CRATE, } } @@ -1106,21 +1113,27 @@ impl SourceFile { where F: FnOnce() -> Option, { - if *self.external_src.borrow() == ExternalSource::AbsentOk { + if matches!( + *self.external_src.borrow(), + ExternalSource::Foreign { kind: ExternalSourceKind::AbsentOk, .. } + ) { let src = get_src(); let mut external_src = self.external_src.borrow_mut(); // Check that no-one else have provided the source while we were getting it - if *external_src == ExternalSource::AbsentOk { + if let ExternalSource::Foreign { + kind: src_kind @ ExternalSourceKind::AbsentOk, .. + } = &mut *external_src + { if let Some(src) = src { let mut hasher: StableHasher = StableHasher::new(); hasher.write(src.as_bytes()); if hasher.finish::() == self.src_hash { - *external_src = ExternalSource::Present(src); + *src_kind = ExternalSourceKind::Present(Lrc::new(src)); return true; } } else { - *external_src = ExternalSource::AbsentErr; + *src_kind = ExternalSourceKind::AbsentErr; } false @@ -1147,11 +1160,7 @@ impl SourceFile { } let begin = { - let line = if let Some(line) = self.lines.get(line_number) { - line - } else { - return None; - }; + let line = self.lines.get(line_number)?; let begin: BytePos = *line - self.start_pos; begin.to_usize() }; diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs index 353f7b3f52bc3..57e68320f3fbb 100644 --- a/src/librustc_span/source_map.rs +++ b/src/librustc_span/source_map.rs @@ -296,14 +296,16 @@ impl SourceMap { &self, filename: FileName, name_was_remapped: bool, - crate_of_origin: u32, src_hash: u128, name_hash: u128, source_len: usize, + cnum: CrateNum, mut file_local_lines: Vec, mut file_local_multibyte_chars: Vec, mut file_local_non_narrow_chars: Vec, mut file_local_normalized_pos: Vec, + original_start_pos: BytePos, + original_end_pos: BytePos, ) -> Lrc { let start_pos = self .allocate_address_space(source_len) @@ -332,10 +334,13 @@ impl SourceMap { name: filename, name_was_remapped, unmapped_path: None, - crate_of_origin, src: None, src_hash, - external_src: Lock::new(ExternalSource::AbsentOk), + external_src: Lock::new(ExternalSource::Foreign { + kind: ExternalSourceKind::AbsentOk, + original_start_pos, + original_end_pos, + }), start_pos, end_pos, lines: file_local_lines, @@ -343,6 +348,7 @@ impl SourceMap { non_narrow_chars: file_local_non_narrow_chars, normalized_pos: file_local_normalized_pos, name_hash, + cnum, }); let mut files = self.files.borrow_mut(); @@ -362,16 +368,16 @@ impl SourceMap { // If there is a doctest offset, applies it to the line. pub fn doctest_offset_line(&self, file: &FileName, orig: usize) -> usize { - return match file { + match file { FileName::DocTest(_, offset) => { - return if *offset >= 0 { - orig + *offset as usize - } else { + if *offset < 0 { orig - (-(*offset)) as usize - }; + } else { + orig + *offset as usize + } } _ => orig, - }; + } } /// Looks up source information about a `BytePos`. @@ -529,6 +535,10 @@ impl SourceMap { let (lo, hi) = self.is_valid_span(sp)?; assert!(hi.line >= lo.line); + if sp.is_dummy() { + return Ok(FileLines { file: lo.file, lines: Vec::new() }); + } + let mut lines = Vec::with_capacity(hi.line - lo.line + 1); // The span starts partway through the first line, @@ -539,6 +549,9 @@ impl SourceMap { // and to the end of the line. Be careful because the line // numbers in Loc are 1-based, so we subtract 1 to get 0-based // lines. + // + // FIXME: now that we handle DUMMY_SP up above, we should consider + // asserting that the line numbers here are all indeed 1-based. let hi_line = hi.line.saturating_sub(1); for line_index in lo.line.saturating_sub(1)..hi_line { let line_len = lo.file.get_line(line_index).map(|s| s.chars().count()).unwrap_or(0); @@ -563,10 +576,10 @@ impl SourceMap { let local_end = self.lookup_byte_offset(sp.hi()); if local_begin.sf.start_pos != local_end.sf.start_pos { - return Err(SpanSnippetError::DistinctSources(DistinctSources { + Err(SpanSnippetError::DistinctSources(DistinctSources { begin: (local_begin.sf.name.clone(), local_begin.sf.start_pos), end: (local_end.sf.name.clone(), local_end.sf.start_pos), - })); + })) } else { self.ensure_source_file_source_present(local_begin.sf.clone()); @@ -584,13 +597,11 @@ impl SourceMap { } if let Some(ref src) = local_begin.sf.src { - return extract_source(src, start_index, end_index); + extract_source(src, start_index, end_index) } else if let Some(src) = local_begin.sf.external_src.borrow().get_source() { - return extract_source(src, start_index, end_index); + extract_source(src, start_index, end_index) } else { - return Err(SpanSnippetError::SourceNotAvailable { - filename: local_begin.sf.name.clone(), - }); + Err(SpanSnippetError::SourceNotAvailable { filename: local_begin.sf.name.clone() }) } } } @@ -722,7 +733,14 @@ impl SourceMap { } } - pub fn def_span(&self, sp: Span) -> Span { + /// Given a `Span`, return a span ending in the closest `{`. This is useful when you have a + /// `Span` enclosing a whole item but we need to point at only the head (usually the first + /// line) of that item. + /// + /// *Only suitable for diagnostics.* + pub fn guess_head_span(&self, sp: Span) -> Span { + // FIXME: extend the AST items to have a head span, or replace callers with pointing at + // the item's ident when appropriate. self.span_until_char(sp, '{') } diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index 6cb7cbf14fdd7..bb41629ef094d 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -182,6 +182,7 @@ symbols! { caller_location, cdylib, cfg, + cfg_accessible, cfg_attr, cfg_attr_multi, cfg_doctest, @@ -252,6 +253,7 @@ symbols! { debug_trait, declare_lint_pass, decl_macro, + debug, Debug, Decodable, Default, @@ -289,7 +291,6 @@ symbols! { dylib, dyn_trait, eh_personality, - eh_unwind_resume, enable, Encodable, env, @@ -454,6 +455,7 @@ symbols! { min_align_of, min_const_fn, min_const_unsafe_fn, + min_specialization, mips_target_feature, mmx_target_feature, module, @@ -471,6 +473,7 @@ symbols! { needs_drop, needs_panic_runtime, negate_unsigned, + negative_impls, never, never_type, never_type_fallback, @@ -543,7 +546,7 @@ symbols! { plugin_registrar, plugins, Poll, - poll_with_tls_context, + poll_with_context, powerpc_target_feature, precise_pointer_size_matching, pref_align_of, @@ -655,6 +658,8 @@ symbols! { rustc_proc_macro_decls, rustc_promotable, rustc_regions, + rustc_unsafe_specialization_marker, + rustc_specialization_trait, rustc_stable, rustc_std_internal_symbol, rustc_symbol_name, @@ -665,7 +670,6 @@ symbols! { rustc_variance, rustfmt, rust_eh_personality, - rust_eh_unwind_resume, rust_oom, rvalue_static_promotion, sanitize, @@ -718,6 +722,7 @@ symbols! { target_has_atomic_load_store, target_thread_local, task, + _task_context, tbm_target_feature, termination_trait, termination_trait_test, @@ -855,12 +860,12 @@ impl Ident { } /// "Normalize" ident for use in comparisons using "item hygiene". - /// Identifiers with same string value become same if they came from the same "modern" macro + /// Identifiers with same string value become same if they came from the same macro 2.0 macro /// (e.g., `macro` item, but not `macro_rules` item) and stay different if they came from - /// different "modern" macros. + /// different macro 2.0 macros. /// Technically, this operation strips all non-opaque marks from ident's syntactic context. - pub fn modern(self) -> Ident { - Ident::new(self.name, self.span.modern()) + pub fn normalize_to_macros_2_0(self) -> Ident { + Ident::new(self.name, self.span.normalize_to_macros_2_0()) } /// "Normalize" ident for use in comparisons using "local variable hygiene". @@ -868,8 +873,8 @@ impl Ident { /// macro (e.g., `macro` or `macro_rules!` items) and stay different if they came from different /// non-transparent macros. /// Technically, this operation strips all transparent marks from ident's syntactic context. - pub fn modern_and_legacy(self) -> Ident { - Ident::new(self.name, self.span.modern_and_legacy()) + pub fn normalize_to_macro_rules(self) -> Ident { + Ident::new(self.name, self.span.normalize_to_macro_rules()) } /// Convert the name to a `SymbolStr`. This is a slowish operation because @@ -981,6 +986,31 @@ impl fmt::Display for IdentPrinter { } } +/// An newtype around `Ident` that calls [Ident::normalize_to_macro_rules] on +/// construction. +// FIXME(matthewj, petrochenkov) Use this more often, add a similar +// `ModernIdent` struct and use that as well. +#[derive(Copy, Clone, Eq, PartialEq, Hash)] +pub struct MacroRulesNormalizedIdent(Ident); + +impl MacroRulesNormalizedIdent { + pub fn new(ident: Ident) -> Self { + Self(ident.normalize_to_macro_rules()) + } +} + +impl fmt::Debug for MacroRulesNormalizedIdent { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&self.0, f) + } +} + +impl fmt::Display for MacroRulesNormalizedIdent { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.0, f) + } +} + /// An interned string. /// /// Internally, a `Symbol` is implemented as an index, and all operations @@ -999,7 +1029,7 @@ rustc_index::newtype_index! { impl Symbol { const fn new(n: u32) -> Self { - Symbol(SymbolIndex::from_u32_const(n)) + Symbol(SymbolIndex::from_u32(n)) } /// Maps a string to its interned representation. diff --git a/src/librustc_codegen_utils/Cargo.toml b/src/librustc_symbol_mangling/Cargo.toml similarity index 79% rename from src/librustc_codegen_utils/Cargo.toml rename to src/librustc_symbol_mangling/Cargo.toml index b5533a8307c3d..1e4fc8f7e6842 100644 --- a/src/librustc_codegen_utils/Cargo.toml +++ b/src/librustc_symbol_mangling/Cargo.toml @@ -1,13 +1,13 @@ [package] authors = ["The Rust Project Developers"] -name = "rustc_codegen_utils" +name = "rustc_symbol_mangling" version = "0.0.0" edition = "2018" [lib] -name = "rustc_codegen_utils" +name = "rustc_symbol_mangling" path = "lib.rs" -test = false +doctest = false [dependencies] log = "0.4" @@ -21,3 +21,4 @@ rustc_hir = { path = "../librustc_hir" } rustc_target = { path = "../librustc_target" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_metadata = { path = "../librustc_metadata" } +rustc_session = { path = "../librustc_session" } diff --git a/src/librustc_codegen_utils/symbol_names/legacy.rs b/src/librustc_symbol_mangling/legacy.rs similarity index 97% rename from src/librustc_codegen_utils/symbol_names/legacy.rs rename to src/librustc_symbol_mangling/legacy.rs index 0dedda9bb6b73..a891d60b0687b 100644 --- a/src/librustc_codegen_utils/symbol_names/legacy.rs +++ b/src/librustc_symbol_mangling/legacy.rs @@ -1,4 +1,3 @@ -use rustc::hir::map::{DefPathData, DisambiguatedDefPathData}; use rustc::ich::NodeIdHashingMode; use rustc::mir::interpret::{ConstValue, Scalar}; use rustc::ty::print::{PrettyPrinter, Print, Printer}; @@ -7,6 +6,7 @@ use rustc::ty::{self, Instance, Ty, TyCtxt, TypeFoldable}; use rustc::util::common::record_time; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def_id::CrateNum; +use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; use log::debug; @@ -59,10 +59,14 @@ pub(super) fn mangle( .print_def_path(def_id, &[]) .unwrap(); - if instance.is_vtable_shim() { + if let ty::InstanceDef::VtableShim(..) = instance.def { let _ = printer.write_str("{{vtable-shim}}"); } + if let ty::InstanceDef::ReifyShim(..) = instance.def { + let _ = printer.write_str("{{reify-shim}}"); + } + printer.path.finish(hash) } @@ -123,7 +127,8 @@ fn get_symbol_hash<'tcx>( } // We want to avoid accidental collision between different types of instances. - // Especially, VtableShim may overlap with its original instance without this. + // Especially, `VtableShim`s and `ReifyShim`s may overlap with their original + // instances without this. discriminant(&instance.def).hash_stable(&mut hcx, &mut hasher); }); diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_symbol_mangling/lib.rs similarity index 97% rename from src/librustc_codegen_utils/symbol_names.rs rename to src/librustc_symbol_mangling/lib.rs index cfde09fad62cc..26cb341050027 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_symbol_mangling/lib.rs @@ -87,14 +87,23 @@ //! virtually impossible. Thus, symbol hash generation exclusively relies on //! DefPaths which are much more robust in the face of changes to the code base. +#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] +#![feature(never_type)] +#![feature(nll)] +#![feature(in_band_lifetimes)] +#![recursion_limit = "256"] + +#[macro_use] +extern crate rustc; + 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::{CrateNum, LOCAL_CRATE}; use rustc_hir::Node; +use rustc_session::config::SymbolManglingVersion; use rustc_span::symbol::Symbol; @@ -103,6 +112,8 @@ use log::debug; mod legacy; mod v0; +pub mod test; + /// 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. diff --git a/src/librustc_codegen_utils/symbol_names_test.rs b/src/librustc_symbol_mangling/test.rs similarity index 100% rename from src/librustc_codegen_utils/symbol_names_test.rs rename to src/librustc_symbol_mangling/test.rs diff --git a/src/librustc_codegen_utils/symbol_names/v0.rs b/src/librustc_symbol_mangling/v0.rs similarity index 98% rename from src/librustc_codegen_utils/symbol_names/v0.rs rename to src/librustc_symbol_mangling/v0.rs index ce6d0d9dc5ba8..fb2fde8513ac9 100644 --- a/src/librustc_codegen_utils/symbol_names/v0.rs +++ b/src/librustc_symbol_mangling/v0.rs @@ -1,4 +1,3 @@ -use rustc::hir::map::{DefPathData, DisambiguatedDefPathData}; use rustc::ty::print::{Print, Printer}; use rustc::ty::subst::{GenericArg, GenericArgKind, Subst}; use rustc::ty::{self, Instance, Ty, TyCtxt, TypeFoldable}; @@ -7,6 +6,7 @@ use rustc_data_structures::base_n; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId}; +use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; use rustc_target::spec::abi::Abi; use std::fmt::Write; @@ -34,8 +34,17 @@ pub(super) fn mangle( binders: vec![], out: String::from(prefix), }; - cx = if instance.is_vtable_shim() { - cx.path_append_ns(|cx| cx.print_def_path(def_id, substs), 'S', 0, "").unwrap() + + // Append `::{shim:...#0}` to shims that can coexist with a non-shim instance. + let shim_kind = match instance.def { + ty::InstanceDef::VtableShim(_) => Some("vtable"), + ty::InstanceDef::ReifyShim(_) => Some("reify"), + + _ => None, + }; + + cx = if let Some(shim_kind) = shim_kind { + cx.path_append_ns(|cx| cx.print_def_path(def_id, substs), 'S', 0, shim_kind).unwrap() } else { cx.print_def_path(def_id, substs).unwrap() }; diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 2f8bbd66c322b..6976ac9f0d73d 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -3,6 +3,7 @@ pub use Primitive::*; use crate::spec::Target; +use std::convert::{TryFrom, TryInto}; use std::ops::{Add, AddAssign, Deref, Mul, Range, RangeInclusive, Sub}; use rustc_index::vec::{Idx, IndexVec}; @@ -240,17 +241,18 @@ pub struct Size { } impl Size { - pub const ZERO: Size = Self::from_bytes(0); + pub const ZERO: Size = Size { raw: 0 }; #[inline] - pub fn from_bits(bits: u64) -> Size { + pub fn from_bits(bits: impl TryInto) -> Size { + let bits = bits.try_into().ok().unwrap(); // Avoid potential overflow from `bits + 7`. Size::from_bytes(bits / 8 + ((bits % 8) + 7) / 8) } #[inline] - pub const fn from_bytes(bytes: u64) -> Size { - Size { raw: bytes } + pub fn from_bytes(bytes: impl TryInto) -> Size { + Size { raw: bytes.try_into().ok().unwrap() } } #[inline] @@ -258,6 +260,11 @@ impl Size { self.raw } + #[inline] + pub fn bytes_usize(self) -> usize { + self.bytes().try_into().unwrap() + } + #[inline] pub fn bits(self) -> u64 { self.bytes().checked_mul(8).unwrap_or_else(|| { @@ -265,6 +272,11 @@ impl Size { }) } + #[inline] + pub fn bits_usize(self) -> usize { + self.bits().try_into().unwrap() + } + #[inline] pub fn align_to(self, align: Align) -> Size { let mask = align.bytes() - 1; @@ -660,9 +672,12 @@ impl FieldPlacement { pub fn offset(&self, i: usize) -> Size { match *self { - FieldPlacement::Union(_) => Size::ZERO, + FieldPlacement::Union(count) => { + assert!(i < count, "tried to access field {} of union with {} fields", i, count); + Size::ZERO + } FieldPlacement::Array { stride, count } => { - let i = i as u64; + let i = u64::try_from(i).unwrap(); assert!(i < count); stride * i } @@ -748,7 +763,7 @@ impl Abi { Primitive::Int(_, signed) => signed, _ => false, }, - _ => false, + _ => panic!("`is_signed` on non-scalar ABI {:?}", self), } } @@ -787,7 +802,7 @@ pub enum Variants { discr: Scalar, discr_kind: DiscriminantKind, discr_index: usize, - variants: IndexVec, + variants: IndexVec, }, } @@ -870,7 +885,7 @@ impl Niche { } #[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] -pub struct LayoutDetails { +pub struct Layout { /// Says where the fields are located within the layout. /// Primitives and uninhabited enums appear as unions without fields. pub fields: FieldPlacement, @@ -901,12 +916,12 @@ pub struct LayoutDetails { pub size: Size, } -impl LayoutDetails { +impl Layout { pub fn scalar(cx: &C, scalar: Scalar) -> Self { let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar.clone()); let size = scalar.value.size(cx); let align = scalar.value.align(cx); - LayoutDetails { + Layout { variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldPlacement::Union(0), abi: Abi::Scalar(scalar), @@ -917,23 +932,24 @@ impl LayoutDetails { } } -/// The details of the layout of a type, alongside the type itself. +/// The layout of a type, alongside the type itself. /// Provides various type traversal APIs (e.g., recursing into fields). /// -/// Note that the details are NOT guaranteed to always be identical -/// to those obtained from `layout_of(ty)`, as we need to produce +/// Note that the layout is NOT guaranteed to always be identical +/// to that obtained from `layout_of(ty)`, as we need to produce /// layouts for which Rust types do not exist, such as enum variants /// or synthetic fields of enums (i.e., discriminants) and fat pointers. +// FIXME: rename to TyAndLayout. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub struct TyLayout<'a, Ty> { pub ty: Ty, - pub details: &'a LayoutDetails, + pub layout: &'a Layout, } impl<'a, Ty> Deref for TyLayout<'a, Ty> { - type Target = &'a LayoutDetails; - fn deref(&self) -> &&'a LayoutDetails { - &self.details + type Target = &'a Layout; + fn deref(&self) -> &&'a Layout { + &self.layout } } @@ -1094,7 +1110,7 @@ impl<'a, Ty> TyLayout<'a, Ty> { }; if !valid { // This is definitely not okay. - trace!("might_permit_raw_init({:?}, zero={}): not valid", self.details, zero); + trace!("might_permit_raw_init({:?}, zero={}): not valid", self.layout, zero); return Ok(false); } diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs index 3c397eb444d1d..98190867d493f 100644 --- a/src/librustc_target/lib.rs +++ b/src/librustc_target/lib.rs @@ -9,6 +9,9 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(bool_to_option)] +#![feature(const_if_match)] +#![feature(const_fn)] +#![feature(const_panic)] #![feature(nll)] #![feature(never_type)] #![feature(associated_type_bounds)] diff --git a/src/librustc_target/spec/abi.rs b/src/librustc_target/spec/abi.rs index ac4c561402b67..1736063cc5f7c 100644 --- a/src/librustc_target/spec/abi.rs +++ b/src/librustc_target/spec/abi.rs @@ -5,19 +5,8 @@ use rustc_macros::HashStable_Generic; #[cfg(test)] mod tests; -#[derive( - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - RustcEncodable, - RustcDecodable, - Clone, - Copy, - Debug, - HashStable_Generic -)] +#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Clone, Copy, Debug)] +#[derive(HashStable_Generic)] pub enum Abi { // N.B., this ordering MUST match the AbiDatas array below. // (This is ensured by the test indices_are_correct().) diff --git a/src/librustc_target/spec/apple_base.rs b/src/librustc_target/spec/apple_base.rs index d116ddf952aaa..4ad65569e6a8a 100644 --- a/src/librustc_target/spec/apple_base.rs +++ b/src/librustc_target/spec/apple_base.rs @@ -57,7 +57,7 @@ pub fn macos_link_env_remove() -> Vec { let mut env_remove = Vec::with_capacity(2); // Remove the `SDKROOT` environment variable if it's clearly set for the wrong platform, which // may occur when we're linking a custom build script while targeting iOS for example. - if let Some(sdkroot) = env::var("SDKROOT").ok() { + if let Ok(sdkroot) = env::var("SDKROOT") { if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("iPhoneSimulator.platform") { env_remove.push("SDKROOT".to_string()) } diff --git a/src/librustc_target/spec/apple_sdk_base.rs b/src/librustc_target/spec/apple_sdk_base.rs index 513754352fbfb..c7cff17b1544c 100644 --- a/src/librustc_target/spec/apple_sdk_base.rs +++ b/src/librustc_target/spec/apple_sdk_base.rs @@ -43,40 +43,26 @@ pub fn get_sdk_root(sdk_name: &str) -> Result { // to allow the SDK path to be set. (For clang, xcrun sets // SDKROOT; for rustc, the user or build system can set it, or we // can fall back to checking for xcrun on PATH.) - if let Some(sdkroot) = env::var("SDKROOT").ok() { + if let Ok(sdkroot) = env::var("SDKROOT") { let p = Path::new(&sdkroot); match sdk_name { // Ignore `SDKROOT` if it's clearly set for the wrong platform. "appletvos" if sdkroot.contains("TVSimulator.platform") - || sdkroot.contains("MacOSX.platform") => - { - () - } + || sdkroot.contains("MacOSX.platform") => {} "appletvsimulator" - if sdkroot.contains("TVOS.platform") || sdkroot.contains("MacOSX.platform") => - { - () - } + if sdkroot.contains("TVOS.platform") || sdkroot.contains("MacOSX.platform") => {} "iphoneos" if sdkroot.contains("iPhoneSimulator.platform") - || sdkroot.contains("MacOSX.platform") => - { - () - } + || sdkroot.contains("MacOSX.platform") => {} "iphonesimulator" - if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("MacOSX.platform") => - { - () + if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("MacOSX.platform") => { } "macosx10.15" if sdkroot.contains("iPhoneOS.platform") - || sdkroot.contains("iPhoneSimulator.platform") => - { - () - } + || sdkroot.contains("iPhoneSimulator.platform") => {} // Ignore `SDKROOT` if it's not a valid path. - _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => (), + _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => {} _ => return Ok(sdkroot), } } diff --git a/src/librustc_target/spec/illumos_base.rs b/src/librustc_target/spec/illumos_base.rs new file mode 100644 index 0000000000000..51444fb0c05ad --- /dev/null +++ b/src/librustc_target/spec/illumos_base.rs @@ -0,0 +1,35 @@ +use crate::spec::TargetOptions; +use std::default::Default; + +pub fn opts() -> TargetOptions { + TargetOptions { + dynamic_linking: true, + executables: true, + has_rpath: true, + target_family: Some("unix".to_string()), + is_like_solaris: true, + limit_rdylib_exports: false, // Linker doesn't support this + eliminate_frame_pointer: false, + + // While we support ELF TLS, rust requires a way to register + // cleanup handlers (in C, this would be something along the lines of: + // void register_callback(void (*fn)(void *), void *arg); + // (see src/libstd/sys/unix/fast_thread_local.rs) that is currently + // missing in illumos. For now at least, we must fallback to using + // pthread_{get,set}specific. + //has_elf_tls: true, + + // XXX: Currently, rust is invoking cc to link, which ends up + // causing these to get included twice. We should eventually transition + // to having rustc invoke ld directly, in which case these will need to + // be uncommented. + // + // We want XPG6 behavior from libc and libm. See standards(5) + //pre_link_objects_exe: vec![ + // "/usr/lib/amd64/values-Xc.o".to_string(), + // "/usr/lib/amd64/values-xpg6.o".to_string(), + //], + + .. Default::default() + } +} diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 37eabb4f26d4b..7482cf5743d90 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -56,6 +56,7 @@ mod fuchsia_base; mod haiku_base; mod hermit_base; mod hermit_kernel_base; +mod illumos_base; mod l4re_base; mod linux_base; mod linux_kernel_base; @@ -447,6 +448,8 @@ supported_targets! { ("x86_64-sun-solaris", "x86_64-pc-solaris", x86_64_sun_solaris), ("sparcv9-sun-solaris", sparcv9_sun_solaris), + ("x86_64-unknown-illumos", x86_64_unknown_illumos), + ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu), ("i686-pc-windows-gnu", i686_pc_windows_gnu), ("i686-uwp-windows-gnu", i686_uwp_windows_gnu), @@ -581,6 +584,12 @@ pub struct TargetOptions { /// user-defined but before post_link_objects. Standard platform /// libraries that should be always be linked to, usually go here. pub late_link_args: LinkArgs, + /// Linker arguments used in addition to `late_link_args` if at least one + /// Rust dependency is dynamically linked. + pub late_link_args_dynamic: LinkArgs, + /// Linker arguments used in addition to `late_link_args` if aall Rust + /// dependencies are statically linked. + pub late_link_args_static: LinkArgs, /// Objects to link after all others, always found within the /// sysroot folder. pub post_link_objects: Vec, // ... unconditionally @@ -694,11 +703,6 @@ pub struct TargetOptions { pub archive_format: String, /// Is asm!() allowed? Defaults to true. pub allow_asm: bool, - /// Whether the target uses a custom unwind resumption routine. - /// By default LLVM lowers `resume` instructions into calls to `_Unwind_Resume` - /// defined in libgcc. If this option is enabled, the target must provide - /// `eh_unwind_resume` lang item. - pub custom_unwind_resume: bool, /// Whether the runtime startup code requires the `main` function be passed /// `argc` and `argv` values. pub main_needs_argc_argv: bool, @@ -865,10 +869,11 @@ impl Default for TargetOptions { post_link_objects: Vec::new(), post_link_objects_crt: Vec::new(), late_link_args: LinkArgs::new(), + late_link_args_dynamic: LinkArgs::new(), + late_link_args_static: LinkArgs::new(), link_env: Vec::new(), link_env_remove: Vec::new(), archive_format: "gnu".to_string(), - custom_unwind_resume: false, main_needs_argc_argv: true, allow_asm: true, has_elf_tls: false, @@ -1144,6 +1149,8 @@ impl Target { key!(pre_link_objects_exe_crt, list); key!(pre_link_objects_dll, list); key!(late_link_args, link_args); + key!(late_link_args_dynamic, link_args); + key!(late_link_args_static, link_args); key!(post_link_objects, list); key!(post_link_objects_crt, list); key!(post_link_args, link_args); @@ -1184,7 +1191,6 @@ impl Target { key!(relro_level, RelroLevel)?; key!(archive_format); key!(allow_asm, bool); - key!(custom_unwind_resume, bool); key!(main_needs_argc_argv, bool); key!(has_elf_tls, bool); key!(obj_is_bitcode, bool); @@ -1372,6 +1378,8 @@ impl ToJson for Target { target_option_val!(pre_link_objects_exe_crt); target_option_val!(pre_link_objects_dll); target_option_val!(link_args - late_link_args); + target_option_val!(link_args - late_link_args_dynamic); + target_option_val!(link_args - late_link_args_static); target_option_val!(post_link_objects); target_option_val!(post_link_objects_crt); target_option_val!(link_args - post_link_args); @@ -1412,7 +1420,6 @@ impl ToJson for Target { target_option_val!(relro_level); target_option_val!(archive_format); target_option_val!(allow_asm); - target_option_val!(custom_unwind_resume); target_option_val!(main_needs_argc_argv); target_option_val!(has_elf_tls); target_option_val!(obj_is_bitcode); diff --git a/src/librustc_target/spec/windows_base.rs b/src/librustc_target/spec/windows_base.rs index 693a343d5a5fb..188548b41fe75 100644 --- a/src/librustc_target/spec/windows_base.rs +++ b/src/librustc_target/spec/windows_base.rs @@ -17,12 +17,13 @@ pub fn opts() -> TargetOptions { ); let mut late_link_args = LinkArgs::new(); + let mut late_link_args_dynamic = LinkArgs::new(); + let mut late_link_args_static = LinkArgs::new(); late_link_args.insert( LinkerFlavor::Gcc, vec![ "-lmingwex".to_string(), "-lmingw32".to_string(), - "-lgcc".to_string(), // alas, mingw* libraries above depend on libgcc "-lmsvcrt".to_string(), // mingw's msvcrt is a weird hybrid import library and static library. // And it seems that the linker fails to use import symbols from msvcrt @@ -37,6 +38,31 @@ pub fn opts() -> TargetOptions { "-lkernel32".to_string(), ], ); + late_link_args_dynamic.insert( + LinkerFlavor::Gcc, + vec![ + // If any of our crates are dynamically linked then we need to use + // the shared libgcc_s-dw2-1.dll. This is required to support + // unwinding across DLL boundaries. + "-lgcc_s".to_string(), + "-lgcc".to_string(), + "-lkernel32".to_string(), + ], + ); + late_link_args_static.insert( + LinkerFlavor::Gcc, + vec![ + // If all of our crates are statically linked then we can get away + // with statically linking the libgcc unwinding code. This allows + // binaries to be redistributed without the libgcc_s-dw2-1.dll + // dependency, but unfortunately break unwinding across DLL + // boundaries when unwinding across FFI boundaries. + "-lgcc".to_string(), + "-lgcc_eh".to_string(), + "-lpthread".to_string(), + "-lkernel32".to_string(), + ], + ); TargetOptions { // FIXME(#13846) this should be enabled for windows @@ -63,8 +89,9 @@ pub fn opts() -> TargetOptions { "rsbegin.o".to_string(), ], late_link_args, + late_link_args_dynamic, + late_link_args_static, post_link_objects: vec!["rsend.o".to_string()], - custom_unwind_resume: true, abi_return_struct_as_int: true, emit_debug_gdb_scripts: false, requires_uwtable: true, diff --git a/src/librustc_target/spec/windows_uwp_base.rs b/src/librustc_target/spec/windows_uwp_base.rs index b19c4dd7eb18c..3f7eb442bbc73 100644 --- a/src/librustc_target/spec/windows_uwp_base.rs +++ b/src/librustc_target/spec/windows_uwp_base.rs @@ -54,7 +54,6 @@ pub fn opts() -> TargetOptions { pre_link_objects_dll: vec!["rsbegin.o".to_string()], late_link_args, post_link_objects: vec!["rsend.o".to_string()], - custom_unwind_resume: true, abi_return_struct_as_int: true, emit_debug_gdb_scripts: false, requires_uwtable: true, diff --git a/src/librustc_target/spec/x86_64_unknown_illumos.rs b/src/librustc_target/spec/x86_64_unknown_illumos.rs new file mode 100644 index 0000000000000..efd391fa8b4ae --- /dev/null +++ b/src/librustc_target/spec/x86_64_unknown_illumos.rs @@ -0,0 +1,28 @@ +use crate::spec::{LinkerFlavor, Target, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::illumos_base::opts(); + base.pre_link_args.insert(LinkerFlavor::Gcc, + vec!["-m64".to_string(), "-std=c99".to_string()]); + base.cpu = "x86-64".to_string(); + base.max_atomic_width = Some(64); + // illumos has its own stack protection which interferes + // with the rust stack probes. See rust-lang/rust#52577 + base.stack_probes = false; + + Ok(Target { + // LLVM does not currently have a separate illumos target, + // so we still pass Solaris to it + llvm_target: "x86_64-pc-solaris".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(), + arch: "x86_64".to_string(), + target_os: "illumos".to_string(), + target_env: String::new(), + target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: base, + }) +} diff --git a/src/librustc_trait_selection/Cargo.toml b/src/librustc_trait_selection/Cargo.toml new file mode 100644 index 0000000000000..5b2da41d06672 --- /dev/null +++ b/src/librustc_trait_selection/Cargo.toml @@ -0,0 +1,27 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustc_trait_selection" +version = "0.0.0" +edition = "2018" + +[lib] +name = "rustc_trait_selection" +path = "lib.rs" +doctest = false + +[dependencies] +fmt_macros = { path = "../libfmt_macros" } +log = { version = "0.4", features = ["release_max_level_info", "std"] } +rustc_attr = { path = "../librustc_attr" } +rustc = { path = "../librustc" } +rustc_ast = { path = "../librustc_ast" } +rustc_data_structures = { path = "../librustc_data_structures" } +rustc_errors = { path = "../librustc_errors" } +rustc_hir = { path = "../librustc_hir" } +rustc_index = { path = "../librustc_index" } +rustc_infer = { path = "../librustc_infer" } +rustc_macros = { path = "../librustc_macros" } +rustc_session = { path = "../librustc_session" } +rustc_span = { path = "../librustc_span" } +rustc_target = { path = "../librustc_target" } +smallvec = { version = "1.0", features = ["union", "may_dangle"] } diff --git a/src/librustc_trait_selection/infer.rs b/src/librustc_trait_selection/infer.rs new file mode 100644 index 0000000000000..7abcbf45277fb --- /dev/null +++ b/src/librustc_trait_selection/infer.rs @@ -0,0 +1,182 @@ +use crate::traits::query::outlives_bounds::InferCtxtExt as _; +use crate::traits::{self, TraitEngine, TraitEngineExt}; + +use rustc::arena::ArenaAllocatable; +use rustc::infer::canonical::{Canonical, CanonicalizedQueryResponse, QueryResponse}; +use rustc::middle::lang_items; +use rustc::traits::query::Fallible; +use rustc::ty::{self, Ty, TypeFoldable}; +use rustc_hir as hir; +use rustc_infer::infer::outlives::env::OutlivesEnvironment; +use rustc_infer::traits::ObligationCause; +use rustc_span::{Span, DUMMY_SP}; + +use std::fmt::Debug; + +pub use rustc_infer::infer::*; + +pub trait InferCtxtExt<'tcx> { + fn type_is_copy_modulo_regions( + &self, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, + span: Span, + ) -> bool; + + fn partially_normalize_associated_types_in( + &self, + span: Span, + body_id: hir::HirId, + param_env: ty::ParamEnv<'tcx>, + value: &T, + ) -> InferOk<'tcx, T> + where + T: TypeFoldable<'tcx>; +} + +impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { + fn type_is_copy_modulo_regions( + &self, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, + span: Span, + ) -> bool { + let ty = self.resolve_vars_if_possible(&ty); + + if !(param_env, ty).has_local_value() { + return ty.is_copy_modulo_regions(self.tcx, param_env, span); + } + + let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem, None); + + // This can get called from typeck (by euv), and `moves_by_default` + // rightly refuses to work with inference variables, but + // moves_by_default has a cache, which we want to use in other + // cases. + traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id, span) + } + + /// Normalizes associated types in `value`, potentially returning + /// new obligations that must further be processed. + fn partially_normalize_associated_types_in( + &self, + span: Span, + body_id: hir::HirId, + param_env: ty::ParamEnv<'tcx>, + value: &T, + ) -> InferOk<'tcx, T> + where + T: TypeFoldable<'tcx>, + { + debug!("partially_normalize_associated_types_in(value={:?})", value); + let mut selcx = traits::SelectionContext::new(self); + let cause = ObligationCause::misc(span, body_id); + let traits::Normalized { value, obligations } = + traits::normalize(&mut selcx, param_env, cause, value); + debug!( + "partially_normalize_associated_types_in: result={:?} predicates={:?}", + value, obligations + ); + InferOk { value, obligations } + } +} + +pub trait InferCtxtBuilderExt<'tcx> { + fn enter_canonical_trait_query( + &mut self, + canonical_key: &Canonical<'tcx, K>, + operation: impl FnOnce(&InferCtxt<'_, 'tcx>, &mut dyn TraitEngine<'tcx>, K) -> Fallible, + ) -> Fallible> + where + K: TypeFoldable<'tcx>, + R: Debug + TypeFoldable<'tcx>, + Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable; +} + +impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> { + /// The "main method" for a canonicalized trait query. Given the + /// canonical key `canonical_key`, this method will create a new + /// inference context, instantiate the key, and run your operation + /// `op`. The operation should yield up a result (of type `R`) as + /// well as a set of trait obligations that must be fully + /// satisfied. These obligations will be processed and the + /// canonical result created. + /// + /// Returns `NoSolution` in the event of any error. + /// + /// (It might be mildly nicer to implement this on `TyCtxt`, and + /// not `InferCtxtBuilder`, but that is a bit tricky right now. + /// In part because we would need a `for<'tcx>` sort of + /// bound for the closure and in part because it is convenient to + /// have `'tcx` be free on this function so that we can talk about + /// `K: TypeFoldable<'tcx>`.) + fn enter_canonical_trait_query( + &mut self, + canonical_key: &Canonical<'tcx, K>, + operation: impl FnOnce(&InferCtxt<'_, 'tcx>, &mut dyn TraitEngine<'tcx>, K) -> Fallible, + ) -> Fallible> + where + K: TypeFoldable<'tcx>, + R: Debug + TypeFoldable<'tcx>, + Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable, + { + self.enter_with_canonical( + DUMMY_SP, + canonical_key, + |ref infcx, key, canonical_inference_vars| { + let mut fulfill_cx = TraitEngine::new(infcx.tcx); + let value = operation(infcx, &mut *fulfill_cx, key)?; + infcx.make_canonicalized_query_response( + canonical_inference_vars, + value, + &mut *fulfill_cx, + ) + }, + ) + } +} + +pub trait OutlivesEnvironmentExt<'tcx> { + fn add_implied_bounds( + &mut self, + infcx: &InferCtxt<'a, 'tcx>, + fn_sig_tys: &[Ty<'tcx>], + body_id: hir::HirId, + span: Span, + ); +} + +impl<'tcx> OutlivesEnvironmentExt<'tcx> for OutlivesEnvironment<'tcx> { + /// This method adds "implied bounds" into the outlives environment. + /// Implied bounds are outlives relationships that we can deduce + /// on the basis that certain types must be well-formed -- these are + /// either the types that appear in the function signature or else + /// the input types to an impl. For example, if you have a function + /// like + /// + /// ``` + /// fn foo<'a, 'b, T>(x: &'a &'b [T]) { } + /// ``` + /// + /// we can assume in the caller's body that `'b: 'a` and that `T: + /// 'b` (and hence, transitively, that `T: 'a`). This method would + /// add those assumptions into the outlives-environment. + /// + /// Tests: `src/test/compile-fail/regions-free-region-ordering-*.rs` + fn add_implied_bounds( + &mut self, + infcx: &InferCtxt<'a, 'tcx>, + fn_sig_tys: &[Ty<'tcx>], + body_id: hir::HirId, + span: Span, + ) { + debug!("add_implied_bounds()"); + + for &ty in fn_sig_tys { + let ty = infcx.resolve_vars_if_possible(&ty); + debug!("add_implied_bounds: ty = {}", ty); + let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty, span); + self.add_outlives_bounds(Some(infcx), implied_bounds) + } + } +} diff --git a/src/librustc_trait_selection/lib.rs b/src/librustc_trait_selection/lib.rs new file mode 100644 index 0000000000000..739aff4fb94c9 --- /dev/null +++ b/src/librustc_trait_selection/lib.rs @@ -0,0 +1,32 @@ +//! This crates defines the trait resolution method. +//! +//! - **Traits.** Trait resolution is implemented in the `traits` module. +//! +//! For more information about how rustc works, see the [rustc guide]. +//! +//! [rustc guide]: https://rust-lang.github.io/rustc-guide/ +//! +//! # Note +//! +//! This API is completely unstable and subject to change. + +#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] +#![feature(bool_to_option)] +#![feature(drain_filter)] +#![feature(in_band_lifetimes)] +#![feature(crate_visibility_modifier)] +#![recursion_limit = "512"] // For rustdoc + +#[macro_use] +extern crate rustc_macros; +#[cfg(target_arch = "x86_64")] +#[macro_use] +extern crate rustc_data_structures; +#[macro_use] +extern crate log; +#[macro_use] +extern crate rustc; + +pub mod infer; +pub mod opaque_types; +pub mod traits; diff --git a/src/librustc_infer/infer/opaque_types/mod.rs b/src/librustc_trait_selection/opaque_types.rs similarity index 91% rename from src/librustc_infer/infer/opaque_types/mod.rs rename to src/librustc_trait_selection/opaque_types.rs index 4d264008ee3ed..30189d189f2ed 100644 --- a/src/librustc_infer/infer/opaque_types/mod.rs +++ b/src/librustc_trait_selection/opaque_types.rs @@ -1,18 +1,18 @@ -use crate::infer::error_reporting::{note_and_explain_free_region, note_and_explain_region}; -use crate::infer::{self, InferCtxt, InferOk, TypeVariableOrigin, TypeVariableOriginKind}; +use crate::infer::InferCtxtExt as _; use crate::traits::{self, PredicateObligation}; -use rustc::middle::region; -use rustc::session::config::nightly_options; use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor}; use rustc::ty::free_region_map::FreeRegionRelations; use rustc::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef}; use rustc::ty::{self, GenericParamDefKind, Ty, TyCtxt}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; -use rustc_errors::{struct_span_err, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, DefIdMap}; use rustc_hir::Node; +use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::infer::{self, InferCtxt, InferOk}; +use rustc_session::config::nightly_options; use rustc_span::Span; pub type OpaqueTypeMap<'tcx> = DefIdMap>; @@ -105,7 +105,58 @@ pub enum GenerateMemberConstraints { IfNoStaticBound, } -impl<'a, 'tcx> InferCtxt<'a, 'tcx> { +pub trait InferCtxtExt<'tcx> { + fn instantiate_opaque_types>( + &self, + parent_def_id: DefId, + body_id: hir::HirId, + param_env: ty::ParamEnv<'tcx>, + value: &T, + value_span: Span, + ) -> InferOk<'tcx, (T, OpaqueTypeMap<'tcx>)>; + + fn constrain_opaque_types>( + &self, + opaque_types: &OpaqueTypeMap<'tcx>, + free_region_relations: &FRR, + ); + + fn constrain_opaque_type>( + &self, + def_id: DefId, + opaque_defn: &OpaqueTypeDecl<'tcx>, + mode: GenerateMemberConstraints, + free_region_relations: &FRR, + ); + + /*private*/ + fn generate_member_constraint( + &self, + concrete_ty: Ty<'tcx>, + opaque_type_generics: &ty::Generics, + opaque_defn: &OpaqueTypeDecl<'tcx>, + opaque_type_def_id: DefId, + ); + + /*private*/ + fn member_constraint_feature_gate( + &self, + opaque_defn: &OpaqueTypeDecl<'tcx>, + opaque_type_def_id: DefId, + conflict1: ty::Region<'tcx>, + conflict2: ty::Region<'tcx>, + ) -> bool; + + fn infer_opaque_definition_from_instantiation( + &self, + def_id: DefId, + substs: SubstsRef<'tcx>, + instantiated_ty: Ty<'tcx>, + span: Span, + ) -> Ty<'tcx>; +} + +impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { /// Replaces all opaque types in `value` with fresh inference variables /// and creates appropriate obligations. For example, given the input: /// @@ -131,7 +182,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// obligations /// - `value` -- the value within which we are instantiating opaque types /// - `value_span` -- the span where the value came from, used in error reporting - pub fn instantiate_opaque_types>( + fn instantiate_opaque_types>( &self, parent_def_id: DefId, body_id: hir::HirId, @@ -319,7 +370,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// - `opaque_types` -- the map produced by `instantiate_opaque_types` /// - `free_region_relations` -- something that can be used to relate /// the free regions (`'a`) that appear in the impl trait. - pub fn constrain_opaque_types>( + fn constrain_opaque_types>( &self, opaque_types: &OpaqueTypeMap<'tcx>, free_region_relations: &FRR, @@ -337,7 +388,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } /// See `constrain_opaque_types` for documentation. - pub fn constrain_opaque_type>( + fn constrain_opaque_type>( &self, def_id: DefId, opaque_defn: &OpaqueTypeDecl<'tcx>, @@ -372,7 +423,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { for required_region in required_region_bounds { concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { - tcx: self.tcx, op: |r| self.sub_regions(infer::CallReturn(span), required_region, r), }); } @@ -453,7 +503,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { - tcx: self.tcx, op: |r| self.sub_regions(infer::CallReturn(span), least_region, r), }); } @@ -490,7 +539,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ); concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { - tcx: self.tcx, op: |r| { self.member_constraint( opaque_type_def_id, @@ -579,7 +627,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// - `substs`, the substs used to instantiate this opaque type /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of /// `opaque_defn.concrete_ty` - pub fn infer_opaque_definition_from_instantiation( + fn infer_opaque_definition_from_instantiation( &self, def_id: DefId, substs: SubstsRef<'tcx>, @@ -618,86 +666,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } -pub fn unexpected_hidden_region_diagnostic( - tcx: TyCtxt<'tcx>, - region_scope_tree: Option<®ion::ScopeTree>, - span: Span, - hidden_ty: Ty<'tcx>, - hidden_region: ty::Region<'tcx>, -) -> DiagnosticBuilder<'tcx> { - let mut err = struct_span_err!( - tcx.sess, - span, - E0700, - "hidden type for `impl Trait` captures lifetime that does not appear in bounds", - ); - - // Explain the region we are capturing. - if let ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic | ty::ReEmpty(_) = hidden_region { - // Assuming regionck succeeded (*), we ought to always be - // capturing *some* region from the fn header, and hence it - // ought to be free. So under normal circumstances, we will go - // down this path which gives a decent human readable - // explanation. - // - // (*) if not, the `tainted_by_errors` flag would be set to - // true in any case, so we wouldn't be here at all. - note_and_explain_free_region( - tcx, - &mut err, - &format!("hidden type `{}` captures ", hidden_ty), - hidden_region, - "", - ); - } else { - // Ugh. This is a painful case: the hidden region is not one - // that we can easily summarize or explain. This can happen - // in a case like - // `src/test/ui/multiple-lifetimes/ordinary-bounds-unsuited.rs`: - // - // ``` - // fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> { - // if condition() { a } else { b } - // } - // ``` - // - // Here the captured lifetime is the intersection of `'a` and - // `'b`, which we can't quite express. - - if let Some(region_scope_tree) = region_scope_tree { - // If the `region_scope_tree` is available, this is being - // invoked from the "region inferencer error". We can at - // least report a really cryptic error for now. - note_and_explain_region( - tcx, - region_scope_tree, - &mut err, - &format!("hidden type `{}` captures ", hidden_ty), - hidden_region, - "", - ); - } else { - // If the `region_scope_tree` is *unavailable*, this is - // being invoked by the code that comes *after* region - // inferencing. This is a bug, as the region inferencer - // ought to have noticed the failed constraint and invoked - // error reporting, which in turn should have prevented us - // from getting trying to infer the hidden type - // completely. - tcx.sess.delay_span_bug( - span, - &format!( - "hidden type captures unexpected lifetime `{:?}` \ - but no region inference failure", - hidden_region, - ), - ); - } - } - - err -} - // Visitor that requires that (almost) all regions in the type visited outlive // `least_region`. We cannot use `push_outlives_components` because regions in // closure signatures are not included in their outlives components. We need to @@ -711,15 +679,11 @@ pub fn unexpected_hidden_region_diagnostic( // // We ignore any type parameters because impl trait values are assumed to // capture all the in-scope type parameters. -struct ConstrainOpaqueTypeRegionVisitor<'tcx, OP> -where - OP: FnMut(ty::Region<'tcx>), -{ - tcx: TyCtxt<'tcx>, +struct ConstrainOpaqueTypeRegionVisitor { op: OP, } -impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<'tcx, OP> +impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor where OP: FnMut(ty::Region<'tcx>), { @@ -746,27 +710,27 @@ where } match ty.kind { - ty::Closure(def_id, ref substs) => { + ty::Closure(_, ref substs) => { // Skip lifetime parameters of the enclosing item(s) - for upvar_ty in substs.as_closure().upvar_tys(def_id, self.tcx) { + for upvar_ty in substs.as_closure().upvar_tys() { upvar_ty.visit_with(self); } - substs.as_closure().sig_ty(def_id, self.tcx).visit_with(self); + substs.as_closure().sig_as_fn_ptr_ty().visit_with(self); } - ty::Generator(def_id, ref substs, _) => { + ty::Generator(_, ref substs, _) => { // Skip lifetime parameters of the enclosing item(s) // Also skip the witness type, because that has no free regions. - for upvar_ty in substs.as_generator().upvar_tys(def_id, self.tcx) { + for upvar_ty in substs.as_generator().upvar_tys() { upvar_ty.visit_with(self); } - substs.as_generator().return_ty(def_id, self.tcx).visit_with(self); - substs.as_generator().yield_ty(def_id, self.tcx).visit_with(self); - substs.as_generator().resume_ty(def_id, self.tcx).visit_with(self); + substs.as_generator().return_ty().visit_with(self); + substs.as_generator().yield_ty().visit_with(self); + substs.as_generator().resume_ty().visit_with(self); } _ => { ty.super_visit_with(self); @@ -852,11 +816,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { // The regions that we expect from borrow checking. ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {} - ty::ReEmpty(_) - | ty::RePlaceholder(_) - | ty::ReVar(_) - | ty::ReScope(_) - | ty::ReClosureBound(_) => { + ty::ReEmpty(_) | ty::RePlaceholder(_) | ty::ReVar(_) | ty::ReScope(_) => { // All of the regions in the type should either have been // erased by writeback, or mapped back to named regions by // borrow checking. diff --git a/src/librustc_infer/traits/auto_trait.rs b/src/librustc_trait_selection/traits/auto_trait.rs similarity index 98% rename from src/librustc_infer/traits/auto_trait.rs rename to src/librustc_trait_selection/traits/auto_trait.rs index 39be8fc1c0fe6..bd980e6eb8b8a 100644 --- a/src/librustc_infer/traits/auto_trait.rs +++ b/src/librustc_trait_selection/traits/auto_trait.rs @@ -113,7 +113,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { return AutoTraitResult::ExplicitImpl; } - return tcx.infer_ctxt().enter(|mut infcx| { + tcx.infer_ctxt().enter(|infcx| { let mut fresh_preds = FxHashSet::default(); // Due to the way projections are handled by SelectionContext, we need to run @@ -164,7 +164,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { let (full_env, full_user_env) = self .evaluate_predicates( - &mut infcx, + &infcx, trait_did, ty, new_env, @@ -219,8 +219,8 @@ impl<'tcx> AutoTraitFinder<'tcx> { let info = AutoTraitInfo { full_user_env, region_data, vid_to_region }; - return AutoTraitResult::PositiveImpl(auto_trait_callback(&infcx, info)); - }); + AutoTraitResult::PositiveImpl(auto_trait_callback(&infcx, info)) + }) } } @@ -384,7 +384,7 @@ impl AutoTraitFinder<'tcx> { ty, trait_did, new_env, final_user_env ); - return Some((new_env, final_user_env)); + Some((new_env, final_user_env)) } /// This method is designed to work around the following issue: @@ -492,7 +492,7 @@ impl AutoTraitFinder<'tcx> { } _ => {} } - return true; + true }); if should_add_new { @@ -591,15 +591,15 @@ impl AutoTraitFinder<'tcx> { } fn is_param_no_infer(&self, substs: SubstsRef<'_>) -> bool { - return self.is_of_param(substs.type_at(0)) && !substs.types().any(|t| t.has_infer_types()); + self.is_of_param(substs.type_at(0)) && !substs.types().any(|t| t.has_infer_types()) } pub fn is_of_param(&self, ty: Ty<'_>) -> bool { - return match ty.kind { + match ty.kind { ty::Param(_) => true, ty::Projection(p) => self.is_of_param(p.self_ty()), _ => false, - }; + } } fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'_>) -> bool { @@ -804,7 +804,7 @@ impl AutoTraitFinder<'tcx> { _ => panic!("Unexpected predicate {:?} {:?}", ty, predicate), }; } - return true; + true } pub fn clean_pred( diff --git a/src/librustc_infer/traits/codegen/mod.rs b/src/librustc_trait_selection/traits/codegen/mod.rs similarity index 71% rename from src/librustc_infer/traits/codegen/mod.rs rename to src/librustc_trait_selection/traits/codegen/mod.rs index f499565e9192a..5c2fc3f305c1f 100644 --- a/src/librustc_infer/traits/codegen/mod.rs +++ b/src/librustc_trait_selection/traits/codegen/mod.rs @@ -72,7 +72,7 @@ pub fn codegen_fulfill_obligation<'tcx>( debug!("fulfill_obligation: register_predicate_obligation {:?}", predicate); fulfill_cx.register_predicate_obligation(&infcx, predicate); }); - let vtable = infcx.drain_fulfillment_cx_or_panic(&mut fulfill_cx, &vtable); + let vtable = drain_fulfillment_cx_or_panic(&infcx, &mut fulfill_cx, &vtable); info!("Cache miss: {:?} => {:?}", trait_ref, vtable); Some(vtable) @@ -81,34 +81,32 @@ pub fn codegen_fulfill_obligation<'tcx>( // # Global Cache -impl<'a, 'tcx> InferCtxt<'a, 'tcx> { - /// Finishes processes any obligations that remain in the - /// fulfillment context, and then returns the result with all type - /// variables removed and regions erased. Because this is intended - /// for use after type-check has completed, if any errors occur, - /// it will panic. It is used during normalization and other cases - /// where processing the obligations in `fulfill_cx` may cause - /// type inference variables that appear in `result` to be - /// unified, and hence we need to process those obligations to get - /// the complete picture of the type. - fn drain_fulfillment_cx_or_panic( - &self, - fulfill_cx: &mut FulfillmentContext<'tcx>, - result: &T, - ) -> T - where - T: TypeFoldable<'tcx>, - { - debug!("drain_fulfillment_cx_or_panic()"); +/// Finishes processes any obligations that remain in the +/// fulfillment context, and then returns the result with all type +/// variables removed and regions erased. Because this is intended +/// for use after type-check has completed, if any errors occur, +/// it will panic. It is used during normalization and other cases +/// where processing the obligations in `fulfill_cx` may cause +/// type inference variables that appear in `result` to be +/// unified, and hence we need to process those obligations to get +/// the complete picture of the type. +fn drain_fulfillment_cx_or_panic( + infcx: &InferCtxt<'_, 'tcx>, + fulfill_cx: &mut FulfillmentContext<'tcx>, + result: &T, +) -> T +where + T: TypeFoldable<'tcx>, +{ + debug!("drain_fulfillment_cx_or_panic()"); - // In principle, we only need to do this so long as `result` - // contains unbound type parameters. It could be a slight - // optimization to stop iterating early. - if let Err(errors) = fulfill_cx.select_all_or_error(self) { - bug!("Encountered errors `{:?}` resolving bounds after type-checking", errors); - } - - let result = self.resolve_vars_if_possible(result); - self.tcx.erase_regions(&result) + // In principle, we only need to do this so long as `result` + // contains unbound type parameters. It could be a slight + // optimization to stop iterating early. + if let Err(errors) = fulfill_cx.select_all_or_error(infcx) { + bug!("Encountered errors `{:?}` resolving bounds after type-checking", errors); } + + let result = infcx.resolve_vars_if_possible(result); + infcx.tcx.erase_regions(&result) } diff --git a/src/librustc_infer/traits/coherence.rs b/src/librustc_trait_selection/traits/coherence.rs similarity index 99% rename from src/librustc_infer/traits/coherence.rs rename to src/librustc_trait_selection/traits/coherence.rs index 9cf4ed8fe573a..dc13af99fec6c 100644 --- a/src/librustc_infer/traits/coherence.rs +++ b/src/librustc_trait_selection/traits/coherence.rs @@ -221,10 +221,10 @@ pub fn trait_ref_is_knowable<'tcx>( // we are an owner. if orphan_check_trait_ref(tcx, trait_ref, InCrate::Local).is_ok() { debug!("trait_ref_is_knowable: orphan check passed"); - return None; + None } else { debug!("trait_ref_is_knowable: nonlocal, nonfundamental, unowned"); - return Some(Conflict::Upstream); + Some(Conflict::Upstream) } } @@ -451,7 +451,7 @@ fn def_id_is_local(def_id: DefId, in_crate: InCrate) -> bool { } } -fn ty_is_non_local_constructor<'tcx>(ty: Ty<'tcx>, in_crate: InCrate) -> Option> { +fn ty_is_non_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> Option> { debug!("ty_is_non_local_constructor({:?})", ty); match ty.kind { diff --git a/src/librustc_trait_selection/traits/engine.rs b/src/librustc_trait_selection/traits/engine.rs new file mode 100644 index 0000000000000..ee4715e0c20f6 --- /dev/null +++ b/src/librustc_trait_selection/traits/engine.rs @@ -0,0 +1,14 @@ +use rustc::ty::TyCtxt; + +use super::FulfillmentContext; +use super::TraitEngine; + +pub trait TraitEngineExt<'tcx> { + fn new(tcx: TyCtxt<'tcx>) -> Box; +} + +impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> { + fn new(_tcx: TyCtxt<'tcx>) -> Box { + Box::new(FulfillmentContext::new()) + } +} diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs new file mode 100644 index 0000000000000..12939519fc28f --- /dev/null +++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs @@ -0,0 +1,1898 @@ +pub mod on_unimplemented; +pub mod suggestions; + +use super::{ + ConstEvalFailure, EvaluationResult, FulfillmentError, FulfillmentErrorCode, + MismatchedProjectionTypes, Obligation, ObligationCause, ObligationCauseCode, + OnUnimplementedDirective, OnUnimplementedNote, OutputTypeParameterMismatch, Overflow, + PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe, +}; + +use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode}; +use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use crate::infer::{self, InferCtxt, TyCtxtInferExt}; +use rustc::mir::interpret::ErrorHandled; +use rustc::ty::error::ExpectedFound; +use rustc::ty::fast_reject; +use rustc::ty::fold::TypeFolder; +use rustc::ty::SubtypePredicate; +use rustc::ty::{ + self, AdtKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, +}; +use rustc_data_structures::fx::FxHashMap; +use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; +use rustc_hir as hir; +use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_hir::{Node, QPath, TyKind, WhereBoundPredicate, WherePredicate}; +use rustc_session::DiagnosticMessageId; +use rustc_span::source_map::SourceMap; +use rustc_span::{ExpnKind, Span, DUMMY_SP}; +use std::fmt; + +use crate::traits::query::evaluate_obligation::InferCtxtExt as _; +use crate::traits::query::normalize::AtExt as _; +use on_unimplemented::InferCtxtExt as _; +use suggestions::InferCtxtExt as _; + +pub use rustc_infer::traits::error_reporting::*; + +pub trait InferCtxtExt<'tcx> { + fn report_fulfillment_errors( + &self, + errors: &[FulfillmentError<'tcx>], + body_id: Option, + fallback_has_occurred: bool, + ); + + fn report_overflow_error( + &self, + obligation: &Obligation<'tcx, T>, + suggest_increasing_limit: bool, + ) -> ! + where + T: fmt::Display + TypeFoldable<'tcx>; + + fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !; + + fn report_selection_error( + &self, + obligation: &PredicateObligation<'tcx>, + error: &SelectionError<'tcx>, + fallback_has_occurred: bool, + points_at_arg: bool, + ); + + /// Given some node representing a fn-like thing in the HIR map, + /// returns a span and `ArgKind` information that describes the + /// arguments it expects. This can be supplied to + /// `report_arg_count_mismatch`. + fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec); + + /// Reports an error when the number of arguments needed by a + /// trait match doesn't match the number that the expression + /// provides. + fn report_arg_count_mismatch( + &self, + span: Span, + found_span: Option, + expected_args: Vec, + found_args: Vec, + is_closure: bool, + ) -> DiagnosticBuilder<'tcx>; +} + +impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { + fn report_fulfillment_errors( + &self, + errors: &[FulfillmentError<'tcx>], + body_id: Option, + fallback_has_occurred: bool, + ) { + #[derive(Debug)] + struct ErrorDescriptor<'tcx> { + predicate: ty::Predicate<'tcx>, + index: Option, // None if this is an old error + } + + let mut error_map: FxHashMap<_, Vec<_>> = self + .reported_trait_errors + .borrow() + .iter() + .map(|(&span, predicates)| { + ( + span, + predicates + .iter() + .map(|&predicate| ErrorDescriptor { predicate, index: None }) + .collect(), + ) + }) + .collect(); + + for (index, error) in errors.iter().enumerate() { + // We want to ignore desugarings here: spans are equivalent even + // if one is the result of a desugaring and the other is not. + let mut span = error.obligation.cause.span; + let expn_data = span.ctxt().outer_expn_data(); + if let ExpnKind::Desugaring(_) = expn_data.kind { + span = expn_data.call_site; + } + + error_map.entry(span).or_default().push(ErrorDescriptor { + predicate: error.obligation.predicate, + index: Some(index), + }); + + self.reported_trait_errors + .borrow_mut() + .entry(span) + .or_default() + .push(error.obligation.predicate.clone()); + } + + // We do this in 2 passes because we want to display errors in order, though + // maybe it *is* better to sort errors by span or something. + let mut is_suppressed = vec![false; errors.len()]; + for (_, error_set) in error_map.iter() { + // We want to suppress "duplicate" errors with the same span. + for error in error_set { + if let Some(index) = error.index { + // Suppress errors that are either: + // 1) strictly implied by another error. + // 2) implied by an error with a smaller index. + for error2 in error_set { + if error2.index.map_or(false, |index2| is_suppressed[index2]) { + // Avoid errors being suppressed by already-suppressed + // errors, to prevent all errors from being suppressed + // at once. + continue; + } + + if self.error_implies(&error2.predicate, &error.predicate) + && !(error2.index >= error.index + && self.error_implies(&error.predicate, &error2.predicate)) + { + info!("skipping {:?} (implied by {:?})", error, error2); + is_suppressed[index] = true; + break; + } + } + } + } + } + + for (error, suppressed) in errors.iter().zip(is_suppressed) { + if !suppressed { + self.report_fulfillment_error(error, body_id, fallback_has_occurred); + } + } + } + + /// Reports that an overflow has occurred and halts compilation. We + /// halt compilation unconditionally because it is important that + /// overflows never be masked -- they basically represent computations + /// whose result could not be truly determined and thus we can't say + /// if the program type checks or not -- and they are unusual + /// occurrences in any case. + fn report_overflow_error( + &self, + obligation: &Obligation<'tcx, T>, + suggest_increasing_limit: bool, + ) -> ! + where + T: fmt::Display + TypeFoldable<'tcx>, + { + let predicate = self.resolve_vars_if_possible(&obligation.predicate); + let mut err = struct_span_err!( + self.tcx.sess, + obligation.cause.span, + E0275, + "overflow evaluating the requirement `{}`", + predicate + ); + + if suggest_increasing_limit { + self.suggest_new_overflow_limit(&mut err); + } + + self.note_obligation_cause_code( + &mut err, + &obligation.predicate, + &obligation.cause.code, + &mut vec![], + ); + + err.emit(); + self.tcx.sess.abort_if_errors(); + bug!(); + } + + /// Reports that a cycle was detected which led to overflow and halts + /// compilation. This is equivalent to `report_overflow_error` except + /// that we can give a more helpful error message (and, in particular, + /// we do not suggest increasing the overflow limit, which is not + /// going to help). + fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! { + let cycle = self.resolve_vars_if_possible(&cycle.to_owned()); + assert!(!cycle.is_empty()); + + debug!("report_overflow_error_cycle: cycle={:?}", cycle); + + self.report_overflow_error(&cycle[0], false); + } + + fn report_selection_error( + &self, + obligation: &PredicateObligation<'tcx>, + error: &SelectionError<'tcx>, + fallback_has_occurred: bool, + points_at_arg: bool, + ) { + let tcx = self.tcx; + let span = obligation.cause.span; + + let mut err = match *error { + SelectionError::Unimplemented => { + if let ObligationCauseCode::CompareImplMethodObligation { + item_name, + impl_item_def_id, + trait_item_def_id, + } + | ObligationCauseCode::CompareImplTypeObligation { + item_name, + impl_item_def_id, + trait_item_def_id, + } = obligation.cause.code + { + self.report_extra_impl_obligation( + span, + item_name, + impl_item_def_id, + trait_item_def_id, + &format!("`{}`", obligation.predicate), + ) + .emit(); + return; + } + match obligation.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() { + return; + } + let trait_ref = trait_predicate.to_poly_trait_ref(); + let (post_message, pre_message, type_def) = self + .get_parent_trait_ref(&obligation.cause.code) + .map(|(t, s)| { + ( + format!(" in `{}`", t), + format!("within `{}`, ", t), + s.map(|s| (format!("within this `{}`", t), s)), + ) + }) + .unwrap_or_default(); + + let OnUnimplementedNote { message, label, note, enclosing_scope } = + self.on_unimplemented_note(trait_ref, obligation); + let have_alt_message = message.is_some() || label.is_some(); + let is_try = self + .tcx + .sess + .source_map() + .span_to_snippet(span) + .map(|s| &s == "?") + .unwrap_or(false); + let is_from = format!("{}", trait_ref.print_only_trait_path()) + .starts_with("std::convert::From<"); + let (message, note) = if is_try && is_from { + ( + Some(format!( + "`?` couldn't convert the error to `{}`", + trait_ref.self_ty(), + )), + Some( + "the question mark operation (`?`) implicitly performs a \ + conversion on the error value using the `From` trait" + .to_owned(), + ), + ) + } else { + (message, note) + }; + + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0277, + "{}", + message.unwrap_or_else(|| format!( + "the trait bound `{}` is not satisfied{}", + trait_ref.without_const().to_predicate(), + post_message, + )) + ); + + let explanation = + if obligation.cause.code == ObligationCauseCode::MainFunctionType { + "consider using `()`, or a `Result`".to_owned() + } else { + format!( + "{}the trait `{}` is not implemented for `{}`", + pre_message, + trait_ref.print_only_trait_path(), + trait_ref.self_ty(), + ) + }; + + if self.suggest_add_reference_to_arg( + &obligation, + &mut err, + &trait_ref, + points_at_arg, + have_alt_message, + ) { + self.note_obligation_cause(&mut err, obligation); + err.emit(); + return; + } + if let Some(ref s) = label { + // If it has a custom `#[rustc_on_unimplemented]` + // error message, let's display it as the label! + err.span_label(span, s.as_str()); + err.help(&explanation); + } else { + err.span_label(span, explanation); + } + if let Some((msg, span)) = type_def { + err.span_label(span, &msg); + } + if let Some(ref s) = note { + // If it has a custom `#[rustc_on_unimplemented]` note, let's display it + err.note(s.as_str()); + } + if let Some(ref s) = enclosing_scope { + let enclosing_scope_span = tcx.def_span( + tcx.hir() + .opt_local_def_id(obligation.cause.body_id) + .unwrap_or_else(|| { + tcx.hir().body_owner_def_id(hir::BodyId { + hir_id: obligation.cause.body_id, + }) + }), + ); + + err.span_label(enclosing_scope_span, s.as_str()); + } + + self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err); + self.suggest_fn_call(&obligation, &mut err, &trait_ref, points_at_arg); + self.suggest_remove_reference(&obligation, &mut err, &trait_ref); + self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref); + self.note_version_mismatch(&mut err, &trait_ref); + if self.suggest_impl_trait(&mut err, span, &obligation, &trait_ref) { + err.emit(); + return; + } + + // Try to report a help message + if !trait_ref.has_infer_types_or_consts() + && self.predicate_can_apply(obligation.param_env, trait_ref) + { + // If a where-clause may be useful, remind the + // user that they can add it. + // + // don't display an on-unimplemented note, as + // these notes will often be of the form + // "the type `T` can't be frobnicated" + // which is somewhat confusing. + self.suggest_restricting_param_bound( + &mut err, + &trait_ref, + obligation.cause.body_id, + ); + } else { + if !have_alt_message { + // Can't show anything else useful, try to find similar impls. + let impl_candidates = self.find_similar_impl_candidates(trait_ref); + self.report_similar_impl_candidates(impl_candidates, &mut err); + } + self.suggest_change_mut( + &obligation, + &mut err, + &trait_ref, + points_at_arg, + ); + } + + // If this error is due to `!: Trait` not implemented but `(): Trait` is + // implemented, and fallback has occurred, then it could be due to a + // variable that used to fallback to `()` now falling back to `!`. Issue a + // note informing about the change in behaviour. + if trait_predicate.skip_binder().self_ty().is_never() + && fallback_has_occurred + { + let predicate = trait_predicate.map_bound(|mut trait_pred| { + trait_pred.trait_ref.substs = self.tcx.mk_substs_trait( + self.tcx.mk_unit(), + &trait_pred.trait_ref.substs[1..], + ); + trait_pred + }); + let unit_obligation = Obligation { + predicate: ty::Predicate::Trait( + predicate, + hir::Constness::NotConst, + ), + ..obligation.clone() + }; + if self.predicate_may_hold(&unit_obligation) { + err.note( + "the trait is implemented for `()`. \ + Possibly this error has been caused by changes to \ + Rust's type-inference algorithm (see issue #48950 \ + \ + for more information). Consider whether you meant to use \ + the type `()` here instead.", + ); + } + } + + err + } + + ty::Predicate::Subtype(ref predicate) => { + // Errors for Subtype predicates show up as + // `FulfillmentErrorCode::CodeSubtypeError`, + // not selection error. + span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate) + } + + ty::Predicate::RegionOutlives(ref predicate) => { + let predicate = self.resolve_vars_if_possible(predicate); + let err = self + .region_outlives_predicate(&obligation.cause, &predicate) + .err() + .unwrap(); + struct_span_err!( + self.tcx.sess, + span, + E0279, + "the requirement `{}` is not satisfied (`{}`)", + predicate, + err, + ) + } + + ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => { + let predicate = self.resolve_vars_if_possible(&obligation.predicate); + struct_span_err!( + self.tcx.sess, + span, + E0280, + "the requirement `{}` is not satisfied", + predicate + ) + } + + ty::Predicate::ObjectSafe(trait_def_id) => { + let violations = self.tcx.object_safety_violations(trait_def_id); + report_object_safety_error(self.tcx, span, trait_def_id, violations) + } + + ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => { + let found_kind = self.closure_kind(closure_substs).unwrap(); + let closure_span = + self.tcx.sess.source_map().guess_head_span( + self.tcx.hir().span_if_local(closure_def_id).unwrap(), + ); + let hir_id = self.tcx.hir().as_local_hir_id(closure_def_id).unwrap(); + let mut err = struct_span_err!( + self.tcx.sess, + closure_span, + E0525, + "expected a closure that implements the `{}` trait, \ + but this closure only implements `{}`", + kind, + found_kind + ); + + err.span_label( + closure_span, + format!("this closure implements `{}`, not `{}`", found_kind, kind), + ); + err.span_label( + obligation.cause.span, + format!("the requirement to implement `{}` derives from here", kind), + ); + + // Additional context information explaining why the closure only implements + // a particular trait. + if let Some(tables) = self.in_progress_tables { + let tables = tables.borrow(); + match (found_kind, tables.closure_kind_origins().get(hir_id)) { + (ty::ClosureKind::FnOnce, Some((span, name))) => { + err.span_label( + *span, + format!( + "closure is `FnOnce` because it moves the \ + variable `{}` out of its environment", + name + ), + ); + } + (ty::ClosureKind::FnMut, Some((span, name))) => { + err.span_label( + *span, + format!( + "closure is `FnMut` because it mutates the \ + variable `{}` here", + name + ), + ); + } + _ => {} + } + } + + err.emit(); + return; + } + + ty::Predicate::WellFormed(ty) => { + // WF predicates cannot themselves make + // errors. They can only block due to + // ambiguity; otherwise, they always + // degenerate into other obligations + // (which may fail). + span_bug!(span, "WF predicate not satisfied for {:?}", ty); + } + + ty::Predicate::ConstEvaluatable(..) => { + // Errors for `ConstEvaluatable` predicates show up as + // `SelectionError::ConstEvalFailure`, + // not `Unimplemented`. + span_bug!( + span, + "const-evaluatable requirement gave wrong error: `{:?}`", + obligation + ) + } + } + } + + OutputTypeParameterMismatch(ref found_trait_ref, ref expected_trait_ref, _) => { + let found_trait_ref = self.resolve_vars_if_possible(&*found_trait_ref); + let expected_trait_ref = self.resolve_vars_if_possible(&*expected_trait_ref); + + if expected_trait_ref.self_ty().references_error() { + return; + } + + let found_trait_ty = found_trait_ref.self_ty(); + + let found_did = match found_trait_ty.kind { + ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did), + ty::Adt(def, _) => Some(def.did), + _ => None, + }; + + let found_span = found_did + .and_then(|did| self.tcx.hir().span_if_local(did)) + .map(|sp| self.tcx.sess.source_map().guess_head_span(sp)); // the sp could be an fn def + + if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) { + // We check closures twice, with obligations flowing in different directions, + // but we want to complain about them only once. + return; + } + + self.reported_closure_mismatch.borrow_mut().insert((span, found_span)); + + let found = match found_trait_ref.skip_binder().substs.type_at(1).kind { + ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()], + _ => vec![ArgKind::empty()], + }; + + let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1); + let expected = match expected_ty.kind { + ty::Tuple(ref tys) => tys + .iter() + .map(|t| ArgKind::from_expected_ty(t.expect_ty(), Some(span))) + .collect(), + _ => vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())], + }; + + if found.len() == expected.len() { + self.report_closure_arg_mismatch( + span, + found_span, + found_trait_ref, + expected_trait_ref, + ) + } else { + let (closure_span, found) = found_did + .and_then(|did| self.tcx.hir().get_if_local(did)) + .map(|node| { + let (found_span, found) = self.get_fn_like_arguments(node); + (Some(found_span), found) + }) + .unwrap_or((found_span, found)); + + self.report_arg_count_mismatch( + span, + closure_span, + expected, + found, + found_trait_ty.is_closure(), + ) + } + } + + TraitNotObjectSafe(did) => { + let violations = self.tcx.object_safety_violations(did); + report_object_safety_error(self.tcx, span, did, violations) + } + + ConstEvalFailure(ErrorHandled::TooGeneric) => { + // In this instance, we have a const expression containing an unevaluated + // generic parameter. We have no idea whether this expression is valid or + // not (e.g. it might result in an error), but we don't want to just assume + // that it's okay, because that might result in post-monomorphisation time + // errors. The onus is really on the caller to provide values that it can + // prove are well-formed. + let mut err = self + .tcx + .sess + .struct_span_err(span, "constant expression depends on a generic parameter"); + // FIXME(const_generics): we should suggest to the user how they can resolve this + // issue. However, this is currently not actually possible + // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083). + err.note("this may fail depending on what value the parameter takes"); + err + } + + // Already reported in the query. + ConstEvalFailure(ErrorHandled::Reported) => { + self.tcx.sess.delay_span_bug(span, "constant in type had an ignored error"); + return; + } + + Overflow => { + bug!("overflow should be handled before the `report_selection_error` path"); + } + }; + + self.note_obligation_cause(&mut err, obligation); + self.point_at_returns_when_relevant(&mut err, &obligation); + + err.emit(); + } + + /// Given some node representing a fn-like thing in the HIR map, + /// returns a span and `ArgKind` information that describes the + /// arguments it expects. This can be supplied to + /// `report_arg_count_mismatch`. + fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec) { + match node { + Node::Expr(&hir::Expr { + kind: hir::ExprKind::Closure(_, ref _decl, id, span, _), + .. + }) => ( + self.tcx.sess.source_map().guess_head_span(span), + self.tcx + .hir() + .body(id) + .params + .iter() + .map(|arg| { + if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } = + *arg.pat + { + ArgKind::Tuple( + Some(span), + args.iter() + .map(|pat| { + let snippet = self + .tcx + .sess + .source_map() + .span_to_snippet(pat.span) + .unwrap(); + (snippet, "_".to_owned()) + }) + .collect::>(), + ) + } else { + let name = + self.tcx.sess.source_map().span_to_snippet(arg.pat.span).unwrap(); + ArgKind::Arg(name, "_".to_owned()) + } + }) + .collect::>(), + ), + Node::Item(&hir::Item { span, kind: hir::ItemKind::Fn(ref sig, ..), .. }) + | Node::ImplItem(&hir::ImplItem { + span, + kind: hir::ImplItemKind::Fn(ref sig, _), + .. + }) + | Node::TraitItem(&hir::TraitItem { + span, + kind: hir::TraitItemKind::Fn(ref sig, _), + .. + }) => ( + self.tcx.sess.source_map().guess_head_span(span), + sig.decl + .inputs + .iter() + .map(|arg| match arg.clone().kind { + hir::TyKind::Tup(ref tys) => ArgKind::Tuple( + Some(arg.span), + vec![("_".to_owned(), "_".to_owned()); tys.len()], + ), + _ => ArgKind::empty(), + }) + .collect::>(), + ), + Node::Ctor(ref variant_data) => { + let span = variant_data + .ctor_hir_id() + .map(|hir_id| self.tcx.hir().span(hir_id)) + .unwrap_or(DUMMY_SP); + let span = self.tcx.sess.source_map().guess_head_span(span); + + (span, vec![ArgKind::empty(); variant_data.fields().len()]) + } + _ => panic!("non-FnLike node found: {:?}", node), + } + } + + /// Reports an error when the number of arguments needed by a + /// trait match doesn't match the number that the expression + /// provides. + fn report_arg_count_mismatch( + &self, + span: Span, + found_span: Option, + expected_args: Vec, + found_args: Vec, + is_closure: bool, + ) -> DiagnosticBuilder<'tcx> { + let kind = if is_closure { "closure" } else { "function" }; + + let args_str = |arguments: &[ArgKind], other: &[ArgKind]| { + let arg_length = arguments.len(); + let distinct = match &other[..] { + &[ArgKind::Tuple(..)] => true, + _ => false, + }; + match (arg_length, arguments.get(0)) { + (1, Some(&ArgKind::Tuple(_, ref fields))) => { + format!("a single {}-tuple as argument", fields.len()) + } + _ => format!( + "{} {}argument{}", + arg_length, + if distinct && arg_length > 1 { "distinct " } else { "" }, + pluralize!(arg_length) + ), + } + }; + + let expected_str = args_str(&expected_args, &found_args); + let found_str = args_str(&found_args, &expected_args); + + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0593, + "{} is expected to take {}, but it takes {}", + kind, + expected_str, + found_str, + ); + + err.span_label(span, format!("expected {} that takes {}", kind, expected_str)); + + if let Some(found_span) = found_span { + err.span_label(found_span, format!("takes {}", found_str)); + + // move |_| { ... } + // ^^^^^^^^-- def_span + // + // move |_| { ... } + // ^^^^^-- prefix + let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span); + // move |_| { ... } + // ^^^-- pipe_span + let pipe_span = + if let Some(span) = found_span.trim_start(prefix_span) { span } else { found_span }; + + // Suggest to take and ignore the arguments with expected_args_length `_`s if + // found arguments is empty (assume the user just wants to ignore args in this case). + // For example, if `expected_args_length` is 2, suggest `|_, _|`. + if found_args.is_empty() && is_closure { + let underscores = vec!["_"; expected_args.len()].join(", "); + err.span_suggestion_verbose( + pipe_span, + &format!( + "consider changing the closure to take and ignore the expected argument{}", + pluralize!(expected_args.len()) + ), + format!("|{}|", underscores), + Applicability::MachineApplicable, + ); + } + + if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] { + if fields.len() == expected_args.len() { + let sugg = fields + .iter() + .map(|(name, _)| name.to_owned()) + .collect::>() + .join(", "); + err.span_suggestion_verbose( + found_span, + "change the closure to take multiple arguments instead of a single tuple", + format!("|{}|", sugg), + Applicability::MachineApplicable, + ); + } + } + if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] { + if fields.len() == found_args.len() && is_closure { + let sugg = format!( + "|({}){}|", + found_args + .iter() + .map(|arg| match arg { + ArgKind::Arg(name, _) => name.to_owned(), + _ => "_".to_owned(), + }) + .collect::>() + .join(", "), + // add type annotations if available + if found_args.iter().any(|arg| match arg { + ArgKind::Arg(_, ty) => ty != "_", + _ => false, + }) { + format!( + ": ({})", + fields + .iter() + .map(|(_, ty)| ty.to_owned()) + .collect::>() + .join(", ") + ) + } else { + String::new() + }, + ); + err.span_suggestion_verbose( + found_span, + "change the closure to accept a tuple instead of individual arguments", + sugg, + Applicability::MachineApplicable, + ); + } + } + } + + err + } +} + +trait InferCtxtPrivExt<'tcx> { + // returns if `cond` not occurring implies that `error` does not occur - i.e., that + // `error` occurring implies that `cond` occurs. + fn error_implies(&self, cond: &ty::Predicate<'tcx>, error: &ty::Predicate<'tcx>) -> bool; + + fn report_fulfillment_error( + &self, + error: &FulfillmentError<'tcx>, + body_id: Option, + fallback_has_occurred: bool, + ); + + fn report_projection_error( + &self, + obligation: &PredicateObligation<'tcx>, + error: &MismatchedProjectionTypes<'tcx>, + ); + + fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool; + + fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str>; + + fn find_similar_impl_candidates( + &self, + trait_ref: ty::PolyTraitRef<'tcx>, + ) -> Vec>; + + fn report_similar_impl_candidates( + &self, + impl_candidates: Vec>, + err: &mut DiagnosticBuilder<'_>, + ); + + /// Gets the parent trait chain start + fn get_parent_trait_ref( + &self, + code: &ObligationCauseCode<'tcx>, + ) -> Option<(String, Option)>; + + /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait + /// with the same path as `trait_ref`, a help message about + /// a probable version mismatch is added to `err` + fn note_version_mismatch( + &self, + err: &mut DiagnosticBuilder<'_>, + trait_ref: &ty::PolyTraitRef<'tcx>, + ); + + fn mk_obligation_for_def_id( + &self, + def_id: DefId, + output_ty: Ty<'tcx>, + cause: ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> PredicateObligation<'tcx>; + + fn maybe_report_ambiguity( + &self, + obligation: &PredicateObligation<'tcx>, + body_id: Option, + ); + + fn predicate_can_apply( + &self, + param_env: ty::ParamEnv<'tcx>, + pred: ty::PolyTraitRef<'tcx>, + ) -> bool; + + fn note_obligation_cause( + &self, + err: &mut DiagnosticBuilder<'_>, + obligation: &PredicateObligation<'tcx>, + ); + + fn suggest_unsized_bound_if_applicable( + &self, + err: &mut DiagnosticBuilder<'_>, + obligation: &PredicateObligation<'tcx>, + ); + + fn is_recursive_obligation( + &self, + obligated_types: &mut Vec<&ty::TyS<'tcx>>, + cause_code: &ObligationCauseCode<'tcx>, + ) -> bool; +} + +impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { + // returns if `cond` not occurring implies that `error` does not occur - i.e., that + // `error` occurring implies that `cond` occurs. + fn error_implies(&self, cond: &ty::Predicate<'tcx>, error: &ty::Predicate<'tcx>) -> bool { + if cond == error { + return true; + } + + let (cond, error) = match (cond, error) { + (&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error, _)) => (cond, error), + _ => { + // FIXME: make this work in other cases too. + return false; + } + }; + + for implication in super::elaborate_predicates(self.tcx, vec![*cond]) { + 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. + // Eventually I'll need to implement param-env-aware + // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic. + let param_env = ty::ParamEnv::empty(); + if self.can_sub(param_env, error, implication).is_ok() { + debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication); + return true; + } + } + } + + false + } + + fn report_fulfillment_error( + &self, + error: &FulfillmentError<'tcx>, + body_id: Option, + fallback_has_occurred: bool, + ) { + debug!("report_fulfillment_error({:?})", error); + match error.code { + FulfillmentErrorCode::CodeSelectionError(ref selection_error) => { + self.report_selection_error( + &error.obligation, + selection_error, + fallback_has_occurred, + error.points_at_arg_span, + ); + } + FulfillmentErrorCode::CodeProjectionError(ref e) => { + self.report_projection_error(&error.obligation, e); + } + FulfillmentErrorCode::CodeAmbiguity => { + self.maybe_report_ambiguity(&error.obligation, body_id); + } + FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => { + self.report_mismatched_types( + &error.obligation.cause, + expected_found.expected, + expected_found.found, + err.clone(), + ) + .emit(); + } + } + } + + fn report_projection_error( + &self, + obligation: &PredicateObligation<'tcx>, + error: &MismatchedProjectionTypes<'tcx>, + ) { + let predicate = self.resolve_vars_if_possible(&obligation.predicate); + + if predicate.references_error() { + return; + } + + self.probe(|_| { + let err_buf; + let mut err = &error.err; + let mut values = None; + + // try to find the mismatched types to report the error with. + // + // this can fail if the problem was higher-ranked, in which + // cause I have no idea for a good error message. + if let ty::Predicate::Projection(ref data) = predicate { + let mut selcx = SelectionContext::new(self); + let (data, _) = self.replace_bound_vars_with_fresh_vars( + obligation.cause.span, + infer::LateBoundRegionConversionTime::HigherRankedType, + data, + ); + let mut obligations = vec![]; + let normalized_ty = super::normalize_projection_type( + &mut selcx, + obligation.param_env, + data.projection_ty, + obligation.cause.clone(), + 0, + &mut obligations, + ); + + debug!( + "report_projection_error obligation.cause={:?} obligation.param_env={:?}", + obligation.cause, obligation.param_env + ); + + debug!( + "report_projection_error normalized_ty={:?} data.ty={:?}", + normalized_ty, data.ty + ); + + let is_normalized_ty_expected = match &obligation.cause.code { + ObligationCauseCode::ItemObligation(_) + | ObligationCauseCode::BindingObligation(_, _) + | ObligationCauseCode::ObjectCastObligation(_) => false, + _ => true, + }; + + if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp( + is_normalized_ty_expected, + normalized_ty, + data.ty, + ) { + values = Some(infer::ValuePairs::Types(ExpectedFound::new( + is_normalized_ty_expected, + normalized_ty, + data.ty, + ))); + + err_buf = error; + err = &err_buf; + } + } + + let msg = format!("type mismatch resolving `{}`", predicate); + let error_id = (DiagnosticMessageId::ErrorId(271), Some(obligation.cause.span), msg); + let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id); + if fresh { + let mut diag = struct_span_err!( + self.tcx.sess, + obligation.cause.span, + E0271, + "type mismatch resolving `{}`", + predicate + ); + self.note_type_err(&mut diag, &obligation.cause, None, values, err); + self.note_obligation_cause(&mut diag, obligation); + diag.emit(); + } + }); + } + + fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool { + /// returns the fuzzy category of a given type, or None + /// if the type can be equated to any type. + fn type_category(t: Ty<'_>) -> Option { + match t.kind { + ty::Bool => Some(0), + ty::Char => Some(1), + ty::Str => Some(2), + ty::Int(..) | ty::Uint(..) | ty::Infer(ty::IntVar(..)) => Some(3), + ty::Float(..) | ty::Infer(ty::FloatVar(..)) => Some(4), + ty::Ref(..) | ty::RawPtr(..) => Some(5), + ty::Array(..) | ty::Slice(..) => Some(6), + ty::FnDef(..) | ty::FnPtr(..) => Some(7), + ty::Dynamic(..) => Some(8), + ty::Closure(..) => Some(9), + ty::Tuple(..) => Some(10), + ty::Projection(..) => Some(11), + ty::Param(..) => Some(12), + ty::Opaque(..) => Some(13), + ty::Never => Some(14), + ty::Adt(adt, ..) => match adt.adt_kind() { + AdtKind::Struct => Some(15), + AdtKind::Union => Some(16), + AdtKind::Enum => Some(17), + }, + ty::Generator(..) => Some(18), + ty::Foreign(..) => Some(19), + ty::GeneratorWitness(..) => Some(20), + ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => None, + ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), + } + } + + match (type_category(a), type_category(b)) { + (Some(cat_a), Some(cat_b)) => match (&a.kind, &b.kind) { + (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => def_a == def_b, + _ => cat_a == cat_b, + }, + // infer and error can be equated to all types + _ => true, + } + } + + fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> { + self.tcx.hir().body(body_id).generator_kind.map(|gen_kind| match gen_kind { + hir::GeneratorKind::Gen => "a generator", + hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "an async block", + hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "an async function", + hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "an async closure", + }) + } + + fn find_similar_impl_candidates( + &self, + trait_ref: ty::PolyTraitRef<'tcx>, + ) -> Vec> { + let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true); + let all_impls = self.tcx.all_impls(trait_ref.def_id()); + + match simp { + Some(simp) => all_impls + .iter() + .filter_map(|&def_id| { + let imp = self.tcx.impl_trait_ref(def_id).unwrap(); + let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true); + if let Some(imp_simp) = imp_simp { + if simp != imp_simp { + return None; + } + } + + Some(imp) + }) + .collect(), + None => { + all_impls.iter().map(|&def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect() + } + } + } + + fn report_similar_impl_candidates( + &self, + impl_candidates: Vec>, + err: &mut DiagnosticBuilder<'_>, + ) { + if impl_candidates.is_empty() { + return; + } + + let len = impl_candidates.len(); + let end = if impl_candidates.len() <= 5 { impl_candidates.len() } else { 4 }; + + let normalize = |candidate| { + self.tcx.infer_ctxt().enter(|ref infcx| { + let normalized = infcx + .at(&ObligationCause::dummy(), ty::ParamEnv::empty()) + .normalize(candidate) + .ok(); + match normalized { + Some(normalized) => format!("\n {:?}", normalized.value), + None => format!("\n {:?}", candidate), + } + }) + }; + + // Sort impl candidates so that ordering is consistent for UI tests. + let mut normalized_impl_candidates = + impl_candidates.iter().map(normalize).collect::>(); + + // Sort before taking the `..end` range, + // because the ordering of `impl_candidates` may not be deterministic: + // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507 + normalized_impl_candidates.sort(); + + err.help(&format!( + "the following implementations were found:{}{}", + normalized_impl_candidates[..end].join(""), + if len > 5 { format!("\nand {} others", len - 4) } else { String::new() } + )); + } + + /// Gets the parent trait chain start + fn get_parent_trait_ref( + &self, + code: &ObligationCauseCode<'tcx>, + ) -> Option<(String, Option)> { + match code { + &ObligationCauseCode::BuiltinDerivedObligation(ref data) => { + let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref); + match self.get_parent_trait_ref(&data.parent_code) { + Some(t) => Some(t), + None => { + let ty = parent_trait_ref.skip_binder().self_ty(); + let span = + TyCategory::from_ty(ty).map(|(_, def_id)| self.tcx.def_span(def_id)); + Some((ty.to_string(), span)) + } + } + } + _ => None, + } + } + + /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait + /// with the same path as `trait_ref`, a help message about + /// a probable version mismatch is added to `err` + fn note_version_mismatch( + &self, + err: &mut DiagnosticBuilder<'_>, + trait_ref: &ty::PolyTraitRef<'tcx>, + ) { + let get_trait_impl = |trait_def_id| { + let mut trait_impl = None; + self.tcx.for_each_relevant_impl(trait_def_id, trait_ref.self_ty(), |impl_def_id| { + if trait_impl.is_none() { + trait_impl = Some(impl_def_id); + } + }); + trait_impl + }; + let required_trait_path = self.tcx.def_path_str(trait_ref.def_id()); + let all_traits = self.tcx.all_traits(LOCAL_CRATE); + let traits_with_same_path: std::collections::BTreeSet<_> = all_traits + .iter() + .filter(|trait_def_id| **trait_def_id != trait_ref.def_id()) + .filter(|trait_def_id| self.tcx.def_path_str(**trait_def_id) == required_trait_path) + .collect(); + for trait_with_same_path in traits_with_same_path { + if let Some(impl_def_id) = get_trait_impl(*trait_with_same_path) { + let impl_span = self.tcx.def_span(impl_def_id); + err.span_help(impl_span, "trait impl with same name found"); + let trait_crate = self.tcx.crate_name(trait_with_same_path.krate); + let crate_msg = format!( + "perhaps two different versions of crate `{}` are being used?", + trait_crate + ); + err.note(&crate_msg); + } + } + } + + fn mk_obligation_for_def_id( + &self, + def_id: DefId, + output_ty: Ty<'tcx>, + cause: ObligationCause<'tcx>, + param_env: ty::ParamEnv<'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.without_const().to_predicate()) + } + + fn maybe_report_ambiguity( + &self, + obligation: &PredicateObligation<'tcx>, + body_id: Option, + ) { + // Unable to successfully determine, probably means + // insufficient type information, but could mean + // ambiguous impls. The latter *ought* to be a + // coherence violation, so we don't report it here. + + let predicate = self.resolve_vars_if_possible(&obligation.predicate); + let span = obligation.cause.span; + + debug!( + "maybe_report_ambiguity(predicate={:?}, obligation={:?} body_id={:?}, code={:?})", + predicate, obligation, body_id, obligation.cause.code, + ); + + // Ambiguity errors are often caused as fallout from earlier + // errors. So just ignore them if this infcx is tainted. + if self.is_tainted_by_errors() { + return; + } + + let mut err = match predicate { + 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); + + if predicate.references_error() { + return; + } + // Typically, this ambiguity should only happen if + // there are unresolved type inference variables + // (otherwise it would suggest a coherence + // failure). But given #21974 that is not necessarily + // the case -- we can have multiple where clauses that + // are only distinguished by a region, which results + // in an ambiguity even when all types are fully + // known, since we don't dispatch based on region + // relationships. + + // This is kind of a hack: it frequently happens that some earlier + // error prevents types from being fully inferred, and then we get + // a bunch of uninteresting errors saying something like " doesn't implement Sized". It may even be true that we + // could just skip over all checks where the self-ty is an + // inference variable, but I was afraid that there might be an + // inference variable created, registered as an obligation, and + // then never forced by writeback, and hence by skipping here we'd + // be ignoring the fact that we don't KNOW the type works + // out. Though even that would probably be harmless, given that + // we're only talking about builtin traits, which are known to be + // inhabited. We used to check for `self.tcx.sess.has_errors()` to + // avoid inundating the user with unnecessary errors, but we now + // check upstream for type errors and don't add the obligations to + // begin with in those cases. + if self + .tcx + .lang_items() + .sized_trait() + .map_or(false, |sized_id| sized_id == trait_ref.def_id()) + { + self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0282).emit(); + return; + } + let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0283); + err.note(&format!("cannot resolve `{}`", predicate)); + if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code { + self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id()); + } else if let ( + Ok(ref snippet), + ObligationCauseCode::BindingObligation(ref def_id, _), + ) = + (self.tcx.sess.source_map().span_to_snippet(span), &obligation.cause.code) + { + let generics = self.tcx.generics_of(*def_id); + if !generics.params.is_empty() && !snippet.ends_with('>') { + // FIXME: To avoid spurious suggestions in functions where type arguments + // where already supplied, we check the snippet to make sure it doesn't + // end with a turbofish. Ideally we would have access to a `PathSegment` + // instead. Otherwise we would produce the following output: + // + // error[E0283]: type annotations needed + // --> $DIR/issue-54954.rs:3:24 + // | + // LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>(); + // | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + // | | + // | cannot infer type + // | help: consider specifying the type argument + // | in the function call: + // | `Tt::const_val::<[i8; 123]>::` + // ... + // LL | const fn const_val() -> usize { + // | --------- - required by this bound in `Tt::const_val` + // | + // = note: cannot resolve `_: Tt` + + err.span_suggestion_verbose( + span.shrink_to_hi(), + &format!( + "consider specifying the type argument{} in the function call", + pluralize!(generics.params.len()), + ), + format!( + "::<{}>", + generics + .params + .iter() + .map(|p| p.name.to_string()) + .collect::>() + .join(", ") + ), + Applicability::HasPlaceholders, + ); + } + } + err + } + + ty::Predicate::WellFormed(ty) => { + // Same hacky approach as above to avoid deluging user + // with error messages. + if ty.references_error() || self.tcx.sess.has_errors() { + return; + } + self.need_type_info_err(body_id, span, ty, ErrorCode::E0282) + } + + ty::Predicate::Subtype(ref data) => { + if data.references_error() || self.tcx.sess.has_errors() { + // no need to overload user in such cases + return; + } + let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder(); + // both must be type variables, or the other would've been instantiated + assert!(a.is_ty_var() && b.is_ty_var()); + self.need_type_info_err(body_id, span, a, ErrorCode::E0282) + } + ty::Predicate::Projection(ref data) => { + let trait_ref = data.to_poly_trait_ref(self.tcx); + let self_ty = trait_ref.self_ty(); + if predicate.references_error() { + return; + } + let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0284); + err.note(&format!("cannot resolve `{}`", predicate)); + err + } + + _ => { + if self.tcx.sess.has_errors() { + return; + } + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0284, + "type annotations needed: cannot resolve `{}`", + predicate, + ); + err.span_label(span, &format!("cannot resolve `{}`", predicate)); + err + } + }; + self.note_obligation_cause(&mut err, obligation); + err.emit(); + } + + /// Returns `true` if the trait predicate may apply for *some* assignment + /// to the type parameters. + fn predicate_can_apply( + &self, + param_env: ty::ParamEnv<'tcx>, + pred: ty::PolyTraitRef<'tcx>, + ) -> bool { + struct ParamToVarFolder<'a, 'tcx> { + infcx: &'a InferCtxt<'a, 'tcx>, + var_map: FxHashMap, Ty<'tcx>>, + } + + impl<'a, 'tcx> TypeFolder<'tcx> for ParamToVarFolder<'a, 'tcx> { + fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { + self.infcx.tcx + } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + if let ty::Param(ty::ParamTy { name, .. }) = ty.kind { + let infcx = self.infcx; + self.var_map.entry(ty).or_insert_with(|| { + infcx.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeParameterDefinition(name, None), + span: DUMMY_SP, + }) + }) + } else { + ty.super_fold_with(self) + } + } + } + + self.probe(|_| { + let mut selcx = SelectionContext::new(self); + + let cleaned_pred = + pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() }); + + let cleaned_pred = super::project::normalize( + &mut selcx, + param_env, + ObligationCause::dummy(), + &cleaned_pred, + ) + .value; + + let obligation = Obligation::new( + ObligationCause::dummy(), + param_env, + cleaned_pred.without_const().to_predicate(), + ); + + self.predicate_may_hold(&obligation) + }) + } + + fn note_obligation_cause( + &self, + err: &mut DiagnosticBuilder<'_>, + obligation: &PredicateObligation<'tcx>, + ) { + // First, attempt to add note to this error with an async-await-specific + // message, and fall back to regular note otherwise. + if !self.maybe_note_obligation_cause_for_async_await(err, obligation) { + self.note_obligation_cause_code( + err, + &obligation.predicate, + &obligation.cause.code, + &mut vec![], + ); + self.suggest_unsized_bound_if_applicable(err, obligation); + } + } + + fn suggest_unsized_bound_if_applicable( + &self, + err: &mut DiagnosticBuilder<'_>, + obligation: &PredicateObligation<'tcx>, + ) { + if let ( + ty::Predicate::Trait(pred, _), + ObligationCauseCode::BindingObligation(item_def_id, span), + ) = (&obligation.predicate, &obligation.cause.code) + { + if let (Some(generics), true) = ( + self.tcx.hir().get_if_local(*item_def_id).as_ref().and_then(|n| n.generics()), + Some(pred.def_id()) == self.tcx.lang_items().sized_trait(), + ) { + for param in generics.params { + if param.span == *span + && !param.bounds.iter().any(|bound| { + bound.trait_def_id() == self.tcx.lang_items().sized_trait() + }) + { + let (span, separator) = match param.bounds { + [] => (span.shrink_to_hi(), ":"), + [.., bound] => (bound.span().shrink_to_hi(), " + "), + }; + err.span_suggestion_verbose( + span, + "consider relaxing the implicit `Sized` restriction", + format!("{} ?Sized", separator), + Applicability::MachineApplicable, + ); + return; + } + } + } + } + } + + fn is_recursive_obligation( + &self, + obligated_types: &mut Vec<&ty::TyS<'tcx>>, + cause_code: &ObligationCauseCode<'tcx>, + ) -> bool { + if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code { + let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref); + + if obligated_types.iter().any(|ot| ot == &parent_trait_ref.skip_binder().self_ty()) { + return true; + } + } + false + } +} + +pub fn recursive_type_with_infinite_size_error( + tcx: TyCtxt<'tcx>, + type_def_id: DefId, +) -> DiagnosticBuilder<'tcx> { + assert!(type_def_id.is_local()); + let span = tcx.hir().span_if_local(type_def_id).unwrap(); + let span = tcx.sess.source_map().guess_head_span(span); + let mut err = struct_span_err!( + tcx.sess, + span, + E0072, + "recursive type `{}` has infinite size", + tcx.def_path_str(type_def_id) + ); + err.span_label(span, "recursive type has infinite size"); + err.help(&format!( + "insert indirection (e.g., a `Box`, `Rc`, or `&`) \ + at some point to make `{}` representable", + tcx.def_path_str(type_def_id) + )); + err +} + +/// Summarizes information +#[derive(Clone)] +pub enum ArgKind { + /// An argument of non-tuple type. Parameters are (name, ty) + Arg(String, String), + + /// An argument of tuple type. For a "found" argument, the span is + /// the locationo in the source of the pattern. For a "expected" + /// argument, it will be None. The vector is a list of (name, ty) + /// strings for the components of the tuple. + Tuple(Option, Vec<(String, String)>), +} + +impl ArgKind { + fn empty() -> ArgKind { + ArgKind::Arg("_".to_owned(), "_".to_owned()) + } + + /// Creates an `ArgKind` from the expected type of an + /// argument. It has no name (`_`) and an optional source span. + pub fn from_expected_ty(t: Ty<'_>, span: Option) -> ArgKind { + match t.kind { + ty::Tuple(ref tys) => ArgKind::Tuple( + span, + tys.iter().map(|ty| ("_".to_owned(), ty.to_string())).collect::>(), + ), + _ => ArgKind::Arg("_".to_owned(), t.to_string()), + } + } +} + +/// Suggest restricting a type param with a new bound. +pub fn suggest_constraining_type_param( + tcx: TyCtxt<'_>, + generics: &hir::Generics<'_>, + err: &mut DiagnosticBuilder<'_>, + param_name: &str, + constraint: &str, + source_map: &SourceMap, + span: Span, + def_id: Option, +) -> bool { + const MSG_RESTRICT_BOUND_FURTHER: &str = "consider further restricting this bound with"; + const MSG_RESTRICT_TYPE: &str = "consider restricting this type parameter with"; + const MSG_RESTRICT_TYPE_FURTHER: &str = "consider further restricting this type parameter with"; + + let param = generics.params.iter().find(|p| p.name.ident().as_str() == param_name); + + let param = if let Some(param) = param { + param + } else { + return false; + }; + + if def_id == tcx.lang_items().sized_trait() { + // Type parameters are already `Sized` by default. + err.span_label(param.span, &format!("this type parameter needs to be `{}`", constraint)); + return true; + } + + if param_name.starts_with("impl ") { + // If there's an `impl Trait` used in argument position, suggest + // restricting it: + // + // fn foo(t: impl Foo) { ... } + // -------- + // | + // help: consider further restricting this bound with `+ Bar` + // + // Suggestion for tools in this case is: + // + // fn foo(t: impl Foo) { ... } + // -------- + // | + // replace with: `impl Foo + Bar` + + err.span_help(param.span, &format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint)); + + err.tool_only_span_suggestion( + param.span, + MSG_RESTRICT_BOUND_FURTHER, + format!("{} + {}", param_name, constraint), + Applicability::MachineApplicable, + ); + + return true; + } + + if generics.where_clause.predicates.is_empty() { + if let Some(bounds_span) = param.bounds_span() { + // If user has provided some bounds, suggest restricting them: + // + // fn foo(t: T) { ... } + // --- + // | + // help: consider further restricting this bound with `+ Bar` + // + // Suggestion for tools in this case is: + // + // fn foo(t: T) { ... } + // -- + // | + // replace with: `T: Bar +` + + err.span_help( + bounds_span, + &format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint), + ); + + let span_hi = param.span.with_hi(span.hi()); + let span_with_colon = source_map.span_through_char(span_hi, ':'); + + if span_hi != param.span && span_with_colon != span_hi { + err.tool_only_span_suggestion( + span_with_colon, + MSG_RESTRICT_BOUND_FURTHER, + format!("{}: {} + ", param_name, constraint), + Applicability::MachineApplicable, + ); + } + } else { + // If user hasn't provided any bounds, suggest adding a new one: + // + // fn foo(t: T) { ... } + // - help: consider restricting this type parameter with `T: Foo` + + err.span_help( + param.span, + &format!("{} `{}: {}`", MSG_RESTRICT_TYPE, param_name, constraint), + ); + + err.tool_only_span_suggestion( + param.span, + MSG_RESTRICT_TYPE, + format!("{}: {}", param_name, constraint), + Applicability::MachineApplicable, + ); + } + + true + } else { + // This part is a bit tricky, because using the `where` clause user can + // provide zero, one or many bounds for the same type parameter, so we + // have following cases to consider: + // + // 1) When the type parameter has been provided zero bounds + // + // Message: + // fn foo(x: X, y: Y) where Y: Foo { ... } + // - help: consider restricting this type parameter with `where X: Bar` + // + // Suggestion: + // fn foo(x: X, y: Y) where Y: Foo { ... } + // - insert: `, X: Bar` + // + // + // 2) When the type parameter has been provided one bound + // + // Message: + // fn foo(t: T) where T: Foo { ... } + // ^^^^^^ + // | + // help: consider further restricting this bound with `+ Bar` + // + // Suggestion: + // fn foo(t: T) where T: Foo { ... } + // ^^ + // | + // replace with: `T: Bar +` + // + // + // 3) When the type parameter has been provided many bounds + // + // Message: + // fn foo(t: T) where T: Foo, T: Bar {... } + // - help: consider further restricting this type parameter with `where T: Zar` + // + // Suggestion: + // fn foo(t: T) where T: Foo, T: Bar {... } + // - insert: `, T: Zar` + + let mut param_spans = Vec::new(); + + for predicate in generics.where_clause.predicates { + if let WherePredicate::BoundPredicate(WhereBoundPredicate { + span, bounded_ty, .. + }) = predicate + { + if let TyKind::Path(QPath::Resolved(_, path)) = &bounded_ty.kind { + if let Some(segment) = path.segments.first() { + if segment.ident.to_string() == param_name { + param_spans.push(span); + } + } + } + } + } + + let where_clause_span = + generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(); + + match ¶m_spans[..] { + &[] => { + err.span_help( + param.span, + &format!("{} `where {}: {}`", MSG_RESTRICT_TYPE, param_name, constraint), + ); + + err.tool_only_span_suggestion( + where_clause_span, + MSG_RESTRICT_TYPE, + format!(", {}: {}", param_name, constraint), + Applicability::MachineApplicable, + ); + } + + &[¶m_span] => { + err.span_help( + param_span, + &format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint), + ); + + let span_hi = param_span.with_hi(span.hi()); + let span_with_colon = source_map.span_through_char(span_hi, ':'); + + if span_hi != param_span && span_with_colon != span_hi { + err.tool_only_span_suggestion( + span_with_colon, + MSG_RESTRICT_BOUND_FURTHER, + format!("{}: {} +", param_name, constraint), + Applicability::MachineApplicable, + ); + } + } + + _ => { + err.span_help( + param.span, + &format!( + "{} `where {}: {}`", + MSG_RESTRICT_TYPE_FURTHER, param_name, constraint, + ), + ); + + err.tool_only_span_suggestion( + where_clause_span, + MSG_RESTRICT_BOUND_FURTHER, + format!(", {}: {}", param_name, constraint), + Applicability::MachineApplicable, + ); + } + } + + true + } +} diff --git a/src/librustc_infer/traits/error_reporting/on_unimplemented.rs b/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs similarity index 91% rename from src/librustc_infer/traits/error_reporting/on_unimplemented.rs rename to src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs index eb34a4875961c..18b2ca8983720 100644 --- a/src/librustc_infer/traits/error_reporting/on_unimplemented.rs +++ b/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs @@ -8,7 +8,27 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_span::symbol::sym; -impl<'a, 'tcx> InferCtxt<'a, 'tcx> { +use super::InferCtxtPrivExt; + +crate trait InferCtxtExt<'tcx> { + /*private*/ + fn impl_similar_to( + &self, + trait_ref: ty::PolyTraitRef<'tcx>, + obligation: &PredicateObligation<'tcx>, + ) -> Option; + + /*private*/ + fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str>; + + fn on_unimplemented_note( + &self, + trait_ref: ty::PolyTraitRef<'tcx>, + obligation: &PredicateObligation<'tcx>, + ) -> OnUnimplementedNote; +} + +impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { fn impl_similar_to( &self, trait_ref: ty::PolyTraitRef<'tcx>, @@ -70,11 +90,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }) } hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(_, hir::TraitMethod::Provided(body_id)), + kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)), .. }) => self.describe_generator(*body_id).or_else(|| Some("a trait method")), hir::Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Method(sig, body_id), + kind: hir::ImplItemKind::Fn(sig, body_id), .. }) => self.describe_generator(*body_id).or_else(|| { Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header { @@ -91,17 +111,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }), hir::Node::Expr(hir::Expr { .. }) => { let parent_hid = hir.get_parent_node(hir_id); - if parent_hid != hir_id { - return self.describe_enclosure(parent_hid); - } else { - None - } + if parent_hid != hir_id { self.describe_enclosure(parent_hid) } else { None } } _ => None, } } - crate fn on_unimplemented_note( + fn on_unimplemented_note( &self, trait_ref: ty::PolyTraitRef<'tcx>, obligation: &PredicateObligation<'tcx>, diff --git a/src/librustc_infer/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs similarity index 85% rename from src/librustc_infer/traits/error_reporting/suggestions.rs rename to src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 228747c3f89e9..a4be70df122d7 100644 --- a/src/librustc_infer/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -1,6 +1,5 @@ use super::{ - ArgKind, EvaluationResult, Obligation, ObligationCause, ObligationCauseCode, - PredicateObligation, + EvaluationResult, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation, }; use crate::infer::InferCtxt; @@ -8,9 +7,7 @@ use crate::traits::error_reporting::suggest_constraining_type_param; use rustc::ty::TypeckTables; use rustc::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; -use rustc_errors::{ - error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style, -}; +use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder, Style}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; @@ -20,8 +17,136 @@ use rustc_span::symbol::{kw, sym}; use rustc_span::{MultiSpan, Span, DUMMY_SP}; use std::fmt; -impl<'a, 'tcx> InferCtxt<'a, 'tcx> { - crate fn suggest_restricting_param_bound( +use super::InferCtxtPrivExt; +use crate::traits::query::evaluate_obligation::InferCtxtExt as _; + +crate trait InferCtxtExt<'tcx> { + fn suggest_restricting_param_bound( + &self, + err: &mut DiagnosticBuilder<'_>, + trait_ref: &ty::PolyTraitRef<'_>, + body_id: hir::HirId, + ); + + fn suggest_borrow_on_unsized_slice( + &self, + code: &ObligationCauseCode<'tcx>, + err: &mut DiagnosticBuilder<'tcx>, + ); + + fn get_closure_name( + &self, + def_id: DefId, + err: &mut DiagnosticBuilder<'_>, + msg: &str, + ) -> Option; + + fn suggest_fn_call( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut DiagnosticBuilder<'_>, + trait_ref: &ty::Binder>, + points_at_arg: bool, + ); + + fn suggest_add_reference_to_arg( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut DiagnosticBuilder<'tcx>, + trait_ref: &ty::Binder>, + points_at_arg: bool, + has_custom_message: bool, + ) -> bool; + + fn suggest_remove_reference( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut DiagnosticBuilder<'tcx>, + trait_ref: &ty::Binder>, + ); + + fn suggest_change_mut( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut DiagnosticBuilder<'tcx>, + trait_ref: &ty::Binder>, + points_at_arg: bool, + ); + + fn suggest_semicolon_removal( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut DiagnosticBuilder<'tcx>, + span: Span, + trait_ref: &ty::Binder>, + ); + + fn suggest_impl_trait( + &self, + err: &mut DiagnosticBuilder<'tcx>, + span: Span, + obligation: &PredicateObligation<'tcx>, + trait_ref: &ty::Binder>, + ) -> bool; + + fn point_at_returns_when_relevant( + &self, + err: &mut DiagnosticBuilder<'tcx>, + obligation: &PredicateObligation<'tcx>, + ); + + fn report_closure_arg_mismatch( + &self, + span: Span, + found_span: Option, + expected_ref: ty::PolyTraitRef<'tcx>, + found: ty::PolyTraitRef<'tcx>, + ) -> DiagnosticBuilder<'tcx>; + + fn suggest_fully_qualified_path( + &self, + err: &mut DiagnosticBuilder<'_>, + def_id: DefId, + span: Span, + trait_ref: DefId, + ); + + fn maybe_note_obligation_cause_for_async_await( + &self, + err: &mut DiagnosticBuilder<'_>, + obligation: &PredicateObligation<'tcx>, + ) -> bool; + + fn note_obligation_cause_for_async_await( + &self, + err: &mut DiagnosticBuilder<'_>, + target_span: Span, + scope_span: &Option, + expr: Option, + snippet: String, + first_generator: DefId, + last_generator: Option, + trait_ref: ty::TraitRef<'_>, + target_ty: Ty<'tcx>, + tables: &ty::TypeckTables<'_>, + obligation: &PredicateObligation<'tcx>, + next_code: Option<&ObligationCauseCode<'tcx>>, + ); + + fn note_obligation_cause_code( + &self, + err: &mut DiagnosticBuilder<'_>, + predicate: &T, + cause_code: &ObligationCauseCode<'tcx>, + obligated_types: &mut Vec<&ty::TyS<'tcx>>, + ) where + T: fmt::Display; + + fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>); +} + +impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { + fn suggest_restricting_param_bound( &self, mut err: &mut DiagnosticBuilder<'_>, trait_ref: &ty::PolyTraitRef<'_>, @@ -78,7 +203,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }) | hir::Node::ImplItem(hir::ImplItem { generics, - kind: hir::ImplItemKind::Method(..), + kind: hir::ImplItemKind::Fn(..), .. }) | hir::Node::Item(hir::Item { @@ -157,7 +282,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - hir::Node::Crate => return, + hir::Node::Crate(..) => return, _ => {} } @@ -168,7 +293,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// When encountering an assignment of an unsized trait, like `let x = ""[..];`, provide a /// suggestion to borrow the initializer in order to use have a slice instead. - crate fn suggest_borrow_on_unsized_slice( + fn suggest_borrow_on_unsized_slice( &self, code: &ObligationCauseCode<'tcx>, err: &mut DiagnosticBuilder<'tcx>, @@ -195,7 +320,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// Given a closure's `DefId`, return the given name of the closure. /// /// This doesn't account for reassignments, but it's only used for suggestions. - crate fn get_closure_name( + fn get_closure_name( &self, def_id: DefId, err: &mut DiagnosticBuilder<'_>, @@ -226,14 +351,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // Different to previous arm because one is `&hir::Local` and the other // is `P`. Some(hir::Node::Local(local)) => get_name(err, &local.pat.kind), - _ => return None, + _ => None, } } /// We tried to apply the bound to an `fn` or closure. Check whether calling it would /// evaluate to a type that *would* satisfy the trait binding. If it would, suggest calling /// it: `bar(foo)` → `bar(foo())`. This case is *very* likely to be hit if `foo` is `async`. - crate fn suggest_fn_call( + fn suggest_fn_call( &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, @@ -242,9 +367,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ) { let self_ty = trait_ref.self_ty(); let (def_id, output_ty, callable) = match self_ty.kind { - ty::Closure(def_id, substs) => { - (def_id, self.closure_sig(def_id, substs).output(), "closure") - } + ty::Closure(def_id, substs) => (def_id, substs.as_closure().sig().output(), "closure"), ty::FnDef(def_id, _) => (def_id, self_ty.fn_sig(self.tcx).output(), "function"), _ => return, }; @@ -265,7 +388,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } let hir = self.tcx.hir(); // Get the name of the callable and the arguments to be used in the suggestion. - let snippet = match hir.get_if_local(def_id) { + let (snippet, sugg) = match hir.get_if_local(def_id) { Some(hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(_, decl, _, span, ..), .. @@ -276,7 +399,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { None => return, }; let args = decl.inputs.iter().map(|_| "_").collect::>().join(", "); - format!("{}({})", name, args) + let sugg = format!("({})", args); + (format!("{}{}", name, sugg), sugg) } Some(hir::Node::Item(hir::Item { ident, @@ -297,7 +421,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }) .collect::>() .join(", "); - format!("{}({})", ident, args) + let sugg = format!("({})", args); + (format!("{}{}", ident, sugg), sugg) } _ => return, }; @@ -306,10 +431,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // an argument, the `obligation.cause.span` points at the expression // of the argument, so we can provide a suggestion. This is signaled // by `points_at_arg`. Otherwise, we give a more general note. - err.span_suggestion( - obligation.cause.span, + err.span_suggestion_verbose( + obligation.cause.span.shrink_to_hi(), &msg, - snippet, + sugg, Applicability::HasPlaceholders, ); } else { @@ -317,7 +442,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - crate fn suggest_add_reference_to_arg( + fn suggest_add_reference_to_arg( &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'tcx>, @@ -389,7 +514,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`, /// suggest removing these references until we reach a type that implements the trait. - crate fn suggest_remove_reference( + fn suggest_remove_reference( &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'tcx>, @@ -451,7 +576,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// Check if the trait bound is implemented for a different mutability and note it in the /// final error. - crate fn suggest_change_mut( + fn suggest_change_mut( &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'tcx>, @@ -494,7 +619,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .source_map() .span_take_while(span, |c| c.is_whitespace() || *c == '&'); if points_at_arg && mutability == hir::Mutability::Not && refs_number > 0 { - err.span_suggestion( + err.span_suggestion_verbose( sp, "consider changing this borrow's mutability", "&mut ".to_string(), @@ -513,7 +638,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - crate fn suggest_semicolon_removal( + fn suggest_semicolon_removal( &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'tcx>, @@ -549,7 +674,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// If all conditions are met to identify a returned `dyn Trait`, suggest using `impl Trait` if /// applicable and signal that the error has been expanded appropriately and needs to be /// emitted. - crate fn suggest_impl_trait( + fn suggest_impl_trait( &self, err: &mut DiagnosticBuilder<'tcx>, span: Span, @@ -723,7 +848,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { true } - crate fn point_at_returns_when_relevant( + fn point_at_returns_when_relevant( &self, err: &mut DiagnosticBuilder<'tcx>, obligation: &PredicateObligation<'tcx>, @@ -753,220 +878,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - /// Given some node representing a fn-like thing in the HIR map, - /// returns a span and `ArgKind` information that describes the - /// arguments it expects. This can be supplied to - /// `report_arg_count_mismatch`. - pub fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec) { - match node { - Node::Expr(&hir::Expr { - kind: hir::ExprKind::Closure(_, ref _decl, id, span, _), - .. - }) => ( - self.tcx.sess.source_map().def_span(span), - self.tcx - .hir() - .body(id) - .params - .iter() - .map(|arg| { - if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } = - *arg.pat - { - ArgKind::Tuple( - Some(span), - args.iter() - .map(|pat| { - let snippet = self - .tcx - .sess - .source_map() - .span_to_snippet(pat.span) - .unwrap(); - (snippet, "_".to_owned()) - }) - .collect::>(), - ) - } else { - let name = - self.tcx.sess.source_map().span_to_snippet(arg.pat.span).unwrap(); - ArgKind::Arg(name, "_".to_owned()) - } - }) - .collect::>(), - ), - Node::Item(&hir::Item { span, kind: hir::ItemKind::Fn(ref sig, ..), .. }) - | Node::ImplItem(&hir::ImplItem { - span, - kind: hir::ImplItemKind::Method(ref sig, _), - .. - }) - | Node::TraitItem(&hir::TraitItem { - span, - kind: hir::TraitItemKind::Fn(ref sig, _), - .. - }) => ( - self.tcx.sess.source_map().def_span(span), - sig.decl - .inputs - .iter() - .map(|arg| match arg.clone().kind { - hir::TyKind::Tup(ref tys) => ArgKind::Tuple( - Some(arg.span), - vec![("_".to_owned(), "_".to_owned()); tys.len()], - ), - _ => ArgKind::empty(), - }) - .collect::>(), - ), - Node::Ctor(ref variant_data) => { - let span = variant_data - .ctor_hir_id() - .map(|hir_id| self.tcx.hir().span(hir_id)) - .unwrap_or(DUMMY_SP); - let span = self.tcx.sess.source_map().def_span(span); - - (span, vec![ArgKind::empty(); variant_data.fields().len()]) - } - _ => panic!("non-FnLike node found: {:?}", node), - } - } - - /// Reports an error when the number of arguments needed by a - /// trait match doesn't match the number that the expression - /// provides. - pub fn report_arg_count_mismatch( - &self, - span: Span, - found_span: Option, - expected_args: Vec, - found_args: Vec, - is_closure: bool, - ) -> DiagnosticBuilder<'tcx> { - let kind = if is_closure { "closure" } else { "function" }; - - let args_str = |arguments: &[ArgKind], other: &[ArgKind]| { - let arg_length = arguments.len(); - let distinct = match &other[..] { - &[ArgKind::Tuple(..)] => true, - _ => false, - }; - match (arg_length, arguments.get(0)) { - (1, Some(&ArgKind::Tuple(_, ref fields))) => { - format!("a single {}-tuple as argument", fields.len()) - } - _ => format!( - "{} {}argument{}", - arg_length, - if distinct && arg_length > 1 { "distinct " } else { "" }, - pluralize!(arg_length) - ), - } - }; - - let expected_str = args_str(&expected_args, &found_args); - let found_str = args_str(&found_args, &expected_args); - - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0593, - "{} is expected to take {}, but it takes {}", - kind, - expected_str, - found_str, - ); - - err.span_label(span, format!("expected {} that takes {}", kind, expected_str)); - - if let Some(found_span) = found_span { - err.span_label(found_span, format!("takes {}", found_str)); - - // move |_| { ... } - // ^^^^^^^^-- def_span - // - // move |_| { ... } - // ^^^^^-- prefix - let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span); - // move |_| { ... } - // ^^^-- pipe_span - let pipe_span = - if let Some(span) = found_span.trim_start(prefix_span) { span } else { found_span }; - - // Suggest to take and ignore the arguments with expected_args_length `_`s if - // found arguments is empty (assume the user just wants to ignore args in this case). - // For example, if `expected_args_length` is 2, suggest `|_, _|`. - if found_args.is_empty() && is_closure { - let underscores = vec!["_"; expected_args.len()].join(", "); - err.span_suggestion( - pipe_span, - &format!( - "consider changing the closure to take and ignore the expected argument{}", - if expected_args.len() < 2 { "" } else { "s" } - ), - format!("|{}|", underscores), - Applicability::MachineApplicable, - ); - } - - if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] { - if fields.len() == expected_args.len() { - let sugg = fields - .iter() - .map(|(name, _)| name.to_owned()) - .collect::>() - .join(", "); - err.span_suggestion( - found_span, - "change the closure to take multiple arguments instead of a single tuple", - format!("|{}|", sugg), - Applicability::MachineApplicable, - ); - } - } - if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] { - if fields.len() == found_args.len() && is_closure { - let sugg = format!( - "|({}){}|", - found_args - .iter() - .map(|arg| match arg { - ArgKind::Arg(name, _) => name.to_owned(), - _ => "_".to_owned(), - }) - .collect::>() - .join(", "), - // add type annotations if available - if found_args.iter().any(|arg| match arg { - ArgKind::Arg(_, ty) => ty != "_", - _ => false, - }) { - format!( - ": ({})", - fields - .iter() - .map(|(_, ty)| ty.to_owned()) - .collect::>() - .join(", ") - ) - } else { - String::new() - }, - ); - err.span_suggestion( - found_span, - "change the closure to accept a tuple instead of individual arguments", - sugg, - Applicability::MachineApplicable, - ); - } - } - } - - err - } - - crate fn report_closure_arg_mismatch( + fn report_closure_arg_mismatch( &self, span: Span, found_span: Option, @@ -1022,10 +934,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err } -} -impl<'a, 'tcx> InferCtxt<'a, 'tcx> { - crate fn suggest_fully_qualified_path( + fn suggest_fully_qualified_path( &self, err: &mut DiagnosticBuilder<'_>, def_id: DefId, @@ -1091,7 +1001,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// ``` /// /// Returns `true` if an async-await specific note was added to the diagnostic. - crate fn maybe_note_obligation_cause_for_async_await( + fn maybe_note_obligation_cause_for_async_await( &self, err: &mut DiagnosticBuilder<'_>, obligation: &PredicateObligation<'tcx>, @@ -1195,15 +1105,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let generator_did_root = self.tcx.closure_base_def_id(generator_did); debug!( "maybe_note_obligation_cause_for_async_await: generator_did={:?} \ - generator_did_root={:?} in_progress_tables.local_id_root={:?} span={:?}", + generator_did_root={:?} in_progress_tables.hir_owner={:?} span={:?}", generator_did, generator_did_root, - in_progress_tables.as_ref().map(|t| t.local_id_root), + in_progress_tables.as_ref().map(|t| t.hir_owner), span ); let query_tables; let tables: &TypeckTables<'tcx> = match &in_progress_tables { - Some(t) if t.local_id_root == Some(generator_did_root) => t, + Some(t) if t.hir_owner.map(|owner| owner.to_def_id()) == Some(generator_did_root) => t, _ => { query_tables = self.tcx.typeck_tables_of(generator_did); &query_tables @@ -1271,7 +1181,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// Unconditionally adds the diagnostic note described in /// `maybe_note_obligation_cause_for_async_await`'s documentation comment. - crate fn note_obligation_cause_for_async_await( + fn note_obligation_cause_for_async_await( &self, err: &mut DiagnosticBuilder<'_>, target_span: Span, @@ -1377,7 +1287,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let parent = hir.get_parent_node(expr_id); if let Some(hir::Node::Expr(e)) = hir.find(parent) { let parent_span = hir.span(parent); - let parent_did = parent.owner_def_id(); + let parent_did = parent.owner.to_def_id(); // ```rust // impl T { // fn foo(&self) -> i32 {} @@ -1423,7 +1333,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ); } - crate fn note_obligation_cause_code( + fn note_obligation_cause_code( &self, err: &mut DiagnosticBuilder<'_>, predicate: &T, @@ -1471,7 +1381,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let msg = format!("required by `{}`", item_name); if let Some(sp) = tcx.hir().span_if_local(item_def_id) { - let sp = tcx.sess.source_map().def_span(sp); + let sp = tcx.sess.source_map().guess_head_span(sp); err.span_label(sp, &msg); } else { err.note(&msg); @@ -1638,7 +1548,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - crate fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) { + fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) { let current_limit = self.tcx.sess.recursion_limit.get(); let suggested_limit = current_limit * 2; err.help(&format!( @@ -1657,9 +1567,9 @@ struct ReturnsVisitor<'v> { } impl<'v> Visitor<'v> for ReturnsVisitor<'v> { - type Map = rustc::hir::map::Map<'v>; + type Map = hir::intravisit::ErasedMap<'v>; - fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap { hir::intravisit::NestedVisitorMap::None } diff --git a/src/librustc_infer/traits/fulfill.rs b/src/librustc_trait_selection/traits/fulfill.rs similarity index 90% rename from src/librustc_infer/traits/fulfill.rs rename to src/librustc_trait_selection/traits/fulfill.rs index ac9ff484a0274..0578c00fefb17 100644 --- a/src/librustc_infer/traits/fulfill.rs +++ b/src/librustc_trait_selection/traits/fulfill.rs @@ -1,12 +1,12 @@ -use crate::infer::{InferCtxt, ShallowResolver}; +use crate::infer::{InferCtxt, TyOrConstInferVar}; use rustc::ty::error::ExpectedFound; use rustc::ty::{self, ToPolyTraitRef, Ty, TypeFoldable}; use rustc_data_structures::obligation_forest::ProcessResult; use rustc_data_structures::obligation_forest::{DoCompleted, Error, ForestObligation}; use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor}; +use rustc_infer::traits::{TraitEngine, TraitEngineExt as _}; use std::marker::PhantomData; -use super::engine::{TraitEngine, TraitEngineExt}; use super::project; use super::select::SelectionContext; use super::wf; @@ -17,6 +17,9 @@ use super::{ConstEvalFailure, Unimplemented}; use super::{FulfillmentError, FulfillmentErrorCode}; use super::{ObligationCause, PredicateObligation}; +use crate::traits::error_reporting::InferCtxtExt as _; +use crate::traits::query::evaluate_obligation::InferCtxtExt as _; + impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> { /// Note that we include both the `ParamEnv` and the `Predicate`, /// as the `ParamEnv` can influence whether fulfillment succeeds @@ -70,7 +73,10 @@ pub struct FulfillmentContext<'tcx> { #[derive(Clone, Debug)] pub struct PendingPredicateObligation<'tcx> { pub obligation: PredicateObligation<'tcx>, - pub stalled_on: Vec, + // FIXME(eddyb) look into whether this could be a `SmallVec`. + // Judging by the comment in `process_obligation`, the 1-element case + // is common so this could be a `SmallVec<[TyOrConstInferVar<'tcx>; 1]>`. + pub stalled_on: Vec>, } // `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. @@ -128,7 +134,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> { // FIXME: if we kept the original cache key, we could mark projection // obligations as complete for the projection cache here. - errors.extend(outcome.errors.into_iter().map(|e| to_fulfillment_error(e))); + errors.extend(outcome.errors.into_iter().map(to_fulfillment_error)); // If nothing new was added, no need to keep looping. if outcome.stalled { @@ -211,7 +217,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { .predicates .to_errors(CodeAmbiguity) .into_iter() - .map(|e| to_fulfillment_error(e)) + .map(to_fulfillment_error) .collect(); if errors.is_empty() { Ok(()) } else { Err(errors) } } @@ -263,8 +269,8 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { // Match arms are in order of frequency, which matters because this // code is so hot. 1 and 0 dominate; 2+ is fairly rare. 1 => { - let infer = pending_obligation.stalled_on[0]; - ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(infer) + let infer_var = pending_obligation.stalled_on[0]; + self.selcx.infcx().ty_or_const_infer_var_changed(infer_var) } 0 => { // In this case we haven't changed, but wish to make a change. @@ -274,8 +280,8 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { // This `for` loop was once a call to `all()`, but this lower-level // form was a perf win. See #64545 for details. (|| { - for &infer in &pending_obligation.stalled_on { - if ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(infer) { + for &infer_var in &pending_obligation.stalled_on { + if self.selcx.infcx().ty_or_const_infer_var_changed(infer_var) { return true; } } @@ -306,13 +312,6 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { debug!("process_obligation: obligation = {:?} cause = {:?}", obligation, obligation.cause); - fn infer_ty(ty: Ty<'tcx>) -> ty::InferTy { - match ty.kind { - ty::Infer(infer) => infer, - _ => panic!(), - } - } - match obligation.predicate { ty::Predicate::Trait(ref data, _) => { let trait_obligation = obligation.with(data.clone()); @@ -442,8 +441,8 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { } } - ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => { - match self.selcx.infcx().closure_kind(closure_def_id, closure_substs) { + ty::Predicate::ClosureKind(_, closure_substs, kind) => { + match self.selcx.infcx().closure_kind(closure_substs) { Some(closure_kind) => { if closure_kind.extends(kind) { ProcessResult::Changed(vec![]) @@ -464,7 +463,8 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { obligation.cause.span, ) { None => { - pending_obligation.stalled_on = vec![infer_ty(ty)]; + pending_obligation.stalled_on = + vec![TyOrConstInferVar::maybe_from_ty(ty).unwrap()]; ProcessResult::Unchanged } Some(os) => ProcessResult::Changed(mk_pending(os)), @@ -480,8 +480,8 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { None => { // None means that both are unresolved. pending_obligation.stalled_on = vec![ - infer_ty(subtype.skip_binder().a), - infer_ty(subtype.skip_binder().b), + TyOrConstInferVar::maybe_from_ty(subtype.skip_binder().a).unwrap(), + TyOrConstInferVar::maybe_from_ty(subtype.skip_binder().b).unwrap(), ]; ProcessResult::Unchanged } @@ -531,20 +531,23 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { } } -/// Returns the set of type variables contained in a trait ref +/// Returns the set of type inference variables contained in a trait ref. fn trait_ref_type_vars<'a, 'tcx>( selcx: &mut SelectionContext<'a, 'tcx>, - t: ty::PolyTraitRef<'tcx>, -) -> Vec { - t.skip_binder() // ok b/c this check doesn't care about regions + trait_ref: ty::PolyTraitRef<'tcx>, +) -> Vec> { + trait_ref + .skip_binder() // ok b/c this check doesn't care about regions + // FIXME(eddyb) walk over `GenericArg` to support const infer vars. .input_types() - .map(|t| selcx.infcx().resolve_vars_if_possible(&t)) - .filter(|t| t.has_infer_types()) - .flat_map(|t| t.walk()) - .filter_map(|t| match t.kind { - ty::Infer(infer) => Some(infer), - _ => None, - }) + .map(|ty| selcx.infcx().resolve_vars_if_possible(&ty)) + // FIXME(eddyb) try using `maybe_walk` to skip *all* subtrees that + // don't contain inference variables, not just the outermost level. + // FIXME(eddyb) use `has_infer_types_or_const`. + .filter(|ty| ty.has_infer_types()) + .flat_map(|ty| ty.walk()) + // FIXME(eddyb) use `TyOrConstInferVar::maybe_from_generic_arg`. + .filter_map(TyOrConstInferVar::maybe_from_ty) .collect() } diff --git a/src/librustc_infer/traits/misc.rs b/src/librustc_trait_selection/traits/misc.rs similarity index 94% rename from src/librustc_infer/traits/misc.rs rename to src/librustc_trait_selection/traits/misc.rs index 7ab918c159e1f..d500cff67c64b 100644 --- a/src/librustc_infer/traits/misc.rs +++ b/src/librustc_trait_selection/traits/misc.rs @@ -1,10 +1,13 @@ //! Miscellaneous type-system utilities that are too small to deserve their own modules. -use crate::infer::TyCtxtInferExt; +use crate::infer::InferCtxtExt as _; use crate::traits::{self, ObligationCause}; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_hir as hir; +use rustc_infer::infer::TyCtxtInferExt; + +use crate::traits::error_reporting::InferCtxtExt; #[derive(Clone)] pub enum CopyImplementationError<'tcx> { diff --git a/src/librustc_trait_selection/traits/mod.rs b/src/librustc_trait_selection/traits/mod.rs new file mode 100644 index 0000000000000..43a90c4a6c164 --- /dev/null +++ b/src/librustc_trait_selection/traits/mod.rs @@ -0,0 +1,533 @@ +//! Trait Resolution. See the [rustc dev guide] for more information on how this works. +//! +//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html + +#[allow(dead_code)] +pub mod auto_trait; +pub mod codegen; +mod coherence; +mod engine; +pub mod error_reporting; +mod fulfill; +pub mod misc; +mod object_safety; +mod on_unimplemented; +mod project; +pub mod query; +mod select; +mod specialize; +mod structural_match; +mod util; +pub mod wf; + +use crate::infer::outlives::env::OutlivesEnvironment; +use crate::infer::{InferCtxt, RegionckMode, TyCtxtInferExt}; +use crate::traits::error_reporting::InferCtxtExt as _; +use crate::traits::query::evaluate_obligation::InferCtxtExt as _; +use rustc::middle::region; +use rustc::ty::fold::TypeFoldable; +use rustc::ty::subst::{InternalSubsts, SubstsRef}; +use rustc::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, WithConstness}; +use rustc::util::common::ErrorReported; +use rustc_hir as hir; +use rustc_hir::def_id::DefId; +use rustc_span::{Span, DUMMY_SP}; + +use std::fmt::Debug; + +pub use self::FulfillmentErrorCode::*; +pub use self::ObligationCauseCode::*; +pub use self::SelectionError::*; +pub use self::Vtable::*; + +pub use self::coherence::{add_placeholder_note, orphan_check, overlapping_impls}; +pub use self::coherence::{OrphanCheckErr, OverlapResult}; +pub use self::engine::TraitEngineExt; +pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation}; +pub use self::object_safety::astconv_object_safety_violations; +pub use self::object_safety::is_vtable_safe_method; +pub use self::object_safety::MethodViolationCode; +pub use self::object_safety::ObjectSafetyViolation; +pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote}; +pub use self::project::{ + normalize, normalize_projection_type, normalize_to, poly_project_and_unify_type, +}; +pub use self::select::{EvaluationCache, SelectionCache, SelectionContext}; +pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError}; +pub use self::specialize::find_associated_item; +pub use self::specialize::specialization_graph::FutureCompatOverlapError; +pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind; +pub use self::specialize::{specialization_graph, translate_substs, OverlapError}; +pub use self::structural_match::search_for_structural_match_violation; +pub use self::structural_match::type_marked_structural; +pub use self::structural_match::NonStructuralMatchTy; +pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs}; +pub use self::util::{expand_trait_aliases, TraitAliasExpander}; +pub use self::util::{ + get_vtable_index_of_object_method, impl_is_default, impl_item_is_final, + predicate_for_trait_def, upcast_choices, +}; +pub use self::util::{ + supertrait_def_ids, supertraits, transitive_bounds, SupertraitDefIds, Supertraits, +}; + +pub use rustc_infer::traits::*; + +/// Whether to skip the leak check, as part of a future compatibility warning step. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum SkipLeakCheck { + Yes, + No, +} + +impl SkipLeakCheck { + fn is_yes(self) -> bool { + self == SkipLeakCheck::Yes + } +} + +/// The "default" for skip-leak-check corresponds to the current +/// behavior (do not skip the leak check) -- not the behavior we are +/// transitioning into. +impl Default for SkipLeakCheck { + fn default() -> Self { + SkipLeakCheck::No + } +} + +/// The mode that trait queries run in. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum TraitQueryMode { + // Standard/un-canonicalized queries get accurate + // spans etc. passed in and hence can do reasonable + // error reporting on their own. + Standard, + // Canonicalized queries get dummy spans and hence + // must generally propagate errors to + // pre-canonicalization callsites. + Canonical, +} + +/// Creates predicate obligations from the generic bounds. +pub fn predicates_for_generics<'tcx>( + cause: ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + generic_bounds: &ty::InstantiatedPredicates<'tcx>, +) -> PredicateObligations<'tcx> { + util::predicates_for_generics(cause, 0, param_env, generic_bounds) +} + +/// Determines whether the type `ty` is known to meet `bound` and +/// returns true if so. Returns false if `ty` either does not meet +/// `bound` or is not known to meet bound (note that this is +/// conservative towards *no impl*, which is the opposite of the +/// `evaluate` methods). +pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>( + infcx: &InferCtxt<'a, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, + def_id: DefId, + span: Span, +) -> bool { + debug!( + "type_known_to_meet_bound_modulo_regions(ty={:?}, bound={:?})", + ty, + infcx.tcx.def_path_str(def_id) + ); + + let trait_ref = ty::TraitRef { def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]) }; + let obligation = Obligation { + param_env, + cause: ObligationCause::misc(span, hir::DUMMY_HIR_ID), + recursion_depth: 0, + predicate: trait_ref.without_const().to_predicate(), + }; + + let result = infcx.predicate_must_hold_modulo_regions(&obligation); + debug!( + "type_known_to_meet_ty={:?} bound={} => {:?}", + ty, + infcx.tcx.def_path_str(def_id), + result + ); + + if result && ty.has_infer_types_or_consts() { + // Because of inference "guessing", selection can sometimes claim + // to succeed while the success requires a guess. To ensure + // this function's result remains infallible, we must confirm + // that guess. While imperfect, I believe this is sound. + + // The handling of regions in this area of the code is terrible, + // see issue #29149. We should be able to improve on this with + // NLL. + let mut fulfill_cx = FulfillmentContext::new_ignoring_regions(); + + // We can use a dummy node-id here because we won't pay any mind + // to region obligations that arise (there shouldn't really be any + // anyhow). + let cause = ObligationCause::misc(span, hir::DUMMY_HIR_ID); + + fulfill_cx.register_bound(infcx, param_env, ty, def_id, cause); + + // Note: we only assume something is `Copy` if we can + // *definitively* show that it implements `Copy`. Otherwise, + // assume it is move; linear is always ok. + match fulfill_cx.select_all_or_error(infcx) { + Ok(()) => { + debug!( + "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} success", + ty, + infcx.tcx.def_path_str(def_id) + ); + true + } + Err(e) => { + debug!( + "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} errors={:?}", + ty, + infcx.tcx.def_path_str(def_id), + e + ); + false + } + } + } else { + result + } +} + +fn do_normalize_predicates<'tcx>( + tcx: TyCtxt<'tcx>, + region_context: DefId, + cause: ObligationCause<'tcx>, + elaborated_env: ty::ParamEnv<'tcx>, + predicates: Vec>, +) -> Result>, ErrorReported> { + debug!( + "do_normalize_predicates(predicates={:?}, region_context={:?}, cause={:?})", + predicates, region_context, cause, + ); + let span = cause.span; + tcx.infer_ctxt().enter(|infcx| { + // FIXME. We should really... do something with these region + // obligations. But this call just continues the older + // behavior (i.e., doesn't cause any new bugs), and it would + // take some further refactoring to actually solve them. In + // particular, we would have to handle implied bounds + // properly, and that code is currently largely confined to + // regionck (though I made some efforts to extract it + // out). -nmatsakis + // + // @arielby: In any case, these obligations are checked + // by wfcheck anyway, so I'm not sure we have to check + // them here too, and we will remove this function when + // we move over to lazy normalization *anyway*. + let fulfill_cx = FulfillmentContext::new_ignoring_regions(); + let predicates = + match fully_normalize(&infcx, fulfill_cx, cause, elaborated_env, &predicates) { + Ok(predicates) => predicates, + Err(errors) => { + infcx.report_fulfillment_errors(&errors, None, false); + return Err(ErrorReported); + } + }; + + debug!("do_normalize_predictes: normalized predicates = {:?}", predicates); + + let region_scope_tree = region::ScopeTree::default(); + + // We can use the `elaborated_env` here; the region code only + // cares about declarations like `'a: 'b`. + let outlives_env = OutlivesEnvironment::new(elaborated_env); + + infcx.resolve_regions_and_report_errors( + region_context, + ®ion_scope_tree, + &outlives_env, + RegionckMode::default(), + ); + + let predicates = match infcx.fully_resolve(&predicates) { + Ok(predicates) => predicates, + Err(fixup_err) => { + // If we encounter a fixup error, it means that some type + // variable wound up unconstrained. I actually don't know + // if this can happen, and I certainly don't expect it to + // happen often, but if it did happen it probably + // represents a legitimate failure due to some kind of + // unconstrained variable, and it seems better not to ICE, + // all things considered. + tcx.sess.span_err(span, &fixup_err.to_string()); + return Err(ErrorReported); + } + }; + if predicates.has_local_value() { + // FIXME: shouldn't we, you know, actually report an error here? or an ICE? + Err(ErrorReported) + } else { + Ok(predicates) + } + }) +} + +// FIXME: this is gonna need to be removed ... +/// Normalizes the parameter environment, reporting errors if they occur. +pub fn normalize_param_env_or_error<'tcx>( + tcx: TyCtxt<'tcx>, + region_context: DefId, + unnormalized_env: ty::ParamEnv<'tcx>, + cause: ObligationCause<'tcx>, +) -> ty::ParamEnv<'tcx> { + // I'm not wild about reporting errors here; I'd prefer to + // have the errors get reported at a defined place (e.g., + // during typeck). Instead I have all parameter + // environments, in effect, going through this function + // and hence potentially reporting errors. This ensures of + // course that we never forget to normalize (the + // alternative seemed like it would involve a lot of + // manual invocations of this fn -- and then we'd have to + // deal with the errors at each of those sites). + // + // In any case, in practice, typeck constructs all the + // parameter environments once for every fn as it goes, + // and errors will get reported then; so after typeck we + // can be sure that no errors should occur. + + debug!( + "normalize_param_env_or_error(region_context={:?}, unnormalized_env={:?}, cause={:?})", + region_context, unnormalized_env, cause + ); + + let mut predicates: Vec<_> = + util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.to_vec()).collect(); + + debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates); + + let elaborated_env = ty::ParamEnv::new( + tcx.intern_predicates(&predicates), + unnormalized_env.reveal, + unnormalized_env.def_id, + ); + + // HACK: we are trying to normalize the param-env inside *itself*. The problem is that + // normalization expects its param-env to be already normalized, which means we have + // a circularity. + // + // The way we handle this is by normalizing the param-env inside an unnormalized version + // of the param-env, which means that if the param-env contains unnormalized projections, + // we'll have some normalization failures. This is unfortunate. + // + // Lazy normalization would basically handle this by treating just the + // normalizing-a-trait-ref-requires-itself cycles as evaluation failures. + // + // Inferred outlives bounds can create a lot of `TypeOutlives` predicates for associated + // types, so to make the situation less bad, we normalize all the predicates *but* + // the `TypeOutlives` predicates first inside the unnormalized parameter environment, and + // then we normalize the `TypeOutlives` bounds inside the normalized parameter environment. + // + // This works fairly well because trait matching does not actually care about param-env + // TypeOutlives predicates - these are normally used by regionck. + let outlives_predicates: Vec<_> = predicates + .drain_filter(|predicate| match predicate { + ty::Predicate::TypeOutlives(..) => true, + _ => false, + }) + .collect(); + + debug!( + "normalize_param_env_or_error: predicates=(non-outlives={:?}, outlives={:?})", + predicates, outlives_predicates + ); + let non_outlives_predicates = match do_normalize_predicates( + tcx, + region_context, + cause.clone(), + elaborated_env, + predicates, + ) { + Ok(predicates) => predicates, + // An unnormalized env is better than nothing. + Err(ErrorReported) => { + debug!("normalize_param_env_or_error: errored resolving non-outlives predicates"); + return elaborated_env; + } + }; + + debug!("normalize_param_env_or_error: non-outlives predicates={:?}", non_outlives_predicates); + + // Not sure whether it is better to include the unnormalized TypeOutlives predicates + // here. I believe they should not matter, because we are ignoring TypeOutlives param-env + // predicates here anyway. Keeping them here anyway because it seems safer. + let outlives_env: Vec<_> = + non_outlives_predicates.iter().chain(&outlives_predicates).cloned().collect(); + let outlives_env = + ty::ParamEnv::new(tcx.intern_predicates(&outlives_env), unnormalized_env.reveal, None); + let outlives_predicates = match do_normalize_predicates( + tcx, + region_context, + cause, + outlives_env, + outlives_predicates, + ) { + Ok(predicates) => predicates, + // An unnormalized env is better than nothing. + Err(ErrorReported) => { + debug!("normalize_param_env_or_error: errored resolving outlives predicates"); + return elaborated_env; + } + }; + debug!("normalize_param_env_or_error: outlives predicates={:?}", outlives_predicates); + + let mut predicates = non_outlives_predicates; + predicates.extend(outlives_predicates); + debug!("normalize_param_env_or_error: final predicates={:?}", predicates); + ty::ParamEnv::new( + tcx.intern_predicates(&predicates), + unnormalized_env.reveal, + unnormalized_env.def_id, + ) +} + +pub fn fully_normalize<'a, 'tcx, T>( + infcx: &InferCtxt<'a, 'tcx>, + mut fulfill_cx: FulfillmentContext<'tcx>, + cause: ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + value: &T, +) -> Result>> +where + T: TypeFoldable<'tcx>, +{ + debug!("fully_normalize_with_fulfillcx(value={:?})", value); + let selcx = &mut SelectionContext::new(infcx); + let Normalized { value: normalized_value, obligations } = + project::normalize(selcx, param_env, cause, value); + debug!( + "fully_normalize: normalized_value={:?} obligations={:?}", + normalized_value, obligations + ); + for obligation in obligations { + fulfill_cx.register_predicate_obligation(selcx.infcx(), obligation); + } + + debug!("fully_normalize: select_all_or_error start"); + fulfill_cx.select_all_or_error(infcx)?; + debug!("fully_normalize: select_all_or_error complete"); + let resolved_value = infcx.resolve_vars_if_possible(&normalized_value); + debug!("fully_normalize: resolved_value={:?}", resolved_value); + Ok(resolved_value) +} + +/// Normalizes the predicates and checks whether they hold in an empty +/// 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. +pub fn normalize_and_test_predicates<'tcx>( + tcx: TyCtxt<'tcx>, + predicates: Vec>, +) -> bool { + 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::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); + for obligation in obligations { + fulfill_cx.register_predicate_obligation(&infcx, obligation); + } + for predicate in predicates { + let obligation = Obligation::new(cause.clone(), param_env, predicate); + fulfill_cx.register_predicate_obligation(&infcx, obligation); + } + + fulfill_cx.select_all_or_error(&infcx).is_ok() + }); + debug!("normalize_and_test_predicates(predicates={:?}) = {:?}", predicates, result); + result +} + +fn substitute_normalize_and_test_predicates<'tcx>( + tcx: TyCtxt<'tcx>, + 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); + + debug!("substitute_normalize_and_test_predicates(key={:?}) = {:?}", key, result); + result +} + +/// Given a trait `trait_ref`, iterates the vtable entries +/// that come from `trait_ref`, including its supertraits. +#[inline] // FIXME(#35870): avoid closures being unexported due to `impl Trait`. +fn vtable_methods<'tcx>( + tcx: TyCtxt<'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>, +) -> &'tcx [Option<(DefId, SubstsRef<'tcx>)>] { + debug!("vtable_methods({:?})", trait_ref); + + tcx.arena.alloc_from_iter(supertraits(tcx, trait_ref).flat_map(move |trait_ref| { + let trait_methods = tcx + .associated_items(trait_ref.def_id()) + .in_definition_order() + .filter(|item| item.kind == ty::AssocKind::Method); + + // Now list each method's DefId and InternalSubsts (for within its trait). + // If the method can never be called from this object, produce None. + trait_methods.map(move |trait_method| { + debug!("vtable_methods: trait_method={:?}", trait_method); + let def_id = trait_method.def_id; + + // Some methods cannot be called on an object; skip those. + if !is_vtable_safe_method(tcx, trait_ref.def_id(), &trait_method) { + debug!("vtable_methods: not vtable safe"); + return None; + } + + // The method may have some early-bound lifetimes; add regions for those. + let substs = trait_ref.map_bound(|trait_ref| { + InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind { + GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(), + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => { + trait_ref.substs[param.index as usize] + } + }) + }); + + // The trait type may have higher-ranked lifetimes in it; + // erase them if they appear, so that we get the type + // at some particular call site. + let substs = + tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &substs); + + // It's possible that the method relies on where-clauses that + // do not hold for this particular set of type parameters. + // 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); + if !normalize_and_test_predicates(tcx, predicates.predicates) { + debug!("vtable_methods: predicates do not hold"); + return None; + } + + Some((def_id, substs)) + }) + })) +} + +pub fn provide(providers: &mut ty::query::Providers<'_>) { + object_safety::provide(providers); + *providers = ty::query::Providers { + specialization_graph_of: specialize::specialization_graph_provider, + specializes: specialize::specializes, + codegen_fulfill_obligation: codegen::codegen_fulfill_obligation, + vtable_methods, + substitute_normalize_and_test_predicates, + ..*providers + }; +} diff --git a/src/librustc_infer/traits/object_safety.rs b/src/librustc_trait_selection/traits/object_safety.rs similarity index 99% rename from src/librustc_infer/traits/object_safety.rs rename to src/librustc_trait_selection/traits/object_safety.rs index 6f20f5ac47e57..5cc1da045fc37 100644 --- a/src/librustc_infer/traits/object_safety.rs +++ b/src/librustc_trait_selection/traits/object_safety.rs @@ -11,6 +11,7 @@ use super::elaborate_predicates; use crate::infer::TyCtxtInferExt; +use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::{self, Obligation, ObligationCause}; use rustc::ty::subst::{InternalSubsts, Subst}; use rustc::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; @@ -38,7 +39,7 @@ pub fn astconv_object_safety_violations( let violations = traits::supertrait_def_ids(tcx, trait_def_id) .map(|def_id| predicates_reference_self(tcx, def_id, true)) .filter(|spans| !spans.is_empty()) - .map(|spans| ObjectSafetyViolation::SupertraitSelf(spans)) + .map(ObjectSafetyViolation::SupertraitSelf) .collect(); debug!("astconv_object_safety_violations(trait_def_id={:?}) = {:?}", trait_def_id, violations); @@ -184,7 +185,7 @@ fn get_sized_bounds(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> .filter_map(|pred| { match pred { hir::WherePredicate::BoundPredicate(pred) - if pred.bounded_ty.hir_id.owner_def_id() == trait_def_id => + if pred.bounded_ty.hir_id.owner.to_def_id() == trait_def_id => { // Fetch spans for trait bounds that are Sized: // `trait T where Self: Pred` diff --git a/src/librustc_infer/traits/on_unimplemented.rs b/src/librustc_trait_selection/traits/on_unimplemented.rs similarity index 100% rename from src/librustc_infer/traits/on_unimplemented.rs rename to src/librustc_trait_selection/traits/on_unimplemented.rs diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs new file mode 100644 index 0000000000000..badd94a5ed934 --- /dev/null +++ b/src/librustc_trait_selection/traits/project.rs @@ -0,0 +1,1513 @@ +//! Code for projecting associated types out of trait references. + +use super::elaborate_predicates; +use super::specialization_graph; +use super::translate_substs; +use super::util; +use super::MismatchedProjectionTypes; +use super::Obligation; +use super::ObligationCause; +use super::PredicateObligation; +use super::Selection; +use super::SelectionContext; +use super::SelectionError; +use super::{Normalized, NormalizedTy, ProjectionCacheEntry, ProjectionCacheKey}; +use super::{VtableClosureData, VtableFnPointerData, VtableGeneratorData, VtableImplData}; + +use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime}; +use crate::traits::error_reporting::InferCtxtExt; +use rustc::ty::fold::{TypeFoldable, TypeFolder}; +use rustc::ty::subst::{InternalSubsts, Subst}; +use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness}; +use rustc_ast::ast::Ident; +use rustc_errors::ErrorReported; +use rustc_hir::def_id::DefId; +use rustc_span::symbol::sym; +use rustc_span::DUMMY_SP; + +pub use rustc::traits::Reveal; + +pub type PolyProjectionObligation<'tcx> = Obligation<'tcx, ty::PolyProjectionPredicate<'tcx>>; + +pub type ProjectionObligation<'tcx> = Obligation<'tcx, ty::ProjectionPredicate<'tcx>>; + +pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::ProjectionTy<'tcx>>; + +/// When attempting to resolve `::Name` ... +#[derive(Debug)] +pub enum ProjectionTyError<'tcx> { + /// ...we found multiple sources of information and couldn't resolve the ambiguity. + TooManyCandidates, + + /// ...an error occurred matching `T : TraitRef` + TraitSelectionError(SelectionError<'tcx>), +} + +#[derive(PartialEq, Eq, Debug)] +enum ProjectionTyCandidate<'tcx> { + // from a where-clause in the env or object type + ParamEnv(ty::PolyProjectionPredicate<'tcx>), + + // from the definition of `Trait` when you have something like <::B as Trait2>::C + TraitDef(ty::PolyProjectionPredicate<'tcx>), + + // from a "impl" (or a "pseudo-impl" returned by select) + Select(Selection<'tcx>), +} + +enum ProjectionTyCandidateSet<'tcx> { + None, + Single(ProjectionTyCandidate<'tcx>), + Ambiguous, + Error(SelectionError<'tcx>), +} + +impl<'tcx> ProjectionTyCandidateSet<'tcx> { + fn mark_ambiguous(&mut self) { + *self = ProjectionTyCandidateSet::Ambiguous; + } + + fn mark_error(&mut self, err: SelectionError<'tcx>) { + *self = ProjectionTyCandidateSet::Error(err); + } + + // Returns true if the push was successful, or false if the candidate + // was discarded -- this could be because of ambiguity, or because + // a higher-priority candidate is already there. + fn push_candidate(&mut self, candidate: ProjectionTyCandidate<'tcx>) -> bool { + use self::ProjectionTyCandidate::*; + use self::ProjectionTyCandidateSet::*; + + // This wacky variable is just used to try and + // make code readable and avoid confusing paths. + // It is assigned a "value" of `()` only on those + // paths in which we wish to convert `*self` to + // ambiguous (and return false, because the candidate + // was not used). On other paths, it is not assigned, + // and hence if those paths *could* reach the code that + // comes after the match, this fn would not compile. + let convert_to_ambiguous; + + match self { + None => { + *self = Single(candidate); + return true; + } + + Single(current) => { + // Duplicates can happen inside ParamEnv. In the case, we + // perform a lazy deduplication. + if current == &candidate { + return false; + } + + // Prefer where-clauses. As in select, if there are multiple + // candidates, we prefer where-clause candidates over impls. This + // may seem a bit surprising, since impls are the source of + // "truth" in some sense, but in fact some of the impls that SEEM + // applicable are not, because of nested obligations. Where + // clauses are the safer choice. See the comment on + // `select::SelectionCandidate` and #21974 for more details. + match (current, candidate) { + (ParamEnv(..), ParamEnv(..)) => convert_to_ambiguous = (), + (ParamEnv(..), _) => return false, + (_, ParamEnv(..)) => unreachable!(), + (_, _) => convert_to_ambiguous = (), + } + } + + Ambiguous | Error(..) => { + return false; + } + } + + // We only ever get here when we moved from a single candidate + // to ambiguous. + let () = convert_to_ambiguous; + *self = Ambiguous; + false + } +} + +/// Evaluates constraints of the form: +/// +/// for<...> ::U == V +/// +/// If successful, this may result in additional obligations. Also returns +/// the projection cache key used to track these additional obligations. +pub fn poly_project_and_unify_type<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &PolyProjectionObligation<'tcx>, +) -> Result>>, MismatchedProjectionTypes<'tcx>> { + debug!("poly_project_and_unify_type(obligation={:?})", obligation); + + let infcx = selcx.infcx(); + infcx.commit_if_ok(|snapshot| { + let (placeholder_predicate, placeholder_map) = + infcx.replace_bound_vars_with_placeholders(&obligation.predicate); + + let placeholder_obligation = obligation.with(placeholder_predicate); + let result = project_and_unify_type(selcx, &placeholder_obligation)?; + infcx + .leak_check(false, &placeholder_map, snapshot) + .map_err(|err| MismatchedProjectionTypes { err })?; + Ok(result) + }) +} + +/// Evaluates constraints of the form: +/// +/// ::U == V +/// +/// If successful, this may result in additional obligations. +fn project_and_unify_type<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionObligation<'tcx>, +) -> Result>>, MismatchedProjectionTypes<'tcx>> { + debug!("project_and_unify_type(obligation={:?})", obligation); + + let mut obligations = vec![]; + let normalized_ty = match opt_normalize_projection_type( + selcx, + obligation.param_env, + obligation.predicate.projection_ty, + obligation.cause.clone(), + obligation.recursion_depth, + &mut obligations, + ) { + Some(n) => n, + None => return Ok(None), + }; + + debug!( + "project_and_unify_type: normalized_ty={:?} obligations={:?}", + normalized_ty, obligations + ); + + let infcx = selcx.infcx(); + match infcx + .at(&obligation.cause, obligation.param_env) + .eq(normalized_ty, obligation.predicate.ty) + { + Ok(InferOk { obligations: inferred_obligations, value: () }) => { + obligations.extend(inferred_obligations); + Ok(Some(obligations)) + } + Err(err) => { + debug!("project_and_unify_type: equating types encountered error {:?}", err); + Err(MismatchedProjectionTypes { err }) + } + } +} + +/// Normalizes any associated type projections in `value`, replacing +/// them with a fully resolved type where possible. The return value +/// combines the normalized result and any additional obligations that +/// were incurred as result. +pub fn normalize<'a, 'b, 'tcx, T>( + selcx: &'a mut SelectionContext<'b, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + cause: ObligationCause<'tcx>, + value: &T, +) -> Normalized<'tcx, T> +where + T: TypeFoldable<'tcx>, +{ + let mut obligations = Vec::new(); + let value = normalize_to(selcx, param_env, cause, value, &mut obligations); + Normalized { value, obligations } +} + +pub fn normalize_to<'a, 'b, 'tcx, T>( + selcx: &'a mut SelectionContext<'b, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + cause: ObligationCause<'tcx>, + value: &T, + obligations: &mut Vec>, +) -> T +where + T: TypeFoldable<'tcx>, +{ + normalize_with_depth_to(selcx, param_env, cause, 0, value, obligations) +} + +/// As `normalize`, but with a custom depth. +pub fn normalize_with_depth<'a, 'b, 'tcx, T>( + selcx: &'a mut SelectionContext<'b, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + cause: ObligationCause<'tcx>, + depth: usize, + value: &T, +) -> Normalized<'tcx, T> +where + T: TypeFoldable<'tcx>, +{ + let mut obligations = Vec::new(); + let value = normalize_with_depth_to(selcx, param_env, cause, depth, value, &mut obligations); + Normalized { value, obligations } +} + +pub fn normalize_with_depth_to<'a, 'b, 'tcx, T>( + selcx: &'a mut SelectionContext<'b, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + cause: ObligationCause<'tcx>, + depth: usize, + value: &T, + obligations: &mut Vec>, +) -> T +where + T: TypeFoldable<'tcx>, +{ + debug!("normalize_with_depth(depth={}, value={:?})", depth, value); + let mut normalizer = AssocTypeNormalizer::new(selcx, param_env, cause, depth, obligations); + let result = normalizer.fold(value); + debug!( + "normalize_with_depth: depth={} result={:?} with {} obligations", + depth, + result, + normalizer.obligations.len() + ); + debug!("normalize_with_depth: depth={} obligations={:?}", depth, normalizer.obligations); + result +} + +struct AssocTypeNormalizer<'a, 'b, 'tcx> { + selcx: &'a mut SelectionContext<'b, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + cause: ObligationCause<'tcx>, + obligations: &'a mut Vec>, + depth: usize, +} + +impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { + fn new( + selcx: &'a mut SelectionContext<'b, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + cause: ObligationCause<'tcx>, + depth: usize, + obligations: &'a mut Vec>, + ) -> AssocTypeNormalizer<'a, 'b, 'tcx> { + AssocTypeNormalizer { selcx, param_env, cause, obligations, depth } + } + + fn fold>(&mut self, value: &T) -> T { + let value = self.selcx.infcx().resolve_vars_if_possible(value); + + if !value.has_projections() { value } else { value.fold_with(self) } + } +} + +impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { + fn tcx<'c>(&'c self) -> TyCtxt<'tcx> { + self.selcx.tcx() + } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + if !ty.has_projections() { + return ty; + } + // We don't want to normalize associated types that occur inside of region + // binders, because they may contain bound regions, and we can't cope with that. + // + // Example: + // + // for<'a> fn(>::A) + // + // Instead of normalizing `>::A` here, we'll + // normalize it when we instantiate those bound regions (which + // should occur eventually). + + let ty = ty.super_fold_with(self); + match ty.kind { + ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { + // (*) + // Only normalize `impl Trait` after type-checking, usually in codegen. + match self.param_env.reveal { + Reveal::UserFacing => ty, + + Reveal::All => { + let recursion_limit = *self.tcx().sess.recursion_limit.get(); + if self.depth >= recursion_limit { + let obligation = Obligation::with_depth( + self.cause.clone(), + recursion_limit, + self.param_env, + ty, + ); + self.selcx.infcx().report_overflow_error(&obligation, true); + } + + let generic_ty = self.tcx().type_of(def_id); + let concrete_ty = generic_ty.subst(self.tcx(), substs); + self.depth += 1; + let folded_ty = self.fold_ty(concrete_ty); + self.depth -= 1; + folded_ty + } + } + } + + ty::Projection(ref data) if !data.has_escaping_bound_vars() => { + // (*) + + // (*) This is kind of hacky -- we need to be able to + // handle normalization within binders because + // otherwise we wind up a need to normalize when doing + // trait matching (since you can have a trait + // obligation like `for<'a> T::B : Fn(&'a int)`), but + // we can't normalize with bound regions in scope. So + // far now we just ignore binders but only normalize + // if all bound regions are gone (and then we still + // have to renormalize whenever we instantiate a + // binder). It would be better to normalize in a + // binding-aware fashion. + + let normalized_ty = normalize_projection_type( + self.selcx, + self.param_env, + *data, + self.cause.clone(), + self.depth, + &mut self.obligations, + ); + debug!( + "AssocTypeNormalizer: depth={} normalized {:?} to {:?}, \ + now with {} obligations", + self.depth, + ty, + normalized_ty, + self.obligations.len() + ); + normalized_ty + } + + _ => ty, + } + } + + fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + let constant = constant.super_fold_with(self); + constant.eval(self.selcx.tcx(), self.param_env) + } +} + +/// The guts of `normalize`: normalize a specific projection like `::Item`. The result is always a type (and possibly +/// additional obligations). If ambiguity arises, which implies that +/// there are unresolved type variables in the projection, we will +/// substitute a fresh type variable `$X` and generate a new +/// obligation `::Item == $X` for later. +pub fn normalize_projection_type<'a, 'b, 'tcx>( + selcx: &'a mut SelectionContext<'b, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + projection_ty: ty::ProjectionTy<'tcx>, + cause: ObligationCause<'tcx>, + depth: usize, + obligations: &mut Vec>, +) -> Ty<'tcx> { + opt_normalize_projection_type( + selcx, + param_env, + projection_ty, + cause.clone(), + depth, + obligations, + ) + .unwrap_or_else(move || { + // if we bottom out in ambiguity, create a type variable + // and a deferred predicate to resolve this when more type + // information is available. + + let tcx = selcx.infcx().tcx; + let def_id = projection_ty.item_def_id; + let ty_var = selcx.infcx().next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::NormalizeProjectionType, + span: tcx.def_span(def_id), + }); + let projection = ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, ty: ty_var }); + let obligation = + Obligation::with_depth(cause, depth + 1, param_env, projection.to_predicate()); + obligations.push(obligation); + ty_var + }) +} + +/// The guts of `normalize`: normalize a specific projection like `::Item`. The result is always a type (and possibly +/// additional obligations). Returns `None` in the case of ambiguity, +/// which indicates that there are unbound type variables. +/// +/// This function used to return `Option>`, which contains a +/// `Ty<'tcx>` and an obligations vector. But that obligation vector was very +/// often immediately appended to another obligations vector. So now this +/// function takes an obligations vector and appends to it directly, which is +/// slightly uglier but avoids the need for an extra short-lived allocation. +fn opt_normalize_projection_type<'a, 'b, 'tcx>( + selcx: &'a mut SelectionContext<'b, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + projection_ty: ty::ProjectionTy<'tcx>, + cause: ObligationCause<'tcx>, + depth: usize, + obligations: &mut Vec>, +) -> Option> { + let infcx = selcx.infcx(); + + let projection_ty = infcx.resolve_vars_if_possible(&projection_ty); + let cache_key = ProjectionCacheKey::new(projection_ty); + + debug!( + "opt_normalize_projection_type(\ + projection_ty={:?}, \ + depth={})", + projection_ty, depth + ); + + // FIXME(#20304) For now, I am caching here, which is good, but it + // means we don't capture the type variables that are created in + // the case of ambiguity. Which means we may create a large stream + // of such variables. OTOH, if we move the caching up a level, we + // would not benefit from caching when proving `T: Trait` + // bounds. It might be the case that we want two distinct caches, + // or else another kind of cache entry. + + let cache_result = infcx.inner.borrow_mut().projection_cache.try_start(cache_key); + match cache_result { + Ok(()) => {} + Err(ProjectionCacheEntry::Ambiguous) => { + // If we found ambiguity the last time, that means we will continue + // to do so until some type in the key changes (and we know it + // hasn't, because we just fully resolved it). + debug!( + "opt_normalize_projection_type: \ + found cache entry: ambiguous" + ); + return None; + } + Err(ProjectionCacheEntry::InProgress) => { + // If while normalized A::B, we are asked to normalize + // A::B, just return A::B itself. This is a conservative + // answer, in the sense that A::B *is* clearly equivalent + // to A::B, though there may be a better value we can + // find. + + // Under lazy normalization, this can arise when + // bootstrapping. That is, imagine an environment with a + // where-clause like `A::B == u32`. Now, if we are asked + // to normalize `A::B`, we will want to check the + // where-clauses in scope. So we will try to unify `A::B` + // with `A::B`, which can trigger a recursive + // normalization. In that case, I think we will want this code: + // + // ``` + // let ty = selcx.tcx().mk_projection(projection_ty.item_def_id, + // projection_ty.substs; + // return Some(NormalizedTy { value: v, obligations: vec![] }); + // ``` + + debug!( + "opt_normalize_projection_type: \ + found cache entry: in-progress" + ); + + // But for now, let's classify this as an overflow: + let recursion_limit = *selcx.tcx().sess.recursion_limit.get(); + let obligation = + Obligation::with_depth(cause, recursion_limit, param_env, projection_ty); + selcx.infcx().report_overflow_error(&obligation, false); + } + Err(ProjectionCacheEntry::NormalizedTy(ty)) => { + // This is the hottest path in this function. + // + // If we find the value in the cache, then return it along + // with the obligations that went along with it. Note + // that, when using a fulfillment context, these + // obligations could in principle be ignored: they have + // already been registered when the cache entry was + // created (and hence the new ones will quickly be + // discarded as duplicated). But when doing trait + // evaluation this is not the case, and dropping the trait + // evaluations can causes ICEs (e.g., #43132). + debug!( + "opt_normalize_projection_type: \ + found normalized ty `{:?}`", + ty + ); + + // Once we have inferred everything we need to know, we + // can ignore the `obligations` from that point on. + if infcx.unresolved_type_vars(&ty.value).is_none() { + infcx.inner.borrow_mut().projection_cache.complete_normalized(cache_key, &ty); + // No need to extend `obligations`. + } else { + obligations.extend(ty.obligations); + } + + obligations.push(get_paranoid_cache_value_obligation( + infcx, + param_env, + projection_ty, + cause, + depth, + )); + return Some(ty.value); + } + Err(ProjectionCacheEntry::Error) => { + debug!( + "opt_normalize_projection_type: \ + found error" + ); + let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth); + obligations.extend(result.obligations); + return Some(result.value); + } + } + + let obligation = Obligation::with_depth(cause.clone(), depth, param_env, projection_ty); + match project_type(selcx, &obligation) { + Ok(ProjectedTy::Progress(Progress { + ty: projected_ty, + obligations: mut projected_obligations, + })) => { + // if projection succeeded, then what we get out of this + // is also non-normalized (consider: it was derived from + // an impl, where-clause etc) and hence we must + // re-normalize it + + debug!( + "opt_normalize_projection_type: \ + projected_ty={:?} \ + depth={} \ + projected_obligations={:?}", + projected_ty, depth, projected_obligations + ); + + let result = if projected_ty.has_projections() { + let mut normalizer = AssocTypeNormalizer::new( + selcx, + param_env, + cause, + depth + 1, + &mut projected_obligations, + ); + let normalized_ty = normalizer.fold(&projected_ty); + + debug!( + "opt_normalize_projection_type: \ + normalized_ty={:?} depth={}", + normalized_ty, depth + ); + + Normalized { value: normalized_ty, obligations: projected_obligations } + } else { + Normalized { value: projected_ty, obligations: projected_obligations } + }; + + let cache_value = prune_cache_value_obligations(infcx, &result); + infcx.inner.borrow_mut().projection_cache.insert_ty(cache_key, cache_value); + obligations.extend(result.obligations); + Some(result.value) + } + Ok(ProjectedTy::NoProgress(projected_ty)) => { + debug!( + "opt_normalize_projection_type: \ + projected_ty={:?} no progress", + projected_ty + ); + let result = Normalized { value: projected_ty, obligations: vec![] }; + infcx.inner.borrow_mut().projection_cache.insert_ty(cache_key, result.clone()); + // No need to extend `obligations`. + Some(result.value) + } + Err(ProjectionTyError::TooManyCandidates) => { + debug!( + "opt_normalize_projection_type: \ + too many candidates" + ); + infcx.inner.borrow_mut().projection_cache.ambiguous(cache_key); + None + } + Err(ProjectionTyError::TraitSelectionError(_)) => { + debug!("opt_normalize_projection_type: ERROR"); + // if we got an error processing the `T as Trait` part, + // just return `ty::err` but add the obligation `T : + // Trait`, which when processed will cause the error to be + // reported later + + infcx.inner.borrow_mut().projection_cache.error(cache_key); + let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth); + obligations.extend(result.obligations); + Some(result.value) + } + } +} + +/// If there are unresolved type variables, then we need to include +/// any subobligations that bind them, at least until those type +/// variables are fully resolved. +fn prune_cache_value_obligations<'a, 'tcx>( + infcx: &'a InferCtxt<'a, 'tcx>, + result: &NormalizedTy<'tcx>, +) -> NormalizedTy<'tcx> { + if infcx.unresolved_type_vars(&result.value).is_none() { + return NormalizedTy { value: result.value, obligations: vec![] }; + } + + let mut obligations: Vec<_> = result + .obligations + .iter() + .filter(|obligation| match obligation.predicate { + // We found a `T: Foo` predicate, let's check + // if `U` references any unresolved type + // variables. In principle, we only care if this + // projection can help resolve any of the type + // variables found in `result.value` -- but we just + // check for any type variables here, for fear of + // indirect obligations (e.g., we project to `?0`, + // but we have `T: Foo` and `?1: Bar`). + ty::Predicate::Projection(ref data) => infcx.unresolved_type_vars(&data.ty()).is_some(), + + // We are only interested in `T: Foo` predicates, whre + // `U` references one of `unresolved_type_vars`. =) + _ => false, + }) + .cloned() + .collect(); + + obligations.shrink_to_fit(); + + NormalizedTy { value: result.value, obligations } +} + +/// Whenever we give back a cache result for a projection like `::Item ==> X`, we *always* include the obligation to prove +/// that `T: Trait` (we may also include some other obligations). This +/// may or may not be necessary -- in principle, all the obligations +/// that must be proven to show that `T: Trait` were also returned +/// when the cache was first populated. But there are some vague concerns, +/// and so we take the precautionary measure of including `T: Trait` in +/// the result: +/// +/// Concern #1. The current setup is fragile. Perhaps someone could +/// have failed to prove the concerns from when the cache was +/// populated, but also not have used a snapshot, in which case the +/// cache could remain populated even though `T: Trait` has not been +/// shown. In this case, the "other code" is at fault -- when you +/// project something, you are supposed to either have a snapshot or +/// else prove all the resulting obligations -- but it's still easy to +/// get wrong. +/// +/// Concern #2. Even within the snapshot, if those original +/// obligations are not yet proven, then we are able to do projections +/// that may yet turn out to be wrong. This *may* lead to some sort +/// of trouble, though we don't have a concrete example of how that +/// can occur yet. But it seems risky at best. +fn get_paranoid_cache_value_obligation<'a, 'tcx>( + infcx: &'a InferCtxt<'a, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + projection_ty: ty::ProjectionTy<'tcx>, + cause: ObligationCause<'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.without_const().to_predicate(), + } +} + +/// If we are projecting `::Item`, but `T: Trait` does not +/// hold. In various error cases, we cannot generate a valid +/// normalized projection. Therefore, we create an inference variable +/// return an associated obligation that, when fulfilled, will lead to +/// an error. +/// +/// Note that we used to return `Error` here, but that was quite +/// dubious -- the premise was that an error would *eventually* be +/// reported, when the obligation was processed. But in general once +/// you see a `Error` you are supposed to be able to assume that an +/// error *has been* reported, so that you can take whatever heuristic +/// paths you want to take. To make things worse, it was possible for +/// cycles to arise, where you basically had a setup like ` +/// as Trait>::Foo == $0`. Here, normalizing ` as +/// Trait>::Foo> to `[type error]` would lead to an obligation of +/// ` as Trait>::Foo`. We are supposed to report +/// an error for this obligation, but we legitimately should not, +/// because it contains `[type error]`. Yuck! (See issue #29857 for +/// one case where this arose.) +fn normalize_to_error<'a, 'tcx>( + selcx: &mut SelectionContext<'a, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + projection_ty: ty::ProjectionTy<'tcx>, + cause: ObligationCause<'tcx>, + depth: usize, +) -> NormalizedTy<'tcx> { + let trait_ref = projection_ty.trait_ref(selcx.tcx()).to_poly_trait_ref(); + let trait_obligation = Obligation { + cause, + recursion_depth: depth, + param_env, + predicate: trait_ref.without_const().to_predicate(), + }; + let tcx = selcx.infcx().tcx; + let def_id = projection_ty.item_def_id; + let new_value = selcx.infcx().next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::NormalizeProjectionType, + span: tcx.def_span(def_id), + }); + Normalized { value: new_value, obligations: vec![trait_obligation] } +} + +enum ProjectedTy<'tcx> { + Progress(Progress<'tcx>), + NoProgress(Ty<'tcx>), +} + +struct Progress<'tcx> { + ty: Ty<'tcx>, + obligations: Vec>, +} + +impl<'tcx> Progress<'tcx> { + fn error(tcx: TyCtxt<'tcx>) -> Self { + Progress { ty: tcx.types.err, obligations: vec![] } + } + + fn with_addl_obligations(mut self, mut obligations: Vec>) -> Self { + debug!( + "with_addl_obligations: self.obligations.len={} obligations.len={}", + self.obligations.len(), + obligations.len() + ); + + debug!( + "with_addl_obligations: self.obligations={:?} obligations={:?}", + self.obligations, obligations + ); + + self.obligations.append(&mut obligations); + self + } +} + +/// Computes the result of a projection type (if we can). +/// +/// IMPORTANT: +/// - `obligation` must be fully normalized +fn project_type<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, +) -> Result, ProjectionTyError<'tcx>> { + debug!("project(obligation={:?})", obligation); + + let recursion_limit = *selcx.tcx().sess.recursion_limit.get(); + if obligation.recursion_depth >= recursion_limit { + debug!("project: overflow!"); + return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow)); + } + + let obligation_trait_ref = &obligation.predicate.trait_ref(selcx.tcx()); + + debug!("project: obligation_trait_ref={:?}", obligation_trait_ref); + + if obligation_trait_ref.references_error() { + return Ok(ProjectedTy::Progress(Progress::error(selcx.tcx()))); + } + + let mut candidates = ProjectionTyCandidateSet::None; + + // Make sure that the following procedures are kept in order. ParamEnv + // needs to be first because it has highest priority, and Select checks + // the return value of push_candidate which assumes it's ran at last. + assemble_candidates_from_param_env(selcx, obligation, &obligation_trait_ref, &mut candidates); + + assemble_candidates_from_trait_def(selcx, obligation, &obligation_trait_ref, &mut candidates); + + assemble_candidates_from_impls(selcx, obligation, &obligation_trait_ref, &mut candidates); + + match candidates { + ProjectionTyCandidateSet::Single(candidate) => Ok(ProjectedTy::Progress( + confirm_candidate(selcx, obligation, &obligation_trait_ref, candidate), + )), + ProjectionTyCandidateSet::None => Ok(ProjectedTy::NoProgress( + selcx + .tcx() + .mk_projection(obligation.predicate.item_def_id, obligation.predicate.substs), + )), + // Error occurred while trying to processing impls. + ProjectionTyCandidateSet::Error(e) => Err(ProjectionTyError::TraitSelectionError(e)), + // Inherent ambiguity that prevents us from even enumerating the + // candidates. + ProjectionTyCandidateSet::Ambiguous => Err(ProjectionTyError::TooManyCandidates), + } +} + +/// The first thing we have to do is scan through the parameter +/// environment to see whether there are any projection predicates +/// there that can answer this question. +fn assemble_candidates_from_param_env<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + obligation_trait_ref: &ty::TraitRef<'tcx>, + candidate_set: &mut ProjectionTyCandidateSet<'tcx>, +) { + debug!("assemble_candidates_from_param_env(..)"); + assemble_candidates_from_predicates( + selcx, + obligation, + obligation_trait_ref, + candidate_set, + ProjectionTyCandidate::ParamEnv, + obligation.param_env.caller_bounds.iter().cloned(), + ); +} + +/// In the case of a nested projection like <::FooT as Bar>::BarT, we may find +/// that the definition of `Foo` has some clues: +/// +/// ``` +/// trait Foo { +/// type FooT : Bar +/// } +/// ``` +/// +/// Here, for example, we could conclude that the result is `i32`. +fn assemble_candidates_from_trait_def<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + obligation_trait_ref: &ty::TraitRef<'tcx>, + candidate_set: &mut ProjectionTyCandidateSet<'tcx>, +) { + debug!("assemble_candidates_from_trait_def(..)"); + + let tcx = selcx.tcx(); + // Check whether the self-type is itself a projection. + let (def_id, substs) = match obligation_trait_ref.self_ty().kind { + ty::Projection(ref data) => (data.trait_ref(tcx).def_id, data.substs), + ty::Opaque(def_id, substs) => (def_id, substs), + ty::Infer(ty::TyVar(_)) => { + // If the self-type is an inference variable, then it MAY wind up + // being a projected type, so induce an ambiguity. + candidate_set.mark_ambiguous(); + return; + } + _ => return, + }; + + // If so, extract what we know from the trait and try to come up with a good answer. + let trait_predicates = tcx.predicates_of(def_id); + let bounds = trait_predicates.instantiate(tcx, substs); + let bounds = elaborate_predicates(tcx, bounds.predicates); + assemble_candidates_from_predicates( + selcx, + obligation, + obligation_trait_ref, + candidate_set, + ProjectionTyCandidate::TraitDef, + bounds, + ) +} + +fn assemble_candidates_from_predicates<'cx, 'tcx, I>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + obligation_trait_ref: &ty::TraitRef<'tcx>, + candidate_set: &mut ProjectionTyCandidateSet<'tcx>, + ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionTyCandidate<'tcx>, + env_predicates: I, +) where + I: IntoIterator>, +{ + debug!("assemble_candidates_from_predicates(obligation={:?})", obligation); + let infcx = selcx.infcx(); + for predicate in env_predicates { + debug!("assemble_candidates_from_predicates: predicate={:?}", predicate); + if let ty::Predicate::Projection(data) = predicate { + let same_def_id = data.projection_def_id() == obligation.predicate.item_def_id; + + let is_match = same_def_id + && infcx.probe(|_| { + let data_poly_trait_ref = data.to_poly_trait_ref(infcx.tcx); + let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref(); + infcx + .at(&obligation.cause, obligation.param_env) + .sup(obligation_poly_trait_ref, data_poly_trait_ref) + .map(|InferOk { obligations: _, value: () }| { + // FIXME(#32730) -- do we need to take obligations + // into account in any way? At the moment, no. + }) + .is_ok() + }); + + debug!( + "assemble_candidates_from_predicates: candidate={:?} \ + is_match={} same_def_id={}", + data, is_match, same_def_id + ); + + if is_match { + candidate_set.push_candidate(ctor(data)); + } + } + } +} + +fn assemble_candidates_from_impls<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + obligation_trait_ref: &ty::TraitRef<'tcx>, + candidate_set: &mut ProjectionTyCandidateSet<'tcx>, +) { + // If we are resolving `>::Item == Type`, + // start out by selecting the predicate `T as TraitRef<...>`: + let poly_trait_ref = obligation_trait_ref.to_poly_trait_ref(); + let trait_obligation = obligation.with(poly_trait_ref.to_poly_trait_predicate()); + let _ = selcx.infcx().commit_if_ok(|_| { + let vtable = match selcx.select(&trait_obligation) { + Ok(Some(vtable)) => vtable, + Ok(None) => { + candidate_set.mark_ambiguous(); + return Err(()); + } + Err(e) => { + debug!("assemble_candidates_from_impls: selection error {:?}", e); + candidate_set.mark_error(e); + return Err(()); + } + }; + + let eligible = match &vtable { + super::VtableClosure(_) + | super::VtableGenerator(_) + | super::VtableFnPointer(_) + | super::VtableObject(_) + | super::VtableTraitAlias(_) => { + debug!("assemble_candidates_from_impls: vtable={:?}", vtable); + true + } + super::VtableImpl(impl_data) => { + // We have to be careful when projecting out of an + // impl because of specialization. If we are not in + // codegen (i.e., projection mode is not "any"), and the + // impl's type is declared as default, then we disable + // projection (even if the trait ref is fully + // monomorphic). In the case where trait ref is not + // fully monomorphic (i.e., includes type parameters), + // this is because those type parameters may + // ultimately be bound to types from other crates that + // may have specialized impls we can't see. In the + // case where the trait ref IS fully monomorphic, this + // is a policy decision that we made in the RFC in + // order to preserve flexibility for the crate that + // defined the specializable impl to specialize later + // for existing types. + // + // In either case, we handle this by not adding a + // candidate for an impl if it contains a `default` + // type. + // + // NOTE: This should be kept in sync with the similar code in + // `rustc::ty::instance::resolve_associated_item()`. + let node_item = + assoc_ty_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id) + .map_err(|ErrorReported| ())?; + + let is_default = if node_item.node.is_from_trait() { + // If true, the impl inherited a `type Foo = Bar` + // given in the trait, which is implicitly default. + // Otherwise, the impl did not specify `type` and + // neither did the trait: + // + // ```rust + // trait Foo { type T; } + // impl Foo for Bar { } + // ``` + // + // This is an error, but it will be + // reported in `check_impl_items_against_trait`. + // We accept it here but will flag it as + // an error when we confirm the candidate + // (which will ultimately lead to `normalize_to_error` + // being invoked). + false + } else { + // If we're looking at a trait *impl*, the item is + // specializable if the impl or the item are marked + // `default`. + node_item.item.defaultness.is_default() + || super::util::impl_is_default(selcx.tcx(), node_item.node.def_id()) + }; + + match is_default { + // Non-specializable items are always projectable + false => true, + + // Only reveal a specializable default if we're past type-checking + // and the obligation is monomorphic, otherwise passes such as + // transmute checking and polymorphic MIR optimizations could + // get a result which isn't correct for all monomorphizations. + true if obligation.param_env.reveal == Reveal::All => { + // NOTE(eddyb) inference variables can resolve to parameters, so + // assume `poly_trait_ref` isn't monomorphic, if it contains any. + let poly_trait_ref = + selcx.infcx().resolve_vars_if_possible(&poly_trait_ref); + !poly_trait_ref.needs_infer() && !poly_trait_ref.needs_subst() + } + + true => { + debug!( + "assemble_candidates_from_impls: not eligible due to default: \ + assoc_ty={} predicate={}", + selcx.tcx().def_path_str(node_item.item.def_id), + obligation.predicate, + ); + false + } + } + } + super::VtableParam(..) => { + // This case tell us nothing about the value of an + // associated type. Consider: + // + // ``` + // trait SomeTrait { type Foo; } + // fn foo(...) { } + // ``` + // + // If the user writes `::Foo`, then the `T + // : SomeTrait` binding does not help us decide what the + // type `Foo` is (at least, not more specifically than + // what we already knew). + // + // But wait, you say! What about an example like this: + // + // ``` + // fn bar>(...) { ... } + // ``` + // + // Doesn't the `T : Sometrait` predicate help + // resolve `T::Foo`? And of course it does, but in fact + // that single predicate is desugared into two predicates + // in the compiler: a trait predicate (`T : SomeTrait`) and a + // projection. And the projection where clause is handled + // in `assemble_candidates_from_param_env`. + false + } + super::VtableAutoImpl(..) | super::VtableBuiltin(..) => { + // These traits have no associated types. + span_bug!( + obligation.cause.span, + "Cannot project an associated type from `{:?}`", + vtable + ); + } + }; + + if eligible { + if candidate_set.push_candidate(ProjectionTyCandidate::Select(vtable)) { + Ok(()) + } else { + Err(()) + } + } else { + Err(()) + } + }); +} + +fn confirm_candidate<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + obligation_trait_ref: &ty::TraitRef<'tcx>, + candidate: ProjectionTyCandidate<'tcx>, +) -> Progress<'tcx> { + debug!("confirm_candidate(candidate={:?}, obligation={:?})", candidate, obligation); + + match candidate { + ProjectionTyCandidate::ParamEnv(poly_projection) + | ProjectionTyCandidate::TraitDef(poly_projection) => { + confirm_param_env_candidate(selcx, obligation, poly_projection) + } + + ProjectionTyCandidate::Select(vtable) => { + confirm_select_candidate(selcx, obligation, obligation_trait_ref, vtable) + } + } +} + +fn confirm_select_candidate<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + obligation_trait_ref: &ty::TraitRef<'tcx>, + vtable: Selection<'tcx>, +) -> Progress<'tcx> { + match vtable { + super::VtableImpl(data) => confirm_impl_candidate(selcx, obligation, data), + super::VtableGenerator(data) => confirm_generator_candidate(selcx, obligation, data), + super::VtableClosure(data) => confirm_closure_candidate(selcx, obligation, data), + super::VtableFnPointer(data) => confirm_fn_pointer_candidate(selcx, obligation, data), + super::VtableObject(_) => confirm_object_candidate(selcx, obligation, obligation_trait_ref), + super::VtableAutoImpl(..) + | super::VtableParam(..) + | super::VtableBuiltin(..) + | super::VtableTraitAlias(..) => + // we don't create Select candidates with this kind of resolution + { + span_bug!( + obligation.cause.span, + "Cannot project an associated type from `{:?}`", + vtable + ) + } + } +} + +fn confirm_object_candidate<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + obligation_trait_ref: &ty::TraitRef<'tcx>, +) -> Progress<'tcx> { + let self_ty = obligation_trait_ref.self_ty(); + let object_ty = selcx.infcx().shallow_resolve(self_ty); + debug!("confirm_object_candidate(object_ty={:?})", object_ty); + let data = match object_ty.kind { + ty::Dynamic(ref data, ..) => data, + _ => span_bug!( + obligation.cause.span, + "confirm_object_candidate called with non-object: {:?}", + object_ty + ), + }; + let env_predicates = data + .projection_bounds() + .map(|p| p.with_self_ty(selcx.tcx(), object_ty).to_predicate()) + .collect(); + let env_predicate = { + let env_predicates = elaborate_predicates(selcx.tcx(), env_predicates); + + // select only those projections that are actually projecting an + // item with the correct name + let env_predicates = env_predicates.filter_map(|p| match p { + ty::Predicate::Projection(data) => { + if data.projection_def_id() == obligation.predicate.item_def_id { + Some(data) + } else { + None + } + } + _ => None, + }); + + // select those with a relevant trait-ref + let mut env_predicates = env_predicates.filter(|data| { + let data_poly_trait_ref = data.to_poly_trait_ref(selcx.tcx()); + let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref(); + selcx.infcx().probe(|_| { + selcx + .infcx() + .at(&obligation.cause, obligation.param_env) + .sup(obligation_poly_trait_ref, data_poly_trait_ref) + .is_ok() + }) + }); + + // select the first matching one; there really ought to be one or + // else the object type is not WF, since an object type should + // include all of its projections explicitly + match env_predicates.next() { + Some(env_predicate) => env_predicate, + None => { + debug!( + "confirm_object_candidate: no env-predicate \ + found in object type `{:?}`; ill-formed", + object_ty + ); + return Progress::error(selcx.tcx()); + } + } + }; + + confirm_param_env_candidate(selcx, obligation, env_predicate) +} + +fn confirm_generator_candidate<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + vtable: VtableGeneratorData<'tcx, PredicateObligation<'tcx>>, +) -> Progress<'tcx> { + let gen_sig = vtable.substs.as_generator().poly_sig(); + let Normalized { value: gen_sig, obligations } = normalize_with_depth( + selcx, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &gen_sig, + ); + + debug!( + "confirm_generator_candidate: obligation={:?},gen_sig={:?},obligations={:?}", + obligation, gen_sig, obligations + ); + + let tcx = selcx.tcx(); + + let gen_def_id = tcx.lang_items().gen_trait().unwrap(); + + let predicate = super::util::generator_trait_ref_and_outputs( + tcx, + gen_def_id, + obligation.predicate.self_ty(), + gen_sig, + ) + .map_bound(|(trait_ref, yield_ty, return_ty)| { + let name = tcx.associated_item(obligation.predicate.item_def_id).ident.name; + let ty = if name == sym::Return { + return_ty + } else if name == sym::Yield { + yield_ty + } else { + bug!() + }; + + ty::ProjectionPredicate { + projection_ty: ty::ProjectionTy { + substs: trait_ref.substs, + item_def_id: obligation.predicate.item_def_id, + }, + ty, + } + }); + + confirm_param_env_candidate(selcx, obligation, predicate) + .with_addl_obligations(vtable.nested) + .with_addl_obligations(obligations) +} + +fn confirm_fn_pointer_candidate<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + fn_pointer_vtable: VtableFnPointerData<'tcx, PredicateObligation<'tcx>>, +) -> Progress<'tcx> { + let fn_type = selcx.infcx().shallow_resolve(fn_pointer_vtable.fn_ty); + let sig = fn_type.fn_sig(selcx.tcx()); + let Normalized { value: sig, obligations } = normalize_with_depth( + selcx, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &sig, + ); + + confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes) + .with_addl_obligations(fn_pointer_vtable.nested) + .with_addl_obligations(obligations) +} + +fn confirm_closure_candidate<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + vtable: VtableClosureData<'tcx, PredicateObligation<'tcx>>, +) -> Progress<'tcx> { + let closure_sig = vtable.substs.as_closure().sig(); + let Normalized { value: closure_sig, obligations } = normalize_with_depth( + selcx, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &closure_sig, + ); + + debug!( + "confirm_closure_candidate: obligation={:?},closure_sig={:?},obligations={:?}", + obligation, closure_sig, obligations + ); + + confirm_callable_candidate(selcx, obligation, closure_sig, util::TupleArgumentsFlag::No) + .with_addl_obligations(vtable.nested) + .with_addl_obligations(obligations) +} + +fn confirm_callable_candidate<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + fn_sig: ty::PolyFnSig<'tcx>, + flag: util::TupleArgumentsFlag, +) -> Progress<'tcx> { + let tcx = selcx.tcx(); + + debug!("confirm_callable_candidate({:?},{:?})", obligation, fn_sig); + + // the `Output` associated type is declared on `FnOnce` + let fn_once_def_id = tcx.lang_items().fn_once_trait().unwrap(); + + let predicate = super::util::closure_trait_ref_and_return_type( + tcx, + fn_once_def_id, + obligation.predicate.self_ty(), + fn_sig, + flag, + ) + .map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate { + projection_ty: ty::ProjectionTy::from_ref_and_name( + tcx, + trait_ref, + Ident::with_dummy_span(rustc_hir::FN_OUTPUT_NAME), + ), + ty: ret_type, + }); + + confirm_param_env_candidate(selcx, obligation, predicate) +} + +fn confirm_param_env_candidate<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + poly_cache_entry: ty::PolyProjectionPredicate<'tcx>, +) -> Progress<'tcx> { + let infcx = selcx.infcx(); + let cause = &obligation.cause; + let param_env = obligation.param_env; + + let (cache_entry, _) = infcx.replace_bound_vars_with_fresh_vars( + cause.span, + LateBoundRegionConversionTime::HigherRankedType, + &poly_cache_entry, + ); + + let cache_trait_ref = cache_entry.projection_ty.trait_ref(infcx.tcx); + let obligation_trait_ref = obligation.predicate.trait_ref(infcx.tcx); + match infcx.at(cause, param_env).eq(cache_trait_ref, obligation_trait_ref) { + Ok(InferOk { value: _, obligations }) => Progress { ty: cache_entry.ty, obligations }, + Err(e) => { + let msg = format!( + "Failed to unify obligation `{:?}` with poly_projection `{:?}`: {:?}", + obligation, poly_cache_entry, e, + ); + debug!("confirm_param_env_candidate: {}", msg); + infcx.tcx.sess.delay_span_bug(obligation.cause.span, &msg); + Progress { ty: infcx.tcx.types.err, obligations: vec![] } + } + } +} + +fn confirm_impl_candidate<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + impl_vtable: VtableImplData<'tcx, PredicateObligation<'tcx>>, +) -> Progress<'tcx> { + let tcx = selcx.tcx(); + + let VtableImplData { impl_def_id, substs, nested } = impl_vtable; + let assoc_item_id = obligation.predicate.item_def_id; + let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap(); + + let param_env = obligation.param_env; + let assoc_ty = match assoc_ty_def(selcx, impl_def_id, assoc_item_id) { + Ok(assoc_ty) => assoc_ty, + Err(ErrorReported) => return Progress { ty: tcx.types.err, obligations: nested }, + }; + + if !assoc_ty.item.defaultness.has_value() { + // This means that the impl is missing a definition for the + // associated type. This error will be reported by the type + // checker method `check_impl_items_against_trait`, so here we + // just return Error. + debug!( + "confirm_impl_candidate: no associated type {:?} for {:?}", + assoc_ty.item.ident, obligation.predicate + ); + return Progress { ty: tcx.types.err, obligations: nested }; + } + let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs); + let substs = translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.node); + let ty = if let ty::AssocKind::OpaqueTy = assoc_ty.item.kind { + let item_substs = InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id); + tcx.mk_opaque(assoc_ty.item.def_id, item_substs) + } else { + tcx.type_of(assoc_ty.item.def_id) + }; + if substs.len() != tcx.generics_of(assoc_ty.item.def_id).count() { + tcx.sess + .delay_span_bug(DUMMY_SP, "impl item and trait item have different parameter counts"); + Progress { ty: tcx.types.err, obligations: nested } + } else { + Progress { ty: ty.subst(tcx, substs), obligations: nested } + } +} + +/// Locate the definition of an associated type in the specialization hierarchy, +/// starting from the given impl. +/// +/// Based on the "projection mode", this lookup may in fact only examine the +/// topmost impl. See the comments for `Reveal` for more details. +fn assoc_ty_def( + selcx: &SelectionContext<'_, '_>, + impl_def_id: DefId, + assoc_ty_def_id: DefId, +) -> Result, ErrorReported> { + let tcx = selcx.tcx(); + let assoc_ty_name = tcx.associated_item(assoc_ty_def_id).ident; + let trait_def_id = tcx.impl_trait_ref(impl_def_id).unwrap().def_id; + let trait_def = tcx.trait_def(trait_def_id); + + // This function may be called while we are still building the + // specialization graph that is queried below (via TraitDef::ancestors()), + // so, in order to avoid unnecessary infinite recursion, we manually look + // for the associated item at the given impl. + // If there is no such item in that impl, this function will fail with a + // cycle error if the specialization graph is currently being built. + let impl_node = specialization_graph::Node::Impl(impl_def_id); + for item in impl_node.items(tcx) { + if matches!(item.kind, ty::AssocKind::Type | ty::AssocKind::OpaqueTy) + && tcx.hygienic_eq(item.ident, assoc_ty_name, trait_def_id) + { + return Ok(specialization_graph::NodeItem { + node: specialization_graph::Node::Impl(impl_def_id), + item: *item, + }); + } + } + + let ancestors = trait_def.ancestors(tcx, impl_def_id)?; + if let Some(assoc_item) = ancestors.leaf_def(tcx, assoc_ty_name, ty::AssocKind::Type) { + Ok(assoc_item) + } else { + // This is saying that neither the trait nor + // the impl contain a definition for this + // associated type. Normally this situation + // could only arise through a compiler bug -- + // if the user wrote a bad item name, it + // should have failed in astconv. + bug!("No associated type `{}` for {}", assoc_ty_name, tcx.def_path_str(impl_def_id)) + } +} + +crate trait ProjectionCacheKeyExt<'tcx>: Sized { + fn from_poly_projection_predicate( + selcx: &mut SelectionContext<'cx, 'tcx>, + predicate: &ty::PolyProjectionPredicate<'tcx>, + ) -> Option; +} + +impl<'tcx> ProjectionCacheKeyExt<'tcx> for ProjectionCacheKey<'tcx> { + fn from_poly_projection_predicate( + selcx: &mut SelectionContext<'cx, 'tcx>, + predicate: &ty::PolyProjectionPredicate<'tcx>, + ) -> Option { + let infcx = selcx.infcx(); + // We don't do cross-snapshot caching of obligations with escaping regions, + // so there's no cache key to use + predicate.no_bound_vars().map(|predicate| { + ProjectionCacheKey::new( + // We don't attempt to match up with a specific type-variable state + // from a specific call to `opt_normalize_projection_type` - if + // there's no precise match, the original cache entry is "stranded" + // anyway. + infcx.resolve_vars_if_possible(&predicate.projection_ty), + ) + }) + } +} diff --git a/src/librustc_infer/traits/query/dropck_outlives.rs b/src/librustc_trait_selection/traits/query/dropck_outlives.rs similarity index 93% rename from src/librustc_infer/traits/query/dropck_outlives.rs rename to src/librustc_trait_selection/traits/query/dropck_outlives.rs index a1d7a2836e42d..03c6cf35e8881 100644 --- a/src/librustc_infer/traits/query/dropck_outlives.rs +++ b/src/librustc_trait_selection/traits/query/dropck_outlives.rs @@ -7,7 +7,11 @@ use rustc::ty::{self, Ty, TyCtxt}; pub use rustc::traits::query::{DropckOutlivesResult, DtorckConstraint}; -impl<'cx, 'tcx> At<'cx, 'tcx> { +pub trait AtExt<'tcx> { + fn dropck_outlives(&self, ty: Ty<'tcx>) -> InferOk<'tcx, Vec>>; +} + +impl<'cx, 'tcx> AtExt<'tcx> for 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 /// of the destructor. These basically correspond to data that the @@ -25,7 +29,7 @@ impl<'cx, 'tcx> At<'cx, 'tcx> { /// /// [#1238]: https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md /// [#1327]: https://github.com/rust-lang/rfcs/blob/master/text/1327-dropck-param-eyepatch.md - pub fn dropck_outlives(&self, ty: Ty<'tcx>) -> InferOk<'tcx, Vec>> { + fn dropck_outlives(&self, ty: Ty<'tcx>) -> InferOk<'tcx, Vec>> { debug!("dropck_outlives(ty={:?}, param_env={:?})", ty, self.param_env,); // Quick check: there are a number of cases that we know do not require @@ -105,8 +109,8 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { // (T1..Tn) and closures have same properties as T1..Tn -- // check if *any* of those are trivial. ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t.expect_ty())), - ty::Closure(def_id, ref substs) => { - substs.as_closure().upvar_tys(def_id, tcx).all(|t| trivial_dropck_outlives(tcx, t)) + ty::Closure(_, ref substs) => { + substs.as_closure().upvar_tys().all(|t| trivial_dropck_outlives(tcx, t)) } ty::Adt(def, _) => { diff --git a/src/librustc_infer/traits/query/evaluate_obligation.rs b/src/librustc_trait_selection/traits/query/evaluate_obligation.rs similarity index 71% rename from src/librustc_infer/traits/query/evaluate_obligation.rs rename to src/librustc_trait_selection/traits/query/evaluate_obligation.rs index b9ce3ccff2748..0569f6217da65 100644 --- a/src/librustc_infer/traits/query/evaluate_obligation.rs +++ b/src/librustc_trait_selection/traits/query/evaluate_obligation.rs @@ -4,10 +4,35 @@ use crate::traits::{ EvaluationResult, OverflowError, PredicateObligation, SelectionContext, TraitQueryMode, }; -impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { +pub trait InferCtxtExt<'tcx> { + fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool; + + fn predicate_must_hold_considering_regions( + &self, + obligation: &PredicateObligation<'tcx>, + ) -> bool; + + fn predicate_must_hold_modulo_regions(&self, obligation: &PredicateObligation<'tcx>) -> bool; + + fn evaluate_obligation( + &self, + obligation: &PredicateObligation<'tcx>, + ) -> Result; + + // Helper function that canonicalizes and runs the query. If an + // overflow results, we re-run it in the local context so we can + // report a nice error. + /*crate*/ + fn evaluate_obligation_no_overflow( + &self, + obligation: &PredicateObligation<'tcx>, + ) -> EvaluationResult; +} + +impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { /// Evaluates whether the predicate can be satisfied (by any means) /// in the given `ParamEnv`. - pub fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool { + fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool { self.evaluate_obligation_no_overflow(obligation).may_apply() } @@ -17,7 +42,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// /// This version may conservatively fail when outlives obligations /// are required. - pub fn predicate_must_hold_considering_regions( + fn predicate_must_hold_considering_regions( &self, obligation: &PredicateObligation<'tcx>, ) -> bool { @@ -29,15 +54,12 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// not entirely accurate if inference variables are involved. /// /// This version ignores all outlives constraints. - pub fn predicate_must_hold_modulo_regions( - &self, - obligation: &PredicateObligation<'tcx>, - ) -> bool { + fn predicate_must_hold_modulo_regions(&self, obligation: &PredicateObligation<'tcx>) -> bool { self.evaluate_obligation_no_overflow(obligation).must_apply_modulo_regions() } /// Evaluate a given predicate, capturing overflow and propagating it back. - pub fn evaluate_obligation( + fn evaluate_obligation( &self, obligation: &PredicateObligation<'tcx>, ) -> Result { @@ -53,7 +75,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { // Helper function that canonicalizes and runs the query. If an // overflow results, we re-run it in the local context so we can // report a nice error. - crate fn evaluate_obligation_no_overflow( + fn evaluate_obligation_no_overflow( &self, obligation: &PredicateObligation<'tcx>, ) -> EvaluationResult { diff --git a/src/librustc_infer/traits/query/method_autoderef.rs b/src/librustc_trait_selection/traits/query/method_autoderef.rs similarity index 100% rename from src/librustc_infer/traits/query/method_autoderef.rs rename to src/librustc_trait_selection/traits/query/method_autoderef.rs diff --git a/src/librustc_infer/traits/query/mod.rs b/src/librustc_trait_selection/traits/query/mod.rs similarity index 100% rename from src/librustc_infer/traits/query/mod.rs rename to src/librustc_trait_selection/traits/query/mod.rs diff --git a/src/librustc_infer/traits/query/normalize.rs b/src/librustc_trait_selection/traits/query/normalize.rs similarity index 93% rename from src/librustc_infer/traits/query/normalize.rs rename to src/librustc_trait_selection/traits/query/normalize.rs index 4577e3d2e1cf8..77128bc8c8ab4 100644 --- a/src/librustc_infer/traits/query/normalize.rs +++ b/src/librustc_trait_selection/traits/query/normalize.rs @@ -5,17 +5,24 @@ use crate::infer::at::At; use crate::infer::canonical::OriginalQueryValues; use crate::infer::{InferCtxt, InferOk}; -use crate::traits::project::Normalized; +use crate::traits::error_reporting::InferCtxtExt; use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal}; use rustc::ty::fold::{TypeFoldable, TypeFolder}; use rustc::ty::subst::Subst; use rustc::ty::{self, Ty, TyCtxt}; +use rustc_infer::traits::Normalized; use super::NoSolution; pub use rustc::traits::query::NormalizationResult; -impl<'cx, 'tcx> At<'cx, 'tcx> { +pub trait AtExt<'tcx> { + fn normalize(&self, value: &T) -> Result, NoSolution> + where + T: TypeFoldable<'tcx>; +} + +impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> { /// Normalize `value` in the context of the inference context, /// yielding a resulting type, or an error if `value` cannot be /// normalized. If you don't care about regions, you should prefer @@ -29,7 +36,7 @@ impl<'cx, 'tcx> At<'cx, 'tcx> { /// normalizing, but for now should be used only when we actually /// know that normalization will succeed, since error reporting /// and other details are still "under development". - pub fn normalize(&self, value: &T) -> Result, NoSolution> + fn normalize(&self, value: &T) -> Result, NoSolution> where T: TypeFoldable<'tcx>, { @@ -162,12 +169,12 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { debug!("QueryNormalizer: result = {:#?}", result); debug!("QueryNormalizer: obligations = {:#?}", obligations); self.obligations.extend(obligations); - return result.normalized_ty; + result.normalized_ty } Err(_) => { self.error = true; - return ty; + ty } } } @@ -184,6 +191,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { } fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + let constant = constant.super_fold_with(self); constant.eval(self.infcx.tcx, self.param_env) } } diff --git a/src/librustc_infer/traits/query/outlives_bounds.rs b/src/librustc_trait_selection/traits/query/outlives_bounds.rs similarity index 78% rename from src/librustc_infer/traits/query/outlives_bounds.rs rename to src/librustc_trait_selection/traits/query/outlives_bounds.rs index eb32ebf5c4db4..05c96dd520ab7 100644 --- a/src/librustc_infer/traits/query/outlives_bounds.rs +++ b/src/librustc_trait_selection/traits/query/outlives_bounds.rs @@ -1,14 +1,25 @@ use crate::infer::canonical::OriginalQueryValues; use crate::infer::InferCtxt; use crate::traits::query::NoSolution; -use crate::traits::{FulfillmentContext, ObligationCause, TraitEngine, TraitEngineExt}; +use crate::traits::{FulfillmentContext, ObligationCause, TraitEngine}; use rustc::ty::{self, Ty}; use rustc_hir as hir; +use rustc_infer::traits::TraitEngineExt as _; use rustc_span::source_map::Span; pub use rustc::traits::query::OutlivesBound; -impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { +pub trait InferCtxtExt<'tcx> { + fn implied_outlives_bounds( + &self, + param_env: ty::ParamEnv<'tcx>, + body_id: hir::HirId, + ty: Ty<'tcx>, + span: Span, + ) -> Vec>; +} + +impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { /// Implied bounds are region relationships that we deduce /// automatically. The idea is that (e.g.) a caller must check that a /// function's argument types are well-formed immediately before @@ -30,7 +41,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// - `ty`, the type that we are supposed to assume is WF. /// - `span`, a span to use when normalizing, hopefully not important, /// might be useful if a `bug!` occurs. - pub fn implied_outlives_bounds( + fn implied_outlives_bounds( &self, param_env: ty::ParamEnv<'tcx>, body_id: hir::HirId, @@ -82,22 +93,3 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { result.value } } - -pub fn explicit_outlives_bounds<'tcx>( - param_env: ty::ParamEnv<'tcx>, -) -> impl Iterator> + 'tcx { - debug!("explicit_outlives_bounds()"); - param_env.caller_bounds.into_iter().filter_map(move |predicate| match predicate { - ty::Predicate::Projection(..) - | ty::Predicate::Trait(..) - | ty::Predicate::Subtype(..) - | ty::Predicate::WellFormed(..) - | ty::Predicate::ObjectSafe(..) - | ty::Predicate::ClosureKind(..) - | ty::Predicate::TypeOutlives(..) - | ty::Predicate::ConstEvaluatable(..) => None, - ty::Predicate::RegionOutlives(ref data) => data - .no_bound_vars() - .map(|ty::OutlivesPredicate(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a)), - }) -} diff --git a/src/librustc_infer/traits/query/type_op/ascribe_user_type.rs b/src/librustc_trait_selection/traits/query/type_op/ascribe_user_type.rs similarity index 100% rename from src/librustc_infer/traits/query/type_op/ascribe_user_type.rs rename to src/librustc_trait_selection/traits/query/type_op/ascribe_user_type.rs diff --git a/src/librustc_infer/traits/query/type_op/custom.rs b/src/librustc_trait_selection/traits/query/type_op/custom.rs similarity index 96% rename from src/librustc_infer/traits/query/type_op/custom.rs rename to src/librustc_trait_selection/traits/query/type_op/custom.rs index c1c9030b88805..915e8ae4a7ad6 100644 --- a/src/librustc_infer/traits/query/type_op/custom.rs +++ b/src/librustc_trait_selection/traits/query/type_op/custom.rs @@ -4,7 +4,9 @@ use std::fmt; use crate::infer::canonical::query_response; use crate::infer::canonical::QueryRegionConstraints; -use crate::traits::{ObligationCause, TraitEngine, TraitEngineExt}; +use crate::traits::engine::TraitEngineExt as _; +use crate::traits::{ObligationCause, TraitEngine}; +use rustc_infer::traits::TraitEngineExt as _; use rustc_span::source_map::DUMMY_SP; use std::rc::Rc; diff --git a/src/librustc_infer/traits/query/type_op/eq.rs b/src/librustc_trait_selection/traits/query/type_op/eq.rs similarity index 100% rename from src/librustc_infer/traits/query/type_op/eq.rs rename to src/librustc_trait_selection/traits/query/type_op/eq.rs diff --git a/src/librustc_infer/traits/query/type_op/implied_outlives_bounds.rs b/src/librustc_trait_selection/traits/query/type_op/implied_outlives_bounds.rs similarity index 100% rename from src/librustc_infer/traits/query/type_op/implied_outlives_bounds.rs rename to src/librustc_trait_selection/traits/query/type_op/implied_outlives_bounds.rs diff --git a/src/librustc_infer/traits/query/type_op/mod.rs b/src/librustc_trait_selection/traits/query/type_op/mod.rs similarity index 100% rename from src/librustc_infer/traits/query/type_op/mod.rs rename to src/librustc_trait_selection/traits/query/type_op/mod.rs diff --git a/src/librustc_infer/traits/query/type_op/normalize.rs b/src/librustc_trait_selection/traits/query/type_op/normalize.rs similarity index 100% rename from src/librustc_infer/traits/query/type_op/normalize.rs rename to src/librustc_trait_selection/traits/query/type_op/normalize.rs diff --git a/src/librustc_infer/traits/query/type_op/outlives.rs b/src/librustc_trait_selection/traits/query/type_op/outlives.rs similarity index 100% rename from src/librustc_infer/traits/query/type_op/outlives.rs rename to src/librustc_trait_selection/traits/query/type_op/outlives.rs diff --git a/src/librustc_infer/traits/query/type_op/prove_predicate.rs b/src/librustc_trait_selection/traits/query/type_op/prove_predicate.rs similarity index 100% rename from src/librustc_infer/traits/query/type_op/prove_predicate.rs rename to src/librustc_trait_selection/traits/query/type_op/prove_predicate.rs diff --git a/src/librustc_infer/traits/query/type_op/subtype.rs b/src/librustc_trait_selection/traits/query/type_op/subtype.rs similarity index 100% rename from src/librustc_infer/traits/query/type_op/subtype.rs rename to src/librustc_trait_selection/traits/query/type_op/subtype.rs diff --git a/src/librustc_infer/traits/select.rs b/src/librustc_trait_selection/traits/select.rs similarity index 97% rename from src/librustc_infer/traits/select.rs rename to src/librustc_trait_selection/traits/select.rs index b50f14475fceb..2d6fabea6ec75 100644 --- a/src/librustc_infer/traits/select.rs +++ b/src/librustc_trait_selection/traits/select.rs @@ -9,9 +9,7 @@ use self::SelectionCandidate::*; use super::coherence::{self, Conflict}; use super::project; -use super::project::{ - normalize_with_depth, normalize_with_depth_to, Normalized, ProjectionCacheKey, -}; +use super::project::{normalize_with_depth, normalize_with_depth_to}; use super::util; use super::util::{closure_trait_ref_and_return_type, predicate_for_trait_def}; use super::wf; @@ -21,6 +19,7 @@ use super::SelectionResult; use super::TraitNotObjectSafe; use super::TraitQueryMode; use super::{BuiltinDerivedObligation, ImplDerivedObligation, ObligationCauseCode}; +use super::{Normalized, ProjectionCacheKey}; use super::{ObjectCastObligation, Obligation}; use super::{ObligationCause, PredicateObligation, TraitObligation}; use super::{OutputTypeParameterMismatch, Overflow, SelectionError, Unimplemented}; @@ -34,6 +33,8 @@ use super::{ }; use crate::infer::{CombinedSnapshot, InferCtxt, InferOk, PlaceholderMap, TypeFreshener}; +use crate::traits::error_reporting::InferCtxtExt; +use crate::traits::project::ProjectionCacheKeyExt; use rustc::dep_graph::{DepKind, DepNodeIndex}; use rustc::middle::lang_items; use rustc::ty::fast_reject; @@ -95,47 +96,6 @@ pub struct SelectionContext<'cx, 'tcx> { query_mode: TraitQueryMode, } -#[derive(Clone, Debug)] -pub enum IntercrateAmbiguityCause { - DownstreamCrate { trait_desc: String, self_desc: Option }, - UpstreamCrateUpdate { trait_desc: String, self_desc: Option }, - ReservationImpl { message: String }, -} - -impl IntercrateAmbiguityCause { - /// Emits notes when the overlap is caused by complex intercrate ambiguities. - /// See #23980 for details. - pub fn add_intercrate_ambiguity_hint(&self, err: &mut rustc_errors::DiagnosticBuilder<'_>) { - err.note(&self.intercrate_ambiguity_hint()); - } - - pub fn intercrate_ambiguity_hint(&self) -> String { - match self { - &IntercrateAmbiguityCause::DownstreamCrate { ref trait_desc, ref self_desc } => { - let self_desc = if let &Some(ref ty) = self_desc { - format!(" for type `{}`", ty) - } else { - String::new() - }; - format!("downstream crates may implement trait `{}`{}", trait_desc, self_desc) - } - &IntercrateAmbiguityCause::UpstreamCrateUpdate { ref trait_desc, ref self_desc } => { - let self_desc = if let &Some(ref ty) = self_desc { - format!(" for type `{}`", ty) - } else { - String::new() - }; - format!( - "upstream crates may add a new impl of trait `{}`{} \ - in future versions", - trait_desc, self_desc - ) - } - &IntercrateAmbiguityCause::ReservationImpl { ref message } => message.clone(), - } - } -} - // A stack that walks back up the stack frame. struct TraitObligationStack<'prev, 'tcx> { obligation: &'prev TraitObligation<'tcx>, @@ -518,8 +478,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => { - match self.infcx.closure_kind(closure_def_id, closure_substs) { + ty::Predicate::ClosureKind(_, closure_substs, kind) => { + match self.infcx.closure_kind(closure_substs) { Some(closure_kind) => { if closure_kind.extends(kind) { Ok(EvaluatedToOk) @@ -1640,9 +1600,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // touch bound regions, they just capture the in-scope // type/region parameters match obligation.self_ty().skip_binder().kind { - ty::Closure(closure_def_id, closure_substs) => { + ty::Closure(_, closure_substs) => { debug!("assemble_unboxed_candidates: kind={:?} obligation={:?}", kind, obligation); - match self.infcx.closure_kind(closure_def_id, closure_substs) { + match self.infcx.closure_kind(closure_substs) { Some(closure_kind) => { debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind); if closure_kind.extends(kind) { @@ -2274,9 +2234,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Where(ty::Binder::bind(tys.iter().map(|k| k.expect_ty()).collect())) } - ty::Closure(def_id, substs) => { + ty::Closure(_, substs) => { // (*) binder moved here - Where(ty::Binder::bind(substs.as_closure().upvar_tys(def_id, self.tcx()).collect())) + Where(ty::Binder::bind(substs.as_closure().upvar_tys().collect())) } ty::Adt(..) | ty::Projection(..) | ty::Param(..) | ty::Opaque(..) => { @@ -2353,17 +2313,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { tys.iter().map(|k| k.expect_ty()).collect() } - ty::Closure(def_id, ref substs) => { - substs.as_closure().upvar_tys(def_id, self.tcx()).collect() - } + ty::Closure(_, ref substs) => substs.as_closure().upvar_tys().collect(), - ty::Generator(def_id, ref substs, _) => { - let witness = substs.as_generator().witness(def_id, self.tcx()); - substs - .as_generator() - .upvar_tys(def_id, self.tcx()) - .chain(iter::once(witness)) - .collect() + ty::Generator(_, ref substs, _) => { + let witness = substs.as_generator().witness(); + substs.as_generator().upvar_tys().chain(iter::once(witness)).collect() } ty::GeneratorWitness(types) => { @@ -2832,7 +2786,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { trait_def_id, trait_obligations ); - VtableTraitAliasData { alias_def_id, substs: substs, nested: trait_obligations } + VtableTraitAliasData { alias_def_id, substs, nested: trait_obligations } }) } @@ -2851,7 +2805,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!("confirm_generator_candidate({:?},{:?},{:?})", obligation, generator_def_id, substs); - let trait_ref = self.generator_trait_ref_unnormalized(obligation, generator_def_id, substs); + let trait_ref = self.generator_trait_ref_unnormalized(obligation, substs); let Normalized { value: trait_ref, mut obligations } = normalize_with_depth( self, obligation.param_env, @@ -2896,7 +2850,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => bug!("closure candidate for non-closure {:?}", obligation), }; - let trait_ref = self.closure_trait_ref_unnormalized(obligation, closure_def_id, substs); + let trait_ref = self.closure_trait_ref_unnormalized(obligation, substs); let Normalized { value: trait_ref, mut obligations } = normalize_with_depth( self, obligation.param_env, @@ -2987,13 +2941,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let existential_predicates = data_a.map_bound(|data_a| { let iter = data_a .principal() - .map(|x| ty::ExistentialPredicate::Trait(x)) + .map(ty::ExistentialPredicate::Trait) .into_iter() - .chain( - data_a - .projection_bounds() - .map(|x| ty::ExistentialPredicate::Projection(x)), - ) + .chain(data_a.projection_bounds().map(ty::ExistentialPredicate::Projection)) .chain(data_b.auto_traits().map(ty::ExistentialPredicate::AutoTrait)); tcx.mk_existential_predicates(iter) }); @@ -3382,16 +3332,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn closure_trait_ref_unnormalized( &mut self, obligation: &TraitObligation<'tcx>, - closure_def_id: DefId, substs: SubstsRef<'tcx>, ) -> ty::PolyTraitRef<'tcx> { - debug!( - "closure_trait_ref_unnormalized(obligation={:?}, closure_def_id={:?}, substs={:?})", - obligation, closure_def_id, substs, - ); - let closure_type = self.infcx.closure_sig(closure_def_id, substs); + debug!("closure_trait_ref_unnormalized(obligation={:?}, substs={:?})", obligation, substs); + let closure_sig = substs.as_closure().sig(); - debug!("closure_trait_ref_unnormalized: closure_type = {:?}", closure_type); + debug!("closure_trait_ref_unnormalized: closure_sig = {:?}", closure_sig); // (1) Feels icky to skip the binder here, but OTOH we know // that the self-type is an unboxed closure type and hence is @@ -3402,7 +3348,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.tcx(), obligation.predicate.def_id(), obligation.predicate.skip_binder().self_ty(), // (1) - closure_type, + closure_sig, util::TupleArgumentsFlag::No, ) .map_bound(|(trait_ref, _)| trait_ref) @@ -3411,10 +3357,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn generator_trait_ref_unnormalized( &mut self, obligation: &TraitObligation<'tcx>, - closure_def_id: DefId, substs: SubstsRef<'tcx>, ) -> ty::PolyTraitRef<'tcx> { - let gen_sig = substs.as_generator().poly_sig(closure_def_id, self.tcx()); + let gen_sig = substs.as_generator().poly_sig(); // (1) Feels icky to skip the binder here, but OTOH we know // that the self-type is an generator type and hence is @@ -3506,9 +3451,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } -impl<'tcx> TraitObligation<'tcx> { +trait TraitObligationExt<'tcx> { + fn derived_cause( + &self, + variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>, + ) -> ObligationCause<'tcx>; +} + +impl<'tcx> TraitObligationExt<'tcx> for TraitObligation<'tcx> { #[allow(unused_comparisons)] - pub fn derived_cause( + fn derived_cause( &self, variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>, ) -> ObligationCause<'tcx> { diff --git a/src/librustc_infer/traits/specialize/mod.rs b/src/librustc_trait_selection/traits/specialize/mod.rs similarity index 68% rename from src/librustc_infer/traits/specialize/mod.rs rename to src/librustc_trait_selection/traits/specialize/mod.rs index 51da759da99f8..732716ef86577 100644 --- a/src/librustc_infer/traits/specialize/mod.rs +++ b/src/librustc_trait_selection/traits/specialize/mod.rs @@ -130,24 +130,27 @@ pub fn find_associated_item<'tcx>( let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap(); let trait_def = tcx.trait_def(trait_def_id); - let ancestors = trait_def.ancestors(tcx, impl_data.impl_def_id); - match ancestors.leaf_def(tcx, item.ident, item.kind) { - Some(node_item) => { - let substs = tcx.infer_ctxt().enter(|infcx| { - let param_env = param_env.with_reveal_all(); - let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs); - let substs = translate_substs( - &infcx, - param_env, - impl_data.impl_def_id, - substs, - node_item.node, - ); - infcx.tcx.erase_regions(&substs) - }); - (node_item.item.def_id, substs) + if let Ok(ancestors) = trait_def.ancestors(tcx, impl_data.impl_def_id) { + match ancestors.leaf_def(tcx, item.ident, item.kind) { + Some(node_item) => { + let substs = tcx.infer_ctxt().enter(|infcx| { + let param_env = param_env.with_reveal_all(); + let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs); + let substs = translate_substs( + &infcx, + param_env, + impl_data.impl_def_id, + substs, + node_item.node, + ); + infcx.tcx.erase_regions(&substs) + }); + (node_item.item.def_id, substs) + } + None => bug!("{:?} not found in {:?}", item, impl_data.impl_def_id), } - None => bug!("{:?} not found in {:?}", item, impl_data.impl_def_id), + } else { + (item.def_id, substs) } } @@ -161,7 +164,9 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, // The feature gate should prevent introducing new specializations, but not // taking advantage of upstream ones. - if !tcx.features().specialization && (impl1_def_id.is_local() || impl2_def_id.is_local()) { + let features = tcx.features(); + let specialization_enabled = features.specialization || features.min_specialization; + if !specialization_enabled && (impl1_def_id.is_local() || impl2_def_id.is_local()) { return false; } @@ -319,85 +324,7 @@ pub(super) fn specialization_graph_provider( }; if let Some(overlap) = overlap { - let impl_span = - tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap()); - - // Work to be done after we've built the DiagnosticBuilder. We have to define it - // now because the struct_lint methods don't return back the DiagnosticBuilder - // that's passed in. - let decorate = |err: LintDiagnosticBuilder<'_>| { - let msg = format!( - "conflicting implementations of trait `{}`{}:{}", - overlap.trait_desc, - overlap - .self_desc - .clone() - .map_or(String::new(), |ty| { format!(" for type `{}`", ty) }), - match used_to_be_allowed { - Some(FutureCompatOverlapErrorKind::Issue33140) => " (E0119)", - _ => "", - } - ); - let mut err = err.build(&msg); - match tcx.span_of_impl(overlap.with_impl) { - Ok(span) => { - err.span_label( - tcx.sess.source_map().def_span(span), - "first implementation here".to_string(), - ); - - err.span_label( - impl_span, - format!( - "conflicting implementation{}", - overlap - .self_desc - .map_or(String::new(), |ty| format!(" for `{}`", ty)) - ), - ); - } - Err(cname) => { - let msg = match to_pretty_impl_header(tcx, overlap.with_impl) { - Some(s) => format!( - "conflicting implementation in crate `{}`:\n- {}", - cname, s - ), - None => format!("conflicting implementation in crate `{}`", cname), - }; - err.note(&msg); - } - } - - for cause in &overlap.intercrate_ambiguity_causes { - cause.add_intercrate_ambiguity_hint(&mut err); - } - - if overlap.involves_placeholder { - coherence::add_placeholder_note(&mut err); - } - err.emit() - }; - - match used_to_be_allowed { - None => { - let err = struct_span_err!(tcx.sess, impl_span, E0119, ""); - decorate(LintDiagnosticBuilder::new(err)); - } - Some(kind) => { - let lint = match kind { - FutureCompatOverlapErrorKind::Issue33140 => { - ORDER_DEPENDENT_TRAIT_OBJECTS - } - FutureCompatOverlapErrorKind::LeakCheck => COHERENCE_LEAK_CHECK, - }; - tcx.struct_span_lint_hir( - lint, - tcx.hir().as_local_hir_id(impl_def_id).unwrap(), - impl_span, - decorate, - ) - } - }; + report_overlap_conflict(tcx, overlap, impl_def_id, used_to_be_allowed, &mut sg); } } else { let parent = tcx.impl_parent(impl_def_id).unwrap_or(trait_id); @@ -408,17 +335,176 @@ pub(super) fn specialization_graph_provider( tcx.arena.alloc(sg) } +fn report_overlap_conflict( + tcx: TyCtxt<'_>, + overlap: OverlapError, + impl_def_id: DefId, + used_to_be_allowed: Option, + sg: &mut specialization_graph::Graph, +) { + let impl_polarity = tcx.impl_polarity(impl_def_id); + let other_polarity = tcx.impl_polarity(overlap.with_impl); + match (impl_polarity, other_polarity) { + (ty::ImplPolarity::Negative, ty::ImplPolarity::Positive) => { + report_negative_positive_conflict( + tcx, + &overlap, + impl_def_id, + impl_def_id, + overlap.with_impl, + sg, + ); + } + + (ty::ImplPolarity::Positive, ty::ImplPolarity::Negative) => { + report_negative_positive_conflict( + tcx, + &overlap, + impl_def_id, + overlap.with_impl, + impl_def_id, + sg, + ); + } + + _ => { + report_conflicting_impls(tcx, overlap, impl_def_id, used_to_be_allowed, sg); + } + } +} + +fn report_negative_positive_conflict( + tcx: TyCtxt<'_>, + overlap: &OverlapError, + local_impl_def_id: DefId, + negative_impl_def_id: DefId, + positive_impl_def_id: DefId, + sg: &mut specialization_graph::Graph, +) { + let impl_span = + tcx.sess.source_map().guess_head_span(tcx.span_of_impl(local_impl_def_id).unwrap()); + + let mut err = struct_span_err!( + tcx.sess, + impl_span, + E0748, + "found both positive and negative implementation of trait `{}`{}:", + overlap.trait_desc, + overlap.self_desc.clone().map_or(String::new(), |ty| format!(" for type `{}`", ty)) + ); + + match tcx.span_of_impl(negative_impl_def_id) { + Ok(span) => { + err.span_label( + tcx.sess.source_map().guess_head_span(span), + "negative implementation here".to_string(), + ); + } + Err(cname) => { + err.note(&format!("negative implementation in crate `{}`", cname)); + } + } + + match tcx.span_of_impl(positive_impl_def_id) { + Ok(span) => { + err.span_label( + tcx.sess.source_map().guess_head_span(span), + "positive implementation here".to_string(), + ); + } + Err(cname) => { + err.note(&format!("positive implementation in crate `{}`", cname)); + } + } + + sg.has_errored = true; + err.emit(); +} + +fn report_conflicting_impls( + tcx: TyCtxt<'_>, + overlap: OverlapError, + impl_def_id: DefId, + used_to_be_allowed: Option, + sg: &mut specialization_graph::Graph, +) { + let impl_span = tcx.sess.source_map().guess_head_span(tcx.span_of_impl(impl_def_id).unwrap()); + + // Work to be done after we've built the DiagnosticBuilder. We have to define it + // now because the struct_lint methods don't return back the DiagnosticBuilder + // that's passed in. + let decorate = |err: LintDiagnosticBuilder<'_>| { + let msg = format!( + "conflicting implementations of trait `{}`{}:{}", + overlap.trait_desc, + overlap.self_desc.clone().map_or(String::new(), |ty| { format!(" for type `{}`", ty) }), + match used_to_be_allowed { + Some(FutureCompatOverlapErrorKind::Issue33140) => " (E0119)", + _ => "", + } + ); + let mut err = err.build(&msg); + match tcx.span_of_impl(overlap.with_impl) { + Ok(span) => { + err.span_label( + tcx.sess.source_map().guess_head_span(span), + "first implementation here".to_string(), + ); + + err.span_label( + impl_span, + format!( + "conflicting implementation{}", + overlap.self_desc.map_or(String::new(), |ty| format!(" for `{}`", ty)) + ), + ); + } + Err(cname) => { + let msg = match to_pretty_impl_header(tcx, overlap.with_impl) { + Some(s) => format!("conflicting implementation in crate `{}`:\n- {}", cname, s), + None => format!("conflicting implementation in crate `{}`", cname), + }; + err.note(&msg); + } + } + + for cause in &overlap.intercrate_ambiguity_causes { + cause.add_intercrate_ambiguity_hint(&mut err); + } + + if overlap.involves_placeholder { + coherence::add_placeholder_note(&mut err); + } + err.emit() + }; + + match used_to_be_allowed { + None => { + sg.has_errored = true; + let err = struct_span_err!(tcx.sess, impl_span, E0119, ""); + decorate(LintDiagnosticBuilder::new(err)); + } + Some(kind) => { + let lint = match kind { + FutureCompatOverlapErrorKind::Issue33140 => ORDER_DEPENDENT_TRAIT_OBJECTS, + FutureCompatOverlapErrorKind::LeakCheck => COHERENCE_LEAK_CHECK, + }; + tcx.struct_span_lint_hir( + lint, + tcx.hir().as_local_hir_id(impl_def_id).unwrap(), + impl_span, + decorate, + ) + } + }; +} + /// Recovers the "impl X for Y" signature from `impl_def_id` and returns it as a /// string. fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option { use std::fmt::Write; - let trait_ref = if let Some(tr) = tcx.impl_trait_ref(impl_def_id) { - tr - } else { - return None; - }; - + let trait_ref = tcx.impl_trait_ref(impl_def_id)?; let mut w = "impl".to_owned(); let substs = InternalSubsts::identity_for_item(tcx, impl_def_id); diff --git a/src/librustc_infer/traits/specialize/specialization_graph.rs b/src/librustc_trait_selection/traits/specialize/specialization_graph.rs similarity index 100% rename from src/librustc_infer/traits/specialize/specialization_graph.rs rename to src/librustc_trait_selection/traits/specialize/specialization_graph.rs diff --git a/src/librustc_infer/traits/structural_match.rs b/src/librustc_trait_selection/traits/structural_match.rs similarity index 100% rename from src/librustc_infer/traits/structural_match.rs rename to src/librustc_trait_selection/traits/structural_match.rs diff --git a/src/librustc_trait_selection/traits/util.rs b/src/librustc_trait_selection/traits/util.rs new file mode 100644 index 0000000000000..cd4595e76ccec --- /dev/null +++ b/src/librustc_trait_selection/traits/util.rs @@ -0,0 +1,675 @@ +use rustc_errors::DiagnosticBuilder; +use rustc_span::Span; +use smallvec::smallvec; +use smallvec::SmallVec; + +use rustc::ty::outlives::Component; +use rustc::ty::subst::{GenericArg, Subst, SubstsRef}; +use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness}; +use rustc_data_structures::fx::FxHashSet; +use rustc_hir as hir; +use rustc_hir::def_id::DefId; + +use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext}; + +fn anonymize_predicate<'tcx>(tcx: TyCtxt<'tcx>, pred: &ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { + match *pred { + ty::Predicate::Trait(ref data, constness) => { + ty::Predicate::Trait(tcx.anonymize_late_bound_regions(data), constness) + } + + ty::Predicate::RegionOutlives(ref data) => { + ty::Predicate::RegionOutlives(tcx.anonymize_late_bound_regions(data)) + } + + ty::Predicate::TypeOutlives(ref data) => { + ty::Predicate::TypeOutlives(tcx.anonymize_late_bound_regions(data)) + } + + ty::Predicate::Projection(ref data) => { + ty::Predicate::Projection(tcx.anonymize_late_bound_regions(data)) + } + + ty::Predicate::WellFormed(data) => ty::Predicate::WellFormed(data), + + ty::Predicate::ObjectSafe(data) => ty::Predicate::ObjectSafe(data), + + ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => { + ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) + } + + ty::Predicate::Subtype(ref data) => { + ty::Predicate::Subtype(tcx.anonymize_late_bound_regions(data)) + } + + ty::Predicate::ConstEvaluatable(def_id, substs) => { + ty::Predicate::ConstEvaluatable(def_id, substs) + } + } +} + +struct PredicateSet<'tcx> { + tcx: TyCtxt<'tcx>, + set: FxHashSet>, +} + +impl PredicateSet<'tcx> { + fn new(tcx: TyCtxt<'tcx>) -> Self { + Self { tcx, set: Default::default() } + } + + fn insert(&mut self, pred: &ty::Predicate<'tcx>) -> bool { + // We have to be careful here because we want + // + // for<'a> Foo<&'a int> + // + // and + // + // for<'b> Foo<&'b int> + // + // to be considered equivalent. So normalize all late-bound + // regions before we throw things into the underlying set. + self.set.insert(anonymize_predicate(self.tcx, pred)) + } +} + +impl>> Extend for PredicateSet<'tcx> { + fn extend>(&mut self, iter: I) { + for pred in iter { + self.insert(pred.as_ref()); + } + } +} + +/////////////////////////////////////////////////////////////////////////// +// `Elaboration` iterator +/////////////////////////////////////////////////////////////////////////// + +/// "Elaboration" is the process of identifying all the predicates that +/// are implied by a source predicate. Currently, this basically means +/// walking the "supertraits" and other similar assumptions. For example, +/// if we know that `T: Ord`, the elaborator would deduce that `T: PartialOrd` +/// holds as well. Similarly, if we have `trait Foo: 'static`, and we know that +/// `T: Foo`, then we know that `T: 'static`. +pub struct Elaborator<'tcx> { + stack: Vec>, + visited: PredicateSet<'tcx>, +} + +pub fn elaborate_trait_ref<'tcx>( + tcx: TyCtxt<'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>, +) -> Elaborator<'tcx> { + elaborate_predicates(tcx, vec![trait_ref.without_const().to_predicate()]) +} + +pub fn elaborate_trait_refs<'tcx>( + tcx: TyCtxt<'tcx>, + trait_refs: impl Iterator>, +) -> Elaborator<'tcx> { + let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate()).collect(); + elaborate_predicates(tcx, predicates) +} + +pub fn elaborate_predicates<'tcx>( + tcx: TyCtxt<'tcx>, + mut predicates: Vec>, +) -> Elaborator<'tcx> { + let mut visited = PredicateSet::new(tcx); + predicates.retain(|pred| visited.insert(pred)); + Elaborator { stack: predicates, visited } +} + +impl Elaborator<'tcx> { + pub fn filter_to_traits(self) -> FilterToTraits { + FilterToTraits::new(self) + } + + fn elaborate(&mut self, predicate: &ty::Predicate<'tcx>) { + let tcx = self.visited.tcx; + match *predicate { + ty::Predicate::Trait(ref data, _) => { + // Get predicates declared on the trait. + let predicates = tcx.super_predicates_of(data.def_id()); + + let predicates = predicates + .predicates + .iter() + .map(|(pred, _)| pred.subst_supertrait(tcx, &data.to_poly_trait_ref())); + debug!("super_predicates: data={:?} predicates={:?}", data, predicates.clone()); + + // Only keep those bounds that we haven't already seen. + // This is necessary to prevent infinite recursion in some + // cases. One common case is when people define + // `trait Sized: Sized { }` rather than `trait Sized { }`. + let visited = &mut self.visited; + let predicates = predicates.filter(|pred| visited.insert(pred)); + + self.stack.extend(predicates); + } + ty::Predicate::WellFormed(..) => { + // Currently, we do not elaborate WF predicates, + // although we easily could. + } + ty::Predicate::ObjectSafe(..) => { + // Currently, we do not elaborate object-safe + // predicates. + } + ty::Predicate::Subtype(..) => { + // Currently, we do not "elaborate" predicates like `X <: Y`, + // though conceivably we might. + } + ty::Predicate::Projection(..) => { + // Nothing to elaborate in a projection predicate. + } + ty::Predicate::ClosureKind(..) => { + // Nothing to elaborate when waiting for a closure's kind to be inferred. + } + ty::Predicate::ConstEvaluatable(..) => { + // Currently, we do not elaborate const-evaluatable + // predicates. + } + ty::Predicate::RegionOutlives(..) => { + // Nothing to elaborate from `'a: 'b`. + } + ty::Predicate::TypeOutlives(ref data) => { + // We know that `T: 'a` for some type `T`. We can + // often elaborate this. For example, if we know that + // `[U]: 'a`, that implies that `U: 'a`. Similarly, if + // we know `&'a U: 'b`, then we know that `'a: 'b` and + // `U: 'b`. + // + // We can basically ignore bound regions here. So for + // example `for<'c> Foo<'a,'c>: 'b` can be elaborated to + // `'a: 'b`. + + // Ignore `for<'a> T: 'a` -- we might in the future + // consider this as evidence that `T: 'static`, but + // I'm a bit wary of such constructions and so for now + // I want to be conservative. --nmatsakis + let ty_max = data.skip_binder().0; + let r_min = data.skip_binder().1; + if r_min.is_late_bound() { + return; + } + + let visited = &mut self.visited; + let mut components = smallvec![]; + tcx.push_outlives_components(ty_max, &mut components); + self.stack.extend( + components + .into_iter() + .filter_map(|component| match component { + Component::Region(r) => { + if r.is_late_bound() { + None + } else { + Some(ty::Predicate::RegionOutlives(ty::Binder::dummy( + ty::OutlivesPredicate(r, r_min), + ))) + } + } + + Component::Param(p) => { + let ty = tcx.mk_ty_param(p.index, p.name); + Some(ty::Predicate::TypeOutlives(ty::Binder::dummy( + ty::OutlivesPredicate(ty, r_min), + ))) + } + + Component::UnresolvedInferenceVariable(_) => None, + + Component::Projection(_) | Component::EscapingProjection(_) => { + // We can probably do more here. This + // corresponds to a case like `>::U: 'b`. + None + } + }) + .filter(|p| visited.insert(p)), + ); + } + } + } +} + +impl Iterator for Elaborator<'tcx> { + type Item = ty::Predicate<'tcx>; + + fn size_hint(&self) -> (usize, Option) { + (self.stack.len(), None) + } + + fn next(&mut self) -> Option> { + // Extract next item from top-most stack frame, if any. + if let Some(pred) = self.stack.pop() { + self.elaborate(&pred); + Some(pred) + } else { + None + } + } +} + +/////////////////////////////////////////////////////////////////////////// +// Supertrait iterator +/////////////////////////////////////////////////////////////////////////// + +pub type Supertraits<'tcx> = FilterToTraits>; + +pub fn supertraits<'tcx>( + tcx: TyCtxt<'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>, +) -> Supertraits<'tcx> { + elaborate_trait_ref(tcx, trait_ref).filter_to_traits() +} + +pub fn transitive_bounds<'tcx>( + tcx: TyCtxt<'tcx>, + bounds: impl Iterator>, +) -> Supertraits<'tcx> { + elaborate_trait_refs(tcx, bounds).filter_to_traits() +} + +/////////////////////////////////////////////////////////////////////////// +// `TraitAliasExpander` iterator +/////////////////////////////////////////////////////////////////////////// + +/// "Trait alias expansion" is the process of expanding a sequence of trait +/// references into another sequence by transitively following all trait +/// aliases. e.g. If you have bounds like `Foo + Send`, a trait alias +/// `trait Foo = Bar + Sync;`, and another trait alias +/// `trait Bar = Read + Write`, then the bounds would expand to +/// `Read + Write + Sync + Send`. +/// Expansion is done via a DFS (depth-first search), and the `visited` field +/// is used to avoid cycles. +pub struct TraitAliasExpander<'tcx> { + tcx: TyCtxt<'tcx>, + stack: Vec>, +} + +/// Stores information about the expansion of a trait via a path of zero or more trait aliases. +#[derive(Debug, Clone)] +pub struct TraitAliasExpansionInfo<'tcx> { + pub path: SmallVec<[(ty::PolyTraitRef<'tcx>, Span); 4]>, +} + +impl<'tcx> TraitAliasExpansionInfo<'tcx> { + fn new(trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self { + Self { path: smallvec![(trait_ref, span)] } + } + + /// Adds diagnostic labels to `diag` for the expansion path of a trait through all intermediate + /// trait aliases. + pub fn label_with_exp_info( + &self, + diag: &mut DiagnosticBuilder<'_>, + top_label: &str, + use_desc: &str, + ) { + diag.span_label(self.top().1, top_label); + if self.path.len() > 1 { + for (_, sp) in self.path.iter().rev().skip(1).take(self.path.len() - 2) { + diag.span_label(*sp, format!("referenced here ({})", use_desc)); + } + } + diag.span_label( + self.bottom().1, + format!("trait alias used in trait object type ({})", use_desc), + ); + } + + pub fn trait_ref(&self) -> &ty::PolyTraitRef<'tcx> { + &self.top().0 + } + + pub fn top(&self) -> &(ty::PolyTraitRef<'tcx>, Span) { + self.path.last().unwrap() + } + + pub fn bottom(&self) -> &(ty::PolyTraitRef<'tcx>, Span) { + self.path.first().unwrap() + } + + fn clone_and_push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self { + let mut path = self.path.clone(); + path.push((trait_ref, span)); + + Self { path } + } +} + +pub fn expand_trait_aliases<'tcx>( + tcx: TyCtxt<'tcx>, + trait_refs: impl IntoIterator, Span)>, +) -> TraitAliasExpander<'tcx> { + let items: Vec<_> = trait_refs + .into_iter() + .map(|(trait_ref, span)| TraitAliasExpansionInfo::new(trait_ref, span)) + .collect(); + TraitAliasExpander { tcx, stack: items } +} + +impl<'tcx> TraitAliasExpander<'tcx> { + /// If `item` is a trait alias and its predicate has not yet been visited, then expands `item` + /// to the definition, pushes the resulting expansion onto `self.stack`, and returns `false`. + /// Otherwise, immediately returns `true` if `item` is a regular trait, or `false` if it is a + /// trait alias. + /// The return value indicates whether `item` should be yielded to the user. + fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool { + let tcx = self.tcx; + let trait_ref = item.trait_ref(); + let pred = trait_ref.without_const().to_predicate(); + + debug!("expand_trait_aliases: trait_ref={:?}", trait_ref); + + // Don't recurse if this bound is not a trait alias. + let is_alias = tcx.is_trait_alias(trait_ref.def_id()); + if !is_alias { + return true; + } + + // 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.without_const().to_predicate()) == anon_pred + }) { + return false; + } + + // Get components of trait alias. + let predicates = tcx.super_predicates_of(trait_ref.def_id()); + + let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| { + pred.subst_supertrait(tcx, &trait_ref) + .to_opt_poly_trait_ref() + .map(|trait_ref| item.clone_and_push(trait_ref, *span)) + }); + debug!("expand_trait_aliases: items={:?}", items.clone()); + + self.stack.extend(items); + + false + } +} + +impl<'tcx> Iterator for TraitAliasExpander<'tcx> { + type Item = TraitAliasExpansionInfo<'tcx>; + + fn size_hint(&self) -> (usize, Option) { + (self.stack.len(), None) + } + + fn next(&mut self) -> Option> { + while let Some(item) = self.stack.pop() { + if self.expand(&item) { + return Some(item); + } + } + None + } +} + +/////////////////////////////////////////////////////////////////////////// +// Iterator over def-IDs of supertraits +/////////////////////////////////////////////////////////////////////////// + +pub struct SupertraitDefIds<'tcx> { + tcx: TyCtxt<'tcx>, + stack: Vec, + visited: FxHashSet, +} + +pub fn supertrait_def_ids(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SupertraitDefIds<'_> { + SupertraitDefIds { + tcx, + stack: vec![trait_def_id], + visited: Some(trait_def_id).into_iter().collect(), + } +} + +impl Iterator for SupertraitDefIds<'tcx> { + type Item = DefId; + + fn next(&mut self) -> Option { + let def_id = self.stack.pop()?; + let predicates = self.tcx.super_predicates_of(def_id); + let visited = &mut self.visited; + self.stack.extend( + predicates + .predicates + .iter() + .filter_map(|(pred, _)| pred.to_opt_poly_trait_ref()) + .map(|trait_ref| trait_ref.def_id()) + .filter(|&super_def_id| visited.insert(super_def_id)), + ); + Some(def_id) + } +} + +/////////////////////////////////////////////////////////////////////////// +// Other +/////////////////////////////////////////////////////////////////////////// + +/// A filter around an iterator of predicates that makes it yield up +/// just trait references. +pub struct FilterToTraits { + base_iterator: I, +} + +impl FilterToTraits { + fn new(base: I) -> FilterToTraits { + FilterToTraits { base_iterator: base } + } +} + +impl<'tcx, I: Iterator>> Iterator for FilterToTraits { + type Item = ty::PolyTraitRef<'tcx>; + + fn next(&mut self) -> Option> { + while let Some(pred) = self.base_iterator.next() { + if let ty::Predicate::Trait(data, _) = pred { + return Some(data.to_poly_trait_ref()); + } + } + None + } + + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.base_iterator.size_hint(); + (0, upper) + } +} + +/////////////////////////////////////////////////////////////////////////// +// Other +/////////////////////////////////////////////////////////////////////////// + +/// Instantiate all bound parameters of the impl with the given substs, +/// returning the resulting trait ref and all obligations that arise. +/// The obligations are closed under normalization. +pub fn impl_trait_ref_and_oblig<'a, 'tcx>( + selcx: &mut SelectionContext<'a, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + impl_def_id: DefId, + impl_substs: SubstsRef<'tcx>, +) -> (ty::TraitRef<'tcx>, Vec>) { + let impl_trait_ref = selcx.tcx().impl_trait_ref(impl_def_id).unwrap(); + let impl_trait_ref = impl_trait_ref.subst(selcx.tcx(), impl_substs); + let Normalized { value: impl_trait_ref, obligations: normalization_obligations1 } = + super::normalize(selcx, param_env, ObligationCause::dummy(), &impl_trait_ref); + + let predicates = selcx.tcx().predicates_of(impl_def_id); + let predicates = predicates.instantiate(selcx.tcx(), impl_substs); + let Normalized { value: predicates, obligations: normalization_obligations2 } = + super::normalize(selcx, param_env, ObligationCause::dummy(), &predicates); + let impl_obligations = + predicates_for_generics(ObligationCause::dummy(), 0, param_env, &predicates); + + let impl_obligations: Vec<_> = impl_obligations + .into_iter() + .chain(normalization_obligations1) + .chain(normalization_obligations2) + .collect(); + + (impl_trait_ref, impl_obligations) +} + +/// See [`super::obligations_for_generics`]. +pub fn predicates_for_generics<'tcx>( + cause: ObligationCause<'tcx>, + recursion_depth: usize, + param_env: ty::ParamEnv<'tcx>, + generic_bounds: &ty::InstantiatedPredicates<'tcx>, +) -> Vec> { + debug!("predicates_for_generics(generic_bounds={:?})", generic_bounds); + + generic_bounds + .predicates + .iter() + .map(|&predicate| Obligation { + cause: cause.clone(), + recursion_depth, + param_env, + predicate, + }) + .collect() +} + +pub fn predicate_for_trait_ref<'tcx>( + cause: ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + trait_ref: ty::TraitRef<'tcx>, + recursion_depth: usize, +) -> PredicateObligation<'tcx> { + Obligation { + cause, + param_env, + recursion_depth, + predicate: trait_ref.without_const().to_predicate(), + } +} + +pub fn predicate_for_trait_def( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + cause: ObligationCause<'tcx>, + trait_def_id: DefId, + recursion_depth: usize, + self_ty: Ty<'tcx>, + params: &[GenericArg<'tcx>], +) -> PredicateObligation<'tcx> { + let trait_ref = + ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(self_ty, params) }; + predicate_for_trait_ref(cause, param_env, trait_ref, recursion_depth) +} + +/// Casts a trait reference into a reference to one of its super +/// traits; returns `None` if `target_trait_def_id` is not a +/// supertrait. +pub fn upcast_choices( + tcx: TyCtxt<'tcx>, + source_trait_ref: ty::PolyTraitRef<'tcx>, + target_trait_def_id: DefId, +) -> Vec> { + if source_trait_ref.def_id() == target_trait_def_id { + return vec![source_trait_ref]; // Shortcut the most common case. + } + + supertraits(tcx, source_trait_ref).filter(|r| r.def_id() == target_trait_def_id).collect() +} + +/// Given a trait `trait_ref`, returns the number of vtable entries +/// that come from `trait_ref`, excluding its supertraits. Used in +/// computing the vtable base for an upcast trait of a trait object. +pub fn count_own_vtable_entries(tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> usize { + let mut entries = 0; + // Count number of methods and add them to the total offset. + // Skip over associated types and constants. + for trait_item in tcx.associated_items(trait_ref.def_id()).in_definition_order() { + if trait_item.kind == ty::AssocKind::Method { + entries += 1; + } + } + entries +} + +/// Given an upcast trait object described by `object`, returns the +/// index of the method `method_def_id` (which should be part of +/// `object.upcast_trait_ref`) within the vtable for `object`. +pub fn get_vtable_index_of_object_method( + tcx: TyCtxt<'tcx>, + object: &super::VtableObjectData<'tcx, N>, + method_def_id: DefId, +) -> usize { + // Count number of methods preceding the one we are selecting and + // add them to the total offset. + // Skip over associated types and constants. + let mut entries = object.vtable_base; + for trait_item in tcx.associated_items(object.upcast_trait_ref.def_id()).in_definition_order() { + if trait_item.def_id == method_def_id { + // The item with the ID we were given really ought to be a method. + assert_eq!(trait_item.kind, ty::AssocKind::Method); + return entries; + } + if trait_item.kind == ty::AssocKind::Method { + entries += 1; + } + } + + bug!("get_vtable_index_of_object_method: {:?} was not found", method_def_id); +} + +pub fn closure_trait_ref_and_return_type( + tcx: TyCtxt<'tcx>, + fn_trait_def_id: DefId, + self_ty: Ty<'tcx>, + sig: ty::PolyFnSig<'tcx>, + tuple_arguments: TupleArgumentsFlag, +) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>)> { + let arguments_tuple = match tuple_arguments { + TupleArgumentsFlag::No => sig.skip_binder().inputs()[0], + TupleArgumentsFlag::Yes => tcx.intern_tup(sig.skip_binder().inputs()), + }; + let trait_ref = ty::TraitRef { + def_id: fn_trait_def_id, + substs: tcx.mk_substs_trait(self_ty, &[arguments_tuple.into()]), + }; + ty::Binder::bind((trait_ref, sig.skip_binder().output())) +} + +pub fn generator_trait_ref_and_outputs( + tcx: TyCtxt<'tcx>, + fn_trait_def_id: DefId, + self_ty: Ty<'tcx>, + sig: ty::PolyGenSig<'tcx>, +) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> { + let trait_ref = ty::TraitRef { + def_id: fn_trait_def_id, + substs: tcx.mk_substs_trait(self_ty, &[sig.skip_binder().resume_ty.into()]), + }; + ty::Binder::bind((trait_ref, sig.skip_binder().yield_ty, sig.skip_binder().return_ty)) +} + +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 { + defaultness.is_default() + } else { + false + } + } + None => tcx.impl_defaultness(node_item_def_id).is_default(), + } +} + +pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool { + assoc_item.defaultness.is_final() && !impl_is_default(tcx, assoc_item.container.id()) +} + +pub enum TupleArgumentsFlag { + Yes, + No, +} diff --git a/src/librustc_infer/traits/wf.rs b/src/librustc_trait_selection/traits/wf.rs similarity index 99% rename from src/librustc_infer/traits/wf.rs rename to src/librustc_trait_selection/traits/wf.rs index 980a3f0478134..aa129d2b81c53 100644 --- a/src/librustc_infer/traits/wf.rs +++ b/src/librustc_trait_selection/traits/wf.rs @@ -1,5 +1,5 @@ -use crate::infer::opaque_types::required_region_bounds; use crate::infer::InferCtxt; +use crate::opaque_types::required_region_bounds; use crate::traits::{self, AssocTypeBoundData}; use rustc::middle::lang_items; use rustc::ty::subst::SubstsRef; @@ -186,7 +186,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { _ => (None, None), }; - let item_span = item.map(|i| tcx.sess.source_map().def_span(i.span)); + let item_span = item.map(|i| tcx.sess.source_map().guess_head_span(i.span)); match pred { ty::Predicate::Projection(proj) => { // The obligation comes not from the current `impl` nor the `trait` being @@ -474,7 +474,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // generators don't take arguments. } - ty::Closure(def_id, substs) => { + ty::Closure(_, substs) => { // Only check the upvar types for WF, not the rest // of the types within. This is needed because we // capture the signature and it may not be WF @@ -505,7 +505,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // anyway, except via auto trait matching (which // only inspects the upvar types). subtys.skip_current_subtree(); // subtree handled by compute_projection - for upvar_ty in substs.as_closure().upvar_tys(def_id, self.infcx.tcx) { + for upvar_ty in substs.as_closure().upvar_tys() { self.compute(upvar_ty); } } @@ -595,7 +595,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } // if we made it through that loop above, we made progress! - return true; + true } fn nominal_obligations( diff --git a/src/librustc_traits/Cargo.toml b/src/librustc_traits/Cargo.toml index 0dc3ad2983333..5e33efb1cf9b5 100644 --- a/src/librustc_traits/Cargo.toml +++ b/src/librustc_traits/Cargo.toml @@ -19,3 +19,4 @@ rustc_ast = { path = "../librustc_ast" } rustc_span = { path = "../librustc_span" } smallvec = { version = "1.0", features = ["union", "may_dangle"] } rustc_infer = { path = "../librustc_infer" } +rustc_trait_selection = { path = "../librustc_trait_selection" } diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index 2f854c045e50e..7068723f534e7 100644 --- a/src/librustc_traits/dropck_outlives.rs +++ b/src/librustc_traits/dropck_outlives.rs @@ -5,11 +5,17 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::DefId; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits::query::dropck_outlives::trivial_dropck_outlives; -use rustc_infer::traits::query::dropck_outlives::{DropckOutlivesResult, DtorckConstraint}; -use rustc_infer::traits::query::{CanonicalTyGoal, NoSolution}; -use rustc_infer::traits::{Normalized, ObligationCause, TraitEngine, TraitEngineExt}; +use rustc_infer::traits::TraitEngineExt as _; use rustc_span::source_map::{Span, DUMMY_SP}; +use rustc_trait_selection::traits::query::dropck_outlives::trivial_dropck_outlives; +use rustc_trait_selection::traits::query::dropck_outlives::{ + DropckOutlivesResult, DtorckConstraint, +}; +use rustc_trait_selection::traits::query::normalize::AtExt; +use rustc_trait_selection::traits::query::{CanonicalTyGoal, NoSolution}; +use rustc_trait_selection::traits::{ + Normalized, ObligationCause, TraitEngine, TraitEngineExt as _, +}; crate fn provide(p: &mut Providers<'_>) { *p = Providers { dropck_outlives, adt_dtorck_constraint, ..*p }; @@ -201,13 +207,13 @@ fn dtorck_constraint_for_ty<'tcx>( } } - ty::Closure(def_id, substs) => { - for ty in substs.as_closure().upvar_tys(def_id, tcx) { + ty::Closure(_, substs) => { + for ty in substs.as_closure().upvar_tys() { dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty, constraints)?; } } - ty::Generator(def_id, substs, _movability) => { + ty::Generator(_, substs, _movability) => { // rust-lang/rust#49918: types can be constructed, stored // in the interior, and sit idle when generator yields // (and is subsequently dropped). @@ -234,10 +240,10 @@ fn dtorck_constraint_for_ty<'tcx>( constraints.outlives.extend( substs .as_generator() - .upvar_tys(def_id, tcx) + .upvar_tys() .map(|t| -> ty::subst::GenericArg<'tcx> { t.into() }), ); - constraints.outlives.push(substs.as_generator().resume_ty(def_id, tcx).into()); + constraints.outlives.push(substs.as_generator().resume_ty().into()); } ty::Adt(def, substs) => { diff --git a/src/librustc_traits/evaluate_obligation.rs b/src/librustc_traits/evaluate_obligation.rs index 4cf5b66b3cbeb..87895d8e384da 100644 --- a/src/librustc_traits/evaluate_obligation.rs +++ b/src/librustc_traits/evaluate_obligation.rs @@ -1,11 +1,11 @@ use rustc::ty::query::Providers; use rustc::ty::{ParamEnvAnd, TyCtxt}; use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits::query::CanonicalPredicateGoal; -use rustc_infer::traits::{ +use rustc_span::source_map::DUMMY_SP; +use rustc_trait_selection::traits::query::CanonicalPredicateGoal; +use rustc_trait_selection::traits::{ EvaluationResult, Obligation, ObligationCause, OverflowError, SelectionContext, TraitQueryMode, }; -use rustc_span::source_map::DUMMY_SP; crate fn provide(p: &mut Providers<'_>) { *p = Providers { evaluate_obligation, ..*p }; diff --git a/src/librustc_traits/implied_outlives_bounds.rs b/src/librustc_traits/implied_outlives_bounds.rs index 1b6b8735651b5..4505a1e59d9ba 100644 --- a/src/librustc_traits/implied_outlives_bounds.rs +++ b/src/librustc_traits/implied_outlives_bounds.rs @@ -7,12 +7,14 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_hir as hir; use rustc_infer::infer::canonical::{self, Canonical}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; -use rustc_infer::traits::query::outlives_bounds::OutlivesBound; -use rustc_infer::traits::query::{CanonicalTyGoal, Fallible, NoSolution}; -use rustc_infer::traits::wf; -use rustc_infer::traits::FulfillmentContext; -use rustc_infer::traits::{TraitEngine, TraitEngineExt}; +use rustc_infer::traits::TraitEngineExt as _; use rustc_span::source_map::DUMMY_SP; +use rustc_trait_selection::infer::InferCtxtBuilderExt; +use rustc_trait_selection::traits::query::outlives_bounds::OutlivesBound; +use rustc_trait_selection::traits::query::{CanonicalTyGoal, Fallible, NoSolution}; +use rustc_trait_selection::traits::wf; +use rustc_trait_selection::traits::FulfillmentContext; +use rustc_trait_selection::traits::TraitEngine; use smallvec::{smallvec, SmallVec}; crate fn provide(p: &mut Providers<'_>) { diff --git a/src/librustc_traits/lowering/environment.rs b/src/librustc_traits/lowering/environment.rs index db392ede432e1..ed6259d457361 100644 --- a/src/librustc_traits/lowering/environment.rs +++ b/src/librustc_traits/lowering/environment.rs @@ -146,7 +146,7 @@ crate fn program_clauses_for_env<'tcx>( debug!("program_clauses_for_env: closure = {:#?}", closure); - return tcx.mk_clauses(closure.into_iter()); + tcx.mk_clauses(closure.into_iter()) } crate fn environment(tcx: TyCtxt<'_>, def_id: DefId) -> Environment<'_> { @@ -190,7 +190,7 @@ crate fn environment(tcx: TyCtxt<'_>, def_id: DefId) -> Environment<'_> { }, Node::ImplItem(item) => match item.kind { - ImplItemKind::Method(..) => NodeKind::Fn, + ImplItemKind::Fn(..) => NodeKind::Fn, _ => NodeKind::Other, }, diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs index 9b48cf489ba26..e3f9bd78073e9 100644 --- a/src/librustc_traits/lowering/mod.rs +++ b/src/librustc_traits/lowering/mod.rs @@ -1,6 +1,5 @@ mod environment; -use rustc::hir::map::definitions::DefPathData; use rustc::hir::map::Map; use rustc::traits::{ Clause, Clauses, DomainGoal, FromEnv, GoalKind, PolyDomainGoal, ProgramClause, @@ -13,6 +12,7 @@ use rustc_ast::ast; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; +use rustc_hir::definitions::DefPathData; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_span::symbol::sym; @@ -603,8 +603,8 @@ impl ClauseDumper<'tcx> { impl Visitor<'tcx> for ClauseDumper<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { diff --git a/src/librustc_traits/normalize_erasing_regions.rs b/src/librustc_traits/normalize_erasing_regions.rs index 4e5f20d80b0d8..065cf38eb2490 100644 --- a/src/librustc_traits/normalize_erasing_regions.rs +++ b/src/librustc_traits/normalize_erasing_regions.rs @@ -1,22 +1,24 @@ use rustc::traits::query::NoSolution; use rustc::ty::query::Providers; -use rustc::ty::{self, ParamEnvAnd, Ty, TyCtxt}; +use rustc::ty::subst::GenericArg; +use rustc::ty::{self, ParamEnvAnd, TyCtxt}; use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits::{Normalized, ObligationCause}; +use rustc_trait_selection::traits::query::normalize::AtExt; +use rustc_trait_selection::traits::{Normalized, ObligationCause}; use std::sync::atomic::Ordering; crate fn provide(p: &mut Providers<'_>) { - *p = Providers { normalize_ty_after_erasing_regions, ..*p }; + *p = Providers { normalize_generic_arg_after_erasing_regions, ..*p }; } -fn normalize_ty_after_erasing_regions<'tcx>( +fn normalize_generic_arg_after_erasing_regions<'tcx>( tcx: TyCtxt<'tcx>, - goal: ParamEnvAnd<'tcx, Ty<'tcx>>, -) -> Ty<'tcx> { - debug!("normalize_ty_after_erasing_regions(goal={:#?})", goal); + goal: ParamEnvAnd<'tcx, GenericArg<'tcx>>, +) -> GenericArg<'tcx> { + debug!("normalize_generic_arg_after_erasing_regions(goal={:#?})", goal); let ParamEnvAnd { param_env, value } = goal; - tcx.sess.perf_stats.normalize_ty_after_erasing_regions.fetch_add(1, Ordering::Relaxed); + tcx.sess.perf_stats.normalize_generic_arg_after_erasing_regions.fetch_add(1, Ordering::Relaxed); tcx.infer_ctxt().enter(|infcx| { let cause = ObligationCause::dummy(); match infcx.at(&cause, param_env).normalize(&value) { diff --git a/src/librustc_traits/normalize_projection_ty.rs b/src/librustc_traits/normalize_projection_ty.rs index b567895634763..57abff769de9b 100644 --- a/src/librustc_traits/normalize_projection_ty.rs +++ b/src/librustc_traits/normalize_projection_ty.rs @@ -3,11 +3,13 @@ use rustc::ty::{ParamEnvAnd, TyCtxt}; use rustc_hir as hir; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits::query::{ +use rustc_infer::traits::TraitEngineExt as _; +use rustc_span::DUMMY_SP; +use rustc_trait_selection::infer::InferCtxtBuilderExt; +use rustc_trait_selection::traits::query::{ normalize::NormalizationResult, CanonicalProjectionGoal, NoSolution, }; -use rustc_infer::traits::{self, ObligationCause, SelectionContext, TraitEngineExt}; -use rustc_span::DUMMY_SP; +use rustc_trait_selection::traits::{self, ObligationCause, SelectionContext}; use std::sync::atomic::Ordering; crate fn provide(p: &mut Providers<'_>) { diff --git a/src/librustc_traits/type_op.rs b/src/librustc_traits/type_op.rs index 4118133806141..7ed828c91679c 100644 --- a/src/librustc_traits/type_op.rs +++ b/src/librustc_traits/type_op.rs @@ -8,14 +8,18 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; -use rustc_infer::traits::query::type_op::ascribe_user_type::AscribeUserType; -use rustc_infer::traits::query::type_op::eq::Eq; -use rustc_infer::traits::query::type_op::normalize::Normalize; -use rustc_infer::traits::query::type_op::prove_predicate::ProvePredicate; -use rustc_infer::traits::query::type_op::subtype::Subtype; -use rustc_infer::traits::query::{Fallible, NoSolution}; -use rustc_infer::traits::{Normalized, Obligation, ObligationCause, TraitEngine, TraitEngineExt}; +use rustc_infer::traits::TraitEngineExt as _; use rustc_span::DUMMY_SP; +use rustc_trait_selection::infer::InferCtxtBuilderExt; +use rustc_trait_selection::infer::InferCtxtExt; +use rustc_trait_selection::traits::query::normalize::AtExt; +use rustc_trait_selection::traits::query::type_op::ascribe_user_type::AscribeUserType; +use rustc_trait_selection::traits::query::type_op::eq::Eq; +use rustc_trait_selection::traits::query::type_op::normalize::Normalize; +use rustc_trait_selection::traits::query::type_op::prove_predicate::ProvePredicate; +use rustc_trait_selection::traits::query::type_op::subtype::Subtype; +use rustc_trait_selection::traits::query::{Fallible, NoSolution}; +use rustc_trait_selection::traits::{Normalized, Obligation, ObligationCause, TraitEngine}; use std::fmt; crate fn provide(p: &mut Providers<'_>) { @@ -76,11 +80,11 @@ impl AscribeUserTypeCx<'me, 'tcx> { where T: ToTrace<'tcx>, { - Ok(self - .infcx + self.infcx .at(&ObligationCause::dummy(), self.param_env) .relate(a, variance, b)? - .into_value_registering_obligations(self.infcx, self.fulfill_cx)) + .into_value_registering_obligations(self.infcx, self.fulfill_cx); + Ok(()) } fn prove_predicate(&mut self, predicate: Predicate<'tcx>) { @@ -161,10 +165,11 @@ fn type_op_eq<'tcx>( ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> { tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| { let (param_env, Eq { a, b }) = key.into_parts(); - Ok(infcx + infcx .at(&ObligationCause::dummy(), param_env) .eq(a, b)? - .into_value_registering_obligations(infcx, fulfill_cx)) + .into_value_registering_obligations(infcx, fulfill_cx); + Ok(()) }) } @@ -217,10 +222,11 @@ fn type_op_subtype<'tcx>( ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> { tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| { let (param_env, Subtype { sub, sup }) = key.into_parts(); - Ok(infcx + infcx .at(&ObligationCause::dummy(), param_env) .sup(sup, sub)? - .into_value_registering_obligations(infcx, fulfill_cx)) + .into_value_registering_obligations(infcx, fulfill_cx); + Ok(()) }) } diff --git a/src/librustc_ty/Cargo.toml b/src/librustc_ty/Cargo.toml index 6e64df3492b0f..cf0b4b82eea72 100644 --- a/src/librustc_ty/Cargo.toml +++ b/src/librustc_ty/Cargo.toml @@ -15,4 +15,6 @@ rustc_data_structures = { path = "../librustc_data_structures" } rustc_hir = { path = "../librustc_hir" } rustc_infer = { path = "../librustc_infer" } rustc_span = { path = "../librustc_span" } +rustc_session = { path = "../librustc_session" } rustc_target = { path = "../librustc_target" } +rustc_trait_selection = { path = "../librustc_trait_selection" } diff --git a/src/librustc_ty/common_traits.rs b/src/librustc_ty/common_traits.rs index e0ce6ad23a650..311ba383f3055 100644 --- a/src/librustc_ty/common_traits.rs +++ b/src/librustc_ty/common_traits.rs @@ -3,8 +3,8 @@ use rustc::middle::lang_items; use rustc::ty::{self, Ty, TyCtxt}; use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits; use rustc_span::DUMMY_SP; +use rustc_trait_selection::traits; fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { is_item_raw(tcx, query, lang_items::CopyTraitLangItem) diff --git a/src/librustc_ty/instance.rs b/src/librustc_ty/instance.rs index 8b1ba57e81945..a5abe7b6413cc 100644 --- a/src/librustc_ty/instance.rs +++ b/src/librustc_ty/instance.rs @@ -1,8 +1,9 @@ use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Instance, TyCtxt, TypeFoldable}; use rustc_hir::def_id::DefId; -use rustc_infer::traits; +use rustc_span::sym; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::traits; use log::debug; @@ -31,21 +32,26 @@ pub fn resolve_instance<'tcx>( debug!(" => intrinsic"); ty::InstanceDef::Intrinsic(def_id) } - _ => { - if Some(def_id) == tcx.lang_items().drop_in_place_fn() { - let ty = substs.type_at(0); - if ty.needs_drop(tcx, param_env.with_reveal_all()) { - debug!(" => nontrivial drop glue"); - ty::InstanceDef::DropGlue(def_id, Some(ty)) - } else { - debug!(" => trivial drop glue"); - ty::InstanceDef::DropGlue(def_id, None) + ty::FnDef(def_id, substs) if Some(def_id) == tcx.lang_items().drop_in_place_fn() => { + let ty = substs.type_at(0); + + if ty.needs_drop(tcx, param_env) { + // `DropGlue` requires a monomorphic aka concrete type. + if ty.needs_subst() { + return None; } + + debug!(" => nontrivial drop glue"); + ty::InstanceDef::DropGlue(def_id, Some(ty)) } else { - debug!(" => free item"); - ty::InstanceDef::Item(def_id) + debug!(" => trivial drop glue"); + ty::InstanceDef::DropGlue(def_id, None) } } + _ => { + debug!(" => free item"); + ty::InstanceDef::Item(def_id) + } }; Some(Instance { def, substs }) }; @@ -113,20 +119,44 @@ fn resolve_associated_item<'tcx>( trait_closure_kind, )) } - traits::VtableFnPointer(ref data) => Some(Instance { - def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty), - substs: rcvr_substs, - }), + traits::VtableFnPointer(ref data) => { + // `FnPtrShim` requires a monomorphic aka concrete type. + if data.fn_ty.needs_subst() { + return None; + } + + Some(Instance { + def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty), + substs: rcvr_substs, + }) + } traits::VtableObject(ref data) => { let index = traits::get_vtable_index_of_object_method(tcx, data, def_id); Some(Instance { def: ty::InstanceDef::Virtual(def_id, index), substs: rcvr_substs }) } traits::VtableBuiltin(..) => { - if tcx.lang_items().clone_trait().is_some() { - Some(Instance { - def: ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty()), - substs: rcvr_substs, - }) + if Some(trait_ref.def_id) == tcx.lang_items().clone_trait() { + // FIXME(eddyb) use lang items for methods instead of names. + let name = tcx.item_name(def_id); + if name == sym::clone { + let self_ty = trait_ref.self_ty(); + + // `CloneShim` requires a monomorphic aka concrete type. + if self_ty.needs_subst() { + return None; + } + + Some(Instance { + def: ty::InstanceDef::CloneShim(def_id, self_ty), + substs: rcvr_substs, + }) + } else { + assert_eq!(name, sym::clone_from); + + // Use the default `fn clone_from` from `trait Clone`. + let substs = tcx.erase_regions(&rcvr_substs); + Some(ty::Instance::new(def_id, substs)) + } } else { None } diff --git a/src/librustc_ty/needs_drop.rs b/src/librustc_ty/needs_drop.rs index 0f71246c73759..37af8168f87d9 100644 --- a/src/librustc_ty/needs_drop.rs +++ b/src/librustc_ty/needs_drop.rs @@ -93,8 +93,8 @@ where match component.kind { _ if component.is_copy_modulo_regions(tcx, self.param_env, DUMMY_SP) => (), - ty::Closure(def_id, substs) => { - for upvar_ty in substs.as_closure().upvar_tys(def_id, tcx) { + ty::Closure(_, substs) => { + for upvar_ty in substs.as_closure().upvar_tys() { queue_type(self, upvar_ty); } } @@ -132,7 +132,7 @@ where } } - return None; + None } } diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs index 6bc29d0493e68..4b522997537b7 100644 --- a/src/librustc_ty/ty.rs +++ b/src/librustc_ty/ty.rs @@ -1,13 +1,13 @@ use rustc::hir::map as hir_map; -use rustc::session::CrateDisambiguator; use rustc::ty::subst::Subst; 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}; -use rustc_infer::traits; +use rustc_session::CrateDisambiguator; use rustc_span::symbol::Symbol; use rustc_span::Span; +use rustc_trait_selection::traits; fn sized_constraint_for_ty<'tcx>( tcx: TyCtxt<'tcx>, @@ -210,7 +210,7 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] { } } -fn associated_items<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::AssociatedItems { +fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::AssociatedItems { let items = tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did)); tcx.arena.alloc(ty::AssociatedItems::new(items)) } @@ -273,8 +273,7 @@ fn original_crate_name(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Symbol { } fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { - assert_eq!(crate_num, LOCAL_CRATE); - tcx.hir().crate_hash + tcx.index_hir(crate_num).crate_hash } fn instance_def_size_estimate<'tcx>( diff --git a/src/librustc_typeck/Cargo.toml b/src/librustc_typeck/Cargo.toml index 51a9b259c8f70..e61a36f844f87 100644 --- a/src/librustc_typeck/Cargo.toml +++ b/src/librustc_typeck/Cargo.toml @@ -19,8 +19,10 @@ rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } rustc_hir = { path = "../librustc_hir" } rustc_target = { path = "../librustc_target" } +rustc_session = { path = "../librustc_session" } smallvec = { version = "1.0", features = ["union", "may_dangle"] } rustc_ast = { path = "../librustc_ast" } rustc_span = { path = "../librustc_span" } rustc_index = { path = "../librustc_index" } rustc_infer = { path = "../librustc_infer" } +rustc_trait_selection = { path = "../librustc_trait_selection" } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 36461f2400cef..54c646b855777 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -6,13 +6,10 @@ // ignore-tidy-filelength use crate::collect::PlaceholderHirTyCollector; -use crate::lint; use crate::middle::lang_items::SizedTraitLangItem; use crate::middle::resolve_lifetime as rl; use crate::require_c_abi_if_c_variadic; use crate::util::common::ErrorReported; -use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; -use rustc::session::{parse::feature_err, Session}; use rustc::ty::subst::{self, InternalSubsts, Subst, SubstsRef}; use rustc::ty::{self, Const, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; use rustc::ty::{GenericParamDef, GenericParamDefKind}; @@ -23,24 +20,25 @@ use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::intravisit::Visitor; +use rustc_hir::intravisit::{walk_generics, Visitor}; use rustc_hir::print; -use rustc_hir::{Constness, ExprKind, GenericArg, GenericArgs}; -use rustc_infer::traits; -use rustc_infer::traits::astconv_object_safety_violations; -use rustc_infer::traits::error_reporting::report_object_safety_error; -use rustc_infer::traits::wf::object_region_bounds; +use rustc_hir::{Constness, GenericArg, GenericArgs}; +use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, LATE_BOUND_LIFETIME_ARGUMENTS}; +use rustc_session::parse::feature_err; +use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::{MultiSpan, Span, DUMMY_SP}; use rustc_target::spec::abi; -use smallvec::SmallVec; +use rustc_trait_selection::traits; +use rustc_trait_selection::traits::astconv_object_safety_violations; +use rustc_trait_selection::traits::error_reporting::report_object_safety_error; +use rustc_trait_selection::traits::wf::object_region_bounds; +use smallvec::SmallVec; use std::collections::BTreeSet; use std::iter; use std::slice; -use rustc::mir::interpret::LitToConstInput; - #[derive(Debug)] pub struct PathSeg(pub DefId, pub usize); @@ -340,7 +338,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut multispan = MultiSpan::from_span(span); multispan.push_span_label(span_late, note.to_string()); tcx.struct_span_lint_hir( - lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS, + LATE_BOUND_LIFETIME_ARGUMENTS, args.args[0].id(), multispan, |lint| lint.build(msg).emit(), @@ -782,7 +780,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } (GenericParamDefKind::Const, GenericArg::Const(ct)) => { - self.ast_const_to_const(&ct.value, tcx.type_of(param.def_id)).into() + let ct_def_id = tcx.hir().local_def_id(ct.value.hir_id).expect_local(); + ty::Const::from_anon_const(tcx, ct_def_id).into() } _ => unreachable!(), }, @@ -838,18 +837,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } }, ); - if !inferred_params.is_empty() { - // We always collect the spans for placeholder types when evaluating `fn`s, but we - // only want to emit an error complaining about them if infer types (`_`) are not - // allowed. `allow_ty_infer` gates this behavior. - crate::collect::placeholder_type_error( - tcx, - inferred_params[0], - &[], - inferred_params, - false, - ); - } self.complain_about_missing_type_params( missing_type_params, @@ -1441,17 +1428,24 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let (assoc_ident, def_scope) = tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id); - // We have already adjusted the item name above, so compare with `ident.modern()` instead + // We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead // of calling `filter_by_name_and_kind`. let assoc_ty = tcx .associated_items(candidate.def_id()) .filter_by_name_unhygienic(assoc_ident.name) - .find(|i| i.kind == ty::AssocKind::Type && i.ident.modern() == assoc_ident) + .find(|i| { + i.kind == ty::AssocKind::Type && i.ident.normalize_to_macros_2_0() == assoc_ident + }) .expect("missing associated type"); if !assoc_ty.vis.is_accessible_from(def_scope, tcx) { - let msg = format!("associated type `{}` is private", binding.item_name); - tcx.sess.span_err(binding.span, &msg); + tcx.sess + .struct_span_err( + binding.span, + &format!("associated type `{}` is private", binding.item_name), + ) + .span_label(binding.span, "private associated type") + .emit(); } tcx.check_stability(assoc_ty.def_id, Some(hir_ref_id), binding.span); @@ -1691,9 +1685,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }; // Erase the `dummy_self` (`trait_object_dummy_self`) used above. - let existential_trait_refs = regular_traits - .iter() - .map(|i| i.trait_ref().map_bound(|trait_ref| trait_ref_to_existential(trait_ref))); + let existential_trait_refs = + regular_traits.iter().map(|i| i.trait_ref().map_bound(trait_ref_to_existential)); let existential_projections = bounds.projection_bounds.iter().map(|(bound, _)| { bound.map_bound(|b| { let trait_ref = trait_ref_to_existential(b.projection_ty.trait_ref(tcx)); @@ -2126,7 +2119,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { return Err(ErrorReported); } } - return Ok(bound); + Ok(bound) } fn complain_about_assoc_type_not_found( @@ -2276,7 +2269,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } if let Some(sp) = tcx.hir().span_if_local(adt_def.did) { - let sp = tcx.sess.source_map().def_span(sp); + let sp = tcx.sess.source_map().guess_head_span(sp); err.span_label(sp, format!("variant `{}` not found here", assoc_ident)); } @@ -2298,12 +2291,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let (assoc_ident, def_scope) = tcx.adjust_ident_and_get_scope(assoc_ident, trait_did, hir_ref_id); - // We have already adjusted the item name above, so compare with `ident.modern()` instead + // We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead // of calling `filter_by_name_and_kind`. let item = tcx .associated_items(trait_did) .in_definition_order() - .find(|i| i.kind.namespace() == Namespace::TypeNS && i.ident.modern() == assoc_ident) + .find(|i| { + i.kind.namespace() == Namespace::TypeNS + && i.ident.normalize_to_macros_2_0() == assoc_ident + }) .expect("missing associated type"); let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, assoc_segment, bound); @@ -2311,8 +2307,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let kind = DefKind::AssocTy; if !item.vis.is_accessible_from(def_scope, tcx) { - let msg = format!("{} `{}` is private", kind.descr(item.def_id), assoc_ident); - tcx.sess.span_err(span, &msg); + let kind = kind.descr(item.def_id); + let msg = format!("{} `{}` is private", kind, assoc_ident); + tcx.sess + .struct_span_err(span, &msg) + .span_label(span, &format!("private {}", kind)) + .emit(); } tcx.check_stability(item.def_id, Some(hir_ref_id), span); @@ -2704,7 +2704,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } Res::Err => { self.set_tainted_by_errors(); - return self.tcx().types.err; + self.tcx().types.err } _ => span_bug!(span, "unexpected resolution: {:?}", path.res), } @@ -2734,7 +2734,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } hir::TyKind::BareFn(ref bf) => { require_c_abi_if_c_variadic(tcx, &bf.decl, bf.abi, ast_ty.span); - tcx.mk_fn_ptr(self.ty_of_fn(bf.unsafety, bf.abi, &bf.decl, &[], None)) + tcx.mk_fn_ptr(self.ty_of_fn( + bf.unsafety, + bf.abi, + &bf.decl, + &hir::Generics::empty(), + None, + )) } hir::TyKind::TraitObject(ref bounds, ref lifetime) => { self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime) @@ -2762,7 +2768,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .unwrap_or(tcx.types.err) } hir::TyKind::Array(ref ty, ref length) => { - let length = self.ast_const_to_const(length, tcx.types.usize); + let length_def_id = tcx.hir().local_def_id(length.hir_id).expect_local(); + let length = ty::Const::from_anon_const(tcx, length_def_id); let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(&ty), length)); self.normalize_ty(ast_ty.span, array_ty) } @@ -2794,75 +2801,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { result_ty } - /// Returns the `DefId` of the constant parameter that the provided expression is a path to. - pub fn const_param_def_id(&self, expr: &hir::Expr<'_>) -> Option { - // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments - // currently have to be wrapped in curly brackets, so it's necessary to special-case. - let expr = match &expr.kind { - ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => { - block.expr.as_ref().unwrap() - } - _ => expr, - }; - - match &expr.kind { - ExprKind::Path(hir::QPath::Resolved(_, path)) => match path.res { - Res::Def(DefKind::ConstParam, did) => Some(did), - _ => None, - }, - _ => None, - } - } - - pub fn ast_const_to_const( - &self, - ast_const: &hir::AnonConst, - ty: Ty<'tcx>, - ) -> &'tcx ty::Const<'tcx> { - debug!("ast_const_to_const(id={:?}, ast_const={:?})", ast_const.hir_id, ast_const); - - let tcx = self.tcx(); - let def_id = tcx.hir().local_def_id(ast_const.hir_id); - - let expr = &tcx.hir().body(ast_const.body).value; - - let lit_input = match expr.kind { - hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }), - hir::ExprKind::Unary(hir::UnOp::UnNeg, ref expr) => match expr.kind { - hir::ExprKind::Lit(ref lit) => { - Some(LitToConstInput { lit: &lit.node, ty, neg: true }) - } - _ => None, - }, - _ => None, - }; - - if let Some(lit_input) = lit_input { - // If an error occurred, ignore that it's a literal and leave reporting the error up to - // mir. - if let Ok(c) = tcx.at(expr.span).lit_to_const(lit_input) { - return c; - } else { - tcx.sess.delay_span_bug(expr.span, "ast_const_to_const: couldn't lit_to_const"); - } - } - - let kind = if let Some(def_id) = self.const_param_def_id(expr) { - // Find the name and index of the const parameter by indexing the generics of the - // parent item and construct a `ParamConst`. - let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); - let item_id = tcx.hir().get_parent_node(hir_id); - let item_def_id = tcx.hir().local_def_id(item_id); - let generics = tcx.generics_of(item_def_id); - let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(hir_id)]; - let name = tcx.hir().name(hir_id); - ty::ConstKind::Param(ty::ParamConst::new(index, name)) - } else { - ty::ConstKind::Unevaluated(def_id, InternalSubsts::identity_for_item(tcx, def_id), None) - }; - tcx.mk_const(ty::Const { val: kind, ty }) - } - pub fn impl_trait_ty_to_ty( &self, def_id: DefId, @@ -2917,7 +2855,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { unsafety: hir::Unsafety, abi: abi::Abi, decl: &hir::FnDecl<'_>, - generic_params: &[hir::GenericParam<'_>], + generics: &hir::Generics<'_>, ident_span: Option, ) -> ty::PolyFnSig<'tcx> { debug!("ty_of_fn"); @@ -2929,6 +2867,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { for ty in decl.inputs { visitor.visit_ty(ty); } + walk_generics(&mut visitor, generics); + let input_tys = decl.inputs.iter().map(|a| self.ty_of_arg(a, None)); let output_ty = match decl.output { hir::FnRetTy::Return(ref output) => { @@ -2943,16 +2883,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let bare_fn_ty = ty::Binder::bind(tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi)); - if !self.allow_ty_infer() { + if let (false, Some(ident_span)) = (self.allow_ty_infer(), ident_span) { // We always collect the spans for placeholder types when evaluating `fn`s, but we // only want to emit an error complaining about them if infer types (`_`) are not - // allowed. `allow_ty_infer` gates this behavior. + // allowed. `allow_ty_infer` gates this behavior. We check for the presence of + // `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`. crate::collect::placeholder_type_error( tcx, - ident_span.map(|sp| sp.shrink_to_hi()).unwrap_or(DUMMY_SP), - generic_params, + ident_span.shrink_to_hi(), + &generics.params[..], visitor.0, - ident_span.is_some(), + true, ); } @@ -2976,8 +2917,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx.sess, decl.output.span(), E0581, - "return type references {} \ - which is not constrained by the fn input types", + "return type references {} which is not constrained by the fn input types", lifetime_name ); if let ty::BrAnon(_) = *br { @@ -2988,8 +2928,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // though we can easily give a hint that ought to be // relevant. err.note( - "lifetimes appearing in an associated type \ - are not considered constrained", + "lifetimes appearing in an associated type are not considered constrained", ); } err.emit(); @@ -3042,7 +2981,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) .emit(); } - return Some(r); + Some(r) } } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 2c71fec6809f7..a34389b7d8968 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -4,9 +4,9 @@ use rustc::ty::Ty; use rustc_hir as hir; use rustc_hir::ExprKind; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::traits::ObligationCauseCode; -use rustc_infer::traits::{IfExpressionCause, MatchExpressionArmCause, ObligationCause}; use rustc_span::Span; +use rustc_trait_selection::traits::ObligationCauseCode; +use rustc_trait_selection::traits::{IfExpressionCause, MatchExpressionArmCause, ObligationCause}; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn check_match( @@ -332,7 +332,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // | |_____^ expected integer, found `()` // ``` if outer_sp.is_some() { - outer_sp = Some(self.tcx.sess.source_map().def_span(span)); + outer_sp = Some(self.tcx.sess.source_map().guess_head_span(span)); } else_expr.span } diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index 67bfb090253f0..2315b42aec54c 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -1,17 +1,17 @@ use super::method::MethodCallee; use super::{FnCtxt, Needs, PlaceOp}; -use rustc::session::DiagnosticMessageId; use rustc::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; use rustc::ty::{self, TraitRef, Ty, TyCtxt, WithConstness}; use rustc::ty::{ToPredicate, TypeFoldable}; +use rustc_ast::ast::Ident; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_infer::infer::{InferCtxt, InferOk}; -use rustc_infer::traits::{self, TraitEngine}; - -use rustc_ast::ast::Ident; +use rustc_session::DiagnosticMessageId; use rustc_span::Span; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; +use rustc_trait_selection::traits::{self, TraitEngine}; use std::iter; diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 3f8019e64b2db..ec796043d3ac8 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -104,13 +104,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Check whether this is a call to a closure where we // haven't yet decided on whether the closure is fn vs // fnmut vs fnonce. If so, we have to defer further processing. - if self.closure_kind(def_id, substs).is_none() { - let closure_ty = self.closure_sig(def_id, substs); - let fn_sig = self + if self.closure_kind(substs).is_none() { + let closure_sig = substs.as_closure().sig(); + let closure_sig = self .replace_bound_vars_with_fresh_vars( call_expr.span, infer::FnCall, - &closure_ty, + &closure_sig, ) .0; let adjustments = autoderef.adjust_steps(self, Needs::None); @@ -121,12 +121,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { callee_expr, adjusted_ty, adjustments, - fn_sig, - closure_def_id: def_id, + fn_sig: closure_sig, closure_substs: substs, }, ); - return Some(CallStep::DeferredClosure(fn_sig)); + return Some(CallStep::DeferredClosure(closure_sig)); } } @@ -459,7 +458,6 @@ pub struct DeferredCallResolution<'tcx> { adjusted_ty: Ty<'tcx>, adjustments: Vec>, fn_sig: ty::FnSig<'tcx>, - closure_def_id: DefId, closure_substs: SubstsRef<'tcx>, } @@ -469,7 +467,7 @@ impl<'a, 'tcx> DeferredCallResolution<'tcx> { // we should not be invoked until the closure kind has been // determined by upvar inference - assert!(fcx.closure_kind(self.closure_def_id, self.closure_substs).is_some()); + assert!(fcx.closure_kind(self.closure_substs).is_some()); // We may now know enough to figure out fn vs fnmut etc. match fcx.try_overloaded_call_traits(self.call_expr, self.adjusted_ty, None) { diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index ff100c261f14a..2875d38a996a0 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -31,11 +31,9 @@ use super::FnCtxt; use crate::hir::def_id::DefId; -use crate::lint; use crate::type_error_struct; use crate::util::common::ErrorReported; use rustc::middle::lang_items; -use rustc::session::Session; use rustc::ty::adjustment::AllowTwoPhase; use rustc::ty::cast::{CastKind, CastTy}; use rustc::ty::error::TypeError; @@ -44,9 +42,11 @@ use rustc::ty::{self, Ty, TypeAndMut, TypeFoldable}; use rustc_ast::ast; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; -use rustc_infer::traits; -use rustc_infer::traits::error_reporting::report_object_safety_error; +use rustc_session::lint; +use rustc_session::Session; use rustc_span::Span; +use rustc_trait_selection::traits; +use rustc_trait_selection::traits::error_reporting::report_object_safety_error; /// Reifies a cast check to be checked once we have full type information for /// a function context. diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 8689db1b1eb56..a277220b1a200 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -12,10 +12,11 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_infer::infer::{InferOk, InferResult}; -use rustc_infer::traits::error_reporting::ArgKind; -use rustc_infer::traits::Obligation; use rustc_span::source_map::Span; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::traits::error_reporting::ArgKind; +use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; +use rustc_trait_selection::traits::Obligation; use std::cmp; use std::iter; @@ -76,51 +77,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let generator_types = check_fn(self, self.param_env, liberated_sig, decl, expr.hir_id, body, gen).1; - // Create type variables (for now) to represent the transformed - // types of upvars. These will be unified during the upvar - // inference phase (`upvar.rs`). let base_substs = InternalSubsts::identity_for_item(self.tcx, self.tcx.closure_base_def_id(expr_def_id)); + // HACK(eddyb) this hardcodes indices into substs but it should rely on + // `ClosureSubsts` and `GeneratorSubsts` providing constructors, instead. + // That would also remove the need for most of the inference variables, + // as they immediately unified with the actual type below, including + // the `InferCtxt::closure_sig` and `ClosureSubsts::sig_ty` methods. + let tupled_upvars_idx = base_substs.len() + if generator_types.is_some() { 4 } else { 2 }; let substs = base_substs.extend_to(self.tcx, expr_def_id, |param, _| match param.kind { GenericParamDefKind::Lifetime => span_bug!(expr.span, "closure has lifetime param"), - GenericParamDefKind::Type { .. } => self - .infcx - .next_ty_var(TypeVariableOrigin { + GenericParamDefKind::Type { .. } => if param.index as usize == tupled_upvars_idx { + self.tcx.mk_tup(self.tcx.upvars(expr_def_id).iter().flat_map(|upvars| { + upvars.iter().map(|(&var_hir_id, _)| { + // Create type variables (for now) to represent the transformed + // types of upvars. These will be unified during the upvar + // inference phase (`upvar.rs`). + self.infcx.next_ty_var(TypeVariableOrigin { + // FIXME(eddyb) distinguish upvar inference variables from the rest. + kind: TypeVariableOriginKind::ClosureSynthetic, + span: self.tcx.hir().span(var_hir_id), + }) + }) + })) + } else { + // Create type variables (for now) to represent the various + // pieces of information kept in `{Closure,Generic}Substs`. + // They will either be unified below, or later during the upvar + // inference phase (`upvar.rs`) + self.infcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::ClosureSynthetic, span: expr.span, }) - .into(), + } + .into(), GenericParamDefKind::Const => span_bug!(expr.span, "closure has const param"), }); if let Some(GeneratorTypes { resume_ty, yield_ty, interior, movability }) = generator_types { let generator_substs = substs.as_generator(); - self.demand_eqtype( - expr.span, - resume_ty, - generator_substs.resume_ty(expr_def_id, self.tcx), - ); - self.demand_eqtype( - expr.span, - yield_ty, - generator_substs.yield_ty(expr_def_id, self.tcx), - ); - self.demand_eqtype( - expr.span, - liberated_sig.output(), - generator_substs.return_ty(expr_def_id, self.tcx), - ); - self.demand_eqtype( - expr.span, - interior, - generator_substs.witness(expr_def_id, self.tcx), - ); - return self.tcx.mk_generator(expr_def_id, substs, movability); - } + self.demand_eqtype(expr.span, resume_ty, generator_substs.resume_ty()); + self.demand_eqtype(expr.span, yield_ty, generator_substs.yield_ty()); + self.demand_eqtype(expr.span, liberated_sig.output(), generator_substs.return_ty()); + self.demand_eqtype(expr.span, interior, generator_substs.witness()); - let closure_type = self.tcx.mk_closure(expr_def_id, substs); + // HACK(eddyb) this forces the types equated above into `substs` but + // it should rely on `GeneratorSubsts` providing a constructor, instead. + let substs = self.resolve_vars_if_possible(&substs); - debug!("check_closure: expr.hir_id={:?} closure_type={:?}", expr.hir_id, closure_type); + return self.tcx.mk_generator(expr_def_id, substs, movability); + } // Tuple up the arguments and insert the resulting function type into // the `closures` table. @@ -140,20 +146,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); let sig_fn_ptr_ty = self.tcx.mk_fn_ptr(sig); - self.demand_eqtype( - expr.span, - sig_fn_ptr_ty, - substs.as_closure().sig_ty(expr_def_id, self.tcx), - ); + self.demand_eqtype(expr.span, sig_fn_ptr_ty, substs.as_closure().sig_as_fn_ptr_ty()); if let Some(kind) = opt_kind { - self.demand_eqtype( - expr.span, - kind.to_ty(self.tcx), - substs.as_closure().kind_ty(expr_def_id, self.tcx), - ); + self.demand_eqtype(expr.span, kind.to_ty(self.tcx), substs.as_closure().kind_ty()); } + // HACK(eddyb) this forces the types equated above into `substs` but + // it should rely on `ClosureSubsts` providing a constructor, instead. + let substs = self.resolve_vars_if_possible(&substs); + + let closure_type = self.tcx.mk_closure(expr_def_id, substs); + + debug!("check_closure: expr.hir_id={:?} closure_type={:?}", expr.hir_id, closure_type); + closure_type } diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 3720b74d92e07..33fc18b4b6e68 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -52,7 +52,6 @@ use crate::astconv::AstConv; use crate::check::{FnCtxt, Needs}; -use rustc::session::parse::feature_err; use rustc::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast, }; @@ -63,13 +62,15 @@ use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TypeAndMut}; use rustc_errors::{struct_span_err, DiagnosticBuilder}; use rustc_hir as hir; -use rustc_hir::def_id::DefId; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{Coercion, InferOk, InferResult}; -use rustc_infer::traits::{self, ObligationCause, ObligationCauseCode}; +use rustc_session::parse::feature_err; use rustc_span::symbol::sym; use rustc_span::{self, Span}; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::traits::error_reporting::InferCtxtExt; +use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; + use smallvec::{smallvec, SmallVec}; use std::ops::Deref; @@ -111,7 +112,7 @@ fn identity(_: Ty<'_>) -> Vec> { vec![] } -fn simple<'tcx>(kind: Adjust<'tcx>) -> impl FnOnce(Ty<'tcx>) -> Vec> { +fn simple(kind: Adjust<'tcx>) -> impl FnOnce(Ty<'tcx>) -> Vec> { move |target| vec![Adjustment { kind, target }] } @@ -234,11 +235,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // unsafe qualifier. self.coerce_from_fn_pointer(a, a_f, b) } - ty::Closure(def_id_a, substs_a) => { + ty::Closure(_, substs_a) => { // Non-capturing closures are coercible to // function pointers or unsafe function pointers. // It cannot convert closures that require unsafe. - self.coerce_closure_to_fn(a, def_id_a, substs_a, b) + self.coerce_closure_to_fn(a, substs_a, b) } _ => { // Otherwise, just use unification rules. @@ -730,7 +731,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { fn coerce_closure_to_fn( &self, a: Ty<'tcx>, - def_id_a: DefId, substs_a: SubstsRef<'tcx>, b: Ty<'tcx>, ) -> CoerceResult<'tcx> { @@ -741,16 +741,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let b = self.shallow_resolve(b); match b.kind { - ty::FnPtr(fn_ty) if self.tcx.upvars(def_id_a).map_or(true, |v| v.is_empty()) => { + ty::FnPtr(fn_ty) if substs_a.as_closure().upvar_tys().next().is_none() => { // We coerce the closure, which has fn type // `extern "rust-call" fn((arg0,arg1,...)) -> _` // to // `fn(arg0,arg1,...) -> _` // or // `unsafe fn(arg0,arg1,...) -> _` - let sig = self.closure_sig(def_id_a, substs_a); + let closure_sig = substs_a.as_closure().sig(); let unsafety = fn_ty.unsafety(); - let pointer_ty = self.tcx.coerce_closure_fn_ty(sig, unsafety); + let pointer_ty = self.tcx.coerce_closure_fn_ty(closure_sig, unsafety); debug!("coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})", a, b, pointer_ty); self.unify_and( pointer_ty, diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 0c8dec8f8d4a9..412f687b43ec6 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -1,4 +1,3 @@ -use rustc::hir::map::Map; use rustc::ty::error::{ExpectedFound, TypeError}; use rustc::ty::subst::{InternalSubsts, Subst}; use rustc::ty::util::ExplicitSelf; @@ -10,8 +9,9 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit; use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind}; use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; -use rustc_infer::traits::{self, ObligationCause, ObligationCauseCode, Reveal}; use rustc_span::Span; +use rustc_trait_selection::traits::error_reporting::InferCtxtExt; +use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, Reveal}; use super::{potentially_plural_count, FnCtxt, Inherited}; @@ -35,7 +35,7 @@ crate fn compare_impl_method<'tcx>( ) { debug!("compare_impl_method(impl_trait_ref={:?})", impl_trait_ref); - let impl_m_span = tcx.sess.source_map().def_span(impl_m_span); + let impl_m_span = tcx.sess.source_map().guess_head_span(impl_m_span); if let Err(ErrorReported) = compare_self_type(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref) { @@ -213,7 +213,7 @@ fn compare_predicate_entailment<'tcx>( ); tcx.infer_ctxt().enter(|infcx| { - let inh = Inherited::new(infcx, impl_m.def_id); + let inh = Inherited::new(infcx, impl_m.def_id.expect_local()); let infcx = &inh.infcx; debug!("compare_impl_method: caller_bounds={:?}", param_env.caller_bounds); @@ -363,7 +363,7 @@ fn check_region_bounds_on_impl_item<'tcx>( // the moment, give a kind of vague error message. if trait_params != impl_params { let item_kind = assoc_item_kind_str(impl_m); - let def_span = tcx.sess.source_map().def_span(span); + let def_span = tcx.sess.source_map().guess_head_span(span); let span = tcx.hir().get_generics(impl_m.def_id).map(|g| g.span).unwrap_or(def_span); let mut err = struct_span_err!( tcx.sess, @@ -375,7 +375,7 @@ fn check_region_bounds_on_impl_item<'tcx>( ); err.span_label(span, &format!("lifetimes do not match {} in trait", item_kind)); if let Some(sp) = tcx.hir().span_if_local(trait_m.def_id) { - let def_sp = tcx.sess.source_map().def_span(sp); + let def_sp = tcx.sess.source_map().guess_head_span(sp); let sp = tcx.hir().get_generics(trait_m.def_id).map(|g| g.span).unwrap_or(def_sp); err.span_label( sp, @@ -402,7 +402,7 @@ fn extract_spans_for_error_reporting<'a, 'tcx>( let tcx = infcx.tcx; let impl_m_hir_id = tcx.hir().as_local_hir_id(impl_m.def_id).unwrap(); let (impl_m_output, impl_m_iter) = match tcx.hir().expect_impl_item(impl_m_hir_id).kind { - ImplItemKind::Method(ref impl_m_sig, _) => { + ImplItemKind::Fn(ref impl_m_sig, _) => { (&impl_m_sig.decl.output, impl_m_sig.decl.inputs.iter()) } _ => bug!("{:?} is not a method", impl_m), @@ -677,7 +677,7 @@ fn compare_number_of_generics<'tcx>( impl_count, kind, pluralize!(impl_count), - suffix.unwrap_or_else(|| String::new()), + suffix.unwrap_or_else(String::new), ), ); } @@ -731,7 +731,7 @@ fn compare_number_of_method_arguments<'tcx>( }; let impl_m_hir_id = tcx.hir().as_local_hir_id(impl_m.def_id).unwrap(); let impl_span = match tcx.hir().expect_impl_item(impl_m_hir_id).kind { - ImplItemKind::Method(ref impl_m_sig, _) => { + ImplItemKind::Fn(ref impl_m_sig, _) => { let pos = if impl_number_args > 0 { impl_number_args - 1 } else { 0 }; if let Some(arg) = impl_m_sig.decl.inputs.get(pos) { if pos == 0 { @@ -872,7 +872,7 @@ fn compare_synthetic_generics<'tcx>( let impl_m = tcx.hir().as_local_hir_id(impl_m.def_id)?; let impl_m = tcx.hir().impl_item(hir::ImplItemId { hir_id: impl_m }); let input_tys = match impl_m.kind { - hir::ImplItemKind::Method(ref sig, _) => sig.decl.inputs, + hir::ImplItemKind::Fn(ref sig, _) => sig.decl.inputs, _ => unreachable!(), }; struct Visitor(Option, hir::def_id::DefId); @@ -889,10 +889,10 @@ fn compare_synthetic_generics<'tcx>( } } } - type Map = Map<'v>; + type Map = intravisit::ErasedMap<'v>; fn nested_visit_map( &mut self, - ) -> intravisit::NestedVisitorMap<'_, Self::Map> + ) -> intravisit::NestedVisitorMap { intravisit::NestedVisitorMap::None } @@ -950,7 +950,7 @@ crate fn compare_const_impl<'tcx>( tcx.infer_ctxt().enter(|infcx| { let param_env = tcx.param_env(impl_c.def_id); - let inh = Inherited::new(infcx, impl_c.def_id); + let inh = Inherited::new(infcx, impl_c.def_id.expect_local()); let infcx = &inh.infcx; // The below is for the most part highly similar to the procedure @@ -1130,7 +1130,7 @@ fn compare_type_predicate_entailment( normalize_cause.clone(), ); tcx.infer_ctxt().enter(|infcx| { - let inh = Inherited::new(infcx, impl_ty.def_id); + let inh = Inherited::new(infcx, impl_ty.def_id.expect_local()); let infcx = &inh.infcx; debug!("compare_type_predicate_entailment: caller_bounds={:?}", param_env.caller_bounds); diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 6df9d0541952c..0556c80e4f707 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -1,6 +1,8 @@ use crate::check::FnCtxt; use rustc_infer::infer::InferOk; -use rustc_infer::traits::{self, ObligationCause}; +use rustc_trait_selection::infer::InferCtxtExt as _; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; +use rustc_trait_selection::traits::{self, ObligationCause}; use rustc::ty::adjustment::AllowTwoPhase; use rustc::ty::{self, AssocItem, Ty}; diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index ead7536f8c664..e48ebbbb23514 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -9,9 +9,12 @@ use rustc::ty::subst::{Subst, SubstsRef}; use rustc::ty::{self, Predicate, Ty, TyCtxt}; use rustc_errors::struct_span_err; use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::{InferOk, SuppressRegionErrors, TyCtxtInferExt}; -use rustc_infer::traits::{ObligationCause, TraitEngine, TraitEngineExt}; +use rustc_infer::infer::{InferOk, RegionckMode, TyCtxtInferExt}; +use rustc_infer::traits::TraitEngineExt as _; use rustc_span::Span; +use rustc_trait_selection::traits::error_reporting::InferCtxtExt; +use rustc_trait_selection::traits::query::dropck_outlives::AtExt; +use rustc_trait_selection::traits::{ObligationCause, TraitEngine, TraitEngineExt}; /// This function confirms that the `Drop` implementation identified by /// `drop_impl_did` is not any more specialized than the type it is @@ -136,7 +139,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>( drop_impl_did, ®ion_scope_tree, &outlives_env, - SuppressRegionErrors::default(), + RegionckMode::default(), ); Ok(()) }) diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 859a219c95a21..dffed9a836c21 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -18,7 +18,6 @@ use crate::type_error_struct; use crate::util::common::ErrorReported; use rustc::middle::lang_items; -use rustc::mir::interpret::ErrorHandled; use rustc::ty; use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::ty::Ty; @@ -34,10 +33,10 @@ use rustc_hir::def_id::DefId; use rustc_hir::{ExprKind, QPath}; use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::traits::{self, ObligationCauseCode}; use rustc_span::hygiene::DesugaringKind; use rustc_span::source_map::Span; use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_trait_selection::traits::{self, ObligationCauseCode}; use std::fmt::Display; @@ -1008,13 +1007,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { let tcx = self.tcx; - let count_def_id = tcx.hir().local_def_id(count.hir_id); - let count = if self.const_param_def_id(count).is_some() { - Ok(self.to_const(count, tcx.type_of(count_def_id))) - } else { - tcx.const_eval_poly(count_def_id) - .map(|val| ty::Const::from_value(tcx, val, tcx.type_of(count_def_id))) - }; + let count = self.to_const(count); let uty = match expected { ExpectHasType(uty) => match uty.kind { @@ -1042,17 +1035,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if element_ty.references_error() { return tcx.types.err; } - match count { - Ok(count) => tcx.mk_ty(ty::Array(t, count)), - Err(ErrorHandled::TooGeneric) => { - self.tcx.sess.span_err( - tcx.def_span(count_def_id), - "array lengths can't depend on generic parameters", - ); - tcx.types.err - } - Err(ErrorHandled::Reported) => tcx.types.err, - } + + tcx.mk_ty(ty::Array(t, count)) } fn check_expr_tuple( @@ -1069,16 +1053,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }); - let elt_ts_iter = elts.iter().enumerate().map(|(i, e)| { - let t = match flds { - Some(ref fs) if i < fs.len() => { - let ety = fs[i].expect_ty(); - self.check_expr_coercable_to_type(&e, ety); - ety - } - _ => self.check_expr_with_expectation(&e, NoExpectation), - }; - t + let elt_ts_iter = elts.iter().enumerate().map(|(i, e)| match flds { + Some(ref fs) if i < fs.len() => { + let ety = fs[i].expect_ty(); + self.check_expr_coercable_to_type(&e, ety); + ety + } + _ => self.check_expr_with_expectation(&e, NoExpectation), }); let tuple = self.tcx.mk_tup(elt_ts_iter); if tuple.references_error() { @@ -1203,7 +1184,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .fields .iter() .enumerate() - .map(|(i, field)| (field.ident.modern(), (i, field))) + .map(|(i, field)| (field.ident.normalize_to_macros_2_0(), (i, field))) .collect::>(); let mut seen_fields = FxHashMap::default(); @@ -1469,7 +1450,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (ident, def_scope) = self.tcx.adjust_ident_and_get_scope(field, base_def.did, self.body_id); let fields = &base_def.non_enum_variant().fields; - if let Some(index) = fields.iter().position(|f| f.ident.modern() == ident) { + if let Some(index) = + fields.iter().position(|f| f.ident.normalize_to_macros_2_0() == ident) + { let field = &fields[index]; let field_ty = self.field_ty(expr.span, field, substs); // Save the index of all fields regardless of their visibility in case @@ -1581,13 +1564,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let mut err = struct_span_err!( self.tcx().sess, - expr.span, + field.span, E0616, "field `{}` of {} `{}` is private", field, kind_name, struct_path ); + err.span_label(field.span, "private field"); // Also check if an accessible method exists, which is often what is meant. if self.method_exists(field, expr_t, expr.hir_id, false) && !self.expr_in_place(expr.hir_id) { @@ -1612,7 +1596,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { field, expr_t ); - + err.span_label(field.span, "method, not a field"); if !self.expr_in_place(expr.hir_id) { self.suggest_method_call( &mut err, @@ -1629,7 +1613,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } fn point_at_param_definition(&self, err: &mut DiagnosticBuilder<'_>, param: ty::ParamTy) { - let generics = self.tcx.generics_of(self.body_id.owner_def_id()); + let generics = self.tcx.generics_of(self.body_id.owner.to_def_id()); let generic_param = generics.type_param(¶m, self.tcx); if let ty::GenericParamDefKind::Type { synthetic: Some(..), .. } = generic_param.kind { return; diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs index 7e52657377393..cdf68256a7a88 100644 --- a/src/librustc_typeck/check/generator_interior.rs +++ b/src/librustc_typeck/check/generator_interior.rs @@ -4,7 +4,6 @@ //! types computed here. use super::FnCtxt; -use rustc::hir::map::Map; use rustc::middle::region::{self, YieldData}; use rustc::ty::{self, Ty}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -209,9 +208,9 @@ pub fn resolve_interior<'a, 'tcx>( // librustc/middle/region.rs since `expr_count` is compared against the results // there. impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index d2a358c3e09b8..6f9d8a8e58fa5 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -137,21 +137,14 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { let (n_tps, inputs, output) = match &name[..] { "breakpoint" => (0, Vec::new(), tcx.mk_unit()), "size_of" | "pref_align_of" | "min_align_of" => (1, Vec::new(), tcx.types.usize), - "size_of_val" | "min_align_of_val" => ( - 1, - vec![tcx.mk_imm_ref( - tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BrAnon(0))), - param(0), - )], - tcx.types.usize, - ), + "size_of_val" | "min_align_of_val" => { + (1, vec![tcx.mk_imm_ptr(param(0))], tcx.types.usize) + } "rustc_peek" => (1, vec![param(0)], param(0)), "caller_location" => (0, vec![], tcx.caller_location_ty()), - "panic_if_uninhabited" | "panic_if_zero_invalid" | "panic_if_any_invalid" => { + "assert_inhabited" | "assert_zero_valid" | "assert_uninit_valid" => { (1, Vec::new(), tcx.mk_unit()) } - "init" => (1, Vec::new(), param(0)), - "uninit" => (1, Vec::new(), param(0)), "forget" => (1, vec![param(0)], tcx.mk_unit()), "transmute" => (2, vec![param(0)], param(1)), "move_val_init" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()), @@ -299,14 +292,25 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { "try" => { let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8); - let fn_ty = ty::Binder::bind(tcx.mk_fn_sig( + let try_fn_ty = ty::Binder::bind(tcx.mk_fn_sig( iter::once(mut_u8), tcx.mk_unit(), false, hir::Unsafety::Normal, Abi::Rust, )); - (0, vec![tcx.mk_fn_ptr(fn_ty), mut_u8, mut_u8], tcx.types.i32) + let catch_fn_ty = ty::Binder::bind(tcx.mk_fn_sig( + [mut_u8, mut_u8].iter().cloned(), + tcx.mk_unit(), + false, + hir::Unsafety::Normal, + Abi::Rust, + )); + ( + 0, + vec![tcx.mk_fn_ptr(try_fn_ty), mut_u8, tcx.mk_fn_ptr(catch_fn_ty)], + tcx.types.i32, + ) } "va_start" | "va_end" => match mk_va_list_ty(hir::Mutability::Mut) { diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 108affe5a86c0..d340d6ff5c271 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -11,8 +11,8 @@ use rustc::ty::subst::{Subst, SubstsRef}; use rustc::ty::{self, GenericParamDefKind, Ty}; use rustc_hir as hir; use rustc_infer::infer::{self, InferOk}; -use rustc_infer::traits; use rustc_span::Span; +use rustc_trait_selection::traits; use std::ops::Deref; @@ -331,7 +331,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { } (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => self.to_ty(ty).into(), (GenericParamDefKind::Const, GenericArg::Const(ct)) => { - self.to_const(&ct.value, self.tcx.type_of(param.def_id)).into() + self.to_const(&ct.value).into() } _ => unreachable!(), }, diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 189b05a819bab..962f9807546ac 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -22,8 +22,9 @@ use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace}; use rustc_hir::def_id::DefId; use rustc_infer::infer::{self, InferOk}; -use rustc_infer::traits; use rustc_span::Span; +use rustc_trait_selection::traits; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use self::probe::{IsSuggestion, ProbeScope}; @@ -136,7 +137,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self_ty: Ty<'tcx>, call_expr: &hir::Expr<'_>, ) { - let has_params = self + let params = self .probe_for_name( method_name.span, probe::Mode::MethodCall, @@ -146,26 +147,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_expr.hir_id, ProbeScope::TraitsInScope, ) - .and_then(|pick| { + .map(|pick| { let sig = self.tcx.fn_sig(pick.item.def_id); - Ok(sig.inputs().skip_binder().len() > 1) - }); + sig.inputs().skip_binder().len().saturating_sub(1) + }) + .unwrap_or(0); // Account for `foo.bar`; - let sugg_span = method_name.span.with_hi(call_expr.span.hi()); - let snippet = self - .tcx - .sess - .source_map() - .span_to_snippet(sugg_span) - .unwrap_or_else(|_| method_name.to_string()); - let (suggestion, applicability) = if has_params.unwrap_or_default() { - (format!("{}(...)", snippet), Applicability::HasPlaceholders) - } else { - (format!("{}()", snippet), Applicability::MaybeIncorrect) - }; + let sugg_span = call_expr.span.shrink_to_hi(); + let (suggestion, applicability) = ( + format!("({})", (0..params).map(|_| "_").collect::>().join(", ")), + if params > 0 { Applicability::HasPlaceholders } else { Applicability::MaybeIncorrect }, + ); - err.span_suggestion(sugg_span, msg, suggestion, applicability); + err.span_suggestion_verbose(sugg_span, msg, suggestion, applicability); } /// Performs method lookup. If lookup is successful, it will return the callee @@ -367,11 +362,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let fn_sig = tcx.fn_sig(def_id); let fn_sig = self.replace_bound_vars_with_fresh_vars(span, infer::FnCall, &fn_sig).0; let fn_sig = fn_sig.subst(self.tcx, substs); - let fn_sig = match self.normalize_associated_types_in_as_infer_ok(span, &fn_sig) { - InferOk { value, obligations: o } => { - obligations.extend(o); - value - } + + let InferOk { value, obligations: o } = + self.normalize_associated_types_in_as_infer_ok(span, &fn_sig); + let fn_sig = { + obligations.extend(o); + value }; // Register obligations for the parameters. This will include the @@ -383,12 +379,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Note that as the method comes from a trait, it should not have // any late-bound regions appearing in its bounds. let bounds = self.tcx.predicates_of(def_id).instantiate(self.tcx, substs); - let bounds = match self.normalize_associated_types_in_as_infer_ok(span, &bounds) { - InferOk { value, obligations: o } => { - obligations.extend(o); - value - } + + let InferOk { value, obligations: o } = + self.normalize_associated_types_in_as_infer_ok(span, &bounds); + let bounds = { + obligations.extend(o); + value }; + assert!(!bounds.has_escaping_bound_vars()); let cause = traits::ObligationCause::misc(span, self.body_id); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index d35761a6a21f5..45b1c7d6ea740 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -8,9 +8,7 @@ use crate::check::FnCtxt; use crate::hir::def::DefKind; use crate::hir::def_id::DefId; -use rustc::lint; use rustc::middle::stability; -use rustc::session::config::nightly_options; use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc::ty::GenericParamDefKind; use rustc::ty::{ @@ -28,11 +26,16 @@ use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; -use rustc_infer::traits::query::method_autoderef::MethodAutoderefBadTy; -use rustc_infer::traits::query::method_autoderef::{CandidateStep, MethodAutoderefStepsResult}; -use rustc_infer::traits::query::CanonicalTyGoal; -use rustc_infer::traits::{self, ObligationCause}; +use rustc_session::config::nightly_options; +use rustc_session::lint; use rustc_span::{symbol::Symbol, Span, DUMMY_SP}; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; +use rustc_trait_selection::traits::query::method_autoderef::MethodAutoderefBadTy; +use rustc_trait_selection::traits::query::method_autoderef::{ + CandidateStep, MethodAutoderefStepsResult, +}; +use rustc_trait_selection::traits::query::CanonicalTyGoal; +use rustc_trait_selection::traits::{self, ObligationCause}; use std::cmp::max; use std::iter; use std::mem; diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 654ec372dedff..e940ecce0b9fb 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -4,7 +4,6 @@ use crate::check::FnCtxt; use crate::middle::lang_items::FnOnceTraitLangItem; use rustc::hir::map as hir_map; -use rustc::hir::map::Map; use rustc::ty::print::with_crate_prefix; use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; use rustc_ast::ast; @@ -17,9 +16,10 @@ use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::intravisit; use rustc_hir::{ExprKind, Node, QPath}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::traits::Obligation; use rustc_span::symbol::kw; use rustc_span::{source_map, FileName, Span}; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; +use rustc_trait_selection::traits::Obligation; use std::cmp::Ordering; @@ -147,7 +147,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(note_span) = note_span { // We have a span pointing to the method. Show note with snippet. err.span_note( - self.tcx.sess.source_map().def_span(note_span), + self.tcx.sess.source_map().guess_head_span(note_span), ¬e_str, ); } else { @@ -189,8 +189,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(item) => item, None => continue, }; - let item_span = - self.tcx.sess.source_map().def_span(self.tcx.def_span(item.def_id)); + let item_span = self + .tcx + .sess + .source_map() + .guess_head_span(self.tcx.def_span(item.def_id)); let idx = if sources.len() > 1 { let msg = &format!( "candidate #{} is defined in the trait `{}`", @@ -397,7 +400,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(def) = actual.ty_adt_def() { if let Some(full_sp) = tcx.hir().span_if_local(def.did) { - let def_sp = tcx.sess.source_map().def_span(full_sp); + let def_sp = tcx.sess.source_map().guess_head_span(full_sp); err.span_label( def_sp, format!( @@ -427,7 +430,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); if let Some((field, field_ty)) = field_receiver { - let scope = self.tcx.parent_module(self.body_id); + let scope = self.tcx.parent_module(self.body_id).to_def_id(); let is_accessible = field.vis.is_accessible_from(scope, self.tcx); if is_accessible { @@ -537,8 +540,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut restrict_type_params = false; if !unsatisfied_predicates.is_empty() { - let def_span = - |def_id| self.tcx.sess.source_map().def_span(self.tcx.def_span(def_id)); + let def_span = |def_id| { + self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id)) + }; let mut type_params = FxHashMap::default(); let mut bound_spans = vec![]; let mut collect_type_param_suggestions = @@ -758,25 +762,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { MethodError::Ambiguity(sources) => { let mut err = struct_span_err!( self.sess(), - span, + item_name.span, E0034, "multiple applicable items in scope" ); - err.span_label(span, format!("multiple `{}` found", item_name)); + err.span_label(item_name.span, format!("multiple `{}` found", item_name)); report_candidates(span, &mut err, sources, sugg_span); err.emit(); } MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => { + let kind = kind.descr(def_id); let mut err = struct_span_err!( self.tcx.sess, - span, + item_name.span, E0624, "{} `{}` is private", - kind.descr(def_id), + kind, item_name ); + err.span_label(item_name.span, &format!("private {}", kind)); self.suggest_valid_traits(&mut err, out_of_scope_traits); err.emit(); } @@ -828,7 +834,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { candidates: Vec, ) { let module_did = self.tcx.parent_module(self.body_id); - let module_id = self.tcx.hir().as_local_hir_id(module_did).unwrap(); + let module_id = self.tcx.hir().as_local_hir_id(module_did.to_def_id()).unwrap(); let krate = self.tcx.hir().krate(); let (span, found_use) = UsePlacementFinder::check(self.tcx, krate, module_id); if let Some(span) = span { @@ -938,10 +944,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { })) = id.map(|id| self.tcx.hir().get(id)) { let self_first_arg = match method { - hir::TraitMethod::Required([ident, ..]) => { + hir::TraitFn::Required([ident, ..]) => { ident.name == kw::SelfLower } - hir::TraitMethod::Provided(body_id) => { + hir::TraitFn::Provided(body_id) => { match &self.tcx.hir().body(*body_id).params[..] { [hir::Param { pat: @@ -1018,9 +1024,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Obtain the span for `param` and use it for a structured suggestion. let mut suggested = false; if let (Some(ref param), Some(ref table)) = (param_type, self.in_progress_tables) { - let table = table.borrow(); - if let Some(did) = table.local_id_root { - let generics = self.tcx.generics_of(did); + let table_owner = table.borrow().hir_owner; + if let Some(table_owner) = table_owner { + let generics = self.tcx.generics_of(table_owner.to_def_id()); let type_param = generics.type_param(param, self.tcx); let hir = &self.tcx.hir(); if let Some(id) = hir.as_local_hir_id(type_param.def_id) { @@ -1115,7 +1121,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let [trait_info] = &candidates[..] { if let Some(span) = self.tcx.hir().span_if_local(trait_info.def_id) { err.span_note( - self.tcx.sess.source_map().def_span(span), + self.tcx.sess.source_map().guess_head_span(span), &format!( "`{}` defines an item `{}`, perhaps you need to {} it", self.tcx.def_path_str(trait_info.def_id), @@ -1346,9 +1352,9 @@ impl intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> { } } - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { intravisit::NestedVisitorMap::None } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f1f505e18599a..91ab94bc684e2 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -90,10 +90,8 @@ pub mod writeback; use crate::astconv::{AstConv, GenericArgCountMismatch, PathSeg}; use crate::middle::lang_items; use rustc::hir::map::blocks::FnLikeNode; -use rustc::hir::map::Map; use rustc::middle::region; use rustc::mir::interpret::ConstValue; -use rustc::session::parse::feature_err; use rustc::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast, }; @@ -114,24 +112,33 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, DiagnosticId}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{ExprKind, GenericArg, HirIdMap, Item, ItemKind, Node, PatKind, QPath}; use rustc_index::vec::Idx; use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; -use rustc_infer::infer::opaque_types::OpaqueTypeDecl; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_infer::infer::{self, InferCtxt, InferOk, InferResult, TyCtxtInferExt}; -use rustc_infer::traits::error_reporting::recursive_type_with_infinite_size_error; -use rustc_infer::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine}; +use rustc_session::config::{self, EntryFnType}; +use rustc_session::lint; +use rustc_session::parse::feature_err; +use rustc_session::Session; use rustc_span::hygiene::DesugaringKind; use rustc_span::source_map::{original_sp, DUMMY_SP}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{self, BytePos, MultiSpan, Span}; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::infer::InferCtxtExt as _; +use rustc_trait_selection::opaque_types::{InferCtxtExt as _, OpaqueTypeDecl}; +use rustc_trait_selection::traits::error_reporting::recursive_type_with_infinite_size_error; +use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; +use rustc_trait_selection::traits::{ + self, ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt, +}; use std::cell::{Cell, Ref, RefCell, RefMut}; use std::cmp; @@ -141,10 +148,7 @@ use std::mem::replace; use std::ops::{self, Deref}; use std::slice; -use crate::lint; use crate::require_c_abi_if_c_variadic; -use crate::session::config::EntryFnType; -use crate::session::Session; use crate::util::common::{indenter, ErrorReported}; use crate::TypeAndSubsts; @@ -629,20 +633,15 @@ impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> { /// `F: for<'b, 'tcx> where 'tcx FnOnce(Inherited<'b, 'tcx>)`. pub struct InheritedBuilder<'tcx> { infcx: infer::InferCtxtBuilder<'tcx>, - def_id: DefId, + def_id: LocalDefId, } impl Inherited<'_, 'tcx> { - pub fn build(tcx: TyCtxt<'tcx>, def_id: DefId) -> InheritedBuilder<'tcx> { - let hir_id_root = if def_id.is_local() { - let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); - DefId::local(hir_id.owner) - } else { - def_id - }; + pub fn build(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> InheritedBuilder<'tcx> { + let hir_owner = tcx.hir().local_def_id_to_hir_id(def_id).owner; InheritedBuilder { - infcx: tcx.infer_ctxt().with_fresh_in_progress_tables(hir_id_root), + infcx: tcx.infer_ctxt().with_fresh_in_progress_tables(hir_owner), def_id, } } @@ -659,10 +658,10 @@ impl<'tcx> InheritedBuilder<'tcx> { } impl Inherited<'a, 'tcx> { - fn new(infcx: InferCtxt<'a, 'tcx>, def_id: DefId) -> Self { + fn new(infcx: InferCtxt<'a, 'tcx>, def_id: LocalDefId) -> Self { let tcx = infcx.tcx; - let item_id = tcx.hir().as_local_hir_id(def_id); - let body_id = item_id.and_then(|id| tcx.hir().maybe_body_owned_by(id)); + let item_id = tcx.hir().local_def_id_to_hir_id(def_id); + let body_id = tcx.hir().maybe_body_owned_by(item_id); let implicit_region_bound = body_id.map(|body_id| { let body = tcx.hir().body(body_id); tcx.mk_region(ty::ReScope(region::Scope { @@ -811,14 +810,14 @@ fn primary_body_of( }, Node::TraitItem(item) => match item.kind { hir::TraitItemKind::Const(ref ty, Some(body)) => Some((body, Some(ty), None, None)), - hir::TraitItemKind::Fn(ref sig, hir::TraitMethod::Provided(body)) => { + hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { Some((body, None, Some(&sig.header), Some(&sig.decl))) } _ => None, }, Node::ImplItem(item) => match item.kind { hir::ImplItemKind::Const(ref ty, body) => Some((body, Some(ty), None, None)), - hir::ImplItemKind::Method(ref sig, body) => { + hir::ImplItemKind::Fn(ref sig, body) => { Some((body, None, Some(&sig.header), Some(&sig.decl))) } _ => None, @@ -999,12 +998,19 @@ fn typeck_tables_of_with_fallback<'tcx>( }); let body = tcx.hir().body(body_id); - let tables = Inherited::build(tcx, def_id).enter(|inh| { + let tables = Inherited::build(tcx, def_id.expect_local()).enter(|inh| { let param_env = tcx.param_env(def_id); let fcx = if let (Some(header), Some(decl)) = (fn_header, fn_decl) { let fn_sig = if crate::collect::get_infer_ret_ty(&decl.output).is_some() { let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id); - AstConv::ty_of_fn(&fcx, header.unsafety, header.abi, decl, &[], None) + AstConv::ty_of_fn( + &fcx, + header.unsafety, + header.abi, + decl, + &hir::Generics::empty(), + None, + ) } else { tcx.fn_sig(def_id) }; @@ -1124,7 +1130,7 @@ fn typeck_tables_of_with_fallback<'tcx>( // Consistency check our TypeckTables instance can hold all ItemLocalIds // it will need to hold. - assert_eq!(tables.local_id_root, Some(DefId::local(id.owner))); + assert_eq!(tables.hir_owner, Some(id.owner)); tables } @@ -1172,9 +1178,9 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> { } impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } @@ -1473,7 +1479,7 @@ fn check_fn<'a, 'tcx>( } } } else { - let span = sess.source_map().def_span(span); + let span = sess.source_map().guess_head_span(span); sess.span_err(span, "function should have one argument"); } } else { @@ -1514,7 +1520,7 @@ fn check_fn<'a, 'tcx>( } } } else { - let span = sess.source_map().def_span(span); + let span = sess.source_map().guess_head_span(span); sess.span_err(span, "function should have one argument"); } } else { @@ -1577,7 +1583,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: DefId) -> bool { } else { span_bug!(span, "unions must be ty::Adt, but got {:?}", item_type.kind); } - return true; + true } /// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo` @@ -1653,11 +1659,14 @@ fn check_opaque_for_inheriting_lifetimes(tcx: TyCtxt<'tcx>, def_id: DefId, span: _ => unreachable!(), }; - tcx.sess.span_err(span, &format!( + tcx.sess.span_err( + span, + &format!( "`{}` return type cannot contain a projection or `Self` that references lifetimes from \ a parent scope", if is_async { "async fn" } else { "impl Trait" }, - )); + ), + ); } } @@ -1835,8 +1844,8 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: DefId, span: Span) Ok(ConstValue::ByRef { alloc, .. }) => { if alloc.relocations().len() != 0 { let msg = "statics with a custom `#[link_section]` must be a \ - simple list of bytes on the wasm target with no \ - extra levels of indirection such as references"; + simple list of bytes on the wasm target with no \ + extra levels of indirection such as references"; tcx.sess.span_err(span, msg); } } @@ -1891,13 +1900,16 @@ fn check_specialization_validity<'tcx>( ) { let kind = match impl_item.kind { hir::ImplItemKind::Const(..) => ty::AssocKind::Const, - hir::ImplItemKind::Method(..) => ty::AssocKind::Method, + hir::ImplItemKind::Fn(..) => ty::AssocKind::Method, hir::ImplItemKind::OpaqueTy(..) => ty::AssocKind::OpaqueTy, hir::ImplItemKind::TyAlias(_) => ty::AssocKind::Type, }; - let mut ancestor_impls = trait_def - .ancestors(tcx, impl_id) + let ancestors = match trait_def.ancestors(tcx, impl_id) { + Ok(ancestors) => ancestors, + Err(_) => return, + }; + let mut ancestor_impls = ancestors .skip(1) .filter_map(|parent| { if parent.is_from_trait() { @@ -1953,7 +1965,7 @@ fn check_impl_items_against_trait<'tcx>( impl_trait_ref: ty::TraitRef<'tcx>, impl_item_refs: &[hir::ImplItemRef<'_>], ) { - let impl_span = tcx.sess.source_map().def_span(full_impl_span); + let impl_span = tcx.sess.source_map().guess_head_span(full_impl_span); // If the trait reference itself is erroneous (so the compilation is going // to fail), skip checking the items here -- the `impl_item` table in `tcx` @@ -1962,6 +1974,24 @@ fn check_impl_items_against_trait<'tcx>( return; } + // Negative impls are not expected to have any items + match tcx.impl_polarity(impl_id) { + ty::ImplPolarity::Reservation | ty::ImplPolarity::Positive => {} + ty::ImplPolarity::Negative => { + if let [first_item_ref, ..] = impl_item_refs { + let first_item_span = tcx.hir().impl_item(first_item_ref.id).span; + struct_span_err!( + tcx.sess, + first_item_span, + E0749, + "negative impls cannot have any items" + ) + .emit(); + } + return; + } + } + // Locate trait definition and items let trait_def = tcx.trait_def(impl_trait_ref.def_id); @@ -2001,7 +2031,7 @@ fn check_impl_items_against_trait<'tcx>( impl_item.span, E0323, "item `{}` is an associated const, \ - which doesn't match its trait `{}`", + which doesn't match its trait `{}`", ty_impl_item.ident, impl_trait_ref.print_only_trait_path() ); @@ -2014,7 +2044,7 @@ fn check_impl_items_against_trait<'tcx>( err.emit() } } - hir::ImplItemKind::Method(..) => { + hir::ImplItemKind::Fn(..) => { let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id); if ty_trait_item.kind == ty::AssocKind::Method { compare_impl_method( @@ -2078,16 +2108,17 @@ fn check_impl_items_against_trait<'tcx>( // Check for missing items from trait let mut missing_items = Vec::new(); - for trait_item in tcx.associated_items(impl_trait_ref.def_id).in_definition_order() { - let is_implemented = trait_def - .ancestors(tcx, impl_id) - .leaf_def(tcx, trait_item.ident, trait_item.kind) - .map(|node_item| !node_item.node.is_from_trait()) - .unwrap_or(false); - - if !is_implemented && !traits::impl_is_default(tcx, impl_id) { - if !trait_item.defaultness.has_value() { - missing_items.push(*trait_item); + if let Ok(ancestors) = trait_def.ancestors(tcx, impl_id) { + for trait_item in tcx.associated_items(impl_trait_ref.def_id).in_definition_order() { + let is_implemented = ancestors + .leaf_def(tcx, trait_item.ident, trait_item.kind) + .map(|node_item| !node_item.node.is_from_trait()) + .unwrap_or(false); + + if !is_implemented && !traits::impl_is_default(tcx, impl_id) { + if !trait_item.defaultness.has_value() { + missing_items.push(*trait_item); + } } } } @@ -2306,7 +2337,7 @@ fn check_representable(tcx: TyCtxt<'_>, sp: Span, item_def_id: DefId) -> bool { } Representability::Representable | Representability::ContainsRecursive => (), } - return true; + true } pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: DefId) { @@ -2498,7 +2529,7 @@ fn check_transparent(tcx: TyCtxt<'_>, sp: Span, def_id: DefId) { if !adt.repr.transparent() { return; } - let sp = tcx.sess.source_map().def_span(sp); + let sp = tcx.sess.source_map().guess_head_span(sp); if adt.is_union() && !tcx.features().transparent_unions { feature_err( @@ -3276,13 +3307,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty } - /// Returns the `DefId` of the constant parameter that the provided expression is a path to. - pub fn const_param_def_id(&self, hir_c: &hir::AnonConst) -> Option { - AstConv::const_param_def_id(self, &self.tcx.hir().body(hir_c.body).value) - } - - pub fn to_const(&self, ast_c: &hir::AnonConst, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> { - AstConv::ast_const_to_const(self, ast_c, ty) + pub fn to_const(&self, ast_c: &hir::AnonConst) -> &'tcx ty::Const<'tcx> { + let c = self.tcx.hir().local_def_id(ast_c.hir_id).expect_local(); + ty::Const::from_anon_const(self.tcx, c) } // If the type given by the user has free regions, save it for later, since @@ -3548,7 +3575,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let adjusted_ty = autoderef.unambiguous_final_ty(self); debug!( "try_index_step(expr={:?}, base_expr={:?}, adjusted_ty={:?}, \ - index_ty={:?})", + index_ty={:?})", expr, base_expr, adjusted_ty, index_ty ); @@ -3651,14 +3678,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Otherwise, fall back to the immutable version. let (imm_tr, imm_op) = self.resolve_place_op(op, false); - let method = match (method, imm_tr) { + match (method, imm_tr) { (None, Some(trait_did)) => { self.lookup_method_in_trait(span, imm_op, trait_did, base_ty, Some(arg_tys)) } (method, _) => method, - }; - - method + } } fn check_method_argument_types( @@ -3871,7 +3896,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - if let Some(def_s) = def_span.map(|sp| tcx.sess.source_map().def_span(sp)) { + if let Some(def_s) = def_span.map(|sp| tcx.sess.source_map().guess_head_span(sp)) { err.span_label(def_s, "defined here"); } if sugg_unit { @@ -4701,7 +4726,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label( fn_span, "implicitly returns `()` as its body has no tail or `return` \ - expression", + expression", ); } }, @@ -4733,9 +4758,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let node = self.tcx.hir().get(self.tcx.hir().get_parent_item(id)); match node { Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) - | Node::ImplItem(&hir::ImplItem { - kind: hir::ImplItemKind::Method(_, body_id), .. - }) => { + | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => { let body = self.tcx.hir().body(body_id); if let ExprKind::Block(block, _) = &body.value.kind { return Some(block.span); @@ -4774,7 +4797,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) => Some((&sig.decl, ident, true)), Node::ImplItem(&hir::ImplItem { ident, - kind: hir::ImplItemKind::Method(ref sig, ..), + kind: hir::ImplItemKind::Fn(ref sig, ..), .. }) => Some((&sig.decl, ident, false)), _ => None, @@ -4832,18 +4855,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let hir = self.tcx.hir(); let (def_id, sig) = match found.kind { ty::FnDef(def_id, _) => (def_id, found.fn_sig(self.tcx)), - ty::Closure(def_id, substs) => { - // We don't use `closure_sig` to account for malformed closures like - // `|_: [_; continue]| {}` and instead we don't suggest anything. - let closure_sig_ty = substs.as_closure().sig_ty(def_id, self.tcx); - ( - def_id, - match closure_sig_ty.kind { - ty::FnPtr(sig) => sig, - _ => return false, - }, - ) - } + ty::Closure(def_id, substs) => (def_id, substs.as_closure().sig()), _ => return false, }; @@ -4859,11 +4871,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match hir.get_if_local(def_id) { Some(Node::Item(hir::Item { kind: ItemKind::Fn(.., body_id), .. })) | Some(Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Method(_, body_id), + kind: hir::ImplItemKind::Fn(_, body_id), .. })) | Some(Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(.., hir::TraitMethod::Provided(body_id)), + kind: hir::TraitItemKind::Fn(.., hir::TraitFn::Provided(body_id)), .. })) => { let body = hir.body(*body_id); @@ -4934,7 +4946,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .join(", ") } Some(Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(.., hir::TraitMethod::Required(idents)), + kind: hir::TraitItemKind::Fn(.., hir::TraitFn::Required(idents)), .. })) => { sugg_call = idents @@ -4951,15 +4963,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } _ => {} } - if let Ok(code) = self.sess().source_map().span_to_snippet(expr.span) { - err.span_suggestion( - expr.span, - &format!("use parentheses to {}", msg), - format!("{}({})", code, sugg_call), - applicability, - ); - return true; - } + err.span_suggestion_verbose( + expr.span.shrink_to_hi(), + &format!("use parentheses to {}", msg), + format!("({})", sugg_call), + applicability, + ); + return true; } false } @@ -4977,7 +4987,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (&found.kind, self.suggest_fn_call(err, expr, expected, found)) { if let Some(sp) = self.tcx.hir().span_if_local(*def_id) { - let sp = self.sess().source_map().def_span(sp); + let sp = self.sess().source_map().guess_head_span(sp); err.span_label(sp, &format!("{} defined here", found)); } } else if !self.check_for_cast(err, expr, found, expected) { @@ -5526,7 +5536,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.to_ty(ty).into() } (GenericParamDefKind::Const, GenericArg::Const(ct)) => { - self.to_const(&ct.value, self.tcx.type_of(param.def_id)).into() + self.to_const(&ct.value).into() } _ => unreachable!(), }, @@ -5588,11 +5598,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match self.at(&self.misc(span), self.param_env).sup(impl_ty, self_ty) { Ok(ok) => self.register_infer_ok_obligations(ok), Err(_) => { - self.tcx.sess.delay_span_bug(span, &format!( + self.tcx.sess.delay_span_bug( + span, + &format!( "instantiate_value_path: (UFCS) {:?} was a subtype of {:?} but now is not?", self_ty, impl_ty, - )); + ), + ); } } } @@ -5778,12 +5791,12 @@ fn fatally_break_rust(sess: &Session) { handler.note_without_error("the compiler expectedly panicked. this is a feature."); handler.note_without_error( "we would appreciate a joke overview: \ - https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675", + https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675", ); handler.note_without_error(&format!( "rustc {} running on {}", option_env!("CFG_VERSION").unwrap_or("unknown_version"), - crate::session::config::host_triple(), + config::host_triple(), )); } diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index bf3511a26143c..f589805e1e261 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -10,6 +10,7 @@ use rustc_errors::{self, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_span::Span; +use rustc_trait_selection::infer::InferCtxtExt; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Checks a `a = b` @@ -860,7 +861,7 @@ enum Op { } /// Dereferences a single level of immutable referencing. -fn deref_ty_if_possible<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> { +fn deref_ty_if_possible(ty: Ty<'tcx>) -> Ty<'tcx> { match ty.kind { ty::Ref(_, ty, hir::Mutability::Not) => ty, _ => ty, diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 70b39a62cd718..0c4a05e61814d 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -11,9 +11,9 @@ use rustc_hir::pat_util::EnumerateAndAdjustIterator; use rustc_hir::{HirId, Pat, PatKind}; use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::traits::{ObligationCause, Pattern}; use rustc_span::hygiene::DesugaringKind; use rustc_span::source_map::{Span, Spanned}; +use rustc_trait_selection::traits::{ObligationCause, Pattern}; use std::cmp; use std::collections::hash_map::Entry::{Occupied, Vacant}; @@ -716,7 +716,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Res::Def(DefKind::Ctor(_, CtorKind::Const), _) | Res::SelfCtor(..) | Res::Def(DefKind::Const, _) - | Res::Def(DefKind::AssocConst, _) => {} // OK + | Res::Def(DefKind::AssocConst, _) + | Res::Def(DefKind::ConstParam, _) => {} // OK _ => bug!("unexpected pattern resolution: {:?}", res), } @@ -752,17 +753,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { res.descr(), ), ); - let (msg, sugg) = match parent_pat { - Some(Pat { kind: hir::PatKind::Struct(..), .. }) => ( - "bind the struct field to a different name instead", - format!("{}: other_{}", ident, ident.as_str().to_lowercase()), - ), - _ => ( - "introduce a new binding instead", - format!("other_{}", ident.as_str().to_lowercase()), - ), + match parent_pat { + Some(Pat { kind: hir::PatKind::Struct(..), .. }) => { + e.span_suggestion_verbose( + ident.span.shrink_to_hi(), + "bind the struct field to a different name instead", + format!(": other_{}", ident.as_str().to_lowercase()), + Applicability::HasPlaceholders, + ); + } + _ => { + let msg = "introduce a new binding instead"; + let sugg = format!("other_{}", ident.as_str().to_lowercase()); + e.span_suggestion(ident.span, msg, sugg, Applicability::HasPlaceholders); + } }; - e.span_suggestion(ident.span, msg, sugg, Applicability::HasPlaceholders); } } e.emit(); @@ -830,7 +835,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { on_error(); return tcx.types.err; } - Res::Def(DefKind::AssocConst, _) | Res::Def(DefKind::AssocFn, _) => { + Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) => { report_unexpected_res(res); return tcx.types.err; } @@ -1015,14 +1020,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Adt(adt, substs) => (substs, adt), _ => span_bug!(pat.span, "struct pattern is not an ADT"), }; - let kind_name = adt.variant_descr(); // Index the struct fields' types. let field_map = variant .fields .iter() .enumerate() - .map(|(i, field)| (field.ident.modern(), (i, field))) + .map(|(i, field)| (field.ident.normalize_to_macros_2_0(), (i, field))) .collect::>(); // Keep track of which fields have already appeared in the pattern. @@ -1063,13 +1067,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut unmentioned_fields = variant .fields .iter() - .map(|field| field.ident.modern()) + .map(|field| field.ident.normalize_to_macros_2_0()) .filter(|ident| !used_fields.contains_key(&ident)) .collect::>(); if !inexistent_fields.is_empty() && !variant.recovered { self.error_inexistent_fields( - kind_name, + adt.variant_descr(), &inexistent_fields, &mut unmentioned_fields, variant, @@ -1078,18 +1082,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Require `..` if struct has non_exhaustive attribute. if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc { - struct_span_err!( - tcx.sess, - pat.span, - E0638, - "`..` required with {} marked as non-exhaustive", - kind_name - ) - .emit(); + self.error_foreign_non_exhaustive_spat(pat, adt.variant_descr(), fields.is_empty()); } // Report an error if incorrect number of the fields were specified. - if kind_name == "union" { + if adt.is_union() { if fields.len() != 1 { tcx.sess .struct_span_err(pat.span, "union patterns should have exactly one field") @@ -1104,6 +1101,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { no_field_errors } + fn error_foreign_non_exhaustive_spat(&self, pat: &Pat<'_>, descr: &str, no_fields: bool) { + let sess = self.tcx.sess; + let sm = sess.source_map(); + let sp_brace = sm.end_point(pat.span); + let sp_comma = sm.end_point(pat.span.with_hi(sp_brace.hi())); + let sugg = if no_fields || sp_brace != sp_comma { ".. }" } else { ", .. }" }; + + let mut err = struct_span_err!( + sess, + pat.span, + E0638, + "`..` required with {} marked as non-exhaustive", + descr + ); + err.span_suggestion_verbose( + sp_comma, + "add `..` at the end of the field list to ignore all other fields", + sugg.to_string(), + Applicability::MachineApplicable, + ); + err.emit(); + } + fn error_field_already_bound(&self, span: Span, ident: ast::Ident, other_field: Span) { struct_span_err!( self.tcx.sess, diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index c0e33637fd047..a1345895689e0 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -76,7 +76,6 @@ use crate::check::dropck; use crate::check::FnCtxt; use crate::mem_categorization as mc; use crate::middle::region; -use rustc::hir::map::Map; use rustc::ty::adjustment; use rustc::ty::subst::{GenericArgKind, SubstsRef}; use rustc::ty::{self, Ty}; @@ -85,8 +84,10 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::PatKind; use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::{self, RegionObligation, SuppressRegionErrors}; +use rustc_infer::infer::{self, RegionObligation, RegionckMode}; use rustc_span::Span; +use rustc_trait_selection::infer::OutlivesEnvironmentExt; +use rustc_trait_selection::opaque_types::InferCtxtExt; use std::mem; use std::ops::Deref; @@ -122,10 +123,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcx.visit_body(body); rcx.visit_region_obligations(id); } - rcx.resolve_regions_and_report_errors(SuppressRegionErrors::when_nll_is_enabled(self.tcx)); - - assert!(self.tables.borrow().free_region_map.is_empty()); - self.tables.borrow_mut().free_region_map = rcx.outlives_environment.into_free_region_map(); + rcx.resolve_regions_and_report_errors(RegionckMode::for_item_body(self.tcx)); } /// Region checking during the WF phase for items. `wf_tys` are the @@ -143,7 +141,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcx.outlives_environment.add_implied_bounds(self, wf_tys, item_id, span); rcx.outlives_environment.save_implied_bounds(item_id); rcx.visit_region_obligations(item_id); - rcx.resolve_regions_and_report_errors(SuppressRegionErrors::default()); + rcx.resolve_regions_and_report_errors(RegionckMode::default()); } /// Region check a function body. Not invoked on closures, but @@ -166,13 +164,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcx.visit_fn_body(fn_id, body, self.tcx.hir().span(fn_id)); } - rcx.resolve_regions_and_report_errors(SuppressRegionErrors::when_nll_is_enabled(self.tcx)); - - // In this mode, we also copy the free-region-map into the - // tables of the enclosing fcx. In the other regionck modes - // (e.g., `regionck_item`), we don't have an enclosing tables. - assert!(self.tables.borrow().free_region_map.is_empty()); - self.tables.borrow_mut().free_region_map = rcx.outlives_environment.into_free_region_map(); + rcx.resolve_regions_and_report_errors(RegionckMode::for_item_body(self.tcx)); } } @@ -353,7 +345,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { self.select_all_obligations_or_error(); } - fn resolve_regions_and_report_errors(&self, suppress: SuppressRegionErrors) { + fn resolve_regions_and_report_errors(&self, mode: RegionckMode) { self.infcx.process_registered_region_obligations( self.outlives_environment.region_bound_pairs_map(), self.implicit_region_bound, @@ -364,7 +356,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { self.subject_def_id, &self.region_scope_tree, &self.outlives_environment, - suppress, + mode, ); } @@ -415,9 +407,9 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionCtxt<'a, 'tcx> { // hierarchy, and in particular the relationships between free // regions, until regionck, as described in #3238. - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } @@ -1236,8 +1228,8 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { // A closure capture can't be borrowed for longer than the // reference to the closure. - if let ty::Closure(closure_def_id, substs) = ty.kind { - match self.infcx.closure_kind(closure_def_id, substs) { + if let ty::Closure(_, substs) = ty.kind { + match self.infcx.closure_kind(substs) { Some(ty::ClosureKind::Fn) | Some(ty::ClosureKind::FnMut) => { // Region of environment pointer let env_region = self.tcx.mk_region(ty::ReFree(ty::FreeRegion { diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index b5ed6335dc011..ff4e2cdab78d7 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -35,7 +35,6 @@ use super::FnCtxt; use crate::expr_use_visitor as euv; use crate::mem_categorization as mc; use crate::mem_categorization::PlaceBase; -use rustc::hir::map::Map; use rustc::ty::{self, Ty, TyCtxt, UpvarSubsts}; use rustc_ast::ast; use rustc_data_structures::fx::FxIndexMap; @@ -60,9 +59,9 @@ struct InferBorrowKindVisitor<'a, 'tcx> { } impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } @@ -108,7 +107,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let infer_kind = if let UpvarSubsts::Closure(closure_substs) = substs { - self.closure_kind(closure_def_id, closure_substs).is_none().then_some(closure_substs) + self.closure_kind(closure_substs).is_none().then_some(closure_substs) } else { None }; @@ -119,7 +118,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for (&var_hir_id, _) in upvars.iter() { let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { hir_id: var_hir_id }, - closure_expr_id: LocalDefId::from_def_id(closure_def_id), + closure_expr_id: closure_def_id.expect_local(), }; debug!("seed upvar_id {:?}", upvar_id); // Adding the upvar Id to the list of Upvars, which will be added @@ -169,7 +168,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Unify the (as yet unbound) type variable in the closure // substs with the kind we inferred. let inferred_kind = delegate.current_closure_kind; - let closure_kind_ty = closure_substs.as_closure().kind_ty(closure_def_id, self.tcx); + let closure_kind_ty = closure_substs.as_closure().kind_ty(); self.demand_eqtype(span, inferred_kind.to_ty(self.tcx), closure_kind_ty); // If we have an origin, store it. @@ -198,9 +197,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "analyze_closure: id={:?} substs={:?} final_upvar_tys={:?}", closure_hir_id, substs, final_upvar_tys ); - for (upvar_ty, final_upvar_ty) in - substs.upvar_tys(closure_def_id, self.tcx).zip(final_upvar_tys) - { + for (upvar_ty, final_upvar_ty) in substs.upvar_tys().zip(final_upvar_tys) { self.demand_suptype(span, upvar_ty, final_upvar_ty); } @@ -229,7 +226,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let upvar_ty = self.node_ty(var_hir_id); let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { hir_id: var_hir_id }, - closure_expr_id: LocalDefId::from_def_id(closure_def_id), + closure_expr_id: closure_def_id.expect_local(), }; let capture = self.tables.borrow().upvar_capture(upvar_id); diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 335b4a2850116..c89c4b028b4ea 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -2,23 +2,24 @@ use crate::check::{FnCtxt, Inherited}; use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter}; use rustc::middle::lang_items; -use rustc::session::parse::feature_err; use rustc::ty::subst::{InternalSubsts, Subst}; +use rustc::ty::trait_def::TraitSpecializationKind; use rustc::ty::{ self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, }; use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; +use rustc_hir as hir; use rustc_hir::def_id::DefId; +use rustc_hir::itemlikevisit::ParItemLikeVisitor; use rustc_hir::ItemKind; -use rustc_infer::infer::opaque_types::may_define_opaque_type; -use rustc_infer::traits::{self, ObligationCause, ObligationCauseCode}; +use rustc_session::parse::feature_err; use rustc_span::symbol::sym; use rustc_span::Span; - -use rustc_hir as hir; -use rustc_hir::itemlikevisit::ParItemLikeVisitor; +use rustc_trait_selection::opaque_types::may_define_opaque_type; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; +use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; /// Helper type of a temporary returned by `.for_item(...)`. /// This is necessary because we can't write the following bound: @@ -97,34 +98,48 @@ 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 of_trait, ref self_ty, .. } => { + hir::ItemKind::Impl { + defaultness, + defaultness_span, + polarity, + 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)); - let polarity = tcx.impl_polarity(def_id); if let (hir::Defaultness::Default { .. }, true) = (defaultness, is_auto) { - tcx.sess.span_err(item.span, "impls of auto traits cannot be default"); + let sp = of_trait.as_ref().map(|t| t.path.span).unwrap_or(item.span); + let mut err = + tcx.sess.struct_span_err(sp, "impls of auto traits cannot be default"); + err.span_labels(defaultness_span, "default because of this"); + err.span_label(sp, "auto trait"); + err.emit(); } - match polarity { - ty::ImplPolarity::Positive => { + // We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span. + match (tcx.impl_polarity(def_id), polarity) { + (ty::ImplPolarity::Positive, _) => { check_impl(tcx, item, self_ty, of_trait); } - ty::ImplPolarity::Negative => { + (ty::ImplPolarity::Negative, ast::ImplPolarity::Negative(span)) => { // FIXME(#27579): what amount of WF checking do we need for neg impls? - if of_trait.is_some() && !is_auto { + if let hir::Defaultness::Default { .. } = defaultness { + let mut spans = vec![span]; + spans.extend(defaultness_span); struct_span_err!( tcx.sess, - item.span, - E0192, - "negative impls are only allowed for \ - auto traits (e.g., `Send` and `Sync`)" + spans, + E0750, + "negative impls cannot be default impls" ) - .emit() + .emit(); } } - ty::ImplPolarity::Reservation => { + (ty::ImplPolarity::Reservation, _) => { // FIXME: what amount of WF checking do we need for reservation impls? } + _ => unreachable!(), } } hir::ItemKind::Fn(..) => { @@ -247,7 +262,7 @@ pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: DefId) { let impl_item = tcx.hir().expect_impl_item(hir_id); let method_sig = match impl_item.kind { - hir::ImplItemKind::Method(ref sig, _) => Some(sig), + hir::ImplItemKind::Fn(ref sig, _) => Some(sig), _ => None, }; @@ -315,12 +330,12 @@ fn for_item<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'_>) -> CheckWfFcxBuilder< } fn for_id(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) -> CheckWfFcxBuilder<'_> { - let def_id = tcx.hir().local_def_id(id); + let def_id = tcx.hir().local_def_id(id).expect_local(); CheckWfFcxBuilder { inherited: Inherited::build(tcx, def_id), id, span, - param_env: tcx.param_env(def_id), + param_env: tcx.param_env(def_id.to_def_id()), } } @@ -411,7 +426,9 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { let trait_def_id = tcx.hir().local_def_id(item.hir_id); let trait_def = tcx.trait_def(trait_def_id); - if trait_def.is_marker { + if trait_def.is_marker + || matches!(trait_def.specialization_kind, TraitSpecializationKind::Marker) + { for associated_def_id in &*tcx.associated_item_def_ids(trait_def_id) { struct_span_err!( tcx.sess, @@ -883,13 +900,13 @@ fn check_opaque_types<'fcx, 'tcx>( .struct_span_err( span, "non-defining opaque type use \ - in defining scope", + in defining scope", ) .span_label( param_span, "cannot use static lifetime; use a bound lifetime \ - instead or remove the lifetime parameter from the \ - opaque type", + instead or remove the lifetime parameter from the \ + opaque type", ) .emit(); } else { @@ -904,13 +921,13 @@ fn check_opaque_types<'fcx, 'tcx>( .struct_span_err( span, "non-defining opaque type use \ - in defining scope", + in defining scope", ) .span_note( tcx.def_span(param.def_id), &format!( "used non-generic const {} for \ - generic parameter", + generic parameter", ty, ), ) @@ -925,7 +942,7 @@ fn check_opaque_types<'fcx, 'tcx>( .struct_span_err( span, "non-defining opaque type use \ - in defining scope", + in defining scope", ) .span_note(spans, "lifetime used multiple times") .emit(); @@ -1011,7 +1028,7 @@ fn check_method_receiver<'fcx, 'tcx>( span, &format!( "`{}` cannot be used as the type of `self` without \ - the `arbitrary_self_types` feature", + the `arbitrary_self_types` feature", receiver_ty, ), ) diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 380e256c9fc9a..65f81ef033dd7 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -4,18 +4,18 @@ use crate::check::FnCtxt; -use rustc::hir::map::Map; use rustc::ty::adjustment::{Adjust, Adjustment, PointerCast}; use rustc::ty::fold::{TypeFoldable, TypeFolder}; use rustc::ty::{self, Ty, TyCtxt}; use rustc_data_structures::sync::Lrc; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, DefIdSet, DefIndex}; +use rustc_hir::def_id::DefIdSet; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc_infer::infer::InferCtxt; use rustc_span::symbol::sym; use rustc_span::Span; +use rustc_trait_selection::opaque_types::InferCtxtExt; use std::mem; @@ -61,7 +61,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { wbcx.visit_fru_field_types(); wbcx.visit_opaque_types(body.value.span); wbcx.visit_coercion_casts(); - wbcx.visit_free_region_map(); wbcx.visit_user_provided_tys(); wbcx.visit_user_provided_sigs(); wbcx.visit_generator_interior_types(); @@ -108,11 +107,11 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { body: &'tcx hir::Body<'tcx>, rustc_dump_user_substs: bool, ) -> WritebackCx<'cx, 'tcx> { - let owner = body.id().hir_id; + let owner = body.id().hir_id.owner; WritebackCx { fcx, - tables: ty::TypeckTables::empty(Some(DefId::local(owner.owner))), + tables: ty::TypeckTables::empty(Some(owner)), body, rustc_dump_user_substs, } @@ -124,7 +123,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fn write_ty_to_tables(&mut self, hir_id: hir::HirId, ty: Ty<'tcx>) { debug!("write_ty_to_tables({:?}, {:?})", hir_id, ty); - assert!(!ty.needs_infer() && !ty.has_placeholders()); + assert!(!ty.needs_infer() && !ty.has_placeholders() && !ty.has_free_regions()); self.tables.node_types_mut().insert(hir_id, ty); } @@ -243,9 +242,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { // traffic in node-ids or update tables in the type context etc. impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } @@ -326,9 +325,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let new_upvar_capture = match *upvar_capture { ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue, ty::UpvarCapture::ByRef(ref upvar_borrow) => { - let r = upvar_borrow.region; - let r = self.resolve(&r, &upvar_id.var_path.hir_id); - ty::UpvarCapture::ByRef(ty::UpvarBorrow { kind: upvar_borrow.kind, region: r }) + ty::UpvarCapture::ByRef(ty::UpvarBorrow { + kind: upvar_borrow.kind, + region: self.tcx().lifetimes.re_erased, + }) } }; debug!("Upvar capture for {:?} resolved to {:?}", upvar_id, new_upvar_capture); @@ -338,11 +338,11 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fn visit_closures(&mut self) { let fcx_tables = self.fcx.tables.borrow(); - debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root); - let common_local_id_root = fcx_tables.local_id_root.unwrap(); + assert_eq!(fcx_tables.hir_owner, self.tables.hir_owner); + let common_hir_owner = fcx_tables.hir_owner.unwrap(); for (&id, &origin) in fcx_tables.closure_kind_origins().iter() { - let hir_id = hir::HirId { owner: common_local_id_root.index, local_id: id }; + let hir_id = hir::HirId { owner: common_hir_owner, local_id: id }; self.tables.closure_kind_origins_mut().insert(hir_id, origin); } } @@ -350,26 +350,21 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fn visit_coercion_casts(&mut self) { let fcx_tables = self.fcx.tables.borrow(); let fcx_coercion_casts = fcx_tables.coercion_casts(); - debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root); + assert_eq!(fcx_tables.hir_owner, self.tables.hir_owner); for local_id in fcx_coercion_casts { self.tables.set_coercion_cast(*local_id); } } - fn visit_free_region_map(&mut self) { - self.tables.free_region_map = self.fcx.tables.borrow().free_region_map.clone(); - debug_assert!(!self.tables.free_region_map.elements().any(|r| r.has_local_value())); - } - fn visit_user_provided_tys(&mut self) { let fcx_tables = self.fcx.tables.borrow(); - debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root); - let common_local_id_root = fcx_tables.local_id_root.unwrap(); + assert_eq!(fcx_tables.hir_owner, self.tables.hir_owner); + let common_hir_owner = fcx_tables.hir_owner.unwrap(); let mut errors_buffer = Vec::new(); for (&local_id, c_ty) in fcx_tables.user_provided_types().iter() { - let hir_id = hir::HirId { owner: common_local_id_root.index, local_id }; + let hir_id = hir::HirId { owner: common_hir_owner, local_id }; if cfg!(debug_assertions) && c_ty.has_local_value() { span_bug!(hir_id.to_span(self.fcx.tcx), "writeback: `{:?}` is a local value", c_ty); @@ -402,7 +397,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fn visit_user_provided_sigs(&mut self) { let fcx_tables = self.fcx.tables.borrow(); - debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root); + assert_eq!(fcx_tables.hir_owner, self.tables.hir_owner); for (&def_id, c_sig) in fcx_tables.user_provided_sigs.iter() { if cfg!(debug_assertions) && c_sig.has_local_value() { @@ -419,15 +414,14 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fn visit_generator_interior_types(&mut self) { let fcx_tables = self.fcx.tables.borrow(); - debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root); + assert_eq!(fcx_tables.hir_owner, self.tables.hir_owner); self.tables.generator_interior_types = fcx_tables.generator_interior_types.clone(); } fn visit_opaque_types(&mut self, span: Span) { for (&def_id, opaque_defn) in self.fcx.opaque_types.borrow().iter() { let hir_id = self.tcx().hir().as_local_hir_id(def_id).unwrap(); - let instantiated_ty = - self.tcx().erase_regions(&self.resolve(&opaque_defn.concrete_ty, &hir_id)); + let instantiated_ty = self.resolve(&opaque_defn.concrete_ty, &hir_id); debug_assert!(!instantiated_ty.has_escaping_bound_vars()); @@ -559,11 +553,11 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fn visit_liberated_fn_sigs(&mut self) { let fcx_tables = self.fcx.tables.borrow(); - debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root); - let common_local_id_root = fcx_tables.local_id_root.unwrap(); + assert_eq!(fcx_tables.hir_owner, self.tables.hir_owner); + let common_hir_owner = fcx_tables.hir_owner.unwrap(); for (&local_id, fn_sig) in fcx_tables.liberated_fn_sigs().iter() { - let hir_id = hir::HirId { owner: common_local_id_root.index, local_id }; + let hir_id = hir::HirId { owner: common_hir_owner, local_id }; let fn_sig = self.resolve(fn_sig, &hir_id); self.tables.liberated_fn_sigs_mut().insert(hir_id, fn_sig.clone()); } @@ -571,11 +565,11 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fn visit_fru_field_types(&mut self) { let fcx_tables = self.fcx.tables.borrow(); - debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root); - let common_local_id_root = fcx_tables.local_id_root.unwrap(); + assert_eq!(fcx_tables.hir_owner, self.tables.hir_owner); + let common_hir_owner = fcx_tables.hir_owner.unwrap(); for (&local_id, ftys) in fcx_tables.fru_field_types().iter() { - let hir_id = hir::HirId { owner: common_local_id_root.index, local_id }; + let hir_id = hir::HirId { owner: common_hir_owner, local_id }; let ftys = self.resolve(ftys, &hir_id); self.tables.fru_field_types_mut().insert(hir_id, ftys); } @@ -603,23 +597,14 @@ impl Locatable for Span { } } -impl Locatable for DefIndex { - fn to_span(&self, tcx: TyCtxt<'_>) -> Span { - let hir_id = tcx.hir().def_index_to_hir_id(*self); - tcx.hir().span(hir_id) - } -} - impl Locatable for hir::HirId { fn to_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.hir().span(*self) } } -/////////////////////////////////////////////////////////////////////////// -// The Resolver. This is the type folding engine that detects -// unresolved types and so forth. - +/// The Resolver. This is the type folding engine that detects +/// unresolved types and so forth. struct Resolver<'cx, 'tcx> { tcx: TyCtxt<'tcx>, infcx: &'cx InferCtxt<'cx, 'tcx>, @@ -652,7 +637,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> { fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { match self.infcx.fully_resolve(&t) { - Ok(t) => t, + Ok(t) => self.infcx.tcx.erase_regions(&t), Err(_) => { debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t); self.report_error(t); @@ -661,15 +646,14 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> { } } - // FIXME This should be carefully checked - // We could use `self.report_error` but it doesn't accept a ty::Region, right now. fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - self.infcx.fully_resolve(&r).unwrap_or(self.tcx.lifetimes.re_static) + debug_assert!(!r.is_late_bound(), "Should not be resolving bound region."); + self.tcx.lifetimes.re_erased } fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { match self.infcx.fully_resolve(&ct) { - Ok(ct) => ct, + Ok(ct) => self.infcx.tcx.erase_regions(&ct), Err(_) => { debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct); // FIXME: we'd like to use `self.report_error`, but it doesn't yet diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index 3517e09133c28..d0414af5b2138 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -1,4 +1,3 @@ -use crate::lint; use rustc::ty::TyCtxt; use rustc_ast::ast; use rustc_data_structures::fx::FxHashMap; @@ -7,6 +6,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::print::visibility_qualified; +use rustc_session::lint; use rustc_span::Span; pub fn check_crate(tcx: TyCtxt<'_>) { diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index aa39a191b3df6..c71f2331759b0 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -12,10 +12,11 @@ use rustc_hir::def_id::DefId; use rustc_hir::ItemKind; use rustc_infer::infer; use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::{SuppressRegionErrors, TyCtxtInferExt}; -use rustc_infer::traits::misc::{can_type_implement_copy, CopyImplementationError}; -use rustc_infer::traits::predicate_for_trait_def; -use rustc_infer::traits::{self, ObligationCause, TraitEngine}; +use rustc_infer::infer::{RegionckMode, TyCtxtInferExt}; +use rustc_trait_selection::traits::error_reporting::InferCtxtExt; +use rustc_trait_selection::traits::misc::{can_type_implement_copy, CopyImplementationError}; +use rustc_trait_selection::traits::predicate_for_trait_def; +use rustc_trait_selection::traits::{self, ObligationCause, TraitEngine, TraitEngineExt}; pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) { let lang_items = tcx.lang_items(); @@ -177,10 +178,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: DefId) { use ty::TyKind::*; match (&source.kind, &target.kind) { (&Ref(r_a, _, mutbl_a), Ref(r_b, _, mutbl_b)) - if infcx.at(&cause, param_env).eq(r_a, r_b).is_ok() && mutbl_a == *mutbl_b => - { - () - } + if infcx.at(&cause, param_env).eq(r_a, r_b).is_ok() && mutbl_a == *mutbl_b => {} (&RawPtr(tm_a), &RawPtr(tm_b)) if tm_a.mutbl == tm_b.mutbl => (), (&Adt(def_a, substs_a), &Adt(def_b, substs_b)) if def_a.is_struct() && def_b.is_struct() => @@ -217,7 +215,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: DefId) { let ty_b = field.ty(tcx, substs_b); if let Ok(layout) = tcx.layout_of(param_env.and(ty_a)) { - if layout.is_zst() && layout.details.align.abi.bytes() == 1 { + if layout.is_zst() && layout.align.abi.bytes() == 1 { // ignore ZST fields with alignment of 1 byte return None; } @@ -306,7 +304,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: DefId) { impl_did, ®ion_scope_tree, &outlives_env, - SuppressRegionErrors::default(), + RegionckMode::default(), ); } } @@ -322,7 +320,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: DefId) { } } -pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedInfo { +pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedInfo { debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did); let coerce_unsized_trait = tcx.lang_items().coerce_unsized_trait().unwrap(); @@ -567,7 +565,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn impl_did, ®ion_scope_tree, &outlives_env, - SuppressRegionErrors::default(), + RegionckMode::default(), ); CoerceUnsizedInfo { custom_kind: kind } diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs index 60e5df68b5842..c6ee9ab60abf3 100644 --- a/src/librustc_typeck/coherence/inherent_impls.rs +++ b/src/librustc_typeck/coherence/inherent_impls.rs @@ -272,9 +272,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { item.span, ); } - ty::Error => { - return; - } + ty::Error => {} _ => { struct_span_err!( self.tcx.sess, @@ -288,7 +286,6 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { to wrap it instead", ) .emit(); - return; } } } diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs index 778eee3586b4b..7513759c76b01 100644 --- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs +++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs @@ -3,7 +3,7 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; -use rustc_infer::traits::{self, SkipLeakCheck}; +use rustc_trait_selection::traits::{self, SkipLeakCheck}; pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, crate_num: CrateNum) { assert_eq!(crate_num, LOCAL_CRATE); @@ -26,7 +26,8 @@ impl InherentOverlapChecker<'tcx> { let collision = impl_items2.filter_by_name_unhygienic(item1.ident.name).any(|item2| { // Symbols and namespace match, compare hygienically. item1.kind.namespace() == item2.kind.namespace() - && item1.ident.modern() == item2.ident.modern() + && item1.ident.normalize_to_macros_2_0() + == item2.ident.normalize_to_macros_2_0() }); if collision { @@ -50,11 +51,12 @@ impl InherentOverlapChecker<'tcx> { let collision = impl_items2.filter_by_name_unhygienic(item1.ident.name).find(|item2| { // Symbols and namespace match, compare hygienically. item1.kind.namespace() == item2.kind.namespace() - && item1.ident.modern() == item2.ident.modern() + && item1.ident.normalize_to_macros_2_0() + == item2.ident.normalize_to_macros_2_0() }); if let Some(item2) = collision { - let name = item1.ident.modern(); + let name = item1.ident.normalize_to_macros_2_0(); let mut err = struct_span_err!( self.tcx.sess, self.tcx.span_of_impl(item1.def_id).unwrap(), diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index d24ee5f156bcf..6ed4f62c4bea2 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -9,8 +9,8 @@ use rustc::ty::query::Providers; use rustc::ty::{self, TyCtxt, TypeFoldable}; use rustc_errors::struct_span_err; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; -use rustc_infer::traits; use rustc_span::Span; +use rustc_trait_selection::traits; mod builtin; mod inherent_impls; @@ -20,7 +20,7 @@ mod unsafety; /// Obtains the span of just the impl header of `impl_def_id`. fn impl_header_span(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Span { - tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap()) + tcx.sess.source_map().guess_head_span(tcx.span_of_impl(impl_def_id).unwrap()) } fn check_impl(tcx: TyCtxt<'_>, impl_def_id: DefId, trait_ref: ty::TraitRef<'_>) { @@ -76,6 +76,22 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt<'_>, impl_def_id: DefId, tra return; } + if let ty::trait_def::TraitSpecializationKind::AlwaysApplicable = + tcx.trait_def(trait_def_id).specialization_kind + { + if !tcx.features().specialization && !tcx.features().min_specialization { + let span = impl_header_span(tcx, impl_def_id); + tcx.sess + .struct_span_err( + span, + "implementing `rustc_specialization_trait` traits is unstable", + ) + .help("add `#![feature(min_specialization)]` to the crate attributes to enable") + .emit(); + return; + } + } + let trait_name = if did == li.fn_trait() { "Fn" } else if did == li.fn_mut_trait() { diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 0a57449357324..cc0ad364177a0 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -6,7 +6,7 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits; +use rustc_trait_selection::traits; pub fn check(tcx: TyCtxt<'_>) { let mut orphan = OrphanChecker { tcx }; @@ -34,7 +34,7 @@ impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> { let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap(); let trait_def_id = trait_ref.def_id; let sm = self.tcx.sess.source_map(); - let sp = sm.def_span(item.span); + let sp = sm.guess_head_span(item.span); match traits::orphan_check(self.tcx, def_id) { Ok(()) => {} Err(traits::OrphanCheckErr::NonLocalInputType(tys)) => { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index cd63dacdcda0e..42cd7246f086e 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -17,14 +17,12 @@ use crate::astconv::{AstConv, Bounds, SizedByDefault}; use crate::check::intrinsic::intrinsic_operation_unsafety; use crate::constrained_generic_params as cgp; -use crate::lint; use crate::middle::lang_items; use crate::middle::resolve_lifetime as rl; use rustc::hir::map::blocks::FnLikeNode; use rustc::hir::map::Map; use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc::mir::mono::Linkage; -use rustc::session::parse::feature_err; use rustc::ty::query::Providers; use rustc::ty::subst::{InternalSubsts, Subst}; use rustc::ty::util::Discr; @@ -42,6 +40,8 @@ use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{GenericParamKind, Node, Unsafety}; +use rustc_session::lint; +use rustc_session::parse::feature_err; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi; @@ -105,9 +105,9 @@ pub struct ItemCtxt<'tcx> { crate struct PlaceholderHirTyCollector(crate Vec); impl<'v> Visitor<'v> for PlaceholderHirTyCollector { - type Map = Map<'v>; + type Map = intravisit::ErasedMap<'v>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } fn visit_ty(&mut self, t: &'v hir::Ty<'v>) { @@ -162,8 +162,10 @@ crate fn placeholder_type_error( // `struct S(T);` instead of `struct S<_, T>(T);`. sugg.push((arg.span, (*type_name).to_string())); } else { + let last = generics.iter().last().unwrap(); sugg.push(( - generics.iter().last().unwrap().span.shrink_to_hi(), + // Account for bounds, we want `fn foo(_: K)` not `fn foo(_: K)`. + last.bounds_span().unwrap_or(last.span).shrink_to_hi(), format!(", {}", type_name), )); } @@ -201,8 +203,8 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { @@ -745,7 +747,7 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::HirId) { tcx.predicates_of(def_id); let impl_item = tcx.hir().expect_impl_item(impl_item_id); match impl_item.kind { - hir::ImplItemKind::Method(..) => { + hir::ImplItemKind::Fn(..) => { tcx.fn_sig(def_id); } hir::ImplItemKind::TyAlias(_) | hir::ImplItemKind::OpaqueTy(_) => { @@ -828,7 +830,7 @@ fn convert_variant( .iter() .map(|f| { let fid = tcx.hir().local_def_id(f.hir_id); - let dup_span = seen_fields.get(&f.ident.modern()).cloned(); + let dup_span = seen_fields.get(&f.ident.normalize_to_macros_2_0()).cloned(); if let Some(prev_span) = dup_span { struct_span_err!( tcx.sess, @@ -841,7 +843,7 @@ fn convert_variant( .span_label(prev_span, format!("`{}` first declared here", f.ident)) .emit(); } else { - seen_fields.insert(f.ident.modern(), f.span); + seen_fields.insert(f.ident.normalize_to_macros_2_0(), f.span); } ty::FieldDef { @@ -1032,8 +1034,23 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TraitDef { } let is_marker = tcx.has_attr(def_id, sym::marker); + let spec_kind = if tcx.has_attr(def_id, sym::rustc_unsafe_specialization_marker) { + ty::trait_def::TraitSpecializationKind::Marker + } else if tcx.has_attr(def_id, sym::rustc_specialization_trait) { + ty::trait_def::TraitSpecializationKind::AlwaysApplicable + } else { + ty::trait_def::TraitSpecializationKind::None + }; let def_path_hash = tcx.def_path_hash(def_id); - let def = ty::TraitDef::new(def_id, unsafety, paren_sugar, is_auto, is_marker, def_path_hash); + let def = ty::TraitDef::new( + def_id, + unsafety, + paren_sugar, + is_auto, + is_marker, + spec_kind, + def_path_hash, + ); tcx.arena.alloc(def) } @@ -1045,9 +1062,9 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option for LateBoundRegionsDetector<'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } @@ -1127,7 +1144,7 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option None, }, Node::ImplItem(item) => match item.kind { - hir::ImplItemKind::Method(ref sig, _) => { + hir::ImplItemKind::Fn(ref sig, _) => { has_late_bound_regions(tcx, &item.generics, &sig.decl) } _ => None, @@ -1291,47 +1308,67 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { // Now create the real type and const parameters. let type_start = own_start - has_self as u32 + params.len() as u32; let mut i = 0; - params.extend(ast_generics.params.iter().filter_map(|param| { - let kind = match param.kind { - GenericParamKind::Type { ref default, synthetic, .. } => { - if !allow_defaults && default.is_some() { - if !tcx.features().default_type_parameter_fallback { - tcx.struct_span_lint_hir( - lint::builtin::INVALID_TYPE_PARAM_DEFAULT, - param.hir_id, - param.span, - |lint| { - lint.build( - "defaults for type parameters are only allowed in \ - `struct`, `enum`, `type`, or `trait` definitions.", - ) - .emit(); - }, - ); - } - } - ty::GenericParamDefKind::Type { - has_default: default.is_some(), - object_lifetime_default: object_lifetime_defaults - .as_ref() - .map_or(rl::Set1::Empty, |o| o[i]), - synthetic, + // FIXME(const_generics): a few places in the compiler expect generic params + // to be in the order lifetimes, then type params, then const params. + // + // To prevent internal errors in case const parameters are supplied before + // type parameters we first add all type params, then all const params. + params.extend(ast_generics.params.iter().filter_map(|param| { + if let GenericParamKind::Type { ref default, synthetic, .. } = param.kind { + if !allow_defaults && default.is_some() { + if !tcx.features().default_type_parameter_fallback { + tcx.struct_span_lint_hir( + lint::builtin::INVALID_TYPE_PARAM_DEFAULT, + param.hir_id, + param.span, + |lint| { + lint.build( + "defaults for type parameters are only allowed in \ + `struct`, `enum`, `type`, or `trait` definitions.", + ) + .emit(); + }, + ); } } - GenericParamKind::Const { .. } => ty::GenericParamDefKind::Const, - _ => return None, - }; - let param_def = ty::GenericParamDef { - index: type_start + i as u32, - name: param.name.ident().name, - def_id: tcx.hir().local_def_id(param.hir_id), - pure_wrt_drop: param.pure_wrt_drop, - kind, - }; - i += 1; - Some(param_def) + let kind = ty::GenericParamDefKind::Type { + has_default: default.is_some(), + object_lifetime_default: object_lifetime_defaults + .as_ref() + .map_or(rl::Set1::Empty, |o| o[i]), + synthetic, + }; + + let param_def = ty::GenericParamDef { + index: type_start + i as u32, + name: param.name.ident().name, + def_id: tcx.hir().local_def_id(param.hir_id), + pure_wrt_drop: param.pure_wrt_drop, + kind, + }; + i += 1; + Some(param_def) + } else { + None + } + })); + + params.extend(ast_generics.params.iter().filter_map(|param| { + if let GenericParamKind::Const { .. } = param.kind { + let param_def = ty::GenericParamDef { + index: type_start + i as u32, + name: param.name.ident().name, + def_id: tcx.hir().local_def_id(param.hir_id), + pure_wrt_drop: param.pure_wrt_drop, + kind: ty::GenericParamDefKind::Const, + }; + i += 1; + Some(param_def) + } else { + None + } })); // provide junk type parameter defs - the only place that @@ -1339,9 +1376,9 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { // and we don't do that for closures. if let Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(.., gen), .. }) = node { let dummy_args = if gen.is_some() { - &["", "", "", ""][..] + &["", "", "", "", ""][..] } else { - &["", ""][..] + &["", "", ""][..] }; params.extend(dummy_args.iter().enumerate().map(|(i, &arg)| ty::GenericParamDef { @@ -1355,22 +1392,6 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { synthetic: None, }, })); - - if let Some(upvars) = tcx.upvars(def_id) { - params.extend(upvars.iter().zip((dummy_args.len() as u32)..).map(|(_, i)| { - ty::GenericParamDef { - index: type_start + i, - name: Symbol::intern(""), - def_id, - pure_wrt_drop: false, - kind: ty::GenericParamDefKind::Type { - has_default: false, - object_lifetime_default: rl::Set1::Empty, - synthetic: None, - }, - } - })); - } } let param_def_id_to_index = params.iter().map(|param| (param.def_id, param.index)).collect(); @@ -1437,12 +1458,12 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { match tcx.hir().get(hir_id) { TraitItem(hir::TraitItem { - kind: TraitItemKind::Fn(sig, TraitMethod::Provided(_)), + kind: TraitItemKind::Fn(sig, TraitFn::Provided(_)), ident, generics, .. }) - | ImplItem(hir::ImplItem { kind: ImplItemKind::Method(sig, _), ident, generics, .. }) + | ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), ident, generics, .. }) | Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), ident, .. }) => { match get_infer_ret_ty(&sig.decl.output) { Some(ty) => { @@ -1467,7 +1488,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { sig.header.unsafety, sig.header.abi, &sig.decl, - &generics.params[..], + &generics, Some(ident.span), ), } @@ -1478,18 +1499,17 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { ident, generics, .. - }) => AstConv::ty_of_fn( - &icx, - header.unsafety, - header.abi, - decl, - &generics.params[..], - Some(ident.span), - ), - - ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(ref fn_decl, _, _), .. }) => { + }) => { + AstConv::ty_of_fn(&icx, header.unsafety, header.abi, decl, &generics, Some(ident.span)) + } + + ForeignItem(&hir::ForeignItem { + kind: ForeignItemKind::Fn(ref fn_decl, _, _), + ident, + .. + }) => { let abi = tcx.hir().get_foreign_abi(hir_id); - compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi) + compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi, ident) } Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor_hir_id().is_some() => { @@ -1512,16 +1532,13 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { // argument. In any case they are embedded within the // closure type as part of the `ClosureSubsts`. // - // To get - // the signature of a closure, you should use the - // `closure_sig` method on the `ClosureSubsts`: - // - // closure_substs.sig(def_id, tcx) + // To get the signature of a closure, you should use the + // `sig` method on the `ClosureSubsts`: // - // or, inside of an inference context, you can use - // - // infcx.closure_sig(def_id, closure_substs) - bug!("to get the signature of a closure, use `closure_sig()` not `fn_sig()`"); + // substs.as_closure().sig(def_id, tcx) + bug!( + "to get the signature of a closure, use `substs.as_closure().sig()` not `fn_sig()`", + ); } x => { @@ -1548,9 +1565,10 @@ 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 { polarity: hir::ImplPolarity::Negative(_), .. } => { + hir::ItemKind::Impl { polarity: hir::ImplPolarity::Negative(span), of_trait, .. } => { if is_rustc_reservation { - tcx.sess.span_err(item.span, "reservation impls can't be negative"); + let span = span.to(of_trait.as_ref().map(|t| t.path.span).unwrap_or(*span)); + tcx.sess.span_err(span, "reservation impls can't be negative"); } ty::ImplPolarity::Negative } @@ -2104,13 +2122,21 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( def_id: DefId, decl: &'tcx hir::FnDecl<'tcx>, abi: abi::Abi, + ident: Ident, ) -> ty::PolyFnSig<'tcx> { let unsafety = if abi == abi::Abi::RustIntrinsic { intrinsic_operation_unsafety(&tcx.item_name(def_id).as_str()) } else { hir::Unsafety::Unsafe }; - let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), unsafety, abi, decl, &[], None); + let fty = AstConv::ty_of_fn( + &ItemCtxt::new(tcx, def_id), + unsafety, + abi, + decl, + &hir::Generics::empty(), + Some(ident.span), + ); // Feature gate SIMD types in FFI, since I am not sure that the // ABIs are handled at all correctly. -huonw @@ -2307,6 +2333,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { let attrs = tcx.get_attrs(id); let mut codegen_fn_attrs = CodegenFnAttrs::new(); + if should_inherit_track_caller(tcx, id) { + codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER; + } let whitelist = tcx.target_features_whitelist(LOCAL_CRATE); @@ -2551,6 +2580,32 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { codegen_fn_attrs } +/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller +/// applied to the method prototype. +fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool { + if let Some(impl_item) = tcx.opt_associated_item(def_id) { + if let ty::AssocItemContainer::ImplContainer(impl_def_id) = impl_item.container { + if let Some(trait_def_id) = tcx.trait_id_of_impl(impl_def_id) { + if let Some(trait_item) = tcx + .associated_items(trait_def_id) + .filter_by_name_unhygienic(impl_item.ident.name) + .find(move |trait_item| { + trait_item.kind == ty::AssocKind::Method + && tcx.hygienic_eq(impl_item.ident, trait_item.ident, trait_def_id) + }) + { + return tcx + .codegen_fn_attrs(trait_item.def_id) + .flags + .intersects(CodegenFnAttrFlags::TRACK_CALLER); + } + } + } + } + + false +} + fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option { use rustc_ast::ast::{Lit, LitIntType, LitKind}; let meta_item_list = attr.meta_item_list(); diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs index 815235adc7175..30741ed53b58b 100644 --- a/src/librustc_typeck/collect/type_of.rs +++ b/src/librustc_typeck/collect/type_of.rs @@ -1,5 +1,4 @@ use rustc::hir::map::Map; -use rustc::session::parse::feature_err; use rustc::ty::subst::{GenericArgKind, InternalSubsts, Subst}; use rustc::ty::util::IntTypeExt; use rustc::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; @@ -11,9 +10,10 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit; use rustc_hir::intravisit::Visitor; use rustc_hir::Node; -use rustc_infer::traits; +use rustc_session::parse::feature_err; use rustc_span::symbol::{sym, Ident}; use rustc_span::{Span, DUMMY_SP}; +use rustc_trait_selection::traits; use super::ItemCtxt; use super::{bad_placeholder_type, is_suggestable_infer_ty}; @@ -47,7 +47,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { }, Node::ImplItem(item) => match item.kind { - ImplItemKind::Method(..) => { + ImplItemKind::Fn(..) => { let substs = InternalSubsts::identity_for_item(tcx, def_id); tcx.mk_fn_def(def_id, substs) } @@ -188,12 +188,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { Node::Field(field) => icx.to_ty(&field.ty), Node::Expr(&Expr { kind: ExprKind::Closure(.., gen), .. }) => { - if gen.is_some() { - return tcx.typeck_tables_of(def_id).node_type(hir_id); - } - let substs = InternalSubsts::identity_for_item(tcx, def_id); - tcx.mk_closure(def_id, substs) + if let Some(movability) = gen { + tcx.mk_generator(def_id, substs, movability) + } else { + tcx.mk_closure(def_id, substs) + } } Node::AnonConst(_) => { @@ -235,36 +235,41 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { }; if let Some(path) = path { - let arg_index = path + // We've encountered an `AnonConst` in some path, so we need to + // figure out which generic parameter it corresponds to and return + // the relevant type. + + let (arg_index, segment) = path .segments .iter() - .filter_map(|seg| seg.args.as_ref()) - .map(|generic_args| generic_args.args) - .find_map(|args| { + .filter_map(|seg| seg.args.as_ref().map(|args| (args.args, seg))) + .find_map(|(args, seg)| { args.iter() .filter(|arg| arg.is_const()) .enumerate() .filter(|(_, arg)| arg.id() == hir_id) - .map(|(index, _)| index) + .map(|(index, _)| (index, seg)) .next() }) .unwrap_or_else(|| { bug!("no arg matching AnonConst in path"); }); - // We've encountered an `AnonConst` in some path, so we need to - // figure out which generic parameter it corresponds to and return - // the relevant type. - let generics = match path.res { + // Try to use the segment resolution if it is valid, otherwise we + // default to the path resolution. + let res = segment.res.filter(|&r| r != Res::Err).unwrap_or(path.res); + let generics = match res { Res::Def(DefKind::Ctor(..), def_id) => { tcx.generics_of(tcx.parent(def_id).unwrap()) } Res::Def(_, def_id) => tcx.generics_of(def_id), - Res::Err => return tcx.types.err, res => { tcx.sess.delay_span_bug( DUMMY_SP, - &format!("unexpected const parent path def {:?}", res,), + &format!( + "unexpected anon const res {:?} in path: {:?}", + res, path, + ), ); return tcx.types.err; } @@ -284,13 +289,22 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { .map(|param| tcx.type_of(param.def_id)) // This is no generic parameter associated with the arg. This is // probably from an extra arg where one is not needed. - .unwrap_or(tcx.types.err) + .unwrap_or_else(|| { + tcx.sess.delay_span_bug( + DUMMY_SP, + &format!( + "missing generic parameter for `AnonConst`, parent: {:?}, res: {:?}", + parent_node, res + ), + ); + tcx.types.err + }) } else { tcx.sess.delay_span_bug( DUMMY_SP, &format!("unexpected const parent path {:?}", parent_node,), ); - return tcx.types.err; + tcx.types.err } } @@ -529,8 +543,8 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { impl<'tcx> intravisit::Visitor<'tcx> for ConstraintLocator<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { - intravisit::NestedVisitorMap::All(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { + intravisit::NestedVisitorMap::All(self.tcx.hir()) } fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) { if let hir::ExprKind::Closure(..) = ex.kind { diff --git a/src/librustc_typeck/constrained_generic_params.rs b/src/librustc_typeck/constrained_generic_params.rs index aff3768e35c55..b16aa6ff3b2e4 100644 --- a/src/librustc_typeck/constrained_generic_params.rs +++ b/src/librustc_typeck/constrained_generic_params.rs @@ -79,10 +79,18 @@ impl<'tcx> TypeVisitor<'tcx> for ParameterCollector { } fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool { - if let ty::ConstKind::Param(data) = c.val { - self.parameters.push(Parameter::from(data)); + match c.val { + ty::ConstKind::Unevaluated(..) if !self.include_nonconstraining => { + // Constant expressions are not injective + return c.ty.visit_with(self); + } + ty::ConstKind::Param(data) => { + self.parameters.push(Parameter::from(data)); + } + _ => {} } - false + + c.super_visit_with(self) } } diff --git a/src/librustc_typeck/expr_use_visitor.rs b/src/librustc_typeck/expr_use_visitor.rs index 6666b1699943e..a45d8ce6823a3 100644 --- a/src/librustc_typeck/expr_use_visitor.rs +++ b/src/librustc_typeck/expr_use_visitor.rs @@ -519,7 +519,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { for &var_id in upvars.keys() { let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { hir_id: var_id }, - closure_expr_id: closure_def_id.to_local(), + closure_expr_id: closure_def_id.expect_local(), }; let upvar_capture = self.mc.tables.upvar_capture(upvar_id); let captured_place = return_if_err!(self.cat_captured_var( diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index 0a765a1f9c93c..42cb4fcf85dcb 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -9,6 +9,8 @@ //! fixed, but for the moment it's easier to do these checks early. use crate::constrained_generic_params as cgp; +use min_specialization::check_min_specialization; + use rustc::ty::query::Providers; use rustc::ty::{self, TyCtxt, TypeFoldable}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -16,9 +18,11 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::itemlikevisit::ItemLikeVisitor; +use rustc_span::Span; + use std::collections::hash_map::Entry::{Occupied, Vacant}; -use rustc_span::Span; +mod min_specialization; /// Checks that all the type/lifetime parameters on an impl also /// appear in the trait ref or self type (or are constrained by a @@ -60,7 +64,9 @@ pub fn impl_wf_check(tcx: TyCtxt<'_>) { } fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: DefId) { - tcx.hir().visit_item_likes_in_module(module_def_id, &mut ImplWfCheck { tcx }); + let min_specialization = tcx.features().min_specialization; + tcx.hir() + .visit_item_likes_in_module(module_def_id, &mut ImplWfCheck { tcx, min_specialization }); } pub fn provide(providers: &mut Providers<'_>) { @@ -69,6 +75,7 @@ pub fn provide(providers: &mut Providers<'_>) { struct ImplWfCheck<'tcx> { tcx: TyCtxt<'tcx>, + min_specialization: bool, } impl ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> { @@ -77,6 +84,9 @@ impl ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> { let impl_def_id = self.tcx.hir().local_def_id(item.hir_id); enforce_impl_params_are_constrained(self.tcx, impl_def_id, items); enforce_impl_items_are_distinct(self.tcx, items); + if self.min_specialization { + check_min_specialization(self.tcx, impl_def_id, item.span); + } } } @@ -227,7 +237,7 @@ fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_item_refs: &[hir::ImplI hir::ImplItemKind::TyAlias(_) => &mut seen_type_items, _ => &mut seen_value_items, }; - match seen_items.entry(impl_item.ident.modern()) { + match seen_items.entry(impl_item.ident.normalize_to_macros_2_0()) { Occupied(entry) => { let mut err = struct_span_err!( tcx.sess, diff --git a/src/librustc_typeck/impl_wf_check/min_specialization.rs b/src/librustc_typeck/impl_wf_check/min_specialization.rs new file mode 100644 index 0000000000000..ef94500f5c444 --- /dev/null +++ b/src/librustc_typeck/impl_wf_check/min_specialization.rs @@ -0,0 +1,409 @@ +//! # Minimal Specialization +//! +//! This module contains the checks for sound specialization used when the +//! `min_specialization` feature is enabled. This requires that the impl is +//! *always applicable*. +//! +//! If `impl1` specializes `impl2` then `impl1` is always applicable if we know +//! that all the bounds of `impl2` are satisfied, and all of the bounds of +//! `impl1` are satisfied for some choice of lifetimes then we know that +//! `impl1` applies for any choice of lifetimes. +//! +//! ## Basic approach +//! +//! To enforce this requirement on specializations we take the following +//! approach: +//! +//! 1. Match up the substs for `impl2` so that the implemented trait and +//! self-type match those for `impl1`. +//! 2. Check for any direct use of `'static` in the substs of `impl2`. +//! 3. Check that all of the generic parameters of `impl1` occur at most once +//! in the *unconstrained* substs for `impl2`. A parameter is constrained if +//! its value is completely determined by an associated type projection +//! predicate. +//! 4. Check that all predicates on `impl1` either exist on `impl2` (after +//! matching substs), or are well-formed predicates for the trait's type +//! arguments. +//! +//! ## Example +//! +//! Suppose we have the following always applicable impl: +//! +//! ```rust +//! impl SpecExtend for std::vec::IntoIter { /* specialized impl */ } +//! impl> SpecExtend for I { /* default impl */ } +//! ``` +//! +//! We get that the subst for `impl2` are `[T, std::vec::IntoIter]`. `T` is +//! constrained to be `::Item`, so we check only +//! `std::vec::IntoIter` for repeated parameters, which it doesn't have. The +//! predicates of `impl1` are only `T: Sized`, which is also a predicate of +//! `impl2`. So this specialization is sound. +//! +//! ## Extensions +//! +//! Unfortunately not all specializations in the standard library are allowed +//! by this. So there are two extensions to these rules that allow specializing +//! on some traits: that is, using them as bounds on the specializing impl, +//! even when they don't occur in the base impl. +//! +//! ### rustc_specialization_trait +//! +//! If a trait is always applicable, then it's sound to specialize on it. We +//! check trait is always applicable in the same way as impls, except that step +//! 4 is now "all predicates on `impl1` are always applicable". We require that +//! `specialization` or `min_specialization` is enabled to implement these +//! traits. +//! +//! ### rustc_unsafe_specialization_marker +//! +//! There are also some specialization on traits with no methods, including the +//! stable `FusedIterator` trait. We allow marking marker traits with an +//! unstable attribute that means we ignore them in point 3 of the checks +//! above. This is unsound, in the sense that the specialized impl may be used +//! when it doesn't apply, but we allow it in the short term since it can't +//! cause use after frees with purely safe code in the same way as specializing +//! on traits with methods can. + +use crate::constrained_generic_params as cgp; + +use rustc::middle::region::ScopeTree; +use rustc::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; +use rustc::ty::trait_def::TraitSpecializationKind; +use rustc::ty::{self, InstantiatedPredicates, TyCtxt, TypeFoldable}; +use rustc_data_structures::fx::FxHashSet; +use rustc_hir as hir; +use rustc_hir::def_id::DefId; +use rustc_infer::infer::outlives::env::OutlivesEnvironment; +use rustc_infer::infer::{InferCtxt, RegionckMode, TyCtxtInferExt}; +use rustc_infer::traits::specialization_graph::Node; +use rustc_span::Span; +use rustc_trait_selection::traits::{self, translate_substs, wf}; + +pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: DefId, span: Span) { + if let Some(node) = parent_specialization_node(tcx, impl_def_id) { + tcx.infer_ctxt().enter(|infcx| { + check_always_applicable(&infcx, impl_def_id, node, span); + }); + } +} + +fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: DefId) -> Option { + let trait_ref = tcx.impl_trait_ref(impl1_def_id)?; + let trait_def = tcx.trait_def(trait_ref.def_id); + + let impl2_node = trait_def.ancestors(tcx, impl1_def_id).ok()?.nth(1)?; + + let always_applicable_trait = + matches!(trait_def.specialization_kind, TraitSpecializationKind::AlwaysApplicable); + if impl2_node.is_from_trait() && !always_applicable_trait { + // Implementing a normal trait isn't a specialization. + return None; + } + Some(impl2_node) +} + +/// Check that `impl1` is a sound specialization +fn check_always_applicable( + infcx: &InferCtxt<'_, '_>, + impl1_def_id: DefId, + impl2_node: Node, + span: Span, +) { + if let Some((impl1_substs, impl2_substs)) = + get_impl_substs(infcx, impl1_def_id, impl2_node, span) + { + let impl2_def_id = impl2_node.def_id(); + debug!( + "check_always_applicable(\nimpl1_def_id={:?},\nimpl2_def_id={:?},\nimpl2_substs={:?}\n)", + impl1_def_id, impl2_def_id, impl2_substs + ); + + let tcx = infcx.tcx; + + let parent_substs = if impl2_node.is_from_trait() { + impl2_substs.to_vec() + } else { + unconstrained_parent_impl_substs(tcx, impl2_def_id, impl2_substs) + }; + + check_static_lifetimes(tcx, &parent_substs, span); + check_duplicate_params(tcx, impl1_substs, &parent_substs, span); + + check_predicates(infcx, impl1_def_id, impl1_substs, impl2_node, impl2_substs, span); + } +} + +/// Given a specializing impl `impl1`, and the base impl `impl2`, returns two +/// substitutions `(S1, S2)` that equate their trait references. The returned +/// types are expressed in terms of the generics of `impl1`. +/// +/// Example +/// +/// impl Foo for B { /* impl2 */ } +/// impl Foo> for C { /* impl1 */ } +/// +/// Would return `S1 = [C]` and `S2 = [Vec, C]`. +fn get_impl_substs<'tcx>( + infcx: &InferCtxt<'_, 'tcx>, + impl1_def_id: DefId, + impl2_node: Node, + span: Span, +) -> Option<(SubstsRef<'tcx>, SubstsRef<'tcx>)> { + let tcx = infcx.tcx; + let param_env = tcx.param_env(impl1_def_id); + + let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id); + let impl2_substs = translate_substs(infcx, param_env, impl1_def_id, impl1_substs, impl2_node); + + // Conservatively use an empty `ParamEnv`. + let outlives_env = OutlivesEnvironment::new(ty::ParamEnv::empty()); + infcx.resolve_regions_and_report_errors( + impl1_def_id, + &ScopeTree::default(), + &outlives_env, + RegionckMode::default(), + ); + let impl2_substs = match infcx.fully_resolve(&impl2_substs) { + Ok(s) => s, + Err(_) => { + tcx.sess.struct_span_err(span, "could not resolve substs on overridden impl").emit(); + return None; + } + }; + Some((impl1_substs, impl2_substs)) +} + +/// Returns a list of all of the unconstrained subst of the given impl. +/// +/// For example given the impl: +/// +/// impl<'a, T, I> ... where &'a I: IntoIterator +/// +/// This would return the substs corresponding to `['a, I]`, because knowing +/// `'a` and `I` determines the value of `T`. +fn unconstrained_parent_impl_substs<'tcx>( + tcx: TyCtxt<'tcx>, + impl_def_id: DefId, + impl_substs: SubstsRef<'tcx>, +) -> Vec> { + let impl_generic_predicates = tcx.predicates_of(impl_def_id); + let mut unconstrained_parameters = FxHashSet::default(); + let mut constrained_params = FxHashSet::default(); + let impl_trait_ref = tcx.impl_trait_ref(impl_def_id); + + // Unfortunately the functions in `constrained_generic_parameters` don't do + // what we want here. We want only a list of constrained parameters while + // the functions in `cgp` add the constrained parameters to a list of + // unconstrained parameters. + for (predicate, _) in impl_generic_predicates.predicates.iter() { + if let ty::Predicate::Projection(proj) = predicate { + let projection_ty = proj.skip_binder().projection_ty; + let projected_ty = proj.skip_binder().ty; + + let unbound_trait_ref = projection_ty.trait_ref(tcx); + if Some(unbound_trait_ref) == impl_trait_ref { + continue; + } + + unconstrained_parameters.extend(cgp::parameters_for(&projection_ty, true)); + + for param in cgp::parameters_for(&projected_ty, false) { + if !unconstrained_parameters.contains(¶m) { + constrained_params.insert(param.0); + } + } + + unconstrained_parameters.extend(cgp::parameters_for(&projected_ty, true)); + } + } + + impl_substs + .iter() + .enumerate() + .filter(|&(idx, _)| !constrained_params.contains(&(idx as u32))) + .map(|(_, arg)| *arg) + .collect() +} + +/// Check that parameters of the derived impl don't occur more than once in the +/// equated substs of the base impl. +/// +/// For example forbid the following: +/// +/// impl Tr for A { } +/// impl Tr for (B, B) { } +/// +/// Note that only consider the unconstrained parameters of the base impl: +/// +/// impl> Tr for I { } +/// impl Tr for Vec { } +/// +/// The substs for the parent impl here are `[T, Vec]`, which repeats `T`, +/// but `S` is constrained in the parent impl, so `parent_substs` is only +/// `[Vec]`. This means we allow this impl. +fn check_duplicate_params<'tcx>( + tcx: TyCtxt<'tcx>, + impl1_substs: SubstsRef<'tcx>, + parent_substs: &Vec>, + span: Span, +) { + let mut base_params = cgp::parameters_for(parent_substs, true); + base_params.sort_by_key(|param| param.0); + if let (_, [duplicate, ..]) = base_params.partition_dedup() { + let param = impl1_substs[duplicate.0 as usize]; + tcx.sess + .struct_span_err(span, &format!("specializing impl repeats parameter `{}`", param)) + .emit(); + } +} + +/// Check that `'static` lifetimes are not introduced by the specializing impl. +/// +/// For example forbid the following: +/// +/// impl Tr for A { } +/// impl Tr for &'static i32 { } +fn check_static_lifetimes<'tcx>( + tcx: TyCtxt<'tcx>, + parent_substs: &Vec>, + span: Span, +) { + if tcx.any_free_region_meets(parent_substs, |r| *r == ty::ReStatic) { + tcx.sess.struct_span_err(span, "cannot specialize on `'static` lifetime").emit(); + } +} + +/// Check whether predicates on the specializing impl (`impl1`) are allowed. +/// +/// Each predicate `P` must be: +/// +/// * global (not reference any parameters) +/// * `T: Tr` predicate where `Tr` is an always-applicable trait +/// * on the base `impl impl2` +/// * Currently this check is done using syntactic equality, which is +/// conservative but generally sufficient. +/// * a well-formed predicate of a type argument of the trait being implemented, +/// including the `Self`-type. +fn check_predicates<'tcx>( + infcx: &InferCtxt<'_, 'tcx>, + impl1_def_id: DefId, + impl1_substs: SubstsRef<'tcx>, + impl2_node: Node, + impl2_substs: SubstsRef<'tcx>, + span: Span, +) { + let tcx = infcx.tcx; + let impl1_predicates = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs); + let mut impl2_predicates = if impl2_node.is_from_trait() { + // Always applicable traits have to be always applicable without any + // assumptions. + InstantiatedPredicates::empty() + } else { + tcx.predicates_of(impl2_node.def_id()).instantiate(tcx, impl2_substs) + }; + debug!( + "check_always_applicable(\nimpl1_predicates={:?},\nimpl2_predicates={:?}\n)", + impl1_predicates, impl2_predicates, + ); + + // Since impls of always applicable traits don't get to assume anything, we + // can also assume their supertraits apply. + // + // For example, we allow: + // + // #[rustc_specialization_trait] + // trait AlwaysApplicable: Debug { } + // + // impl Tr for T { } + // impl Tr for T { } + // + // Specializing on `AlwaysApplicable` allows also specializing on `Debug` + // which is sound because we forbid impls like the following + // + // impl AlwaysApplicable for D { } + let always_applicable_traits: Vec<_> = impl1_predicates + .predicates + .iter() + .filter(|predicate| { + matches!( + trait_predicate_kind(tcx, predicate), + Some(TraitSpecializationKind::AlwaysApplicable) + ) + }) + .copied() + .collect(); + + // Include the well-formed predicates of the type parameters of the impl. + for ty in tcx.impl_trait_ref(impl1_def_id).unwrap().substs.types() { + if let Some(obligations) = wf::obligations( + infcx, + tcx.param_env(impl1_def_id), + tcx.hir().as_local_hir_id(impl1_def_id).unwrap(), + ty, + span, + ) { + impl2_predicates + .predicates + .extend(obligations.into_iter().map(|obligation| obligation.predicate)) + } + } + impl2_predicates.predicates.extend(traits::elaborate_predicates(tcx, always_applicable_traits)); + + for predicate in impl1_predicates.predicates { + if !impl2_predicates.predicates.contains(&predicate) { + check_specialization_on(tcx, &predicate, span) + } + } +} + +fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: &ty::Predicate<'tcx>, span: Span) { + debug!("can_specialize_on(predicate = {:?})", predicate); + match predicate { + // Global predicates are either always true or always false, so we + // are fine to specialize on. + _ if predicate.is_global() => (), + // We allow specializing on explicitly marked traits with no associated + // items. + ty::Predicate::Trait(pred, hir::Constness::NotConst) => { + if !matches!( + trait_predicate_kind(tcx, predicate), + Some(TraitSpecializationKind::Marker) + ) { + tcx.sess + .struct_span_err( + span, + &format!( + "cannot specialize on trait `{}`", + tcx.def_path_str(pred.def_id()), + ), + ) + .emit() + } + } + _ => tcx + .sess + .struct_span_err(span, &format!("cannot specialize on `{:?}`", predicate)) + .emit(), + } +} + +fn trait_predicate_kind<'tcx>( + tcx: TyCtxt<'tcx>, + predicate: &ty::Predicate<'tcx>, +) -> Option { + match predicate { + ty::Predicate::Trait(pred, hir::Constness::NotConst) => { + Some(tcx.trait_def(pred.def_id()).specialization_kind) + } + ty::Predicate::Trait(_, hir::Constness::Const) + | ty::Predicate::RegionOutlives(_) + | ty::Predicate::TypeOutlives(_) + | ty::Predicate::Projection(_) + | ty::Predicate::WellFormed(_) + | ty::Predicate::Subtype(_) + | ty::Predicate::ObjectSafe(_) + | ty::Predicate::ClosureKind(..) + | ty::Predicate::ConstEvaluatable(..) => None, + } +} diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index c5f339d6b7648..fd854c750184e 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -62,8 +62,10 @@ This API is completely unstable and subject to change. #![feature(crate_visibility_modifier)] #![feature(in_band_lifetimes)] #![feature(nll)] +#![feature(or_patterns)] #![feature(try_blocks)] #![feature(never_type)] +#![feature(slice_partition_dedup)] #![recursion_limit = "256"] #[macro_use] @@ -87,10 +89,7 @@ mod outlives; mod structured_errors; mod variance; -use rustc::lint; use rustc::middle; -use rustc::session; -use rustc::session::config::EntryFnType; use rustc::ty::query::Providers; use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TyCtxt}; @@ -101,9 +100,14 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::Node; use rustc_infer::infer::{InferOk, TyCtxtInferExt}; -use rustc_infer::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt}; +use rustc_infer::traits::TraitEngineExt as _; +use rustc_session::config::EntryFnType; use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; +use rustc_trait_selection::traits::{ + ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt as _, +}; use std::iter; diff --git a/src/librustc_typeck/mem_categorization.rs b/src/librustc_typeck/mem_categorization.rs index 8e06948a10953..7d8bf71cf97b7 100644 --- a/src/librustc_typeck/mem_categorization.rs +++ b/src/librustc_typeck/mem_categorization.rs @@ -59,6 +59,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::PatKind; use rustc_infer::infer::InferCtxt; use rustc_span::Span; +use rustc_trait_selection::infer::InferCtxtExt; #[derive(Clone, Debug)] pub enum PlaceBase { @@ -469,7 +470,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { hir_id: var_id }, - closure_expr_id: closure_expr_def_id.to_local(), + closure_expr_id: closure_expr_def_id.expect_local(), }; let var_ty = self.node_ty(var_id)?; diff --git a/src/librustc_typeck/outlives/utils.rs b/src/librustc_typeck/outlives/utils.rs index 0cc322f8c2d3d..e1bd78e5113d1 100644 --- a/src/librustc_typeck/outlives/utils.rs +++ b/src/librustc_typeck/outlives/utils.rs @@ -170,7 +170,6 @@ fn is_free_region(tcx: TyCtxt<'_>, region: Region<'_>) -> bool { // These regions don't appear in types from type declarations: RegionKind::ReErased - | RegionKind::ReClosureBound(..) | RegionKind::ReScope(..) | RegionKind::ReVar(..) | RegionKind::RePlaceholder(..) diff --git a/src/librustc_typeck/structured_errors.rs b/src/librustc_typeck/structured_errors.rs index 99b7b2001a9e9..a4f8472ae2891 100644 --- a/src/librustc_typeck/structured_errors.rs +++ b/src/librustc_typeck/structured_errors.rs @@ -1,6 +1,6 @@ -use rustc::session::Session; use rustc::ty::{Ty, TypeFoldable}; use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId}; +use rustc_session::Session; use rustc_span::Span; pub trait StructuredDiagnostic<'tcx> { diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index fc3b7201a1e63..11612066d44b2 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -111,7 +111,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> { } fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) { - if let hir::ImplItemKind::Method(..) = impl_item.kind { + if let hir::ImplItemKind::Fn(..) = impl_item.kind { self.visit_node_helper(impl_item.hir_id); } } @@ -449,7 +449,6 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } ty::ReFree(..) - | ty::ReClosureBound(..) | ty::ReScope(..) | ty::ReVar(..) | ty::RePlaceholder(..) diff --git a/src/librustc_typeck/variance/mod.rs b/src/librustc_typeck/variance/mod.rs index b1fcc3d3fe8f9..3cbb42bb5f309 100644 --- a/src/librustc_typeck/variance/mod.rs +++ b/src/librustc_typeck/variance/mod.rs @@ -60,7 +60,7 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[ty::Variance] { }, Node::ImplItem(item) => match item.kind { - hir::ImplItemKind::Method(..) => {} + hir::ImplItemKind::Fn(..) => {} _ => unsupported(), }, diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs index bd44a3eda98ce..7e6ec96b379d8 100644 --- a/src/librustc_typeck/variance/terms.rs +++ b/src/librustc_typeck/variance/terms.rs @@ -170,7 +170,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> { } fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) { - if let hir::ImplItemKind::Method(..) = impl_item.kind { + if let hir::ImplItemKind::Fn(..) = impl_item.kind { self.add_inferreds_for_item(impl_item.hir_id); } } diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 407b50382fa37..c85b21a55007f 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -1,7 +1,7 @@ use rustc::ty::{self, Region, RegionVid, TypeFoldable}; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; -use rustc_infer::traits::auto_trait::{self, AutoTraitResult}; +use rustc_trait_selection::traits::auto_trait::{self, AutoTraitResult}; use std::fmt::Debug; diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 4a1e2570d06c5..e66f869771794 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -1,3 +1,4 @@ +use crate::rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc::ty::subst::Subst; use rustc::ty::{ToPredicate, WithConstness}; use rustc_hir as hir; diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 775d600fc3d4b..57d499e38a77b 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -360,6 +360,7 @@ impl<'a> fmt::Display for Html<'a> { "fuchsia" => "Fuchsia", "haiku" => "Haiku", "hermit" => "HermitCore", + "illumos" => "illumos", "ios" => "iOS", "l4re" => "L4Re", "linux" => "Linux", diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index f600b3308e882..153f7af9f97ca 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -41,11 +41,7 @@ pub fn try_inline( attrs: Option>, visited: &mut FxHashSet, ) -> Option> { - let did = if let Some(did) = res.opt_def_id() { - did - } else { - return None; - }; + let did = res.opt_def_id()?; if did.is_local() { return None; } @@ -578,7 +574,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean: name: ref _name, }, ref bounds, - } => !(*s == "Self" && did == trait_did) && !bounds.is_empty(), + } => !(bounds.is_empty() || *s == "Self" && did == trait_did), _ => true, }); g diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 661666b6637f1..7dfcf0a637eb3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -141,6 +141,7 @@ impl Clean for CrateNum { cx.tcx .hir() .krate() + .item .module .item_ids .iter() @@ -194,6 +195,7 @@ impl Clean for CrateNum { cx.tcx .hir() .krate() + .item .module .item_ids .iter() @@ -448,7 +450,6 @@ impl Clean> for ty::RegionKind { | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReEmpty(_) - | ty::ReClosureBound(_) | ty::ReErased => { debug!("cannot clean region {:?}", self); None @@ -1076,16 +1077,36 @@ impl Clean for hir::PolyTraitRef<'_> { } } +impl Clean for hir::def::DefKind { + fn clean(&self, _: &DocContext<'_>) -> TypeKind { + match *self { + hir::def::DefKind::Mod => TypeKind::Module, + hir::def::DefKind::Struct => TypeKind::Struct, + hir::def::DefKind::Union => TypeKind::Union, + hir::def::DefKind::Enum => TypeKind::Enum, + hir::def::DefKind::Trait => TypeKind::Trait, + hir::def::DefKind::TyAlias => TypeKind::Typedef, + hir::def::DefKind::ForeignTy => TypeKind::Foreign, + hir::def::DefKind::TraitAlias => TypeKind::TraitAlias, + hir::def::DefKind::Fn => TypeKind::Function, + hir::def::DefKind::Const => TypeKind::Const, + hir::def::DefKind::Static => TypeKind::Static, + hir::def::DefKind::Macro(_) => TypeKind::Macro, + _ => TypeKind::Foreign, + } + } +} + impl Clean for hir::TraitItem<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { let inner = match self.kind { hir::TraitItemKind::Const(ref ty, default) => { AssocConstItem(ty.clean(cx), default.map(|e| print_const_expr(cx, e))) } - hir::TraitItemKind::Fn(ref sig, hir::TraitMethod::Provided(body)) => { + hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { MethodItem((sig, &self.generics, body, None).clean(cx)) } - hir::TraitItemKind::Fn(ref sig, hir::TraitMethod::Required(ref names)) => { + hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(ref names)) => { let (generics, decl) = enter_impl_trait(cx, || { (self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx)) }); @@ -1116,7 +1137,7 @@ impl Clean for hir::ImplItem<'_> { hir::ImplItemKind::Const(ref ty, expr) => { AssocConstItem(ty.clean(cx), Some(print_const_expr(cx, expr))) } - hir::ImplItemKind::Method(ref sig, body) => { + hir::ImplItemKind::Fn(ref sig, body) => { MethodItem((sig, &self.generics, body, Some(self.defaultness)).clean(cx)) } hir::ImplItemKind::TyAlias(ref ty) => { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index b1aa094204a1e..73f2c399e5698 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -836,8 +836,8 @@ pub struct Method { pub decl: FnDecl, pub header: hir::FnHeader, pub defaultness: Option, - pub all_types: Vec, - pub ret_types: Vec, + pub all_types: Vec<(Type, TypeKind)>, + pub ret_types: Vec<(Type, TypeKind)>, } #[derive(Clone, Debug)] @@ -845,8 +845,8 @@ pub struct TyMethod { pub header: hir::FnHeader, pub decl: FnDecl, pub generics: Generics, - pub all_types: Vec, - pub ret_types: Vec, + pub all_types: Vec<(Type, TypeKind)>, + pub ret_types: Vec<(Type, TypeKind)>, } #[derive(Clone, Debug)] @@ -854,8 +854,8 @@ pub struct Function { pub decl: FnDecl, pub generics: Generics, pub header: hir::FnHeader, - pub all_types: Vec, - pub ret_types: Vec, + pub all_types: Vec<(Type, TypeKind)>, + pub ret_types: Vec<(Type, TypeKind)>, } #[derive(Clone, PartialEq, Eq, Debug, Hash)] @@ -1042,7 +1042,7 @@ pub enum PrimitiveType { Never, } -#[derive(Clone, Copy, Debug)] +#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)] pub enum TypeKind { Enum, Function, diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 21e3d24cc968b..82e34710f0cbf 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -184,7 +184,7 @@ pub fn get_real_types( arg: &Type, cx: &DocContext<'_>, recurse: i32, -) -> FxHashSet { +) -> FxHashSet<(Type, TypeKind)> { let arg_s = arg.print().to_string(); let mut res = FxHashSet::default(); if recurse >= 10 { @@ -209,7 +209,11 @@ pub fn get_real_types( if !adds.is_empty() { res.extend(adds); } else if !ty.is_full_generic() { - res.insert(ty); + if let Some(did) = ty.def_id() { + if let Some(kind) = cx.tcx.def_kind(did).clean(cx) { + res.insert((ty, kind)); + } + } } } } @@ -225,13 +229,21 @@ pub fn get_real_types( if !adds.is_empty() { res.extend(adds); } else if !ty.is_full_generic() { - res.insert(ty.clone()); + if let Some(did) = ty.def_id() { + if let Some(kind) = cx.tcx.def_kind(did).clean(cx) { + res.insert((ty.clone(), kind)); + } + } } } } } } else { - res.insert(arg.clone()); + if let Some(did) = arg.def_id() { + if let Some(kind) = cx.tcx.def_kind(did).clean(cx) { + res.insert((arg.clone(), kind)); + } + } if let Some(gens) = arg.generics() { for gen in gens.iter() { if gen.is_full_generic() { @@ -239,8 +251,10 @@ pub fn get_real_types( if !adds.is_empty() { res.extend(adds); } - } else { - res.insert(gen.clone()); + } else if let Some(did) = gen.def_id() { + if let Some(kind) = cx.tcx.def_kind(did).clean(cx) { + res.insert((gen.clone(), kind)); + } } } } @@ -256,7 +270,7 @@ pub fn get_all_types( generics: &Generics, decl: &FnDecl, cx: &DocContext<'_>, -) -> (Vec, Vec) { +) -> (Vec<(Type, TypeKind)>, Vec<(Type, TypeKind)>) { let mut all_types = FxHashSet::default(); for arg in decl.inputs.values.iter() { if arg.type_.is_self_type() { @@ -266,7 +280,11 @@ pub fn get_all_types( if !args.is_empty() { all_types.extend(args); } else { - all_types.insert(arg.type_.clone()); + if let Some(did) = arg.type_.def_id() { + if let Some(kind) = cx.tcx.def_kind(did).clean(cx) { + all_types.insert((arg.type_.clone(), kind)); + } + } } } @@ -274,7 +292,11 @@ pub fn get_all_types( FnRetTy::Return(ref return_type) => { let mut ret = get_real_types(generics, &return_type, cx, 0); if ret.is_empty() { - ret.insert(return_type.clone()); + if let Some(did) = return_type.def_id() { + if let Some(kind) = cx.tcx.def_kind(did).clean(cx) { + ret.insert((return_type.clone(), kind)); + } + } } ret.into_iter().collect() } @@ -485,7 +507,7 @@ pub fn print_const(cx: &DocContext<'_>, n: &'tcx ty::Const<'_>) -> String { } pub fn print_evaluated_const(cx: &DocContext<'_>, def_id: DefId) -> Option { - let value = cx.tcx.const_eval_poly(def_id).ok().and_then(|val| { + cx.tcx.const_eval_poly(def_id).ok().and_then(|val| { let ty = cx.tcx.type_of(def_id); match (val, &ty.kind) { (_, &ty::Ref(..)) => None, @@ -496,9 +518,7 @@ pub fn print_evaluated_const(cx: &DocContext<'_>, def_id: DefId) -> Option None, } - }); - - value + }) } fn format_integer_with_underscore_sep(num: &str) -> String { diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 58c8a7d82bfb5..179c5bfacf32e 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -4,15 +4,14 @@ use std::ffi::OsStr; use std::fmt; use std::path::PathBuf; -use rustc::lint::Level; -use rustc::session; -use rustc::session::config::{ +use rustc_session::config::{self, parse_crate_types_from_list, parse_externs, CrateType}; +use rustc_session::config::{ build_codegen_options, build_debugging_options, get_cmd_lint_options, host_triple, nightly_options, }; -use rustc::session::config::{parse_crate_types_from_list, parse_externs, CrateType}; -use rustc::session::config::{CodegenOptions, DebuggingOptions, ErrorOutputType, Externs}; -use rustc::session::search_paths::SearchPath; +use rustc_session::config::{CodegenOptions, DebuggingOptions, ErrorOutputType, Externs}; +use rustc_session::lint::Level; +use rustc_session::search_paths::SearchPath; use rustc_span::edition::{Edition, DEFAULT_EDITION}; use rustc_target::spec::TargetTriple; @@ -299,9 +298,9 @@ impl Options { return Err(0); } - let color = session::config::parse_color(&matches); - let (json_rendered, _artifacts) = session::config::parse_json(&matches); - let error_format = session::config::parse_error_format(&matches, color, json_rendered); + let color = config::parse_color(&matches); + let (json_rendered, _artifacts) = config::parse_json(&matches); + let error_format = config::parse_error_format(&matches, color, json_rendered); let codegen_options = build_codegen_options(matches, error_format); let debugging_options = build_debugging_options(matches, error_format); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index b9ae3d53afc04..f0b9ad2852f51 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -1,23 +1,22 @@ use rustc::middle::cstore::CrateStore; use rustc::middle::privacy::AccessLevels; -use rustc::session::config::ErrorOutputType; -use rustc::session::DiagnosticOutput; -use rustc::session::{self, config}; use rustc::ty::{Ty, TyCtxt}; +use rustc_ast::ast::CRATE_NODE_ID; +use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_driver::abort_on_err; +use rustc_errors::emitter::{Emitter, EmitterWriter}; +use rustc_errors::json::JsonEmitter; use rustc_feature::UnstableFeatures; use rustc_hir::def::Namespace::TypeNS; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; use rustc_hir::HirId; use rustc_interface::interface; use rustc_resolve as resolve; +use rustc_session::config::ErrorOutputType; use rustc_session::lint; - -use rustc_ast::ast::CRATE_NODE_ID; -use rustc_attr as attr; -use rustc_errors::emitter::{Emitter, EmitterWriter}; -use rustc_errors::json::JsonEmitter; +use rustc_session::DiagnosticOutput; +use rustc_session::{config, Session}; use rustc_span::source_map; use rustc_span::symbol::sym; use rustc_span::DUMMY_SP; @@ -34,8 +33,8 @@ use crate::html::render::RenderInfo; use crate::passes::{self, Condition::*, ConditionalPass}; -pub use rustc::session::config::{CodegenOptions, DebuggingOptions, Input, Options}; -pub use rustc::session::search_paths::SearchPath; +pub use rustc_session::config::{CodegenOptions, DebuggingOptions, Input, Options}; +pub use rustc_session::search_paths::SearchPath; pub type ExternalPaths = FxHashMap, clean::TypeKind)>; @@ -68,7 +67,7 @@ pub struct DocContext<'tcx> { } impl<'tcx> DocContext<'tcx> { - pub fn sess(&self) -> &session::Session { + pub fn sess(&self) -> &Session { &self.tcx.sess } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 42529a6682ec1..e13bf270440e2 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -844,11 +844,7 @@ pub fn plain_summary_line(md: &str) -> String { type Item = String; fn next(&mut self) -> Option { - let next_event = self.inner.next(); - if next_event.is_none() { - return None; - } - let next_event = next_event.unwrap(); + let next_event = self.inner.next()?; let (ret, is_in) = match next_event { Event::Start(Tag::Paragraph) => (None, 1), Event::Start(Tag::Heading(_)) => (None, 1), @@ -870,7 +866,7 @@ pub fn plain_summary_line(md: &str) -> String { } let mut s = String::with_capacity(md.len() * 3 / 2); let p = ParserWrapper { inner: Parser::new(md), is_in: 0, is_first: true }; - p.into_iter().filter(|t| !t.is_empty()).for_each(|i| s.push_str(&i)); + p.filter(|t| !t.is_empty()).for_each(|i| s.push_str(&i)); s } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 2d1e3c29055cf..eb7a367acf439 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -44,7 +44,6 @@ use std::sync::Arc; use rustc::middle::privacy::AccessLevels; use rustc::middle::stability; -use rustc_ast::ast; use rustc_ast_pretty::pprust; use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -59,7 +58,7 @@ use rustc_span::symbol::{sym, Symbol}; use serde::ser::SerializeSeq; use serde::{Serialize, Serializer}; -use crate::clean::{self, AttributesExt, Deprecation, GetDefId, SelfTy}; +use crate::clean::{self, AttributesExt, Deprecation, GetDefId, SelfTy, TypeKind}; use crate::config::{OutputFormat, RenderOptions}; use crate::docfs::{DocFS, ErrorStorage, PathError}; use crate::doctree; @@ -303,19 +302,25 @@ impl Serialize for IndexItem { /// A type used for the search index. #[derive(Debug)] -struct Type { +struct RenderType { + ty: Option, + idx: Option, name: Option, - generics: Option>, + generics: Option>, } -impl Serialize for Type { +impl Serialize for RenderType { fn serialize(&self, serializer: S) -> Result where S: Serializer, { if let Some(name) = &self.name { let mut seq = serializer.serialize_seq(None)?; - seq.serialize_element(&name)?; + if let Some(id) = self.idx { + seq.serialize_element(&id)?; + } else { + seq.serialize_element(&name)?; + } if let Some(generics) = &self.generics { seq.serialize_element(&generics)?; } @@ -326,11 +331,32 @@ impl Serialize for Type { } } +/// A type used for the search index. +#[derive(Debug)] +struct Generic { + name: String, + defid: Option, + idx: Option, +} + +impl Serialize for Generic { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + if let Some(id) = self.idx { + serializer.serialize_some(&id) + } else { + serializer.serialize_some(&self.name) + } + } +} + /// Full type of functions/methods in the search index. #[derive(Debug)] struct IndexItemFunctionType { - inputs: Vec, - output: Option>, + inputs: Vec, + output: Option>, } impl Serialize for IndexItemFunctionType { @@ -341,8 +367,8 @@ impl Serialize for IndexItemFunctionType { // If we couldn't figure out a type, just write `null`. let mut iter = self.inputs.iter(); if match self.output { - Some(ref output) => iter.chain(output.iter()).any(|ref i| i.name.is_none()), - None => iter.any(|ref i| i.name.is_none()), + Some(ref output) => iter.chain(output.iter()).any(|ref i| i.ty.name.is_none()), + None => iter.any(|ref i| i.ty.name.is_none()), } { serializer.serialize_none() } else { @@ -360,6 +386,31 @@ impl Serialize for IndexItemFunctionType { } } +#[derive(Debug)] +pub struct TypeWithKind { + ty: RenderType, + kind: TypeKind, +} + +impl From<(RenderType, TypeKind)> for TypeWithKind { + fn from(x: (RenderType, TypeKind)) -> TypeWithKind { + TypeWithKind { ty: x.0, kind: x.1 } + } +} + +impl Serialize for TypeWithKind { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut seq = serializer.serialize_seq(None)?; + seq.serialize_element(&self.ty.name)?; + let x: ItemType = self.kind.into(); + seq.serialize_element(&x)?; + seq.end() + } +} + thread_local!(static CACHE_KEY: RefCell> = Default::default()); thread_local!(pub static CURRENT_DEPTH: Cell = Cell::new(0)); @@ -1543,7 +1594,7 @@ impl Context { } if self.shared.sort_modules_alphabetically { - for (_, items) in &mut map { + for items in map.values_mut() { items.sort(); } } @@ -3126,25 +3177,6 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum) { render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } -fn render_attribute(attr: &ast::MetaItem) -> Option { - let path = pprust::path_to_string(&attr.path); - - if attr.is_word() { - Some(path) - } else if let Some(v) = attr.value_str() { - Some(format!("{} = {:?}", path, v)) - } else if let Some(values) = attr.meta_item_list() { - let display: Vec<_> = values - .iter() - .filter_map(|attr| attr.meta_item().and_then(|mi| render_attribute(mi))) - .collect(); - - if !display.is_empty() { Some(format!("{}({})", path, display.join(", "))) } else { None } - } else { - None - } -} - const ATTRIBUTE_WHITELIST: &[Symbol] = &[ sym::export_name, sym::lang, @@ -3170,9 +3202,8 @@ fn render_attributes(w: &mut Buffer, it: &clean::Item, top: bool) { if !ATTRIBUTE_WHITELIST.contains(&attr.name_or_empty()) { continue; } - if let Some(s) = render_attribute(&attr.meta().unwrap()) { - attrs.push_str(&format!("#[{}]\n", s)); - } + + attrs.push_str(&pprust::attribute_to_string(&attr)); } if !attrs.is_empty() { write!( @@ -3396,10 +3427,8 @@ fn render_assoc_items( let deref_impl = traits.iter().find(|t| t.inner_impl().trait_.def_id() == c.deref_trait_did); if let Some(impl_) = deref_impl { - let has_deref_mut = traits - .iter() - .find(|t| t.inner_impl().trait_.def_id() == c.deref_mut_trait_did) - .is_some(); + let has_deref_mut = + traits.iter().any(|t| t.inner_impl().trait_.def_id() == c.deref_mut_trait_did); render_deref_methods(w, cx, impl_, containing_item, has_deref_mut); } @@ -3740,7 +3769,7 @@ fn render_impl( ) { for trait_item in &t.items { let n = trait_item.name.clone(); - if i.items.iter().find(|m| m.name == n).is_some() { + if i.items.iter().any(|m| m.name == n) { continue; } let did = i.trait_.as_ref().unwrap().def_id().unwrap(); diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 4198369eca8f5..b93738319a634 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -12,7 +12,7 @@ use std::path::{Path, PathBuf}; use serde::Serialize; use super::{plain_summary_line, shorten, Impl, IndexItem, IndexItemFunctionType, ItemType}; -use super::{RenderInfo, Type}; +use super::{Generic, RenderInfo, RenderType, TypeWithKind}; /// Indicates where an external crate can be found. pub enum ExternalLocation { @@ -588,17 +588,20 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { let mut lastpathid = 0usize; for item in search_index { - item.parent_idx = item.parent.map(|defid| { + item.parent_idx = item.parent.and_then(|defid| { if defid_to_pathid.contains_key(&defid) { - *defid_to_pathid.get(&defid).expect("no pathid") + defid_to_pathid.get(&defid).map(|x| *x) } else { let pathid = lastpathid; defid_to_pathid.insert(defid, pathid); lastpathid += 1; - let &(ref fqp, short) = paths.get(&defid).unwrap(); - crate_paths.push((short, fqp.last().unwrap().clone())); - pathid + if let Some(&(ref fqp, short)) = paths.get(&defid) { + crate_paths.push((short, fqp.last().unwrap().clone())); + Some(pathid) + } else { + None + } } }); @@ -647,24 +650,28 @@ fn get_index_search_type(item: &clean::Item) -> Option { _ => return None, }; - let inputs = - all_types.iter().map(|arg| get_index_type(&arg)).filter(|a| a.name.is_some()).collect(); + let inputs = all_types + .iter() + .map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty), *kind))) + .filter(|a| a.ty.name.is_some()) + .collect(); let output = ret_types .iter() - .map(|arg| get_index_type(&arg)) - .filter(|a| a.name.is_some()) + .map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty), *kind))) + .filter(|a| a.ty.name.is_some()) .collect::>(); let output = if output.is_empty() { None } else { Some(output) }; Some(IndexItemFunctionType { inputs, output }) } -fn get_index_type(clean_type: &clean::Type) -> Type { - let t = Type { +fn get_index_type(clean_type: &clean::Type) -> RenderType { + RenderType { + ty: clean_type.def_id(), + idx: None, name: get_index_type_name(clean_type, true).map(|s| s.to_ascii_lowercase()), generics: get_generics(clean_type), - }; - t + } } fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option { @@ -685,12 +692,17 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option } } -fn get_generics(clean_type: &clean::Type) -> Option> { +fn get_generics(clean_type: &clean::Type) -> Option> { clean_type.generics().and_then(|types| { let r = types .iter() - .filter_map(|t| get_index_type_name(t, false)) - .map(|s| s.to_ascii_lowercase()) + .filter_map(|t| { + if let Some(name) = get_index_type_name(t, false) { + Some(Generic { name: name.to_ascii_lowercase(), defid: t.def_id(), idx: None }) + } else { + None + } + }) .collect::>(); if r.is_empty() { None } else { Some(r) } }) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index a799aed698578..3f12fb893a440 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -523,13 +523,14 @@ function getSearchElement() { } function initSearch(rawSearchIndex) { - var currentResults, index, searchIndex; var MAX_LEV_DISTANCE = 3; var MAX_RESULTS = 200; var GENERICS_DATA = 1; var NAME = 0; var INPUTS_DATA = 0; var OUTPUT_DATA = 1; + var NO_TYPE_FILTER = -1; + var currentResults, index, searchIndex; var params = getQueryStringParams(); // Populate search bar with query string search term when provided, @@ -556,7 +557,7 @@ function getSearchElement() { return i; } } - return -1; + return NO_TYPE_FILTER; } var valLower = query.query.toLowerCase(), @@ -719,6 +720,13 @@ function getSearchElement() { }; } + function getObjectFromId(id) { + if (typeof id === "number") { + return searchIndex[id]; + } + return {'name': id}; + } + function checkGenerics(obj, val) { // The names match, but we need to be sure that all generics kinda // match as well. @@ -735,8 +743,10 @@ function getSearchElement() { for (var y = 0; y < vlength; ++y) { var lev = { pos: -1, lev: MAX_LEV_DISTANCE + 1}; var elength = elems.length; + var firstGeneric = getObjectFromId(val.generics[y]).name; for (var x = 0; x < elength; ++x) { - var tmp_lev = levenshtein(elems[x], val.generics[y]); + var tmp_lev = levenshtein(getObjectFromId(elems[x]).name, + firstGeneric); if (tmp_lev < lev.lev) { lev.lev = tmp_lev; lev.pos = x; @@ -771,8 +781,9 @@ function getSearchElement() { for (var y = 0; allFound === true && y < val.generics.length; ++y) { allFound = false; + var firstGeneric = getObjectFromId(val.generics[y]).name; for (x = 0; allFound === false && x < elems.length; ++x) { - allFound = elems[x] === val.generics[y]; + allFound = getObjectFromId(elems[x]).name === firstGeneric; } if (allFound === true) { elems.splice(x - 1, 1); @@ -829,16 +840,22 @@ function getSearchElement() { return lev_distance + 1; } - function findArg(obj, val, literalSearch) { + function findArg(obj, val, literalSearch, typeFilter) { var lev_distance = MAX_LEV_DISTANCE + 1; - if (obj && obj.type && obj.type[INPUTS_DATA] && - obj.type[INPUTS_DATA].length > 0) { + if (obj && obj.type && obj.type[INPUTS_DATA] && obj.type[INPUTS_DATA].length > 0) { var length = obj.type[INPUTS_DATA].length; for (var i = 0; i < length; i++) { - var tmp = checkType(obj.type[INPUTS_DATA][i], val, literalSearch); - if (literalSearch === true && tmp === true) { - return true; + var tmp = obj.type[INPUTS_DATA][i]; + if (typePassesFilter(typeFilter, tmp[1]) === false) { + continue; + } + tmp = checkType(tmp, val, literalSearch); + if (literalSearch === true) { + if (tmp === true) { + return true; + } + continue; } lev_distance = Math.min(tmp, lev_distance); if (lev_distance === 0) { @@ -849,20 +866,20 @@ function getSearchElement() { return literalSearch === true ? false : lev_distance; } - function checkReturned(obj, val, literalSearch) { + function checkReturned(obj, val, literalSearch, typeFilter) { var lev_distance = MAX_LEV_DISTANCE + 1; if (obj && obj.type && obj.type.length > OUTPUT_DATA) { var ret = obj.type[OUTPUT_DATA]; - if (!obj.type[OUTPUT_DATA].length) { + if (typeof ret[0] === "string") { ret = [ret]; } for (var x = 0; x < ret.length; ++x) { - var r = ret[x]; - if (typeof r === "string") { - r = [r]; + var tmp = ret[x]; + if (typePassesFilter(typeFilter, tmp[1]) === false) { + continue; } - var tmp = checkType(r, val, literalSearch); + tmp = checkType(tmp, val, literalSearch); if (literalSearch === true) { if (tmp === true) { return true; @@ -917,7 +934,7 @@ function getSearchElement() { function typePassesFilter(filter, type) { // No filter - if (filter < 0) return true; + if (filter <= NO_TYPE_FILTER) return true; // Exact match if (filter === type) return true; @@ -926,11 +943,13 @@ function getSearchElement() { var name = itemTypes[type]; switch (itemTypes[filter]) { case "constant": - return (name == "associatedconstant"); + return name === "associatedconstant"; case "fn": - return (name == "method" || name == "tymethod"); + return name === "method" || name === "tymethod"; case "type": - return (name == "primitive" || name == "keyword"); + return name === "primitive" || name === "associatedtype"; + case "trait": + return name === "traitalias"; } // No match @@ -959,42 +978,33 @@ function getSearchElement() { if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) { continue; } - in_args = findArg(searchIndex[i], val, true); - returned = checkReturned(searchIndex[i], val, true); + in_args = findArg(searchIndex[i], val, true, typeFilter); + returned = checkReturned(searchIndex[i], val, true, typeFilter); ty = searchIndex[i]; fullId = generateId(ty); - if (searchWords[i] === val.name) { - // filter type: ... queries - if (typePassesFilter(typeFilter, searchIndex[i].ty) && - results[fullId] === undefined) - { - results[fullId] = {id: i, index: -1}; - } - } else if ((in_args === true || returned === true) && - typePassesFilter(typeFilter, searchIndex[i].ty)) { - if (in_args === true || returned === true) { - if (in_args === true) { - results_in_args[fullId] = { - id: i, - index: -1, - dontValidate: true, - }; - } - if (returned === true) { - results_returned[fullId] = { - id: i, - index: -1, - dontValidate: true, - }; - } - } else { - results[fullId] = { - id: i, - index: -1, - dontValidate: true, - }; - } + if (searchWords[i] === val.name + && typePassesFilter(typeFilter, searchIndex[i].ty) + && results[fullId] === undefined) { + results[fullId] = { + id: i, + index: -1, + dontValidate: true, + }; + } + if (in_args === true && results_in_args[fullId] === undefined) { + results_in_args[fullId] = { + id: i, + index: -1, + dontValidate: true, + }; + } + if (returned === true && results_returned[fullId] === undefined) { + results_returned[fullId] = { + id: i, + index: -1, + dontValidate: true, + }; } } query.inputs = [val]; @@ -1025,7 +1035,7 @@ function getSearchElement() { // allow searching for void (no output) functions as well var typeOutput = type.length > OUTPUT_DATA ? type[OUTPUT_DATA].name : ""; - returned = checkReturned(ty, output, true); + returned = checkReturned(ty, output, true, NO_TYPE_FILTER); if (output.name === "*" || returned === true) { in_args = false; var is_module = false; @@ -1126,16 +1136,8 @@ function getSearchElement() { lev += 1; } } - if ((in_args = findArg(ty, valGenerics)) <= MAX_LEV_DISTANCE) { - if (typePassesFilter(typeFilter, ty.ty) === false) { - in_args = MAX_LEV_DISTANCE + 1; - } - } - if ((returned = checkReturned(ty, valGenerics)) <= MAX_LEV_DISTANCE) { - if (typePassesFilter(typeFilter, ty.ty) === false) { - returned = MAX_LEV_DISTANCE + 1; - } - } + in_args = findArg(ty, valGenerics, false, typeFilter); + returned = checkReturned(ty, valGenerics, false, typeFilter); lev += lev_add; if (lev > 0 && val.length > 3 && searchWords[j].indexOf(val) > -1) { diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index f05db6c218524..8887bca3c5962 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -1032,7 +1032,7 @@ h3 > .collapse-toggle, h4 > .collapse-toggle { .information { position: absolute; - left: -20px; + left: -25px; margin-top: 7px; z-index: 1; } @@ -1047,12 +1047,13 @@ h3 > .collapse-toggle, h4 > .collapse-toggle { width: 120px; display: none; text-align: center; - padding: 5px 3px; + padding: 5px 3px 3px 3px; border-radius: 6px; margin-left: 5px; top: -5px; left: 105%; z-index: 10; + font-size: 16px; } .tooltip:hover .tooltiptext { @@ -1063,14 +1064,20 @@ h3 > .collapse-toggle, h4 > .collapse-toggle { content: " "; position: absolute; top: 50%; - left: 11px; + left: 16px; margin-top: -5px; border-width: 5px; border-style: solid; } +.tooltip.compile_fail, .tooltip.ignore { + font-weight: bold; + font-size: 20px; +} + .tooltip .tooltiptext { border: 1px solid; + font-weight: normal; } pre.rust { diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index e7041d54c6bfd..ff32a0fa09e4d 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -254,7 +254,7 @@ a.test-arrow:hover{ } pre.compile_fail { - border-left: 2px solid rgba(255,0,0,.6); + border-left: 2px solid rgba(255,0,0,.8); } pre.compile_fail:hover, .information:hover + pre.compile_fail { @@ -270,7 +270,7 @@ pre.ignore:hover, .information:hover + pre.ignore { } .tooltip.compile_fail { - color: rgba(255,0,0,.6); + color: rgba(255,0,0,.8); } .information > .compile_fail:hover { @@ -282,7 +282,7 @@ pre.ignore:hover, .information:hover + pre.ignore { } .information > .ignore:hover { - color: rgba(255,142,0,1); + color: #ff9200; } .search-failed a { @@ -290,8 +290,9 @@ pre.ignore:hover, .information:hover + pre.ignore { } .tooltip .tooltiptext { - background-color: black; + background-color: #000; color: #fff; + border-color: #000; } .tooltip .tooltiptext::after { diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index a1efef6701fd1..2b2819f7126b4 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -248,7 +248,7 @@ a.test-arrow:hover{ } pre.compile_fail { - border-left: 2px solid rgba(255,0,0,.4); + border-left: 2px solid rgba(255,0,0,.5); } pre.compile_fail:hover, .information:hover + pre.compile_fail { @@ -256,7 +256,7 @@ pre.compile_fail:hover, .information:hover + pre.compile_fail { } pre.ignore { - border-left: 2px solid rgba(255,142,0,.4); + border-left: 2px solid rgba(255,142,0,.6); } pre.ignore:hover, .information:hover + pre.ignore { @@ -264,7 +264,7 @@ pre.ignore:hover, .information:hover + pre.ignore { } .tooltip.compile_fail { - color: rgba(255,0,0,.3); + color: rgba(255,0,0,.5); } .information > .compile_fail:hover { @@ -272,11 +272,11 @@ pre.ignore:hover, .information:hover + pre.ignore { } .tooltip.ignore { - color: rgba(255,142,0,.3); + color: rgba(255,142,0,.6); } .information > .ignore:hover { - color: rgba(255,142,0,1); + color: #ff9200; } .search-failed a { @@ -284,7 +284,7 @@ pre.ignore:hover, .information:hover + pre.ignore { } .tooltip .tooltiptext { - background-color: black; + background-color: #000; color: #fff; } diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs index 9fc1d76185fb7..6790f3bd5d0b1 100644 --- a/src/librustdoc/html/static_files.rs +++ b/src/librustdoc/html/static_files.rs @@ -8,106 +8,106 @@ //! directly written to a `Write` handle. /// The file contents of the main `rustdoc.css` file, responsible for the core layout of the page. -pub static RUSTDOC_CSS: &'static str = include_str!("static/rustdoc.css"); +pub static RUSTDOC_CSS: &str = include_str!("static/rustdoc.css"); /// The file contents of `settings.css`, responsible for the items on the settings page. -pub static SETTINGS_CSS: &'static str = include_str!("static/settings.css"); +pub static SETTINGS_CSS: &str = include_str!("static/settings.css"); /// The file contents of the `noscript.css` file, used in case JS isn't supported or is disabled. -pub static NOSCRIPT_CSS: &'static str = include_str!("static/noscript.css"); +pub static NOSCRIPT_CSS: &str = include_str!("static/noscript.css"); /// The file contents of `normalize.css`, included to even out standard elements between browser /// implementations. -pub static NORMALIZE_CSS: &'static str = include_str!("static/normalize.css"); +pub static NORMALIZE_CSS: &str = include_str!("static/normalize.css"); /// The file contents of `main.js`, which contains the core JavaScript used on documentation pages, /// including search behavior and docblock folding, among others. -pub static MAIN_JS: &'static str = include_str!("static/main.js"); +pub static MAIN_JS: &str = include_str!("static/main.js"); /// The file contents of `settings.js`, which contains the JavaScript used to handle the settings /// page. -pub static SETTINGS_JS: &'static str = include_str!("static/settings.js"); +pub static SETTINGS_JS: &str = include_str!("static/settings.js"); /// The file contents of `storage.js`, which contains functionality related to browser Local /// Storage, used to store documentation settings. -pub static STORAGE_JS: &'static str = include_str!("static/storage.js"); +pub static STORAGE_JS: &str = include_str!("static/storage.js"); /// The file contents of `brush.svg`, the icon used for the theme-switch button. -pub static BRUSH_SVG: &'static [u8] = include_bytes!("static/brush.svg"); +pub static BRUSH_SVG: &[u8] = include_bytes!("static/brush.svg"); /// The file contents of `wheel.svg`, the icon used for the settings button. -pub static WHEEL_SVG: &'static [u8] = include_bytes!("static/wheel.svg"); +pub static WHEEL_SVG: &[u8] = include_bytes!("static/wheel.svg"); /// The file contents of `down-arrow.svg`, the icon used for the crate choice combobox. -pub static DOWN_ARROW_SVG: &'static [u8] = include_bytes!("static/down-arrow.svg"); +pub static DOWN_ARROW_SVG: &[u8] = include_bytes!("static/down-arrow.svg"); /// The contents of `COPYRIGHT.txt`, the license listing for files distributed with documentation /// output. -pub static COPYRIGHT: &'static [u8] = include_bytes!("static/COPYRIGHT.txt"); +pub static COPYRIGHT: &[u8] = include_bytes!("static/COPYRIGHT.txt"); /// The contents of `LICENSE-APACHE.txt`, the text of the Apache License, version 2.0. -pub static LICENSE_APACHE: &'static [u8] = include_bytes!("static/LICENSE-APACHE.txt"); +pub static LICENSE_APACHE: &[u8] = include_bytes!("static/LICENSE-APACHE.txt"); /// The contents of `LICENSE-MIT.txt`, the text of the MIT License. -pub static LICENSE_MIT: &'static [u8] = include_bytes!("static/LICENSE-MIT.txt"); +pub static LICENSE_MIT: &[u8] = include_bytes!("static/LICENSE-MIT.txt"); /// The contents of `rust-logo.png`, the default icon of the documentation. -pub static RUST_LOGO: &'static [u8] = include_bytes!("static/rust-logo.png"); +pub static RUST_LOGO: &[u8] = include_bytes!("static/rust-logo.png"); /// The contents of `favicon.ico`, the default favicon of the documentation. -pub static RUST_FAVICON: &'static [u8] = include_bytes!("static/favicon.ico"); +pub static RUST_FAVICON: &[u8] = include_bytes!("static/favicon.ico"); /// The built-in themes given to every documentation site. pub mod themes { /// The "light" theme, selected by default when no setting is available. Used as the basis for /// the `--check-theme` functionality. - pub static LIGHT: &'static str = include_str!("static/themes/light.css"); + pub static LIGHT: &str = include_str!("static/themes/light.css"); /// The "dark" theme. - pub static DARK: &'static str = include_str!("static/themes/dark.css"); + pub static DARK: &str = include_str!("static/themes/dark.css"); } /// Files related to the Fira Sans font. pub mod fira_sans { /// The file `FiraSans-Regular.woff`, the Regular variant of the Fira Sans font. - pub static REGULAR: &'static [u8] = include_bytes!("static/FiraSans-Regular.woff"); + pub static REGULAR: &[u8] = include_bytes!("static/FiraSans-Regular.woff"); /// The file `FiraSans-Medium.woff`, the Medium variant of the Fira Sans font. - pub static MEDIUM: &'static [u8] = include_bytes!("static/FiraSans-Medium.woff"); + pub static MEDIUM: &[u8] = include_bytes!("static/FiraSans-Medium.woff"); /// The file `FiraSans-LICENSE.txt`, the license text for the Fira Sans font. - pub static LICENSE: &'static [u8] = include_bytes!("static/FiraSans-LICENSE.txt"); + pub static LICENSE: &[u8] = include_bytes!("static/FiraSans-LICENSE.txt"); } /// Files related to the Source Serif Pro font. pub mod source_serif_pro { /// The file `SourceSerifPro-Regular.ttf.woff`, the Regular variant of the Source Serif Pro /// font. - pub static REGULAR: &'static [u8] = include_bytes!("static/SourceSerifPro-Regular.ttf.woff"); + pub static REGULAR: &[u8] = include_bytes!("static/SourceSerifPro-Regular.ttf.woff"); /// The file `SourceSerifPro-Bold.ttf.woff`, the Bold variant of the Source Serif Pro font. - pub static BOLD: &'static [u8] = include_bytes!("static/SourceSerifPro-Bold.ttf.woff"); + pub static BOLD: &[u8] = include_bytes!("static/SourceSerifPro-Bold.ttf.woff"); /// The file `SourceSerifPro-It.ttf.woff`, the Italic variant of the Source Serif Pro font. - pub static ITALIC: &'static [u8] = include_bytes!("static/SourceSerifPro-It.ttf.woff"); + pub static ITALIC: &[u8] = include_bytes!("static/SourceSerifPro-It.ttf.woff"); /// The file `SourceSerifPro-LICENSE.txt`, the license text for the Source Serif Pro font. - pub static LICENSE: &'static [u8] = include_bytes!("static/SourceSerifPro-LICENSE.md"); + pub static LICENSE: &[u8] = include_bytes!("static/SourceSerifPro-LICENSE.md"); } /// Files related to the Source Code Pro font. pub mod source_code_pro { /// The file `SourceCodePro-Regular.woff`, the Regular variant of the Source Code Pro font. - pub static REGULAR: &'static [u8] = include_bytes!("static/SourceCodePro-Regular.woff"); + pub static REGULAR: &[u8] = include_bytes!("static/SourceCodePro-Regular.woff"); /// The file `SourceCodePro-Semibold.woff`, the Semibold variant of the Source Code Pro font. - pub static SEMIBOLD: &'static [u8] = include_bytes!("static/SourceCodePro-Semibold.woff"); + pub static SEMIBOLD: &[u8] = include_bytes!("static/SourceCodePro-Semibold.woff"); /// The file `SourceCodePro-LICENSE.txt`, the license text of the Source Code Pro font. - pub static LICENSE: &'static [u8] = include_bytes!("static/SourceCodePro-LICENSE.txt"); + pub static LICENSE: &[u8] = include_bytes!("static/SourceCodePro-LICENSE.txt"); } /// Files related to the sidebar in rustdoc sources. pub mod sidebar { /// File script to handle sidebar. - pub static SOURCE_SCRIPT: &'static str = include_str!("static/source-script.js"); + pub static SOURCE_SCRIPT: &str = include_str!("static/source-script.js"); } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 4ea14ab9077c6..33cabad9193c4 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -38,6 +38,7 @@ extern crate rustc_resolve; extern crate rustc_session; extern crate rustc_span as rustc_span; extern crate rustc_target; +extern crate rustc_trait_selection; extern crate rustc_typeck; extern crate test as testing; #[macro_use] @@ -48,8 +49,8 @@ use std::env; use std::panic; use std::process; -use rustc::session::config::{make_crate_type_option, ErrorOutputType, RustcOptGroup}; -use rustc::session::{early_error, early_warn}; +use rustc_session::config::{make_crate_type_option, ErrorOutputType, RustcOptGroup}; +use rustc_session::{early_error, early_warn}; #[macro_use] mod externalfiles; @@ -266,7 +267,7 @@ fn opts() -> Vec { unstable("display-warnings", |o| { o.optflag("", "display-warnings", "to print code warnings when testing doc") }), - unstable("crate-version", |o| { + stable("crate-version", |o| { o.optopt("", "crate-version", "crate version to print into documentation", "VERSION") }), unstable("sort-modules-by-appearance", |o| { diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index f48224512ba4f..98300385c8fb8 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -8,7 +8,6 @@ use rustc_ast::attr; use rustc_span::symbol::sym; use rustc_span::FileName; use serde::Serialize; -use serde_json; use std::collections::BTreeMap; use std::ops; diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 75355b84fee83..113c781e33205 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1,4 +1,3 @@ -use rustc::lint; use rustc::ty; use rustc_ast::ast::{self, Ident}; use rustc_errors::Applicability; @@ -12,6 +11,7 @@ use rustc_hir::def::{ }; use rustc_hir::def_id::DefId; use rustc_resolve::ParentScope; +use rustc_session::lint; use rustc_span::symbol::Symbol; use rustc_span::DUMMY_SP; @@ -348,7 +348,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { let parent_node = self.cx.as_local_hir_id(item.def_id).and_then(|hir_id| { // FIXME: this fails hard for impls in non-module scope, but is necessary for the // current `resolve()` implementation. - match self.cx.as_local_hir_id(self.cx.tcx.parent_module(hir_id)).unwrap() { + match self.cx.as_local_hir_id(self.cx.tcx.parent_module(hir_id).to_def_id()).unwrap() { id if id != hir_id => Some(id), _ => None, } diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 71cff637c1272..38f371783e994 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -1,9 +1,9 @@ //! Contains information about "passes", used to modify crate information during the documentation //! process. -use rustc::lint; use rustc::middle::privacy::AccessLevels; use rustc_hir::def_id::{DefId, DefIdSet}; +use rustc_session::lint; use rustc_span::{InnerSpan, Span, DUMMY_SP}; use std::mem; use std::ops::Range; diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index b63dbbf80d864..c5aa4677d5659 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -1,5 +1,4 @@ use rustc::hir::map::Map; -use rustc::session::{self, config, DiagnosticOutput}; use rustc::util::common::ErrorReported; use rustc_ast::ast; use rustc_ast::with_globals; @@ -8,6 +7,7 @@ use rustc_feature::UnstableFeatures; use rustc_hir as hir; use rustc_hir::intravisit; use rustc_interface::interface; +use rustc_session::{self, config, DiagnosticOutput, Session}; use rustc_span::edition::Edition; use rustc_span::source_map::SourceMap; use rustc_span::symbol::sym; @@ -52,7 +52,7 @@ pub fn run(options: Options) -> i32 { cg: options.codegen_options.clone(), externs: options.externs.clone(), unstable_features: UnstableFeatures::from_environment(), - lint_cap: Some(::rustc::lint::Level::Allow), + lint_cap: Some(rustc_session::lint::Level::Allow), actually_rustdoc: true, debugging_opts: config::DebuggingOptions { ..config::basic_debugging_options() }, edition: options.edition, @@ -107,12 +107,12 @@ pub fn run(options: Options) -> i32 { let mut hir_collector = HirCollector { sess: compiler.session(), collector: &mut collector, - map: *tcx.hir(), + map: tcx.hir(), codes: ErrorCodes::from( compiler.session().opts.unstable_features.is_nightly_build(), ), }; - hir_collector.visit_testable("".to_string(), &krate.attrs, |this| { + hir_collector.visit_testable("".to_string(), &krate.item.attrs, |this| { intravisit::walk_crate(this, krate); }); }); @@ -146,6 +146,7 @@ fn scrape_test_config(krate: &::rustc_hir::Crate) -> TestOptions { TestOptions { no_crate_inject: false, display_warnings: false, attrs: Vec::new() }; let test_attrs: Vec<_> = krate + .item .attrs .iter() .filter(|a| a.check_name(sym::doc)) @@ -449,7 +450,7 @@ pub fn make_test( } if !found_macro { - if let ast::ItemKind::Mac(..) = item.kind { + if let ast::ItemKind::MacCall(..) = item.kind { found_macro = true; } } @@ -853,9 +854,9 @@ impl Tester for Collector { } struct HirCollector<'a, 'hir> { - sess: &'a session::Session, + sess: &'a Session, collector: &'a mut Collector, - map: &'a Map<'hir>, + map: Map<'hir>, codes: ErrorCodes, } @@ -903,8 +904,8 @@ impl<'a, 'hir> HirCollector<'a, 'hir> { impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> { type Map = Map<'hir>; - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { - intravisit::NestedVisitorMap::All(&self.map) + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { + intravisit::NestedVisitorMap::All(self.map) } fn visit_item(&mut self, item: &'hir hir::Item) { @@ -955,7 +956,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> { } fn visit_macro_def(&mut self, macro_def: &'hir hir::MacroDef) { - self.visit_testable(macro_def.name.to_string(), ¯o_def.attrs, |_| ()); + self.visit_testable(macro_def.ident.to_string(), ¯o_def.attrs, |_| ()); } } diff --git a/src/librustdoc/theme.rs b/src/librustdoc/theme.rs index a8a571e7c5491..9dd1d3706ffbd 100644 --- a/src/librustdoc/theme.rs +++ b/src/librustdoc/theme.rs @@ -234,9 +234,7 @@ pub fn load_css_paths(v: &[u8]) -> CssPath { } pub fn get_differences(against: &CssPath, other: &CssPath, v: &mut Vec) { - if against.name != other.name { - return; - } else { + if against.name == other.name { for child in &against.children { let mut found = false; let mut found_working = false; diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 8f2f88d08bf7a..e49395c6fd438 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -64,11 +64,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { pub fn visit(mut self, krate: &'tcx hir::Crate) -> Module<'tcx> { let mut module = self.visit_mod_contents( - krate.span, - krate.attrs, + krate.item.span, + krate.item.attrs, &Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public }, hir::CRATE_HIR_ID, - &krate.module, + &krate.item.module, None, ); // Attach the crate's exported macros to the top-level module: @@ -563,6 +563,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { polarity, defaultness, constness, + defaultness_span: _, ref generics, ref of_trait, self_ty, @@ -620,8 +621,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { def: &'tcx hir::MacroDef, renamed: Option, ) -> Macro<'tcx> { - debug!("visit_local_macro: {}", def.name); - let tts = def.body.trees().collect::>(); + debug!("visit_local_macro: {}", def.ident); + let tts = def.ast.body.inner_tokens().trees().collect::>(); // Extract the spans of all matchers. They represent the "interface" of the macro. let matchers = tts.chunks(4).map(|arm| arm[0].span()).collect(); @@ -629,7 +630,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { hid: def.hir_id, def_id: self.cx.tcx.hir().local_def_id(def.hir_id), attrs: &def.attrs, - name: renamed.unwrap_or(def.name), + name: renamed.unwrap_or(def.ident.name), whence: def.span, matchers, imported_from: None, diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index b147aa55b2a61..0dd2f79d066e4 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -27,7 +27,7 @@ hashbrown = { version = "0.6.2", default-features = false, features = ['rustc-de [dependencies.backtrace_rs] package = "backtrace" -version = "0.3.44" +version = "0.3.46" default-features = false # without the libstd `backtrace` feature, stub out everything features = [ "rustc-dep-of-std" ] # enable build support for integrating into libstd diff --git a/src/libstd/backtrace.rs b/src/libstd/backtrace.rs index 97db0ff3791d7..e10d466030f0b 100644 --- a/src/libstd/backtrace.rs +++ b/src/libstd/backtrace.rs @@ -92,6 +92,7 @@ // a backtrace or actually symbolizing it. use crate::env; +use crate::ffi::c_void; use crate::fmt; use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst}; use crate::sync::Mutex; @@ -144,10 +145,16 @@ fn _assert_send_sync() { } struct BacktraceFrame { - frame: backtrace::Frame, + frame: RawFrame, symbols: Vec, } +enum RawFrame { + Actual(backtrace::Frame), + #[cfg(test)] + Fake, +} + struct BacktraceSymbol { name: Option>, filename: Option, @@ -162,8 +169,8 @@ enum BytesOrWide { impl fmt::Debug for Backtrace { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { let mut capture = match &self.inner { - Inner::Unsupported => return fmt.write_str("unsupported backtrace"), - Inner::Disabled => return fmt.write_str("disabled backtrace"), + Inner::Unsupported => return fmt.write_str(""), + Inner::Disabled => return fmt.write_str(""), Inner::Captured(c) => c.lock().unwrap(), }; capture.resolve(); @@ -193,11 +200,11 @@ impl fmt::Debug for BacktraceSymbol { if let Some(fn_name) = self.name.as_ref().map(|b| backtrace::SymbolName::new(b)) { write!(fmt, "fn: \"{:#}\"", fn_name)?; } else { - write!(fmt, "fn: \"\"")?; + write!(fmt, "fn: ")?; } if let Some(fname) = self.filename.as_ref() { - write!(fmt, ", file: {:?}", fname)?; + write!(fmt, ", file: \"{:?}\"", fname)?; } if let Some(line) = self.lineno.as_ref() { @@ -243,7 +250,7 @@ impl Backtrace { }, }; ENABLED.store(enabled as usize + 1, SeqCst); - return enabled; + enabled } /// Capture a stack backtrace of the current thread. @@ -293,7 +300,10 @@ impl Backtrace { let mut actual_start = None; unsafe { backtrace::trace_unsynchronized(|frame| { - frames.push(BacktraceFrame { frame: frame.clone(), symbols: Vec::new() }); + frames.push(BacktraceFrame { + frame: RawFrame::Actual(frame.clone()), + symbols: Vec::new(), + }); if frame.symbol_address() as usize == ip && actual_start.is_none() { actual_start = Some(frames.len()); } @@ -393,8 +403,13 @@ impl Capture { let _lock = lock(); for frame in self.frames.iter_mut() { let symbols = &mut frame.symbols; + let frame = match &frame.frame { + RawFrame::Actual(frame) => frame, + #[cfg(test)] + RawFrame::Fake => unimplemented!(), + }; unsafe { - backtrace::resolve_frame_unsynchronized(&frame.frame, |symbol| { + backtrace::resolve_frame_unsynchronized(frame, |symbol| { symbols.push(BacktraceSymbol { name: symbol.name().map(|m| m.as_bytes().to_vec()), filename: symbol.filename_raw().map(|b| match b { @@ -408,3 +423,65 @@ impl Capture { } } } + +impl RawFrame { + fn ip(&self) -> *mut c_void { + match self { + RawFrame::Actual(frame) => frame.ip(), + #[cfg(test)] + RawFrame::Fake => 1 as *mut c_void, + } + } +} + +#[test] +fn test_debug() { + let backtrace = Backtrace { + inner: Inner::Captured(Mutex::new(Capture { + actual_start: 1, + resolved: true, + frames: vec![ + BacktraceFrame { + frame: RawFrame::Fake, + symbols: vec![BacktraceSymbol { + name: Some(b"std::backtrace::Backtrace::create".to_vec()), + filename: Some(BytesOrWide::Bytes(b"rust/backtrace.rs".to_vec())), + lineno: Some(100), + }], + }, + BacktraceFrame { + frame: RawFrame::Fake, + symbols: vec![BacktraceSymbol { + name: Some(b"__rust_maybe_catch_panic".to_vec()), + filename: None, + lineno: None, + }], + }, + BacktraceFrame { + frame: RawFrame::Fake, + symbols: vec![ + BacktraceSymbol { + name: Some(b"std::rt::lang_start_internal".to_vec()), + filename: Some(BytesOrWide::Bytes(b"rust/rt.rs".to_vec())), + lineno: Some(300), + }, + BacktraceSymbol { + name: Some(b"std::rt::lang_start".to_vec()), + filename: Some(BytesOrWide::Bytes(b"rust/rt.rs".to_vec())), + lineno: Some(400), + }, + ], + }, + ], + })), + }; + + #[rustfmt::skip] + let expected = "Backtrace [\ + \n { fn: \"__rust_maybe_catch_panic\" },\ + \n { fn: \"std::rt::lang_start_internal\", file: \"rust/rt.rs\", line: 300 },\ + \n { fn: \"std::rt::lang_start\", file: \"rust/rt.rs\", line: 400 },\ + \n]"; + + assert_eq!(format!("{:#?}", backtrace), expected); +} diff --git a/src/libstd/build.rs b/src/libstd/build.rs index 8db7bc12cd308..806c9b84559e8 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -25,6 +25,16 @@ fn main() { println!("cargo:rustc-link-lib=posix4"); println!("cargo:rustc-link-lib=pthread"); println!("cargo:rustc-link-lib=resolv"); + } else if target.contains("illumos") { + println!("cargo:rustc-link-lib=socket"); + println!("cargo:rustc-link-lib=posix4"); + println!("cargo:rustc-link-lib=pthread"); + println!("cargo:rustc-link-lib=resolv"); + println!("cargo:rustc-link-lib=nsl"); + // SSP symbols are provided in a separate library, rather that by libc (for now) + println!("cargo:rustc-link-lib=ssp"); + // Use libumem for the (malloc-compatible) allocator + println!("cargo:rustc-link-lib=umem"); } else if target.contains("apple-darwin") { println!("cargo:rustc-link-lib=System"); diff --git a/src/libstd/env.rs b/src/libstd/env.rs index af35a5d9b7c47..6aad082a97f9a 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -723,8 +723,8 @@ pub struct ArgsOs { /// (such as `*` and `?`). On Windows this is not done, and such arguments are /// passed as-is. /// -/// On glibc Linux, arguments are retrieved by placing a function in .init_array. -/// glibc passes argc, argv, and envp to functions in .init_array, as a non-standard extension. +/// On glibc Linux systems, arguments are retrieved by placing a function in ".init_array". +/// Glibc passes argc, argv, and envp to functions in ".init_array", as a non-standard extension. /// This allows `std::env::args` to work even in a `cdylib` or `staticlib`, as it does on macOS /// and Windows. /// @@ -758,8 +758,8 @@ pub fn args() -> Args { /// set to arbitrary text, and it may not even exist, so this property should /// not be relied upon for security purposes. /// -/// On glibc Linux, arguments are retrieved by placing a function in .init_array. -/// glibc passes argc, argv, and envp to functions in .init_array, as a non-standard extension. +/// On glibc Linux systems, arguments are retrieved by placing a function in ".init_array". +/// Glibc passes argc, argv, and envp to functions in ".init_array", as a non-standard extension. /// This allows `std::env::args` to work even in a `cdylib` or `staticlib`, as it does on macOS /// and Windows. /// diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 2a370f192964f..b394f2efc2e35 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -88,7 +88,7 @@ pub trait Error: Debug + Display { /// fn main() { /// match get_super_error() { /// Err(e) => { - /// println!("Error: {}", e.description()); + /// println!("Error: {}", e); /// println!("Caused by: {}", e.source().unwrap()); /// } /// _ => println!("No error"), diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index a1128a589a64a..e8e6f27b95b22 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -949,7 +949,7 @@ impl f64 { // because of their non-standard behavior (e.g., log(-n) returns -Inf instead // of expected NaN). fn log_wrapper f64>(self, log_fn: F) -> f64 { - if !cfg!(target_os = "solaris") { + if !cfg!(any(target_os = "solaris", target_os = "illumos")) { log_fn(self) } else { if self.is_finite() { diff --git a/src/libstd/future.rs b/src/libstd/future.rs index 7b1beb1ecda80..c0675eeba98da 100644 --- a/src/libstd/future.rs +++ b/src/libstd/future.rs @@ -1,12 +1,14 @@ //! Asynchronous values. -use core::cell::Cell; -use core::marker::Unpin; -use core::ops::{Drop, Generator, GeneratorState}; -use core::option::Option; -use core::pin::Pin; -use core::ptr::NonNull; -use core::task::{Context, Poll}; +#[cfg(bootstrap)] +use core::{ + cell::Cell, + marker::Unpin, + ops::{Drop, Generator, GeneratorState}, + pin::Pin, + ptr::NonNull, + task::{Context, Poll}, +}; #[doc(inline)] #[stable(feature = "futures_api", since = "1.36.0")] @@ -17,6 +19,7 @@ pub use core::future::*; /// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give /// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`). // This is `const` to avoid extra errors after we recover from `const async fn` +#[cfg(bootstrap)] #[doc(hidden)] #[unstable(feature = "gen_future", issue = "50547")] pub const fn from_generator>(x: T) -> impl Future { @@ -24,6 +27,7 @@ pub const fn from_generator>(x: T) -> impl Future>(T); // We rely on the fact that async/await futures are immovable in order to create // self-referential borrows in the underlying generator. +#[cfg(bootstrap)] impl> !Unpin for GenFuture {} +#[cfg(bootstrap)] #[doc(hidden)] #[unstable(feature = "gen_future", issue = "50547")] impl> Future for GenFuture { @@ -41,22 +47,22 @@ impl> Future for GenFuture { // Safe because we're !Unpin + !Drop mapping to a ?Unpin value let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) }; let _guard = unsafe { set_task_context(cx) }; - match gen.resume( - #[cfg(not(bootstrap))] - (), - ) { + match gen.resume(()) { GeneratorState::Yielded(()) => Poll::Pending, GeneratorState::Complete(x) => Poll::Ready(x), } } } +#[cfg(bootstrap)] thread_local! { static TLS_CX: Cell>>> = Cell::new(None); } +#[cfg(bootstrap)] struct SetOnDrop(Option>>); +#[cfg(bootstrap)] impl Drop for SetOnDrop { fn drop(&mut self) { TLS_CX.with(|tls_cx| { @@ -67,6 +73,7 @@ impl Drop for SetOnDrop { // Safety: the returned guard must drop before `cx` is dropped and before // any previous guard is dropped. +#[cfg(bootstrap)] unsafe fn set_task_context(cx: &mut Context<'_>) -> SetOnDrop { // transmute the context's lifetime to 'static so we can store it. let cx = core::mem::transmute::<&mut Context<'_>, &mut Context<'static>>(cx); @@ -74,6 +81,7 @@ unsafe fn set_task_context(cx: &mut Context<'_>) -> SetOnDrop { SetOnDrop(old_cx) } +#[cfg(bootstrap)] #[doc(hidden)] #[unstable(feature = "gen_future", issue = "50547")] /// Polls a future in the current thread-local task waker. diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 420d6ea589a22..88d556229e4cb 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -502,7 +502,7 @@ pub trait Read { /// how many bytes were read. /// /// This function does not provide any guarantees about whether it blocks - /// waiting for data, but if an object needs to block for a read but cannot + /// waiting for data, but if an object needs to block for a read and cannot, /// it will typically signal this via an [`Err`] return value. /// /// If the return value of this method is [`Ok(n)`], then it must be @@ -951,6 +951,12 @@ pub trait Read { #[repr(transparent)] pub struct IoSliceMut<'a>(sys::io::IoSliceMut<'a>); +#[stable(feature = "iovec-send-sync", since = "1.44.0")] +unsafe impl<'a> Send for IoSliceMut<'a> {} + +#[stable(feature = "iovec-send-sync", since = "1.44.0")] +unsafe impl<'a> Sync for IoSliceMut<'a> {} + #[stable(feature = "iovec", since = "1.36.0")] impl<'a> fmt::Debug for IoSliceMut<'a> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -1050,9 +1056,16 @@ impl<'a> DerefMut for IoSliceMut<'a> { /// ABI compatible with the `iovec` type on Unix platforms and `WSABUF` on /// Windows. #[stable(feature = "iovec", since = "1.36.0")] +#[derive(Copy, Clone)] #[repr(transparent)] pub struct IoSlice<'a>(sys::io::IoSlice<'a>); +#[stable(feature = "iovec-send-sync", since = "1.44.0")] +unsafe impl<'a> Send for IoSlice<'a> {} + +#[stable(feature = "iovec-send-sync", since = "1.44.0")] +unsafe impl<'a> Sync for IoSlice<'a> {} + #[stable(feature = "iovec", since = "1.36.0")] impl<'a> fmt::Debug for IoSlice<'a> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index d410faca30d9e..9a82ae7626d97 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -6,7 +6,7 @@ use crate::cell::RefCell; use crate::fmt; use crate::io::lazy::Lazy; use crate::io::{self, BufReader, Initializer, IoSlice, IoSliceMut, LineWriter}; -use crate::sync::{Arc, Mutex, MutexGuard}; +use crate::sync::{Arc, Mutex, MutexGuard, Once}; use crate::sys::stdio; use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard}; use crate::thread::LocalKey; @@ -493,7 +493,11 @@ pub fn stdout() -> Stdout { Ok(stdout) => Maybe::Real(stdout), _ => Maybe::Fake, }; - Arc::new(ReentrantMutex::new(RefCell::new(LineWriter::new(stdout)))) + unsafe { + let ret = Arc::new(ReentrantMutex::new(RefCell::new(LineWriter::new(stdout)))); + ret.init(); + return ret; + } } } @@ -520,7 +524,7 @@ impl Stdout { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> StdoutLock<'_> { - StdoutLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) } + StdoutLock { inner: self.inner.lock() } } } @@ -581,7 +585,7 @@ impl fmt::Debug for StdoutLock<'_> { /// an error. #[stable(feature = "rust1", since = "1.0.0")] pub struct Stderr { - inner: Arc>>>, + inner: &'static ReentrantMutex>>, } /// A locked reference to the `Stderr` handle. @@ -639,19 +643,28 @@ pub struct StderrLock<'a> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn stderr() -> Stderr { - static INSTANCE: Lazy>>> = Lazy::new(); - return Stderr { - inner: unsafe { INSTANCE.get(stderr_init).expect("cannot access stderr during shutdown") }, - }; - - fn stderr_init() -> Arc>>> { - // This must not reentrantly access `INSTANCE` - let stderr = match stderr_raw() { - Ok(stderr) => Maybe::Real(stderr), - _ => Maybe::Fake, - }; - Arc::new(ReentrantMutex::new(RefCell::new(stderr))) - } + // Note that unlike `stdout()` we don't use `Lazy` here which registers a + // destructor. Stderr is not buffered nor does the `stderr_raw` type consume + // any owned resources, so there's no need to run any destructors at some + // point in the future. + // + // This has the added benefit of allowing `stderr` to be usable during + // process shutdown as well! + static INSTANCE: ReentrantMutex>> = + unsafe { ReentrantMutex::new(RefCell::new(Maybe::Fake)) }; + + // When accessing stderr we need one-time initialization of the reentrant + // mutex, followed by one-time detection of whether we actually have a + // stderr handle or not. Afterwards we can just always use the now-filled-in + // `INSTANCE` value. + static INIT: Once = Once::new(); + INIT.call_once(|| unsafe { + INSTANCE.init(); + if let Ok(stderr) = stderr_raw() { + *INSTANCE.lock().borrow_mut() = Maybe::Real(stderr); + } + }); + return Stderr { inner: &INSTANCE }; } impl Stderr { @@ -677,7 +690,7 @@ impl Stderr { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> StderrLock<'_> { - StderrLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) } + StderrLock { inner: self.inner.lock() } } } @@ -792,10 +805,14 @@ fn print_to( { let result = local_s .try_with(|s| { - if let Ok(mut borrowed) = s.try_borrow_mut() { - if let Some(w) = borrowed.as_mut() { - return w.write_fmt(args); - } + // Note that we completely remove a local sink to write to in case + // our printing recursively panics/prints, so the recursive + // panic/print goes to the global sink instead of our local sink. + let prev = s.borrow_mut().take(); + if let Some(mut w) = prev { + let result = w.write_fmt(args); + *s.borrow_mut() = Some(w); + return result; } global_s().write_fmt(args) }) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index 3c69c1160d5b5..314424631fcbf 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -234,12 +234,55 @@ mod crate_keyword {} #[doc(keyword = "else")] // -/// What to do when an [`if`] condition does not hold. +/// What expression to evaluate when an [`if`] condition evaluates to [`false`]. /// -/// The documentation for this keyword is [not yet complete]. Pull requests welcome! +/// `else` expressions are optional. When no else expressions are supplied it is assumed to evaluate +/// to the unit type `()`. +/// +/// The type that the `else` blocks evaluate to must be compatible with the type that the `if` block +/// evaluates to. +/// +/// As can be seen below, `else` must be followed by either: `if`, `if let`, or a block `{}` and it +/// will return the value of that expression. +/// +/// ```rust +/// let result = if true == false { +/// "oh no" +/// } else if "something" == "other thing" { +/// "oh dear" +/// } else if let Some(200) = "blarg".parse::().ok() { +/// "uh oh" +/// } else { +/// println!("Sneaky side effect."); +/// "phew, nothing's broken" +/// }; +/// ``` +/// +/// Here's another example but here we do not try and return an expression: +/// +/// ```rust +/// if true == false { +/// println!("oh no"); +/// } else if "something" == "other thing" { +/// println!("oh dear"); +/// } else if let Some(200) = "blarg".parse::().ok() { +/// println!("uh oh"); +/// } else { +/// println!("phew, nothing's broken"); +/// } +/// ``` /// +/// The above is _still_ an expression but it will always evaluate to `()`. +/// +/// There is possibly no limit to the number of `else` blocks that could follow an `if` expression +/// however if you have several then a [`match`] expression might be preferable. +/// +/// Read more about control flow in the [Rust Book]. +/// +/// [Rust Book]: ../book/ch03-05-control-flow.html#handling-multiple-conditions-with-else-if +/// [`match`]: keyword.match.html +/// [`false`]: keyword.false.html /// [`if`]: keyword.if.html -/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601 mod else_keyword {} #[doc(keyword = "enum")] @@ -637,10 +680,18 @@ mod impl_keyword {} // /// Iterate over a series of values with [`for`]. /// -/// The documentation for this keyword is [not yet complete]. Pull requests welcome! +/// The expression immediately following `in` must implement the [`Iterator`] trait. +/// +/// ## Literal Examples: +/// +/// * `for _ **in** 1..3 {}` - Iterate over an exclusive range up to but excluding 3. +/// * `for _ **in** 1..=3 {}` - Iterate over an inclusive range up to and includeing 3. +/// +/// (Read more about [range patterns]) /// +/// [`Iterator`]: ../book/ch13-04-performance.html +/// [`range patterns`]: ../reference/patterns.html?highlight=range#range-patterns /// [`for`]: keyword.for.html -/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601 mod in_keyword {} #[doc(keyword = "let")] @@ -925,9 +976,15 @@ mod mut_keyword {} // /// Make an item visible to others. /// -/// The documentation for this keyword is [not yet complete]. Pull requests welcome! +/// The keyword `pub` makes any module, function, or data structure accessible from inside +/// of external modules. The `pub` keyword may also be used in a `use` declaration to re-export +/// an identifier from a namespace. /// -/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601 +/// For more information on the `pub` keyword, please see the visibility section +/// of the [reference] and for some examples, see [Rust by Example]. +/// +/// [reference]:../reference/visibility-and-privacy.html?highlight=pub#visibility-and-privacy +/// [Rust by Example]:../rust-by-example/mod/visibility.html mod pub_keyword {} #[doc(keyword = "ref")] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 231908ddda0ae..d41105270549e 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -240,6 +240,7 @@ #![feature(atomic_mut_ptr)] #![feature(box_syntax)] #![feature(c_variadic)] +#![cfg_attr(not(bootstrap), feature(cfg_accessible))] #![feature(cfg_target_has_atomic)] #![feature(cfg_target_thread_local)] #![feature(char_error_internals)] @@ -277,6 +278,7 @@ #![feature(maybe_uninit_ref)] #![feature(maybe_uninit_slice)] #![feature(needs_panic_runtime)] +#![cfg_attr(not(bootstrap), feature(negative_impls))] #![feature(never_type)] #![feature(nll)] #![feature(optin_builtin_traits)] @@ -292,7 +294,8 @@ #![feature(shrink_to)] #![feature(slice_concat_ext)] #![feature(slice_internals)] -#![feature(specialization)] +#![cfg_attr(bootstrap, feature(specialization))] +#![cfg_attr(not(bootstrap), feature(min_specialization))] #![feature(staged_api)] #![feature(std_internals)] #![feature(stdsimd)] @@ -308,6 +311,7 @@ #![feature(untagged_unions)] #![feature(unwind_attributes)] #![feature(vec_into_raw_parts)] +#![feature(wake_trait)] // NB: the above list is sorted to minimize merge conflicts. #![default_lib_allocator] @@ -461,9 +465,14 @@ pub mod time; #[stable(feature = "futures_api", since = "1.36.0")] pub mod task { //! Types and Traits for working with asynchronous tasks. + #[doc(inline)] #[stable(feature = "futures_api", since = "1.36.0")] pub use core::task::*; + + #[doc(inline)] + #[unstable(feature = "wake_trait", issue = "69912")] + pub use alloc::task::*; } #[stable(feature = "futures_api", since = "1.36.0")] diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index 57cba6b1f7a1b..de6360cf020f5 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -989,11 +989,26 @@ mod tests { // s has been moved into the tsa call } - // FIXME: figure out why this fails on openbsd and fix it #[test] - #[cfg(not(any(windows, target_os = "openbsd")))] - fn to_socket_addr_str_bad() { - assert!(tsa("1200::AB00:1234::2552:7777:1313:34300").is_err()); + fn bind_udp_socket_bad() { + // rust-lang/rust#53957: This is a regression test for a parsing problem + // discovered as part of issue rust-lang/rust#23076, where we were + // incorrectly parsing invalid input and then that would result in a + // successful `UdpSocket` binding when we would expect failure. + // + // At one time, this test was written as a call to `tsa` with + // INPUT_23076. However, that structure yields an unreliable test, + // because it ends up passing junk input to the DNS server, and some DNS + // servers will respond with `Ok` to such input, with the ip address of + // the DNS server itself. + // + // This form of the test is more robust: even when the DNS server + // returns its own address, it is still an error to bind a UDP socket to + // a non-local address, and so we still get an error here in that case. + + const INPUT_23076: &'static str = "1200::AB00:1234::2552:7777:1313:34300"; + + assert!(crate::net::UdpSocket::bind(INPUT_23076).is_err()) } #[test] diff --git a/src/libstd/os/illumos/fs.rs b/src/libstd/os/illumos/fs.rs new file mode 100644 index 0000000000000..4e69111240d24 --- /dev/null +++ b/src/libstd/os/illumos/fs.rs @@ -0,0 +1,120 @@ +#![stable(feature = "metadata_ext", since = "1.1.0")] + +use libc; + +use crate::fs::Metadata; +use crate::sys_common::AsInner; + +#[allow(deprecated)] +use crate::os::illumos::raw; + +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html +#[stable(feature = "metadata_ext", since = "1.1.0")] +pub trait MetadataExt { + /// Gain a reference to the underlying `stat` structure which contains + /// the raw information returned by the OS. + /// + /// The contents of the returned `stat` are **not** consistent across + /// Unix platforms. The `os::unix::fs::MetadataExt` trait contains the + /// cross-Unix abstractions contained within the raw stat. + #[stable(feature = "metadata_ext", since = "1.1.0")] + #[rustc_deprecated(since = "1.8.0", + reason = "deprecated in favor of the accessor \ + methods of this trait")] + #[allow(deprecated)] + fn as_raw_stat(&self) -> &raw::stat; + + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_dev(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ino(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mode(&self) -> u32; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_nlink(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_uid(&self) -> u32; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_gid(&self) -> u32; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_rdev(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_size(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_atime(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_atime_nsec(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mtime(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mtime_nsec(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ctime(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ctime_nsec(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blksize(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blocks(&self) -> u64; +} + +#[stable(feature = "metadata_ext", since = "1.1.0")] +impl MetadataExt for Metadata { + #[allow(deprecated)] + fn as_raw_stat(&self) -> &raw::stat { + unsafe { + &*(self.as_inner().as_inner() as *const libc::stat + as *const raw::stat) + } + } + fn st_dev(&self) -> u64 { + self.as_inner().as_inner().st_dev as u64 + } + fn st_ino(&self) -> u64 { + self.as_inner().as_inner().st_ino as u64 + } + fn st_mode(&self) -> u32 { + self.as_inner().as_inner().st_mode as u32 + } + fn st_nlink(&self) -> u64 { + self.as_inner().as_inner().st_nlink as u64 + } + fn st_uid(&self) -> u32 { + self.as_inner().as_inner().st_uid as u32 + } + fn st_gid(&self) -> u32 { + self.as_inner().as_inner().st_gid as u32 + } + fn st_rdev(&self) -> u64 { + self.as_inner().as_inner().st_rdev as u64 + } + fn st_size(&self) -> u64 { + self.as_inner().as_inner().st_size as u64 + } + fn st_atime(&self) -> i64 { + self.as_inner().as_inner().st_atime as i64 + } + fn st_atime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_atime_nsec as i64 + } + fn st_mtime(&self) -> i64 { + self.as_inner().as_inner().st_mtime as i64 + } + fn st_mtime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_mtime_nsec as i64 + } + fn st_ctime(&self) -> i64 { + self.as_inner().as_inner().st_ctime as i64 + } + fn st_ctime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_ctime_nsec as i64 + } + fn st_blksize(&self) -> u64 { + self.as_inner().as_inner().st_blksize as u64 + } + fn st_blocks(&self) -> u64 { + self.as_inner().as_inner().st_blocks as u64 + } +} diff --git a/src/libstd/os/illumos/mod.rs b/src/libstd/os/illumos/mod.rs new file mode 100644 index 0000000000000..e61926f89356a --- /dev/null +++ b/src/libstd/os/illumos/mod.rs @@ -0,0 +1,6 @@ +//! illumos-specific definitions + +#![stable(feature = "raw_ext", since = "1.1.0")] + +pub mod fs; +pub mod raw; diff --git a/src/libstd/os/illumos/raw.rs b/src/libstd/os/illumos/raw.rs new file mode 100644 index 0000000000000..93270efea2b68 --- /dev/null +++ b/src/libstd/os/illumos/raw.rs @@ -0,0 +1,65 @@ +//! Solaris-specific raw type definitions + +#![stable(feature = "raw_ext", since = "1.1.0")] +#![rustc_deprecated(since = "1.8.0", + reason = "these type aliases are no longer supported by \ + the standard library, the `libc` crate on \ + crates.io should be used instead for the correct \ + definitions")] +#![allow(deprecated)] + +use crate::os::raw::c_long; +use crate::os::unix::raw::{uid_t, gid_t}; + +#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = u64; +#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u64; +#[stable(feature = "raw_ext", since = "1.1.0")] pub type dev_t = u64; +#[stable(feature = "raw_ext", since = "1.1.0")] pub type fflags_t = u32; +#[stable(feature = "raw_ext", since = "1.1.0")] pub type ino_t = u64; +#[stable(feature = "raw_ext", since = "1.1.0")] pub type mode_t = u32; +#[stable(feature = "raw_ext", since = "1.1.0")] pub type nlink_t = u64; +#[stable(feature = "raw_ext", since = "1.1.0")] pub type off_t = u64; +#[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i64; + +#[stable(feature = "pthread_t", since = "1.8.0")] +pub type pthread_t = u32; + +#[repr(C)] +#[derive(Clone)] +#[stable(feature = "raw_ext", since = "1.1.0")] +pub struct stat { + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_dev: dev_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ino: ino_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mode: mode_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_nlink: nlink_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_uid: uid_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_gid: gid_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_rdev: dev_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_size: off_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_atime: time_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_atime_nsec: c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mtime: time_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mtime_nsec: c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ctime: time_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ctime_nsec: c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_blksize: blksize_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_blocks: blkcnt_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub __unused: [u8; 16] +} diff --git a/src/libstd/os/mod.rs b/src/libstd/os/mod.rs index 91e37ed833a4f..d8518cb5ea12c 100644 --- a/src/libstd/os/mod.rs +++ b/src/libstd/os/mod.rs @@ -52,6 +52,8 @@ pub mod freebsd; pub mod fuchsia; #[cfg(target_os = "haiku")] pub mod haiku; +#[cfg(target_os = "illumos")] +pub mod illumos; #[cfg(target_os = "ios")] pub mod ios; #[cfg(target_os = "macos")] diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 8b12aaaa7e2fd..10078bd4aee82 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -14,7 +14,6 @@ use crate::fmt; use crate::intrinsics; use crate::mem::{self, ManuallyDrop}; use crate::process; -use crate::raw; use crate::sync::atomic::{AtomicBool, Ordering}; use crate::sys::stdio::panic_output; use crate::sys_common::backtrace::{self, RustBacktrace}; @@ -41,12 +40,7 @@ use realstd::io::set_panic; // hook up these functions, but it is not this day! #[allow(improper_ctypes)] extern "C" { - fn __rust_maybe_catch_panic( - f: fn(*mut u8), - data: *mut u8, - data_ptr: *mut usize, - vtable_ptr: *mut usize, - ) -> u32; + fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static); /// `payload` is actually a `*mut &mut dyn BoxMeUp` but that would cause FFI warnings. /// It cannot be `Box` because the other end of this call does not depend @@ -247,54 +241,88 @@ pub unsafe fn r#try R>(f: F) -> Result> union Data { f: ManuallyDrop, r: ManuallyDrop, + p: ManuallyDrop>, } // We do some sketchy operations with ownership here for the sake of - // performance. We can only pass pointers down to - // `__rust_maybe_catch_panic` (can't pass objects by value), so we do all - // the ownership tracking here manually using a union. + // performance. We can only pass pointers down to `do_call` (can't pass + // objects by value), so we do all the ownership tracking here manually + // using a union. // // We go through a transition where: // - // * First, we set the data to be the closure that we're going to call. + // * First, we set the data field `f` to be the argumentless closure that we're going to call. // * When we make the function call, the `do_call` function below, we take - // ownership of the function pointer. At this point the `Data` union is + // ownership of the function pointer. At this point the `data` union is // entirely uninitialized. // * If the closure successfully returns, we write the return value into the - // data's return slot. Note that `ptr::write` is used as it's overwriting - // uninitialized data. - // * Finally, when we come back out of the `__rust_maybe_catch_panic` we're + // data's return slot (field `r`). + // * If the closure panics (`do_catch` below), we write the panic payload into field `p`. + // * Finally, when we come back out of the `try` intrinsic we're // in one of two states: // // 1. The closure didn't panic, in which case the return value was - // filled in. We move it out of `data` and return it. - // 2. The closure panicked, in which case the return value wasn't - // filled in. In this case the entire `data` union is invalid, so - // there is no need to drop anything. + // filled in. We move it out of `data.r` and return it. + // 2. The closure panicked, in which case the panic payload was + // filled in. We move it out of `data.p` and return it. // // Once we stack all that together we should have the "most efficient' // method of calling a catch panic whilst juggling ownership. - let mut any_data = 0; - let mut any_vtable = 0; let mut data = Data { f: ManuallyDrop::new(f) }; - let r = __rust_maybe_catch_panic( - do_call::, - &mut data as *mut _ as *mut u8, - &mut any_data, - &mut any_vtable, - ); - - return if r == 0 { + let data_ptr = &mut data as *mut _ as *mut u8; + return if do_try(do_call::, data_ptr, do_catch::) == 0 { Ok(ManuallyDrop::into_inner(data.r)) } else { - update_panic_count(-1); - Err(mem::transmute(raw::TraitObject { - data: any_data as *mut _, - vtable: any_vtable as *mut _, - })) + Err(ManuallyDrop::into_inner(data.p)) }; + // Compatibility wrapper around the try intrinsic for bootstrap. + // + // We also need to mark it #[inline(never)] to work around a bug on MinGW + // targets: the unwinding implementation was relying on UB, but this only + // becomes a problem in practice if inlining is involved. + #[cfg(not(bootstrap))] + use intrinsics::r#try as do_try; + #[cfg(bootstrap)] + #[inline(never)] + unsafe fn do_try(try_fn: fn(*mut u8), data: *mut u8, catch_fn: fn(*mut u8, *mut u8)) -> i32 { + use crate::mem::MaybeUninit; + #[cfg(target_env = "msvc")] + type TryPayload = [u64; 2]; + #[cfg(not(target_env = "msvc"))] + type TryPayload = *mut u8; + + let mut payload: MaybeUninit = MaybeUninit::uninit(); + let payload_ptr = payload.as_mut_ptr() as *mut u8; + let r = intrinsics::r#try(try_fn, data, payload_ptr); + if r != 0 { + #[cfg(target_env = "msvc")] + { + catch_fn(data, payload_ptr) + } + #[cfg(not(target_env = "msvc"))] + { + catch_fn(data, payload.assume_init()) + } + } + r + } + + // We consider unwinding to be rare, so mark this function as cold. However, + // do not mark it no-inline -- that decision is best to leave to the + // optimizer (in most cases this function is not inlined even as a normal, + // non-cold function, though, as of the writing of this comment). + #[cold] + unsafe fn cleanup(payload: *mut u8) -> Box { + let obj = Box::from_raw(__rust_panic_cleanup(payload)); + update_panic_count(-1); + obj + } + + // See comment on do_try above for why #[inline(never)] is needed on bootstrap. + #[cfg_attr(bootstrap, inline(never))] + #[cfg_attr(not(bootstrap), inline)] fn do_call R, R>(data: *mut u8) { unsafe { let data = data as *mut Data; @@ -303,6 +331,19 @@ pub unsafe fn r#try R>(f: F) -> Result> data.r = ManuallyDrop::new(f()); } } + + // We *do* want this part of the catch to be inlined: this allows the + // compiler to properly track accesses to the Data union and optimize it + // away most of the time. + #[inline] + fn do_catch R, R>(data: *mut u8, payload: *mut u8) { + unsafe { + let data = data as *mut Data; + let data = &mut (*data); + let obj = cleanup(payload); + data.p = ManuallyDrop::new(obj); + } + } } /// Determines whether the current thread is unwinding because of panic. diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs index 7c0efe828c27a..6712f5ba5808c 100644 --- a/src/libstd/prelude/v1.rs +++ b/src/libstd/prelude/v1.rs @@ -53,6 +53,15 @@ pub use core::prelude::v1::{ PartialEq, PartialOrd, RustcDecodable, RustcEncodable, }; +#[cfg(not(bootstrap))] +#[unstable( + feature = "cfg_accessible", + issue = "64797", + reason = "`cfg_accessible` is not fully implemented" +)] +#[doc(hidden)] +pub use core::prelude::v1::cfg_accessible; + // The file so far is equivalent to src/libcore/prelude/v1.rs, // and below to src/liballoc/prelude.rs. // Those files are duplicated rather than using glob imports diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index b99b4d8d9fdf0..1e6b6c430be90 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -363,7 +363,7 @@ impl Once { /// assert!(handle.join().is_err()); /// assert_eq!(INIT.is_completed(), false); /// ``` - #[stable(feature = "once_is_completed", since = "1.44.0")] + #[stable(feature = "once_is_completed", since = "1.43.0")] #[inline] pub fn is_completed(&self) -> bool { // An `Acquire` load is enough because that makes all the initialization diff --git a/src/libstd/sys/cloudabi/io.rs b/src/libstd/sys/cloudabi/io.rs index 976e122463d1b..d5f475b4310fd 100644 --- a/src/libstd/sys/cloudabi/io.rs +++ b/src/libstd/sys/cloudabi/io.rs @@ -1,5 +1,6 @@ use crate::mem; +#[derive(Copy, Clone)] pub struct IoSlice<'a>(&'a [u8]); impl<'a> IoSlice<'a> { diff --git a/src/libstd/sys/cloudabi/mutex.rs b/src/libstd/sys/cloudabi/mutex.rs index 4aa25e2505271..580ab0e8ad863 100644 --- a/src/libstd/sys/cloudabi/mutex.rs +++ b/src/libstd/sys/cloudabi/mutex.rs @@ -53,16 +53,16 @@ pub struct ReentrantMutex { } impl ReentrantMutex { - pub unsafe fn uninitialized() -> ReentrantMutex { + pub const unsafe fn uninitialized() -> ReentrantMutex { ReentrantMutex { lock: UnsafeCell::new(MaybeUninit::uninit()), recursion: UnsafeCell::new(MaybeUninit::uninit()), } } - pub unsafe fn init(&mut self) { - self.lock = UnsafeCell::new(MaybeUninit::new(AtomicU32::new(abi::LOCK_UNLOCKED.0))); - self.recursion = UnsafeCell::new(MaybeUninit::new(0)); + pub unsafe fn init(&self) { + *self.lock.get() = MaybeUninit::new(AtomicU32::new(abi::LOCK_UNLOCKED.0)); + *self.recursion.get() = MaybeUninit::new(0); } pub unsafe fn try_lock(&self) -> bool { diff --git a/src/libstd/sys/hermit/io.rs b/src/libstd/sys/hermit/io.rs index 976e122463d1b..d5f475b4310fd 100644 --- a/src/libstd/sys/hermit/io.rs +++ b/src/libstd/sys/hermit/io.rs @@ -1,5 +1,6 @@ use crate::mem; +#[derive(Copy, Clone)] pub struct IoSlice<'a>(&'a [u8]); impl<'a> IoSlice<'a> { diff --git a/src/libstd/sys/hermit/mutex.rs b/src/libstd/sys/hermit/mutex.rs index b5c75f738d228..3d4813209cbc4 100644 --- a/src/libstd/sys/hermit/mutex.rs +++ b/src/libstd/sys/hermit/mutex.rs @@ -46,13 +46,13 @@ pub struct ReentrantMutex { } impl ReentrantMutex { - pub unsafe fn uninitialized() -> ReentrantMutex { + pub const unsafe fn uninitialized() -> ReentrantMutex { ReentrantMutex { inner: ptr::null() } } #[inline] - pub unsafe fn init(&mut self) { - let _ = abi::recmutex_init(&mut self.inner as *mut *const c_void); + pub unsafe fn init(&self) { + let _ = abi::recmutex_init(&self.inner as *const *const c_void as *mut _); } #[inline] diff --git a/src/libstd/sys/sgx/io.rs b/src/libstd/sys/sgx/io.rs index 976e122463d1b..d5f475b4310fd 100644 --- a/src/libstd/sys/sgx/io.rs +++ b/src/libstd/sys/sgx/io.rs @@ -1,5 +1,6 @@ use crate::mem; +#[derive(Copy, Clone)] pub struct IoSlice<'a>(&'a [u8]); impl<'a> IoSlice<'a> { diff --git a/src/libstd/sys/sgx/mutex.rs b/src/libstd/sys/sgx/mutex.rs index eebbea1b285ba..4911c2f538769 100644 --- a/src/libstd/sys/sgx/mutex.rs +++ b/src/libstd/sys/sgx/mutex.rs @@ -75,7 +75,7 @@ impl ReentrantMutex { } #[inline] - pub unsafe fn init(&mut self) {} + pub unsafe fn init(&self) {} #[inline] pub unsafe fn lock(&self) { diff --git a/src/libstd/sys/unix/alloc.rs b/src/libstd/sys/unix/alloc.rs index 77417e4133127..8e193935460eb 100644 --- a/src/libstd/sys/unix/alloc.rs +++ b/src/libstd/sys/unix/alloc.rs @@ -52,7 +52,12 @@ unsafe impl GlobalAlloc for System { } } -#[cfg(any(target_os = "android", target_os = "redox", target_os = "solaris"))] +#[cfg(any( + target_os = "android", + target_os = "illumos", + target_os = "redox", + target_os = "solaris" +))] #[inline] unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { // On android we currently target API level 9 which unfortunately @@ -75,7 +80,12 @@ unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { libc::memalign(layout.align(), layout.size()) as *mut u8 } -#[cfg(not(any(target_os = "android", target_os = "redox", target_os = "solaris")))] +#[cfg(not(any( + target_os = "android", + target_os = "illumos", + target_os = "redox", + target_os = "solaris" +)))] #[inline] unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { let mut out = ptr::null_mut(); diff --git a/src/libstd/sys/unix/args.rs b/src/libstd/sys/unix/args.rs index 09acc3f6e3ea8..4c3e8542d576d 100644 --- a/src/libstd/sys/unix/args.rs +++ b/src/libstd/sys/unix/args.rs @@ -65,6 +65,7 @@ impl DoubleEndedIterator for Args { target_os = "netbsd", target_os = "openbsd", target_os = "solaris", + target_os = "illumos", target_os = "emscripten", target_os = "haiku", target_os = "l4re", diff --git a/src/libstd/sys/unix/env.rs b/src/libstd/sys/unix/env.rs index 984bcfa45099b..7f5e9b04dba4b 100644 --- a/src/libstd/sys/unix/env.rs +++ b/src/libstd/sys/unix/env.rs @@ -97,6 +97,17 @@ pub mod os { pub const EXE_EXTENSION: &str = ""; } +#[cfg(target_os = "illumos")] +pub mod os { + pub const FAMILY: &str = "unix"; + pub const OS: &str = "illumos"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; +} + #[cfg(target_os = "haiku")] pub mod os { pub const FAMILY: &str = "unix"; diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs index 8a99836912a33..1bba56e334a2e 100644 --- a/src/libstd/sys/unix/fd.rs +++ b/src/libstd/sys/unix/fd.rs @@ -153,6 +153,7 @@ impl FileDesc { #[cfg(not(any( target_env = "newlib", target_os = "solaris", + target_os = "illumos", target_os = "emscripten", target_os = "fuchsia", target_os = "l4re", @@ -169,6 +170,7 @@ impl FileDesc { #[cfg(any( target_env = "newlib", target_os = "solaris", + target_os = "illumos", target_os = "emscripten", target_os = "fuchsia", target_os = "l4re", diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index ab2a871b92df4..f3b6bcf0340ec 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -22,6 +22,7 @@ use libc::fstatat64; target_os = "linux", target_os = "emscripten", target_os = "solaris", + target_os = "illumos", target_os = "l4re", target_os = "fuchsia", target_os = "redox" @@ -200,7 +201,12 @@ pub struct DirEntry { // on Solaris and Fuchsia because a) it uses a zero-length // array to store the name, b) its lifetime between readdir // calls is not guaranteed. - #[cfg(any(target_os = "solaris", target_os = "fuchsia", target_os = "redox"))] + #[cfg(any( + target_os = "solaris", + target_os = "illumos", + target_os = "fuchsia", + target_os = "redox" + ))] name: Box<[u8]>, } @@ -403,7 +409,10 @@ impl fmt::Debug for ReadDir { impl Iterator for ReadDir { type Item = io::Result; - #[cfg(any(target_os = "solaris", target_os = "fuchsia", target_os = "redox"))] + #[cfg(any(target_os = "solaris", + target_os = "fuchsia", + target_os = "redox", + target_os = "illumos"))] fn next(&mut self) -> Option> { use crate::slice; @@ -441,7 +450,10 @@ impl Iterator for ReadDir { } } - #[cfg(not(any(target_os = "solaris", target_os = "fuchsia", target_os = "redox")))] + #[cfg(not(any(target_os = "solaris", + target_os = "fuchsia", + target_os = "redox", + target_os = "illumos")))] fn next(&mut self) -> Option> { if self.end_of_stream { return None; @@ -514,12 +526,12 @@ impl DirEntry { lstat(&self.path()) } - #[cfg(any(target_os = "solaris", target_os = "haiku"))] + #[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "haiku"))] pub fn file_type(&self) -> io::Result { lstat(&self.path()).map(|m| m.file_type()) } - #[cfg(not(any(target_os = "solaris", target_os = "haiku")))] + #[cfg(not(any(target_os = "solaris", target_os = "illumos", target_os = "haiku")))] pub fn file_type(&self) -> io::Result { match self.entry.d_type { libc::DT_CHR => Ok(FileType { mode: libc::S_IFCHR }), @@ -540,6 +552,7 @@ impl DirEntry { target_os = "emscripten", target_os = "android", target_os = "solaris", + target_os = "illumos", target_os = "haiku", target_os = "l4re", target_os = "fuchsia", @@ -586,7 +599,12 @@ impl DirEntry { fn name_bytes(&self) -> &[u8] { unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()).to_bytes() } } - #[cfg(any(target_os = "solaris", target_os = "fuchsia", target_os = "redox"))] + #[cfg(any( + target_os = "solaris", + target_os = "illumos", + target_os = "fuchsia", + target_os = "redox" + ))] fn name_bytes(&self) -> &[u8] { &*self.name } diff --git a/src/libstd/sys/unix/io.rs b/src/libstd/sys/unix/io.rs index b4a64e93c842b..deb5ee76bd035 100644 --- a/src/libstd/sys/unix/io.rs +++ b/src/libstd/sys/unix/io.rs @@ -3,6 +3,7 @@ use crate::slice; use libc::{c_void, iovec}; +#[derive(Copy, Clone)] #[repr(transparent)] pub struct IoSlice<'a> { vec: iovec, diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index fbcb006ecdf11..0154609d939f3 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -17,6 +17,8 @@ pub use crate::os::freebsd as platform; pub use crate::os::fuchsia as platform; #[cfg(all(not(doc), target_os = "haiku"))] pub use crate::os::haiku as platform; +#[cfg(all(not(doc), target_os = "illumos"))] +pub use crate::os::illumos as platform; #[cfg(all(not(doc), target_os = "ios"))] pub use crate::os::ios as platform; #[cfg(all(not(doc), target_os = "l4re"))] diff --git a/src/libstd/sys/unix/mutex.rs b/src/libstd/sys/unix/mutex.rs index b38375a2e03c5..103d87e3d2f91 100644 --- a/src/libstd/sys/unix/mutex.rs +++ b/src/libstd/sys/unix/mutex.rs @@ -92,11 +92,11 @@ unsafe impl Send for ReentrantMutex {} unsafe impl Sync for ReentrantMutex {} impl ReentrantMutex { - pub unsafe fn uninitialized() -> ReentrantMutex { + pub const unsafe fn uninitialized() -> ReentrantMutex { ReentrantMutex { inner: UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER) } } - pub unsafe fn init(&mut self) { + pub unsafe fn init(&self) { let mut attr = MaybeUninit::::uninit(); let result = libc::pthread_mutexattr_init(attr.as_mut_ptr()); debug_assert_eq!(result, 0); diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index 91f7d1524ccef..a9cd5094997bd 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -54,7 +54,7 @@ extern "C" { ), link_name = "__errno" )] - #[cfg_attr(target_os = "solaris", link_name = "___errno")] + #[cfg_attr(any(target_os = "solaris", target_os = "illumos"), link_name = "___errno")] #[cfg_attr( any(target_os = "macos", target_os = "ios", target_os = "freebsd"), link_name = "__error" @@ -357,7 +357,7 @@ pub fn current_exe() -> io::Result { } } -#[cfg(any(target_os = "solaris"))] +#[cfg(any(target_os = "solaris", target_os = "illumos"))] pub fn current_exe() -> io::Result { extern "C" { fn getexecname() -> *const c_char; diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs index 9ce5f3d014cc1..eed6fbf13b7d2 100644 --- a/src/libstd/sys/unix/rand.rs +++ b/src/libstd/sys/unix/rand.rs @@ -12,6 +12,7 @@ pub fn hashmap_random_keys() -> (u64, u64) { #[cfg(all( unix, + not(target_os = "macos"), not(target_os = "ios"), not(target_os = "openbsd"), not(target_os = "freebsd"), @@ -92,6 +93,42 @@ mod imp { } } +#[cfg(target_os = "macos")] +mod imp { + use crate::fs::File; + use crate::io::Read; + use crate::sys::os::errno; + use libc::{c_int, c_void, size_t}; + + fn getentropy_fill_bytes(v: &mut [u8]) -> bool { + weak!(fn getentropy(*mut c_void, size_t) -> c_int); + + getentropy + .get() + .map(|f| { + // getentropy(2) permits a maximum buffer size of 256 bytes + for s in v.chunks_mut(256) { + let ret = unsafe { f(s.as_mut_ptr() as *mut c_void, s.len()) }; + if ret == -1 { + panic!("unexpected getentropy error: {}", errno()); + } + } + true + }) + .unwrap_or(false) + } + + pub fn fill_bytes(v: &mut [u8]) { + if getentropy_fill_bytes(v) { + return; + } + + // for older macos which doesn't support getentropy + let mut file = File::open("/dev/urandom").expect("failed to open /dev/urandom"); + file.read_exact(v).expect("failed to read /dev/urandom") + } +} + #[cfg(target_os = "openbsd")] mod imp { use crate::sys::os::errno; diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs index 9e8be55075578..5e10357835056 100644 --- a/src/libstd/sys/unix/stack_overflow.rs +++ b/src/libstd/sys/unix/stack_overflow.rs @@ -33,6 +33,7 @@ impl Drop for Handler { target_os = "dragonfly", target_os = "freebsd", target_os = "solaris", + target_os = "illumos", all(target_os = "netbsd", not(target_vendor = "rumprun")), target_os = "openbsd" ))] @@ -45,8 +46,9 @@ mod imp { use libc::{mmap, munmap}; use libc::{sigaction, sighandler_t, SA_ONSTACK, SA_SIGINFO, SIGBUS, SIG_DFL}; use libc::{sigaltstack, SIGSTKSZ, SS_DISABLE}; - use libc::{MAP_ANON, MAP_PRIVATE, PROT_READ, PROT_WRITE, SIGSEGV}; + use libc::{MAP_ANON, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SIGSEGV}; + use crate::sys::unix::os::page_size; use crate::sys_common::thread_info; #[cfg(any(target_os = "linux", target_os = "android"))] @@ -137,12 +139,22 @@ mod imp { } unsafe fn get_stackp() -> *mut libc::c_void { - let stackp = - mmap(ptr::null_mut(), SIGSTKSZ, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + let stackp = mmap( + ptr::null_mut(), + SIGSTKSZ + page_size(), + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, + -1, + 0, + ); if stackp == MAP_FAILED { panic!("failed to allocate an alternative stack"); } - stackp + let guard_result = libc::mprotect(stackp, page_size(), PROT_NONE); + if guard_result != 0 { + panic!("failed to set up alternative stack guard page"); + } + stackp.add(page_size()) } #[cfg(any( @@ -151,7 +163,8 @@ mod imp { target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", - target_os = "solaris" + target_os = "solaris", + target_os = "illumos" ))] unsafe fn get_stack() -> libc::stack_t { libc::stack_t { ss_sp: get_stackp(), ss_flags: 0, ss_size: SIGSTKSZ } @@ -190,7 +203,9 @@ mod imp { ss_size: SIGSTKSZ, }; sigaltstack(&stack, ptr::null_mut()); - munmap(handler._data, SIGSTKSZ); + // We know from `get_stackp` that the alternate stack we installed is part of a mapping + // that started one page earlier, so walk back a page and unmap from there. + munmap(handler._data.sub(page_size()), SIGSTKSZ + page_size()); } } } @@ -201,6 +216,7 @@ mod imp { target_os = "dragonfly", target_os = "freebsd", target_os = "solaris", + target_os = "illumos", all(target_os = "netbsd", not(target_vendor = "rumprun")), target_os = "openbsd" )))] diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 674d4c7113801..47f55efe9b752 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -125,7 +125,7 @@ impl Thread { } } - #[cfg(target_os = "solaris")] + #[cfg(any(target_os = "solaris", target_os = "illumos"))] pub fn set_name(name: &CStr) { weak! { fn pthread_setname_np( @@ -148,7 +148,7 @@ impl Thread { target_os = "redox" ))] pub fn set_name(_name: &CStr) { - // Newlib, Illumos, Haiku, and Emscripten have no way to set a thread name. + // Newlib, Haiku, and Emscripten have no way to set a thread name. } #[cfg(target_os = "fuchsia")] pub fn set_name(_name: &CStr) { diff --git a/src/libstd/sys/vxworks/io.rs b/src/libstd/sys/vxworks/io.rs index f1a2c8446ff8b..0f68ebf8da9cc 100644 --- a/src/libstd/sys/vxworks/io.rs +++ b/src/libstd/sys/vxworks/io.rs @@ -3,6 +3,7 @@ use crate::slice; use libc::{c_void, iovec}; +#[derive(Copy, Clone)] #[repr(transparent)] pub struct IoSlice<'a> { vec: iovec, diff --git a/src/libstd/sys/vxworks/mutex.rs b/src/libstd/sys/vxworks/mutex.rs index b38375a2e03c5..103d87e3d2f91 100644 --- a/src/libstd/sys/vxworks/mutex.rs +++ b/src/libstd/sys/vxworks/mutex.rs @@ -92,11 +92,11 @@ unsafe impl Send for ReentrantMutex {} unsafe impl Sync for ReentrantMutex {} impl ReentrantMutex { - pub unsafe fn uninitialized() -> ReentrantMutex { + pub const unsafe fn uninitialized() -> ReentrantMutex { ReentrantMutex { inner: UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER) } } - pub unsafe fn init(&mut self) { + pub unsafe fn init(&self) { let mut attr = MaybeUninit::::uninit(); let result = libc::pthread_mutexattr_init(attr.as_mut_ptr()); debug_assert_eq!(result, 0); diff --git a/src/libstd/sys/wasi/io.rs b/src/libstd/sys/wasi/io.rs index ee20ea6dab87a..0ad2e152855b7 100644 --- a/src/libstd/sys/wasi/io.rs +++ b/src/libstd/sys/wasi/io.rs @@ -1,6 +1,7 @@ use crate::marker::PhantomData; use crate::slice; +#[derive(Copy, Clone)] #[repr(transparent)] pub struct IoSlice<'a> { vec: wasi::Ciovec, diff --git a/src/libstd/sys/wasm/io.rs b/src/libstd/sys/wasm/io.rs index 976e122463d1b..d5f475b4310fd 100644 --- a/src/libstd/sys/wasm/io.rs +++ b/src/libstd/sys/wasm/io.rs @@ -1,5 +1,6 @@ use crate::mem; +#[derive(Copy, Clone)] pub struct IoSlice<'a>(&'a [u8]); impl<'a> IoSlice<'a> { diff --git a/src/libstd/sys/wasm/mutex.rs b/src/libstd/sys/wasm/mutex.rs index 07238d087308f..7aaf1b3a343b6 100644 --- a/src/libstd/sys/wasm/mutex.rs +++ b/src/libstd/sys/wasm/mutex.rs @@ -47,11 +47,11 @@ impl Mutex { pub struct ReentrantMutex {} impl ReentrantMutex { - pub unsafe fn uninitialized() -> ReentrantMutex { + pub const unsafe fn uninitialized() -> ReentrantMutex { ReentrantMutex {} } - pub unsafe fn init(&mut self) {} + pub unsafe fn init(&self) {} pub unsafe fn lock(&self) {} diff --git a/src/libstd/sys/wasm/mutex_atomics.rs b/src/libstd/sys/wasm/mutex_atomics.rs index 90c628a19c22e..268a53bb5641c 100644 --- a/src/libstd/sys/wasm/mutex_atomics.rs +++ b/src/libstd/sys/wasm/mutex_atomics.rs @@ -80,11 +80,11 @@ unsafe impl Sync for ReentrantMutex {} // released when this recursion counter reaches 0. impl ReentrantMutex { - pub unsafe fn uninitialized() -> ReentrantMutex { + pub const unsafe fn uninitialized() -> ReentrantMutex { ReentrantMutex { owner: AtomicU32::new(0), recursions: UnsafeCell::new(0) } } - pub unsafe fn init(&mut self) { + pub unsafe fn init(&self) { // nothing to do... } diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 4d377341be30f..7f93ef8795308 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -295,6 +295,7 @@ pub struct WSADATA { pub szSystemStatus: [u8; WSASYS_STATUS_LEN + 1], } +#[derive(Copy, Clone)] #[repr(C)] pub struct WSABUF { pub len: ULONG, @@ -1044,6 +1045,10 @@ compat_fn! { _dwBufferSize: DWORD) -> BOOL { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0 } + pub fn GetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime: LPFILETIME) + -> () { + GetSystemTimeAsFileTime(lpSystemTimeAsFileTime) + } pub fn SleepConditionVariableSRW(ConditionVariable: PCONDITION_VARIABLE, SRWLock: PSRWLOCK, dwMilliseconds: DWORD, diff --git a/src/libstd/sys/windows/io.rs b/src/libstd/sys/windows/io.rs index 9d8018fd5e864..5525d2832526f 100644 --- a/src/libstd/sys/windows/io.rs +++ b/src/libstd/sys/windows/io.rs @@ -2,6 +2,7 @@ use crate::marker::PhantomData; use crate::slice; use crate::sys::c; +#[derive(Copy, Clone)] #[repr(transparent)] pub struct IoSlice<'a> { vec: c::WSABUF, diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs index 281eb294c65d8..63dfc640908e9 100644 --- a/src/libstd/sys/windows/mutex.rs +++ b/src/libstd/sys/windows/mutex.rs @@ -109,7 +109,7 @@ impl Mutex { 0 => {} n => return n as *mut _, } - let mut re = box ReentrantMutex::uninitialized(); + let re = box ReentrantMutex::uninitialized(); re.init(); let re = Box::into_raw(re); match self.lock.compare_and_swap(0, re as usize, Ordering::SeqCst) { @@ -157,11 +157,11 @@ unsafe impl Send for ReentrantMutex {} unsafe impl Sync for ReentrantMutex {} impl ReentrantMutex { - pub fn uninitialized() -> ReentrantMutex { + pub const fn uninitialized() -> ReentrantMutex { ReentrantMutex { inner: UnsafeCell::new(MaybeUninit::uninit()) } } - pub unsafe fn init(&mut self) { + pub unsafe fn init(&self) { c::InitializeCriticalSection((&mut *self.inner.get()).as_mut_ptr()); } diff --git a/src/libstd/sys/windows/time.rs b/src/libstd/sys/windows/time.rs index 86667ca7ab2dd..900260169c767 100644 --- a/src/libstd/sys/windows/time.rs +++ b/src/libstd/sys/windows/time.rs @@ -74,7 +74,7 @@ impl SystemTime { pub fn now() -> SystemTime { unsafe { let mut t: SystemTime = mem::zeroed(); - c::GetSystemTimeAsFileTime(&mut t.t); + c::GetSystemTimePreciseAsFileTime(&mut t.t); t } } diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index 289ee07babfcf..e9b1e86d7ae49 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -28,7 +28,7 @@ pub fn lock() -> impl Drop { unsafe { LOCK.lock(); - return Guard; + Guard } } @@ -70,7 +70,7 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt:: let mut print_path = move |fmt: &mut fmt::Formatter<'_>, bows: BytesOrWideString<'_>| { output_filename(fmt, bows, print_fmt, cwd.as_ref()) }; - write!(fmt, "stack backtrace:\n")?; + writeln!(fmt, "stack backtrace:")?; let mut bt_fmt = BacktraceFmt::new(fmt, print_fmt, &mut print_path); bt_fmt.add_context()?; let mut idx = 0; diff --git a/src/libstd/sys_common/net.rs b/src/libstd/sys_common/net.rs index 135e8308afaea..cdd3d2edf1fa1 100644 --- a/src/libstd/sys_common/net.rs +++ b/src/libstd/sys_common/net.rs @@ -17,7 +17,7 @@ cfg_if::cfg_if! { if #[cfg(any( target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", - target_os = "openbsd", target_os = "netbsd", + target_os = "openbsd", target_os = "netbsd", target_os = "illumos", target_os = "solaris", target_os = "haiku", target_os = "l4re"))] { use crate::sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP; use crate::sys::net::netc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP; @@ -43,7 +43,7 @@ cfg_if::cfg_if! { if #[cfg(any( target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", - target_os = "solaris"))] { + target_os = "solaris", target_os = "illumos"))] { use libc::c_uchar; type IpV4MultiCastType = c_uchar; } else { diff --git a/src/libstd/sys_common/process.rs b/src/libstd/sys_common/process.rs index 042641852b3e9..f3a2962098b4d 100644 --- a/src/libstd/sys_common/process.rs +++ b/src/libstd/sys_common/process.rs @@ -47,7 +47,7 @@ impl CommandEnv { } } for (key, maybe_val) in self.vars.iter() { - if let &Some(ref val) = maybe_val { + if let Some(ref val) = maybe_val { env::set_var(key, val); } else { env::remove_var(key); diff --git a/src/libstd/sys_common/remutex.rs b/src/libstd/sys_common/remutex.rs index a1ad44a3666ed..4f19bbc467f33 100644 --- a/src/libstd/sys_common/remutex.rs +++ b/src/libstd/sys_common/remutex.rs @@ -3,7 +3,6 @@ use crate::marker; use crate::ops::Deref; use crate::panic::{RefUnwindSafe, UnwindSafe}; use crate::sys::mutex as sys; -use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult}; /// A re-entrant mutual exclusion /// @@ -11,8 +10,7 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult}; /// available. The thread which has already locked the mutex can lock it /// multiple times without blocking, preventing a common source of deadlocks. pub struct ReentrantMutex { - inner: Box, - poison: poison::Flag, + inner: sys::ReentrantMutex, data: T, } @@ -39,23 +37,30 @@ pub struct ReentrantMutexGuard<'a, T: 'a> { // funny underscores due to how Deref currently works (it disregards field // privacy). __lock: &'a ReentrantMutex, - __poison: poison::Guard, } impl !marker::Send for ReentrantMutexGuard<'_, T> {} impl ReentrantMutex { /// Creates a new reentrant mutex in an unlocked state. - pub fn new(t: T) -> ReentrantMutex { - unsafe { - let mut mutex = ReentrantMutex { - inner: box sys::ReentrantMutex::uninitialized(), - poison: poison::Flag::new(), - data: t, - }; - mutex.inner.init(); - mutex - } + /// + /// # Unsafety + /// + /// This function is unsafe because it is required that `init` is called + /// once this mutex is in its final resting place, and only then are the + /// lock/unlock methods safe. + pub const unsafe fn new(t: T) -> ReentrantMutex { + ReentrantMutex { inner: sys::ReentrantMutex::uninitialized(), data: t } + } + + /// Initializes this mutex so it's ready for use. + /// + /// # Unsafety + /// + /// Unsafe to call more than once, and must be called after this will no + /// longer move in memory. + pub unsafe fn init(&self) { + self.inner.init(); } /// Acquires a mutex, blocking the current thread until it is able to do so. @@ -70,7 +75,7 @@ impl ReentrantMutex { /// If another user of this mutex panicked while holding the mutex, then /// this call will return failure if the mutex would otherwise be /// acquired. - pub fn lock(&self) -> LockResult> { + pub fn lock(&self) -> ReentrantMutexGuard<'_, T> { unsafe { self.inner.lock() } ReentrantMutexGuard::new(&self) } @@ -87,12 +92,8 @@ impl ReentrantMutex { /// If another user of this mutex panicked while holding the mutex, then /// this call will return failure if the mutex would otherwise be /// acquired. - pub fn try_lock(&self) -> TryLockResult> { - if unsafe { self.inner.try_lock() } { - Ok(ReentrantMutexGuard::new(&self)?) - } else { - Err(TryLockError::WouldBlock) - } + pub fn try_lock(&self) -> Option> { + if unsafe { self.inner.try_lock() } { Some(ReentrantMutexGuard::new(&self)) } else { None } } } @@ -108,11 +109,8 @@ impl Drop for ReentrantMutex { impl fmt::Debug for ReentrantMutex { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.try_lock() { - Ok(guard) => f.debug_struct("ReentrantMutex").field("data", &*guard).finish(), - Err(TryLockError::Poisoned(err)) => { - f.debug_struct("ReentrantMutex").field("data", &**err.get_ref()).finish() - } - Err(TryLockError::WouldBlock) => { + Some(guard) => f.debug_struct("ReentrantMutex").field("data", &*guard).finish(), + None => { struct LockedPlaceholder; impl fmt::Debug for LockedPlaceholder { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -127,11 +125,8 @@ impl fmt::Debug for ReentrantMutex { } impl<'mutex, T> ReentrantMutexGuard<'mutex, T> { - fn new(lock: &'mutex ReentrantMutex) -> LockResult> { - poison::map_result(lock.poison.borrow(), |guard| ReentrantMutexGuard { - __lock: lock, - __poison: guard, - }) + fn new(lock: &'mutex ReentrantMutex) -> ReentrantMutexGuard<'mutex, T> { + ReentrantMutexGuard { __lock: lock } } } @@ -147,7 +142,6 @@ impl Drop for ReentrantMutexGuard<'_, T> { #[inline] fn drop(&mut self) { unsafe { - self.__lock.poison.done(&self.__poison); self.__lock.inner.unlock(); } } @@ -162,13 +156,17 @@ mod tests { #[test] fn smoke() { - let m = ReentrantMutex::new(()); + let m = unsafe { + let m = ReentrantMutex::new(()); + m.init(); + m + }; { - let a = m.lock().unwrap(); + let a = m.lock(); { - let b = m.lock().unwrap(); + let b = m.lock(); { - let c = m.lock().unwrap(); + let c = m.lock(); assert_eq!(*c, ()); } assert_eq!(*b, ()); @@ -179,15 +177,19 @@ mod tests { #[test] fn is_mutex() { - let m = Arc::new(ReentrantMutex::new(RefCell::new(0))); + let m = unsafe { + let m = Arc::new(ReentrantMutex::new(RefCell::new(0))); + m.init(); + m + }; let m2 = m.clone(); - let lock = m.lock().unwrap(); + let lock = m.lock(); let child = thread::spawn(move || { - let lock = m2.lock().unwrap(); + let lock = m2.lock(); assert_eq!(*lock.borrow(), 4950); }); for i in 0..100 { - let lock = m.lock().unwrap(); + let lock = m.lock(); *lock.borrow_mut() += i; } drop(lock); @@ -196,17 +198,21 @@ mod tests { #[test] fn trylock_works() { - let m = Arc::new(ReentrantMutex::new(())); + let m = unsafe { + let m = Arc::new(ReentrantMutex::new(())); + m.init(); + m + }; let m2 = m.clone(); - let _lock = m.try_lock().unwrap(); - let _lock2 = m.try_lock().unwrap(); + let _lock = m.try_lock(); + let _lock2 = m.try_lock(); thread::spawn(move || { let lock = m2.try_lock(); - assert!(lock.is_err()); + assert!(lock.is_none()); }) .join() .unwrap(); - let _lock3 = m.try_lock().unwrap(); + let _lock3 = m.try_lock(); } pub struct Answer<'a>(pub ReentrantMutexGuard<'a, RefCell>); @@ -215,22 +221,4 @@ mod tests { *self.0.borrow_mut() = 42; } } - - #[test] - fn poison_works() { - let m = Arc::new(ReentrantMutex::new(RefCell::new(0))); - let mc = m.clone(); - let result = thread::spawn(move || { - let lock = mc.lock().unwrap(); - *lock.borrow_mut() = 1; - let lock2 = mc.lock().unwrap(); - *lock.borrow_mut() = 2; - let _answer = Answer(lock2); - panic!("What the answer to my lifetimes dilemma is?"); - }) - .join(); - assert!(result.is_err()); - let r = m.lock().err().unwrap().into_inner(); - assert_eq!(*r.borrow(), 42); - } } diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index 1d96cdfe46042..498950e682101 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -599,24 +599,16 @@ impl Wtf8 { #[inline] fn final_lead_surrogate(&self) -> Option { - let len = self.len(); - if len < 3 { - return None; - } - match &self.bytes[(len - 3)..] { - &[0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)), + match self.bytes { + [.., 0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)), _ => None, } } #[inline] fn initial_trail_surrogate(&self) -> Option { - let len = self.len(); - if len < 3 { - return None; - } - match &self.bytes[..3] { - &[0xED, b2 @ 0xB0..=0xBF, b3] => Some(decode_surrogate(b2, b3)), + match self.bytes { + [0xED, b2 @ 0xB0..=0xBF, b3, ..] => Some(decode_surrogate(b2, b3)), _ => None, } } diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 0dc43c7e6510a..282e268efd206 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -1082,8 +1082,8 @@ impl ThreadId { /// it is not guaranteed which values new threads will return, and this may /// change across Rust versions. #[unstable(feature = "thread_id_value", issue = "67939")] - pub fn as_u64(&self) -> u64 { - self.0.get() + pub fn as_u64(&self) -> NonZeroU64 { + self.0 } } diff --git a/src/libtest/cli.rs b/src/libtest/cli.rs index 5317063b80d11..aac454c023c80 100644 --- a/src/libtest/cli.rs +++ b/src/libtest/cli.rs @@ -213,7 +213,7 @@ macro_rules! unstable_optflag { let opt = $matches.opt_present($option_name); if !$allow_unstable && opt { return Err(format!( - "The \"{}\" flag is only accepted on the nightly compiler", + "The \"{}\" flag is only accepted on the nightly compiler with -Z unstable-options", $option_name )); } diff --git a/src/libtest/console.rs b/src/libtest/console.rs index 149c9202e6e2d..ff741e3bd53be 100644 --- a/src/libtest/console.rs +++ b/src/libtest/console.rs @@ -169,7 +169,7 @@ pub fn list_tests_console(opts: &TestOpts, tests: Vec) -> io::Res if !quiet { if ntest != 0 || nbench != 0 { - writeln!(output, "")?; + writeln!(output)?; } writeln!(output, "{}, {}", plural(ntest, "test"), plural(nbench, "benchmark"))?; diff --git a/src/libtest/formatters/mod.rs b/src/libtest/formatters/mod.rs index a64c0fc263d80..1fb840520a656 100644 --- a/src/libtest/formatters/mod.rs +++ b/src/libtest/formatters/mod.rs @@ -36,5 +36,5 @@ pub(crate) fn write_stderr_delimiter(test_output: &mut Vec, test_name: &Test Some(_) => test_output.push(b'\n'), None => (), } - write!(test_output, "---- {} stderr ----\n", test_name).unwrap(); + writeln!(test_output, "---- {} stderr ----", test_name).unwrap(); } diff --git a/src/libtest/helpers/concurrency.rs b/src/libtest/helpers/concurrency.rs index 6b0c8a8af32b4..e8f3820558a6d 100644 --- a/src/libtest/helpers/concurrency.rs +++ b/src/libtest/helpers/concurrency.rs @@ -77,6 +77,7 @@ pub fn get_concurrency() -> usize { target_os = "linux", target_os = "macos", target_os = "solaris", + target_os = "illumos", ))] fn num_cpus() -> usize { unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize } diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs index aab8d012fdf68..077005371c0cf 100644 --- a/src/libtest/stats.rs +++ b/src/libtest/stats.rs @@ -204,7 +204,7 @@ impl Stats for [f64] { } fn median(&self) -> f64 { - self.percentile(50 as f64) + self.percentile(50_f64) } fn var(&self) -> f64 { @@ -230,7 +230,7 @@ impl Stats for [f64] { } fn std_dev_pct(&self) -> f64 { - let hundred = 100 as f64; + let hundred = 100_f64; (self.std_dev() / self.mean()) * hundred } @@ -244,7 +244,7 @@ impl Stats for [f64] { } fn median_abs_dev_pct(&self) -> f64 { - let hundred = 100 as f64; + let hundred = 100_f64; (self.median_abs_dev() / self.median()) * hundred } @@ -257,11 +257,11 @@ impl Stats for [f64] { fn quartiles(&self) -> (f64, f64, f64) { let mut tmp = self.to_vec(); local_sort(&mut tmp); - let first = 25f64; + let first = 25_f64; let a = percentile_of_sorted(&tmp, first); - let second = 50f64; + let second = 50_f64; let b = percentile_of_sorted(&tmp, second); - let third = 75f64; + let third = 75_f64; let c = percentile_of_sorted(&tmp, third); (a, b, c) } @@ -281,7 +281,7 @@ fn percentile_of_sorted(sorted_samples: &[f64], pct: f64) -> f64 { } let zero: f64 = 0.0; assert!(zero <= pct); - let hundred = 100f64; + let hundred = 100_f64; assert!(pct <= hundred); if pct == hundred { return sorted_samples[sorted_samples.len() - 1]; @@ -307,7 +307,7 @@ pub fn winsorize(samples: &mut [f64], pct: f64) { let mut tmp = samples.to_vec(); local_sort(&mut tmp); let lo = percentile_of_sorted(&tmp, pct); - let hundred = 100 as f64; + let hundred = 100_f64; let hi = percentile_of_sorted(&tmp, hundred - pct); for samp in samples { if *samp > hi { diff --git a/src/libtest/types.rs b/src/libtest/types.rs index 2619f99592aa9..5b75d2f367fff 100644 --- a/src/libtest/types.rs +++ b/src/libtest/types.rs @@ -59,10 +59,10 @@ impl TestName { } pub fn with_padding(&self, padding: NamePadding) -> TestName { - let name = match self { - &TestName::StaticTestName(name) => Cow::Borrowed(name), - &TestName::DynTestName(ref name) => Cow::Owned(name.clone()), - &TestName::AlignedTestName(ref name, _) => name.clone(), + let name = match *self { + TestName::StaticTestName(name) => Cow::Borrowed(name), + TestName::DynTestName(ref name) => Cow::Owned(name.clone()), + TestName::AlignedTestName(ref name, _) => name.clone(), }; TestName::AlignedTestName(name, padding) diff --git a/src/libunwind/build.rs b/src/libunwind/build.rs index a24808b32506f..c8d2419ab4514 100644 --- a/src/libunwind/build.rs +++ b/src/libunwind/build.rs @@ -30,11 +30,18 @@ fn main() { } } else if target.contains("solaris") { println!("cargo:rustc-link-lib=gcc_s"); + } else if target.contains("illumos") { + println!("cargo:rustc-link-lib=gcc_s"); } else if target.contains("dragonfly") { println!("cargo:rustc-link-lib=gcc_pic"); } else if target.contains("pc-windows-gnu") { - println!("cargo:rustc-link-lib=static-nobundle=gcc_eh"); - println!("cargo:rustc-link-lib=static-nobundle=pthread"); + // This is handled in the target spec with late_link_args_[static|dynamic] + + // cfg!(bootstrap) doesn't work in build scripts + if env::var("RUSTC_STAGE").ok() == Some("0".to_string()) { + println!("cargo:rustc-link-lib=static-nobundle=gcc_eh"); + println!("cargo:rustc-link-lib=static-nobundle=pthread"); + } } else if target.contains("uwp-windows-gnu") { println!("cargo:rustc-link-lib=unwind"); } else if target.contains("fuchsia") { diff --git a/src/rtstartup/rsbegin.rs b/src/rtstartup/rsbegin.rs index f92ff9f071a48..bd1946133e8af 100644 --- a/src/rtstartup/rsbegin.rs +++ b/src/rtstartup/rsbegin.rs @@ -60,37 +60,36 @@ pub mod eh_frames { } // Unwind info registration/deregistration routines. - // See the docs of `unwind` module in libstd. + // See the docs of libpanic_unwind. extern "C" { fn rust_eh_register_frames(eh_frame_begin: *const u8, object: *mut u8); fn rust_eh_unregister_frames(eh_frame_begin: *const u8, object: *mut u8); } - unsafe fn init() { + unsafe extern "C" fn init() { // register unwind info on module startup rust_eh_register_frames(&__EH_FRAME_BEGIN__ as *const u8, &mut OBJ as *mut _ as *mut u8); } - unsafe fn uninit() { + unsafe extern "C" fn uninit() { // unregister on shutdown rust_eh_unregister_frames(&__EH_FRAME_BEGIN__ as *const u8, &mut OBJ as *mut _ as *mut u8); } - // MSVC-specific init/uninit routine registration - pub mod ms_init { - // .CRT$X?? sections are roughly analogous to ELF's .init_array and .fini_array, - // except that they exploit the fact that linker will sort them alphabitically, - // so e.g., sections with names between .CRT$XIA and .CRT$XIZ are guaranteed to be - // placed between those two, without requiring any ordering of objects on the linker - // command line. - // Note that ordering of same-named sections from different objects is not guaranteed. - // Since .CRT$XIA contains init array's header symbol, which must always come first, - // we place our initialization callback into .CRT$XIB. + // MinGW-specific init/uninit routine registration + pub mod mingw_init { + // MinGW's startup objects (crt0.o / dllcrt0.o) will invoke global constructors in the + // .ctors and .dtors sections on startup and exit. In the case of DLLs, this is done when + // the DLL is loaded and unloaded. + // + // The linker will sort the sections, which ensures that our callbacks are located at the + // end of the list. Since constructors are run in reverse order, this ensures that our + // callbacks are the first and last ones executed. - #[link_section = ".CRT$XIB"] // .CRT$XI? : C initialization callbacks - pub static P_INIT: unsafe fn() = super::init; + #[link_section = ".ctors.65535"] // .ctors.* : C initialization callbacks + pub static P_INIT: unsafe extern "C" fn() = super::init; - #[link_section = ".CRT$XTY"] // .CRT$XT? : C termination callbacks - pub static P_UNINIT: unsafe fn() = super::uninit; + #[link_section = ".dtors.65535"] // .dtors.* : C termination callbacks + pub static P_UNINIT: unsafe extern "C" fn() = super::uninit; } } diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 90d24d20737db..9e8614e3b6d34 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -67,7 +67,11 @@ extern "C" void LLVMInitializePasses() { } extern "C" void LLVMTimeTraceProfilerInitialize() { -#if LLVM_VERSION_GE(9, 0) +#if LLVM_VERSION_GE(10, 0) + timeTraceProfilerInitialize( + /* TimeTraceGranularity */ 0, + /* ProcName */ "rustc"); +#elif LLVM_VERSION_GE(9, 0) timeTraceProfilerInitialize(); #endif } diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 25cfee3373dc4..799adb418822d 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -1333,8 +1333,13 @@ extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign, LLVMValueRef Val, LLVMValueRef Size, bool IsVolatile) { +#if LLVM_VERSION_GE(10, 0) + return wrap(unwrap(B)->CreateMemSet( + unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile)); +#else return wrap(unwrap(B)->CreateMemSet( unwrap(Dst), unwrap(Val), unwrap(Size), DstAlign, IsVolatile)); +#endif } extern "C" LLVMValueRef diff --git a/src/stage0.txt b/src/stage0.txt index 55416b6729adb..4d9a91e38b33c 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,7 +12,7 @@ # source tarball for a stable release you'll likely see `1.x.0` for rustc and # `0.x.0` for Cargo where they were released on `date`. -date: 2020-02-29 +date: 2020-03-12 rustc: beta cargo: beta diff --git a/src/stdarch b/src/stdarch index dea57529b3695..abe96ca3b87fc 160000 --- a/src/stdarch +++ b/src/stdarch @@ -1 +1 @@ -Subproject commit dea57529b3695605909e7d327bb6551d7a10c788 +Subproject commit abe96ca3b87fcca6aa1dfcefd40d8c8d92d2e673 diff --git a/src/test/codegen-units/partitioning/extern-drop-glue.rs b/src/test/codegen-units/partitioning/extern-drop-glue.rs index 662519067d78e..1cb85382239cd 100644 --- a/src/test/codegen-units/partitioning/extern-drop-glue.rs +++ b/src/test/codegen-units/partitioning/extern-drop-glue.rs @@ -1,9 +1,9 @@ // ignore-tidy-linelength -// We specify -Z incremental here because we want to test the partitioning for +// We specify -C incremental here because we want to test the partitioning for // incremental compilation // We specify opt-level=0 because `drop_in_place` is `Internal` when optimizing -// compile-flags:-Zprint-mono-items=lazy -Zincremental=tmp/partitioning-tests/extern-drop-glue +// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/extern-drop-glue // compile-flags:-Zinline-in-all-cgus -Copt-level=0 #![allow(dead_code)] diff --git a/src/test/codegen-units/partitioning/extern-generic.rs b/src/test/codegen-units/partitioning/extern-generic.rs index c96c54312fbaa..88d6116a987fe 100644 --- a/src/test/codegen-units/partitioning/extern-generic.rs +++ b/src/test/codegen-units/partitioning/extern-generic.rs @@ -1,7 +1,7 @@ // ignore-tidy-linelength -// We specify -Z incremental here because we want to test the partitioning for +// We specify -C incremental here because we want to test the partitioning for // incremental compilation -// compile-flags:-Zprint-mono-items=eager -Zincremental=tmp/partitioning-tests/extern-generic -Zshare-generics=y +// compile-flags:-Zprint-mono-items=eager -Cincremental=tmp/partitioning-tests/extern-generic -Zshare-generics=y #![allow(dead_code)] #![crate_type="lib"] diff --git a/src/test/codegen-units/partitioning/inlining-from-extern-crate.rs b/src/test/codegen-units/partitioning/inlining-from-extern-crate.rs index e943f54a40631..7afeb0a0f367b 100644 --- a/src/test/codegen-units/partitioning/inlining-from-extern-crate.rs +++ b/src/test/codegen-units/partitioning/inlining-from-extern-crate.rs @@ -1,7 +1,7 @@ // ignore-tidy-linelength -// We specify -Z incremental here because we want to test the partitioning for +// We specify -C incremental here because we want to test the partitioning for // incremental compilation -// compile-flags:-Zprint-mono-items=lazy -Zincremental=tmp/partitioning-tests/inlining-from-extern-crate +// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/inlining-from-extern-crate // compile-flags:-Zinline-in-all-cgus #![crate_type="lib"] diff --git a/src/test/codegen-units/partitioning/local-drop-glue.rs b/src/test/codegen-units/partitioning/local-drop-glue.rs index 14a50bf579806..c082b40827878 100644 --- a/src/test/codegen-units/partitioning/local-drop-glue.rs +++ b/src/test/codegen-units/partitioning/local-drop-glue.rs @@ -1,8 +1,8 @@ // ignore-tidy-linelength -// We specify -Z incremental here because we want to test the partitioning for +// We specify -C incremental here because we want to test the partitioning for // incremental compilation // We specify opt-level=0 because `drop_in_place` is `Internal` when optimizing -// compile-flags:-Zprint-mono-items=lazy -Zincremental=tmp/partitioning-tests/local-drop-glue +// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/local-drop-glue // compile-flags:-Zinline-in-all-cgus -Copt-level=0 #![allow(dead_code)] diff --git a/src/test/codegen-units/partitioning/local-generic.rs b/src/test/codegen-units/partitioning/local-generic.rs index dcff638b0b1ce..4518166a1c9ba 100644 --- a/src/test/codegen-units/partitioning/local-generic.rs +++ b/src/test/codegen-units/partitioning/local-generic.rs @@ -1,7 +1,7 @@ // ignore-tidy-linelength -// We specify -Z incremental here because we want to test the partitioning for +// We specify -C incremental here because we want to test the partitioning for // incremental compilation -// compile-flags:-Zprint-mono-items=eager -Zincremental=tmp/partitioning-tests/local-generic +// compile-flags:-Zprint-mono-items=eager -Cincremental=tmp/partitioning-tests/local-generic #![allow(dead_code)] #![crate_type="lib"] diff --git a/src/test/codegen-units/partitioning/local-inlining-but-not-all.rs b/src/test/codegen-units/partitioning/local-inlining-but-not-all.rs index 18211fad31e58..6322f55d2b740 100644 --- a/src/test/codegen-units/partitioning/local-inlining-but-not-all.rs +++ b/src/test/codegen-units/partitioning/local-inlining-but-not-all.rs @@ -1,7 +1,7 @@ // ignore-tidy-linelength -// We specify -Z incremental here because we want to test the partitioning for +// We specify -C incremental here because we want to test the partitioning for // incremental compilation -// compile-flags:-Zprint-mono-items=lazy -Zincremental=tmp/partitioning-tests/local-inlining-but-not-all +// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/local-inlining-but-not-all // compile-flags:-Zinline-in-all-cgus=no #![allow(dead_code)] diff --git a/src/test/codegen-units/partitioning/local-inlining.rs b/src/test/codegen-units/partitioning/local-inlining.rs index 7aa83e4bf4163..d75dfc91262e2 100644 --- a/src/test/codegen-units/partitioning/local-inlining.rs +++ b/src/test/codegen-units/partitioning/local-inlining.rs @@ -1,7 +1,7 @@ // ignore-tidy-linelength -// We specify -Z incremental here because we want to test the partitioning for +// We specify -C incremental here because we want to test the partitioning for // incremental compilation -// compile-flags:-Zprint-mono-items=lazy -Zincremental=tmp/partitioning-tests/local-inlining +// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/local-inlining // compile-flags:-Zinline-in-all-cgus #![allow(dead_code)] diff --git a/src/test/codegen-units/partitioning/local-transitive-inlining.rs b/src/test/codegen-units/partitioning/local-transitive-inlining.rs index 5bc56146794bf..3cf03966865e1 100644 --- a/src/test/codegen-units/partitioning/local-transitive-inlining.rs +++ b/src/test/codegen-units/partitioning/local-transitive-inlining.rs @@ -1,7 +1,7 @@ // ignore-tidy-linelength -// We specify -Z incremental here because we want to test the partitioning for +// We specify -C incremental here because we want to test the partitioning for // incremental compilation -// compile-flags:-Zprint-mono-items=lazy -Zincremental=tmp/partitioning-tests/local-transitive-inlining +// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/local-transitive-inlining // compile-flags:-Zinline-in-all-cgus #![allow(dead_code)] diff --git a/src/test/codegen-units/partitioning/methods-are-with-self-type.rs b/src/test/codegen-units/partitioning/methods-are-with-self-type.rs index c2961ed9322ad..6c55904c1bf10 100644 --- a/src/test/codegen-units/partitioning/methods-are-with-self-type.rs +++ b/src/test/codegen-units/partitioning/methods-are-with-self-type.rs @@ -4,9 +4,9 @@ // ignore-test // ignore-tidy-linelength -// We specify -Z incremental here because we want to test the partitioning for +// We specify -C incremental here because we want to test the partitioning for // incremental compilation -// compile-flags:-Zprint-mono-items=lazy -Zincremental=tmp/partitioning-tests/methods-are-with-self-type +// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/methods-are-with-self-type #![allow(dead_code)] #![feature(start)] diff --git a/src/test/codegen-units/partitioning/regular-modules.rs b/src/test/codegen-units/partitioning/regular-modules.rs index f42dc3dfc17a9..c8ceeafd0bfe9 100644 --- a/src/test/codegen-units/partitioning/regular-modules.rs +++ b/src/test/codegen-units/partitioning/regular-modules.rs @@ -1,7 +1,7 @@ // ignore-tidy-linelength -// We specify -Z incremental here because we want to test the partitioning for +// We specify -C incremental here because we want to test the partitioning for // incremental compilation -// compile-flags:-Zprint-mono-items=eager -Zincremental=tmp/partitioning-tests/regular-modules +// compile-flags:-Zprint-mono-items=eager -Cincremental=tmp/partitioning-tests/regular-modules #![allow(dead_code)] #![crate_type="lib"] diff --git a/src/test/codegen-units/partitioning/shared-generics.rs b/src/test/codegen-units/partitioning/shared-generics.rs index 47ff94437ff37..99142dd6b7e25 100644 --- a/src/test/codegen-units/partitioning/shared-generics.rs +++ b/src/test/codegen-units/partitioning/shared-generics.rs @@ -2,7 +2,7 @@ // no-prefer-dynamic // NOTE: We always compile this test with -Copt-level=0 because higher opt-levels // prevent drop-glue from participating in share-generics. -// compile-flags:-Zprint-mono-items=eager -Zshare-generics=yes -Zincremental=tmp/partitioning-tests/shared-generics-exe -Copt-level=0 +// compile-flags:-Zprint-mono-items=eager -Zshare-generics=yes -Cincremental=tmp/partitioning-tests/shared-generics-exe -Copt-level=0 #![crate_type="rlib"] diff --git a/src/test/codegen-units/partitioning/statics.rs b/src/test/codegen-units/partitioning/statics.rs index bbded480b0c15..5eac046b810d7 100644 --- a/src/test/codegen-units/partitioning/statics.rs +++ b/src/test/codegen-units/partitioning/statics.rs @@ -1,6 +1,6 @@ -// We specify -Z incremental here because we want to test the partitioning for +// We specify -C incremental here because we want to test the partitioning for // incremental compilation -// compile-flags:-Zprint-mono-items=lazy -Zincremental=tmp/partitioning-tests/statics +// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/statics #![crate_type="rlib"] diff --git a/src/test/codegen-units/partitioning/vtable-through-const.rs b/src/test/codegen-units/partitioning/vtable-through-const.rs index 06e2ef6bb2257..5a1d95d266987 100644 --- a/src/test/codegen-units/partitioning/vtable-through-const.rs +++ b/src/test/codegen-units/partitioning/vtable-through-const.rs @@ -1,8 +1,8 @@ // ignore-tidy-linelength -// We specify -Z incremental here because we want to test the partitioning for +// We specify -C incremental here because we want to test the partitioning for // incremental compilation -// compile-flags:-Zprint-mono-items=lazy -Zincremental=tmp/partitioning-tests/vtable-through-const +// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/vtable-through-const // compile-flags:-Zinline-in-all-cgus // This test case makes sure, that references made through constants are diff --git a/src/test/codegen/catch-unwind.rs b/src/test/codegen/catch-unwind.rs new file mode 100644 index 0000000000000..3c9bc35d1c8bd --- /dev/null +++ b/src/test/codegen/catch-unwind.rs @@ -0,0 +1,19 @@ +// compile-flags: -O + +#![crate_type = "lib"] + +extern "C" { + fn bar(); +} + +// CHECK-LABEL: @foo +#[no_mangle] +pub unsafe fn foo() -> i32 { + // CHECK: call void @bar + // CHECK: ret i32 0 + std::panic::catch_unwind(|| { + bar(); + 0 + }) + .unwrap() +} diff --git a/src/test/codegen/consts.rs b/src/test/codegen/consts.rs index a89ecdfd3a901..e53e75b339bef 100644 --- a/src/test/codegen/consts.rs +++ b/src/test/codegen/consts.rs @@ -10,11 +10,11 @@ // CHECK: @STATIC = {{.*}}, align 4 // This checks the constants from inline_enum_const -// CHECK: @{{[0-9]+}} = {{.*}}, align 2 +// CHECK: @alloc5 = {{.*}}, align 2 // This checks the constants from {low,high}_align_const, they share the same // constant, but the alignment differs, so the higher one should be used -// CHECK: [[LOW_HIGH:@[0-9]+]] = {{.*}} getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* @2, i32 0, i32 0, i32 0), {{.*}}, +// CHECK: [[LOW_HIGH:@[0-9]+]] = {{.*}} getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* @alloc15, i32 0, i32 0, i32 0), {{.*}} #[derive(Copy, Clone)] // repr(i16) is required for the {low,high}_align_const test diff --git a/src/test/codegen/debug-column-msvc.rs b/src/test/codegen/debug-column-msvc.rs new file mode 100644 index 0000000000000..aad8b372a8a92 --- /dev/null +++ b/src/test/codegen/debug-column-msvc.rs @@ -0,0 +1,16 @@ +// Verify that no column information is emitted for MSVC targets +// +// only-msvc +// compile-flags: -C debuginfo=2 + +// CHECK-NOT: !DILexicalBlock({{.*}}column: {{.*}}) +// CHECK-NOT: !DILocation({{.*}}column: {{.*}}) + +pub fn add(a: u32, b: u32) -> u32 { + a + b +} + +fn main() { + let c = add(1, 2); + println!("{}", c); +} diff --git a/src/test/codegen/debug-column.rs b/src/test/codegen/debug-column.rs new file mode 100644 index 0000000000000..f348c48566d51 --- /dev/null +++ b/src/test/codegen/debug-column.rs @@ -0,0 +1,24 @@ +// Verify that debuginfo column nubmers are 1-based byte offsets. +// +// ignore-windows +// compile-flags: -C debuginfo=2 + +fn main() { + unsafe { + // Column numbers are 1-based. Regression test for #65437. + // CHECK: call void @giraffe(), !dbg [[A:!.*]] + giraffe(); + + // Column numbers use byte offests. Regression test for #67360 + // CHECK: call void @turtle(), !dbg [[B:!.*]] +/* ż */ turtle(); + + // CHECK: [[A]] = !DILocation(line: 10, column: 9, + // CHECK: [[B]] = !DILocation(line: 14, column: 10, + } +} + +extern { + fn giraffe(); + fn turtle(); +} diff --git a/src/test/codegen/remap_path_prefix/main.rs b/src/test/codegen/remap_path_prefix/main.rs index 52ffb97a5b221..4724dc3c3e593 100644 --- a/src/test/codegen/remap_path_prefix/main.rs +++ b/src/test/codegen/remap_path_prefix/main.rs @@ -12,7 +12,7 @@ mod aux_mod; include!("aux_mod.rs"); // Here we check that the expansion of the file!() macro is mapped. -// CHECK: @0 = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>, align 1 +// CHECK: @alloc1 = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>, align 1 pub static FILE_PATH: &'static str = file!(); fn main() { diff --git a/src/test/codegen/repeat-trusted-len.rs b/src/test/codegen/repeat-trusted-len.rs index 8fbe712065bde..8e08b78ad1eee 100644 --- a/src/test/codegen/repeat-trusted-len.rs +++ b/src/test/codegen/repeat-trusted-len.rs @@ -5,14 +5,9 @@ use std::iter; -// CHECK: @helper([[USIZE:i[0-9]+]] %_1) -#[no_mangle] -pub fn helper(_: usize) { -} - // CHECK-LABEL: @repeat_take_collect #[no_mangle] pub fn repeat_take_collect() -> Vec { -// CHECK: call void @llvm.memset.p0i8.[[USIZE]](i8* {{(nonnull )?}}align 1{{.*}} %{{[0-9]+}}, i8 42, [[USIZE]] 100000, i1 false) +// CHECK: call void @llvm.memset.p0i8.i{{[0-9]+}}(i8* {{(nonnull )?}}align 1{{.*}} %{{[0-9]+}}, i8 42, i{{[0-9]+}} 100000, i1 false) iter::repeat(42).take(100000).collect() } diff --git a/src/test/codegen/try-panic-abort.rs b/src/test/codegen/try-panic-abort.rs new file mode 100644 index 0000000000000..166d2bb99426d --- /dev/null +++ b/src/test/codegen/try-panic-abort.rs @@ -0,0 +1,20 @@ +// compile-flags: -C panic=abort -O + +#![crate_type = "lib"] +#![feature(unwind_attributes, core_intrinsics)] + +extern "C" { + #[unwind(allow)] + fn bar(data: *mut u8); +} +extern "Rust" { + fn catch(data: *mut u8, exception: *mut u8); +} + +// CHECK-LABEL: @foo +#[no_mangle] +pub unsafe fn foo() -> i32 { + // CHECK: call void @bar + // CHECK: ret i32 0 + std::intrinsics::r#try(|x| bar(x), 0 as *mut u8, |x, y| catch(x, y)) +} diff --git a/src/test/compile-fail/auxiliary/panic-runtime-lang-items.rs b/src/test/compile-fail/auxiliary/panic-runtime-lang-items.rs index abe34a39caf34..3e5cdad7ab936 100644 --- a/src/test/compile-fail/auxiliary/panic-runtime-lang-items.rs +++ b/src/test/compile-fail/auxiliary/panic-runtime-lang-items.rs @@ -11,5 +11,3 @@ use core::panic::PanicInfo; fn panic_impl(info: &PanicInfo) -> ! { loop {} } #[lang = "eh_personality"] fn eh_personality() {} -#[lang = "eh_unwind_resume"] -fn eh_unwind_resume() {} diff --git a/src/test/compile-fail/issue-52443.rs b/src/test/compile-fail/issue-52443.rs index 597fbbf00d53c..3a022230b39a7 100644 --- a/src/test/compile-fail/issue-52443.rs +++ b/src/test/compile-fail/issue-52443.rs @@ -7,10 +7,5 @@ fn main() { //~^ ERROR `while` is not allowed in a `const` //~| WARN denote infinite loops with [(); { for _ in 0usize.. {}; 0}]; - //~^ ERROR calls in constants are limited to constant functions - //~| ERROR calls in constants are limited to constant functions - //~| ERROR `for` is not allowed in a `const` - //~| ERROR references in constants may only refer to immutable values - //~| ERROR evaluation of constant value failed - //~| ERROR constant contains unimplemented expression type + //~^ ERROR `for` is not allowed in a `const` } diff --git a/src/test/debuginfo/pretty-std-collections.rs b/src/test/debuginfo/pretty-std-collections.rs index f8997fad9a53f..1da2042b2224a 100644 --- a/src/test/debuginfo/pretty-std-collections.rs +++ b/src/test/debuginfo/pretty-std-collections.rs @@ -17,35 +17,51 @@ // gdb-command: print btree_set // gdb-check:$1 = BTreeSet(len: 15) = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14} +// gdb-command: print empty_btree_set +// gdb-check:$2 = BTreeSet(len: 0) + // gdb-command: print btree_map -// gdb-check:$2 = BTreeMap(len: 15) = {[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 5, [6] = 6, [7] = 7, [8] = 8, [9] = 9, [10] = 10, [11] = 11, [12] = 12, [13] = 13, [14] = 14} +// gdb-check:$3 = BTreeMap(len: 15) = {[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 5, [6] = 6, [7] = 7, [8] = 8, [9] = 9, [10] = 10, [11] = 11, [12] = 12, [13] = 13, [14] = 14} + +// gdb-command: print empty_btree_map +// gdb-check:$4 = BTreeMap(len: 0) + +// gdb-command: print nasty_btree_map +// gdb-check:$5 = BTreeMap(len: 1) = {[1] = pretty_std_collections::MyLeafNode (11)} // gdb-command: print vec_deque -// gdb-check:$3 = VecDeque(len: 3, cap: 8) = {5, 3, 7} +// gdb-check:$6 = VecDeque(len: 3, cap: 8) = {5, 3, 7} // gdb-command: print vec_deque2 -// gdb-check:$4 = VecDeque(len: 7, cap: 8) = {2, 3, 4, 5, 6, 7, 8} +// gdb-check:$7 = VecDeque(len: 7, cap: 8) = {2, 3, 4, 5, 6, 7, 8} #![allow(unused_variables)] -use std::collections::BTreeSet; use std::collections::BTreeMap; +use std::collections::BTreeSet; use std::collections::VecDeque; +struct MyLeafNode(i32); // helps to ensure we don't blindly replace substring "LeafNode" fn main() { - // BTreeSet let mut btree_set = BTreeSet::new(); for i in 0..15 { btree_set.insert(i); } + let mut empty_btree_set: BTreeSet = BTreeSet::new(); + // BTreeMap let mut btree_map = BTreeMap::new(); for i in 0..15 { btree_map.insert(i, i); } + let mut empty_btree_map: BTreeMap = BTreeMap::new(); + + let mut nasty_btree_map: BTreeMap = BTreeMap::new(); + nasty_btree_map.insert(1, MyLeafNode(11)); + // VecDeque let mut vec_deque = VecDeque::new(); vec_deque.push_back(5); @@ -63,4 +79,6 @@ fn main() { zzz(); // #break } -fn zzz() { () } +fn zzz() { + () +} diff --git a/src/test/incremental/change_symbol_export_status.rs b/src/test/incremental/change_symbol_export_status.rs index f3de46d99ddc0..9b3b381d6210a 100644 --- a/src/test/incremental/change_symbol_export_status.rs +++ b/src/test/incremental/change_symbol_export_status.rs @@ -2,10 +2,8 @@ // compile-flags: -Zquery-dep-graph #![feature(rustc_attrs)] -#![allow(private_no_mangle_fns)] - -#![rustc_partition_codegened(module="change_symbol_export_status-mod1", cfg="rpass2")] -#![rustc_partition_reused(module="change_symbol_export_status-mod2", cfg="rpass2")] +#![rustc_partition_codegened(module = "change_symbol_export_status-mod1", cfg = "rpass2")] +#![rustc_partition_reused(module = "change_symbol_export_status-mod2", cfg = "rpass2")] // This test case makes sure that a change in symbol visibility is detected by // our dependency tracking. We do this by changing a module's visibility to diff --git a/src/test/incremental/hashes/call_expressions.rs b/src/test/incremental/hashes/call_expressions.rs index 50d3657d417f3..3706ab4a02075 100644 --- a/src/test/incremental/hashes/call_expressions.rs +++ b/src/test/incremental/hashes/call_expressions.rs @@ -25,7 +25,7 @@ pub fn change_callee_function() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_callee_function() { callee2(1, 2) @@ -40,7 +40,7 @@ pub fn change_argument_function() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_argument_function() { callee1(1, 3) @@ -55,10 +55,10 @@ mod change_callee_indirectly_function { #[cfg(not(cfail1))] use super::callee2 as callee; - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] + #[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] pub fn change_callee_indirectly_function() { @@ -81,7 +81,7 @@ pub fn change_callee_method() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_callee_method() { let s = Struct; @@ -98,7 +98,7 @@ pub fn change_argument_method() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_argument_method() { let s = Struct; @@ -115,7 +115,7 @@ pub fn change_ufcs_callee_method() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_ufcs_callee_method() { let s = Struct; @@ -132,7 +132,7 @@ pub fn change_argument_method_ufcs() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_argument_method_ufcs() { let s = Struct; @@ -149,10 +149,10 @@ pub fn change_to_ufcs() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] -// One might think this would be expanded in the HirBody/Mir, but it actually -// results in slightly different Hir/Mir. +// One might think this would be expanded in the hir_owner_nodes/Mir, but it actually +// results in slightly different hir_owner/Mir. pub fn change_to_ufcs() { let s = Struct; Struct::method1(&s, 'x', true); @@ -171,7 +171,7 @@ pub mod change_ufcs_callee_indirectly { #[cfg(not(cfail1))] use super::Struct2 as Struct; - #[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] diff --git a/src/test/incremental/hashes/closure_expressions.rs b/src/test/incremental/hashes/closure_expressions.rs index 08693560d0b6e..b1e9ed678c4c5 100644 --- a/src/test/incremental/hashes/closure_expressions.rs +++ b/src/test/incremental/hashes/closure_expressions.rs @@ -21,7 +21,7 @@ pub fn change_closure_body() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] pub fn change_closure_body() { let _ = || 3u32; @@ -37,7 +37,7 @@ pub fn add_parameter() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_parameter() { let x = 0u32; @@ -53,7 +53,7 @@ pub fn change_parameter_pattern() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_parameter_pattern() { let _ = |(x,): (u32,)| x; @@ -68,7 +68,7 @@ pub fn add_move() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] pub fn add_move() { let _ = move || 1; @@ -84,8 +84,8 @@ pub fn add_type_ascription_to_parameter() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, typeck_tables_of")] -#[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, typeck_tables_of")] +#[rustc_clean(cfg = "cfail3")] pub fn add_type_ascription_to_parameter() { let closure = |x: u32| x + 1u32; let _: u32 = closure(1); @@ -101,7 +101,7 @@ pub fn change_parameter_type() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_parameter_type() { let closure = |x: u16| (x as u64) + 1; diff --git a/src/test/incremental/hashes/consts.rs b/src/test/incremental/hashes/consts.rs index 3d2eed89636e8..6e0db6a49aae2 100644 --- a/src/test/incremental/hashes/consts.rs +++ b/src/test/incremental/hashes/consts.rs @@ -19,7 +19,7 @@ const CONST_VISIBILITY: u8 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] pub const CONST_VISIBILITY: u8 = 0; @@ -29,7 +29,7 @@ pub const CONST_VISIBILITY: u8 = 0; const CONST_CHANGE_TYPE_1: i32 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_1: u32 = 0; @@ -39,13 +39,13 @@ const CONST_CHANGE_TYPE_1: u32 = 0; const CONST_CHANGE_TYPE_2: Option = None; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_2: Option = None; // Change value between simple literals -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_VALUE_1: i16 = { #[cfg(cfail1)] @@ -57,7 +57,7 @@ const CONST_CHANGE_VALUE_1: i16 = { // Change value between expressions -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_VALUE_2: i16 = { #[cfg(cfail1)] @@ -67,7 +67,7 @@ const CONST_CHANGE_VALUE_2: i16 = { { 1 + 2 } }; -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_VALUE_3: i16 = { #[cfg(cfail1)] @@ -77,7 +77,7 @@ const CONST_CHANGE_VALUE_3: i16 = { { 2 * 3 } }; -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_VALUE_4: i16 = { #[cfg(cfail1)] @@ -99,11 +99,11 @@ mod const_change_type_indirectly { #[cfg(not(cfail1))] use super::ReferencedType2 as Type; - #[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_INDIRECTLY_1: Type = Type; - #[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_INDIRECTLY_2: Option = None; } diff --git a/src/test/incremental/hashes/enum_constructors.rs b/src/test/incremental/hashes/enum_constructors.rs index 575b2e92966ea..99c50f7e17356 100644 --- a/src/test/incremental/hashes/enum_constructors.rs +++ b/src/test/incremental/hashes/enum_constructors.rs @@ -34,7 +34,7 @@ pub fn change_field_value_struct_like() -> Enum { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_field_value_struct_like() -> Enum { Enum::Struct { @@ -57,7 +57,7 @@ pub fn change_field_order_struct_like() -> Enum { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] // FIXME(michaelwoerister):Interesting. I would have thought that that changes the MIR. And it // would if it were not all constants @@ -96,7 +96,7 @@ pub fn change_constructor_path_struct_like() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_constructor_path_struct_like() { let _ = Enum2::Struct { @@ -119,7 +119,7 @@ pub fn change_constructor_variant_struct_like() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_constructor_variant_struct_like() { let _ = Enum2::Struct2 { @@ -139,7 +139,7 @@ pub mod change_constructor_path_indirectly_struct_like { #[rustc_clean( cfg="cfail2", - except="fn_sig,Hir,HirBody,optimized_mir,mir_built,\ + except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,mir_built,\ typeck_tables_of" )] #[rustc_clean(cfg="cfail3")] @@ -161,7 +161,7 @@ pub mod change_constructor_variant_indirectly_struct_like { #[cfg(not(cfail1))] use super::Enum2::Struct2 as Variant; - #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built")] #[rustc_clean(cfg="cfail3")] pub fn function() -> Enum2 { Variant { @@ -180,7 +180,7 @@ pub fn change_field_value_tuple_like() -> Enum { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_field_value_tuple_like() -> Enum { Enum::Tuple(0, 1, 3) @@ -197,7 +197,7 @@ pub fn change_constructor_path_tuple_like() { #[cfg(not(cfail1))] #[rustc_clean( cfg="cfail2", - except="HirBody,optimized_mir,mir_built,typeck_tables_of" + except="hir_owner_nodes,optimized_mir,mir_built,typeck_tables_of" )] #[rustc_clean(cfg="cfail3")] pub fn change_constructor_path_tuple_like() { @@ -215,7 +215,7 @@ pub fn change_constructor_variant_tuple_like() { #[cfg(not(cfail1))] #[rustc_clean( cfg="cfail2", - except="HirBody,optimized_mir,mir_built,typeck_tables_of" + except="hir_owner_nodes,optimized_mir,mir_built,typeck_tables_of" )] #[rustc_clean(cfg="cfail3")] pub fn change_constructor_variant_tuple_like() { @@ -232,7 +232,7 @@ pub mod change_constructor_path_indirectly_tuple_like { #[rustc_clean( cfg="cfail2", - except="fn_sig,Hir,HirBody,optimized_mir,mir_built,\ + except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,mir_built,\ typeck_tables_of" )] #[rustc_clean(cfg="cfail3")] @@ -251,7 +251,7 @@ pub mod change_constructor_variant_indirectly_tuple_like { #[cfg(not(cfail1))] use super::Enum2::Tuple2 as Variant; - #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn function() -> Enum2 { Variant(0, 1, 2) @@ -278,7 +278,7 @@ pub fn change_constructor_path_c_like() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_constructor_path_c_like() { let _ = Clike2::B; @@ -293,7 +293,7 @@ pub fn change_constructor_variant_c_like() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_constructor_variant_c_like() { let _ = Clike::C; @@ -309,7 +309,7 @@ pub mod change_constructor_path_indirectly_c_like { #[rustc_clean( cfg="cfail2", - except="fn_sig,Hir,HirBody,optimized_mir,mir_built,\ + except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,mir_built,\ typeck_tables_of" )] #[rustc_clean(cfg="cfail3")] @@ -328,7 +328,7 @@ pub mod change_constructor_variant_indirectly_c_like { #[cfg(not(cfail1))] use super::Clike::B as Variant; - #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built")] #[rustc_clean(cfg="cfail3")] pub fn function() -> Clike { Variant diff --git a/src/test/incremental/hashes/enum_defs.rs b/src/test/incremental/hashes/enum_defs.rs index 7256c1aa15326..624870cc9ec8f 100644 --- a/src/test/incremental/hashes/enum_defs.rs +++ b/src/test/incremental/hashes/enum_defs.rs @@ -26,7 +26,7 @@ enum EnumVisibility { A } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] pub enum EnumVisibility { A @@ -42,7 +42,7 @@ enum EnumChangeNameCStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumChangeNameCStyleVariant { Variant1, @@ -59,7 +59,7 @@ enum EnumChangeNameTupleStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumChangeNameTupleStyleVariant { Variant1, @@ -76,7 +76,7 @@ enum EnumChangeNameStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumChangeNameStructStyleVariant { Variant1, @@ -93,7 +93,7 @@ enum EnumChangeValueCStyleVariant0 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] enum EnumChangeValueCStyleVariant0 { Variant1, @@ -109,7 +109,7 @@ enum EnumChangeValueCStyleVariant1 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumChangeValueCStyleVariant1 { Variant1, @@ -125,7 +125,7 @@ enum EnumAddCStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumAddCStyleVariant { Variant1, @@ -142,7 +142,7 @@ enum EnumRemoveCStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumRemoveCStyleVariant { Variant1, @@ -157,7 +157,7 @@ enum EnumAddTupleStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumAddTupleStyleVariant { Variant1, @@ -174,7 +174,7 @@ enum EnumRemoveTupleStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumRemoveTupleStyleVariant { Variant1, @@ -189,7 +189,7 @@ enum EnumAddStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumAddStructStyleVariant { Variant1, @@ -206,7 +206,7 @@ enum EnumRemoveStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumRemoveStructStyleVariant { Variant1, @@ -221,7 +221,7 @@ enum EnumChangeFieldTypeTupleStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] enum EnumChangeFieldTypeTupleStyleVariant { Variant1(u32, @@ -238,7 +238,7 @@ enum EnumChangeFieldTypeStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] enum EnumChangeFieldTypeStructStyleVariant { Variant1, @@ -257,7 +257,7 @@ enum EnumChangeFieldNameStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumChangeFieldNameStructStyleVariant { Variant1 { a: u32, c: u32 }, @@ -272,7 +272,7 @@ enum EnumChangeOrderTupleStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] enum EnumChangeOrderTupleStyleVariant { Variant1( @@ -289,7 +289,7 @@ enum EnumChangeFieldOrderStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumChangeFieldOrderStructStyleVariant { Variant1 { b: f32, a: u32 }, @@ -304,7 +304,7 @@ enum EnumAddFieldTupleStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumAddFieldTupleStyleVariant { Variant1(u32, u32, u32), @@ -319,7 +319,7 @@ enum EnumAddFieldStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumAddFieldStructStyleVariant { Variant1 { a: u32, b: u32, c: u32 }, @@ -335,7 +335,7 @@ enum EnumAddMustUse { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] #[must_use] enum EnumAddMustUse { @@ -353,7 +353,7 @@ enum EnumAddReprC { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] #[repr(C)] enum EnumAddReprC { @@ -531,7 +531,7 @@ enum EnumSwapUsageTypeParameters { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] enum EnumSwapUsageTypeParameters { Variant1 { @@ -552,7 +552,7 @@ enum EnumSwapUsageLifetimeParameters<'a, 'b> { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] enum EnumSwapUsageLifetimeParameters<'a, 'b> { Variant1 { @@ -577,7 +577,7 @@ mod change_field_type_indirectly_tuple_style { #[cfg(not(cfail1))] use super::ReferencedType2 as FieldType; - #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] enum TupleStyle { Variant1( @@ -595,7 +595,7 @@ mod change_field_type_indirectly_struct_style { #[cfg(not(cfail1))] use super::ReferencedType2 as FieldType; - #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] enum StructStyle { Variant1 { @@ -618,7 +618,7 @@ mod change_trait_bound_indirectly { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="Hir,HirBody,predicates_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] enum Enum { Variant1(T) @@ -634,7 +634,7 @@ mod change_trait_bound_indirectly_where { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="Hir,HirBody,predicates_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] enum Enum where T: Trait { Variant1(T) diff --git a/src/test/incremental/hashes/exported_vs_not.rs b/src/test/incremental/hashes/exported_vs_not.rs index ef275cabeaff9..4ea58705017ee 100644 --- a/src/test/incremental/hashes/exported_vs_not.rs +++ b/src/test/incremental/hashes/exported_vs_not.rs @@ -7,8 +7,8 @@ #![crate_type="rlib"] // Case 1: The function body is not exported to metadata. If the body changes, -// the hash of the HirBody node should change, but not the hash of -// either the Hir or the Metadata node. +// the hash of the hir_owner_nodes node should change, but not the hash of +// either the hir_owner or the Metadata node. #[cfg(cfail1)] pub fn body_not_exported_to_metadata() -> u32 { @@ -16,7 +16,7 @@ pub fn body_not_exported_to_metadata() -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn body_not_exported_to_metadata() -> u32 { 2 @@ -25,7 +25,7 @@ pub fn body_not_exported_to_metadata() -> u32 { // Case 2: The function body *is* exported to metadata because the function is -// marked as #[inline]. Only the hash of the Hir depnode should be +// marked as #[inline]. Only the hash of the hir_owner depnode should be // unaffected by a change to the body. #[cfg(cfail1)] @@ -35,7 +35,7 @@ pub fn body_exported_to_metadata_because_of_inline() -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] #[inline] pub fn body_exported_to_metadata_because_of_inline() -> u32 { @@ -45,7 +45,7 @@ pub fn body_exported_to_metadata_because_of_inline() -> u32 { // Case 2: The function body *is* exported to metadata because the function is -// generic. Only the hash of the Hir depnode should be +// generic. Only the hash of the hir_owner depnode should be // unaffected by a change to the body. #[cfg(cfail1)] @@ -55,7 +55,7 @@ pub fn body_exported_to_metadata_because_of_generic() -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] #[inline] pub fn body_exported_to_metadata_because_of_generic() -> u32 { diff --git a/src/test/incremental/hashes/for_loops.rs b/src/test/incremental/hashes/for_loops.rs index 70820dfaea4a0..d3d5a69c171f9 100644 --- a/src/test/incremental/hashes/for_loops.rs +++ b/src/test/incremental/hashes/for_loops.rs @@ -25,7 +25,7 @@ pub fn change_loop_body() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_loop_body() { let mut _x = 0; @@ -48,7 +48,7 @@ pub fn change_iteration_variable_name() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_iteration_variable_name() { let mut _x = 0; @@ -71,7 +71,7 @@ pub fn change_iteration_variable_pattern() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_iteration_variable_pattern() { let mut _x = 0; @@ -94,7 +94,7 @@ pub fn change_iterable() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, promoted_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, promoted_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_iterable() { let mut _x = 0; @@ -116,7 +116,7 @@ pub fn add_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_break() { let mut _x = 0; @@ -139,7 +139,7 @@ pub fn add_loop_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] pub fn add_loop_label() { let mut _x = 0; @@ -162,7 +162,7 @@ pub fn add_loop_label_to_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] pub fn add_loop_label_to_break() { let mut _x = 0; @@ -187,7 +187,7 @@ pub fn change_break_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_break_label() { let mut _x = 0; @@ -212,7 +212,7 @@ pub fn add_loop_label_to_continue() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] pub fn add_loop_label_to_continue() { let mut _x = 0; @@ -237,7 +237,7 @@ pub fn change_continue_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_continue_label() { let mut _x = 0; @@ -262,7 +262,7 @@ pub fn change_continue_to_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_continue_to_break() { let mut _x = 0; diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs index 9cc2d3bcf6045..a6b936fcbcf89 100644 --- a/src/test/incremental/hashes/function_interfaces.rs +++ b/src/test/incremental/hashes/function_interfaces.rs @@ -9,198 +9,196 @@ // revisions: cfail1 cfail2 cfail3 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans - #![allow(warnings)] #![feature(linkage)] #![feature(rustc_attrs)] #![crate_type = "rlib"] - // Add Parameter --------------------------------------------------------------- #[cfg(cfail1)] pub fn add_parameter() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", - except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")] +#[rustc_clean( + cfg = "cfail2", + except = "hir_owner, hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of, fn_sig" +)] #[rustc_clean(cfg = "cfail3")] pub fn add_parameter(p: i32) {} - // Add Return Type ------------------------------------------------------------- #[cfg(cfail1)] pub fn add_return_type() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes")] #[rustc_clean(cfg = "cfail3")] pub fn add_return_type() -> () {} - // Change Parameter Type ------------------------------------------------------- #[cfg(cfail1)] pub fn type_of_parameter(p: i32) {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", - except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")] +#[rustc_clean( + cfg = "cfail2", + except = "hir_owner, hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of, fn_sig" +)] #[rustc_clean(cfg = "cfail3")] pub fn type_of_parameter(p: i64) {} - // Change Parameter Type Reference --------------------------------------------- #[cfg(cfail1)] pub fn type_of_parameter_ref(p: &i32) {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", - except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")] +#[rustc_clean( + cfg = "cfail2", + except = "hir_owner, hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of, fn_sig" +)] #[rustc_clean(cfg = "cfail3")] pub fn type_of_parameter_ref(p: &mut i32) {} - // Change Parameter Order ------------------------------------------------------ #[cfg(cfail1)] pub fn order_of_parameters(p1: i32, p2: i64) {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", - except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")] +#[rustc_clean( + cfg = "cfail2", + except = "hir_owner, hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of, fn_sig" +)] #[rustc_clean(cfg = "cfail3")] pub fn order_of_parameters(p2: i64, p1: i32) {} - // Unsafe ---------------------------------------------------------------------- #[cfg(cfail1)] pub fn make_unsafe() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", - except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")] +#[rustc_clean( + cfg = "cfail2", + except = "hir_owner, hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of, fn_sig" +)] #[rustc_clean(cfg = "cfail3")] pub unsafe fn make_unsafe() {} - // Extern ---------------------------------------------------------------------- #[cfg(cfail1)] pub fn make_extern() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, typeck_tables_of, fn_sig")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck_tables_of, fn_sig")] #[rustc_clean(cfg = "cfail3")] pub extern "C" fn make_extern() {} - // Type Parameter -------------------------------------------------------------- #[cfg(cfail1)] pub fn type_parameter() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", - except = "Hir, HirBody, generics_of, type_of, predicates_of")] +#[rustc_clean( + cfg = "cfail2", + except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of" +)] #[rustc_clean(cfg = "cfail3")] pub fn type_parameter() {} - // Lifetime Parameter ---------------------------------------------------------- #[cfg(cfail1)] pub fn lifetime_parameter() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, generics_of")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, generics_of")] #[rustc_clean(cfg = "cfail3")] pub fn lifetime_parameter<'a>() {} - // Trait Bound ----------------------------------------------------------------- #[cfg(cfail1)] pub fn trait_bound() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn trait_bound() {} - // Builtin Bound --------------------------------------------------------------- #[cfg(cfail1)] pub fn builtin_bound() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn builtin_bound() {} - // Lifetime Bound -------------------------------------------------------------- #[cfg(cfail1)] pub fn lifetime_bound<'a, T>() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", - except = "Hir, HirBody, generics_of, type_of, predicates_of")] +#[rustc_clean( + cfg = "cfail2", + except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of" +)] #[rustc_clean(cfg = "cfail3")] pub fn lifetime_bound<'a, T: 'a>() {} - // Second Trait Bound ---------------------------------------------------------- #[cfg(cfail1)] pub fn second_trait_bound() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn second_trait_bound() {} - // Second Builtin Bound -------------------------------------------------------- #[cfg(cfail1)] pub fn second_builtin_bound() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn second_builtin_bound() {} - // Second Lifetime Bound ------------------------------------------------------- #[cfg(cfail1)] pub fn second_lifetime_bound<'a, 'b, T: 'a>() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", - except = "Hir, HirBody, generics_of, type_of, predicates_of")] +#[rustc_clean( + cfg = "cfail2", + except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of" +)] #[rustc_clean(cfg = "cfail3")] pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {} - // Inline ---------------------------------------------------------------------- #[cfg(cfail1)] pub fn inline() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes")] #[rustc_clean(cfg = "cfail3")] #[inline] pub fn inline() {} - // Inline Never ---------------------------------------------------------------- #[cfg(cfail1)] @@ -208,36 +206,33 @@ pub fn inline() {} pub fn inline_never() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes")] #[rustc_clean(cfg = "cfail3")] #[inline(never)] pub fn inline_never() {} - // No Mangle ------------------------------------------------------------------- #[cfg(cfail1)] pub fn no_mangle() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes")] #[rustc_clean(cfg = "cfail3")] #[no_mangle] pub fn no_mangle() {} - // Linkage --------------------------------------------------------------------- #[cfg(cfail1)] pub fn linkage() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes")] #[rustc_clean(cfg = "cfail3")] #[linkage = "weak_odr"] pub fn linkage() {} - // Return Impl Trait ----------------------------------------------------------- #[cfg(cfail1)] @@ -246,13 +241,12 @@ pub fn return_impl_trait() -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, typeck_tables_of, fn_sig")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck_tables_of, fn_sig")] #[rustc_clean(cfg = "cfail3")] pub fn return_impl_trait() -> impl Clone { 0 } - // Change Return Impl Trait ---------------------------------------------------- #[cfg(cfail1)] @@ -267,7 +261,6 @@ pub fn change_return_impl_trait() -> impl Copy { 0u32 } - // Change Return Type Indirectly ----------------------------------------------- pub struct ReferencedType1; @@ -279,15 +272,16 @@ pub mod change_return_type_indirectly { #[cfg(not(cfail1))] use super::ReferencedType2 as ReturnType; - #[rustc_clean(cfg = "cfail2", - except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")] + #[rustc_clean( + cfg = "cfail2", + except = "hir_owner, hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of, fn_sig" + )] #[rustc_clean(cfg = "cfail3")] pub fn indirect_return_type() -> ReturnType { ReturnType {} } } - // Change Parameter Type Indirectly -------------------------------------------- pub mod change_parameter_type_indirectly { @@ -296,13 +290,14 @@ pub mod change_parameter_type_indirectly { #[cfg(not(cfail1))] use super::ReferencedType2 as ParameterType; - #[rustc_clean(cfg = "cfail2", - except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")] + #[rustc_clean( + cfg = "cfail2", + except = "hir_owner, hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of, fn_sig" + )] #[rustc_clean(cfg = "cfail3")] pub fn indirect_parameter_type(p: ParameterType) {} } - // Change Trait Bound Indirectly ----------------------------------------------- pub trait ReferencedTrait1 {} @@ -314,12 +309,11 @@ pub mod change_trait_bound_indirectly { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")] + #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn indirect_trait_bound(p: T) {} } - // Change Trait Bound Indirectly In Where Clause ------------------------------- pub mod change_trait_bound_indirectly_in_where_clause { @@ -328,7 +322,7 @@ pub mod change_trait_bound_indirectly_in_where_clause { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")] + #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn indirect_trait_bound_where(p: T) where diff --git a/src/test/incremental/hashes/if_expressions.rs b/src/test/incremental/hashes/if_expressions.rs index 4b73f1371f872..29b3f1f5b1d83 100644 --- a/src/test/incremental/hashes/if_expressions.rs +++ b/src/test/incremental/hashes/if_expressions.rs @@ -25,7 +25,7 @@ pub fn change_condition(x: bool) -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_condition(x: bool) -> u32 { if !x { @@ -46,7 +46,7 @@ pub fn change_then_branch(x: bool) -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_then_branch(x: bool) -> u32 { if x { @@ -69,7 +69,7 @@ pub fn change_else_branch(x: bool) -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_else_branch(x: bool) -> u32 { if x { @@ -94,7 +94,7 @@ pub fn add_else_branch(x: bool) -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] pub fn add_else_branch(x: bool) -> u32 { let mut ret = 1; @@ -120,7 +120,7 @@ pub fn change_condition_if_let(x: Option) -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_condition_if_let(x: Option) -> u32 { if let Some(_) = x { @@ -143,7 +143,7 @@ pub fn change_then_branch_if_let(x: Option) -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_then_branch_if_let(x: Option) -> u32 { if let Some(x) = x { @@ -166,7 +166,7 @@ pub fn change_else_branch_if_let(x: Option) -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_else_branch_if_let(x: Option) -> u32 { if let Some(x) = x { @@ -191,7 +191,7 @@ pub fn add_else_branch_if_let(x: Option) -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] pub fn add_else_branch_if_let(x: Option) -> u32 { let mut ret = 1; diff --git a/src/test/incremental/hashes/indexing_expressions.rs b/src/test/incremental/hashes/indexing_expressions.rs index 08cf19d776028..7a8cbc3566ee9 100644 --- a/src/test/incremental/hashes/indexing_expressions.rs +++ b/src/test/incremental/hashes/indexing_expressions.rs @@ -20,10 +20,10 @@ fn change_simple_index(slice: &[u32]) -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] +#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] fn change_simple_index(slice: &[u32]) -> u32 { slice[4] } @@ -37,10 +37,10 @@ fn change_lower_bound(slice: &[u32]) -> &[u32] { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] +#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] fn change_lower_bound(slice: &[u32]) -> &[u32] { &slice[2..5] } @@ -54,10 +54,10 @@ fn change_upper_bound(slice: &[u32]) -> &[u32] { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] +#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] fn change_upper_bound(slice: &[u32]) -> &[u32] { &slice[3..7] } @@ -71,10 +71,10 @@ fn add_lower_bound(slice: &[u32]) -> &[u32] { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] +#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] fn add_lower_bound(slice: &[u32]) -> &[u32] { &slice[3..4] } @@ -88,10 +88,10 @@ fn add_upper_bound(slice: &[u32]) -> &[u32] { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] +#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] fn add_upper_bound(slice: &[u32]) -> &[u32] { &slice[3..7] } @@ -105,10 +105,10 @@ fn change_mutability(slice: &mut [u32]) -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] +#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] fn change_mutability(slice: &mut [u32]) -> u32 { (&slice[3..5])[0] } @@ -122,10 +122,10 @@ fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] +#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] { &slice[3..=7] } diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs index 24d436f5f9727..a9c8457f7f260 100644 --- a/src/test/incremental/hashes/inherent_impls.rs +++ b/src/test/incremental/hashes/inherent_impls.rs @@ -23,7 +23,7 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,associated_item_def_ids")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,associated_item_def_ids")] #[rustc_clean(cfg="cfail3")] impl Foo { #[rustc_clean(cfg="cfail3")] @@ -44,7 +44,7 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="HirBody,optimized_mir,promoted_mir,mir_built,typeck_tables_of" + except="hir_owner_nodes,optimized_mir,promoted_mir,mir_built,typeck_tables_of" )] #[rustc_clean(cfg="cfail3")] pub fn method_body() { @@ -68,7 +68,7 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="HirBody,optimized_mir,promoted_mir,mir_built,typeck_tables_of" + except="hir_owner_nodes,optimized_mir,promoted_mir,mir_built,typeck_tables_of" )] #[rustc_clean(cfg="cfail3")] #[inline] @@ -85,10 +85,10 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="associated_item,Hir,HirBody")] + #[rustc_clean(cfg="cfail2", except="associated_item,hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] fn method_privacy() { } } @@ -100,7 +100,7 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] impl Foo { #[rustc_dirty(cfg="cfail2", except="type_of,predicates_of,promoted_mir")] @@ -120,7 +120,7 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="Hir,HirBody,fn_sig,typeck_tables_of,optimized_mir,mir_built" + except="hir_owner,hir_owner_nodes,fn_sig,typeck_tables_of,optimized_mir,mir_built" )] #[rustc_clean(cfg="cfail3")] pub fn method_selfmutness(&mut self) { } @@ -135,7 +135,7 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,associated_item_def_ids")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,associated_item_def_ids")] #[rustc_clean(cfg="cfail3")] impl Foo { #[rustc_clean(cfg="cfail2")] @@ -160,7 +160,7 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="Hir,HirBody,fn_sig,typeck_tables_of,optimized_mir,mir_built" + except="hir_owner,hir_owner_nodes,fn_sig,typeck_tables_of,optimized_mir,mir_built" )] #[rustc_clean(cfg="cfail3")] pub fn add_method_parameter(&self, _: i32) { } @@ -178,7 +178,7 @@ impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_method_parameter_name(&self, b: i64) { } } @@ -197,7 +197,7 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="Hir,HirBody,fn_sig,optimized_mir,mir_built,typeck_tables_of")] + except="hir_owner,hir_owner_nodes,fn_sig,optimized_mir,mir_built,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_method_return_type(&self) -> u8 { 0 } } @@ -214,7 +214,7 @@ impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] #[inline] pub fn make_method_inline(&self) -> u8 { 0 } @@ -232,7 +232,7 @@ impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_method_parameter_order(&self, b: i64, a: i64) { } } @@ -251,7 +251,7 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="Hir,HirBody,fn_sig,typeck_tables_of,optimized_mir,mir_built" + except="hir_owner,hir_owner_nodes,fn_sig,typeck_tables_of,optimized_mir,mir_built" )] #[rustc_clean(cfg="cfail3")] pub unsafe fn make_method_unsafe(&self) { } @@ -269,7 +269,7 @@ impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="Hir,HirBody,fn_sig,typeck_tables_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub extern fn make_method_extern(&self) { } } @@ -286,7 +286,7 @@ impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="Hir,HirBody,fn_sig,typeck_tables_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub extern "system" fn change_method_calling_convention(&self) { } } @@ -312,7 +312,7 @@ impl Foo { // if we lower generics before the body, then the `HirId` for // things in the body will be affected. So if you start to see // `typeck_tables_of` appear dirty, that might be the cause. -nmatsakis - #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] pub fn add_lifetime_parameter_to_method<'a>(&self) { } } @@ -340,7 +340,7 @@ impl Foo { // appear dirty, that might be the cause. -nmatsakis #[rustc_clean( cfg="cfail2", - except="Hir,HirBody,generics_of,predicates_of,type_of", + except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of", )] #[rustc_clean(cfg="cfail3")] pub fn add_type_parameter_to_method(&self) { } @@ -360,7 +360,7 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="Hir,HirBody,generics_of,predicates_of,type_of,typeck_tables_of" + except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of" )] #[rustc_clean(cfg="cfail3")] pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b: 'a>(&self) { } @@ -387,7 +387,7 @@ impl Foo { // generics before the body, then the `HirId` for things in the // body will be affected. So if you start to see `typeck_tables_of` // appear dirty, that might be the cause. -nmatsakis - #[rustc_clean(cfg="cfail2", except="Hir,HirBody,generics_of,predicates_of,\ + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,\ type_of")] #[rustc_clean(cfg="cfail3")] pub fn add_lifetime_bound_to_type_param_of_method<'a, T: 'a>(&self) { } @@ -414,7 +414,7 @@ impl Foo { // generics before the body, then the `HirId` for things in the // body will be affected. So if you start to see `typeck_tables_of` // appear dirty, that might be the cause. -nmatsakis - #[rustc_clean(cfg="cfail2", except="Hir,HirBody,predicates_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] pub fn add_trait_bound_to_type_param_of_method(&self) { } } @@ -431,7 +431,7 @@ impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] #[no_mangle] pub fn add_no_mangle_to_method(&self) { } @@ -448,7 +448,7 @@ impl Bar { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,generics_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of")] #[rustc_clean(cfg="cfail3")] impl Bar { #[rustc_clean( @@ -468,7 +468,7 @@ impl Bar { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] impl Bar { #[rustc_clean(cfg="cfail2", except="fn_sig,optimized_mir,mir_built,typeck_tables_of")] @@ -485,7 +485,7 @@ impl Bar { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] impl Bar { #[rustc_clean(cfg="cfail2")] @@ -502,7 +502,7 @@ impl Bar { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] impl Bar { #[rustc_clean(cfg="cfail2")] diff --git a/src/test/incremental/hashes/inline_asm.rs b/src/test/incremental/hashes/inline_asm.rs index c50ee73d71438..fb3c6378f74ab 100644 --- a/src/test/incremental/hashes/inline_asm.rs +++ b/src/test/incremental/hashes/inline_asm.rs @@ -33,7 +33,7 @@ pub fn change_template(a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_template(a: i32) -> i32 { @@ -69,7 +69,7 @@ pub fn change_output(a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_output(a: i32) -> i32 { @@ -105,7 +105,7 @@ pub fn change_input(_a: i32, _b: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_input(_a: i32, _b: i32) -> i32 { @@ -140,7 +140,7 @@ pub fn change_input_constraint(_a: i32, _b: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_input_constraint(_a: i32, _b: i32) -> i32 { @@ -175,7 +175,7 @@ pub fn change_clobber(_a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_clobber(_a: i32) -> i32 { @@ -210,7 +210,7 @@ pub fn change_options(_a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_options(_a: i32) -> i32 { diff --git a/src/test/incremental/hashes/let_expressions.rs b/src/test/incremental/hashes/let_expressions.rs index 68545b7daaa5c..924ed451e59f8 100644 --- a/src/test/incremental/hashes/let_expressions.rs +++ b/src/test/incremental/hashes/let_expressions.rs @@ -22,7 +22,7 @@ pub fn change_name() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir")] + except="hir_owner_nodes,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_name() { let _y = 2u64; @@ -38,7 +38,7 @@ pub fn add_type() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,typeck_tables_of,mir_built,optimized_mir")] + except="hir_owner_nodes,typeck_tables_of,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn add_type() { let _x: u32 = 2u32; @@ -54,7 +54,7 @@ pub fn change_type() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,typeck_tables_of,mir_built,optimized_mir")] + except="hir_owner_nodes,typeck_tables_of,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_type() { let _x: u8 = 2; @@ -70,7 +70,7 @@ pub fn change_mutability_of_reference_type() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,typeck_tables_of,mir_built,optimized_mir")] + except="hir_owner_nodes,typeck_tables_of,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_mutability_of_reference_type() { let _x: &mut u64; @@ -86,7 +86,7 @@ pub fn change_mutability_of_slot() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,typeck_tables_of,mir_built,optimized_mir")] + except="hir_owner_nodes,typeck_tables_of,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_mutability_of_slot() { let _x: u64 = 0; @@ -102,7 +102,7 @@ pub fn change_simple_binding_to_pattern() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,typeck_tables_of,mir_built,optimized_mir")] + except="hir_owner_nodes,typeck_tables_of,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_simple_binding_to_pattern() { let (_a, _b) = (0u8, 'x'); @@ -118,7 +118,7 @@ pub fn change_name_in_pattern() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir")] + except="hir_owner_nodes,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_name_in_pattern() { let (_a, _c) = (1u8, 'y'); @@ -134,7 +134,7 @@ pub fn add_ref_in_pattern() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,typeck_tables_of,mir_built,optimized_mir")] + except="hir_owner_nodes,typeck_tables_of,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn add_ref_in_pattern() { let (ref _a, _b) = (1u8, 'y'); @@ -150,7 +150,7 @@ pub fn add_amp_in_pattern() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,typeck_tables_of,mir_built,optimized_mir")] + except="hir_owner_nodes,typeck_tables_of,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn add_amp_in_pattern() { let (&_a, _b) = (&1u8, 'y'); @@ -166,7 +166,7 @@ pub fn change_mutability_of_binding_in_pattern() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,typeck_tables_of,mir_built,optimized_mir")] + except="hir_owner_nodes,typeck_tables_of,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_mutability_of_binding_in_pattern() { let (mut _a, _b) = (99u8, 'q'); @@ -182,7 +182,7 @@ pub fn add_initializer() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,typeck_tables_of,mir_built,optimized_mir")] + except="hir_owner_nodes,typeck_tables_of,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn add_initializer() { let _x: i16 = 3i16; @@ -198,7 +198,7 @@ pub fn change_initializer() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir")] + except="hir_owner_nodes,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_initializer() { let _x = 5u16; diff --git a/src/test/incremental/hashes/loop_expressions.rs b/src/test/incremental/hashes/loop_expressions.rs index a2222db4c59ad..65db89eb976cf 100644 --- a/src/test/incremental/hashes/loop_expressions.rs +++ b/src/test/incremental/hashes/loop_expressions.rs @@ -25,7 +25,7 @@ pub fn change_loop_body() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_loop_body() { let mut _x = 0; @@ -47,7 +47,7 @@ pub fn add_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_break() { let mut _x = 0; @@ -70,7 +70,7 @@ pub fn add_loop_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] pub fn add_loop_label() { let mut _x = 0; @@ -93,7 +93,7 @@ pub fn add_loop_label_to_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] pub fn add_loop_label_to_break() { let mut _x = 0; @@ -118,7 +118,7 @@ pub fn change_break_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_break_label() { let mut _x = 0; @@ -143,7 +143,7 @@ pub fn add_loop_label_to_continue() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] pub fn add_loop_label_to_continue() { let mut _x = 0; @@ -168,7 +168,7 @@ pub fn change_continue_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_continue_label() { let mut _x = 0; @@ -193,7 +193,7 @@ pub fn change_continue_to_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_continue_to_break() { let mut _x = 0; diff --git a/src/test/incremental/hashes/match_expressions.rs b/src/test/incremental/hashes/match_expressions.rs index 840b2222d90a1..033723a4c7796 100644 --- a/src/test/incremental/hashes/match_expressions.rs +++ b/src/test/incremental/hashes/match_expressions.rs @@ -26,7 +26,7 @@ pub fn add_arm(x: u32) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir,typeck_tables_of")] + except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_arm(x: u32) -> u32 { match x { @@ -51,7 +51,7 @@ pub fn change_order_of_arms(x: u32) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir")] + except="hir_owner_nodes,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_order_of_arms(x: u32) -> u32 { match x { @@ -75,7 +75,7 @@ pub fn add_guard_clause(x: u32, y: bool) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir,typeck_tables_of")] + except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_guard_clause(x: u32, y: bool) -> u32 { match x { @@ -99,7 +99,7 @@ pub fn change_guard_clause(x: u32, y: bool) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir,typeck_tables_of")] + except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_guard_clause(x: u32, y: bool) -> u32 { match x { @@ -123,7 +123,7 @@ pub fn add_at_binding(x: u32) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir,typeck_tables_of")] + except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_at_binding(x: u32) -> u32 { match x { @@ -147,7 +147,7 @@ pub fn change_name_of_at_binding(x: u32) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir")] + except="hir_owner_nodes,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_name_of_at_binding(x: u32) -> u32 { match x { @@ -170,7 +170,7 @@ pub fn change_simple_name_to_pattern(x: u32) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir,typeck_tables_of")] + except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_simple_name_to_pattern(x: u32) -> u32 { match (x, x & 1) { @@ -193,7 +193,7 @@ pub fn change_name_in_pattern(x: u32) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir")] + except="hir_owner_nodes,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_name_in_pattern(x: u32) -> u32 { match (x, x & 1) { @@ -216,7 +216,7 @@ pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir,typeck_tables_of")] + except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 { match (x, x & 1) { @@ -238,7 +238,7 @@ pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir,typeck_tables_of")] + except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 { match (x, x & 1) { @@ -260,7 +260,7 @@ pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", -except="HirBody,mir_built,optimized_mir,typeck_tables_of")] +except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 { match (&x, x & 1) { @@ -283,7 +283,7 @@ pub fn change_rhs_of_arm(x: u32) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir")] + except="hir_owner_nodes,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_rhs_of_arm(x: u32) -> u32 { match x { @@ -307,7 +307,7 @@ pub fn add_alternative_to_arm(x: u32) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir,typeck_tables_of")] + except="hir_owner_nodes,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_alternative_to_arm(x: u32) -> u32 { match x { diff --git a/src/test/incremental/hashes/panic_exprs.rs b/src/test/incremental/hashes/panic_exprs.rs index 70b0a5ab78cd7..9de2aaa1bfd11 100644 --- a/src/test/incremental/hashes/panic_exprs.rs +++ b/src/test/incremental/hashes/panic_exprs.rs @@ -18,7 +18,7 @@ // Indexing expression -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn indexing(slice: &[u8]) -> u8 { #[cfg(cfail1)] @@ -33,7 +33,7 @@ pub fn indexing(slice: &[u8]) -> u8 { // Arithmetic overflow plus -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_plus(val: i32) -> i32 { #[cfg(cfail1)] @@ -48,7 +48,7 @@ pub fn arithmetic_overflow_plus(val: i32) -> i32 { // Arithmetic overflow minus -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_minus(val: i32) -> i32 { #[cfg(cfail1)] @@ -63,7 +63,7 @@ pub fn arithmetic_overflow_minus(val: i32) -> i32 { // Arithmetic overflow mult -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_mult(val: i32) -> i32 { #[cfg(cfail1)] @@ -78,7 +78,7 @@ pub fn arithmetic_overflow_mult(val: i32) -> i32 { // Arithmetic overflow negation -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_negation(val: i32) -> i32 { #[cfg(cfail1)] @@ -93,7 +93,7 @@ pub fn arithmetic_overflow_negation(val: i32) -> i32 { // Division by zero -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn division_by_zero(val: i32) -> i32 { #[cfg(cfail1)] @@ -107,7 +107,7 @@ pub fn division_by_zero(val: i32) -> i32 { } // Division by zero -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn mod_by_zero(val: i32) -> i32 { #[cfg(cfail1)] @@ -122,7 +122,7 @@ pub fn mod_by_zero(val: i32) -> i32 { // shift left -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn shift_left(val: i32, shift: usize) -> i32 { #[cfg(cfail1)] @@ -137,7 +137,7 @@ pub fn shift_left(val: i32, shift: usize) -> i32 { // shift right -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn shift_right(val: i32, shift: usize) -> i32 { #[cfg(cfail1)] diff --git a/src/test/incremental/hashes/statics.rs b/src/test/incremental/hashes/statics.rs index d70ebb08b715a..caf4e12cc4b76 100644 --- a/src/test/incremental/hashes/statics.rs +++ b/src/test/incremental/hashes/statics.rs @@ -21,7 +21,7 @@ static STATIC_VISIBILITY: u8 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] pub static STATIC_VISIBILITY: u8 = 0; @@ -31,7 +31,7 @@ pub static STATIC_VISIBILITY: u8 = 0; static STATIC_MUTABILITY: u8 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] static mut STATIC_MUTABILITY: u8 = 0; @@ -41,7 +41,7 @@ static mut STATIC_MUTABILITY: u8 = 0; static STATIC_LINKAGE: u8 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] #[linkage="weak_odr"] static STATIC_LINKAGE: u8 = 0; @@ -52,7 +52,7 @@ static STATIC_LINKAGE: u8 = 0; static STATIC_NO_MANGLE: u8 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] #[no_mangle] static STATIC_NO_MANGLE: u8 = 0; @@ -63,7 +63,7 @@ static STATIC_NO_MANGLE: u8 = 0; static STATIC_THREAD_LOCAL: u8 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] #[thread_local] static STATIC_THREAD_LOCAL: u8 = 0; @@ -74,7 +74,7 @@ static STATIC_THREAD_LOCAL: u8 = 0; static STATIC_CHANGE_TYPE_1: i16 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] static STATIC_CHANGE_TYPE_1: u64 = 0; @@ -84,13 +84,13 @@ static STATIC_CHANGE_TYPE_1: u64 = 0; static STATIC_CHANGE_TYPE_2: Option = None; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] static STATIC_CHANGE_TYPE_2: Option = None; // Change value between simple literals -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] static STATIC_CHANGE_VALUE_1: i16 = { #[cfg(cfail1)] @@ -102,7 +102,7 @@ static STATIC_CHANGE_VALUE_1: i16 = { // Change value between expressions -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] static STATIC_CHANGE_VALUE_2: i16 = { #[cfg(cfail1)] @@ -112,7 +112,7 @@ static STATIC_CHANGE_VALUE_2: i16 = { { 1 + 2 } }; -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] static STATIC_CHANGE_VALUE_3: i16 = { #[cfg(cfail1)] @@ -122,7 +122,7 @@ static STATIC_CHANGE_VALUE_3: i16 = { { 2 * 3 } }; -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] static STATIC_CHANGE_VALUE_4: i16 = { #[cfg(cfail1)] @@ -144,11 +144,11 @@ mod static_change_type_indirectly { #[cfg(not(cfail1))] use super::ReferencedType2 as Type; - #[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] static STATIC_CHANGE_TYPE_INDIRECTLY_1: Type = Type; - #[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] static STATIC_CHANGE_TYPE_INDIRECTLY_2: Option = None; } diff --git a/src/test/incremental/hashes/struct_constructors.rs b/src/test/incremental/hashes/struct_constructors.rs index 7ae1798c7a2e7..006b712923b99 100644 --- a/src/test/incremental/hashes/struct_constructors.rs +++ b/src/test/incremental/hashes/struct_constructors.rs @@ -31,7 +31,7 @@ pub fn change_field_value_regular_struct() -> RegularStruct { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_field_value_regular_struct() -> RegularStruct { RegularStruct { @@ -54,7 +54,7 @@ pub fn change_field_order_regular_struct() -> RegularStruct { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_field_order_regular_struct() -> RegularStruct { RegularStruct { @@ -82,7 +82,7 @@ pub fn add_field_regular_struct() -> RegularStruct { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_field_regular_struct() -> RegularStruct { let struct1 = RegularStruct { @@ -117,7 +117,7 @@ pub fn change_field_label_regular_struct() -> RegularStruct { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_field_label_regular_struct() -> RegularStruct { let struct1 = RegularStruct { @@ -152,7 +152,7 @@ pub fn change_constructor_path_regular_struct() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_constructor_path_regular_struct() { let _ = RegularStruct2 { @@ -173,7 +173,7 @@ pub mod change_constructor_path_indirectly_regular_struct { #[rustc_clean( cfg="cfail2", - except="fn_sig,Hir,HirBody,optimized_mir,mir_built,typeck_tables_of" + except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,mir_built,typeck_tables_of" )] #[rustc_clean(cfg="cfail3")] pub fn function() -> Struct { @@ -196,7 +196,7 @@ pub fn change_field_value_tuple_struct() -> TupleStruct { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_field_value_tuple_struct() -> TupleStruct { TupleStruct(0, 1, 3) @@ -213,7 +213,7 @@ pub fn change_constructor_path_tuple_struct() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,mir_built,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_constructor_path_tuple_struct() { let _ = TupleStruct2(0, 1, 2); @@ -230,7 +230,7 @@ pub mod change_constructor_path_indirectly_tuple_struct { #[rustc_clean( cfg="cfail2", - except="fn_sig,Hir,HirBody,optimized_mir,mir_built,typeck_tables_of" + except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,mir_built,typeck_tables_of" )] #[rustc_clean(cfg="cfail3")] pub fn function() -> Struct { diff --git a/src/test/incremental/hashes/struct_defs.rs b/src/test/incremental/hashes/struct_defs.rs index e0c5696483158..a42bd9261f95d 100644 --- a/src/test/incremental/hashes/struct_defs.rs +++ b/src/test/incremental/hashes/struct_defs.rs @@ -24,13 +24,13 @@ pub struct LayoutPacked; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] +#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -41,13 +41,13 @@ pub struct LayoutPacked; struct LayoutC; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] +#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -61,13 +61,13 @@ struct LayoutC; struct TupleStructFieldType(i32); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] +#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -84,13 +84,13 @@ struct TupleStructFieldType( struct TupleStructAddField(i32); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] +#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -106,13 +106,13 @@ struct TupleStructAddField( struct TupleStructFieldVisibility(char); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] +#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -125,13 +125,13 @@ struct TupleStructFieldVisibility(pub char); struct RecordStructFieldType { x: f32 } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] +#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -148,13 +148,13 @@ struct RecordStructFieldType { struct RecordStructFieldName { x: f32 } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] +#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -167,13 +167,13 @@ struct RecordStructFieldName { y: f32 } struct RecordStructAddField { x: f32 } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] +#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -188,13 +188,13 @@ struct RecordStructAddField { struct RecordStructFieldVisibility { x: f32 } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] +#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -209,13 +209,13 @@ struct RecordStructFieldVisibility { struct AddLifetimeParameter<'a>(&'a f32, &'a f64); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_dirty(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] +#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -228,13 +228,13 @@ struct AddLifetimeParameter<'a, 'b>(&'a f32, &'b f64); struct AddLifetimeParameterBound<'a, 'b>(&'a f32, &'b f64); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_dirty(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] +#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -247,13 +247,13 @@ struct AddLifetimeParameterBound<'a, 'b: 'a>( struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_dirty(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] +#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -269,13 +269,13 @@ struct AddLifetimeParameterBoundWhereClause<'a, 'b>( struct AddTypeParameter(T1, T1); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_dirty(label="generics_of", cfg="cfail2")] #[rustc_dirty(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] +#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -293,13 +293,13 @@ struct AddTypeParameter( struct AddTypeParameterBound(T); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_dirty(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] +#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -312,13 +312,13 @@ struct AddTypeParameterBound( struct AddTypeParameterBoundWhereClause(T); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_dirty(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] +#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -332,13 +332,13 @@ struct AddTypeParameterBoundWhereClause( // fingerprint is stable (i.e., that there are no random influences like memory // addresses taken into account by the hashing algorithm). // Note: there is no #[cfg(...)], so this is ALWAYS compiled -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] +#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -351,13 +351,13 @@ pub struct EmptyStruct; struct Visibility; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] +#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -373,13 +373,13 @@ mod tuple_struct_change_field_type_indirectly { #[cfg(not(cfail1))] use super::ReferencedType2 as FieldType; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] + #[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -396,13 +396,13 @@ mod record_struct_change_field_type_indirectly { #[cfg(not(cfail1))] use super::ReferencedType2 as FieldType; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] + #[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -424,13 +424,13 @@ mod change_trait_bound_indirectly { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_dirty(label="predicates_of", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] + #[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -444,13 +444,13 @@ mod change_trait_bound_indirectly_in_where_clause { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_dirty(label="predicates_of", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] + #[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs index 3006cdccfbb55..aa39ea88e0ec0 100644 --- a/src/test/incremental/hashes/trait_defs.rs +++ b/src/test/incremental/hashes/trait_defs.rs @@ -25,8 +25,8 @@ trait TraitVisibility { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] pub trait TraitVisibility { } @@ -36,8 +36,8 @@ pub trait TraitVisibility { } trait TraitUnsafety { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] unsafe trait TraitUnsafety { } @@ -48,8 +48,8 @@ trait TraitAddMethod { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] pub trait TraitAddMethod { fn method(); } @@ -63,8 +63,8 @@ trait TraitChangeMethodName { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeMethodName { fn methodChanged(); } @@ -78,11 +78,11 @@ trait TraitAddReturnType { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddReturnType { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method() -> u32; } @@ -95,11 +95,11 @@ trait TraitChangeReturnType { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeReturnType { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method() -> u64; } @@ -112,11 +112,11 @@ trait TraitAddParameterToMethod { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddParameterToMethod { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(a: u32); } @@ -130,18 +130,18 @@ trait TraitChangeMethodParameterName { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeMethodParameterName { // FIXME(#38501) This should preferably always be clean. - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(b: u32); - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] + #[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] fn with_default(y: i32) {} } @@ -154,11 +154,11 @@ trait TraitChangeMethodParameterType { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeMethodParameterType { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(a: i64); } @@ -171,11 +171,11 @@ trait TraitChangeMethodParameterTypeRef { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeMethodParameterTypeRef { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(a: &mut i32); } @@ -188,11 +188,11 @@ trait TraitChangeMethodParametersOrder { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeMethodParametersOrder { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(b: i64, a: i32); } @@ -205,11 +205,11 @@ trait TraitAddMethodAutoImplementation { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddMethodAutoImplementation { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method() { } } @@ -223,8 +223,8 @@ trait TraitChangeOrderOfMethods { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeOrderOfMethods { fn method1(); fn method0(); @@ -239,11 +239,11 @@ trait TraitChangeModeSelfRefToMut { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeModeSelfRefToMut { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(&mut self); } @@ -255,13 +255,13 @@ trait TraitChangeModeSelfOwnToMut: Sized { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeModeSelfOwnToMut: Sized { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] + #[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] fn method(mut self) {} } @@ -273,11 +273,11 @@ trait TraitChangeModeSelfOwnToRef { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeModeSelfOwnToRef { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(&self); } @@ -290,11 +290,11 @@ trait TraitAddUnsafeModifier { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddUnsafeModifier { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] unsafe fn method(); } @@ -307,11 +307,11 @@ trait TraitAddExternModifier { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddExternModifier { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] extern fn method(); } @@ -324,11 +324,11 @@ trait TraitChangeExternCToRustIntrinsic { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeExternCToRustIntrinsic { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] extern "stdcall" fn method(); } @@ -341,11 +341,11 @@ trait TraitAddTypeParameterToMethod { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddTypeParameterToMethod { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(); } @@ -358,11 +358,11 @@ trait TraitAddLifetimeParameterToMethod { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddLifetimeParameterToMethod { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method<'a>(); } @@ -379,11 +379,11 @@ trait TraitAddTraitBoundToMethodTypeParameter { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddTraitBoundToMethodTypeParameter { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(); } @@ -396,11 +396,11 @@ trait TraitAddBuiltinBoundToMethodTypeParameter { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddBuiltinBoundToMethodTypeParameter { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(); } @@ -413,11 +413,11 @@ trait TraitAddLifetimeBoundToMethodLifetimeParameter { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddLifetimeBoundToMethodLifetimeParameter { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method<'a, 'b: 'a>(a: &'a u32, b: &'b u32); } @@ -430,11 +430,11 @@ trait TraitAddSecondTraitBoundToMethodTypeParameter { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondTraitBoundToMethodTypeParameter { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(); } @@ -447,11 +447,11 @@ trait TraitAddSecondBuiltinBoundToMethodTypeParameter { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondBuiltinBoundToMethodTypeParameter { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(); } @@ -464,11 +464,11 @@ trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method<'a, 'b, 'c: 'a + 'b>(a: &'a u32, b: &'b u32, c: &'c u32); } @@ -478,14 +478,14 @@ trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { #[cfg(cfail1)] trait TraitAddAssociatedType { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(); } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddAssociatedType { type Associated; @@ -506,11 +506,11 @@ trait TraitAddTraitBoundToAssociatedType { // Apparently the type bound contributes to the predicates of the trait, but // does not change the associated item itself. #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddTraitBoundToAssociatedType { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] type Associated: ReferencedTrait0; fn method(); @@ -527,11 +527,11 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddLifetimeBoundToAssociatedType<'a> { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] type Associated: 'a; fn method(); @@ -548,11 +548,11 @@ trait TraitAddDefaultToAssociatedType { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddDefaultToAssociatedType { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] type Associated = ReferenceType0; fn method(); @@ -567,8 +567,8 @@ trait TraitAddAssociatedConstant { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddAssociatedConstant { const Value: u32; @@ -586,15 +586,15 @@ trait TraitAddInitializerToAssociatedConstant { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddInitializerToAssociatedConstant { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] const Value: u32 = 1; - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(); } @@ -609,15 +609,15 @@ trait TraitChangeTypeOfAssociatedConstant { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeTypeOfAssociatedConstant { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] const Value: f64; - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(); } @@ -628,8 +628,8 @@ trait TraitChangeTypeOfAssociatedConstant { trait TraitAddSuperTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSuperTrait : ReferencedTrait0 { } @@ -639,8 +639,8 @@ trait TraitAddSuperTrait : ReferencedTrait0 { } trait TraitAddBuiltiBound { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddBuiltiBound : Send { } @@ -650,8 +650,8 @@ trait TraitAddBuiltiBound : Send { } trait TraitAddStaticLifetimeBound { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddStaticLifetimeBound : 'static { } @@ -661,16 +661,16 @@ trait TraitAddStaticLifetimeBound : 'static { } trait TraitAddTraitAsSecondBound : ReferencedTrait0 { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddTraitAsSecondBound : ReferencedTrait0 + ReferencedTrait1 { } #[cfg(cfail1)] trait TraitAddTraitAsSecondBoundFromBuiltin : Send { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddTraitAsSecondBoundFromBuiltin : Send + ReferencedTrait0 { } @@ -680,16 +680,16 @@ trait TraitAddTraitAsSecondBoundFromBuiltin : Send + ReferencedTrait0 { } trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 + Send { } #[cfg(cfail1)] trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin : Send { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin: Send + Copy { } @@ -699,16 +699,16 @@ trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin: Send + Copy { } trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 + 'static { } #[cfg(cfail1)] trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send + 'static { } @@ -718,8 +718,8 @@ trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send + 'static { } trait TraitAddTypeParameterToTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddTypeParameterToTrait { } @@ -729,8 +729,8 @@ trait TraitAddTypeParameterToTrait { } trait TraitAddLifetimeParameterToTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddLifetimeParameterToTrait<'a> { } @@ -740,8 +740,8 @@ trait TraitAddLifetimeParameterToTrait<'a> { } trait TraitAddTraitBoundToTypeParameterOfTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddTraitBoundToTypeParameterOfTrait { } @@ -751,8 +751,8 @@ trait TraitAddTraitBoundToTypeParameterOfTrait { } trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T> { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { } @@ -762,8 +762,8 @@ trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { } trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a, 'b> { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b> { } @@ -773,8 +773,8 @@ trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b> { } trait TraitAddBuiltinBoundToTypeParameterOfTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddBuiltinBoundToTypeParameterOfTrait { } @@ -784,8 +784,8 @@ trait TraitAddBuiltinBoundToTypeParameterOfTrait { } trait TraitAddSecondTypeParameterToTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondTypeParameterToTrait { } @@ -795,8 +795,8 @@ trait TraitAddSecondTypeParameterToTrait { } trait TraitAddSecondLifetimeParameterToTrait<'a> { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondLifetimeParameterToTrait<'a, 'b> { } @@ -806,8 +806,8 @@ trait TraitAddSecondLifetimeParameterToTrait<'a, 'b> { } trait TraitAddSecondTraitBoundToTypeParameterOfTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondTraitBoundToTypeParameterOfTrait { } @@ -817,8 +817,8 @@ trait TraitAddSecondTraitBoundToTypeParameterOfTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { } @@ -828,8 +828,8 @@ trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { } trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b, 'c> { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b + 'c, 'b, 'c> { } @@ -839,8 +839,8 @@ trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b + 'c, 'b, 'c> trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait { } @@ -855,8 +855,8 @@ struct ReferenceType1 {} trait TraitAddTraitBoundToTypeParameterOfTraitWhere { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 { } @@ -866,8 +866,8 @@ trait TraitAddTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { } @@ -877,8 +877,8 @@ trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { } trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> where 'a: 'b { } @@ -888,8 +888,8 @@ trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> where 'a: 'b trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere where T: Send { } @@ -899,8 +899,8 @@ trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere where T: Send { } trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 + ReferencedTrait1 { } @@ -911,8 +911,8 @@ trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a + 'b { } @@ -922,8 +922,8 @@ trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b + 'c { } @@ -933,8 +933,8 @@ trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> whe trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere where T: Send { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere where T: Send + Sync { } @@ -945,11 +945,11 @@ mod change_return_type_of_method_indirectly_use { #[cfg(not(cfail1))] use super::ReferenceType1 as ReturnType; - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeReturnType { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method() -> ReturnType; } } @@ -963,11 +963,11 @@ mod change_method_parameter_type_indirectly_by_use { #[cfg(not(cfail1))] use super::ReferenceType1 as ArgType; - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeArgType { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(a: ArgType); } } @@ -981,11 +981,11 @@ mod change_method_parameter_type_bound_indirectly_by_use { #[cfg(not(cfail1))] use super::ReferencedTrait1 as Bound; - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeBoundOfMethodTypeParameter { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(a: T); } } @@ -1000,11 +1000,11 @@ mod change_method_parameter_type_bound_indirectly_by_use_where { #[cfg(not(cfail1))] use super::ReferencedTrait1 as Bound; - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeBoundOfMethodTypeParameterWhere { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(a: T) where T: Bound; } } @@ -1018,8 +1018,8 @@ mod change_method_type_parameter_bound_indirectly { #[cfg(not(cfail1))] use super::ReferencedTrait1 as Bound; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeTraitBound { fn method(a: T); } @@ -1035,8 +1035,8 @@ mod change_method_type_parameter_bound_indirectly_where { #[cfg(not(cfail1))] use super::ReferencedTrait1 as Bound; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeTraitBoundWhere where T: Bound { fn method(a: T); } diff --git a/src/test/incremental/hashes/trait_impls.rs b/src/test/incremental/hashes/trait_impls.rs index fa28b2ebedd13..ddec6ff8eecdd 100644 --- a/src/test/incremental/hashes/trait_impls.rs +++ b/src/test/incremental/hashes/trait_impls.rs @@ -30,18 +30,18 @@ impl ChangeMethodNameTrait for Foo { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] pub trait ChangeMethodNameTrait { - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method_name2(); } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl ChangeMethodNameTrait for Foo { - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method_name2() { } } @@ -59,13 +59,13 @@ impl ChangeMethodBodyTrait for Foo { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl ChangeMethodBodyTrait for Foo { - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] + #[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] fn method_name() { () } @@ -86,13 +86,13 @@ impl ChangeMethodBodyTraitInlined for Foo { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl ChangeMethodBodyTraitInlined for Foo { - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] + #[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(label="hir_owner_nodes", cfg="cfail3")] #[inline] fn method_name() { panic!() @@ -117,11 +117,11 @@ pub trait ChangeMethodSelfnessTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl ChangeMethodSelfnessTrait for Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method_name(&self) { () } @@ -145,11 +145,11 @@ pub trait RemoveMethodSelfnessTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl RemoveMethodSelfnessTrait for Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method_name() {} } @@ -171,11 +171,11 @@ pub trait ChangeMethodSelfmutnessTrait { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl ChangeMethodSelfmutnessTrait for Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method_name(&mut self) {} } @@ -197,8 +197,8 @@ pub trait ChangeItemKindTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl ChangeItemKindTrait for Foo { type name = (); } @@ -223,8 +223,8 @@ pub trait RemoveItemTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl RemoveItemTrait for Foo { type TypeName = (); } @@ -248,8 +248,8 @@ pub trait AddItemTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl AddItemTrait for Foo { type TypeName = (); fn method_name() { } @@ -268,17 +268,17 @@ impl ChangeHasValueTrait for Foo { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] pub trait ChangeHasValueTrait { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method_name() { } } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl ChangeHasValueTrait for Foo { fn method_name() { } } @@ -295,11 +295,11 @@ impl AddDefaultTrait for Foo { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl AddDefaultTrait for Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] default fn method_name() { } } @@ -321,11 +321,11 @@ pub trait AddArgumentTrait { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl AddArgumentTrait for Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method_name(&self, _x: u32) { } } @@ -347,11 +347,11 @@ pub trait ChangeArgumentTypeTrait { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl ChangeArgumentTypeTrait for Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method_name(&self, _x: char) { } } @@ -370,11 +370,11 @@ impl AddTypeParameterToImpl for Bar { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl AddTypeParameterToImpl for Bar { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn id(t: T) -> T { t } } @@ -391,11 +391,11 @@ impl ChangeSelfTypeOfImpl for u32 { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl ChangeSelfTypeOfImpl for u64 { - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn id(self) -> Self { self } } @@ -412,11 +412,11 @@ impl AddLifetimeBoundToImplParameter for T { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl AddLifetimeBoundToImplParameter for T { - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn id(self) -> Self { self } } @@ -433,11 +433,11 @@ impl AddTraitBoundToImplParameter for T { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl AddTraitBoundToImplParameter for T { - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn id(self) -> Self { self } } @@ -454,11 +454,11 @@ impl AddNoMangleToMethod for Foo { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl AddNoMangleToMethod for Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] #[no_mangle] fn add_no_mangle_to_method(&self) { } } @@ -475,11 +475,11 @@ impl MakeMethodInline for Foo { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl MakeMethodInline for Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] #[inline] fn make_method_inline(&self) -> u8 { 0 } } diff --git a/src/test/incremental/hashes/type_defs.rs b/src/test/incremental/hashes/type_defs.rs index 264e8f926ffe5..495445670c006 100644 --- a/src/test/incremental/hashes/type_defs.rs +++ b/src/test/incremental/hashes/type_defs.rs @@ -24,7 +24,7 @@ type ChangePrimitiveType = i32; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangePrimitiveType = i64; @@ -35,7 +35,7 @@ type ChangePrimitiveType = i64; type ChangeMutability = &'static i32; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeMutability = &'static mut i32; @@ -46,7 +46,7 @@ type ChangeMutability = &'static mut i32; type ChangeLifetime<'a> = (&'static i32, &'a i32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeLifetime<'a> = (&'a i32, &'a i32); @@ -60,7 +60,7 @@ struct Struct2; type ChangeTypeStruct = Struct1; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeTypeStruct = Struct2; @@ -71,7 +71,7 @@ type ChangeTypeStruct = Struct2; type ChangeTypeTuple = (u32, u64); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeTypeTuple = (u32, i64); @@ -91,7 +91,7 @@ enum Enum2 { type ChangeTypeEnum = Enum1; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeTypeEnum = Enum2; @@ -102,7 +102,7 @@ type ChangeTypeEnum = Enum2; type AddTupleField = (i32, i64); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddTupleField = (i32, i64, i16); @@ -113,7 +113,7 @@ type AddTupleField = (i32, i64, i16); type ChangeNestedTupleField = (i32, (i64, i16)); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeNestedTupleField = (i32, (i64, i8)); @@ -124,7 +124,7 @@ type ChangeNestedTupleField = (i32, (i64, i8)); type AddTypeParam = (T1, T1); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddTypeParam = (T1, T2); @@ -135,7 +135,7 @@ type AddTypeParam = (T1, T2); type AddTypeParamBound = (T1, u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddTypeParamBound = (T1, u32); @@ -146,7 +146,7 @@ type AddTypeParamBound = (T1, u32); type AddTypeParamBoundWhereClause where T1: Clone = (T1, u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddTypeParamBoundWhereClause where T1: Clone+Copy = (T1, u32); @@ -157,7 +157,7 @@ type AddTypeParamBoundWhereClause where T1: Clone+Copy = (T1, u32); type AddLifetimeParam<'a> = (&'a u32, &'a u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddLifetimeParam<'a, 'b> = (&'a u32, &'b u32); @@ -168,7 +168,7 @@ type AddLifetimeParam<'a, 'b> = (&'a u32, &'b u32); type AddLifetimeParamBound<'a, 'b> = (&'a u32, &'b u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddLifetimeParamBound<'a, 'b: 'a> = (&'a u32, &'b u32); @@ -181,7 +181,7 @@ where 'b: 'a = (&'a u32, &'b u32, &'c u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddLifetimeParamBoundWhereClause<'a, 'b, 'c> where 'b: 'a, @@ -200,7 +200,7 @@ mod change_trait_bound_indirectly { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeTraitBoundIndirectly = (T, u32); } @@ -214,7 +214,7 @@ mod change_trait_bound_indirectly_in_where_clause { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeTraitBoundIndirectly where T : Trait = (T, u32); } diff --git a/src/test/incremental/hashes/unary_and_binary_exprs.rs b/src/test/incremental/hashes/unary_and_binary_exprs.rs index 776a0273ca7b6..c8b53c27b02c8 100644 --- a/src/test/incremental/hashes/unary_and_binary_exprs.rs +++ b/src/test/incremental/hashes/unary_and_binary_exprs.rs @@ -21,7 +21,7 @@ pub fn const_negation() -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn const_negation() -> i32 { -1 @@ -36,7 +36,7 @@ pub fn const_bitwise_not() -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn const_bitwise_not() -> i32 { !99 @@ -51,7 +51,7 @@ pub fn var_negation(x: i32, y: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn var_negation(x: i32, y: i32) -> i32 { -y @@ -66,7 +66,7 @@ pub fn var_bitwise_not(x: i32, y: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn var_bitwise_not(x: i32, y: i32) -> i32 { !y @@ -81,7 +81,7 @@ pub fn var_deref(x: &i32, y: &i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built,typeck_tables_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn var_deref(x: &i32, y: &i32) -> i32 { *y @@ -96,7 +96,7 @@ pub fn first_const_add() -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn first_const_add() -> i32 { 2 + 3 @@ -111,7 +111,7 @@ pub fn second_const_add() -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn second_const_add() -> i32 { 1 + 3 @@ -126,7 +126,7 @@ pub fn first_var_add(a: i32, b: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn first_var_add(a: i32, b: i32) -> i32 { b + 2 @@ -141,7 +141,7 @@ pub fn second_var_add(a: i32, b: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn second_var_add(a: i32, b: i32) -> i32 { 1 + b @@ -156,7 +156,7 @@ pub fn plus_to_minus(a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn plus_to_minus(a: i32) -> i32 { 1 - a @@ -171,7 +171,7 @@ pub fn plus_to_mult(a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn plus_to_mult(a: i32) -> i32 { 1 * a @@ -186,7 +186,7 @@ pub fn plus_to_div(a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn plus_to_div(a: i32) -> i32 { 1 / a @@ -201,7 +201,7 @@ pub fn plus_to_mod(a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn plus_to_mod(a: i32) -> i32 { 1 % a @@ -216,7 +216,7 @@ pub fn and_to_or(a: bool, b: bool) -> bool { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn and_to_or(a: bool, b: bool) -> bool { a || b @@ -231,7 +231,7 @@ pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 { 1 | a @@ -246,7 +246,7 @@ pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 { 1 ^ a @@ -261,7 +261,7 @@ pub fn bitwise_and_to_lshift(a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn bitwise_and_to_lshift(a: i32) -> i32 { a << 1 @@ -276,7 +276,7 @@ pub fn bitwise_and_to_rshift(a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn bitwise_and_to_rshift(a: i32) -> i32 { a >> 1 @@ -291,7 +291,7 @@ pub fn eq_to_uneq(a: i32) -> bool { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn eq_to_uneq(a: i32) -> bool { a != 1 @@ -306,7 +306,7 @@ pub fn eq_to_lt(a: i32) -> bool { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn eq_to_lt(a: i32) -> bool { a < 1 @@ -321,7 +321,7 @@ pub fn eq_to_gt(a: i32) -> bool { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn eq_to_gt(a: i32) -> bool { a > 1 @@ -336,7 +336,7 @@ pub fn eq_to_le(a: i32) -> bool { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn eq_to_le(a: i32) -> bool { a <= 1 @@ -351,7 +351,7 @@ pub fn eq_to_ge(a: i32) -> bool { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn eq_to_ge(a: i32) -> bool { a >= 1 @@ -368,7 +368,7 @@ pub fn type_cast(a: u8) -> u64 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built,typeck_tables_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built,typeck_tables_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn type_cast(a: u8) -> u64 { let b = a as u32; @@ -385,7 +385,7 @@ pub fn value_cast(a: u32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn value_cast(a: u32) -> i32 { 2 as i32 @@ -403,7 +403,7 @@ pub fn place() -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn place() -> i32 { let mut x = 10; @@ -423,7 +423,7 @@ pub fn rvalue() -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn rvalue() -> i32 { let mut x = 10; @@ -440,7 +440,7 @@ pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 { s[j] diff --git a/src/test/incremental/hashes/while_let_loops.rs b/src/test/incremental/hashes/while_let_loops.rs index 615f1fe1fd0b8..36e0fcdbe74d1 100644 --- a/src/test/incremental/hashes/while_let_loops.rs +++ b/src/test/incremental/hashes/while_let_loops.rs @@ -25,7 +25,7 @@ pub fn change_loop_body() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_loop_body() { let mut _x = 0; @@ -48,7 +48,7 @@ pub fn change_loop_condition() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_loop_condition() { let mut _x = 0; @@ -70,7 +70,7 @@ pub fn add_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_break() { let mut _x = 0; @@ -93,7 +93,7 @@ pub fn add_loop_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] pub fn add_loop_label() { let mut _x = 0; @@ -116,7 +116,7 @@ pub fn add_loop_label_to_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] pub fn add_loop_label_to_break() { let mut _x = 0; @@ -141,7 +141,7 @@ pub fn change_break_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_break_label() { let mut _x = 0; @@ -166,7 +166,7 @@ pub fn add_loop_label_to_continue() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] pub fn add_loop_label_to_continue() { let mut _x = 0; @@ -191,7 +191,7 @@ pub fn change_continue_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_continue_label() { let mut _x = 0; @@ -216,7 +216,7 @@ pub fn change_continue_to_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_continue_to_break() { let mut _x = 0; diff --git a/src/test/incremental/hashes/while_loops.rs b/src/test/incremental/hashes/while_loops.rs index a427ffb96e339..83f09bd7be614 100644 --- a/src/test/incremental/hashes/while_loops.rs +++ b/src/test/incremental/hashes/while_loops.rs @@ -25,7 +25,7 @@ pub fn change_loop_body() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_loop_body() { let mut _x = 0; @@ -48,7 +48,7 @@ pub fn change_loop_condition() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_loop_condition() { let mut _x = 0; @@ -70,7 +70,7 @@ pub fn add_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir, typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_break() { let mut _x = 0; @@ -93,7 +93,7 @@ pub fn add_loop_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] pub fn add_loop_label() { let mut _x = 0; @@ -116,7 +116,7 @@ pub fn add_loop_label_to_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] pub fn add_loop_label_to_break() { let mut _x = 0; @@ -141,7 +141,7 @@ pub fn change_break_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_break_label() { let mut _x = 0; @@ -166,7 +166,7 @@ pub fn add_loop_label_to_continue() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] pub fn add_loop_label_to_continue() { let mut _x = 0; @@ -191,7 +191,7 @@ pub fn change_continue_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_continue_label() { let mut _x = 0; @@ -216,7 +216,7 @@ pub fn change_continue_to_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_continue_to_break() { let mut _x = 0; diff --git a/src/test/incremental/ich_method_call_trait_scope.rs b/src/test/incremental/ich_method_call_trait_scope.rs index 9dfd2ae2511b1..847bce7ef90b0 100644 --- a/src/test/incremental/ich_method_call_trait_scope.rs +++ b/src/test/incremental/ich_method_call_trait_scope.rs @@ -26,15 +26,15 @@ mod mod3 { #[cfg(rpass2)] use Trait2; - #[rustc_clean(label="Hir", cfg="rpass2")] - #[rustc_clean(label="HirBody", cfg="rpass2")] + #[rustc_clean(label="hir_owner", cfg="rpass2")] + #[rustc_clean(label="hir_owner_nodes", cfg="rpass2")] #[rustc_dirty(label="typeck_tables_of", cfg="rpass2")] fn bar() { ().method(); } - #[rustc_clean(label="Hir", cfg="rpass2")] - #[rustc_clean(label="HirBody", cfg="rpass2")] + #[rustc_clean(label="hir_owner", cfg="rpass2")] + #[rustc_clean(label="hir_owner_nodes", cfg="rpass2")] #[rustc_clean(label="typeck_tables_of", cfg="rpass2")] fn baz() { 22; // no method call, traits in scope don't matter diff --git a/src/test/incremental/ich_nested_items.rs b/src/test/incremental/ich_nested_items.rs index b2b7e663151e2..aabdaa664112f 100644 --- a/src/test/incremental/ich_nested_items.rs +++ b/src/test/incremental/ich_nested_items.rs @@ -7,18 +7,21 @@ #![crate_type = "rlib"] #![feature(rustc_attrs)] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_clean(label = "hir_owner", cfg = "cfail2")] +#[rustc_dirty(label = "hir_owner_nodes", cfg = "cfail2")] pub fn foo() { #[cfg(cfail1)] - pub fn baz() { } // order is different... + pub fn baz() {} // order is different... - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail2")] - pub fn bar() { } // but that doesn't matter. + // FIXME: Make "hir_owner" use `rustc_clean` here. Currently "hir_owner" includes a reference to + // the parent node, which is the statement holding this item. Changing the position of + // `bar` in `foo` will update that reference and make `hir_owner(bar)` dirty. + #[rustc_dirty(label = "hir_owner", cfg = "cfail2")] + #[rustc_clean(label = "hir_owner_nodes", cfg = "cfail2")] + pub fn bar() {} // but that doesn't matter. #[cfg(cfail2)] - pub fn baz() { } // order is different... + pub fn baz() {} // order is different... - pub fn bap() { } // neither does adding a new item + pub fn bap() {} // neither does adding a new item } diff --git a/src/test/incremental/ich_resolve_results.rs b/src/test/incremental/ich_resolve_results.rs index 0e4ab6b78e2d7..19df2972f8942 100644 --- a/src/test/incremental/ich_resolve_results.rs +++ b/src/test/incremental/ich_resolve_results.rs @@ -28,18 +28,18 @@ mod mod3 { #[cfg(rpass3)] use mod2::Foo; - #[rustc_clean(label="Hir", cfg="rpass2")] - #[rustc_clean(label="HirBody", cfg="rpass2")] - #[rustc_clean(label="Hir", cfg="rpass3")] - #[rustc_dirty(label="HirBody", cfg="rpass3")] + #[rustc_clean(label="hir_owner", cfg="rpass2")] + #[rustc_clean(label="hir_owner_nodes", cfg="rpass2")] + #[rustc_clean(label="hir_owner", cfg="rpass3")] + #[rustc_dirty(label="hir_owner_nodes", cfg="rpass3")] fn in_expr() { Foo(0); } - #[rustc_clean(label="Hir", cfg="rpass2")] - #[rustc_clean(label="HirBody", cfg="rpass2")] - #[rustc_clean(label="Hir", cfg="rpass3")] - #[rustc_dirty(label="HirBody", cfg="rpass3")] + #[rustc_clean(label="hir_owner", cfg="rpass2")] + #[rustc_clean(label="hir_owner_nodes", cfg="rpass2")] + #[rustc_clean(label="hir_owner", cfg="rpass3")] + #[rustc_dirty(label="hir_owner_nodes", cfg="rpass3")] fn in_type() { test::(); } diff --git a/src/test/incremental/inlined_hir_34991/main.rs b/src/test/incremental/inlined_hir_34991/main.rs index 819b8434b0839..bb76a0bb8fe86 100644 --- a/src/test/incremental/inlined_hir_34991/main.rs +++ b/src/test/incremental/inlined_hir_34991/main.rs @@ -1,6 +1,6 @@ // Regression test for #34991: an ICE occurred here because we inline // some of the vector routines and give them a local def-id `X`. This -// got hashed after codegen (`Hir(X)`). When we load back up, we get an +// got hashed after codegen (`hir_owner(X)`). When we load back up, we get an // error because the `X` is remapped to the original def-id (in // libstd), and we can't hash a HIR node from std. diff --git a/src/test/incremental/issue-69596.rs b/src/test/incremental/issue-69596.rs new file mode 100644 index 0000000000000..dc587fdc44b0d --- /dev/null +++ b/src/test/incremental/issue-69596.rs @@ -0,0 +1,21 @@ +// revisions: rpass1 rpass2 + +#![allow(unused_imports)] + +#[macro_export] +macro_rules! a_macro { + () => {}; +} + +#[cfg(rpass1)] +use a_macro as same_name; + +mod same_name {} + +mod needed_mod { + fn _crash() { + use super::same_name; + } +} + +fn main() {} diff --git a/src/test/incremental/source_loc_macros.rs b/src/test/incremental/source_loc_macros.rs index 51ea7d6d447e5..f18d2fdaf0a01 100644 --- a/src/test/incremental/source_loc_macros.rs +++ b/src/test/incremental/source_loc_macros.rs @@ -7,26 +7,26 @@ #![feature(rustc_attrs)] -#[rustc_clean(label="Hir", cfg="rpass2")] -#[rustc_clean(label="HirBody", cfg="rpass2")] +#[rustc_clean(label="hir_owner", cfg="rpass2")] +#[rustc_clean(label="hir_owner_nodes", cfg="rpass2")] fn line_same() { let _ = line!(); } -#[rustc_clean(label="Hir", cfg="rpass2")] -#[rustc_clean(label="HirBody", cfg="rpass2")] +#[rustc_clean(label="hir_owner", cfg="rpass2")] +#[rustc_clean(label="hir_owner_nodes", cfg="rpass2")] fn col_same() { let _ = column!(); } -#[rustc_clean(label="Hir", cfg="rpass2")] -#[rustc_clean(label="HirBody", cfg="rpass2")] +#[rustc_clean(label="hir_owner", cfg="rpass2")] +#[rustc_clean(label="hir_owner_nodes", cfg="rpass2")] fn file_same() { let _ = file!(); } -#[rustc_clean(label="Hir", cfg="rpass2")] -#[rustc_dirty(label="HirBody", cfg="rpass2")] +#[rustc_clean(label="hir_owner", cfg="rpass2")] +#[rustc_dirty(label="hir_owner_nodes", cfg="rpass2")] fn line_different() { #[cfg(rpass1)] { @@ -38,8 +38,8 @@ fn line_different() { } } -#[rustc_clean(label="Hir", cfg="rpass2")] -#[rustc_dirty(label="HirBody", cfg="rpass2")] +#[rustc_clean(label="hir_owner", cfg="rpass2")] +#[rustc_dirty(label="hir_owner_nodes", cfg="rpass2")] fn col_different() { #[cfg(rpass1)] { diff --git a/src/test/incremental/span_hash_stable/auxiliary/sub1.rs b/src/test/incremental/span_hash_stable/auxiliary/sub1.rs index 54fbe4465e3cf..2927ddec4e52c 100644 --- a/src/test/incremental/span_hash_stable/auxiliary/sub1.rs +++ b/src/test/incremental/span_hash_stable/auxiliary/sub1.rs @@ -1,4 +1,4 @@ -#[rustc_clean(label="Hir", cfg="rpass2")] +#[rustc_clean(label="hir_owner", cfg="rpass2")] pub struct SomeType { pub x: u32, pub y: i64, diff --git a/src/test/incremental/span_hash_stable/auxiliary/sub2.rs b/src/test/incremental/span_hash_stable/auxiliary/sub2.rs index 349576168567f..aa635077db8ee 100644 --- a/src/test/incremental/span_hash_stable/auxiliary/sub2.rs +++ b/src/test/incremental/span_hash_stable/auxiliary/sub2.rs @@ -1,4 +1,4 @@ -#[rustc_clean(label="Hir", cfg="rpass2")] +#[rustc_clean(label="hir_owner", cfg="rpass2")] pub struct SomeOtherType { pub a: i32, pub b: u64, diff --git a/src/test/incremental/spans_significant_w_debuginfo.rs b/src/test/incremental/spans_significant_w_debuginfo.rs index e6fdc7cb3a0fc..aff2be830fff8 100644 --- a/src/test/incremental/spans_significant_w_debuginfo.rs +++ b/src/test/incremental/spans_significant_w_debuginfo.rs @@ -12,6 +12,6 @@ pub fn main() {} #[cfg(rpass2)] -#[rustc_dirty(label="Hir", cfg="rpass2")] -#[rustc_dirty(label="HirBody", cfg="rpass2")] +#[rustc_dirty(label="hir_owner", cfg="rpass2")] +#[rustc_dirty(label="hir_owner_nodes", cfg="rpass2")] pub fn main() {} diff --git a/src/test/incremental/string_constant.rs b/src/test/incremental/string_constant.rs index b88acd2af75ab..cc35f3bdf299b 100644 --- a/src/test/incremental/string_constant.rs +++ b/src/test/incremental/string_constant.rs @@ -18,7 +18,7 @@ pub mod x { } #[cfg(cfail2)] - #[rustc_dirty(label="HirBody", cfg="cfail2")] + #[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] #[rustc_dirty(label="optimized_mir", cfg="cfail2")] pub fn x() { println!("{}", "2"); diff --git a/src/test/incremental/unchecked_dirty_clean.rs b/src/test/incremental/unchecked_dirty_clean.rs index 66bdb670167ed..3bc8818aa6f4c 100644 --- a/src/test/incremental/unchecked_dirty_clean.rs +++ b/src/test/incremental/unchecked_dirty_clean.rs @@ -10,13 +10,13 @@ fn main() { - #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] //[cfail2]~^ ERROR found unchecked `#[rustc_dirty]` / `#[rustc_clean]` attribute { // empty block } - #[rustc_clean(label="Hir", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] //[cfail2]~^ ERROR found unchecked `#[rustc_dirty]` / `#[rustc_clean]` attribute { // empty block @@ -24,11 +24,11 @@ fn main() { } struct _Struct { - #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] //[cfail2]~^ ERROR found unchecked `#[rustc_dirty]` / `#[rustc_clean]` attribute _field1: i32, - #[rustc_clean(label="Hir", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] //[cfail2]~^ ERROR found unchecked `#[rustc_dirty]` / `#[rustc_clean]` attribute _field2: i32, } diff --git a/src/test/mir-opt/array-index-is-temporary.rs b/src/test/mir-opt/array-index-is-temporary.rs index 096f98bade25a..57f30acb3a643 100644 --- a/src/test/mir-opt/array-index-is-temporary.rs +++ b/src/test/mir-opt/array-index-is-temporary.rs @@ -15,7 +15,7 @@ fn main() { } // END RUST SOURCE -// START rustc.main.EraseRegions.after.mir +// START rustc.main.SimplifyCfg-elaborate-drops.after.mir // bb0: { // ... // _4 = &mut _2; @@ -38,4 +38,4 @@ fn main() { // ... // return; // } -// END rustc.main.EraseRegions.after.mir +// END rustc.main.SimplifyCfg-elaborate-drops.after.mir diff --git a/src/test/mir-opt/byte_slice.rs b/src/test/mir-opt/byte_slice.rs index 7edfa3e1124db..0fb685c3c4e6d 100644 --- a/src/test/mir-opt/byte_slice.rs +++ b/src/test/mir-opt/byte_slice.rs @@ -6,10 +6,10 @@ fn main() { } // END RUST SOURCE -// START rustc.main.EraseRegions.after.mir +// START rustc.main.SimplifyCfg-elaborate-drops.after.mir // ... // _1 = const b"foo"; // ... // _2 = [const 5u8, const 120u8]; // ... -// END rustc.main.EraseRegions.after.mir +// END rustc.main.SimplifyCfg-elaborate-drops.after.mir diff --git a/src/test/mir-opt/const-promotion-extern-static.rs b/src/test/mir-opt/const-promotion-extern-static.rs index f6f7d0910911c..c858a4c5ee7c6 100644 --- a/src/test/mir-opt/const-promotion-extern-static.rs +++ b/src/test/mir-opt/const-promotion-extern-static.rs @@ -4,9 +4,9 @@ extern "C" { static Y: i32 = 42; -static mut BAR: *const &'static i32 = [&Y].as_ptr(); +static mut BAR: *const &i32 = [&Y].as_ptr(); -static mut FOO: *const &'static i32 = [unsafe { &X }].as_ptr(); +static mut FOO: *const &i32 = [unsafe { &X }].as_ptr(); fn main() {} @@ -14,12 +14,12 @@ fn main() {} // START rustc.FOO.PromoteTemps.before.mir // bb0: { // ... -// _5 = const Scalar(alloc1+0) : &i32; +// _5 = const {alloc1+0: &i32}; // _4 = &(*_5); // _3 = [move _4]; // _2 = &_3; -// _1 = move _2 as &[&'static i32] (Pointer(Unsize)); -// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; +// _1 = move _2 as &[&i32] (Pointer(Unsize)); +// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; // } // ... // bb2: { @@ -31,12 +31,12 @@ fn main() {} // START rustc.BAR.PromoteTemps.before.mir // bb0: { // ... -// _5 = const Scalar(alloc0+0) : &i32; +// _5 = const {alloc0+0: &i32}; // _4 = &(*_5); // _3 = [move _4]; // _2 = &_3; -// _1 = move _2 as &[&'static i32] (Pointer(Unsize)); -// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; +// _1 = move _2 as &[&i32] (Pointer(Unsize)); +// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; // } // ... // bb2: { @@ -50,8 +50,8 @@ fn main() {} // ... // _6 = const BAR::promoted[0]; // _2 = &(*_6); -// _1 = move _2 as &[&'static i32] (Pointer(Unsize)); -// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; +// _1 = move _2 as &[&i32] (Pointer(Unsize)); +// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; // } // ... // bb2: { @@ -63,8 +63,8 @@ fn main() {} // ... // _6 = const FOO::promoted[0]; // _2 = &(*_6); -// _1 = move _2 as &[&'static i32] (Pointer(Unsize)); -// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; +// _1 = move _2 as &[&i32] (Pointer(Unsize)); +// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; // } // ... // bb2: { diff --git a/src/test/mir-opt/const_prop/control-flow-simplification.rs b/src/test/mir-opt/const_prop/control-flow-simplification.rs new file mode 100644 index 0000000000000..0e9f33b15e2cc --- /dev/null +++ b/src/test/mir-opt/const_prop/control-flow-simplification.rs @@ -0,0 +1,64 @@ +// compile-flags: -Zmir-opt-level=1 + +trait NeedsDrop:Sized{ + const NEEDS:bool=std::mem::needs_drop::(); +} + +impl NeedsDrop for This{} + +fn hello(){ + if ::NEEDS { + panic!() + } +} + +pub fn main() { + hello::<()>(); + hello::>(); +} + +// END RUST SOURCE +// START rustc.hello.ConstProp.before.mir +// let mut _0: (); +// let mut _1: bool; +// let mut _2: !; +// bb0: { +// StorageLive(_1); +// _1 = const ::NEEDS; +// switchInt(_1) -> [false: bb1, otherwise: bb2]; +// } +// bb1: { +// _0 = (); +// StorageDead(_1); +// return; +// } +// bb2: { +// StorageLive(_2); +// const std::rt::begin_panic::<&str>(const "explicit panic"); +// } +// END rustc.hello.ConstProp.before.mir +// START rustc.hello.ConstProp.after.mir +// let mut _0: (); +// let mut _1: bool; +// let mut _2: !; +// bb0: { +// StorageLive(_1); +// _1 = const false; +// switchInt(const false) -> [false: bb1, otherwise: bb2]; +// } +// bb1: { +// _0 = (); +// StorageDead(_1); +// return; +// } +// bb2: { +// StorageLive(_2); +// const std::rt::begin_panic::<&str>(const "explicit panic"); +// } +// END rustc.hello.ConstProp.after.mir +// START rustc.hello.PreCodegen.before.mir +// let mut _0: (); +// bb0: { +// return; +// } +// END rustc.hello.PreCodegen.before.mir diff --git a/src/test/mir-opt/const_prop/discriminant.rs b/src/test/mir-opt/const_prop/discriminant.rs index 667d21fc14ee4..636aa1af65333 100644 --- a/src/test/mir-opt/const_prop/discriminant.rs +++ b/src/test/mir-opt/const_prop/discriminant.rs @@ -31,7 +31,7 @@ fn main() { // START rustc.main.ConstProp.after.mir // bb0: { // ... -// _3 = const Scalar(0x01) : std::option::Option; +// _3 = const {transmute(0x01): std::option::Option}; // _4 = const 1isize; // switchInt(const 1isize) -> [1isize: bb2, otherwise: bb1]; // } diff --git a/src/test/mir-opt/const_prop/issue-66971.rs b/src/test/mir-opt/const_prop/issue-66971.rs index 30c75303b3e53..f332bb895095b 100644 --- a/src/test/mir-opt/const_prop/issue-66971.rs +++ b/src/test/mir-opt/const_prop/issue-66971.rs @@ -29,7 +29,7 @@ fn main() { // START rustc.main.ConstProp.after.mir // bb0: { // ... -// _3 = const Scalar() : (); +// _3 = const (); // _2 = (move _3, const 0u8, const 0u8); // ... // _1 = const encode(move _2) -> bb1; diff --git a/src/test/mir-opt/const_prop/read_immutable_static.rs b/src/test/mir-opt/const_prop/read_immutable_static.rs index 693ef78398558..d307cebd71539 100644 --- a/src/test/mir-opt/const_prop/read_immutable_static.rs +++ b/src/test/mir-opt/const_prop/read_immutable_static.rs @@ -10,10 +10,10 @@ fn main() { // START rustc.main.ConstProp.before.mir // bb0: { // ... -// _3 = const Scalar(alloc0+0) : &u8; +// _3 = const {alloc0+0: &u8}; // _2 = (*_3); // ... -// _5 = const Scalar(alloc0+0) : &u8; +// _5 = const {alloc0+0: &u8}; // _4 = (*_5); // _1 = Add(move _2, move _4); // ... diff --git a/src/test/mir-opt/generator-tiny.rs b/src/test/mir-opt/generator-tiny.rs new file mode 100644 index 0000000000000..09e943bd962e6 --- /dev/null +++ b/src/test/mir-opt/generator-tiny.rs @@ -0,0 +1,34 @@ +//! Tests that generators that cannot return or unwind don't have unnecessary +//! panic branches. + +// compile-flags: -Zno-landing-pads + +#![feature(generators, generator_trait)] + +struct HasDrop; + +impl Drop for HasDrop { + fn drop(&mut self) {} +} + +fn callee() {} + +fn main() { + let _gen = |_x: u8| { + let _d = HasDrop; + loop { + yield; + callee(); + } + }; +} + +// END RUST SOURCE + +// START rustc.main-{{closure}}.generator_resume.0.mir +// bb0: { +// ... +// switchInt(move _11) -> [0u32: bb1, 3u32: bb5, otherwise: bb6]; +// } +// ... +// END rustc.main-{{closure}}.generator_resume.0.mir diff --git a/src/test/mir-opt/inline/inline-into-box-place.rs b/src/test/mir-opt/inline/inline-into-box-place.rs index f368bdef6f8e2..fcb7b4c4fe69d 100644 --- a/src/test/mir-opt/inline/inline-into-box-place.rs +++ b/src/test/mir-opt/inline/inline-into-box-place.rs @@ -1,6 +1,7 @@ // ignore-tidy-linelength // ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -Z mir-opt-level=3 +// only-64bit FIXME: the mir representation of RawVec depends on ptr size #![feature(box_syntax)] fn main() { @@ -55,7 +56,7 @@ fn main() { // StorageLive(_2); // _2 = Box(std::vec::Vec); // _4 = &mut (*_2); -// ((*_4).0: alloc::raw_vec::RawVec) = const alloc::raw_vec::RawVec::::NEW; +// ((*_4).0: alloc::raw_vec::RawVec) = const ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), undef_mask: UndefMask { blocks: [65535], len: Size { raw: 16 } }, size: Size { raw: 16 }, align: Align { pow2: 3 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }: alloc::raw_vec::RawVec::; // ((*_4).1: usize) = const 0usize; // _1 = move _2; // StorageDead(_2); diff --git a/src/test/mir-opt/no-drop-for-inactive-variant.rs b/src/test/mir-opt/no-drop-for-inactive-variant.rs new file mode 100644 index 0000000000000..74a606af28fc1 --- /dev/null +++ b/src/test/mir-opt/no-drop-for-inactive-variant.rs @@ -0,0 +1,43 @@ +// ignore-wasm32-bare compiled with panic=abort by default + +// Ensure that there are no drop terminators in `unwrap` (except the one along the cleanup +// path). + +fn unwrap(opt: Option) -> T { + match opt { + Some(x) => x, + None => panic!(), + } +} + +fn main() { + let _ = unwrap(Some(1i32)); +} + +// END RUST SOURCE +// START rustc.unwrap.SimplifyCfg-elaborate-drops.after.mir +// fn unwrap(_1: std::option::Option) -> T { +// ... +// bb0: { +// ... +// switchInt(move _2) -> [0isize: bb2, 1isize: bb4, otherwise: bb3]; +// } +// bb1 (cleanup): { +// resume; +// } +// bb2: { +// ... +// const std::rt::begin_panic::<&str>(const "explicit panic") -> bb5; +// } +// bb3: { +// unreachable; +// } +// bb4: { +// ... +// return; +// } +// bb5 (cleanup): { +// drop(_1) -> bb1; +// } +// } +// END rustc.unwrap.SimplifyCfg-elaborate-drops.after.mir diff --git a/src/test/mir-opt/packed-struct-drop-aligned.rs b/src/test/mir-opt/packed-struct-drop-aligned.rs index 113f81c441f7c..39b9006017958 100644 --- a/src/test/mir-opt/packed-struct-drop-aligned.rs +++ b/src/test/mir-opt/packed-struct-drop-aligned.rs @@ -15,7 +15,7 @@ impl Drop for Droppy { } // END RUST SOURCE -// START rustc.main.EraseRegions.before.mir +// START rustc.main.SimplifyCfg-elaborate-drops.after.mir // fn main() -> () { // let mut _0: (); // let mut _1: Packed; @@ -56,4 +56,4 @@ impl Drop for Droppy { // drop(_1) -> [return: bb2, unwind: bb1]; // } // } -// END rustc.main.EraseRegions.before.mir +// END rustc.main.SimplifyCfg-elaborate-drops.after.mir diff --git a/src/test/mir-opt/remove_fake_borrows.rs b/src/test/mir-opt/remove_fake_borrows.rs index 294fe247c38be..ea106eaf59529 100644 --- a/src/test/mir-opt/remove_fake_borrows.rs +++ b/src/test/mir-opt/remove_fake_borrows.rs @@ -26,16 +26,16 @@ fn main() { // goto -> bb7; // } // bb2: { -// switchInt((*(*((_1 as Some).0: &' &' i32)))) -> [0i32: bb3, otherwise: bb1]; +// switchInt((*(*((_1 as Some).0: &&i32)))) -> [0i32: bb3, otherwise: bb1]; // } // bb3: { // goto -> bb4; // } // bb4: { // _4 = &shallow _1; -// _5 = &shallow ((_1 as Some).0: &' &' i32); -// _6 = &shallow (*((_1 as Some).0: &' &' i32)); -// _7 = &shallow (*(*((_1 as Some).0: &' &' i32))); +// _5 = &shallow ((_1 as Some).0: &&i32); +// _6 = &shallow (*((_1 as Some).0: &&i32)); +// _7 = &shallow (*(*((_1 as Some).0: &&i32))); // StorageLive(_8); // _8 = _2; // switchInt(move _8) -> [false: bb6, otherwise: bb5]; @@ -72,7 +72,7 @@ fn main() { // goto -> bb7; // } // bb2: { -// switchInt((*(*((_1 as Some).0: &' &' i32)))) -> [0i32: bb3, otherwise: bb1]; +// switchInt((*(*((_1 as Some).0: &&i32)))) -> [0i32: bb3, otherwise: bb1]; // } // bb3: { // goto -> bb4; diff --git a/src/test/mir-opt/retag.rs b/src/test/mir-opt/retag.rs index 1c88a9e4d5a32..a0a7a760c2da5 100644 --- a/src/test/mir-opt/retag.rs +++ b/src/test/mir-opt/retag.rs @@ -8,8 +8,12 @@ struct Test(i32); impl Test { // Make sure we run the pass on a method, not just on bare functions. - fn foo<'x>(&self, x: &'x mut i32) -> &'x mut i32 { x } - fn foo_shr<'x>(&self, x: &'x i32) -> &'x i32 { x } + fn foo<'x>(&self, x: &'x mut i32) -> &'x mut i32 { + x + } + fn foo_shr<'x>(&self, x: &'x i32) -> &'x i32 { + x + } } impl Drop for Test { @@ -27,7 +31,10 @@ fn main() { } // Also test closures - let c: fn(&i32) -> &i32 = |x: &i32| -> &i32 { let _y = x; x }; + let c: fn(&i32) -> &i32 = |x: &i32| -> &i32 { + let _y = x; + x + }; let _w = c(&x); // need to call `foo_shr` or it doesn't even get generated @@ -38,7 +45,7 @@ fn main() { } // END RUST SOURCE -// START rustc.{{impl}}-foo.EraseRegions.after.mir +// START rustc.{{impl}}-foo.SimplifyCfg-elaborate-drops.after.mir // bb0: { // Retag([fn entry] _1); // Retag([fn entry] _2); @@ -48,8 +55,8 @@ fn main() { // ... // return; // } -// END rustc.{{impl}}-foo.EraseRegions.after.mir -// START rustc.{{impl}}-foo_shr.EraseRegions.after.mir +// END rustc.{{impl}}-foo.SimplifyCfg-elaborate-drops.after.mir +// START rustc.{{impl}}-foo_shr.SimplifyCfg-elaborate-drops.after.mir // bb0: { // Retag([fn entry] _1); // Retag([fn entry] _2); @@ -59,8 +66,8 @@ fn main() { // ... // return; // } -// END rustc.{{impl}}-foo_shr.EraseRegions.after.mir -// START rustc.main.EraseRegions.after.mir +// END rustc.{{impl}}-foo_shr.SimplifyCfg-elaborate-drops.after.mir +// START rustc.main.SimplifyCfg-elaborate-drops.after.mir // fn main() -> () { // ... // bb0: { @@ -96,8 +103,8 @@ fn main() { // // ... // } -// END rustc.main.EraseRegions.after.mir -// START rustc.main-{{closure}}.EraseRegions.after.mir +// END rustc.main.SimplifyCfg-elaborate-drops.after.mir +// START rustc.main-{{closure}}.SimplifyCfg-elaborate-drops.after.mir // fn main::{{closure}}#0(_1: &[closure@main::{{closure}}#0], _2: &i32) -> &i32 { // ... // bb0: { @@ -112,9 +119,9 @@ fn main() { // return; // } // } -// END rustc.main-{{closure}}.EraseRegions.after.mir +// END rustc.main-{{closure}}.SimplifyCfg-elaborate-drops.after.mir // START rustc.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir -// fn std::intrinsics::drop_in_place(_1: *mut Test) -> () { +// fn std::intrinsics::drop_in_place(_1: *mut Test) -> () { // ... // bb0: { // Retag([raw] _1); diff --git a/src/test/mir-opt/simplify-locals-removes-unused-consts.rs b/src/test/mir-opt/simplify-locals-removes-unused-consts.rs index 6f03438ff7234..e427fd55ad680 100644 --- a/src/test/mir-opt/simplify-locals-removes-unused-consts.rs +++ b/src/test/mir-opt/simplify-locals-removes-unused-consts.rs @@ -1,18 +1,18 @@ // compile-flags: -C overflow-checks=no -fn use_zst(_: ((), ())) { } +fn use_zst(_: ((), ())) {} struct Temp { - x: u8 + x: u8, } -fn use_u8(_: u8) { } +fn use_u8(_: u8) {} fn main() { let ((), ()) = ((), ()); use_zst(((), ())); - use_u8((Temp { x : 40 }).x + 2); + use_u8((Temp { x: 40 }).x + 2); } // END RUST SOURCE @@ -35,28 +35,28 @@ fn main() { // bb0: { // StorageLive(_1); // StorageLive(_2); -// _2 = const Scalar() : (); +// _2 = const (); // StorageLive(_3); -// _3 = const Scalar() : (); -// _1 = const Scalar() : ((), ()); +// _3 = const (); +// _1 = const {transmute(()): ((), ())}; // StorageDead(_3); // StorageDead(_2); // StorageDead(_1); // StorageLive(_4); // StorageLive(_6); -// _6 = const Scalar() : (); +// _6 = const (); // StorageLive(_7); -// _7 = const Scalar() : (); +// _7 = const (); // StorageDead(_7); // StorageDead(_6); -// _4 = const use_zst(const Scalar() : ((), ())) -> bb1; +// _4 = const use_zst(const {transmute(()): ((), ())}) -> bb1; // } // bb1: { // StorageDead(_4); // StorageLive(_8); // StorageLive(_10); // StorageLive(_11); -// _11 = const Scalar(0x28) : Temp; +// _11 = const {transmute(0x28) : Temp}; // _10 = const 40u8; // StorageDead(_10); // _8 = const use_u8(const 42u8) -> bb2; @@ -75,7 +75,7 @@ fn main() { // } // bb0: { // StorageLive(_1); -// _1 = const use_zst(const Scalar() : ((), ())) -> bb1; +// _1 = const use_zst(const {transmute(()): ((), ())}) -> bb1; // } // bb1: { // StorageDead(_1); diff --git a/src/test/mir-opt/storage_live_dead_in_statics.rs b/src/test/mir-opt/storage_live_dead_in_statics.rs index 5dc15286bab50..1c98766b9685c 100644 --- a/src/test/mir-opt/storage_live_dead_in_statics.rs +++ b/src/test/mir-opt/storage_live_dead_in_statics.rs @@ -35,12 +35,12 @@ fn main() { // END RUST SOURCE // START rustc.XXX.mir_map.0.mir -// let mut _0: &'static Foo; -// let _1: &'static Foo; +// let mut _0: &Foo; +// let _1: &Foo; // let _2: Foo; -// let mut _3: &'static [(u32, u32)]; -// let mut _4: &'static [(u32, u32); 42]; -// let _5: &'static [(u32, u32); 42]; +// let mut _3: &[(u32, u32)]; +// let mut _4: &[(u32, u32); 42]; +// let _5: &[(u32, u32); 42]; // let _6: [(u32, u32); 42]; // let mut _7: (u32, u32); // let mut _8: (u32, u32); @@ -178,7 +178,7 @@ fn main() { // _6 = [move _7, move _8, move _9, move _10, move _11, move _12, move _13, move _14, move _15, move _16, move _17, move _18, move _19, move _20, move _21, move _22, move _23, move _24, move _25, move _26, move _27, move _28, move _29, move _30, move _31, move _32, move _33, move _34, move _35, move _36, move _37, move _38, move _39, move _40, move _41, move _42, move _43, move _44, move _45, move _46, move _47, move _48]; // _5 = &_6; // _4 = &(*_5); -// _3 = move _4 as &'static [(u32, u32)] (Pointer(Unsize)); +// _3 = move _4 as &[(u32, u32)] (Pointer(Unsize)); // _2 = Foo { tup: const "hi", data: move _3 }; // _1 = &_2; // _0 = &(*_1); diff --git a/src/test/pretty/attr-literals.rs b/src/test/pretty/attr-literals.rs index 9db7e27b16103..44d2c5db3e668 100644 --- a/src/test/pretty/attr-literals.rs +++ b/src/test/pretty/attr-literals.rs @@ -5,7 +5,7 @@ #![feature(rustc_attrs)] fn main() { - #![rustc_dummy("hi", 1, 2, 1.012, pi = 3.14, bye, name ("John"))] + #![rustc_dummy("hi", 1, 2, 1.012, pi = 3.14, bye, name("John"))] #[rustc_dummy = 8] fn f() { } diff --git a/src/test/pretty/delimited-token-groups.rs b/src/test/pretty/delimited-token-groups.rs index 7bbb7dc911f93..66de0fc6cf7fa 100644 --- a/src/test/pretty/delimited-token-groups.rs +++ b/src/test/pretty/delimited-token-groups.rs @@ -7,7 +7,7 @@ macro_rules! mac { ($ ($ tt : tt) *) => () } mac! { struct S { field1 : u8, field2 : u16, } impl Clone for S { - fn clone () -> S + fn clone() -> S { panic ! () ; @@ -16,9 +16,8 @@ mac! { } mac! { - a - (aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa - aaaaaaaa aaaaaaaa) a + a(aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa + aaaaaaaa aaaaaaaa) a [aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa] a { diff --git a/src/test/pretty/issue-12590-a.rs b/src/test/pretty/issue-12590-a.rs index 1a9e85c42d8fb..ca1fef83cffc5 100644 --- a/src/test/pretty/issue-12590-a.rs +++ b/src/test/pretty/issue-12590-a.rs @@ -1,4 +1,5 @@ // pp-exact +// pretty-compare-only // The next line should not be expanded diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index 8aa4cdeb5394e..ee7586bae820a 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -34,29 +34,29 @@ ((::alloc::fmt::format as for<'r> fn(std::fmt::Arguments<'r>) -> std::string::String {std::fmt::format})(((::core::fmt::Arguments::new_v1 as - fn(&[&str], &[std::fmt::ArgumentV1<'_>]) -> std::fmt::Arguments<'_> {std::fmt::Arguments::<'_>::new_v1})((&([("test" - as - &'static str)] - as - [&str; 1]) - as - &[&str; 1]), - (&(match (() - as - ()) - { - () - => - ([] - as - [std::fmt::ArgumentV1<'_>; 0]), - } - as - [std::fmt::ArgumentV1<'_>; 0]) - as - &[std::fmt::ArgumentV1<'_>; 0])) + fn(&[&str], &[std::fmt::ArgumentV1]) -> std::fmt::Arguments {std::fmt::Arguments::new_v1})((&([("test" + as + &str)] + as + [&str; 1]) + as + &[&str; 1]), + (&(match (() + as + ()) + { + () + => + ([] + as + [std::fmt::ArgumentV1; 0]), + } + as + [std::fmt::ArgumentV1; 0]) + as + &[std::fmt::ArgumentV1; 0])) as - std::fmt::Arguments<'_>)) + std::fmt::Arguments)) as std::string::String); (res as std::string::String) } as std::string::String); diff --git a/src/test/pretty/issue-68710-field-attr-proc-mac-lost.rs b/src/test/pretty/issue-68710-field-attr-proc-mac-lost.rs index 643ca761aac32..031a482595932 100644 --- a/src/test/pretty/issue-68710-field-attr-proc-mac-lost.rs +++ b/src/test/pretty/issue-68710-field-attr-proc-mac-lost.rs @@ -12,5 +12,5 @@ const C: C = #[cfg(debug_assertions)] field: 0, - #[cfg(not (debug_assertions))] + #[cfg(not(debug_assertions))] field: 1,}; diff --git a/src/test/pretty/trait-polarity.rs b/src/test/pretty/trait-polarity.rs index 3aab99bf6a0ae..df1a7946afb11 100644 --- a/src/test/pretty/trait-polarity.rs +++ b/src/test/pretty/trait-polarity.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] // pp-exact diff --git a/src/test/run-make-fulldeps/hotplug_codegen_backend/Makefile b/src/test/run-make-fulldeps/hotplug_codegen_backend/Makefile index e203ec2737fc7..d8ceace7fff25 100644 --- a/src/test/run-make-fulldeps/hotplug_codegen_backend/Makefile +++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/Makefile @@ -1,5 +1,7 @@ include ../tools.mk +# ignore-stage1 + all: /bin/echo || exit 0 # This test requires /bin/echo to exist $(RUSTC) the_backend.rs --crate-name the_backend --crate-type dylib \ diff --git a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs index 07ef2424cc880..0e6c39e0affca 100644 --- a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs +++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs @@ -1,35 +1,38 @@ #![feature(rustc_private)] extern crate rustc; -extern crate rustc_codegen_utils; +extern crate rustc_codegen_ssa; #[macro_use] extern crate rustc_data_structures; -extern crate rustc_hir; -extern crate rustc_target; extern crate rustc_driver; +extern crate rustc_hir; +extern crate rustc_session; extern crate rustc_span; +extern crate rustc_symbol_mangling; +extern crate rustc_target; -use std::any::Any; -use std::sync::Arc; -use std::path::Path; -use rustc_span::symbol::Symbol; -use rustc::session::Session; -use rustc::session::config::OutputFilenames; -use rustc::ty::TyCtxt; -use rustc::ty::query::Providers; -use rustc::middle::cstore::{EncodedMetadata, MetadataLoader, MetadataLoaderDyn}; use rustc::dep_graph::DepGraph; +use rustc::middle::cstore::{EncodedMetadata, MetadataLoader, MetadataLoaderDyn}; +use rustc::ty::query::Providers; +use rustc::ty::TyCtxt; use rustc::util::common::ErrorReported; -use rustc_codegen_utils::codegen_backend::CodegenBackend; -use rustc_data_structures::sync::MetadataRef; +use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::owning_ref::OwningRef; +use rustc_data_structures::sync::MetadataRef; +use rustc_session::config::OutputFilenames; +use rustc_session::Session; +use rustc_span::symbol::Symbol; use rustc_target::spec::Target; +use std::any::Any; +use std::path::Path; +use std::sync::Arc; pub struct NoLlvmMetadataLoader; impl MetadataLoader for NoLlvmMetadataLoader { fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result { - let buf = std::fs::read(filename).map_err(|e| format!("metadata file open err: {:?}", e))?; + let buf = + std::fs::read(filename).map_err(|e| format!("metadata file open err: {:?}", e))?; let buf: OwningRef, [u8]> = OwningRef::new(buf); Ok(rustc_erase_owner!(buf.map_owner_box())) } @@ -47,7 +50,7 @@ impl CodegenBackend for TheBackend { } fn provide(&self, providers: &mut Providers) { - rustc_codegen_utils::symbol_names::provide(providers); + rustc_symbol_mangling::provide(providers); providers.target_features_whitelist = |tcx, _cnum| { tcx.arena.alloc(Default::default()) // Just a dummy @@ -77,7 +80,8 @@ impl CodegenBackend for TheBackend { _sess: &Session, _dep_graph: &DepGraph, ) -> Result, ErrorReported> { - let crate_name = ongoing_codegen.downcast::() + let crate_name = ongoing_codegen + .downcast::() .expect("in join_codegen: ongoing_codegen is not a Symbol"); Ok(crate_name) } @@ -88,17 +92,15 @@ impl CodegenBackend for TheBackend { codegen_results: Box, outputs: &OutputFilenames, ) -> Result<(), ErrorReported> { + use rustc_session::{config::CrateType, output::out_filename}; use std::io::Write; - use rustc::session::config::CrateType; - use rustc_codegen_utils::link::out_filename; - let crate_name = codegen_results.downcast::() - .expect("in link: codegen_results is not a Symbol"); + let crate_name = + codegen_results.downcast::().expect("in link: codegen_results is not a Symbol"); for &crate_type in sess.opts.crate_types.iter() { if crate_type != CrateType::Rlib { sess.fatal(&format!("Crate type is {:?}", crate_type)); } - let output_name = - out_filename(sess, crate_type, &outputs, &*crate_name.as_str()); + let output_name = out_filename(sess, crate_type, &outputs, &*crate_name.as_str()); let mut out_file = ::std::fs::File::create(output_name).unwrap(); write!(out_file, "This has been \"compiled\" successfully.").unwrap(); } diff --git a/src/test/run-make-fulldeps/issue-19371/foo.rs b/src/test/run-make-fulldeps/issue-19371/foo.rs index 12da64fc88f18..af84faa7511c6 100644 --- a/src/test/run-make-fulldeps/issue-19371/foo.rs +++ b/src/test/run-make-fulldeps/issue-19371/foo.rs @@ -1,13 +1,12 @@ #![feature(rustc_private)] -extern crate rustc; extern crate rustc_interface; extern crate rustc_driver; +extern crate rustc_session; extern crate rustc_span; -use rustc::session::DiagnosticOutput; -use rustc::session::config::{Input, Options, - OutputType, OutputTypes}; +use rustc_session::DiagnosticOutput; +use rustc_session::config::{Input, Options, OutputType, OutputTypes}; use rustc_interface::interface; use rustc_span::source_map::FileName; diff --git a/src/test/run-make-fulldeps/target-specs/my-awesome-platform.json b/src/test/run-make-fulldeps/target-specs/my-awesome-platform.json index 8d028280a8da7..00de3de05f07a 100644 --- a/src/test/run-make-fulldeps/target-specs/my-awesome-platform.json +++ b/src/test/run-make-fulldeps/target-specs/my-awesome-platform.json @@ -1,5 +1,5 @@ { - "data-layout": "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128", + "data-layout": "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-f80:32-n8:16:32-S128", "linker-flavor": "gcc", "llvm-target": "i686-unknown-linux-gnu", "target-endian": "little", diff --git a/src/test/run-make-fulldeps/target-specs/my-x86_64-unknown-linux-gnu-platform.json b/src/test/run-make-fulldeps/target-specs/my-x86_64-unknown-linux-gnu-platform.json index 48040ae3da0ef..6d5e964ed4fee 100644 --- a/src/test/run-make-fulldeps/target-specs/my-x86_64-unknown-linux-gnu-platform.json +++ b/src/test/run-make-fulldeps/target-specs/my-x86_64-unknown-linux-gnu-platform.json @@ -1,6 +1,6 @@ { "pre-link-args": {"gcc": ["-m64"]}, - "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128", + "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "linker-flavor": "gcc", "llvm-target": "x86_64-unknown-linux-gnu", "target-endian": "little", diff --git a/src/test/rustdoc-js-std/return-specific-literal.js b/src/test/rustdoc-js-std/return-specific-literal.js new file mode 100644 index 0000000000000..c7c347240b751 --- /dev/null +++ b/src/test/rustdoc-js-std/return-specific-literal.js @@ -0,0 +1,10 @@ +const QUERY = 'struct:"string"'; + +const EXPECTED = { + 'in_args': [ + { 'path': 'std::string::String', 'name': 'ne' }, + ], + 'returned': [ + { 'path': 'std::string::String', 'name': 'add' }, + ], +}; diff --git a/src/test/rustdoc-js-std/return-specific.js b/src/test/rustdoc-js-std/return-specific.js new file mode 100644 index 0000000000000..d9a910553b8de --- /dev/null +++ b/src/test/rustdoc-js-std/return-specific.js @@ -0,0 +1,10 @@ +const QUERY = 'struct:string'; + +const EXPECTED = { + 'in_args': [ + { 'path': 'std::string::String', 'name': 'ne' }, + ], + 'returned': [ + { 'path': 'std::string::String', 'name': 'add' }, + ], +}; diff --git a/src/test/rustdoc-ui/deny-missing-docs-crate.stderr b/src/test/rustdoc-ui/deny-missing-docs-crate.stderr index f0a13b70b977f..821e6b99f7b8f 100644 --- a/src/test/rustdoc-ui/deny-missing-docs-crate.stderr +++ b/src/test/rustdoc-ui/deny-missing-docs-crate.stderr @@ -1,4 +1,4 @@ -error: missing documentation for crate +error: missing documentation for the crate --> $DIR/deny-missing-docs-crate.rs:1:1 | LL | / #![deny(missing_docs)] diff --git a/src/test/rustdoc-ui/issue-61732.rs b/src/test/rustdoc-ui/issue-61732.rs index d4835c092248e..4bd8efeaa3b97 100644 --- a/src/test/rustdoc-ui/issue-61732.rs +++ b/src/test/rustdoc-ui/issue-61732.rs @@ -1,4 +1,4 @@ // This previously triggered an ICE. pub(in crate::r#mod) fn main() {} -//~^ ERROR expected module, found unresolved item +//~^ ERROR failed to resolve: maybe a missing crate `r#mod` diff --git a/src/test/rustdoc-ui/issue-61732.stderr b/src/test/rustdoc-ui/issue-61732.stderr index 6c8ba48864df0..8213422491120 100644 --- a/src/test/rustdoc-ui/issue-61732.stderr +++ b/src/test/rustdoc-ui/issue-61732.stderr @@ -1,11 +1,11 @@ -error[E0577]: expected module, found unresolved item `crate::r#mod` - --> $DIR/issue-61732.rs:3:8 +error[E0433]: failed to resolve: maybe a missing crate `r#mod`? + --> $DIR/issue-61732.rs:3:15 | LL | pub(in crate::r#mod) fn main() {} - | ^^^^^^^^^^^^ not a module + | ^^^^^ maybe a missing crate `r#mod`? error: Compilation failed, aborting rustdoc error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0577`. +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/rustdoc/attributes.rs b/src/test/rustdoc/attributes.rs index 6ecdad3ec0000..e9cd3514a07e2 100644 --- a/src/test/rustdoc/attributes.rs +++ b/src/test/rustdoc/attributes.rs @@ -15,3 +15,7 @@ pub extern "C" fn g() {} pub enum Foo { Bar, } + +// @has foo/struct.Repr.html '//*[@class="docblock attributes top-attr"]' '#[repr(C, align(8))]' +#[repr(C, align(8))] +pub struct Repr; diff --git a/src/test/rustdoc/crate-version.rs b/src/test/rustdoc/crate-version.rs index 9ea84ac031211..893af5c61332d 100644 --- a/src/test/rustdoc/crate-version.rs +++ b/src/test/rustdoc/crate-version.rs @@ -1,3 +1,3 @@ -// compile-flags: --crate-version=1.3.37 -Z unstable-options +// compile-flags: --crate-version=1.3.37 // @has 'crate_version/index.html' '//div[@class="block version"]/p' 'Version 1.3.37' diff --git a/src/test/rustdoc/empty-section.rs b/src/test/rustdoc/empty-section.rs index d95f3a80365cd..665aa38b11eba 100644 --- a/src/test/rustdoc/empty-section.rs +++ b/src/test/rustdoc/empty-section.rs @@ -1,6 +1,6 @@ #![crate_name = "foo"] -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] pub struct Foo; diff --git a/src/test/rustdoc/impl-parts-crosscrate.rs b/src/test/rustdoc/impl-parts-crosscrate.rs index f9583d1a72296..a68db9c70ad2d 100644 --- a/src/test/rustdoc/impl-parts-crosscrate.rs +++ b/src/test/rustdoc/impl-parts-crosscrate.rs @@ -1,7 +1,7 @@ // aux-build:rustdoc-impl-parts-crosscrate.rs // ignore-cross-compile -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] extern crate rustdoc_impl_parts_crosscrate; diff --git a/src/test/rustdoc/impl-parts.rs b/src/test/rustdoc/impl-parts.rs index fbb4e725481c0..68baca9a04e9a 100644 --- a/src/test/rustdoc/impl-parts.rs +++ b/src/test/rustdoc/impl-parts.rs @@ -1,3 +1,4 @@ +#![feature(negative_impls)] #![feature(optin_builtin_traits)] pub auto trait AnOibit {} diff --git a/src/test/rustdoc/issue-55321.rs b/src/test/rustdoc/issue-55321.rs index 257cb32c65c25..8c001db06c5bf 100644 --- a/src/test/rustdoc/issue-55321.rs +++ b/src/test/rustdoc/issue-55321.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] // @has issue_55321/struct.A.html // @has - '//*[@id="implementations-list"]/*[@class="impl"]//code' "impl !Send for A" diff --git a/src/test/rustdoc/negative-impl-sidebar.rs b/src/test/rustdoc/negative-impl-sidebar.rs index 838ca0402e48a..cb46d1778d924 100644 --- a/src/test/rustdoc/negative-impl-sidebar.rs +++ b/src/test/rustdoc/negative-impl-sidebar.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] #![crate_name = "foo"] pub struct Foo; diff --git a/src/test/rustdoc/negative-impl.rs b/src/test/rustdoc/negative-impl.rs index 8ac87f4f0cb97..d76aac6906c46 100644 --- a/src/test/rustdoc/negative-impl.rs +++ b/src/test/rustdoc/negative-impl.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] // @matches negative_impl/struct.Alpha.html '//pre' "pub struct Alpha" pub struct Alpha; diff --git a/src/test/ui-fulldeps/auxiliary/linkage-visibility.rs b/src/test/ui-fulldeps/auxiliary/linkage-visibility.rs index 8917693d45eeb..837ed1f002fc9 100644 --- a/src/test/ui-fulldeps/auxiliary/linkage-visibility.rs +++ b/src/test/ui-fulldeps/auxiliary/linkage-visibility.rs @@ -2,16 +2,14 @@ #![feature(rustc_private)] -// We're testing linkage visibility; the compiler warns us, but we want to -// do the runtime check that these functions aren't exported. -#![allow(private_no_mangle_fns)] - extern crate rustc_metadata; use rustc_metadata::dynamic_lib::DynamicLibrary; #[no_mangle] -pub fn foo() { bar(); } +pub fn foo() { + bar(); +} pub fn foo2() { fn bar2() { @@ -21,11 +19,11 @@ pub fn foo2() { } #[no_mangle] -fn bar() { } +fn bar() {} #[allow(dead_code)] #[no_mangle] -fn baz() { } +fn baz() {} pub fn test() { let lib = DynamicLibrary::open(None).unwrap(); diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs index 4936bdb1ece8c..f8cb1640cb4c1 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs @@ -2,19 +2,19 @@ #![feature(plugin_registrar, rustc_private)] #![feature(box_syntax)] + extern crate rustc_driver; extern crate rustc_hir; -extern crate rustc_span; -#[macro_use] extern crate rustc_lint; +extern crate rustc_span; #[macro_use] extern crate rustc_session; extern crate rustc_ast; +use rustc_ast::attr; use rustc_driver::plugin::Registry; use rustc_lint::{LateContext, LateLintPass, LintContext, LintPass}; use rustc_span::symbol::Symbol; -use rustc_ast::attr; macro_rules! fake_lint_pass { ($struct:ident, $($attr:expr),*) => { @@ -29,10 +29,10 @@ macro_rules! fake_lint_pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for $struct { fn check_crate(&mut self, cx: &LateContext, krate: &rustc_hir::Crate) { $( - if !attr::contains_name(&krate.attrs, $attr) { + if !attr::contains_name(&krate.item.attrs, $attr) { cx.lint(CRATE_NOT_OKAY, |lint| { let msg = format!("crate is not marked with #![{}]", $attr); - lint.build(&msg).set_span(krate.span).emit() + lint.build(&msg).set_span(krate.item.span).emit() }); } )* @@ -50,17 +50,17 @@ declare_lint!(CRATE_NOT_GREEN, Warn, "crate not marked with #![crate_green]"); fake_lint_pass! { PassOkay, - Symbol::intern("rustc_crate_okay") + Symbol::intern("crate_okay") } fake_lint_pass! { PassRedBlue, - Symbol::intern("rustc_crate_red"), Symbol::intern("rustc_crate_blue") + Symbol::intern("crate_red"), Symbol::intern("crate_blue") } fake_lint_pass! { PassGreyGreen, - Symbol::intern("rustc_crate_grey"), Symbol::intern("rustc_crate_green") + Symbol::intern("crate_grey"), Symbol::intern("crate_green") } #[plugin_registrar] diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs index 32b7ed9dfe2c8..6978d02c09d14 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs @@ -27,10 +27,10 @@ declare_lint_pass!(Pass => [CRATE_NOT_OKAY]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_crate(&mut self, cx: &LateContext, krate: &rustc_hir::Crate) { - if !attr::contains_name(&krate.attrs, Symbol::intern("crate_okay")) { + if !attr::contains_name(&krate.item.attrs, Symbol::intern("crate_okay")) { cx.lint(CRATE_NOT_OKAY, |lint| { lint.build("crate is not marked with #![crate_okay]") - .set_span(krate.span) + .set_span(krate.item.span) .emit() }); } diff --git a/src/test/ui-fulldeps/auxiliary/macro-crate-test.rs b/src/test/ui-fulldeps/auxiliary/macro-crate-test.rs deleted file mode 100644 index 56a560acbb44a..0000000000000 --- a/src/test/ui-fulldeps/auxiliary/macro-crate-test.rs +++ /dev/null @@ -1,33 +0,0 @@ -// force-host -// no-prefer-dynamic - -#![crate_type = "proc-macro"] -#![feature(rustc_private)] - -extern crate rustc_ast; -extern crate rustc; -extern crate rustc_driver; -extern crate proc_macro; - -use proc_macro::{TokenTree, TokenStream}; - -#[proc_macro_attribute] -pub fn rustc_duplicate(attr: TokenStream, item: TokenStream) -> TokenStream { - let mut new_name = Some(attr.into_iter().nth(0).unwrap()); - let mut encountered_idents = 0; - let input = item.to_string(); - let ret = item.into_iter().map(move |token| match token { - TokenTree::Ident(_) if encountered_idents == 1 => { - encountered_idents += 1; - new_name.take().unwrap() - } - TokenTree::Ident(_) => { - encountered_idents += 1; - token - } - _ => token - }).collect::(); - let mut input_again = input.parse::().unwrap(); - input_again.extend(ret); - input_again -} diff --git a/src/test/ui-fulldeps/issue-15778-pass.rs b/src/test/ui-fulldeps/issue-15778-pass.rs index 4b3cf07e2830d..c031dbc7155db 100644 --- a/src/test/ui-fulldeps/issue-15778-pass.rs +++ b/src/test/ui-fulldeps/issue-15778-pass.rs @@ -1,23 +1,23 @@ -// run-pass +// check-pass // aux-build:lint-for-crate-rpass.rs // ignore-stage1 // compile-flags: -D crate-not-okay -#![feature(plugin, register_attr, custom_inner_attributes, rustc_attrs)] +#![feature(plugin, register_attr, custom_inner_attributes)] #![register_attr( - rustc_crate_okay, - rustc_crate_blue, - rustc_crate_red, - rustc_crate_grey, - rustc_crate_green, + crate_okay, + crate_blue, + crate_red, + crate_grey, + crate_green, )] #![plugin(lint_for_crate_rpass)] //~ WARNING compiler plugins are deprecated -#![rustc_crate_okay] -#![rustc_crate_blue] -#![rustc_crate_red] -#![rustc_crate_grey] -#![rustc_crate_green] +#![crate_okay] +#![crate_blue] +#![crate_red] +#![crate_grey] +#![crate_green] fn main() {} diff --git a/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs b/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs index 1046355a3433f..3c5738f574c26 100644 --- a/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs +++ b/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs @@ -28,6 +28,6 @@ fn parse() { let path = Path::new(file!()); let path = path.canonicalize().unwrap(); - let mut parser = new_parser_from_file(&parse_session, &path); + let mut parser = new_parser_from_file(&parse_session, &path, None); let _ = parser.parse_crate_mod(); } diff --git a/src/test/ui/asm/issue-69092.rs b/src/test/ui/asm/issue-69092.rs new file mode 100644 index 0000000000000..caa5c2e0b9f96 --- /dev/null +++ b/src/test/ui/asm/issue-69092.rs @@ -0,0 +1,10 @@ +// build-fail +// ignore-emscripten no asm! support +// Regression test for #69092 + +#![feature(asm)] + +fn main() { + unsafe { asm!(".ascii \"Xen\0\""); } + //~^ ERROR: :1:9: error: expected string in '.ascii' directive +} diff --git a/src/test/ui/asm/issue-69092.stderr b/src/test/ui/asm/issue-69092.stderr new file mode 100644 index 0000000000000..5661097cb8b80 --- /dev/null +++ b/src/test/ui/asm/issue-69092.stderr @@ -0,0 +1,11 @@ +error: :1:9: error: expected string in '.ascii' directive + .ascii "Xen + ^ + + --> $DIR/issue-69092.rs:8:14 + | +LL | unsafe { asm!(".ascii \"Xen\0\""); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/associated-const/associated-const-ambiguity-report.stderr b/src/test/ui/associated-const/associated-const-ambiguity-report.stderr index 92a8d19021a2c..c5e32afbbce40 100644 --- a/src/test/ui/associated-const/associated-const-ambiguity-report.stderr +++ b/src/test/ui/associated-const/associated-const-ambiguity-report.stderr @@ -1,8 +1,8 @@ error[E0034]: multiple applicable items in scope - --> $DIR/associated-const-ambiguity-report.rs:17:16 + --> $DIR/associated-const-ambiguity-report.rs:17:23 | LL | const X: i32 = ::ID; - | ^^^^^^^^^ multiple `ID` found + | ^^ multiple `ID` found | note: candidate #1 is defined in an impl of the trait `Foo` for the type `i32` --> $DIR/associated-const-ambiguity-report.rs:10:5 diff --git a/src/test/ui/associated-const/associated-const-private-impl.stderr b/src/test/ui/associated-const/associated-const-private-impl.stderr index 7af55174b1905..1b9d7ac7e6c3f 100644 --- a/src/test/ui/associated-const/associated-const-private-impl.stderr +++ b/src/test/ui/associated-const/associated-const-private-impl.stderr @@ -1,8 +1,8 @@ error[E0624]: associated constant `ID` is private - --> $DIR/associated-const-private-impl.rs:13:19 + --> $DIR/associated-const-private-impl.rs:13:30 | LL | assert_eq!(1, bar1::Foo::ID); - | ^^^^^^^^^^^^^ + | ^^ private associated constant error: aborting due to previous error diff --git a/src/test/ui/associated-const/defaults-cyclic-fail.rs b/src/test/ui/associated-const/defaults-cyclic-fail.rs index 9b899ee316a0e..9fb1bbebc9610 100644 --- a/src/test/ui/associated-const/defaults-cyclic-fail.rs +++ b/src/test/ui/associated-const/defaults-cyclic-fail.rs @@ -1,9 +1,9 @@ // build-fail +//~^ ERROR cycle detected when normalizing `<() as Tr>::A` // Cyclic assoc. const defaults don't error unless *used* trait Tr { const A: u8 = Self::B; - //~^ ERROR cycle detected when const-evaluating + checking `Tr::A` const B: u8 = Self::A; } diff --git a/src/test/ui/associated-const/defaults-cyclic-fail.stderr b/src/test/ui/associated-const/defaults-cyclic-fail.stderr index 940182d4aa676..6b2fbe5be4e30 100644 --- a/src/test/ui/associated-const/defaults-cyclic-fail.stderr +++ b/src/test/ui/associated-const/defaults-cyclic-fail.stderr @@ -1,30 +1,42 @@ -error[E0391]: cycle detected when const-evaluating + checking `Tr::A` - --> $DIR/defaults-cyclic-fail.rs:5:5 +error[E0391]: cycle detected when normalizing `<() as Tr>::A` + | +note: ...which requires const-evaluating + checking `Tr::A`... + --> $DIR/defaults-cyclic-fail.rs:6:5 | LL | const A: u8 = Self::B; | ^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `Tr::A`... + --> $DIR/defaults-cyclic-fail.rs:6:5 | +LL | const A: u8 = Self::B; + | ^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating `Tr::A`... - --> $DIR/defaults-cyclic-fail.rs:5:19 + --> $DIR/defaults-cyclic-fail.rs:6:5 | LL | const A: u8 = Self::B; - | ^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires normalizing `<() as Tr>::B`... +note: ...which requires const-evaluating + checking `Tr::B`... + --> $DIR/defaults-cyclic-fail.rs:8:5 + | +LL | const B: u8 = Self::A; + | ^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating + checking `Tr::B`... --> $DIR/defaults-cyclic-fail.rs:8:5 | LL | const B: u8 = Self::A; | ^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating `Tr::B`... - --> $DIR/defaults-cyclic-fail.rs:8:19 + --> $DIR/defaults-cyclic-fail.rs:8:5 | LL | const B: u8 = Self::A; - | ^^^^^^^ - = note: ...which again requires const-evaluating + checking `Tr::A`, completing the cycle + | ^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires normalizing `<() as Tr>::A`, completing the cycle note: cycle used when const-evaluating `main` - --> $DIR/defaults-cyclic-fail.rs:16:16 + --> $DIR/defaults-cyclic-fail.rs:14:1 | -LL | assert_eq!(<() as Tr>::A, 0); - | ^^^^^^^^^^^^^ +LL | fn main() { + | ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-item/associated-item-enum.stderr b/src/test/ui/associated-item/associated-item-enum.stderr index 6f89530eac933..cadf55454a76e 100644 --- a/src/test/ui/associated-item/associated-item-enum.stderr +++ b/src/test/ui/associated-item/associated-item-enum.stderr @@ -8,7 +8,7 @@ LL | Enum::mispellable(); | ^^^^^^^^^^^ | | | variant or associated item not found in `Enum` - | help: there is a method with a similar name: `misspellable` + | help: there is an associated function with a similar name: `misspellable` error[E0599]: no variant or associated item named `mispellable_trait` found for enum `Enum` in the current scope --> $DIR/associated-item-enum.rs:18:11 diff --git a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr index afb8f146192cc..46a132da309bb 100644 --- a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr +++ b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr @@ -18,22 +18,6 @@ LL | | break 0u8; LL | | }; | |_________- enclosing `async` block -error[E0308]: mismatched types - --> $DIR/async-block-control-flow-static-semantics.rs:13:43 - | -LL | fn return_targets_async_block_not_fn() -> u8 { - | --------------------------------- ^^ expected `u8`, found `()` - | | - | implicitly returns `()` as its body has no tail or `return` expression - -error[E0271]: type mismatch resolving `::Output == ()` - --> $DIR/async-block-control-flow-static-semantics.rs:18:39 - | -LL | let _: &dyn Future = █ - | ^^^^^^ expected `()`, found `u8` - | - = note: required for the cast to the object type `dyn std::future::Future` - error[E0308]: mismatched types --> $DIR/async-block-control-flow-static-semantics.rs:22:58 | @@ -55,6 +39,22 @@ LL | let _: &dyn Future = █ | = note: required for the cast to the object type `dyn std::future::Future` +error[E0308]: mismatched types + --> $DIR/async-block-control-flow-static-semantics.rs:13:43 + | +LL | fn return_targets_async_block_not_fn() -> u8 { + | --------------------------------- ^^ expected `u8`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error[E0271]: type mismatch resolving `::Output == ()` + --> $DIR/async-block-control-flow-static-semantics.rs:18:39 + | +LL | let _: &dyn Future = █ + | ^^^^^^ expected `()`, found `u8` + | + = note: required for the cast to the object type `dyn std::future::Future` + error[E0308]: mismatched types --> $DIR/async-block-control-flow-static-semantics.rs:48:44 | diff --git a/src/test/ui/async-await/async-error-span.rs b/src/test/ui/async-await/async-error-span.rs index 28132c9789c67..cf10ebfeca939 100644 --- a/src/test/ui/async-await/async-error-span.rs +++ b/src/test/ui/async-await/async-error-span.rs @@ -5,6 +5,7 @@ use std::future::Future; fn get_future() -> impl Future { +//~^ ERROR the trait bound `(): std::future::Future` is not satisfied panic!() } diff --git a/src/test/ui/async-await/async-error-span.stderr b/src/test/ui/async-await/async-error-span.stderr index b551b99587dd9..4054e739c483d 100644 --- a/src/test/ui/async-await/async-error-span.stderr +++ b/src/test/ui/async-await/async-error-span.stderr @@ -1,15 +1,27 @@ +error[E0277]: the trait bound `(): std::future::Future` is not satisfied + --> $DIR/async-error-span.rs:7:20 + | +LL | fn get_future() -> impl Future { + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `()` +LL | +LL | panic!() + | -------- this returned value is of type `!` + | + = note: the return type of a function must have a statically known size + error[E0698]: type inside `async fn` body must be known in this context - --> $DIR/async-error-span.rs:12:9 + --> $DIR/async-error-span.rs:13:9 | LL | let a; | ^ cannot infer type | note: the type is part of the `async fn` body because of this `await` - --> $DIR/async-error-span.rs:13:5 + --> $DIR/async-error-span.rs:14:5 | LL | get_future().await; | ^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0698`. +Some errors have detailed explanations: E0277, E0698. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/async-fn-size-moved-locals.rs b/src/test/ui/async-await/async-fn-size-moved-locals.rs index 4a413381aa300..636fafc2bc44a 100644 --- a/src/test/ui/async-await/async-fn-size-moved-locals.rs +++ b/src/test/ui/async-await/async-fn-size-moved-locals.rs @@ -110,9 +110,9 @@ async fn mixed_sizes() { } fn main() { - assert_eq!(1028, std::mem::size_of_val(&single())); - assert_eq!(1032, std::mem::size_of_val(&single_with_noop())); - assert_eq!(3084, std::mem::size_of_val(&joined())); - assert_eq!(3084, std::mem::size_of_val(&joined_with_noop())); - assert_eq!(7188, std::mem::size_of_val(&mixed_sizes())); + assert_eq!(1025, std::mem::size_of_val(&single())); + assert_eq!(1026, std::mem::size_of_val(&single_with_noop())); + assert_eq!(3078, std::mem::size_of_val(&joined())); + assert_eq!(3079, std::mem::size_of_val(&joined_with_noop())); + assert_eq!(7181, std::mem::size_of_val(&mixed_sizes())); } diff --git a/src/test/ui/async-await/async-fn-size-uninit-locals.rs b/src/test/ui/async-await/async-fn-size-uninit-locals.rs index 0558084f4f8a3..d5d7b3fc3f0bd 100644 --- a/src/test/ui/async-await/async-fn-size-uninit-locals.rs +++ b/src/test/ui/async-await/async-fn-size-uninit-locals.rs @@ -95,9 +95,9 @@ async fn join_retval() -> Joiner { } fn main() { - assert_eq!(8, std::mem::size_of_val(&single())); - assert_eq!(12, std::mem::size_of_val(&single_with_noop())); - assert_eq!(3084, std::mem::size_of_val(&joined())); - assert_eq!(3084, std::mem::size_of_val(&joined_with_noop())); - assert_eq!(3080, std::mem::size_of_val(&join_retval())); + assert_eq!(2, std::mem::size_of_val(&single())); + assert_eq!(3, std::mem::size_of_val(&single_with_noop())); + assert_eq!(3078, std::mem::size_of_val(&joined())); + assert_eq!(3078, std::mem::size_of_val(&joined_with_noop())); + assert_eq!(3074, std::mem::size_of_val(&join_retval())); } diff --git a/src/test/ui/async-await/async-fn-size.rs b/src/test/ui/async-await/async-fn-size.rs index b313992db4ecb..0c1f3636446c9 100644 --- a/src/test/ui/async-await/async-fn-size.rs +++ b/src/test/ui/async-await/async-fn-size.rs @@ -86,13 +86,13 @@ async fn await3_level5() -> u8 { fn main() { assert_eq!(2, std::mem::size_of_val(&base())); - assert_eq!(8, std::mem::size_of_val(&await1_level1())); - assert_eq!(12, std::mem::size_of_val(&await2_level1())); - assert_eq!(12, std::mem::size_of_val(&await3_level1())); - assert_eq!(24, std::mem::size_of_val(&await3_level2())); - assert_eq!(36, std::mem::size_of_val(&await3_level3())); - assert_eq!(48, std::mem::size_of_val(&await3_level4())); - assert_eq!(60, std::mem::size_of_val(&await3_level5())); + assert_eq!(3, std::mem::size_of_val(&await1_level1())); + assert_eq!(4, std::mem::size_of_val(&await2_level1())); + assert_eq!(5, std::mem::size_of_val(&await3_level1())); + assert_eq!(8, std::mem::size_of_val(&await3_level2())); + assert_eq!(11, std::mem::size_of_val(&await3_level3())); + assert_eq!(14, std::mem::size_of_val(&await3_level4())); + assert_eq!(17, std::mem::size_of_val(&await3_level5())); assert_eq!(1, wait(base())); assert_eq!(1, wait(await1_level1())); diff --git a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs index 22bcbb1064dd7..cebff3be6b059 100644 --- a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs +++ b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs @@ -62,6 +62,7 @@ fn foo10() -> Result<(), ()> { fn foo11() -> Result<(), ()> { let _ = await bar()?; //~ ERROR `await` is only allowed inside `async` functions and blocks //~^ ERROR incorrect use of `await` + //~| ERROR the `?` operator can only be applied to values that implement `std::ops::Try` Ok(()) } fn foo12() -> Result<(), ()> { diff --git a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr index 92cef80c19360..61f2570b2ff93 100644 --- a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr +++ b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr @@ -71,49 +71,49 @@ LL | let _ = await bar()?; | ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:68:14 + --> $DIR/incorrect-syntax-suggestions.rs:69:14 | LL | let _ = (await bar())?; | ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:73:24 + --> $DIR/incorrect-syntax-suggestions.rs:74:24 | LL | let _ = bar().await(); | ^^ help: `await` is not a method call, remove the parentheses error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:78:24 + --> $DIR/incorrect-syntax-suggestions.rs:79:24 | LL | let _ = bar().await()?; | ^^ help: `await` is not a method call, remove the parentheses error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:106:13 + --> $DIR/incorrect-syntax-suggestions.rs:107:13 | LL | let _ = await!(bar()); | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:110:13 + --> $DIR/incorrect-syntax-suggestions.rs:111:13 | LL | let _ = await!(bar())?; | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:115:17 + --> $DIR/incorrect-syntax-suggestions.rs:116:17 | LL | let _ = await!(bar())?; | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:123:17 + --> $DIR/incorrect-syntax-suggestions.rs:124:17 | LL | let _ = await!(bar())?; | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: expected expression, found `=>` - --> $DIR/incorrect-syntax-suggestions.rs:131:25 + --> $DIR/incorrect-syntax-suggestions.rs:132:25 | LL | match await { await => () } | ----- ^^ expected expression @@ -121,13 +121,13 @@ LL | match await { await => () } | while parsing this incorrect await expression error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:131:11 + --> $DIR/incorrect-syntax-suggestions.rs:132:11 | LL | match await { await => () } | ^^^^^^^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ await => () }.await` error: expected one of `.`, `?`, `{`, or an operator, found `}` - --> $DIR/incorrect-syntax-suggestions.rs:134:1 + --> $DIR/incorrect-syntax-suggestions.rs:135:1 | LL | match await { await => () } | ----- - expected one of `.`, `?`, `{`, or an operator @@ -162,7 +162,7 @@ LL | let _ = await bar()?; | ^^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:68:14 + --> $DIR/incorrect-syntax-suggestions.rs:69:14 | LL | fn foo12() -> Result<(), ()> { | ----- this is not `async` @@ -170,7 +170,7 @@ LL | let _ = (await bar())?; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:73:13 + --> $DIR/incorrect-syntax-suggestions.rs:74:13 | LL | fn foo13() -> Result<(), ()> { | ----- this is not `async` @@ -178,7 +178,7 @@ LL | let _ = bar().await(); | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:78:13 + --> $DIR/incorrect-syntax-suggestions.rs:79:13 | LL | fn foo14() -> Result<(), ()> { | ----- this is not `async` @@ -186,7 +186,7 @@ LL | let _ = bar().await()?; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:83:13 + --> $DIR/incorrect-syntax-suggestions.rs:84:13 | LL | fn foo15() -> Result<(), ()> { | ----- this is not `async` @@ -194,7 +194,7 @@ LL | let _ = bar().await; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:87:13 + --> $DIR/incorrect-syntax-suggestions.rs:88:13 | LL | fn foo16() -> Result<(), ()> { | ----- this is not `async` @@ -202,7 +202,7 @@ LL | let _ = bar().await?; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:92:17 + --> $DIR/incorrect-syntax-suggestions.rs:93:17 | LL | fn foo() -> Result<(), ()> { | --- this is not `async` @@ -210,7 +210,7 @@ LL | let _ = bar().await?; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:99:17 + --> $DIR/incorrect-syntax-suggestions.rs:100:17 | LL | let foo = || { | -- this is not `async` @@ -218,7 +218,7 @@ LL | let _ = bar().await?; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:115:17 + --> $DIR/incorrect-syntax-suggestions.rs:116:17 | LL | fn foo() -> Result<(), ()> { | --- this is not `async` @@ -226,7 +226,7 @@ LL | let _ = await!(bar())?; | ^^^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:123:17 + --> $DIR/incorrect-syntax-suggestions.rs:124:17 | LL | let foo = || { | -- this is not `async` @@ -242,7 +242,16 @@ LL | let _ = await bar()?; = help: the trait `std::ops::Try` is not implemented for `impl std::future::Future` = note: required by `std::ops::Try::into_result` -error: aborting due to 35 previous errors +error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try` + --> $DIR/incorrect-syntax-suggestions.rs:63:19 + | +LL | let _ = await bar()?; + | ^^^^^^ the `?` operator cannot be applied to type `impl std::future::Future` + | + = help: the trait `std::ops::Try` is not implemented for `impl std::future::Future` + = note: required by `std::ops::Try::into_result` + +error: aborting due to 36 previous errors Some errors have detailed explanations: E0277, E0728. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/expansion-in-attrs.rs b/src/test/ui/async-await/expansion-in-attrs.rs new file mode 100644 index 0000000000000..af77c3463b5dd --- /dev/null +++ b/src/test/ui/async-await/expansion-in-attrs.rs @@ -0,0 +1,13 @@ +// check-pass +// edition:2018 + +macro_rules! with_doc { + ($doc: expr) => { + #[doc = $doc] + async fn f() {} + }; +} + +with_doc!(concat!("")); + +fn main() {} diff --git a/src/test/ui/async-await/issue-64130-1-sync.rs b/src/test/ui/async-await/issue-64130-1-sync.rs index cc5ca89f03af0..af83f14bbda5d 100644 --- a/src/test/ui/async-await/issue-64130-1-sync.rs +++ b/src/test/ui/async-await/issue-64130-1-sync.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] // edition:2018 // This tests the the specialized async-await-specific error when futures don't implement an diff --git a/src/test/ui/async-await/issue-64130-2-send.rs b/src/test/ui/async-await/issue-64130-2-send.rs index 1efe2ab3f85e2..2362831d8b8f6 100644 --- a/src/test/ui/async-await/issue-64130-2-send.rs +++ b/src/test/ui/async-await/issue-64130-2-send.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] // edition:2018 // This tests the the specialized async-await-specific error when futures don't implement an diff --git a/src/test/ui/async-await/issue-64130-3-other.rs b/src/test/ui/async-await/issue-64130-3-other.rs index 901544edba18a..b819970d59d50 100644 --- a/src/test/ui/async-await/issue-64130-3-other.rs +++ b/src/test/ui/async-await/issue-64130-3-other.rs @@ -1,4 +1,5 @@ #![feature(optin_builtin_traits)] +#![feature(negative_impls)] // edition:2018 // This tests the the unspecialized async-await-specific error when futures don't implement an diff --git a/src/test/ui/async-await/issue-64130-3-other.stderr b/src/test/ui/async-await/issue-64130-3-other.stderr index d6828172928dd..6456e7abd745d 100644 --- a/src/test/ui/async-await/issue-64130-3-other.stderr +++ b/src/test/ui/async-await/issue-64130-3-other.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `Foo: Qux` is not satisfied in `impl std::future::Future` - --> $DIR/issue-64130-3-other.rs:23:5 + --> $DIR/issue-64130-3-other.rs:24:5 | LL | fn is_qux(t: T) { } | ------ --- required by this bound in `is_qux` @@ -13,7 +13,7 @@ LL | is_qux(bar()); = help: the following implementations were found: note: future does not implement `Qux` as this value is used across an await - --> $DIR/issue-64130-3-other.rs:17:5 + --> $DIR/issue-64130-3-other.rs:18:5 | LL | let x = Foo; | - has type `Foo` diff --git a/src/test/ui/async-await/issue-66312.rs b/src/test/ui/async-await/issue-66312.rs new file mode 100644 index 0000000000000..9224971ecb123 --- /dev/null +++ b/src/test/ui/async-await/issue-66312.rs @@ -0,0 +1,14 @@ +// edition:2018 + +trait Test { + fn is_some(self: T); //~ ERROR invalid `self` parameter type +} + +async fn f() { + let x = Some(2); + if x.is_some() { + println!("Some"); + } +} + +fn main() {} diff --git a/src/test/ui/async-await/issue-66312.stderr b/src/test/ui/async-await/issue-66312.stderr new file mode 100644 index 0000000000000..80d294a10a018 --- /dev/null +++ b/src/test/ui/async-await/issue-66312.stderr @@ -0,0 +1,12 @@ +error[E0307]: invalid `self` parameter type: T + --> $DIR/issue-66312.rs:4:22 + | +LL | fn is_some(self: T); + | ^ + | + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0307`. diff --git a/src/test/ui/async-await/issue-67651.rs b/src/test/ui/async-await/issue-67651.rs new file mode 100644 index 0000000000000..bd96a3b709bae --- /dev/null +++ b/src/test/ui/async-await/issue-67651.rs @@ -0,0 +1,20 @@ +// edition:2018 + +trait From { + fn from(); +} + +impl From for () { + fn from() {} +} + +impl From for () { +//~^ ERROR conflicting implementations of trait + fn from() {} +} + +fn bar() -> impl core::future::Future { + async move { From::from() } +} + +fn main() {} diff --git a/src/test/ui/async-await/issue-67651.stderr b/src/test/ui/async-await/issue-67651.stderr new file mode 100644 index 0000000000000..99857c215eb8f --- /dev/null +++ b/src/test/ui/async-await/issue-67651.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `From` for type `()`: + --> $DIR/issue-67651.rs:11:1 + | +LL | impl From for () { + | ---------------- first implementation here +... +LL | impl From for () { + | ^^^^^^^^^^^^^^^^ conflicting implementation for `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/async-await/issues/issue-62009-1.stderr b/src/test/ui/async-await/issues/issue-62009-1.stderr index cd6670923c2c6..0624c049048c7 100644 --- a/src/test/ui/async-await/issues/issue-62009-1.stderr +++ b/src/test/ui/async-await/issues/issue-62009-1.stderr @@ -33,10 +33,10 @@ error[E0277]: the trait bound `[closure@$DIR/issue-62009-1.rs:16:5: 16:15]: std: LL | (|_| 2333).await; | ^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:16:5: 16:15]` | - ::: $SRC_DIR/libstd/future.rs:LL:COL + ::: $SRC_DIR/libcore/future/mod.rs:LL:COL | LL | F: Future, - | ------ required by this bound in `std::future::poll_with_tls_context` + | ------ required by this bound in `std::future::poll_with_context` error: aborting due to 4 previous errors diff --git a/src/test/ui/async-await/issues/issue-62097.nll.stderr b/src/test/ui/async-await/issues/issue-62097.nll.stderr index f72c645bf8dbf..2a399540e5296 100644 --- a/src/test/ui/async-await/issues/issue-62097.nll.stderr +++ b/src/test/ui/async-await/issues/issue-62097.nll.stderr @@ -16,13 +16,13 @@ help: to force the closure to take ownership of `self` (and any other referenced LL | foo(move || self.bar()).await; | ^^^^^^^ -error[E0521]: borrowed data escapes outside of method +error[E0521]: borrowed data escapes outside of associated function --> $DIR/issue-62097.rs:13:9 | LL | pub async fn run_dummy_fn(&self) { - | ----- `self` is a reference that is only valid in the method body + | ----- `self` is a reference that is only valid in the associated function body LL | foo(|| self.bar()).await; - | ^^^^^^^^^^^^^^^^^^ `self` escapes the method body here + | ^^^^^^^^^^^^^^^^^^ `self` escapes the associated function body here error: aborting due to 2 previous errors diff --git a/src/test/ui/async-await/issues/issue-63388-1.nll.stderr b/src/test/ui/async-await/issues/issue-63388-1.nll.stderr index 696f79ec40f36..464459d2d61ad 100644 --- a/src/test/ui/async-await/issues/issue-63388-1.nll.stderr +++ b/src/test/ui/async-await/issues/issue-63388-1.nll.stderr @@ -9,7 +9,7 @@ LL | ) -> &dyn Foo LL | / { LL | | foo LL | | } - | |_____^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` + | |_____^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` error: aborting due to previous error diff --git a/src/test/ui/async-await/issues/issue-63388-2.nll.stderr b/src/test/ui/async-await/issues/issue-63388-2.nll.stderr deleted file mode 100644 index 6edb9e63d480a..0000000000000 --- a/src/test/ui/async-await/issues/issue-63388-2.nll.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0106]: missing lifetime specifier - --> $DIR/issue-63388-2.rs:12:10 - | -LL | foo: &dyn Foo, bar: &'a dyn Foo - | -------- ----------- -LL | ) -> &dyn Foo - | ^ help: consider using the named lifetime: `&'a` - | - = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `foo` or `bar` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/async-await/issues/issue-63388-2.rs b/src/test/ui/async-await/issues/issue-63388-2.rs index 73e7f25f97d0d..458bc9faeaf27 100644 --- a/src/test/ui/async-await/issues/issue-63388-2.rs +++ b/src/test/ui/async-await/issues/issue-63388-2.rs @@ -8,7 +8,7 @@ trait Foo {} impl Xyz { async fn do_sth<'a>( - foo: &dyn Foo, bar: &'a dyn Foo //~ ERROR cannot infer + foo: &dyn Foo, bar: &'a dyn Foo ) -> &dyn Foo //~ ERROR missing lifetime specifier { foo diff --git a/src/test/ui/async-await/issues/issue-63388-2.stderr b/src/test/ui/async-await/issues/issue-63388-2.stderr index 9f51ced9c3f49..6edb9e63d480a 100644 --- a/src/test/ui/async-await/issues/issue-63388-2.stderr +++ b/src/test/ui/async-await/issues/issue-63388-2.stderr @@ -8,21 +8,6 @@ LL | ) -> &dyn Foo | = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `foo` or `bar` -error: cannot infer an appropriate lifetime - --> $DIR/issue-63388-2.rs:11:9 - | -LL | foo: &dyn Foo, bar: &'a dyn Foo - | ^^^ ...but this borrow... -... -LL | foo - | --- this return type evaluates to the `'static` lifetime... - | -note: ...can't outlive the lifetime `'_` as defined on the method body at 11:14 - --> $DIR/issue-63388-2.rs:11:14 - | -LL | foo: &dyn Foo, bar: &'a dyn Foo - | ^ - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/async-await/issues/issue-65159.rs b/src/test/ui/async-await/issues/issue-65159.rs index b5fee061f277e..2f80435046bdf 100644 --- a/src/test/ui/async-await/issues/issue-65159.rs +++ b/src/test/ui/async-await/issues/issue-65159.rs @@ -5,6 +5,7 @@ async fn copy() -> Result<()> //~ ERROR wrong number of type arguments { Ok(()) + //~^ type annotations needed } fn main() { } diff --git a/src/test/ui/async-await/issues/issue-65159.stderr b/src/test/ui/async-await/issues/issue-65159.stderr index 56d2c38b302e9..04cfa5249982e 100644 --- a/src/test/ui/async-await/issues/issue-65159.stderr +++ b/src/test/ui/async-await/issues/issue-65159.stderr @@ -4,6 +4,13 @@ error[E0107]: wrong number of type arguments: expected 2, found 1 LL | async fn copy() -> Result<()> | ^^^^^^^^^^ expected 2 type arguments -error: aborting due to previous error +error[E0282]: type annotations needed + --> $DIR/issue-65159.rs:7:5 + | +LL | Ok(()) + | ^^ cannot infer type for type parameter `E` declared on the enum `Result` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0107`. +Some errors have detailed explanations: E0107, E0282. +For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs index b12d7bccecead..05960c0c7f636 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs @@ -9,6 +9,9 @@ impl Trait<'_, '_> for T { } async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> { //~^ ERROR ambiguous lifetime bound //~| ERROR ambiguous lifetime bound + //~| ERROR ambiguous lifetime bound + //~| ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds + //~| ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds (a, b) } diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr index f9a1b4b3394c1..c69595a3f4d01 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr @@ -14,5 +14,42 @@ LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<' | = help: add #![feature(member_constraints)] to the crate attributes to enable -error: aborting due to 2 previous errors +error: ambiguous lifetime bound in `impl Trait` + --> $DIR/ret-impl-trait-no-fg.rs:9:64 + | +LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> { + | ^^^^^^^^^^^^^^^^^^ the elided lifetimes here do not outlive one another + | + = help: add #![feature(member_constraints)] to the crate attributes to enable + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ret-impl-trait-no-fg.rs:9:1 + | +LL | / async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> { +LL | | +LL | | +LL | | +... | +LL | | (a, b) +LL | | } + | |_^ + | + = note: hidden type `(&u8, &u8)` captures lifetime '_#4r + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ret-impl-trait-no-fg.rs:9:1 + | +LL | / async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> { +LL | | +LL | | +LL | | +... | +LL | | (a, b) +LL | | } + | |_^ + | + = note: hidden type `(&u8, &u8)` captures lifetime '_#5r + +error: aborting due to 5 previous errors +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/async-await/no-std.rs b/src/test/ui/async-await/no-std.rs new file mode 100644 index 0000000000000..63e93cdff7e77 --- /dev/null +++ b/src/test/ui/async-await/no-std.rs @@ -0,0 +1,13 @@ +// edition:2018 +// check-pass + +#![no_std] +#![crate_type = "rlib"] + +use core::future::Future; + +async fn a(f: impl Future) { + f.await; +} + +fn main() {} diff --git a/src/test/ui/auto-ref-slice-plus-ref.stderr b/src/test/ui/auto-ref-slice-plus-ref.stderr index 50ca5cad4bc68..dc7deb8a7c7ac 100644 --- a/src/test/ui/auto-ref-slice-plus-ref.stderr +++ b/src/test/ui/auto-ref-slice-plus-ref.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `test_mut` found for struct `std::vec::Vec<{intege --> $DIR/auto-ref-slice-plus-ref.rs:7:7 | LL | a.test_mut(); - | ^^^^^^^^ help: there is a method with a similar name: `get_mut` + | ^^^^^^^^ help: there is an associated function with a similar name: `get_mut` | = help: items from traits can only be used if the trait is implemented and in scope note: `MyIter` defines an item `test_mut`, perhaps you need to implement it diff --git a/src/test/ui/binding/ambiguity-item.rs b/src/test/ui/binding/ambiguity-item.rs new file mode 100644 index 0000000000000..10613cc616413 --- /dev/null +++ b/src/test/ui/binding/ambiguity-item.rs @@ -0,0 +1,18 @@ +// Identifier pattern referring to an ambiguity item is an error (issue #46079). + +mod m { + pub fn f() {} +} +use m::*; + +mod n { + pub fn f() {} +} +use n::*; // OK, no conflict with `use m::*;` + +fn main() { + let v = f; //~ ERROR `f` is ambiguous + match v { + f => {} //~ ERROR `f` is ambiguous + } +} diff --git a/src/test/ui/binding/ambiguity-item.stderr b/src/test/ui/binding/ambiguity-item.stderr new file mode 100644 index 0000000000000..615193c0d02db --- /dev/null +++ b/src/test/ui/binding/ambiguity-item.stderr @@ -0,0 +1,41 @@ +error[E0659]: `f` is ambiguous (glob import vs glob import in the same module) + --> $DIR/ambiguity-item.rs:14:13 + | +LL | let v = f; + | ^ ambiguous name + | +note: `f` could refer to the function imported here + --> $DIR/ambiguity-item.rs:6:5 + | +LL | use m::*; + | ^^^^ + = help: consider adding an explicit import of `f` to disambiguate +note: `f` could also refer to the function imported here + --> $DIR/ambiguity-item.rs:11:5 + | +LL | use n::*; // OK, no conflict with `use m::*;` + | ^^^^ + = help: consider adding an explicit import of `f` to disambiguate + +error[E0659]: `f` is ambiguous (glob import vs glob import in the same module) + --> $DIR/ambiguity-item.rs:16:9 + | +LL | f => {} + | ^ ambiguous name + | +note: `f` could refer to the function imported here + --> $DIR/ambiguity-item.rs:6:5 + | +LL | use m::*; + | ^^^^ + = help: consider adding an explicit import of `f` to disambiguate +note: `f` could also refer to the function imported here + --> $DIR/ambiguity-item.rs:11:5 + | +LL | use n::*; // OK, no conflict with `use m::*;` + | ^^^^ + = help: consider adding an explicit import of `f` to disambiguate + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/binding/const-param.rs b/src/test/ui/binding/const-param.rs new file mode 100644 index 0000000000000..3c7f4d071f694 --- /dev/null +++ b/src/test/ui/binding/const-param.rs @@ -0,0 +1,12 @@ +// Identifier pattern referring to a const generic parameter is an error (issue #68853). + +#![feature(const_generics)] //~ WARN the feature `const_generics` is incomplete + +fn check() { + match 1 { + N => {} //~ ERROR const parameters cannot be referenced in patterns + _ => {} + } +} + +fn main() {} diff --git a/src/test/ui/binding/const-param.stderr b/src/test/ui/binding/const-param.stderr new file mode 100644 index 0000000000000..25b1c75c9a004 --- /dev/null +++ b/src/test/ui/binding/const-param.stderr @@ -0,0 +1,17 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/const-param.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0158]: const parameters cannot be referenced in patterns + --> $DIR/const-param.rs:7:9 + | +LL | N => {} + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0158`. diff --git a/src/test/ui/block-result/issue-3563.stderr b/src/test/ui/block-result/issue-3563.stderr index be551f6e889fc..5255e48bee13b 100644 --- a/src/test/ui/block-result/issue-3563.stderr +++ b/src/test/ui/block-result/issue-3563.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `b` found for reference `&Self` in the current sco --> $DIR/issue-3563.rs:3:17 | LL | || self.b() - | ^ help: there is a method with a similar name: `a` + | ^ help: there is an associated function with a similar name: `a` error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-69789-iterator-mut-suggestion.rs b/src/test/ui/borrowck/issue-69789-iterator-mut-suggestion.rs new file mode 100644 index 0000000000000..f6d0e9e04d321 --- /dev/null +++ b/src/test/ui/borrowck/issue-69789-iterator-mut-suggestion.rs @@ -0,0 +1,11 @@ +// Regression test for #69789: rustc generated an invalid suggestion +// when `&` reference from `&mut` iterator is mutated. + +fn main() { + for item in &mut std::iter::empty::<&'static ()>() { + //~^ NOTE this iterator yields `&` references + *item = (); + //~^ ERROR cannot assign + //~| NOTE cannot be written + } +} diff --git a/src/test/ui/borrowck/issue-69789-iterator-mut-suggestion.stderr b/src/test/ui/borrowck/issue-69789-iterator-mut-suggestion.stderr new file mode 100644 index 0000000000000..d2865ffd196a5 --- /dev/null +++ b/src/test/ui/borrowck/issue-69789-iterator-mut-suggestion.stderr @@ -0,0 +1,12 @@ +error[E0594]: cannot assign to `*item` which is behind a `&` reference + --> $DIR/issue-69789-iterator-mut-suggestion.rs:7:9 + | +LL | for item in &mut std::iter::empty::<&'static ()>() { + | -------------------------------------- this iterator yields `&` references +LL | +LL | *item = (); + | ^^^^^^^^^^ `item` is a `&` reference, so the data it refers to cannot be written + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/src/test/ui/closures/issue-52437.rs b/src/test/ui/closures/issue-52437.rs index 1e649a556e01d..634638e1335b3 100644 --- a/src/test/ui/closures/issue-52437.rs +++ b/src/test/ui/closures/issue-52437.rs @@ -3,4 +3,5 @@ fn main() { //~^ ERROR: invalid label name `'static` //~| ERROR: `loop` is not allowed in a `const` //~| ERROR: type annotations needed + //~| ERROR mismatched types } diff --git a/src/test/ui/closures/issue-52437.stderr b/src/test/ui/closures/issue-52437.stderr index b9225e55fe5c7..acb59c7b02d1b 100644 --- a/src/test/ui/closures/issue-52437.stderr +++ b/src/test/ui/closures/issue-52437.stderr @@ -19,7 +19,15 @@ error[E0282]: type annotations needed LL | [(); &(&'static: loop { |x| {}; }) as *const _ as usize] | ^ consider giving this closure parameter a type -error: aborting due to 3 previous errors +error[E0308]: mismatched types + --> $DIR/issue-52437.rs:2:5 + | +LL | fn main() { + | - expected `()` because of default return type +LL | [(); &(&'static: loop { |x| {}; }) as *const _ as usize] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found array `[(); _]` + +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0282, E0658. +Some errors have detailed explanations: E0282, E0308, E0658. For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/codemap_tests/empty_span.rs b/src/test/ui/codemap_tests/empty_span.rs index 4d52b391280a7..7753e2eceb543 100644 --- a/src/test/ui/codemap_tests/empty_span.rs +++ b/src/test/ui/codemap_tests/empty_span.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] fn main() { struct Foo; diff --git a/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.rs b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.rs index b4f5f9ef56bb1..24b878927530c 100644 --- a/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.rs +++ b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] #![feature(marker_trait_attr)] #[marker] @@ -6,13 +6,11 @@ trait MyTrait {} struct TestType(::std::marker::PhantomData); -unsafe impl Send for TestType {} +unsafe impl Send for TestType {} -impl !Send for TestType {} -//~^ ERROR conflicting implementations +impl !Send for TestType {} //~ ERROR found both positive and negative implementation -unsafe impl Send for TestType {} -//~^ ERROR conflicting implementations +unsafe impl Send for TestType {} //~ ERROR conflicting implementations impl !Send for TestType {} diff --git a/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr index 25d3d3ee997a5..5081536b70245 100644 --- a/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr +++ b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr @@ -1,21 +1,22 @@ -error[E0119]: conflicting implementations of trait `std::marker::Send` for type `TestType<_>`: +error[E0748]: found both positive and negative implementation of trait `std::marker::Send` for type `TestType<_>`: --> $DIR/coherence-conflicting-negative-trait-impl.rs:11:1 | -LL | unsafe impl Send for TestType {} - | ---------------------------------------------------- first implementation here +LL | unsafe impl Send for TestType {} + | ------------------------------------------------------ positive implementation here LL | LL | impl !Send for TestType {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here error[E0119]: conflicting implementations of trait `std::marker::Send` for type `TestType<_>`: - --> $DIR/coherence-conflicting-negative-trait-impl.rs:14:1 + --> $DIR/coherence-conflicting-negative-trait-impl.rs:13:1 | -LL | unsafe impl Send for TestType {} - | ---------------------------------------------------- first implementation here +LL | unsafe impl Send for TestType {} + | ------------------------------------------------------ first implementation here ... -LL | unsafe impl Send for TestType {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>` +LL | unsafe impl Send for TestType {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>` error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0119`. +Some errors have detailed explanations: E0119, E0748. +For more information about an error, try `rustc --explain E0119`. diff --git a/src/test/ui/coherence/coherence-default-trait-impl.rs b/src/test/ui/coherence/coherence-default-trait-impl.rs index db24662e2d5ad..4115ba34e17b2 100644 --- a/src/test/ui/coherence/coherence-default-trait-impl.rs +++ b/src/test/ui/coherence/coherence-default-trait-impl.rs @@ -1,4 +1,5 @@ #![feature(optin_builtin_traits)] +#![feature(negative_impls)] auto trait MySafeTrait {} diff --git a/src/test/ui/coherence/coherence-default-trait-impl.stderr b/src/test/ui/coherence/coherence-default-trait-impl.stderr index f6a163268a14a..b08ccb087d91c 100644 --- a/src/test/ui/coherence/coherence-default-trait-impl.stderr +++ b/src/test/ui/coherence/coherence-default-trait-impl.stderr @@ -1,11 +1,11 @@ error[E0199]: implementing the trait `MySafeTrait` is not unsafe - --> $DIR/coherence-default-trait-impl.rs:7:1 + --> $DIR/coherence-default-trait-impl.rs:8:1 | LL | unsafe impl MySafeTrait for Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0200]: the trait `MyUnsafeTrait` requires an `unsafe impl` declaration - --> $DIR/coherence-default-trait-impl.rs:12:1 + --> $DIR/coherence-default-trait-impl.rs:13:1 | LL | impl MyUnsafeTrait for Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs index 5ea69190951e1..a9c8d20a79d75 100644 --- a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs +++ b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs @@ -1,4 +1,5 @@ #![feature(optin_builtin_traits)] +#![feature(negative_impls)] // Test for issue #56934 - that it is impossible to redundantly // implement an auto-trait for a trait object type that contains it. diff --git a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr index b8137b36948cd..23db5328a728b 100644 --- a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr +++ b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr @@ -1,17 +1,17 @@ error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1` - --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:14:1 + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1 | LL | impl !Marker1 for dyn Object + Marker2 { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1` error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2` - --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:16:1 + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:17:1 | LL | impl !Marker2 for dyn Object + Marker2 { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2` error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:22:1 + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:23:1 | LL | impl !Send for dyn Marker2 {} | ^^^^^^^^^^^^^^^----------- @@ -22,13 +22,13 @@ LL | impl !Send for dyn Marker2 {} = note: define and implement a trait or new type instead error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `(dyn Object + 'static)` - --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:26:1 + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:27:1 | LL | impl !Send for dyn Object {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `(dyn Object + Marker2 + 'static)` - --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:27:1 + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:28:1 | LL | impl !Send for dyn Object + Marker2 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type diff --git a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs index 6b5689e8260f0..c565f9c83e89e 100644 --- a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs +++ b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs @@ -1,4 +1,5 @@ #![feature(optin_builtin_traits)] +#![feature(negative_impls)] // Test for issue #56934 - that it is impossible to redundantly // implement an auto-trait for a trait object type that contains it. diff --git a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr index d68337bed0066..141ab7771f325 100644 --- a/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr +++ b/src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr @@ -1,17 +1,17 @@ error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1` - --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:14:1 + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1 | LL | impl Marker1 for dyn Object + Marker2 { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1` error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2` - --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:16:1 + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:17:1 | LL | impl Marker2 for dyn Object + Marker2 { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2` error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:22:1 + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:23:1 | LL | unsafe impl Send for dyn Marker2 {} | ^^^^^^^^^^^^^^^^^^^^^----------- @@ -22,13 +22,13 @@ LL | unsafe impl Send for dyn Marker2 {} = note: define and implement a trait or new type instead error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `(dyn Object + 'static)` - --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:26:1 + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:27:1 | LL | unsafe impl Send for dyn Object {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `(dyn Object + Marker2 + 'static)` - --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:27:1 + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:28:1 | LL | unsafe impl Send for dyn Object + Marker2 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type diff --git a/src/test/ui/coherence/coherence-impls-copy.rs b/src/test/ui/coherence/coherence-impls-copy.rs index dec40f9dd40aa..a86ca0e5eacdc 100644 --- a/src/test/ui/coherence/coherence-impls-copy.rs +++ b/src/test/ui/coherence/coherence-impls-copy.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Copy; diff --git a/src/test/ui/coherence/coherence-impls-send.rs b/src/test/ui/coherence/coherence-impls-send.rs index 7898dc9831da2..e00cb9a7c5b51 100644 --- a/src/test/ui/coherence/coherence-impls-send.rs +++ b/src/test/ui/coherence/coherence-impls-send.rs @@ -1,9 +1,9 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Copy; enum TestE { - A + A, } struct MyType; @@ -26,5 +26,4 @@ unsafe impl Send for &'static [NotSync] {} //~^ ERROR conflicting implementations of trait //~| ERROR only traits defined in the current crate -fn main() { -} +fn main() {} diff --git a/src/test/ui/coherence/coherence-impls-sized.rs b/src/test/ui/coherence/coherence-impls-sized.rs index 19e7349c507ef..231b96ad42efb 100644 --- a/src/test/ui/coherence/coherence-impls-sized.rs +++ b/src/test/ui/coherence/coherence-impls-sized.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Copy; diff --git a/src/test/ui/coherence/coherence-negative-impls-safe-rpass.rs b/src/test/ui/coherence/coherence-negative-impls-safe-rpass.rs index 695a71cbd2d7c..b87e162aca096 100644 --- a/src/test/ui/coherence/coherence-negative-impls-safe-rpass.rs +++ b/src/test/ui/coherence/coherence-negative-impls-safe-rpass.rs @@ -2,7 +2,7 @@ #![allow(dead_code)] // pretty-expanded FIXME #23616 -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Send; diff --git a/src/test/ui/coherence/coherence-negative-impls-safe.rs b/src/test/ui/coherence/coherence-negative-impls-safe.rs index 45c478ecc0362..4821aa6b5ad3d 100644 --- a/src/test/ui/coherence/coherence-negative-impls-safe.rs +++ b/src/test/ui/coherence/coherence-negative-impls-safe.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Send; diff --git a/src/test/ui/coherence/coherence-orphan.rs b/src/test/ui/coherence/coherence-orphan.rs index a7b48825d7c02..3beac04c7e829 100644 --- a/src/test/ui/coherence/coherence-orphan.rs +++ b/src/test/ui/coherence/coherence-orphan.rs @@ -1,5 +1,5 @@ // aux-build:coherence_orphan_lib.rs -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] extern crate coherence_orphan_lib as lib; diff --git a/src/test/ui/conditional-compilation/cfg_accessible-input-validation.rs b/src/test/ui/conditional-compilation/cfg_accessible-input-validation.rs new file mode 100644 index 0000000000000..c51c908a4262e --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg_accessible-input-validation.rs @@ -0,0 +1,24 @@ +#![feature(cfg_accessible)] + +#[cfg_accessible] //~ ERROR malformed `cfg_accessible` attribute input +struct S1; + +#[cfg_accessible = "value"] //~ ERROR malformed `cfg_accessible` attribute input +struct S2; + +#[cfg_accessible()] //~ ERROR `cfg_accessible` path is not specified +struct S3; + +#[cfg_accessible(std, core)] //~ ERROR multiple `cfg_accessible` paths are specified +struct S4; + +#[cfg_accessible("std")] //~ ERROR `cfg_accessible` path cannot be a literal +struct S5; + +#[cfg_accessible(std = "value")] //~ ERROR `cfg_accessible` path cannot accept arguments +struct S6; + +#[cfg_accessible(std(value))] //~ ERROR `cfg_accessible` path cannot accept arguments +struct S7; + +fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg_accessible-input-validation.stderr b/src/test/ui/conditional-compilation/cfg_accessible-input-validation.stderr new file mode 100644 index 0000000000000..86706c766356e --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg_accessible-input-validation.stderr @@ -0,0 +1,44 @@ +error: malformed `cfg_accessible` attribute input + --> $DIR/cfg_accessible-input-validation.rs:3:1 + | +LL | #[cfg_accessible] + | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[cfg_accessible(path)]` + +error: malformed `cfg_accessible` attribute input + --> $DIR/cfg_accessible-input-validation.rs:6:1 + | +LL | #[cfg_accessible = "value"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[cfg_accessible(path)]` + +error: `cfg_accessible` path is not specified + --> $DIR/cfg_accessible-input-validation.rs:9:1 + | +LL | #[cfg_accessible()] + | ^^^^^^^^^^^^^^^^^^^ + +error: multiple `cfg_accessible` paths are specified + --> $DIR/cfg_accessible-input-validation.rs:12:23 + | +LL | #[cfg_accessible(std, core)] + | ^^^^ + +error: `cfg_accessible` path cannot be a literal + --> $DIR/cfg_accessible-input-validation.rs:15:18 + | +LL | #[cfg_accessible("std")] + | ^^^^^ + +error: `cfg_accessible` path cannot accept arguments + --> $DIR/cfg_accessible-input-validation.rs:18:18 + | +LL | #[cfg_accessible(std = "value")] + | ^^^^^^^^^^^^^ + +error: `cfg_accessible` path cannot accept arguments + --> $DIR/cfg_accessible-input-validation.rs:21:18 + | +LL | #[cfg_accessible(std(value))] + | ^^^^^^^^^^ + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/conditional-compilation/cfg_accessible-stuck.rs b/src/test/ui/conditional-compilation/cfg_accessible-stuck.rs new file mode 100644 index 0000000000000..8bc93fa324378 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg_accessible-stuck.rs @@ -0,0 +1,9 @@ +#![feature(cfg_accessible)] + +#[cfg_accessible(Z)] //~ ERROR cannot determine whether the path is accessible or not +struct S; + +#[cfg_accessible(S)] //~ ERROR cannot determine whether the path is accessible or not +struct Z; + +fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg_accessible-stuck.stderr b/src/test/ui/conditional-compilation/cfg_accessible-stuck.stderr new file mode 100644 index 0000000000000..9641441a819b0 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg_accessible-stuck.stderr @@ -0,0 +1,14 @@ +error: cannot determine whether the path is accessible or not + --> $DIR/cfg_accessible-stuck.rs:6:1 + | +LL | #[cfg_accessible(S)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: cannot determine whether the path is accessible or not + --> $DIR/cfg_accessible-stuck.rs:3:1 + | +LL | #[cfg_accessible(Z)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/conditional-compilation/cfg_accessible-unstable.rs b/src/test/ui/conditional-compilation/cfg_accessible-unstable.rs new file mode 100644 index 0000000000000..e9247e67a2a26 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg_accessible-unstable.rs @@ -0,0 +1,2 @@ +#[cfg_accessible(std)] //~ ERROR use of unstable library feature 'cfg_accessible' +fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg_accessible-unstable.stderr b/src/test/ui/conditional-compilation/cfg_accessible-unstable.stderr new file mode 100644 index 0000000000000..2f55b9559c78f --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg_accessible-unstable.stderr @@ -0,0 +1,12 @@ +error[E0658]: use of unstable library feature 'cfg_accessible': `cfg_accessible` is not fully implemented + --> $DIR/cfg_accessible-unstable.rs:1:3 + | +LL | #[cfg_accessible(std)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #64797 for more information + = help: add `#![feature(cfg_accessible)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/conditional-compilation/cfg_accessible.rs b/src/test/ui/conditional-compilation/cfg_accessible.rs new file mode 100644 index 0000000000000..07b0be5b1ae26 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg_accessible.rs @@ -0,0 +1,43 @@ +#![feature(cfg_accessible)] + +mod m { + pub struct ExistingPublic; + struct ExistingPrivate; +} + +#[cfg_accessible(m::ExistingPublic)] +struct ExistingPublic; + +// FIXME: Not implemented yet. +#[cfg_accessible(m::ExistingPrivate)] //~ ERROR not sure whether the path is accessible or not +struct ExistingPrivate; + +// FIXME: Not implemented yet. +#[cfg_accessible(m::NonExistent)] //~ ERROR not sure whether the path is accessible or not +struct ExistingPrivate; + +#[cfg_accessible(n::AccessibleExpanded)] // OK, `cfg_accessible` can wait and retry. +struct AccessibleExpanded; + +macro_rules! generate_accessible_expanded { + () => { + mod n { + pub struct AccessibleExpanded; + } + }; +} + +generate_accessible_expanded!(); + +struct S { + field: u8, +} + +// FIXME: Not implemented yet. +#[cfg_accessible(S::field)] //~ ERROR not sure whether the path is accessible or not +struct Field; + +fn main() { + ExistingPublic; + AccessibleExpanded; +} diff --git a/src/test/ui/conditional-compilation/cfg_accessible.stderr b/src/test/ui/conditional-compilation/cfg_accessible.stderr new file mode 100644 index 0000000000000..167765cd66ee6 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg_accessible.stderr @@ -0,0 +1,38 @@ +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible.rs:12:18 + | +LL | #[cfg_accessible(m::ExistingPrivate)] + | ^^^^^^^^^^^^^^^^^^ + | +note: `cfg_accessible` is not fully implemented + --> $DIR/cfg_accessible.rs:12:18 + | +LL | #[cfg_accessible(m::ExistingPrivate)] + | ^^^^^^^^^^^^^^^^^^ + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible.rs:16:18 + | +LL | #[cfg_accessible(m::NonExistent)] + | ^^^^^^^^^^^^^^ + | +note: `cfg_accessible` is not fully implemented + --> $DIR/cfg_accessible.rs:16:18 + | +LL | #[cfg_accessible(m::NonExistent)] + | ^^^^^^^^^^^^^^ + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible.rs:37:18 + | +LL | #[cfg_accessible(S::field)] + | ^^^^^^^^ + | +note: `cfg_accessible` is not fully implemented + --> $DIR/cfg_accessible.rs:37:18 + | +LL | #[cfg_accessible(S::field)] + | ^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/conflicting-repr-hints.stderr b/src/test/ui/conflicting-repr-hints.stderr index 43b76bf649778..0b78532c73751 100644 --- a/src/test/ui/conflicting-repr-hints.stderr +++ b/src/test/ui/conflicting-repr-hints.stderr @@ -76,5 +76,5 @@ LL | | } error: aborting due to 10 previous errors -Some errors have detailed explanations: E0566, E0587. +Some errors have detailed explanations: E0566, E0587, E0634. For more information about an error, try `rustc --explain E0566`. diff --git a/src/test/ui/const-generics/argument_order.rs b/src/test/ui/const-generics/argument_order.rs new file mode 100644 index 0000000000000..3446600d0495f --- /dev/null +++ b/src/test/ui/const-generics/argument_order.rs @@ -0,0 +1,9 @@ +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +struct Bad { //~ ERROR type parameters must be declared prior + arr: [u8; { N }], + another: T, +} + +fn main() { } diff --git a/src/test/ui/const-generics/argument_order.stderr b/src/test/ui/const-generics/argument_order.stderr new file mode 100644 index 0000000000000..1e3b364eb6089 --- /dev/null +++ b/src/test/ui/const-generics/argument_order.stderr @@ -0,0 +1,16 @@ +error: type parameters must be declared prior to const parameters + --> $DIR/argument_order.rs:4:28 + | +LL | struct Bad { + | -----------------^- help: reorder the parameters: lifetimes, then types, then consts: `` + +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/argument_order.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/cannot-infer-const-args.stderr b/src/test/ui/const-generics/cannot-infer-const-args.stderr index 8379cbd4908e9..c1d7022d56b5f 100644 --- a/src/test/ui/const-generics/cannot-infer-const-args.stderr +++ b/src/test/ui/const-generics/cannot-infer-const-args.stderr @@ -10,7 +10,7 @@ error[E0282]: type annotations needed --> $DIR/cannot-infer-const-args.rs:9:5 | LL | foo(); - | ^^^ cannot infer type for fn item `fn() -> usize {foo::<_: usize>}` + | ^^^ cannot infer type for fn item `fn() -> usize {foo::<{_: usize}>}` error: aborting due to previous error diff --git a/src/test/ui/const-generics/const-generic-type_name.rs b/src/test/ui/const-generics/const-generic-type_name.rs index 28586426b44e9..469843d6aae1e 100644 --- a/src/test/ui/const-generics/const-generic-type_name.rs +++ b/src/test/ui/const-generics/const-generic-type_name.rs @@ -7,5 +7,5 @@ struct S; fn main() { - assert_eq!(std::any::type_name::>(), "const_generic_type_name::S<3usize>"); + assert_eq!(std::any::type_name::>(), "const_generic_type_name::S<3>"); } diff --git a/src/test/ui/const-generics/fn-const-param-infer.stderr b/src/test/ui/const-generics/fn-const-param-infer.stderr index 44eab8baa40a6..05d2dff8e9868 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.stderr +++ b/src/test/ui/const-generics/fn-const-param-infer.stderr @@ -10,12 +10,12 @@ error[E0308]: mismatched types --> $DIR/fn-const-param-infer.rs:16:31 | LL | let _: Checked = Checked::; - | ---------------- ^^^^^^^^^^^^^^^^^^ expected `not_one`, found `not_two` + | ---------------- ^^^^^^^^^^^^^^^^^^ expected `{not_one as fn(usize) -> bool}`, found `{not_two as fn(usize) -> bool}` | | | expected due to this | - = note: expected struct `Checked` - found struct `Checked` + = note: expected struct `Checked<{not_one as fn(usize) -> bool}>` + found struct `Checked<{not_two as fn(usize) -> bool}>` error[E0308]: mismatched types --> $DIR/fn-const-param-infer.rs:20:24 @@ -36,12 +36,12 @@ error[E0308]: mismatched types --> $DIR/fn-const-param-infer.rs:25:40 | LL | let _: Checked<{generic::}> = Checked::<{generic::}>; - | ------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `generic::`, found `generic::` + | ------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{generic:: as fn(usize) -> bool}`, found `{generic:: as fn(usize) -> bool}` | | | expected due to this | - = note: expected struct `Checked>` - found struct `Checked>` + = note: expected struct `Checked<{generic:: as fn(usize) -> bool}>` + found struct `Checked<{generic:: as fn(usize) -> bool}>` error: aborting due to 4 previous errors diff --git a/src/test/ui/const-generics/issues/issue-61336-1.rs b/src/test/ui/const-generics/issues/issue-61336-1.rs index 5b5e431bf2ff6..165d3e1c2e601 100644 --- a/src/test/ui/const-generics/issues/issue-61336-1.rs +++ b/src/test/ui/const-generics/issues/issue-61336-1.rs @@ -1,9 +1,10 @@ #![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +// build-pass + fn f(x: T) -> [T; N] { [x; N] - //~^ ERROR array lengths can't depend on generic parameters } fn main() { diff --git a/src/test/ui/const-generics/issues/issue-61336-1.stderr b/src/test/ui/const-generics/issues/issue-61336-1.stderr index 949fa896d8780..d48d8ff689462 100644 --- a/src/test/ui/const-generics/issues/issue-61336-1.stderr +++ b/src/test/ui/const-generics/issues/issue-61336-1.stderr @@ -6,11 +6,3 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default -error: array lengths can't depend on generic parameters - --> $DIR/issue-61336-1.rs:5:9 - | -LL | [x; N] - | ^ - -error: aborting due to previous error - diff --git a/src/test/ui/const-generics/issues/issue-61336-2.rs b/src/test/ui/const-generics/issues/issue-61336-2.rs index 7bb36f41b8f9d..c5bf6b6ce94a8 100644 --- a/src/test/ui/const-generics/issues/issue-61336-2.rs +++ b/src/test/ui/const-generics/issues/issue-61336-2.rs @@ -2,13 +2,12 @@ //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash fn f(x: T) -> [T; N] { - [x; {N}] - //~^ ERROR array lengths can't depend on generic parameters + [x; { N }] } fn g(x: T) -> [T; N] { - [x; {N}] - //~^ ERROR array lengths can't depend on generic parameters + [x; { N }] + //~^ ERROR the trait bound `T: std::marker::Copy` is not satisfied } fn main() { diff --git a/src/test/ui/const-generics/issues/issue-61336-2.stderr b/src/test/ui/const-generics/issues/issue-61336-2.stderr index 63f86c81b1e7f..9ced427b93c65 100644 --- a/src/test/ui/const-generics/issues/issue-61336-2.stderr +++ b/src/test/ui/const-generics/issues/issue-61336-2.stderr @@ -6,17 +6,19 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default -error: array lengths can't depend on generic parameters - --> $DIR/issue-61336-2.rs:5:9 +error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied + --> $DIR/issue-61336-2.rs:9:5 | -LL | [x; {N}] - | ^^^ - -error: array lengths can't depend on generic parameters - --> $DIR/issue-61336-2.rs:10:9 +LL | [x; { N }] + | ^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` + | +help: consider restricting this type parameter with `T: std::marker::Copy` + --> $DIR/issue-61336-2.rs:8:6 | -LL | [x; {N}] - | ^^^ +LL | fn g(x: T) -> [T; N] { + | ^ + = note: the `Copy` trait is required because the repeated element will be copied -error: aborting due to 2 previous errors +error: aborting due to previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/issues/issue-61336.rs b/src/test/ui/const-generics/issues/issue-61336.rs index edc012cbb3d13..7e84e62d8be42 100644 --- a/src/test/ui/const-generics/issues/issue-61336.rs +++ b/src/test/ui/const-generics/issues/issue-61336.rs @@ -3,12 +3,11 @@ fn f(x: T) -> [T; N] { [x; N] - //~^ ERROR array lengths can't depend on generic parameters } fn g(x: T) -> [T; N] { [x; N] - //~^ ERROR array lengths can't depend on generic parameters + //~^ ERROR the trait bound `T: std::marker::Copy` is not satisfied } fn main() { diff --git a/src/test/ui/const-generics/issues/issue-61336.stderr b/src/test/ui/const-generics/issues/issue-61336.stderr index f96e8e02d4ec0..ace7955fbdd77 100644 --- a/src/test/ui/const-generics/issues/issue-61336.stderr +++ b/src/test/ui/const-generics/issues/issue-61336.stderr @@ -6,17 +6,19 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default -error: array lengths can't depend on generic parameters - --> $DIR/issue-61336.rs:5:9 +error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied + --> $DIR/issue-61336.rs:9:5 | LL | [x; N] - | ^ - -error: array lengths can't depend on generic parameters - --> $DIR/issue-61336.rs:10:9 + | ^^^^^^ the trait `std::marker::Copy` is not implemented for `T` | -LL | [x; N] - | ^ +help: consider restricting this type parameter with `T: std::marker::Copy` + --> $DIR/issue-61336.rs:8:6 + | +LL | fn g(x: T) -> [T; N] { + | ^ + = note: the `Copy` trait is required because the repeated element will be copied -error: aborting due to 2 previous errors +error: aborting due to previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.stderr b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.stderr index 20347ac4b7dac..72f0b333c5a35 100644 --- a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.stderr +++ b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.stderr @@ -10,7 +10,7 @@ warning: unused variable: `foo` --> $DIR/issue-62187-encountered-polymorphic-const.rs:15:9 | LL | let foo = <[u8; 2]>::BIT_LEN; - | ^^^ help: consider prefixing with an underscore: `_foo` + | ^^^ help: if this is intentional, prefix it with an underscore: `_foo` | = note: `#[warn(unused_variables)]` on by default diff --git a/src/test/ui/const-generics/issues/issue-62456.rs b/src/test/ui/const-generics/issues/issue-62456.rs index c5e6fe9104bc9..14b1190df0f99 100644 --- a/src/test/ui/const-generics/issues/issue-62456.rs +++ b/src/test/ui/const-generics/issues/issue-62456.rs @@ -1,9 +1,10 @@ #![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +// build-pass + fn foo() { let _ = [0u64; N + 1]; - //~^ ERROR array lengths can't depend on generic parameters } fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-62456.stderr b/src/test/ui/const-generics/issues/issue-62456.stderr index 9cdccf8407c9b..47dd3c01fa9e0 100644 --- a/src/test/ui/const-generics/issues/issue-62456.stderr +++ b/src/test/ui/const-generics/issues/issue-62456.stderr @@ -6,11 +6,3 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default -error: array lengths can't depend on generic parameters - --> $DIR/issue-62456.rs:5:20 - | -LL | let _ = [0u64; N + 1]; - | ^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/const-generics/issues/issue-62504.rs b/src/test/ui/const-generics/issues/issue-62504.rs new file mode 100644 index 0000000000000..cd3cfaac3b95b --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-62504.rs @@ -0,0 +1,25 @@ +// Regression test for #62504 + +#![feature(const_generics)] +#![allow(incomplete_features)] + +trait HasSize { + const SIZE: usize; +} + +impl HasSize for ArrayHolder<{ X }> { + const SIZE: usize = X; +} + +struct ArrayHolder([u32; X]); + +impl ArrayHolder<{ X }> { + pub const fn new() -> Self { + ArrayHolder([0; Self::SIZE]) + //~^ ERROR: mismatched types + } +} + +fn main() { + let mut array = ArrayHolder::new(); +} diff --git a/src/test/ui/const-generics/issues/issue-62504.stderr b/src/test/ui/const-generics/issues/issue-62504.stderr new file mode 100644 index 0000000000000..4482389bbdd49 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-62504.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/issue-62504.rs:18:21 + | +LL | ArrayHolder([0; Self::SIZE]) + | ^^^^^^^^^^^^^^^ expected `X`, found `Self::SIZE` + | + = note: expected array `[u32; _]` + found array `[u32; _]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/issues/issue-66906.rs b/src/test/ui/const-generics/issues/issue-66906.rs new file mode 100644 index 0000000000000..461fe837dac44 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-66906.rs @@ -0,0 +1,12 @@ +// check-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +pub struct Tuple; + +pub trait Trait { + type Input: From<>::Input>; +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-66906.stderr b/src/test/ui/const-generics/issues/issue-66906.stderr new file mode 100644 index 0000000000000..f8710b67b687e --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-66906.stderr @@ -0,0 +1,8 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/issue-66906.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + diff --git a/src/test/ui/const-generics/issues/issue-67739.rs b/src/test/ui/const-generics/issues/issue-67739.rs new file mode 100644 index 0000000000000..3d657b0947b18 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-67739.rs @@ -0,0 +1,19 @@ +// Regression test for #67739 + +// check-pass + +#![allow(incomplete_features)] +#![feature(const_generics)] + +use std::mem; + +pub trait Trait { + type Associated: Sized; + + fn associated_size(&self) -> usize { + [0u8; mem::size_of::()]; + 0 + } +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-70125-1.rs b/src/test/ui/const-generics/issues/issue-70125-1.rs new file mode 100644 index 0000000000000..8b933c078ff26 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-70125-1.rs @@ -0,0 +1,19 @@ +// run-pass +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +const L: usize = 4; + +pub trait Print { + fn print(&self) -> usize { + N + } +} + +pub struct Printer; +impl Print for Printer {} + +fn main() { + let p = Printer; + assert_eq!(p.print(), 4); +} diff --git a/src/test/ui/const-generics/issues/issue-70125-1.stderr b/src/test/ui/const-generics/issues/issue-70125-1.stderr new file mode 100644 index 0000000000000..f28f58cf5ce4d --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-70125-1.stderr @@ -0,0 +1,8 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/issue-70125-1.rs:2:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + diff --git a/src/test/ui/const-generics/issues/issue-70125-2.rs b/src/test/ui/const-generics/issues/issue-70125-2.rs new file mode 100644 index 0000000000000..ea7a68c2f93d9 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-70125-2.rs @@ -0,0 +1,16 @@ +// run-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +fn main() { + <()>::foo(); +} + +trait Foo { + fn foo() -> usize { + X + } +} + +impl Foo<{3}> for () {} diff --git a/src/test/ui/const-generics/issues/issue-70125-2.stderr b/src/test/ui/const-generics/issues/issue-70125-2.stderr new file mode 100644 index 0000000000000..664aa7ba45161 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-70125-2.stderr @@ -0,0 +1,8 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/issue-70125-2.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + diff --git a/src/test/ui/const-generics/issues/issue-70167.rs b/src/test/ui/const-generics/issues/issue-70167.rs new file mode 100644 index 0000000000000..58fac8e05114a --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-70167.rs @@ -0,0 +1,10 @@ +// check-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +pub trait Trait: From<>::Item> { + type Item; +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-70167.stderr b/src/test/ui/const-generics/issues/issue-70167.stderr new file mode 100644 index 0000000000000..4ba3c204097dc --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-70167.stderr @@ -0,0 +1,8 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/issue-70167.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + diff --git a/src/test/ui/const-generics/issues/issue70273-assoc-fn.rs b/src/test/ui/const-generics/issues/issue70273-assoc-fn.rs new file mode 100644 index 0000000000000..a192ddea9c6ab --- /dev/null +++ b/src/test/ui/const-generics/issues/issue70273-assoc-fn.rs @@ -0,0 +1,17 @@ +// check-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +trait T { + fn f(); +} +struct S; + +impl T<0usize> for S { + fn f() {} +} + +fn main() { + let _err = >::f(); +} diff --git a/src/test/ui/const-generics/issues/issue70273-assoc-fn.stderr b/src/test/ui/const-generics/issues/issue70273-assoc-fn.stderr new file mode 100644 index 0000000000000..64007ade0f2ed --- /dev/null +++ b/src/test/ui/const-generics/issues/issue70273-assoc-fn.stderr @@ -0,0 +1,8 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/issue70273-assoc-fn.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + diff --git a/src/test/ui/const-generics/raw-ptr-const-param.rs b/src/test/ui/const-generics/raw-ptr-const-param.rs index f69c37fbb8f3d..f0349f469626f 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.rs +++ b/src/test/ui/const-generics/raw-ptr-const-param.rs @@ -4,6 +4,6 @@ struct Const; fn main() { - let _: Const<{15 as *const _}> = Const::<{10 as *const _}>; //~ mismatched types - let _: Const<{10 as *const _}> = Const::<{10 as *const _}>; + let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>; //~ mismatched types + let _: Const<{ 10 as *const _ }> = Const::<{ 10 as *const _ }>; } diff --git a/src/test/ui/const-generics/raw-ptr-const-param.stderr b/src/test/ui/const-generics/raw-ptr-const-param.stderr index 9cd39b61dc936..d9794f60a19ce 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.stderr +++ b/src/test/ui/const-generics/raw-ptr-const-param.stderr @@ -7,15 +7,15 @@ LL | #![feature(const_generics, const_compare_raw_pointers)] = note: `#[warn(incomplete_features)]` on by default error[E0308]: mismatched types - --> $DIR/raw-ptr-const-param.rs:7:38 + --> $DIR/raw-ptr-const-param.rs:7:40 | -LL | let _: Const<{15 as *const _}> = Const::<{10 as *const _}>; - | ----------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{pointer}`, found `{pointer}` +LL | let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>; + | ------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{0xf as *const u32}`, found `{0xa as *const u32}` | | | expected due to this | - = note: expected struct `Const<{pointer}>` - found struct `Const<{pointer}>` + = note: expected struct `Const<{0xf as *const u32}>` + found struct `Const<{0xa as *const u32}>` error: aborting due to previous error diff --git a/src/test/ui/const-generics/std/const-generics-range.rs b/src/test/ui/const-generics/std/const-generics-range.rs new file mode 100644 index 0000000000000..6d56fe0d7b8e3 --- /dev/null +++ b/src/test/ui/const-generics/std/const-generics-range.rs @@ -0,0 +1,30 @@ +// check-pass +#![allow(incomplete_features)] +#![feature(const_generics)] + +// `Range` should be usable within const generics: +struct _Range>; +const RANGE : _Range<{ 0 .. 1000 }> = _Range; + +// `RangeFrom` should be usable within const generics: +struct _RangeFrom>; +const RANGE_FROM : _RangeFrom<{ 0 .. }> = _RangeFrom; + +// `RangeFull` should be usable within const generics: +struct _RangeFull; +const RANGE_FULL : _RangeFull<{ .. }> = _RangeFull; + +// Regression test for #70155 +// `RangeInclusive` should be usable within const generics: +struct _RangeInclusive>; +const RANGE_INCLUSIVE : _RangeInclusive<{ 0 ..= 999 }> = _RangeInclusive; + +// `RangeTo` should be usable within const generics: +struct _RangeTo>; +const RANGE_TO : _RangeTo<{ .. 1000 }> = _RangeTo; + +// `RangeToInclusive` should be usable within const generics: +struct _RangeToInclusive>; +const RANGE_TO_INCLUSIVE : _RangeToInclusive<{ ..= 999 }> = _RangeToInclusive; + +pub fn main() {} diff --git a/src/test/ui/const-generics/type_of_anon_const.rs b/src/test/ui/const-generics/type_of_anon_const.rs new file mode 100644 index 0000000000000..776084b77a577 --- /dev/null +++ b/src/test/ui/const-generics/type_of_anon_const.rs @@ -0,0 +1,21 @@ +// run-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +trait T { + fn l() -> usize; + fn r() -> bool; +} + +struct S; + +impl T for S { + fn l() -> usize { N } + fn r() -> bool { M } +} + +fn main() { + assert_eq!(>::l::(), 123); + assert!(>::r::()); +} diff --git a/src/test/ui/const-generics/type_of_anon_const.stderr b/src/test/ui/const-generics/type_of_anon_const.stderr new file mode 100644 index 0000000000000..495d34ce09b81 --- /dev/null +++ b/src/test/ui/const-generics/type_of_anon_const.stderr @@ -0,0 +1,8 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/type_of_anon_const.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + diff --git a/src/test/ui/consts/cast-discriminant-zst-enum.rs b/src/test/ui/consts/cast-discriminant-zst-enum.rs new file mode 100644 index 0000000000000..a77258120111e --- /dev/null +++ b/src/test/ui/consts/cast-discriminant-zst-enum.rs @@ -0,0 +1,47 @@ +// run-pass +// Test a ZST enum whose dicriminant is ~0i128. This caused an ICE when casting to a i32. + +#[derive(Copy, Clone)] +enum Nums { + NegOne = -1, +} + +const NEG_ONE_I8: i8 = Nums::NegOne as i8; +const NEG_ONE_I16: i16 = Nums::NegOne as i16; +const NEG_ONE_I32: i32 = Nums::NegOne as i32; +const NEG_ONE_I64: i64 = Nums::NegOne as i64; +const NEG_ONE_I128: i128 = Nums::NegOne as i128; + +#[inline(never)] +fn identity(t: T) -> T { t } + +fn test_as_arg(n: Nums) { + assert_eq!(-1i8, n as i8); + assert_eq!(-1i16, n as i16); + assert_eq!(-1i32, n as i32); + assert_eq!(-1i64, n as i64); + assert_eq!(-1i128, n as i128); +} + +fn main() { + let kind = Nums::NegOne; + assert_eq!(-1i8, kind as i8); + assert_eq!(-1i16, kind as i16); + assert_eq!(-1i32, kind as i32); + assert_eq!(-1i64, kind as i64); + assert_eq!(-1i128, kind as i128); + + assert_eq!(-1i8, identity(kind) as i8); + assert_eq!(-1i16, identity(kind) as i16); + assert_eq!(-1i32, identity(kind) as i32); + assert_eq!(-1i64, identity(kind) as i64); + assert_eq!(-1i128, identity(kind) as i128); + + test_as_arg(Nums::NegOne); + + assert_eq!(-1i8, NEG_ONE_I8); + assert_eq!(-1i16, NEG_ONE_I16); + assert_eq!(-1i32, NEG_ONE_I32); + assert_eq!(-1i64, NEG_ONE_I64); + assert_eq!(-1i128, NEG_ONE_I128); +} diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr index cb4d35b9a1809..bf5e476d80045 100644 --- a/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr +++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr @@ -2,7 +2,7 @@ error[E0080]: could not evaluate static initializer --> $DIR/assign-to-static-within-other-static.rs:10:5 | LL | FOO = 5; - | ^^^^^^^ tried to modify a static's initial value from another static's initializer + | ^^^^^^^ modifying a static's initial value from another static's initializer error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-3.rs b/src/test/ui/consts/const-eval/const-eval-overflow-3.rs index 6fd8e9cbc806b..3ae55ebdbaf35 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow-3.rs +++ b/src/test/ui/consts/const-eval/const-eval-overflow-3.rs @@ -19,6 +19,7 @@ const A_I8_I : [u32; (i8::MAX as usize) + 1] = [0; (i8::MAX + 1) as usize]; //~^ ERROR evaluation of constant value failed +//~| ERROR mismatched types fn main() { foo(&A_I8_I[..]); diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-3.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-3.stderr index 2c5b4607aa4d3..94b7c12fc1a8b 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow-3.stderr +++ b/src/test/ui/consts/const-eval/const-eval-overflow-3.stderr @@ -4,6 +4,16 @@ error[E0080]: evaluation of constant value failed LL | = [0; (i8::MAX + 1) as usize]; | ^^^^^^^^^^^^^ attempt to add with overflow -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/const-eval-overflow-3.rs:20:7 + | +LL | = [0; (i8::MAX + 1) as usize]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `128usize`, found `(i8::MAX + 1) as usize` + | + = note: expected array `[u32; 128]` + found array `[u32; _]` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0080`. +Some errors have detailed explanations: E0080, E0308. +For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-3b.rs b/src/test/ui/consts/const-eval/const-eval-overflow-3b.rs index db6f17a671aea..e7b88e00febaa 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow-3b.rs +++ b/src/test/ui/consts/const-eval/const-eval-overflow-3b.rs @@ -18,6 +18,7 @@ const A_I8_I = [0; (i8::MAX + 1u8) as usize]; //~^ ERROR mismatched types //~| ERROR cannot add `u8` to `i8` +//~| ERROR mismatched types fn main() { foo(&A_I8_I[..]); diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr index 3da34fe9af7ec..aebe4feef8d5f 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr +++ b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr @@ -12,7 +12,16 @@ LL | = [0; (i8::MAX + 1u8) as usize]; | = help: the trait `std::ops::Add` is not implemented for `i8` -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/const-eval-overflow-3b.rs:18:7 + | +LL | = [0; (i8::MAX + 1u8) as usize]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `128usize`, found `(i8::MAX + 1u8) as usize` + | + = note: expected array `[u32; 128]` + found array `[u32; _]` + +error: aborting due to 3 previous errors Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr index e0df787f80a44..305f259eac22d 100644 --- a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr +++ b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr @@ -12,7 +12,7 @@ error: any use of this value will cause an error LL | const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_8 }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default @@ -22,7 +22,7 @@ error: any use of this value will cause an error LL | const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uint_16 }; | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:34:45 @@ -30,7 +30,7 @@ error: any use of this value will cause an error LL | const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uint_32 }; | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:37:5 @@ -54,7 +54,7 @@ error: any use of this value will cause an error LL | const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:46:45 @@ -62,7 +62,7 @@ error: any use of this value will cause an error LL | const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int_16 }; | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:49:45 @@ -70,7 +70,7 @@ error: any use of this value will cause an error LL | const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int_32 }; | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:52:5 @@ -94,7 +94,7 @@ error: any use of this value will cause an error LL | const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.float_32 }; | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:61:5 @@ -110,7 +110,7 @@ error: any use of this value will cause an error LL | const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.truthy_falsey }; | ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:67:47 @@ -118,7 +118,7 @@ error: any use of this value will cause an error LL | const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.character }; | ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:70:39 @@ -126,7 +126,7 @@ error: any use of this value will cause an error LL | const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:73:41 @@ -134,7 +134,7 @@ error: any use of this value will cause an error LL | const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:76:41 @@ -142,7 +142,7 @@ error: any use of this value will cause an error LL | const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:79:5 @@ -158,7 +158,7 @@ error: any use of this value will cause an error LL | const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_128 }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:85:39 @@ -166,7 +166,7 @@ error: any use of this value will cause an error LL | const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:88:41 @@ -174,7 +174,7 @@ error: any use of this value will cause an error LL | const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:91:41 @@ -182,7 +182,7 @@ error: any use of this value will cause an error LL | const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:94:5 @@ -198,7 +198,7 @@ error: any use of this value will cause an error LL | const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:100:41 @@ -206,7 +206,7 @@ error: any use of this value will cause an error LL | const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:103:5 @@ -222,7 +222,7 @@ error: any use of this value will cause an error LL | const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_falsey }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:109:43 @@ -230,7 +230,7 @@ error: any use of this value will cause an error LL | const STR_CHAR_UNION: char = unsafe { Nonsense { stringy: "3" }.character }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: aborting due to 29 previous errors diff --git a/src/test/ui/consts/const-eval/const_panic_libcore_main.rs b/src/test/ui/consts/const-eval/const_panic_libcore_main.rs index 9afcdf77610f2..6b86feb5921a1 100644 --- a/src/test/ui/consts/const-eval/const_panic_libcore_main.rs +++ b/src/test/ui/consts/const-eval/const_panic_libcore_main.rs @@ -17,8 +17,6 @@ const X: () = unimplemented!(); #[lang = "eh_personality"] fn eh() {} -#[lang = "eh_unwind_resume"] -fn eh_unwind_resume() {} #[panic_handler] fn panic(_info: &PanicInfo) -> ! { diff --git a/src/test/ui/consts/const-eval/const_prop_errors.rs b/src/test/ui/consts/const-eval/const_prop_errors.rs index 48cfea82bd65e..f9a36d37943f3 100644 --- a/src/test/ui/consts/const-eval/const_prop_errors.rs +++ b/src/test/ui/consts/const-eval/const_prop_errors.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass pub trait Foo { fn foo(self) -> u32; diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr index 2cba833a74896..cc40728e6b574 100644 --- a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr @@ -30,7 +30,7 @@ error: any use of this value will cause an error LL | const Z2: i32 = unsafe { *(42 as *const i32) }; | -------------------------^^^^^^^^^^^^^^^^^^^--- | | - | a memory access tried to interpret some bytes as a pointer + | unable to turn bytes into a pointer error: any use of this value will cause an error --> $DIR/const_raw_ptr_ops.rs:17:26 @@ -38,7 +38,7 @@ error: any use of this value will cause an error LL | const Z3: i32 = unsafe { *(44 as *const i32) }; | -------------------------^^^^^^^^^^^^^^^^^^^--- | | - | a memory access tried to interpret some bytes as a pointer + | unable to turn bytes into a pointer error: aborting due to 5 previous errors diff --git a/src/test/ui/consts/const-eval/const_signed_pat.rs b/src/test/ui/consts/const-eval/const_signed_pat.rs index d209e60448687..c61239bb677e8 100644 --- a/src/test/ui/consts/const-eval/const_signed_pat.rs +++ b/src/test/ui/consts/const-eval/const_signed_pat.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass fn main() { const MIN: i8 = -5; diff --git a/src/test/ui/consts/const-eval/double_check.rs b/src/test/ui/consts/const-eval/double_check.rs index ff2fff7fb790e..f156d259abb20 100644 --- a/src/test/ui/consts/const-eval/double_check.rs +++ b/src/test/ui/consts/const-eval/double_check.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass enum Foo { A = 5, diff --git a/src/test/ui/consts/const-eval/double_promotion.rs b/src/test/ui/consts/const-eval/double_promotion.rs index a9a3f071bf89f..48f4426d9cff4 100644 --- a/src/test/ui/consts/const-eval/double_promotion.rs +++ b/src/test/ui/consts/const-eval/double_promotion.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![feature(const_fn, rustc_attrs)] diff --git a/src/test/ui/consts/const-eval/duration_conversion.rs b/src/test/ui/consts/const-eval/duration_conversion.rs index 029d4e5e3732e..87b12937dd4f2 100644 --- a/src/test/ui/consts/const-eval/duration_conversion.rs +++ b/src/test/ui/consts/const-eval/duration_conversion.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass use std::time::Duration; diff --git a/src/test/ui/consts/const-eval/extern_fat_pointer.rs b/src/test/ui/consts/const-eval/extern_fat_pointer.rs index e2b3bc83c3f01..f210d1a0a90c5 100644 --- a/src/test/ui/consts/const-eval/extern_fat_pointer.rs +++ b/src/test/ui/consts/const-eval/extern_fat_pointer.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![feature(extern_types)] diff --git a/src/test/ui/consts/const-eval/ice-generic-assoc-const.rs b/src/test/ui/consts/const-eval/ice-generic-assoc-const.rs index ce0e11f29f442..4444cdfcda9c7 100644 --- a/src/test/ui/consts/const-eval/ice-generic-assoc-const.rs +++ b/src/test/ui/consts/const-eval/ice-generic-assoc-const.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass pub trait Nullable { const NULL: Self; diff --git a/src/test/ui/consts/const-eval/ice-packed.rs b/src/test/ui/consts/const-eval/ice-packed.rs index 250bf954e9ac2..4758a5a9d561c 100644 --- a/src/test/ui/consts/const-eval/ice-packed.rs +++ b/src/test/ui/consts/const-eval/ice-packed.rs @@ -1,4 +1,7 @@ -// build-pass (FIXME(62277): could be check-pass?) +// Regression test for #50356: Compiler panic when using repr(packed) +// associated constant in a match arm + +// check-pass #[derive(Copy, Clone, PartialEq, Eq)] #[repr(packed)] pub struct Num(u64); diff --git a/src/test/ui/consts/const-eval/infinite_loop.rs b/src/test/ui/consts/const-eval/infinite_loop.rs index af5e7658d48d2..c8de259354eac 100644 --- a/src/test/ui/consts/const-eval/infinite_loop.rs +++ b/src/test/ui/consts/const-eval/infinite_loop.rs @@ -2,7 +2,6 @@ fn main() { // Tests the Collatz conjecture with an incorrect base case (0 instead of 1). // The value of `n` will loop indefinitely (4 - 2 - 1 - 4). let _ = [(); { - //~^ WARNING Constant evaluating a complex constant, this might take some time let mut n = 113383; // #20 in https://oeis.org/A006884 while n != 0 { //~^ ERROR `while` is not allowed in a `const` diff --git a/src/test/ui/consts/const-eval/infinite_loop.stderr b/src/test/ui/consts/const-eval/infinite_loop.stderr index e04c31cf39782..ebdb73c446791 100644 --- a/src/test/ui/consts/const-eval/infinite_loop.stderr +++ b/src/test/ui/consts/const-eval/infinite_loop.stderr @@ -1,5 +1,5 @@ error[E0658]: `while` is not allowed in a `const` - --> $DIR/infinite_loop.rs:7:9 + --> $DIR/infinite_loop.rs:6:9 | LL | / while n != 0 { LL | | @@ -14,7 +14,7 @@ LL | | } = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `if` is not allowed in a `const` - --> $DIR/infinite_loop.rs:9:17 + --> $DIR/infinite_loop.rs:8:17 | LL | n = if n % 2 == 0 { n/2 } else { 3*n + 1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,24 +22,11 @@ LL | n = if n % 2 == 0 { n/2 } else { 3*n + 1 }; = note: see issue #49146 for more information = help: add `#![feature(const_if_match)]` to the crate attributes to enable -warning: Constant evaluating a complex constant, this might take some time - --> $DIR/infinite_loop.rs:4:18 - | -LL | let _ = [(); { - | __________________^ -LL | | -LL | | let mut n = 113383; // #20 in https://oeis.org/A006884 -LL | | while n != 0 { -... | -LL | | n -LL | | }]; - | |_____^ - error[E0080]: evaluation of constant value failed - --> $DIR/infinite_loop.rs:9:20 + --> $DIR/infinite_loop.rs:8:20 | LL | n = if n % 2 == 0 { n/2 } else { 3*n + 1 }; - | ^^^^^^^^^^ duplicate interpreter state observed here, const evaluation will never terminate + | ^^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`) error: aborting due to 3 previous errors diff --git a/src/test/ui/consts/const-eval/issue-47971.rs b/src/test/ui/consts/const-eval/issue-47971.rs index 9de150bd0528d..b98e76031d4f3 100644 --- a/src/test/ui/consts/const-eval/issue-47971.rs +++ b/src/test/ui/consts/const-eval/issue-47971.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass struct S(pub &'static u32, pub u32); diff --git a/src/test/ui/consts/const-eval/issue-49296.stderr b/src/test/ui/consts/const-eval/issue-49296.stderr index 48809e0ae649c..798f130a4baf6 100644 --- a/src/test/ui/consts/const-eval/issue-49296.stderr +++ b/src/test/ui/consts/const-eval/issue-49296.stderr @@ -4,7 +4,7 @@ error: any use of this value will cause an error LL | const X: u64 = *wat(42); | ---------------^^^^^^^^- | | - | dangling pointer was dereferenced + | pointer to alloc2 was dereferenced after this allocation got freed | = note: `#[deny(const_err)]` on by default diff --git a/src/test/ui/consts/const-eval/issue-50706.rs b/src/test/ui/consts/const-eval/issue-50706.rs index bf69bc28da41a..a13c27f2e7802 100644 --- a/src/test/ui/consts/const-eval/issue-50706.rs +++ b/src/test/ui/consts/const-eval/issue-50706.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass pub struct Stats; diff --git a/src/test/ui/consts/const-eval/issue-51300.rs b/src/test/ui/consts/const-eval/issue-51300.rs index 4753bf0f7b174..8e68e8c911785 100644 --- a/src/test/ui/consts/const-eval/issue-51300.rs +++ b/src/test/ui/consts/const-eval/issue-51300.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass // https://github.com/rust-lang/rust/issues/51300 #[derive(PartialEq, Eq, Clone, Copy)] diff --git a/src/test/ui/consts/const-eval/issue-52442.rs b/src/test/ui/consts/const-eval/issue-52442.rs index d820c70516124..df4cc8e302677 100644 --- a/src/test/ui/consts/const-eval/issue-52442.rs +++ b/src/test/ui/consts/const-eval/issue-52442.rs @@ -1,6 +1,4 @@ fn main() { [(); { &loop { break } as *const _ as usize } ]; - //~^ ERROR casting pointers to integers in constants is unstable - //~| ERROR `loop` is not allowed in a `const` - //~| ERROR evaluation of constant value failed + //~^ ERROR `loop` is not allowed in a `const` } diff --git a/src/test/ui/consts/const-eval/issue-52442.stderr b/src/test/ui/consts/const-eval/issue-52442.stderr index eda2dbf0b6b15..0ea974f1f6666 100644 --- a/src/test/ui/consts/const-eval/issue-52442.stderr +++ b/src/test/ui/consts/const-eval/issue-52442.stderr @@ -7,22 +7,6 @@ LL | [(); { &loop { break } as *const _ as usize } ]; = note: see issue #52000 for more information = help: add `#![feature(const_loop)]` to the crate attributes to enable -error[E0658]: casting pointers to integers in constants is unstable - --> $DIR/issue-52442.rs:2:13 - | -LL | [(); { &loop { break } as *const _ as usize } ]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #51910 for more information - = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable - -error[E0080]: evaluation of constant value failed - --> $DIR/issue-52442.rs:2:13 - | -LL | [(); { &loop { break } as *const _ as usize } ]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "pointer-to-integer cast" needs an rfc before being allowed inside constants - -error: aborting due to 3 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0080, E0658. -For more information about an error, try `rustc --explain E0080`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/const-eval/issue-52475.rs b/src/test/ui/consts/const-eval/issue-52475.rs index 3788167f44902..869f0b981af7d 100644 --- a/src/test/ui/consts/const-eval/issue-52475.rs +++ b/src/test/ui/consts/const-eval/issue-52475.rs @@ -1,6 +1,5 @@ fn main() { let _ = [(); { - //~^ WARNING Constant evaluating a complex constant, this might take some time let mut x = &0; let mut n = 0; while n < 5 { diff --git a/src/test/ui/consts/const-eval/issue-52475.stderr b/src/test/ui/consts/const-eval/issue-52475.stderr index 31d87925b2cfc..b069537ead963 100644 --- a/src/test/ui/consts/const-eval/issue-52475.stderr +++ b/src/test/ui/consts/const-eval/issue-52475.stderr @@ -1,5 +1,5 @@ error[E0658]: `while` is not allowed in a `const` - --> $DIR/issue-52475.rs:6:9 + --> $DIR/issue-52475.rs:5:9 | LL | / while n < 5 { LL | | @@ -12,24 +12,11 @@ LL | | } = help: add `#![feature(const_loop)]` to the crate attributes to enable = help: add `#![feature(const_if_match)]` to the crate attributes to enable -warning: Constant evaluating a complex constant, this might take some time - --> $DIR/issue-52475.rs:2:18 - | -LL | let _ = [(); { - | __________________^ -LL | | -LL | | let mut x = &0; -LL | | let mut n = 0; -... | -LL | | 0 -LL | | }]; - | |_____^ - error[E0080]: evaluation of constant value failed - --> $DIR/issue-52475.rs:8:17 + --> $DIR/issue-52475.rs:7:17 | LL | n = (n + 1) % 5; - | ^^^^^^^^^^^ duplicate interpreter state observed here, const evaluation will never terminate + | ^^^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`) error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-eval/issue-53157.rs b/src/test/ui/consts/const-eval/issue-53157.rs index ac0940b33e47a..850338625bc01 100644 --- a/src/test/ui/consts/const-eval/issue-53157.rs +++ b/src/test/ui/consts/const-eval/issue-53157.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass macro_rules! m { () => {{ diff --git a/src/test/ui/consts/const-eval/issue-53401.rs b/src/test/ui/consts/const-eval/issue-53401.rs index d300e0b5125da..31c946c3cb761 100644 --- a/src/test/ui/consts/const-eval/issue-53401.rs +++ b/src/test/ui/consts/const-eval/issue-53401.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass pub const STATIC_TRAIT: &dyn Test = &(); diff --git a/src/test/ui/consts/const-eval/issue-55541.rs b/src/test/ui/consts/const-eval/issue-55541.rs index d04570c67ff2e..4c9e10d9cbe16 100644 --- a/src/test/ui/consts/const-eval/issue-55541.rs +++ b/src/test/ui/consts/const-eval/issue-55541.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass // Test that we can handle newtypes wrapping extern types diff --git a/src/test/ui/consts/const-eval/match-test-ptr-null.rs b/src/test/ui/consts/const-eval/match-test-ptr-null.rs index 80494d1662987..5cfe36f57e647 100644 --- a/src/test/ui/consts/const-eval/match-test-ptr-null.rs +++ b/src/test/ui/consts/const-eval/match-test-ptr-null.rs @@ -2,7 +2,7 @@ fn main() { // Make sure match uses the usual pointer comparison code path -- i.e., it should complain // that pointer comparison is disallowed, not that parts of a pointer are accessed as raw // bytes. - let _: [u8; 0] = [4; { + let _: [u8; 0] = [4; { //~ ERROR mismatched types match &1 as *const i32 as usize { //~^ ERROR casting pointers to integers in constants //~| ERROR `match` is not allowed in a `const` diff --git a/src/test/ui/consts/const-eval/match-test-ptr-null.stderr b/src/test/ui/consts/const-eval/match-test-ptr-null.stderr index b47f6d5f845fe..7c4da5e7d86ca 100644 --- a/src/test/ui/consts/const-eval/match-test-ptr-null.stderr +++ b/src/test/ui/consts/const-eval/match-test-ptr-null.stderr @@ -28,7 +28,30 @@ error[E0080]: evaluation of constant value failed LL | match &1 as *const i32 as usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^ "pointer-to-integer cast" needs an rfc before being allowed inside constants -error: aborting due to 3 previous errors +error[E0308]: mismatched types + --> $DIR/match-test-ptr-null.rs:5:22 + | +LL | let _: [u8; 0] = [4; { + | ____________-------___^ + | | | + | | expected due to this +LL | | match &1 as *const i32 as usize { +LL | | +LL | | +... | +LL | | } +LL | | }]; + | |______^ expected `0usize`, found `{ + match &1 as *const i32 as usize { + 0 => 42, + n => n, + } + }` + | + = note: expected array `[u8; 0]` + found array `[u8; _]` + +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0080, E0658. +Some errors have detailed explanations: E0080, E0308, E0658. For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/no_lint_for_statically_known_error.rs b/src/test/ui/consts/const-eval/no_lint_for_statically_known_error.rs index cea367528c975..910ca3c4bcbb6 100644 --- a/src/test/ui/consts/const-eval/no_lint_for_statically_known_error.rs +++ b/src/test/ui/consts/const-eval/no_lint_for_statically_known_error.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass // if `X` were used instead of `x`, `X - 10` would result in a lint. // This file should never produce a lint, no matter how the const diff --git a/src/test/ui/consts/const-eval/promote_mutable_zst_mir_borrowck.rs b/src/test/ui/consts/const-eval/promote_mutable_zst_mir_borrowck.rs index ca75d65a39a92..edda10e6e82e9 100644 --- a/src/test/ui/consts/const-eval/promote_mutable_zst_mir_borrowck.rs +++ b/src/test/ui/consts/const-eval/promote_mutable_zst_mir_borrowck.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass pub fn main() { let y: &'static mut [u8; 0] = &mut []; diff --git a/src/test/ui/consts/const-eval/pub_const_err.rs b/src/test/ui/consts/const-eval/pub_const_err.rs index 4ff140fee7a71..ad165d40a76f2 100644 --- a/src/test/ui/consts/const-eval/pub_const_err.rs +++ b/src/test/ui/consts/const-eval/pub_const_err.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![warn(const_err)] #![crate_type = "lib"] diff --git a/src/test/ui/consts/const-eval/pub_const_err_bin.rs b/src/test/ui/consts/const-eval/pub_const_err_bin.rs index 7f1586336e721..078e4c896df80 100644 --- a/src/test/ui/consts/const-eval/pub_const_err_bin.rs +++ b/src/test/ui/consts/const-eval/pub_const_err_bin.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![warn(const_err)] pub const Z: u32 = 0 - 1; diff --git a/src/test/ui/consts/const-eval/simple_with_undef.rs b/src/test/ui/consts/const-eval/simple_with_undef.rs index 8a9f3fe974d91..1a416dd460d68 100644 --- a/src/test/ui/consts/const-eval/simple_with_undef.rs +++ b/src/test/ui/consts/const-eval/simple_with_undef.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass const PARSE_BOOL: Option<&'static str> = None; static FOO: (Option<&str>, u32) = (PARSE_BOOL, 42); diff --git a/src/test/ui/consts/const-eval/ub-nonnull.stderr b/src/test/ui/consts/const-eval/ub-nonnull.stderr index edfc7ac837fc7..adad1b4f7fafe 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.stderr +++ b/src/test/ui/consts/const-eval/ub-nonnull.stderr @@ -13,7 +13,7 @@ LL | / const OUT_OF_BOUNDS_PTR: NonNull = { unsafe { LL | | let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle LL | | // Use address-of-element for pointer arithmetic. This could wrap around to NULL! LL | | let out_of_bounds_ptr = &ptr[255]; - | | ^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of allocation 8 which has size 1 + | | ^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc8 which has size 1 LL | | mem::transmute(out_of_bounds_ptr) LL | | } }; | |____- diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs index 2d48309b72722..0200bfe9f08f8 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs @@ -6,7 +6,7 @@ use std::mem; // normalize-stderr-test "offset \d+" -> "offset N" -// normalize-stderr-test "allocation \d+" -> "allocation N" +// normalize-stderr-test "alloc\d+" -> "allocN" // normalize-stderr-test "size \d+" -> "size N" #[repr(C)] diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr index a562c64b124f9..80e60dbb58a5d 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:32:1 | LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (going beyond the bounds of its allocation) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -70,7 +70,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:62:1 | LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (going beyond the bounds of its allocation) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -86,7 +86,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:68:1 | LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (not entirely in bounds) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (going beyond the bounds of its allocation) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -192,7 +192,7 @@ error[E0080]: could not evaluate static initializer --> $DIR/ub-wide-ptr.rs:125:5 | LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64)) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocation N which has size N + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocN which has size N error: aborting due to 24 previous errors diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr index d0e35615dab42..cede356a6b8a1 100644 --- a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr +++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr @@ -4,7 +4,7 @@ warning: any use of this value will cause an error LL | unsafe { std::mem::transmute(()) } | ^^^^^^^^^^^^^^^^^^^^^^^ | | - | entering unreachable code + | transmuting to uninhabited type | inside call to `foo` at $DIR/validate_uninhabited_zsts.rs:14:26 ... LL | const FOO: [Empty; 3] = [foo(); 3]; diff --git a/src/test/ui/consts/const-eval/zst_operand_eval.rs b/src/test/ui/consts/const-eval/zst_operand_eval.rs index 7edb6bd03dabf..5f7ddf7f758e0 100644 --- a/src/test/ui/consts/const-eval/zst_operand_eval.rs +++ b/src/test/ui/consts/const-eval/zst_operand_eval.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass static ASSERT: () = [()][!(std::mem::size_of::() == 4) as usize]; diff --git a/src/test/ui/consts/const-int-unchecked.stderr b/src/test/ui/consts/const-int-unchecked.stderr index bf31e0b0732d8..cf70454b6bf9e 100644 --- a/src/test/ui/consts/const-int-unchecked.stderr +++ b/src/test/ui/consts/const-int-unchecked.stderr @@ -4,7 +4,7 @@ error: any use of this value will cause an error LL | const SHL_U8: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) }; | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 8 in `unchecked_shl` + | overflowing shift by 8 in `unchecked_shl` | = note: `#[deny(const_err)]` on by default @@ -14,7 +14,7 @@ error: any use of this value will cause an error LL | const SHL_U16: u16 = unsafe { intrinsics::unchecked_shl(5_u16, 16) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 16 in `unchecked_shl` + | overflowing shift by 16 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:19:31 @@ -22,7 +22,7 @@ error: any use of this value will cause an error LL | const SHL_U32: u32 = unsafe { intrinsics::unchecked_shl(5_u32, 32) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 32 in `unchecked_shl` + | overflowing shift by 32 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:21:31 @@ -30,7 +30,7 @@ error: any use of this value will cause an error LL | const SHL_U64: u64 = unsafe { intrinsics::unchecked_shl(5_u64, 64) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 64 in `unchecked_shl` + | overflowing shift by 64 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:23:33 @@ -38,7 +38,7 @@ error: any use of this value will cause an error LL | const SHL_U128: u128 = unsafe { intrinsics::unchecked_shl(5_u128, 128) }; | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 128 in `unchecked_shl` + | overflowing shift by 128 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:28:29 @@ -46,7 +46,7 @@ error: any use of this value will cause an error LL | const SHL_I8: i8 = unsafe { intrinsics::unchecked_shl(5_i8, 8) }; | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 8 in `unchecked_shl` + | overflowing shift by 8 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:30:31 @@ -54,7 +54,7 @@ error: any use of this value will cause an error LL | const SHL_I16: i16 = unsafe { intrinsics::unchecked_shl(5_16, 16) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 16 in `unchecked_shl` + | overflowing shift by 16 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:32:31 @@ -62,7 +62,7 @@ error: any use of this value will cause an error LL | const SHL_I32: i32 = unsafe { intrinsics::unchecked_shl(5_i32, 32) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 32 in `unchecked_shl` + | overflowing shift by 32 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:34:31 @@ -70,7 +70,7 @@ error: any use of this value will cause an error LL | const SHL_I64: i64 = unsafe { intrinsics::unchecked_shl(5_i64, 64) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 64 in `unchecked_shl` + | overflowing shift by 64 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:36:33 @@ -78,7 +78,7 @@ error: any use of this value will cause an error LL | const SHL_I128: i128 = unsafe { intrinsics::unchecked_shl(5_i128, 128) }; | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 128 in `unchecked_shl` + | overflowing shift by 128 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:41:33 @@ -86,7 +86,7 @@ error: any use of this value will cause an error LL | const SHL_I8_NEG: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -1) }; | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 255 in `unchecked_shl` + | overflowing shift by 255 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:43:35 @@ -94,7 +94,7 @@ error: any use of this value will cause an error LL | const SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_16, -1) }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 65535 in `unchecked_shl` + | overflowing shift by 65535 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:45:35 @@ -102,7 +102,7 @@ error: any use of this value will cause an error LL | const SHL_I32_NEG: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -1) }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 4294967295 in `unchecked_shl` + | overflowing shift by 4294967295 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:47:35 @@ -110,7 +110,7 @@ error: any use of this value will cause an error LL | const SHL_I64_NEG: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -1) }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 18446744073709551615 in `unchecked_shl` + | overflowing shift by 18446744073709551615 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:49:37 @@ -118,7 +118,7 @@ error: any use of this value will cause an error LL | const SHL_I128_NEG: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -1) }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shl` + | overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:55:40 @@ -126,7 +126,7 @@ error: any use of this value will cause an error LL | const SHL_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -6) }; | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 250 in `unchecked_shl` + | overflowing shift by 250 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:57:42 @@ -134,7 +134,7 @@ error: any use of this value will cause an error LL | const SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_16, -13) }; | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 65523 in `unchecked_shl` + | overflowing shift by 65523 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:59:42 @@ -142,7 +142,7 @@ error: any use of this value will cause an error LL | const SHL_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -25) }; | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 4294967271 in `unchecked_shl` + | overflowing shift by 4294967271 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:61:42 @@ -150,7 +150,7 @@ error: any use of this value will cause an error LL | const SHL_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -30) }; | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 18446744073709551586 in `unchecked_shl` + | overflowing shift by 18446744073709551586 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:63:44 @@ -158,7 +158,7 @@ error: any use of this value will cause an error LL | const SHL_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -93) }; | -------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shl` + | overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:70:29 @@ -166,7 +166,7 @@ error: any use of this value will cause an error LL | const SHR_U8: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) }; | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 8 in `unchecked_shr` + | overflowing shift by 8 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:72:31 @@ -174,7 +174,7 @@ error: any use of this value will cause an error LL | const SHR_U16: u16 = unsafe { intrinsics::unchecked_shr(5_u16, 16) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 16 in `unchecked_shr` + | overflowing shift by 16 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:74:31 @@ -182,7 +182,7 @@ error: any use of this value will cause an error LL | const SHR_U32: u32 = unsafe { intrinsics::unchecked_shr(5_u32, 32) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 32 in `unchecked_shr` + | overflowing shift by 32 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:76:31 @@ -190,7 +190,7 @@ error: any use of this value will cause an error LL | const SHR_U64: u64 = unsafe { intrinsics::unchecked_shr(5_u64, 64) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 64 in `unchecked_shr` + | overflowing shift by 64 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:78:33 @@ -198,7 +198,7 @@ error: any use of this value will cause an error LL | const SHR_U128: u128 = unsafe { intrinsics::unchecked_shr(5_u128, 128) }; | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 128 in `unchecked_shr` + | overflowing shift by 128 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:83:29 @@ -206,7 +206,7 @@ error: any use of this value will cause an error LL | const SHR_I8: i8 = unsafe { intrinsics::unchecked_shr(5_i8, 8) }; | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 8 in `unchecked_shr` + | overflowing shift by 8 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:85:31 @@ -214,7 +214,7 @@ error: any use of this value will cause an error LL | const SHR_I16: i16 = unsafe { intrinsics::unchecked_shr(5_16, 16) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 16 in `unchecked_shr` + | overflowing shift by 16 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:87:31 @@ -222,7 +222,7 @@ error: any use of this value will cause an error LL | const SHR_I32: i32 = unsafe { intrinsics::unchecked_shr(5_i32, 32) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 32 in `unchecked_shr` + | overflowing shift by 32 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:89:31 @@ -230,7 +230,7 @@ error: any use of this value will cause an error LL | const SHR_I64: i64 = unsafe { intrinsics::unchecked_shr(5_i64, 64) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 64 in `unchecked_shr` + | overflowing shift by 64 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:91:33 @@ -238,7 +238,7 @@ error: any use of this value will cause an error LL | const SHR_I128: i128 = unsafe { intrinsics::unchecked_shr(5_i128, 128) }; | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 128 in `unchecked_shr` + | overflowing shift by 128 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:96:33 @@ -246,7 +246,7 @@ error: any use of this value will cause an error LL | const SHR_I8_NEG: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -1) }; | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 255 in `unchecked_shr` + | overflowing shift by 255 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:98:35 @@ -254,7 +254,7 @@ error: any use of this value will cause an error LL | const SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_16, -1) }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 65535 in `unchecked_shr` + | overflowing shift by 65535 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:100:35 @@ -262,7 +262,7 @@ error: any use of this value will cause an error LL | const SHR_I32_NEG: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -1) }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 4294967295 in `unchecked_shr` + | overflowing shift by 4294967295 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:102:35 @@ -270,7 +270,7 @@ error: any use of this value will cause an error LL | const SHR_I64_NEG: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -1) }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 18446744073709551615 in `unchecked_shr` + | overflowing shift by 18446744073709551615 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:104:37 @@ -278,7 +278,7 @@ error: any use of this value will cause an error LL | const SHR_I128_NEG: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -1) }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shr` + | overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:110:40 @@ -286,7 +286,7 @@ error: any use of this value will cause an error LL | const SHR_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -6) }; | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 250 in `unchecked_shr` + | overflowing shift by 250 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:112:42 @@ -294,7 +294,7 @@ error: any use of this value will cause an error LL | const SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_16, -13) }; | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 65523 in `unchecked_shr` + | overflowing shift by 65523 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:114:42 @@ -302,7 +302,7 @@ error: any use of this value will cause an error LL | const SHR_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -25) }; | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 4294967271 in `unchecked_shr` + | overflowing shift by 4294967271 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:116:42 @@ -310,7 +310,7 @@ error: any use of this value will cause an error LL | const SHR_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -30) }; | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 18446744073709551586 in `unchecked_shr` + | overflowing shift by 18446744073709551586 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:118:44 @@ -318,7 +318,7 @@ error: any use of this value will cause an error LL | const SHR_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -93) }; | -------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shr` + | overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:123:25 @@ -326,7 +326,7 @@ error: any use of this value will cause an error LL | const _: u16 = unsafe { std::intrinsics::unchecked_add(40000u16, 30000) }; | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflow executing `unchecked_add` + | overflow executing `unchecked_add` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:126:25 @@ -334,7 +334,7 @@ error: any use of this value will cause an error LL | const _: u32 = unsafe { std::intrinsics::unchecked_sub(14u32, 22) }; | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflow executing `unchecked_sub` + | overflow executing `unchecked_sub` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:129:25 @@ -342,7 +342,7 @@ error: any use of this value will cause an error LL | const _: u16 = unsafe { std::intrinsics::unchecked_mul(300u16, 250u16) }; | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflow executing `unchecked_mul` + | overflow executing `unchecked_mul` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:132:25 @@ -358,7 +358,7 @@ error: any use of this value will cause an error LL | const _: i32 = unsafe { std::intrinsics::unchecked_div(i32::min_value(), -1) }; | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflow executing `unchecked_div` + | overflow executing `unchecked_div` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:137:25 @@ -374,7 +374,7 @@ error: any use of this value will cause an error LL | const _: i32 = unsafe { std::intrinsics::unchecked_rem(i32::min_value(), -1) }; | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflow executing `unchecked_rem` + | overflow executing `unchecked_rem` error: aborting due to 47 previous errors diff --git a/src/test/ui/consts/const-size_of-cycle.stderr b/src/test/ui/consts/const-size_of-cycle.stderr index c03b7a19ffc61..aac3622c6de40 100644 --- a/src/test/ui/consts/const-size_of-cycle.stderr +++ b/src/test/ui/consts/const-size_of-cycle.stderr @@ -25,7 +25,7 @@ note: ...which requires const-evaluating + checking `std::intrinsics::size_of`.. LL | pub fn size_of() -> usize; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing layout of `Foo`... - = note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`... + = note: ...which requires normalizing `[u8; _]`... = note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle note: cycle used when processing `Foo` --> $DIR/const-size_of-cycle.rs:7:1 diff --git a/src/test/ui/consts/const_forget.rs b/src/test/ui/consts/const_forget.rs new file mode 100644 index 0000000000000..2dcb72a5a09cb --- /dev/null +++ b/src/test/ui/consts/const_forget.rs @@ -0,0 +1,22 @@ +// check-pass + +#![feature(const_forget)] + +use std::mem::forget; + +const _: () = forget(0i32); +const _: () = forget(Vec::>>::new()); + +// Writing this function signature without const-forget +// triggers compiler errors: +// 1) That we use a non-const fn inside a const fn +// 2) without the forget, it complains about the destructor of Box +// +// FIXME: this method cannot be called in const-eval yet, as Box isn't +// const constructable +#[allow(unused)] +const fn const_forget_box(b: Box) { + forget(b); +} + +fn main() {} diff --git a/src/test/ui/consts/const_limit/const_eval_limit_not_reached.rs b/src/test/ui/consts/const_limit/const_eval_limit_not_reached.rs index 4ed908312fb6d..34abcdf08dae0 100644 --- a/src/test/ui/consts/const_limit/const_eval_limit_not_reached.rs +++ b/src/test/ui/consts/const_limit/const_eval_limit_not_reached.rs @@ -1,15 +1,21 @@ // check-pass + #![feature(const_eval_limit)] -#![const_eval_limit="1000"] +#![feature(const_loop, const_if_match)] -const CONSTANT: usize = limit(); +// This needs to be higher than the number of loop iterations since each pass through the loop may +// hit more than one terminator. +#![const_eval_limit="4000"] -fn main() { - assert_eq!(CONSTANT, 1764); -} +const X: usize = { + let mut x = 0; + while x != 1000 { + x += 1; + } -const fn limit() -> usize { - let x = 42; + x +}; - x * 42 +fn main() { + assert_eq!(X, 1000); } diff --git a/src/test/ui/consts/const_limit/const_eval_limit_reached.rs b/src/test/ui/consts/const_limit/const_eval_limit_reached.rs index d962398d4136e..b45aca0b13e42 100644 --- a/src/test/ui/consts/const_limit/const_eval_limit_reached.rs +++ b/src/test/ui/consts/const_limit/const_eval_limit_reached.rs @@ -1,21 +1,18 @@ -// ignore-tidy-linelength -// only-x86_64 -// check-pass -// NOTE: We always compile this test with -Copt-level=0 because higher opt-levels -// optimize away the const function -// compile-flags:-Copt-level=0 #![feature(const_eval_limit)] -#![const_eval_limit="2"] +#![feature(const_loop, const_if_match)] -const CONSTANT: usize = limit(); -//~^ WARNING Constant evaluating a complex constant, this might take some time +#![const_eval_limit="500"] -fn main() { - assert_eq!(CONSTANT, 1764); -} +const X: usize = { + let mut x = 0; + while x != 1000 { + //~^ ERROR any use of this value will cause an error + x += 1; + } -const fn limit() -> usize { //~ WARNING Constant evaluating a complex constant, this might take some time - let x = 42; + x +}; - x * 42 +fn main() { + assert_eq!(X, 1000); } diff --git a/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr b/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr index e0871ff718561..be522dd6d5d5a 100644 --- a/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr +++ b/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr @@ -1,16 +1,17 @@ -warning: Constant evaluating a complex constant, this might take some time - --> $DIR/const_eval_limit_reached.rs:17:1 +error: any use of this value will cause an error + --> $DIR/const_eval_limit_reached.rs:8:11 | -LL | / const fn limit() -> usize { -LL | | let x = 42; +LL | / const X: usize = { +LL | | let mut x = 0; +LL | | while x != 1000 { + | | ^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`) LL | | -LL | | x * 42 -LL | | } - | |_^ - -warning: Constant evaluating a complex constant, this might take some time - --> $DIR/const_eval_limit_reached.rs:10:1 +... | +LL | | x +LL | | }; + | |__- | -LL | const CONSTANT: usize = limit(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[deny(const_err)]` on by default + +error: aborting due to previous error diff --git a/src/test/ui/consts/dangling-alloc-id-ice.stderr b/src/test/ui/consts/dangling-alloc-id-ice.stderr index bac9f555d271b..0e213555052c8 100644 --- a/src/test/ui/consts/dangling-alloc-id-ice.stderr +++ b/src/test/ui/consts/dangling-alloc-id-ice.stderr @@ -5,7 +5,7 @@ LL | / const FOO: &() = { LL | | let y = (); LL | | unsafe { Foo { y: &y }.long_live_the_unit } LL | | }; - | |__^ type validation failed: encountered dangling pointer in final constant + | |__^ encountered dangling pointer in final constant | = note: `#[deny(const_err)]` on by default diff --git a/src/test/ui/consts/dangling_raw_ptr.stderr b/src/test/ui/consts/dangling_raw_ptr.stderr index 4748be37dffcf..4d4c2876c4598 100644 --- a/src/test/ui/consts/dangling_raw_ptr.stderr +++ b/src/test/ui/consts/dangling_raw_ptr.stderr @@ -5,7 +5,7 @@ LL | / const FOO: *const u32 = { LL | | let x = 42; LL | | &x LL | | }; - | |__^ type validation failed: encountered dangling pointer in final constant + | |__^ encountered dangling pointer in final constant | = note: `#[deny(const_err)]` on by default diff --git a/src/test/ui/consts/issue-52432.rs b/src/test/ui/consts/issue-52432.rs index 2d4c939f47d79..ded79458e637f 100644 --- a/src/test/ui/consts/issue-52432.rs +++ b/src/test/ui/consts/issue-52432.rs @@ -6,5 +6,4 @@ fn main() { //~| ERROR: type annotations needed [(); &(static || {}) as *const _ as usize]; //~^ ERROR: closures cannot be static - //~| ERROR: evaluation of constant value failed } diff --git a/src/test/ui/consts/issue-52432.stderr b/src/test/ui/consts/issue-52432.stderr index e9539d24118a0..d25c11138f400 100644 --- a/src/test/ui/consts/issue-52432.stderr +++ b/src/test/ui/consts/issue-52432.stderr @@ -16,13 +16,7 @@ error[E0282]: type annotations needed LL | [(); &(static |x| {}) as *const _ as usize]; | ^ consider giving this closure parameter a type -error[E0080]: evaluation of constant value failed - --> $DIR/issue-52432.rs:7:10 - | -LL | [(); &(static || {}) as *const _ as usize]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "pointer-to-integer cast" needs an rfc before being allowed inside constants - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0080, E0282, E0697. -For more information about an error, try `rustc --explain E0080`. +Some errors have detailed explanations: E0282, E0697. +For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/consts/issue-69310-array-size-lit-wrong-ty.rs b/src/test/ui/consts/issue-69310-array-size-lit-wrong-ty.rs index 98be8c345a9ed..f0d5fea8e0239 100644 --- a/src/test/ui/consts/issue-69310-array-size-lit-wrong-ty.rs +++ b/src/test/ui/consts/issue-69310-array-size-lit-wrong-ty.rs @@ -3,7 +3,7 @@ // we call the query `lit_to_const(input);`. // However, the literal `input.lit` would not be of the type expected by `input.ty`. // As a result, we immediately called `bug!(...)` instead of bubbling up the problem -// so that it could be handled by the caller of `lit_to_const` (`ast_const_to_const`). +// so that it could be handled by the caller of `lit_to_const` (`from_anon_const`). fn main() {} diff --git a/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr b/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr index da00c49963eec..c7e902132e91a 100644 --- a/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr +++ b/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr @@ -16,7 +16,7 @@ error: any use of this value will cause an error LL | my_fn(); | ^^^^^^^ | | - | tried to call a function with ABI C using caller ABI Rust + | calling a function with ABI C using caller ABI Rust | inside call to `call_rust_fn` at $DIR/abi-mismatch.rs:13:17 ... LL | const VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "C" fn()) }); diff --git a/src/test/ui/consts/miri_unleashed/mutable_const.stderr b/src/test/ui/consts/miri_unleashed/mutable_const.stderr index 86f27784701c6..8456e8ec6870d 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_const.stderr +++ b/src/test/ui/consts/miri_unleashed/mutable_const.stderr @@ -11,7 +11,7 @@ LL | / const MUTATING_BEHIND_RAW: () = { LL | | // Test that `MUTABLE_BEHIND_RAW` is actually immutable, by doing this at const time. LL | | unsafe { LL | | *MUTABLE_BEHIND_RAW = 99 - | | ^^^^^^^^^^^^^^^^^^^^^^^^ tried to modify constant memory + | | ^^^^^^^^^^^^^^^^^^^^^^^^ writing to alloc1 which is read-only LL | | } LL | | }; | |__- diff --git a/src/test/ui/consts/miri_unleashed/mutating_global.rs b/src/test/ui/consts/miri_unleashed/mutating_global.rs new file mode 100644 index 0000000000000..acc6fb026cd69 --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/mutating_global.rs @@ -0,0 +1,15 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you + +// Make sure we cannot mutate globals. + +static mut GLOBAL: i32 = 0; + +const MUTATING_GLOBAL: () = { + unsafe { + GLOBAL = 99 //~ ERROR any use of this value will cause an error + //~^ WARN skipping const checks + //~| WARN skipping const checks + } +}; + +fn main() {} diff --git a/src/test/ui/consts/miri_unleashed/mutating_global.stderr b/src/test/ui/consts/miri_unleashed/mutating_global.stderr new file mode 100644 index 0000000000000..4e67d2c0fb85e --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/mutating_global.stderr @@ -0,0 +1,29 @@ +warning: skipping const checks + --> $DIR/mutating_global.rs:9:9 + | +LL | GLOBAL = 99 + | ^^^^^^ + +warning: skipping const checks + --> $DIR/mutating_global.rs:9:9 + | +LL | GLOBAL = 99 + | ^^^^^^ + +error: any use of this value will cause an error + --> $DIR/mutating_global.rs:9:9 + | +LL | / const MUTATING_GLOBAL: () = { +LL | | unsafe { +LL | | GLOBAL = 99 + | | ^^^^^^^^^^^ modifying a static's initial value from another static's initializer +LL | | +LL | | +LL | | } +LL | | }; + | |__- + | + = note: `#[deny(const_err)]` on by default + +error: aborting due to previous error + diff --git a/src/test/ui/consts/offset_from_ub.stderr b/src/test/ui/consts/offset_from_ub.stderr index 24da983cf0868..217530740079f 100644 --- a/src/test/ui/consts/offset_from_ub.stderr +++ b/src/test/ui/consts/offset_from_ub.stderr @@ -26,7 +26,7 @@ error: any use of this value will cause an error LL | intrinsics::ptr_offset_from(self, origin) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | a memory access tried to interpret some bytes as a pointer + | unable to turn bytes into a pointer | inside call to `std::ptr::const_ptr::::offset_from` at $DIR/offset_from_ub.rs:28:14 | ::: $DIR/offset_from_ub.rs:26:1 @@ -43,7 +43,7 @@ error: any use of this value will cause an error LL | intrinsics::ptr_offset_from(self, origin) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | exact_div: 1 cannot be divided by 2 without remainder + | exact_div: 1isize cannot be divided by 2isize without remainder | inside call to `std::ptr::const_ptr::::offset_from` at $DIR/offset_from_ub.rs:36:14 | ::: $DIR/offset_from_ub.rs:31:1 @@ -81,7 +81,7 @@ error: any use of this value will cause an error LL | intrinsics::ptr_offset_from(self, origin) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | a memory access tried to interpret some bytes as a pointer + | unable to turn bytes into a pointer | inside call to `std::ptr::const_ptr::::offset_from` at $DIR/offset_from_ub.rs:49:14 | ::: $DIR/offset_from_ub.rs:45:1 diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr index b43fbc86f99f2..8db75dd63cf2a 100644 --- a/src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr @@ -2,7 +2,7 @@ error[E0080]: could not evaluate static initializer --> $DIR/static_mut_containing_mut_ref2.rs:7:45 | LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tried to modify a static's initial value from another static's initializer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ modifying a static's initial value from another static's initializer error: aborting due to previous error diff --git a/src/test/ui/consts/static_mut_containing_mut_ref3.stderr b/src/test/ui/consts/static_mut_containing_mut_ref3.stderr index e88e49b097af2..91f9dbd8d0b9e 100644 --- a/src/test/ui/consts/static_mut_containing_mut_ref3.stderr +++ b/src/test/ui/consts/static_mut_containing_mut_ref3.stderr @@ -2,7 +2,7 @@ error[E0080]: could not evaluate static initializer --> $DIR/static_mut_containing_mut_ref3.rs:3:31 | LL | static mut BAR: () = unsafe { FOO.0 = 99; }; - | ^^^^^^^^^^ tried to modify a static's initial value from another static's initializer + | ^^^^^^^^^^ modifying a static's initial value from another static's initializer error: aborting due to previous error diff --git a/src/test/ui/consts/too_generic_eval_ice.rs b/src/test/ui/consts/too_generic_eval_ice.rs index 7a299169bc4e1..7e4d4dbe44610 100644 --- a/src/test/ui/consts/too_generic_eval_ice.rs +++ b/src/test/ui/consts/too_generic_eval_ice.rs @@ -7,6 +7,7 @@ impl Foo { [5; Self::HOST_SIZE] == [6; 0] //~ ERROR no associated item named `HOST_SIZE` //~^ the size for values of type `A` cannot be known //~| the size for values of type `B` cannot be known + //~| binary operation `==` cannot be applied to type `[{integer}; _]` } } diff --git a/src/test/ui/consts/too_generic_eval_ice.stderr b/src/test/ui/consts/too_generic_eval_ice.stderr index 8836de0023c9d..ffa28225b79c6 100644 --- a/src/test/ui/consts/too_generic_eval_ice.stderr +++ b/src/test/ui/consts/too_generic_eval_ice.stderr @@ -41,7 +41,15 @@ LL | [5; Self::HOST_SIZE] == [6; 0] = help: the trait `std::marker::Sized` is not implemented for `B` = note: to learn more, visit -error: aborting due to 3 previous errors +error[E0369]: binary operation `==` cannot be applied to type `[{integer}; _]` + --> $DIR/too_generic_eval_ice.rs:7:30 + | +LL | [5; Self::HOST_SIZE] == [6; 0] + | -------------------- ^^ ------ [{integer}; 0] + | | + | [{integer}; _] + +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0277, E0599. +Some errors have detailed explanations: E0277, E0369, E0599. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr b/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr index 296a55ef16076..5a47771459625 100644 --- a/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr +++ b/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr @@ -21,7 +21,7 @@ LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) }; | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `usize` (word size) - = note: target type: `&'static [u8]` (2 * word size) + = note: target type: `&[u8]` (2 * word size) error: could not evaluate constant pattern --> $DIR/transmute-size-mismatch-before-typeck.rs:10:9 diff --git a/src/test/ui/copy-a-resource.rs b/src/test/ui/copy-a-resource.rs index 55f2dd4ee6dde..1a647692018e5 100644 --- a/src/test/ui/copy-a-resource.rs +++ b/src/test/ui/copy-a-resource.rs @@ -1,3 +1,8 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl + #[derive(Debug)] struct Foo { i: isize, diff --git a/src/test/ui/copy-a-resource.stderr b/src/test/ui/copy-a-resource.stderr index c95e8d239d2b9..71d2eead3554c 100644 --- a/src/test/ui/copy-a-resource.stderr +++ b/src/test/ui/copy-a-resource.stderr @@ -1,11 +1,19 @@ error[E0599]: no method named `clone` found for struct `Foo` in the current scope - --> $DIR/copy-a-resource.rs:18:16 + --> $DIR/copy-a-resource.rs:23:16 | LL | struct Foo { | ---------- method `clone` not found for this ... LL | let _y = x.clone(); | ^^^^^ method not found in `Foo` + | + ::: $SRC_DIR/libcore/clone.rs:LL:COL + | +LL | fn clone(&self) -> Self; + | ----- + | | + | the method is available for `std::sync::Arc` here + | the method is available for `std::rc::Rc` here | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.rs b/src/test/ui/derives/derive-assoc-type-not-impl.rs index 0f642d63a1dcb..fa5afd2419261 100644 --- a/src/test/ui/derives/derive-assoc-type-not-impl.rs +++ b/src/test/ui/derives/derive-assoc-type-not-impl.rs @@ -1,3 +1,8 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl + trait Foo { type X; fn method(&self) {} diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr index c4c85773fbc1d..f15aba97ded81 100644 --- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr +++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr @@ -1,5 +1,5 @@ error[E0599]: no method named `clone` found for struct `Bar` in the current scope - --> $DIR/derive-assoc-type-not-impl.rs:18:30 + --> $DIR/derive-assoc-type-not-impl.rs:23:30 | LL | struct Bar { | ------------------ @@ -12,6 +12,14 @@ LL | struct NotClone; ... LL | Bar:: { x: 1 }.clone(); | ^^^^^ method not found in `Bar` + | + ::: $SRC_DIR/libcore/clone.rs:LL:COL + | +LL | fn clone(&self) -> Self; + | ----- + | | + | the method is available for `std::sync::Arc>` here + | the method is available for `std::rc::Rc>` here | = note: the method `clone` exists but the following trait bounds were not satisfied: `NotClone: std::clone::Clone` diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.rs b/src/test/ui/did_you_mean/bad-assoc-ty.rs index 00845a17b116b..e66b432ede20c 100644 --- a/src/test/ui/did_you_mean/bad-assoc-ty.rs +++ b/src/test/ui/did_you_mean/bad-assoc-ty.rs @@ -49,4 +49,36 @@ trait K {} fn foo>(x: X) {} //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +fn bar(_: F) where F: Fn() -> _ {} +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures + +fn baz _>(_: F) {} +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures + +struct L(F) where F: Fn() -> _; +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +struct M where F: Fn() -> _ { +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures + a: F, +} +enum N where F: Fn() -> _ { +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures + Foo(F), +} + +union O where F: Fn() -> _ { +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR unions with non-`Copy` fields are unstable + foo: F, +} + +trait P where F: Fn() -> _ { +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +} + +trait Q { + fn foo(_: F) where F: Fn() -> _ {} + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +} + fn main() {} diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.stderr b/src/test/ui/did_you_mean/bad-assoc-ty.stderr index 6d5f3d9f14348..c409ea9c6576d 100644 --- a/src/test/ui/did_you_mean/bad-assoc-ty.stderr +++ b/src/test/ui/did_you_mean/bad-assoc-ty.stderr @@ -57,6 +57,19 @@ LL | type J = ty!(u8); | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) +error[E0658]: unions with non-`Copy` fields are unstable + --> $DIR/bad-assoc-ty.rs:69:1 + | +LL | / union O where F: Fn() -> _ { +LL | | +LL | | +LL | | foo: F, +LL | | } + | |_^ + | + = note: see issue #55149 for more information + = help: add `#![feature(untagged_unions)]` to the crate attributes to enable + error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:1:10 | @@ -129,8 +142,101 @@ LL | fn foo>(x: X) {} | ^ ^ not allowed in type signatures | | | not allowed in type signatures + | +help: use type parameters instead + | +LL | fn foo, T>(x: X) {} + | ^ ^ ^^^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:52:34 + | +LL | fn bar(_: F) where F: Fn() -> _ {} + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn bar(_: F) where F: Fn() -> T {} + | ^^^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:55:19 + | +LL | fn baz _>(_: F) {} + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn baz T, T>(_: F) {} + | ^^^^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:58:33 + | +LL | struct L(F) where F: Fn() -> _; + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | struct L(F) where F: Fn() -> T; + | ^^^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:60:30 + | +LL | struct M where F: Fn() -> _ { + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | struct M where F: Fn() -> T { + | ^^^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:64:28 + | +LL | enum N where F: Fn() -> _ { + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | enum N where F: Fn() -> T { + | ^^^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:69:29 + | +LL | union O where F: Fn() -> _ { + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | union O where F: Fn() -> T { + | ^^^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:75:29 + | +LL | trait P where F: Fn() -> _ { + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | trait P where F: Fn() -> T { + | ^^^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:80:38 + | +LL | fn foo(_: F) where F: Fn() -> _ {} + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn foo(_: F) where F: Fn() -> T {} + | ^^^ ^ -error: aborting due to 20 previous errors +error: aborting due to 29 previous errors -Some errors have detailed explanations: E0121, E0223. +Some errors have detailed explanations: E0121, E0223, E0658. For more information about an error, try `rustc --explain E0121`. diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr index f952136a7bfe3..10972697f9fcd 100644 --- a/src/test/ui/did_you_mean/issue-40396.stderr +++ b/src/test/ui/did_you_mean/issue-40396.stderr @@ -2,16 +2,8 @@ error: comparison operators cannot be chained --> $DIR/issue-40396.rs:2:20 | LL | (0..13).collect>(); - | ^^^^^ + | ^ ^ | -help: split the comparison into two... - | -LL | (0..13).collect < Vec && Vec >(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: ...or parenthesize one of the comparisons - | -LL | ((0..13).collect < Vec) >(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `::<...>` instead of `<...>` to specify type arguments | LL | (0..13).collect::>(); @@ -21,7 +13,7 @@ error: comparison operators cannot be chained --> $DIR/issue-40396.rs:4:8 | LL | Vec::new(); - | ^^^^^ + | ^ ^ | help: use `::<...>` instead of `<...>` to specify type arguments | @@ -32,16 +24,8 @@ error: comparison operators cannot be chained --> $DIR/issue-40396.rs:6:20 | LL | (0..13).collect(); - | ^^^^^ - | -help: split the comparison into two... - | -LL | (0..13).collect < Vec && Vec (); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: ...or parenthesize one of the comparisons + | ^ ^ | -LL | ((0..13).collect < Vec) (); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `::<...>` instead of `<...>` to specify type arguments | LL | (0..13).collect::(); diff --git a/src/test/ui/directory_ownership/macro-expanded-mod.rs b/src/test/ui/directory_ownership/macro-expanded-mod.rs index 376c1a9cd6627..9cb159603a8c5 100644 --- a/src/test/ui/directory_ownership/macro-expanded-mod.rs +++ b/src/test/ui/directory_ownership/macro-expanded-mod.rs @@ -1,7 +1,9 @@ // Test that macro-expanded non-inline modules behave correctly macro_rules! mod_decl { - ($i:ident) => { mod $i; } //~ ERROR Cannot declare a non-inline module inside a block + ($i:ident) => { + mod $i; //~ ERROR Cannot declare a non-inline module inside a block + }; } mod macro_expanded_mod_helper { diff --git a/src/test/ui/directory_ownership/macro-expanded-mod.stderr b/src/test/ui/directory_ownership/macro-expanded-mod.stderr index c7780c869d635..f90419247c92b 100644 --- a/src/test/ui/directory_ownership/macro-expanded-mod.stderr +++ b/src/test/ui/directory_ownership/macro-expanded-mod.stderr @@ -1,8 +1,8 @@ error: Cannot declare a non-inline module inside a block unless it has a path attribute - --> $DIR/macro-expanded-mod.rs:4:25 + --> $DIR/macro-expanded-mod.rs:5:9 | -LL | ($i:ident) => { mod $i; } - | ^^ +LL | mod $i; + | ^^^^^^^ ... LL | mod_decl!(foo); | --------------- in this macro invocation diff --git a/src/test/ui/directory_ownership/non-inline-mod-restriction.stderr b/src/test/ui/directory_ownership/non-inline-mod-restriction.stderr index 46acc7e66d8b8..d034942ca5d4c 100644 --- a/src/test/ui/directory_ownership/non-inline-mod-restriction.stderr +++ b/src/test/ui/directory_ownership/non-inline-mod-restriction.stderr @@ -1,8 +1,8 @@ error: Cannot declare a non-inline module inside a block unless it has a path attribute - --> $DIR/non-inline-mod-restriction.rs:4:9 + --> $DIR/non-inline-mod-restriction.rs:4:5 | LL | mod foo; - | ^^^ + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/editions/edition-keywords-2018-2015-parsing.rs b/src/test/ui/editions/edition-keywords-2018-2015-parsing.rs index dbc0465b08e77..d5ed9fb9a285e 100644 --- a/src/test/ui/editions/edition-keywords-2018-2015-parsing.rs +++ b/src/test/ui/editions/edition-keywords-2018-2015-parsing.rs @@ -1,9 +1,17 @@ // edition:2018 // aux-build:edition-kw-macro-2015.rs +#![feature(async_closure)] + +fn main() {} + #[macro_use] extern crate edition_kw_macro_2015; +mod module { + pub fn r#async() {} +} + pub fn check_async() { let mut async = 1; //~ ERROR expected identifier, found keyword `async` let mut r#async = 1; // OK @@ -17,4 +25,6 @@ pub fn check_async() { if passes_ident!(r#async) == 1 {} // OK module::async(); //~ ERROR expected identifier, found keyword `async` module::r#async(); // OK + + let _recovery_witness: () = 0; //~ ERROR mismatched types } diff --git a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr index e12d1a48463d7..28663563c6ccd 100644 --- a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr @@ -1,5 +1,5 @@ error: expected identifier, found keyword `async` - --> $DIR/edition-keywords-2018-2015-parsing.rs:8:13 + --> $DIR/edition-keywords-2018-2015-parsing.rs:16:13 | LL | let mut async = 1; | ^^^^^ expected identifier, found keyword @@ -10,7 +10,7 @@ LL | let mut r#async = 1; | ^^^^^^^ error: expected identifier, found keyword `async` - --> $DIR/edition-keywords-2018-2015-parsing.rs:18:13 + --> $DIR/edition-keywords-2018-2015-parsing.rs:26:13 | LL | module::async(); | ^^^^^ expected identifier, found keyword @@ -21,13 +21,13 @@ LL | module::r#async(); | ^^^^^^^ error: no rules expected the token `r#async` - --> $DIR/edition-keywords-2018-2015-parsing.rs:12:31 + --> $DIR/edition-keywords-2018-2015-parsing.rs:20:31 | LL | r#async = consumes_async!(r#async); | ^^^^^^^ no rules expected this token in macro call error: no rules expected the token `async` - --> $DIR/edition-keywords-2018-2015-parsing.rs:13:35 + --> $DIR/edition-keywords-2018-2015-parsing.rs:21:35 | LL | r#async = consumes_async_raw!(async); | ^^^^^ no rules expected this token in macro call @@ -38,10 +38,19 @@ error: macro expansion ends with an incomplete expression: expected one of `move LL | ($i: ident) => ($i) | ^ expected one of `move`, `|`, or `||` | - ::: $DIR/edition-keywords-2018-2015-parsing.rs:16:8 + ::: $DIR/edition-keywords-2018-2015-parsing.rs:24:8 | LL | if passes_ident!(async) == 1 {} | -------------------- in this macro invocation -error: aborting due to 5 previous errors +error[E0308]: mismatched types + --> $DIR/edition-keywords-2018-2015-parsing.rs:29:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 6 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/editions/edition-keywords-2018-2018-parsing.rs b/src/test/ui/editions/edition-keywords-2018-2018-parsing.rs index 5aca0839f0f15..044ab249f2c26 100644 --- a/src/test/ui/editions/edition-keywords-2018-2018-parsing.rs +++ b/src/test/ui/editions/edition-keywords-2018-2018-parsing.rs @@ -1,9 +1,17 @@ // edition:2018 // aux-build:edition-kw-macro-2018.rs +#![feature(async_closure)] + +fn main() {} + #[macro_use] extern crate edition_kw_macro_2018; +mod module { + pub fn r#async() {} +} + pub fn check_async() { let mut async = 1; //~ ERROR expected identifier, found keyword `async` let mut r#async = 1; // OK @@ -17,4 +25,6 @@ pub fn check_async() { if passes_ident!(r#async) == 1 {} // OK module::async(); //~ ERROR expected identifier, found keyword `async` module::r#async(); // OK + + let _recovery_witness: () = 0; //~ ERROR mismatched types } diff --git a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr index 110165fc077ca..cda7e65e437e8 100644 --- a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr @@ -1,5 +1,5 @@ error: expected identifier, found keyword `async` - --> $DIR/edition-keywords-2018-2018-parsing.rs:8:13 + --> $DIR/edition-keywords-2018-2018-parsing.rs:16:13 | LL | let mut async = 1; | ^^^^^ expected identifier, found keyword @@ -10,7 +10,7 @@ LL | let mut r#async = 1; | ^^^^^^^ error: expected identifier, found keyword `async` - --> $DIR/edition-keywords-2018-2018-parsing.rs:18:13 + --> $DIR/edition-keywords-2018-2018-parsing.rs:26:13 | LL | module::async(); | ^^^^^ expected identifier, found keyword @@ -21,13 +21,13 @@ LL | module::r#async(); | ^^^^^^^ error: no rules expected the token `r#async` - --> $DIR/edition-keywords-2018-2018-parsing.rs:12:31 + --> $DIR/edition-keywords-2018-2018-parsing.rs:20:31 | LL | r#async = consumes_async!(r#async); | ^^^^^^^ no rules expected this token in macro call error: no rules expected the token `async` - --> $DIR/edition-keywords-2018-2018-parsing.rs:13:35 + --> $DIR/edition-keywords-2018-2018-parsing.rs:21:35 | LL | r#async = consumes_async_raw!(async); | ^^^^^ no rules expected this token in macro call @@ -38,10 +38,19 @@ error: macro expansion ends with an incomplete expression: expected one of `move LL | ($i: ident) => ($i) | ^ expected one of `move`, `|`, or `||` | - ::: $DIR/edition-keywords-2018-2018-parsing.rs:16:8 + ::: $DIR/edition-keywords-2018-2018-parsing.rs:24:8 | LL | if passes_ident!(async) == 1 {} | -------------------- in this macro invocation -error: aborting due to 5 previous errors +error[E0308]: mismatched types + --> $DIR/edition-keywords-2018-2018-parsing.rs:29:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 6 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/enum/enum-discrim-too-small2.stderr b/src/test/ui/enum/enum-discrim-too-small2.stderr index 3aa88df29f11b..fadf6ab86b43e 100644 --- a/src/test/ui/enum/enum-discrim-too-small2.stderr +++ b/src/test/ui/enum/enum-discrim-too-small2.stderr @@ -9,24 +9,31 @@ note: the lint level is defined here | LL | #![deny(overflowing_literals)] | ^^^^^^^^^^^^^^^^^^^^ + = note: the literal `223` does not fit into the type `i8` whose range is `-128..=127` error: literal out of range for `i16` --> $DIR/enum-discrim-too-small2.rs:15:12 | LL | Ci16 = 55555, | ^^^^^ + | + = note: the literal `55555` does not fit into the type `i16` whose range is `-32768..=32767` error: literal out of range for `i32` --> $DIR/enum-discrim-too-small2.rs:22:12 | LL | Ci32 = 3_000_000_000, | ^^^^^^^^^^^^^ + | + = note: the literal `3_000_000_000` does not fit into the type `i32` whose range is `-2147483648..=2147483647` error: literal out of range for `i64` --> $DIR/enum-discrim-too-small2.rs:29:12 | LL | Ci64 = 9223372036854775809, | ^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `9223372036854775809` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807` error: aborting due to 4 previous errors diff --git a/src/test/ui/eprint-on-tls-drop.rs b/src/test/ui/eprint-on-tls-drop.rs new file mode 100644 index 0000000000000..9c4800c1a3fa1 --- /dev/null +++ b/src/test/ui/eprint-on-tls-drop.rs @@ -0,0 +1,48 @@ +// run-pass +// ignore-emscripten no processes + +use std::cell::RefCell; +use std::env; +use std::process::Command; + +fn main() { + let name = "YOU_ARE_THE_TEST"; + if env::var(name).is_ok() { + std::thread::spawn(|| { + TLS.with(|f| f.borrow().ensure()); + }) + .join() + .unwrap(); + } else { + let me = env::current_exe().unwrap(); + let output = Command::new(&me).env(name, "1").output().unwrap(); + println!("{:?}", output); + assert!(output.status.success()); + let stderr = String::from_utf8(output.stderr).unwrap(); + assert!(stderr.contains("hello new\n")); + assert!(stderr.contains("hello drop\n")); + } +} + +struct Stuff { + _x: usize, +} + +impl Stuff { + fn new() -> Self { + eprintln!("hello new"); + Self { _x: 0 } + } + + fn ensure(&self) {} +} + +impl Drop for Stuff { + fn drop(&mut self) { + eprintln!("hello drop"); + } +} + +thread_local! { + static TLS: RefCell = RefCell::new(Stuff::new()); +} diff --git a/src/test/ui/error-codes/E0004-2.rs b/src/test/ui/error-codes/E0004-2.rs index c7612fd50a74e..7f1d064cf3f50 100644 --- a/src/test/ui/error-codes/E0004-2.rs +++ b/src/test/ui/error-codes/E0004-2.rs @@ -1,3 +1,8 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl + fn main() { let x = Some(1); diff --git a/src/test/ui/error-codes/E0004-2.stderr b/src/test/ui/error-codes/E0004-2.stderr index f5b41cd1cc0bb..e47a4fa755cac 100644 --- a/src/test/ui/error-codes/E0004-2.stderr +++ b/src/test/ui/error-codes/E0004-2.stderr @@ -1,8 +1,16 @@ error[E0004]: non-exhaustive patterns: `None` and `Some(_)` not covered - --> $DIR/E0004-2.rs:4:11 + --> $DIR/E0004-2.rs:9:11 | LL | match x { } | ^ patterns `None` and `Some(_)` not covered + | + ::: $SRC_DIR/libcore/option.rs:LL:COL + | +LL | None, + | ---- not covered +... +LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T), + | ---- not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms diff --git a/src/test/ui/error-codes/E0005.rs b/src/test/ui/error-codes/E0005.rs index f4730697e1843..75faad80579c6 100644 --- a/src/test/ui/error-codes/E0005.rs +++ b/src/test/ui/error-codes/E0005.rs @@ -1,3 +1,8 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl + fn main() { let x = Some(1); let Some(y) = x; //~ ERROR E0005 diff --git a/src/test/ui/error-codes/E0005.stderr b/src/test/ui/error-codes/E0005.stderr index 577c6e886d523..192b994403191 100644 --- a/src/test/ui/error-codes/E0005.stderr +++ b/src/test/ui/error-codes/E0005.stderr @@ -1,8 +1,13 @@ error[E0005]: refutable pattern in local binding: `None` not covered - --> $DIR/E0005.rs:3:9 + --> $DIR/E0005.rs:8:9 | LL | let Some(y) = x; | ^^^^^^^ pattern `None` not covered + | + ::: $SRC_DIR/libcore/option.rs:LL:COL + | +LL | None, + | ---- not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html diff --git a/src/test/ui/error-codes/E0034.stderr b/src/test/ui/error-codes/E0034.stderr index 6db2ef5051d83..7977e529a11a6 100644 --- a/src/test/ui/error-codes/E0034.stderr +++ b/src/test/ui/error-codes/E0034.stderr @@ -1,8 +1,8 @@ error[E0034]: multiple applicable items in scope - --> $DIR/E0034.rs:20:5 + --> $DIR/E0034.rs:20:11 | LL | Test::foo() - | ^^^^^^^^^ multiple `foo` found + | ^^^ multiple `foo` found | note: candidate #1 is defined in an impl of the trait `Trait1` for the type `Test` --> $DIR/E0034.rs:12:5 diff --git a/src/test/ui/error-codes/E0121.stderr b/src/test/ui/error-codes/E0121.stderr index 5a5c6b40c5afe..ad854837ae5bd 100644 --- a/src/test/ui/error-codes/E0121.stderr +++ b/src/test/ui/error-codes/E0121.stderr @@ -14,7 +14,7 @@ LL | static BAR: _ = "test"; | ^ | | | not allowed in type signatures - | help: replace `_` with the correct type: `&'static str` + | help: replace `_` with the correct type: `&str` error: aborting due to 2 previous errors diff --git a/src/test/ui/error-codes/E0192.rs b/src/test/ui/error-codes/E0192.rs deleted file mode 100644 index c52977e49b457..0000000000000 --- a/src/test/ui/error-codes/E0192.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![feature(optin_builtin_traits)] - -trait Trait { - type Bar; -} - -struct Foo; - -impl !Trait for Foo { } //~ ERROR E0192 - -fn main() { -} diff --git a/src/test/ui/error-codes/E0192.stderr b/src/test/ui/error-codes/E0192.stderr deleted file mode 100644 index 8faa550a50935..0000000000000 --- a/src/test/ui/error-codes/E0192.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0192]: negative impls are only allowed for auto traits (e.g., `Send` and `Sync`) - --> $DIR/E0192.rs:9:1 - | -LL | impl !Trait for Foo { } - | ^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0192`. diff --git a/src/test/ui/error-codes/E0198.rs b/src/test/ui/error-codes/E0198.rs index 00ab0c3562378..041bbe8fdcf69 100644 --- a/src/test/ui/error-codes/E0198.rs +++ b/src/test/ui/error-codes/E0198.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] struct Foo; diff --git a/src/test/ui/error-codes/E0199.rs b/src/test/ui/error-codes/E0199.rs index c95afa3f97d4a..2421bf0a55f65 100644 --- a/src/test/ui/error-codes/E0199.rs +++ b/src/test/ui/error-codes/E0199.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] struct Foo; diff --git a/src/test/ui/error-codes/E0297.rs b/src/test/ui/error-codes/E0297.rs index 27c7960d97731..b26ede9c8e219 100644 --- a/src/test/ui/error-codes/E0297.rs +++ b/src/test/ui/error-codes/E0297.rs @@ -1,3 +1,8 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl + fn main() { let xs : Vec> = vec![Some(1), None]; diff --git a/src/test/ui/error-codes/E0297.stderr b/src/test/ui/error-codes/E0297.stderr index f356a5b954d6d..4a75e9d1771f3 100644 --- a/src/test/ui/error-codes/E0297.stderr +++ b/src/test/ui/error-codes/E0297.stderr @@ -1,8 +1,13 @@ error[E0005]: refutable pattern in `for` loop binding: `None` not covered - --> $DIR/E0297.rs:4:9 + --> $DIR/E0297.rs:9:9 | LL | for Some(x) in xs {} | ^^^^^^^ pattern `None` not covered + | + ::: $SRC_DIR/libcore/option.rs:LL:COL + | +LL | None, + | ---- not covered error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0396-fixed.stderr b/src/test/ui/error-codes/E0396-fixed.stderr index 7222f87da248f..685055525627e 100644 --- a/src/test/ui/error-codes/E0396-fixed.stderr +++ b/src/test/ui/error-codes/E0396-fixed.stderr @@ -4,7 +4,7 @@ error: any use of this value will cause an error LL | const VALUE: u8 = unsafe { *REG_ADDR }; | ---------------------------^^^^^^^^^--- | | - | a memory access tried to interpret some bytes as a pointer + | unable to turn bytes into a pointer | = note: `#[deny(const_err)]` on by default diff --git a/src/test/ui/error-codes/E0423.stderr b/src/test/ui/error-codes/E0423.stderr index 09792845d162c..a985e963e5726 100644 --- a/src/test/ui/error-codes/E0423.stderr +++ b/src/test/ui/error-codes/E0423.stderr @@ -29,20 +29,17 @@ LL | for _ in (std::ops::Range { start: 0, end: 10 }) {} error[E0423]: expected function, tuple struct or tuple variant, found struct `Foo` --> $DIR/E0423.rs:4:13 | -LL | struct Foo { a: bool }; - | ---------------------- `Foo` defined here +LL | struct Foo { a: bool }; + | ---------------------- `Foo` defined here LL | -LL | let f = Foo(); - | ^^^ - | | - | did you mean `Foo { /* fields */ }`? - | help: a function with a similar name exists (notice the capitalization): `foo` +LL | let f = Foo(); + | ^^^ + | | + | did you mean `Foo { /* fields */ }`? + | help: a function with a similar name exists (notice the capitalization): `foo` ... -LL | / fn foo() { -LL | | for _ in std::ops::Range { start: 0, end: 10 } {} -LL | | -LL | | } - | |_- similarly named function `foo` defined here +LL | fn foo() { + | -------- similarly named function `foo` defined here error[E0423]: expected value, found struct `T` --> $DIR/E0423.rs:14:8 diff --git a/src/test/ui/error-codes/E0451.stderr b/src/test/ui/error-codes/E0451.stderr index 655f3a98d7f09..bb92c23e0f600 100644 --- a/src/test/ui/error-codes/E0451.stderr +++ b/src/test/ui/error-codes/E0451.stderr @@ -2,13 +2,13 @@ error[E0451]: field `b` of struct `bar::Foo` is private --> $DIR/E0451.rs:14:21 | LL | let bar::Foo{a, b} = foo; - | ^ field `b` is private + | ^ private field error[E0451]: field `b` of struct `bar::Foo` is private --> $DIR/E0451.rs:18:29 | LL | let f = bar::Foo{ a: 0, b: 0 }; - | ^^^^ field `b` is private + | ^^^^ private field error: aborting due to 2 previous errors diff --git a/src/test/ui/error-codes/E0583.stderr b/src/test/ui/error-codes/E0583.stderr index ef7a48bc8a48f..dbe700355957b 100644 --- a/src/test/ui/error-codes/E0583.stderr +++ b/src/test/ui/error-codes/E0583.stderr @@ -1,10 +1,10 @@ error[E0583]: file not found for module `module_that_doesnt_exist` - --> $DIR/E0583.rs:1:5 + --> $DIR/E0583.rs:1:1 | LL | mod module_that_doesnt_exist; - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: name the file either module_that_doesnt_exist.rs or module_that_doesnt_exist/mod.rs inside the directory "$DIR" + = help: to create the module `module_that_doesnt_exist`, create file "$DIR/module_that_doesnt_exist.rs" error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0603.stderr b/src/test/ui/error-codes/E0603.stderr index 724d04954a3c7..ee902584f56da 100644 --- a/src/test/ui/error-codes/E0603.stderr +++ b/src/test/ui/error-codes/E0603.stderr @@ -2,7 +2,7 @@ error[E0603]: constant `PRIVATE` is private --> $DIR/E0603.rs:6:17 | LL | SomeModule::PRIVATE; - | ^^^^^^^ this constant is private + | ^^^^^^^ private constant | note: the constant `PRIVATE` is defined here --> $DIR/E0603.rs:2:5 diff --git a/src/test/ui/error-codes/E0615.stderr b/src/test/ui/error-codes/E0615.stderr index 772058719ae04..1bc047dd356e0 100644 --- a/src/test/ui/error-codes/E0615.stderr +++ b/src/test/ui/error-codes/E0615.stderr @@ -2,7 +2,12 @@ error[E0615]: attempted to take value of method `method` on type `Foo` --> $DIR/E0615.rs:11:7 | LL | f.method; - | ^^^^^^ help: use parentheses to call the method: `method()` + | ^^^^^^ method, not a field + | +help: use parentheses to call the method + | +LL | f.method(); + | ^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0616.stderr b/src/test/ui/error-codes/E0616.stderr index 556e5db10a944..422bf687e7bd4 100644 --- a/src/test/ui/error-codes/E0616.stderr +++ b/src/test/ui/error-codes/E0616.stderr @@ -1,8 +1,8 @@ error[E0616]: field `x` of struct `a::Foo` is private - --> $DIR/E0616.rs:13:5 + --> $DIR/E0616.rs:13:7 | LL | f.x; - | ^^^ + | ^ private field error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0624.rs b/src/test/ui/error-codes/E0624.rs index 45f72a565ca1b..4c68b70fb165a 100644 --- a/src/test/ui/error-codes/E0624.rs +++ b/src/test/ui/error-codes/E0624.rs @@ -8,5 +8,5 @@ mod inner { fn main() { let foo = inner::Foo; - foo.method(); //~ ERROR method `method` is private [E0624] + foo.method(); //~ ERROR associated function `method` is private [E0624] } diff --git a/src/test/ui/error-codes/E0624.stderr b/src/test/ui/error-codes/E0624.stderr index 01ac24cfbbe12..1d3336fb181a0 100644 --- a/src/test/ui/error-codes/E0624.stderr +++ b/src/test/ui/error-codes/E0624.stderr @@ -1,8 +1,8 @@ -error[E0624]: method `method` is private +error[E0624]: associated function `method` is private --> $DIR/E0624.rs:11:9 | LL | foo.method(); - | ^^^^^^ + | ^^^^^^ private associated function error: aborting due to previous error diff --git a/src/test/ui/error-codes/ex-E0611.stderr b/src/test/ui/error-codes/ex-E0611.stderr index 8bd00a392d4f8..2d22bb395140b 100644 --- a/src/test/ui/error-codes/ex-E0611.stderr +++ b/src/test/ui/error-codes/ex-E0611.stderr @@ -1,8 +1,8 @@ error[E0616]: field `0` of struct `a::Foo` is private - --> $DIR/ex-E0611.rs:11:4 + --> $DIR/ex-E0611.rs:11:6 | LL | y.0; - | ^^^ + | ^ private field error: aborting due to previous error diff --git a/src/test/ui/error-festival.stderr b/src/test/ui/error-festival.stderr index fb5290bf64eb4..7f524230ef006 100644 --- a/src/test/ui/error-festival.stderr +++ b/src/test/ui/error-festival.stderr @@ -8,7 +8,7 @@ error[E0603]: constant `FOO` is private --> $DIR/error-festival.rs:22:10 | LL | foo::FOO; - | ^^^ this constant is private + | ^^^ private constant | note: the constant `FOO` is defined here --> $DIR/error-festival.rs:7:5 diff --git a/src/test/ui/explore-issue-38412.stderr b/src/test/ui/explore-issue-38412.stderr index 4c80989951abc..1855c0b14379d 100644 --- a/src/test/ui/explore-issue-38412.stderr +++ b/src/test/ui/explore-issue-38412.stderr @@ -17,22 +17,22 @@ LL | r.a_unstable_undeclared_pub; = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable error[E0616]: field `b_crate` of struct `pub_and_stability::Record` is private - --> $DIR/explore-issue-38412.rs:31:5 + --> $DIR/explore-issue-38412.rs:31:7 | LL | r.b_crate; - | ^^^^^^^^^ + | ^^^^^^^ private field error[E0616]: field `c_mod` of struct `pub_and_stability::Record` is private - --> $DIR/explore-issue-38412.rs:32:5 + --> $DIR/explore-issue-38412.rs:32:7 | LL | r.c_mod; - | ^^^^^^^ + | ^^^^^ private field error[E0616]: field `d_priv` of struct `pub_and_stability::Record` is private - --> $DIR/explore-issue-38412.rs:33:5 + --> $DIR/explore-issue-38412.rs:33:7 | LL | r.d_priv; - | ^^^^^^^^ + | ^^^^^^ private field error[E0658]: use of unstable library feature 'unstable_undeclared' --> $DIR/explore-issue-38412.rs:37:5 @@ -44,22 +44,22 @@ LL | t.2; = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable error[E0616]: field `3` of struct `pub_and_stability::Tuple` is private - --> $DIR/explore-issue-38412.rs:38:5 + --> $DIR/explore-issue-38412.rs:38:7 | LL | t.3; - | ^^^ + | ^ private field error[E0616]: field `4` of struct `pub_and_stability::Tuple` is private - --> $DIR/explore-issue-38412.rs:39:5 + --> $DIR/explore-issue-38412.rs:39:7 | LL | t.4; - | ^^^ + | ^ private field error[E0616]: field `5` of struct `pub_and_stability::Tuple` is private - --> $DIR/explore-issue-38412.rs:40:5 + --> $DIR/explore-issue-38412.rs:40:7 | LL | t.5; - | ^^^ + | ^ private field error[E0658]: use of unstable library feature 'unstable_undeclared' --> $DIR/explore-issue-38412.rs:44:7 @@ -79,23 +79,23 @@ LL | r.unstable_undeclared(); = note: see issue #38412 for more information = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable -error[E0624]: method `pub_crate` is private +error[E0624]: associated function `pub_crate` is private --> $DIR/explore-issue-38412.rs:50:7 | LL | r.pub_crate(); - | ^^^^^^^^^ + | ^^^^^^^^^ private associated function -error[E0624]: method `pub_mod` is private +error[E0624]: associated function `pub_mod` is private --> $DIR/explore-issue-38412.rs:51:7 | LL | r.pub_mod(); - | ^^^^^^^ + | ^^^^^^^ private associated function -error[E0624]: method `private` is private +error[E0624]: associated function `private` is private --> $DIR/explore-issue-38412.rs:52:7 | LL | r.private(); - | ^^^^^^^ + | ^^^^^^^ private associated function error[E0658]: use of unstable library feature 'unstable_undeclared' --> $DIR/explore-issue-38412.rs:57:7 @@ -115,23 +115,23 @@ LL | t.unstable_undeclared(); = note: see issue #38412 for more information = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable -error[E0624]: method `pub_crate` is private +error[E0624]: associated function `pub_crate` is private --> $DIR/explore-issue-38412.rs:63:7 | LL | t.pub_crate(); - | ^^^^^^^^^ + | ^^^^^^^^^ private associated function -error[E0624]: method `pub_mod` is private +error[E0624]: associated function `pub_mod` is private --> $DIR/explore-issue-38412.rs:64:7 | LL | t.pub_mod(); - | ^^^^^^^ + | ^^^^^^^ private associated function -error[E0624]: method `private` is private +error[E0624]: associated function `private` is private --> $DIR/explore-issue-38412.rs:65:7 | LL | t.private(); - | ^^^^^^^ + | ^^^^^^^ private associated function error: aborting due to 19 previous errors diff --git a/src/test/ui/export-import.stderr b/src/test/ui/export-import.stderr index 8160775ab589e..753424c7f88b8 100644 --- a/src/test/ui/export-import.stderr +++ b/src/test/ui/export-import.stderr @@ -2,7 +2,7 @@ error[E0603]: function `unexported` is private --> $DIR/export-import.rs:1:8 | LL | use m::unexported; - | ^^^^^^^^^^ this function is private + | ^^^^^^^^^^ private function | note: the function `unexported` is defined here --> $DIR/export-import.rs:7:5 diff --git a/src/test/ui/export-tag-variant.stderr b/src/test/ui/export-tag-variant.stderr index f4537a2fb6fae..f73bd454d3592 100644 --- a/src/test/ui/export-tag-variant.stderr +++ b/src/test/ui/export-tag-variant.stderr @@ -2,7 +2,7 @@ error[E0603]: enum `Y` is private --> $DIR/export-tag-variant.rs:7:26 | LL | fn main() { let z = foo::Y::Y1; } - | ^ this enum is private + | ^ private enum | note: the enum `Y` is defined here --> $DIR/export-tag-variant.rs:4:5 diff --git a/src/test/ui/export.stderr b/src/test/ui/export.stderr index 107f531c09a3a..23c29b31c6a8e 100644 --- a/src/test/ui/export.stderr +++ b/src/test/ui/export.stderr @@ -26,7 +26,7 @@ error[E0603]: function `z` is private --> $DIR/export.rs:10:18 | LL | fn main() { foo::z(10); } - | ^ this function is private + | ^ private function | note: the function `z` is defined here --> $DIR/export.rs:5:5 diff --git a/src/test/ui/extern/extern-crate-visibility.stderr b/src/test/ui/extern/extern-crate-visibility.stderr index d0c073d67a4ee..9eeb83ae1a73f 100644 --- a/src/test/ui/extern/extern-crate-visibility.stderr +++ b/src/test/ui/extern/extern-crate-visibility.stderr @@ -2,7 +2,7 @@ error[E0603]: crate import `core` is private --> $DIR/extern-crate-visibility.rs:6:10 | LL | use foo::core::cell; - | ^^^^ this crate import is private + | ^^^^ private crate import | note: the crate import `core` is defined here --> $DIR/extern-crate-visibility.rs:2:5 @@ -14,7 +14,7 @@ error[E0603]: crate import `core` is private --> $DIR/extern-crate-visibility.rs:9:10 | LL | foo::core::cell::Cell::new(0); - | ^^^^ this crate import is private + | ^^^^ private crate import | note: the crate import `core` is defined here --> $DIR/extern-crate-visibility.rs:2:5 diff --git a/src/test/ui/extern/extern-types-unsized.stderr b/src/test/ui/extern/extern-types-unsized.stderr index 0c9165fd9585d..871757ec7b0c6 100644 --- a/src/test/ui/extern/extern-types-unsized.stderr +++ b/src/test/ui/extern/extern-types-unsized.stderr @@ -2,15 +2,17 @@ error[E0277]: the size for values of type `A` cannot be known at compilation tim --> $DIR/extern-types-unsized.rs:22:20 | LL | fn assert_sized() { } - | ------------ -- help: consider relaxing the implicit `Sized` restriction: `: ?Sized` - | | - | required by this bound in `assert_sized` + | ------------ - required by this bound in `assert_sized` ... LL | assert_sized::(); | ^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `A` = note: to learn more, visit +help: consider relaxing the implicit `Sized` restriction + | +LL | fn assert_sized() { } + | ^^^^^^^^ error[E0277]: the size for values of type `A` cannot be known at compilation time --> $DIR/extern-types-unsized.rs:25:5 diff --git a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.rs b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.rs index f0cc9ea70550e..d2e52299c0d86 100644 --- a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.rs +++ b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.rs @@ -1,3 +1,8 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl + #![feature(never_type)] fn foo() -> Result { diff --git a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr index 08c36cece4cf9..c2dd90b91e700 100644 --- a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr +++ b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr @@ -1,8 +1,13 @@ error[E0005]: refutable pattern in local binding: `Err(_)` not covered - --> $DIR/feature-gate-exhaustive-patterns.rs:8:9 + --> $DIR/feature-gate-exhaustive-patterns.rs:13:9 | LL | let Ok(_x) = foo(); | ^^^^^^ pattern `Err(_)` not covered + | + ::: $SRC_DIR/libcore/result.rs:LL:COL + | +LL | Err(#[stable(feature = "rust1", since = "1.0.0")] E), + | --- not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html diff --git a/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr b/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr index 490d29ad8a35f..1553d0531dc09 100644 --- a/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr +++ b/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr @@ -13,8 +13,8 @@ error[E0658]: negative trait bounds are not yet fully implemented; use marker ty LL | impl !AutoDummyTrait for DummyStruct {} | ^^^^^^^^^^^^^^^ | - = note: see issue #13231 for more information - = help: add `#![feature(optin_builtin_traits)]` to the crate attributes to enable + = note: see issue #68318 for more information + = help: add `#![feature(negative_impls)]` to the crate attributes to enable error: aborting due to 2 previous errors diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr index 1e039f17a0d11..1517a7a5c731a 100644 --- a/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr +++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr @@ -1,10 +1,8 @@ -error[E0658]: attributes starting with `rustc` are reserved for use by the `rustc` compiler +error: attributes starting with `rustc` are reserved for use by the `rustc` compiler --> $DIR/feature-gate-rustc-attrs.rs:8:3 | LL | #[rustc::unknown] | ^^^^^ - | - = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable error: expected attribute, found macro `rustc::unknown` --> $DIR/feature-gate-rustc-attrs.rs:8:3 @@ -12,13 +10,11 @@ error: expected attribute, found macro `rustc::unknown` LL | #[rustc::unknown] | ^^^^^^^^^^^^^^ not an attribute -error[E0658]: attributes starting with `rustc` are reserved for use by the `rustc` compiler +error: attributes starting with `rustc` are reserved for use by the `rustc` compiler --> $DIR/feature-gate-rustc-attrs.rs:13:12 | LL | #[unknown::rustc] | ^^^^^ - | - = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable error: expected attribute, found macro `unknown::rustc` --> $DIR/feature-gate-rustc-attrs.rs:13:3 @@ -26,13 +22,11 @@ error: expected attribute, found macro `unknown::rustc` LL | #[unknown::rustc] | ^^^^^^^^^^^^^^ not an attribute -error[E0658]: attributes starting with `rustc` are reserved for use by the `rustc` compiler +error: attributes starting with `rustc` are reserved for use by the `rustc` compiler --> $DIR/feature-gate-rustc-attrs.rs:20:3 | LL | #[rustc_unknown] | ^^^^^^^^^^^^^ - | - = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable error: cannot find attribute `rustc_unknown` in this scope --> $DIR/feature-gate-rustc-attrs.rs:20:3 diff --git a/src/test/ui/fn-in-pat.rs b/src/test/ui/fn-in-pat.rs index b83252012b8f8..2d7c86b8666f8 100644 --- a/src/test/ui/fn-in-pat.rs +++ b/src/test/ui/fn-in-pat.rs @@ -8,7 +8,7 @@ fn hof(_: F) where F: FnMut(()) {} fn ice() { hof(|c| match c { - A::new() => (), //~ ERROR expected tuple struct or tuple variant, found method + A::new() => (), //~ ERROR expected tuple struct or tuple variant, found associated function _ => () }) } diff --git a/src/test/ui/fn-in-pat.stderr b/src/test/ui/fn-in-pat.stderr index 5d6632f2fc2ec..2482d632695cc 100644 --- a/src/test/ui/fn-in-pat.stderr +++ b/src/test/ui/fn-in-pat.stderr @@ -1,4 +1,4 @@ -error[E0164]: expected tuple struct or tuple variant, found method `A::new` +error[E0164]: expected tuple struct or tuple variant, found associated function `A::new` --> $DIR/fn-in-pat.rs:11:9 | LL | A::new() => (), diff --git a/src/test/ui/generator/auto-trait-regions.nll.stderr b/src/test/ui/generator/auto-trait-regions.nll.stderr index bf87aea0d4c1a..794369a8dc02b 100644 --- a/src/test/ui/generator/auto-trait-regions.nll.stderr +++ b/src/test/ui/generator/auto-trait-regions.nll.stderr @@ -1,5 +1,5 @@ error[E0716]: temporary value dropped while borrowed - --> $DIR/auto-trait-regions.rs:45:24 + --> $DIR/auto-trait-regions.rs:46:24 | LL | let a = A(&mut true, &mut true, No); | ^^^^ - temporary value is freed at the end of this statement @@ -12,7 +12,7 @@ LL | assert_foo(a); = note: consider using a `let` binding to create a longer lived value error[E0716]: temporary value dropped while borrowed - --> $DIR/auto-trait-regions.rs:45:35 + --> $DIR/auto-trait-regions.rs:46:35 | LL | let a = A(&mut true, &mut true, No); | ^^^^ - temporary value is freed at the end of this statement @@ -25,13 +25,13 @@ LL | assert_foo(a); = note: consider using a `let` binding to create a longer lived value error: higher-ranked subtype error - --> $DIR/auto-trait-regions.rs:30:5 + --> $DIR/auto-trait-regions.rs:31:5 | LL | assert_foo(gen); | ^^^^^^^^^^^^^^^ error: higher-ranked subtype error - --> $DIR/auto-trait-regions.rs:49:5 + --> $DIR/auto-trait-regions.rs:50:5 | LL | assert_foo(gen); | ^^^^^^^^^^^^^^^ diff --git a/src/test/ui/generator/auto-trait-regions.rs b/src/test/ui/generator/auto-trait-regions.rs index dbd8965dcf0d0..1e77d8058a72b 100644 --- a/src/test/ui/generator/auto-trait-regions.rs +++ b/src/test/ui/generator/auto-trait-regions.rs @@ -1,5 +1,6 @@ #![feature(generators)] #![feature(optin_builtin_traits)] +#![feature(negative_impls)] auto trait Foo {} diff --git a/src/test/ui/generator/auto-trait-regions.stderr b/src/test/ui/generator/auto-trait-regions.stderr index 29a3907d93c84..5ec462e10465f 100644 --- a/src/test/ui/generator/auto-trait-regions.stderr +++ b/src/test/ui/generator/auto-trait-regions.stderr @@ -1,5 +1,5 @@ error: implementation of `Foo` is not general enough - --> $DIR/auto-trait-regions.rs:30:5 + --> $DIR/auto-trait-regions.rs:31:5 | LL | auto trait Foo {} | ----------------- trait `Foo` defined here @@ -11,7 +11,7 @@ LL | assert_foo(gen); = note: ...but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough - --> $DIR/auto-trait-regions.rs:30:5 + --> $DIR/auto-trait-regions.rs:31:5 | LL | auto trait Foo {} | ----------------- trait `Foo` defined here @@ -23,7 +23,7 @@ LL | assert_foo(gen); = note: ...but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough - --> $DIR/auto-trait-regions.rs:49:5 + --> $DIR/auto-trait-regions.rs:50:5 | LL | auto trait Foo {} | ----------------- trait `Foo` defined here @@ -35,7 +35,7 @@ LL | assert_foo(gen); = note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2` error: implementation of `Foo` is not general enough - --> $DIR/auto-trait-regions.rs:49:5 + --> $DIR/auto-trait-regions.rs:50:5 | LL | auto trait Foo {} | ----------------- trait `Foo` defined here diff --git a/src/test/ui/generator/discriminant.rs b/src/test/ui/generator/discriminant.rs new file mode 100644 index 0000000000000..8a0f8a380ab59 --- /dev/null +++ b/src/test/ui/generator/discriminant.rs @@ -0,0 +1,134 @@ +//! Tests that generator discriminant sizes and ranges are chosen optimally and that they are +//! reflected in the output of `mem::discriminant`. + +// run-pass + +#![feature(generators, generator_trait, core_intrinsics)] + +use std::intrinsics::discriminant_value; +use std::marker::Unpin; +use std::mem::size_of_val; +use std::{cmp, ops::*}; + +macro_rules! yield25 { + ($e:expr) => { + yield $e; + yield $e; + yield $e; + yield $e; + yield $e; + + yield $e; + yield $e; + yield $e; + yield $e; + yield $e; + + yield $e; + yield $e; + yield $e; + yield $e; + yield $e; + + yield $e; + yield $e; + yield $e; + yield $e; + yield $e; + + yield $e; + yield $e; + yield $e; + yield $e; + yield $e; + }; +} + +/// Yields 250 times. +macro_rules! yield250 { + () => { + yield250!(()) + }; + + ($e:expr) => { + yield25!($e); + yield25!($e); + yield25!($e); + yield25!($e); + yield25!($e); + + yield25!($e); + yield25!($e); + yield25!($e); + yield25!($e); + yield25!($e); + }; +} + +fn cycle(gen: impl Generator<()> + Unpin, expected_max_discr: u64) { + let mut gen = Box::pin(gen); + let mut max_discr = 0; + loop { + max_discr = cmp::max(max_discr, discriminant_value(gen.as_mut().get_mut())); + match gen.as_mut().resume(()) { + GeneratorState::Yielded(_) => {} + GeneratorState::Complete(_) => { + assert_eq!(max_discr, expected_max_discr); + return; + } + } + } +} + +fn main() { + // Has only one invalid discr. value. + let gen_u8_tiny_niche = || { + || { + // 3 reserved variants + + yield250!(); // 253 variants + + yield; // 254 + yield; // 255 + } + }; + + // Uses all values in the u8 discriminant. + let gen_u8_full = || { + || { + // 3 reserved variants + + yield250!(); // 253 variants + + yield; // 254 + yield; // 255 + yield; // 256 + } + }; + + // Barely needs a u16 discriminant. + let gen_u16 = || { + || { + // 3 reserved variants + + yield250!(); // 253 variants + + yield; // 254 + yield; // 255 + yield; // 256 + yield; // 257 + } + }; + + assert_eq!(size_of_val(&gen_u8_tiny_niche()), 1); + assert_eq!(size_of_val(&Some(gen_u8_tiny_niche())), 1); // uses niche + assert_eq!(size_of_val(&Some(Some(gen_u8_tiny_niche()))), 2); // cannot use niche anymore + assert_eq!(size_of_val(&gen_u8_full()), 1); + assert_eq!(size_of_val(&Some(gen_u8_full())), 2); // cannot use niche + assert_eq!(size_of_val(&gen_u16()), 2); + assert_eq!(size_of_val(&Some(gen_u16())), 2); // uses niche + + cycle(gen_u8_tiny_niche(), 254); + cycle(gen_u8_full(), 255); + cycle(gen_u16(), 256); +} diff --git a/src/test/ui/generator-yielding-or-returning-itself.rs b/src/test/ui/generator/generator-yielding-or-returning-itself.rs similarity index 100% rename from src/test/ui/generator-yielding-or-returning-itself.rs rename to src/test/ui/generator/generator-yielding-or-returning-itself.rs diff --git a/src/test/ui/generator-yielding-or-returning-itself.stderr b/src/test/ui/generator/generator-yielding-or-returning-itself.stderr similarity index 100% rename from src/test/ui/generator-yielding-or-returning-itself.stderr rename to src/test/ui/generator/generator-yielding-or-returning-itself.stderr diff --git a/src/test/ui/generator/issue-69039.rs b/src/test/ui/generator/issue-69039.rs index 60004f3b0aeee..ccc141860aa5f 100644 --- a/src/test/ui/generator/issue-69039.rs +++ b/src/test/ui/generator/issue-69039.rs @@ -4,11 +4,15 @@ use std::ops::{Generator, GeneratorState}; +fn mkstr(my_name: String, my_mood: String) -> String { + format!("{} is {}", my_name.trim(), my_mood.trim()) +} + fn my_scenario() -> impl Generator { |_arg: String| { let my_name = yield "What is your name?"; let my_mood = yield "How are you feeling?"; - format!("{} is {}", my_name.trim(), my_mood.trim()) + mkstr(my_name, my_mood) } } diff --git a/src/test/ui/generator/resume-arg-size.rs b/src/test/ui/generator/resume-arg-size.rs new file mode 100644 index 0000000000000..4f08ac0702bdb --- /dev/null +++ b/src/test/ui/generator/resume-arg-size.rs @@ -0,0 +1,28 @@ +#![feature(generators)] + +// run-pass + +use std::mem::size_of_val; + +fn main() { + // Generator taking a `Copy`able resume arg. + let gen_copy = |mut x: usize| { + loop { + drop(x); + x = yield; + } + }; + + // Generator taking a non-`Copy` resume arg. + let gen_move = |mut x: Box| { + loop { + drop(x); + x = yield; + } + }; + + // Neither of these generators have the resume arg live across the `yield`, so they should be + // 4 Bytes in size (only storing the discriminant) + assert_eq!(size_of_val(&gen_copy), 1); + assert_eq!(size_of_val(&gen_move), 1); +} diff --git a/src/test/ui/generator/size-moved-locals.rs b/src/test/ui/generator/size-moved-locals.rs index 2864fbb2f3c8d..74c60d98154dd 100644 --- a/src/test/ui/generator/size-moved-locals.rs +++ b/src/test/ui/generator/size-moved-locals.rs @@ -58,7 +58,7 @@ fn overlap_move_points() -> impl Generator { } } -fn overlap_x_and_y() -> impl Generator{ +fn overlap_x_and_y() -> impl Generator { static || { let x = Foo([0; FOO_SIZE]); yield; @@ -70,8 +70,8 @@ fn overlap_x_and_y() -> impl Generator{ } fn main() { - assert_eq!(1028, std::mem::size_of_val(&move_before_yield())); - assert_eq!(1032, std::mem::size_of_val(&move_before_yield_with_noop())); - assert_eq!(2056, std::mem::size_of_val(&overlap_move_points())); - assert_eq!(1032, std::mem::size_of_val(&overlap_x_and_y())); + assert_eq!(1025, std::mem::size_of_val(&move_before_yield())); + assert_eq!(1026, std::mem::size_of_val(&move_before_yield_with_noop())); + assert_eq!(2051, std::mem::size_of_val(&overlap_move_points())); + assert_eq!(1026, std::mem::size_of_val(&overlap_x_and_y())); } diff --git a/src/test/ui/generator/too-many-parameters.stderr b/src/test/ui/generator/too-many-parameters.stderr index a297ee43de969..22d40db3f2678 100644 --- a/src/test/ui/generator/too-many-parameters.stderr +++ b/src/test/ui/generator/too-many-parameters.stderr @@ -6,3 +6,4 @@ LL | |(), ()| { error: aborting due to previous error +For more information about this error, try `rustc --explain E0628`. diff --git a/src/test/ui/generic-associated-types/iterable.rs b/src/test/ui/generic-associated-types/iterable.rs index 105ab4a8adc38..616421112db67 100644 --- a/src/test/ui/generic-associated-types/iterable.rs +++ b/src/test/ui/generic-associated-types/iterable.rs @@ -1,3 +1,8 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl + #![allow(incomplete_features)] #![feature(generic_associated_types)] diff --git a/src/test/ui/generic-associated-types/iterable.stderr b/src/test/ui/generic-associated-types/iterable.stderr index ccb1c9bcc7f4e..e18c6cec64e71 100644 --- a/src/test/ui/generic-associated-types/iterable.stderr +++ b/src/test/ui/generic-associated-types/iterable.stderr @@ -1,10 +1,15 @@ error[E0271]: type mismatch resolving `for<'a> < as Iterable>::Iter<'a> as std::iter::Iterator>::Item == as Iterable>::Item<'a>` - --> $DIR/iterable.rs:15:5 + --> $DIR/iterable.rs:20:5 | LL | impl Iterable for Vec { | --------------------------- in this `impl` item LL | type Item<'a> where T: 'a = as Iterator>::Item; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found associated type + | + ::: $SRC_DIR/libcore/iter/traits/iterator.rs:LL:COL + | +LL | type Item; + | ---- associated type defined here | = note: expected reference `&T` found associated type ` as Iterable>::Item<'_>` @@ -12,12 +17,17 @@ LL | type Item<'a> where T: 'a = as Iterator>::Item = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0271]: type mismatch resolving `for<'a> <<[T] as Iterable>::Iter<'a> as std::iter::Iterator>::Item == <[T] as Iterable>::Item<'a>` - --> $DIR/iterable.rs:27:5 + --> $DIR/iterable.rs:32:5 | LL | impl Iterable for [T] { | ------------------------ in this `impl` item LL | type Item<'a> where T: 'a = as Iterator>::Item; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found associated type + | + ::: $SRC_DIR/libcore/iter/traits/iterator.rs:LL:COL + | +LL | type Item; + | ---- associated type defined here | = note: expected reference `&T` found associated type `<[T] as Iterable>::Item<'_>` @@ -25,7 +35,7 @@ LL | type Item<'a> where T: 'a = as Iterator>::Item = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0271]: type mismatch resolving `for<'a> < as Iterable>::Iter<'a> as std::iter::Iterator>::Item == as Iterable>::Item<'a>` - --> $DIR/iterable.rs:19:30 + --> $DIR/iterable.rs:24:30 | LL | trait Iterable { | -------------- required by `Iterable` @@ -39,7 +49,7 @@ LL | fn iter<'a>(&'a self) -> Self::Iter<'a> { = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0271]: type mismatch resolving `for<'a> <<[T] as Iterable>::Iter<'a> as std::iter::Iterator>::Item == <[T] as Iterable>::Item<'a>` - --> $DIR/iterable.rs:31:30 + --> $DIR/iterable.rs:36:30 | LL | trait Iterable { | -------------- required by `Iterable` diff --git a/src/test/ui/glob-resolve1.stderr b/src/test/ui/glob-resolve1.stderr index 3db24431586da..efbd53fd223a4 100644 --- a/src/test/ui/glob-resolve1.stderr +++ b/src/test/ui/glob-resolve1.stderr @@ -47,7 +47,7 @@ error[E0412]: cannot find type `A` in this scope --> $DIR/glob-resolve1.rs:28:11 | LL | pub enum B { B1 } - | ----------------- similarly named enum `B` defined here + | ---------- similarly named enum `B` defined here ... LL | foo::(); | ^ @@ -65,7 +65,7 @@ error[E0412]: cannot find type `C` in this scope --> $DIR/glob-resolve1.rs:29:11 | LL | pub enum B { B1 } - | ----------------- similarly named enum `B` defined here + | ---------- similarly named enum `B` defined here ... LL | foo::(); | ^ @@ -83,7 +83,7 @@ error[E0412]: cannot find type `D` in this scope --> $DIR/glob-resolve1.rs:30:11 | LL | pub enum B { B1 } - | ----------------- similarly named enum `B` defined here + | ---------- similarly named enum `B` defined here ... LL | foo::(); | ^ diff --git a/src/test/ui/hygiene/fields.stderr b/src/test/ui/hygiene/fields.stderr index 89deef492020d..6d784408016f5 100644 --- a/src/test/ui/hygiene/fields.stderr +++ b/src/test/ui/hygiene/fields.stderr @@ -2,7 +2,7 @@ error: type `foo::S` is private --> $DIR/fields.rs:15:17 | LL | let s = S { x: 0 }; - | ^^^^^^^^^^ + | ^^^^^^^^^^ private type ... LL | let s = foo::m!(S, x); | ------------- in this macro invocation @@ -13,7 +13,7 @@ error: type `foo::S` is private --> $DIR/fields.rs:16:17 | LL | let _ = s.x; - | ^ + | ^ private type ... LL | let s = foo::m!(S, x); | ------------- in this macro invocation @@ -24,7 +24,7 @@ error: type `foo::T` is private --> $DIR/fields.rs:18:17 | LL | let t = T(0); - | ^^^^ + | ^^^^ private type ... LL | let s = foo::m!(S, x); | ------------- in this macro invocation @@ -35,7 +35,7 @@ error: type `foo::T` is private --> $DIR/fields.rs:19:17 | LL | let _ = t.0; - | ^ + | ^ private type ... LL | let s = foo::m!(S, x); | ------------- in this macro invocation diff --git a/src/test/ui/hygiene/impl_items.stderr b/src/test/ui/hygiene/impl_items.stderr index 85ee9f4cbf3e6..8ac59263cf21a 100644 --- a/src/test/ui/hygiene/impl_items.stderr +++ b/src/test/ui/hygiene/impl_items.stderr @@ -2,7 +2,7 @@ error: type `for<'r> fn(&'r foo::S) {foo::S::f}` is private --> $DIR/impl_items.rs:12:23 | LL | let _: () = S.f(); - | ^ + | ^ private type ... LL | foo::m!(); | ---------- in this macro invocation diff --git a/src/test/ui/hygiene/intercrate.stderr b/src/test/ui/hygiene/intercrate.stderr index 3912ca337fbec..c27ba74a263e0 100644 --- a/src/test/ui/hygiene/intercrate.stderr +++ b/src/test/ui/hygiene/intercrate.stderr @@ -2,7 +2,7 @@ error: type `fn() -> u32 {intercrate::foo::bar::f}` is private --> $DIR/intercrate.rs:10:16 | LL | assert_eq!(intercrate::foo::m!(), 1); - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ private type | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/hygiene/macro-metavars-legacy.rs b/src/test/ui/hygiene/macro-metavars-legacy.rs new file mode 100644 index 0000000000000..09070f0f561a6 --- /dev/null +++ b/src/test/ui/hygiene/macro-metavars-legacy.rs @@ -0,0 +1,29 @@ +// Ensure macro metavariables are compared with legacy hygiene + +#![feature(rustc_attrs)] + +// run-pass + +macro_rules! make_mac { + ( $($dollar:tt $arg:ident),+ ) => { + macro_rules! mac { + ( $($dollar $arg : ident),+ ) => { + $( $dollar $arg )-+ + } + } + } +} + +macro_rules! show_hygiene { + ( $dollar:tt $arg:ident ) => { + make_mac!($dollar $arg, $dollar arg); + } +} + +show_hygiene!( $arg ); + +fn main() { + let x = 5; + let y = 3; + assert_eq!(2, mac!(x, y)); +} diff --git a/src/test/ui/hygiene/macro-metavars-transparent.rs b/src/test/ui/hygiene/macro-metavars-transparent.rs new file mode 100644 index 0000000000000..e475b5728a098 --- /dev/null +++ b/src/test/ui/hygiene/macro-metavars-transparent.rs @@ -0,0 +1,24 @@ +// Ensure macro metavariables are not compared without removing transparent +// marks. + +#![feature(rustc_attrs)] + +// run-pass + +#[rustc_macro_transparency = "transparent"] +macro_rules! k { + ($($s:tt)*) => { + macro_rules! m { + ($y:tt) => { + $($s)* + } + } + } +} + +k!(1 + $y); + +fn main() { + let x = 2; + assert_eq!(3, m!(x)); +} diff --git a/src/test/ui/hygiene/nested_macro_privacy.stderr b/src/test/ui/hygiene/nested_macro_privacy.stderr index 6e78cb86d80f4..482957a326437 100644 --- a/src/test/ui/hygiene/nested_macro_privacy.stderr +++ b/src/test/ui/hygiene/nested_macro_privacy.stderr @@ -1,8 +1,8 @@ error[E0616]: field `i` of struct `foo::S` is private - --> $DIR/nested_macro_privacy.rs:15:5 + --> $DIR/nested_macro_privacy.rs:15:18 | LL | S::default().i; - | ^^^^^^^^^^^^^^ + | ^ private field error: aborting due to previous error diff --git a/src/test/ui/hygiene/privacy.stderr b/src/test/ui/hygiene/privacy.stderr index 0649dc0ec5836..70a24304dda33 100644 --- a/src/test/ui/hygiene/privacy.stderr +++ b/src/test/ui/hygiene/privacy.stderr @@ -2,7 +2,7 @@ error[E0603]: function `f` is private --> $DIR/privacy.rs:16:14 | LL | foo::f() - | ^ this function is private + | ^ private function | note: the function `f` is defined here --> $DIR/privacy.rs:4:5 diff --git a/src/test/ui/hygiene/rustc-macro-transparency.stderr b/src/test/ui/hygiene/rustc-macro-transparency.stderr index 45a2efebbb8da..024ce8207601e 100644 --- a/src/test/ui/hygiene/rustc-macro-transparency.stderr +++ b/src/test/ui/hygiene/rustc-macro-transparency.stderr @@ -8,13 +8,23 @@ error[E0423]: expected value, found macro `semitransparent` --> $DIR/rustc-macro-transparency.rs:29:5 | LL | semitransparent; - | ^^^^^^^^^^^^^^^ help: use `!` to invoke the macro: `semitransparent!` + | ^^^^^^^^^^^^^^^ + | +help: use `!` to invoke the macro + | +LL | semitransparent!; + | ^ error[E0423]: expected value, found macro `opaque` --> $DIR/rustc-macro-transparency.rs:30:5 | LL | opaque; - | ^^^^^^ help: use `!` to invoke the macro: `opaque!` + | ^^^^^^ + | +help: use `!` to invoke the macro + | +LL | opaque!; + | ^ error: aborting due to 3 previous errors diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr index c0ca341385df5..b5135b53e1890 100644 --- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr +++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr @@ -83,6 +83,16 @@ error[E0599]: no method named `method` found for struct `std::rc::Rc<&mut std::b | LL | std::rc::Rc::new(&mut Box::new(&1i32)).method(); | ^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&i32>>` + | + ::: $DIR/auxiliary/no_method_suggested_traits.rs:8:12 + | +LL | fn method(&self) {} + | ------ + | | + | the method is available for `std::boxed::Box>>` here + | the method is available for `std::pin::Pin>>` here + | the method is available for `std::sync::Arc>>` here + | the method is available for `std::rc::Rc>>` here | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope; perhaps add a `use` for it: diff --git a/src/test/ui/implicit-method-bind.stderr b/src/test/ui/implicit-method-bind.stderr index 968272d4d2c19..c6af47805ea5b 100644 --- a/src/test/ui/implicit-method-bind.stderr +++ b/src/test/ui/implicit-method-bind.stderr @@ -2,7 +2,12 @@ error[E0615]: attempted to take value of method `abs` on type `i32` --> $DIR/implicit-method-bind.rs:2:20 | LL | let _f = 10i32.abs; - | ^^^ help: use parentheses to call the method: `abs()` + | ^^^ method, not a field + | +help: use parentheses to call the method + | +LL | let _f = 10i32.abs(); + | ^^ error: aborting due to previous error diff --git a/src/test/ui/import.stderr b/src/test/ui/import.stderr index 5219ffacd15c0..797712e2db99e 100644 --- a/src/test/ui/import.stderr +++ b/src/test/ui/import.stderr @@ -17,7 +17,7 @@ error[E0603]: unresolved item import `foo` is private --> $DIR/import.rs:15:10 | LL | zed::foo(); - | ^^^ this unresolved item import is private + | ^^^ private unresolved item import | note: the unresolved item import `foo` is defined here --> $DIR/import.rs:10:9 diff --git a/src/test/ui/imports/issue-55884-2.stderr b/src/test/ui/imports/issue-55884-2.stderr index f16d2adb3656e..5adbc4b66d133 100644 --- a/src/test/ui/imports/issue-55884-2.stderr +++ b/src/test/ui/imports/issue-55884-2.stderr @@ -2,13 +2,28 @@ error[E0603]: struct import `ParseOptions` is private --> $DIR/issue-55884-2.rs:12:17 | LL | pub use parser::ParseOptions; - | ^^^^^^^^^^^^ this struct import is private + | ^^^^^^^^^^^^ private struct import | -note: the struct import `ParseOptions` is defined here +note: the struct import `ParseOptions` is defined here... --> $DIR/issue-55884-2.rs:9:9 | LL | use ParseOptions; | ^^^^^^^^^^^^ +note: ...and refers to the struct import `ParseOptions` which is defined here... + --> $DIR/issue-55884-2.rs:12:9 + | +LL | pub use parser::ParseOptions; + | ^^^^^^^^^^^^^^^^^^^^ consider importing it directly +note: ...and refers to the struct import `ParseOptions` which is defined here... + --> $DIR/issue-55884-2.rs:6:13 + | +LL | pub use options::*; + | ^^^^^^^^^^ consider importing it directly +note: ...and refers to the struct `ParseOptions` which is defined here + --> $DIR/issue-55884-2.rs:2:5 + | +LL | pub struct ParseOptions {} + | ^^^^^^^^^^^^^^^^^^^^^^^ consider importing it directly error: aborting due to previous error diff --git a/src/test/ui/imports/issue-62767.rs b/src/test/ui/imports/issue-62767.rs new file mode 100644 index 0000000000000..984d3f0ca92f4 --- /dev/null +++ b/src/test/ui/imports/issue-62767.rs @@ -0,0 +1,15 @@ +// check-pass + +mod m { + pub enum Same { + Same, + } +} + +use m::*; + +// The variant `Same` introduced by this import is not considered when resolving the prefix +// `Same::` during import validation (issue #62767). +use Same::Same; + +fn main() {} diff --git a/src/test/ui/imports/reexports.stderr b/src/test/ui/imports/reexports.stderr index 7b0d63574ec8e..79c8e1130c87a 100644 --- a/src/test/ui/imports/reexports.stderr +++ b/src/test/ui/imports/reexports.stderr @@ -14,25 +14,35 @@ error[E0603]: module import `foo` is private --> $DIR/reexports.rs:33:15 | LL | use b::a::foo::S; - | ^^^ this module import is private + | ^^^ private module import | -note: the module import `foo` is defined here +note: the module import `foo` is defined here... --> $DIR/reexports.rs:21:17 | LL | pub use super::foo; // This is OK since the value `foo` is visible enough. | ^^^^^^^^^^ +note: ...and refers to the module `foo` which is defined here + --> $DIR/reexports.rs:16:5 + | +LL | mod foo { + | ^^^^^^^ error[E0603]: module import `foo` is private --> $DIR/reexports.rs:34:15 | LL | use b::b::foo::S as T; - | ^^^ this module import is private + | ^^^ private module import | -note: the module import `foo` is defined here +note: the module import `foo` is defined here... --> $DIR/reexports.rs:26:17 | LL | pub use super::*; // This is also OK since the value `foo` is visible enough. | ^^^^^^^^ +note: ...and refers to the module `foo` which is defined here + --> $DIR/reexports.rs:16:5 + | +LL | mod foo { + | ^^^^^^^ warning: glob import doesn't reexport anything because no candidate is public enough --> $DIR/reexports.rs:9:17 diff --git a/src/test/ui/imports/unresolved-imports-used.stderr b/src/test/ui/imports/unresolved-imports-used.stderr index 69765b9227d6e..ddf3608933909 100644 --- a/src/test/ui/imports/unresolved-imports-used.stderr +++ b/src/test/ui/imports/unresolved-imports-used.stderr @@ -38,7 +38,7 @@ error[E0603]: function `quz` is private --> $DIR/unresolved-imports-used.rs:9:10 | LL | use qux::quz; - | ^^^ this function is private + | ^^^ private function | note: the function `quz` is defined here --> $DIR/unresolved-imports-used.rs:5:4 diff --git a/src/test/ui/init-large-type.rs b/src/test/ui/init-large-type.rs index a304fc9356b51..ce905572f2a8c 100644 --- a/src/test/ui/init-large-type.rs +++ b/src/test/ui/init-large-type.rs @@ -1,3 +1,4 @@ +// compile-flags: -O // run-pass #![allow(unused_must_use)] @@ -10,17 +11,13 @@ #![feature(intrinsics)] -use std::thread; - -extern "rust-intrinsic" { - pub fn init() -> T; -} +use std::{mem, thread}; const SIZE: usize = 1024 * 1024; fn main() { // do the test in a new thread to avoid (spurious?) stack overflows thread::spawn(|| { - let _memory: [u8; SIZE] = unsafe { init() }; + let _memory: [u8; SIZE] = unsafe { mem::zeroed() }; }).join(); } diff --git a/src/test/ui/init-unsafe.rs b/src/test/ui/init-unsafe.rs deleted file mode 100644 index 3d65cfc234092..0000000000000 --- a/src/test/ui/init-unsafe.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![allow(deprecated)] -#![feature(core_intrinsics)] - -use std::intrinsics::{init}; - -// Test that the `init` intrinsic is really unsafe -pub fn main() { - let stuff = init::(); //~ ERROR call to unsafe function is unsafe -} diff --git a/src/test/ui/init-unsafe.stderr b/src/test/ui/init-unsafe.stderr deleted file mode 100644 index e1126316af34e..0000000000000 --- a/src/test/ui/init-unsafe.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/init-unsafe.rs:8:17 - | -LL | let stuff = init::(); - | ^^^^^^^^^^^^^^^ call to unsafe function - | - = note: consult the function's documentation for information on how to avoid undefined behavior - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/intrinsics/intrinsic-move-val.rs b/src/test/ui/intrinsics/intrinsic-move-val.rs index 75b4ec365fe03..b672f1ed26e8d 100644 --- a/src/test/ui/intrinsics/intrinsic-move-val.rs +++ b/src/test/ui/intrinsics/intrinsic-move-val.rs @@ -5,7 +5,6 @@ mod rusti { extern "rust-intrinsic" { - pub fn init() -> T; pub fn move_val_init(dst: *mut T, src: T); } } @@ -15,17 +14,17 @@ pub fn main() { // sanity check check_drops_state(0, None); - let mut x: Box = box D(1); - assert_eq!(x.0, 1); + let mut x: Option> = Some(box D(1)); + assert_eq!(x.as_ref().unwrap().0, 1); // A normal overwrite, to demonstrate `check_drops_state`. - x = box D(2); + x = Some(box D(2)); // At this point, one destructor has run, because the // overwrite of `x` drops its initial value. check_drops_state(1, Some(1)); - let mut y: Box = rusti::init(); + let mut y: Option> = std::mem::zeroed(); // An initial binding does not overwrite anything. check_drops_state(1, Some(1)); @@ -51,9 +50,9 @@ pub fn main() { // during such a destructor call. We do so after the end of // this scope. - assert_eq!(y.0, 2); - y.0 = 3; - assert_eq!(y.0, 3); + assert_eq!(y.as_ref().unwrap().0, 2); + y.as_mut().unwrap().0 = 3; + assert_eq!(y.as_ref().unwrap().0, 3); check_drops_state(1, Some(1)); } diff --git a/src/test/ui/intrinsics/intrinsic-uninit.rs b/src/test/ui/intrinsics/intrinsic-uninit.rs deleted file mode 100644 index 9555efb639b50..0000000000000 --- a/src/test/ui/intrinsics/intrinsic-uninit.rs +++ /dev/null @@ -1,13 +0,0 @@ -// run-pass -// pretty-expanded FIXME #23616 - -#![feature(intrinsics)] - -mod rusti { - extern "rust-intrinsic" { - pub fn uninit() -> T; - } -} -pub fn main() { - let _a : isize = unsafe {rusti::uninit()}; -} diff --git a/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr b/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr index c95df5b4534c1..52296042eb4a7 100644 --- a/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr +++ b/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr @@ -1,10 +1,10 @@ error[E0583]: file not found for module `baz` - --> $DIR/auxiliary/foo/bar.rs:1:9 + --> $DIR/auxiliary/foo/bar.rs:1:1 | LL | pub mod baz; - | ^^^ + | ^^^^^^^^^^^^ | - = help: name the file either bar/baz.rs or bar/baz/mod.rs inside the directory "$DIR/auxiliary/foo" + = help: to create the module `baz`, create file "$DIR/auxiliary/foo/bar/baz.rs" error: aborting due to previous error diff --git a/src/test/ui/issues/issue-10545.stderr b/src/test/ui/issues/issue-10545.stderr index 4ed7028c0a06b..f1da33eaba1c3 100644 --- a/src/test/ui/issues/issue-10545.stderr +++ b/src/test/ui/issues/issue-10545.stderr @@ -2,7 +2,7 @@ error[E0603]: struct `S` is private --> $DIR/issue-10545.rs:6:14 | LL | fn foo(_: a::S) { - | ^ this struct is private + | ^ private struct | note: the struct `S` is defined here --> $DIR/issue-10545.rs:2:5 diff --git a/src/test/ui/issues/issue-10656.rs b/src/test/ui/issues/issue-10656.rs index 8918dadb47a35..250c4bc442f98 100644 --- a/src/test/ui/issues/issue-10656.rs +++ b/src/test/ui/issues/issue-10656.rs @@ -1,3 +1,3 @@ #![deny(missing_docs)] #![crate_type="lib"] -//~^^ ERROR missing documentation for crate +//~^^ ERROR missing documentation for the crate diff --git a/src/test/ui/issues/issue-10656.stderr b/src/test/ui/issues/issue-10656.stderr index 2e91a598dce40..2e4365f1ed76b 100644 --- a/src/test/ui/issues/issue-10656.stderr +++ b/src/test/ui/issues/issue-10656.stderr @@ -1,4 +1,4 @@ -error: missing documentation for crate +error: missing documentation for the crate --> $DIR/issue-10656.rs:1:1 | LL | / #![deny(missing_docs)] diff --git a/src/test/ui/issues/issue-11593.stderr b/src/test/ui/issues/issue-11593.stderr index bfb4d31323b13..aa9768b1885a2 100644 --- a/src/test/ui/issues/issue-11593.stderr +++ b/src/test/ui/issues/issue-11593.stderr @@ -2,7 +2,7 @@ error[E0603]: trait `Foo` is private --> $DIR/issue-11593.rs:7:24 | LL | impl private_trait_xc::Foo for Bar {} - | ^^^ this trait is private + | ^^^ private trait | note: the trait `Foo` is defined here --> $DIR/auxiliary/private-trait-xc.rs:1:1 diff --git a/src/test/ui/issues/issue-11680.stderr b/src/test/ui/issues/issue-11680.stderr index 898ac10f7d9a9..ea224af8ed7e2 100644 --- a/src/test/ui/issues/issue-11680.stderr +++ b/src/test/ui/issues/issue-11680.stderr @@ -2,7 +2,7 @@ error[E0603]: enum `Foo` is private --> $DIR/issue-11680.rs:6:21 | LL | let _b = other::Foo::Bar(1); - | ^^^ this enum is private + | ^^^ private enum | note: the enum `Foo` is defined here --> $DIR/auxiliary/issue-11680.rs:1:1 @@ -14,7 +14,7 @@ error[E0603]: enum `Foo` is private --> $DIR/issue-11680.rs:9:27 | LL | let _b = other::test::Foo::Bar(1); - | ^^^ this enum is private + | ^^^ private enum | note: the enum `Foo` is defined here --> $DIR/auxiliary/issue-11680.rs:6:5 diff --git a/src/test/ui/issues/issue-13407.stderr b/src/test/ui/issues/issue-13407.stderr index f211d623ab12b..f30b6cdeaf073 100644 --- a/src/test/ui/issues/issue-13407.stderr +++ b/src/test/ui/issues/issue-13407.stderr @@ -2,7 +2,7 @@ error[E0603]: unit struct `C` is private --> $DIR/issue-13407.rs:6:8 | LL | A::C = 1; - | ^ this unit struct is private + | ^ private unit struct | note: the unit struct `C` is defined here --> $DIR/issue-13407.rs:2:5 diff --git a/src/test/ui/issues/issue-13641.stderr b/src/test/ui/issues/issue-13641.stderr index f90cb18b6fc9d..cdd0772d39fb0 100644 --- a/src/test/ui/issues/issue-13641.stderr +++ b/src/test/ui/issues/issue-13641.stderr @@ -2,7 +2,7 @@ error[E0603]: struct `Foo` is private --> $DIR/issue-13641.rs:9:8 | LL | a::Foo::new(); - | ^^^ this struct is private + | ^^^ private struct | note: the struct `Foo` is defined here --> $DIR/issue-13641.rs:2:5 @@ -14,7 +14,7 @@ error[E0603]: enum `Bar` is private --> $DIR/issue-13641.rs:11:8 | LL | a::Bar::new(); - | ^^^ this enum is private + | ^^^ private enum | note: the enum `Bar` is defined here --> $DIR/issue-13641.rs:4:5 diff --git a/src/test/ui/issues/issue-13853-2.stderr b/src/test/ui/issues/issue-13853-2.stderr index ea3b38940cf01..49b946b354e53 100644 --- a/src/test/ui/issues/issue-13853-2.stderr +++ b/src/test/ui/issues/issue-13853-2.stderr @@ -2,7 +2,12 @@ error[E0615]: attempted to take value of method `get` on type `std::boxed::Box<( --> $DIR/issue-13853-2.rs:5:43 | LL | fn foo(res : Box) { res.get } - | ^^^ help: use parentheses to call the method: `get()` + | ^^^ method, not a field + | +help: use parentheses to call the method + | +LL | fn foo(res : Box) { res.get() } + | ^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-16683.nll.stderr b/src/test/ui/issues/issue-16683.nll.stderr index f76e7a4e44fd7..b82b0b552e2dd 100644 --- a/src/test/ui/issues/issue-16683.nll.stderr +++ b/src/test/ui/issues/issue-16683.nll.stderr @@ -1,10 +1,10 @@ -error[E0521]: borrowed data escapes outside of method +error[E0521]: borrowed data escapes outside of associated function --> $DIR/issue-16683.rs:4:9 | LL | fn b(&self) { - | ----- `self` is a reference that is only valid in the method body + | ----- `self` is a reference that is only valid in the associated function body LL | self.a(); - | ^^^^^^^^ `self` escapes the method body here + | ^^^^^^^^ `self` escapes the associated function body here error: aborting due to previous error diff --git a/src/test/ui/issues/issue-16725.stderr b/src/test/ui/issues/issue-16725.stderr index e0a1ca8a5ac31..84359803bbae7 100644 --- a/src/test/ui/issues/issue-16725.stderr +++ b/src/test/ui/issues/issue-16725.stderr @@ -2,7 +2,7 @@ error[E0603]: function `bar` is private --> $DIR/issue-16725.rs:6:19 | LL | unsafe { foo::bar(); } - | ^^^ this function is private + | ^^^ private function | note: the function `bar` is defined here --> $DIR/auxiliary/issue-16725.rs:2:5 diff --git a/src/test/ui/issues/issue-17718-const-privacy.stderr b/src/test/ui/issues/issue-17718-const-privacy.stderr index 07d825ba9cb3b..d4595be749034 100644 --- a/src/test/ui/issues/issue-17718-const-privacy.stderr +++ b/src/test/ui/issues/issue-17718-const-privacy.stderr @@ -2,7 +2,7 @@ error[E0603]: constant `B` is private --> $DIR/issue-17718-const-privacy.rs:5:8 | LL | use a::B; - | ^ this constant is private + | ^ private constant | note: the constant `B` is defined here --> $DIR/issue-17718-const-privacy.rs:13:5 @@ -14,7 +14,7 @@ error[E0603]: constant `BAR` is private --> $DIR/issue-17718-const-privacy.rs:8:5 | LL | BAR, - | ^^^ this constant is private + | ^^^ private constant | note: the constant `BAR` is defined here --> $DIR/auxiliary/issue-17718-const-privacy.rs:4:1 diff --git a/src/test/ui/issues/issue-17718-static-sync.rs b/src/test/ui/issues/issue-17718-static-sync.rs index dccbde6a3c532..6f278d76bb18b 100644 --- a/src/test/ui/issues/issue-17718-static-sync.rs +++ b/src/test/ui/issues/issue-17718-static-sync.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Sync; diff --git a/src/test/ui/issues/issue-17758.nll.stderr b/src/test/ui/issues/issue-17758.nll.stderr index 92e21f4dc1769..23557b4d956aa 100644 --- a/src/test/ui/issues/issue-17758.nll.stderr +++ b/src/test/ui/issues/issue-17758.nll.stderr @@ -1,10 +1,10 @@ -error[E0521]: borrowed data escapes outside of method +error[E0521]: borrowed data escapes outside of associated function --> $DIR/issue-17758.rs:7:9 | LL | fn bar(&self) { - | ----- `self` is a reference that is only valid in the method body + | ----- `self` is a reference that is only valid in the associated function body LL | self.foo(); - | ^^^^^^^^^^ `self` escapes the method body here + | ^^^^^^^^^^ `self` escapes the associated function body here error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17999.stderr b/src/test/ui/issues/issue-17999.stderr index 448208ef033f7..4a1ef7350b8cb 100644 --- a/src/test/ui/issues/issue-17999.stderr +++ b/src/test/ui/issues/issue-17999.stderr @@ -2,7 +2,7 @@ error: unused variable: `x` --> $DIR/issue-17999.rs:5:13 | LL | let x = (); - | ^ help: consider prefixing with an underscore: `_x` + | ^ help: if this is intentional, prefix it with an underscore: `_x` | note: the lint level is defined here --> $DIR/issue-17999.rs:1:9 @@ -14,7 +14,7 @@ error: unused variable: `a` --> $DIR/issue-17999.rs:7:13 | LL | a => {} - | ^ help: consider prefixing with an underscore: `_a` + | ^ help: if this is intentional, prefix it with an underscore: `_a` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-21174.stderr b/src/test/ui/issues/issue-21174.stderr index 5ac5a8665bc69..09402c3d81410 100644 --- a/src/test/ui/issues/issue-21174.stderr +++ b/src/test/ui/issues/issue-21174.stderr @@ -4,8 +4,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently- LL | let new: T::B = unsafe { std::mem::transmute(value) }; | ^^^^^^^^^^^^^^^^^^^ | - = note: source type: `>::A` (size can vary because of ::A) - = note: target type: `>::B` (size can vary because of ::B) + = note: source type: `::A` (this type does not have a fixed size) + = note: target type: `::B` (this type does not have a fixed size) error: aborting due to previous error diff --git a/src/test/ui/issues/issue-21202.rs b/src/test/ui/issues/issue-21202.rs index 2c5f1394449b4..f62de7ce7dbe7 100644 --- a/src/test/ui/issues/issue-21202.rs +++ b/src/test/ui/issues/issue-21202.rs @@ -8,7 +8,7 @@ mod B { use crate1::A::Foo; fn bar(f: Foo) { Foo::foo(&f); - //~^ ERROR: method `foo` is private + //~^ ERROR: associated function `foo` is private } } diff --git a/src/test/ui/issues/issue-21202.stderr b/src/test/ui/issues/issue-21202.stderr index d19e42d8d9cad..9b3b7a72e049e 100644 --- a/src/test/ui/issues/issue-21202.stderr +++ b/src/test/ui/issues/issue-21202.stderr @@ -1,8 +1,8 @@ -error[E0624]: method `foo` is private - --> $DIR/issue-21202.rs:10:9 +error[E0624]: associated function `foo` is private + --> $DIR/issue-21202.rs:10:14 | LL | Foo::foo(&f); - | ^^^^^^^^ + | ^^^ private associated function error: aborting due to previous error diff --git a/src/test/ui/issues/issue-22599.stderr b/src/test/ui/issues/issue-22599.stderr index 9c3b2cbe6c796..2b34830d08427 100644 --- a/src/test/ui/issues/issue-22599.stderr +++ b/src/test/ui/issues/issue-22599.stderr @@ -2,7 +2,7 @@ error: unused variable: `a` --> $DIR/issue-22599.rs:8:19 | LL | v = match 0 { a => 0 }; - | ^ help: consider prefixing with an underscore: `_a` + | ^ help: if this is intentional, prefix it with an underscore: `_a` | note: the lint level is defined here --> $DIR/issue-22599.rs:1:9 diff --git a/src/test/ui/issues/issue-22638.stderr b/src/test/ui/issues/issue-22638.stderr index 83dd93b853dad..41965d6b35536 100644 --- a/src/test/ui/issues/issue-22638.stderr +++ b/src/test/ui/issues/issue-22638.stderr @@ -8,7 +8,7 @@ LL | | a.matches(f) LL | | } | |_____^ | - = note: consider adding a `#![type_length_limit="26214380"]` attribute to your crate + = note: consider adding a `#![type_length_limit="30408681"]` attribute to your crate error: aborting due to previous error diff --git a/src/test/ui/issues/issue-23080-2.rs b/src/test/ui/issues/issue-23080-2.rs index d20bb4bd90726..7f6b9e3fba79f 100644 --- a/src/test/ui/issues/issue-23080-2.rs +++ b/src/test/ui/issues/issue-23080-2.rs @@ -1,6 +1,7 @@ //~ ERROR #![feature(optin_builtin_traits)] +#![feature(negative_impls)] unsafe auto trait Trait { type Output; //~ ERROR E0380 diff --git a/src/test/ui/issues/issue-23080-2.stderr b/src/test/ui/issues/issue-23080-2.stderr index fcd1ecfa98288..48ce09aaa34da 100644 --- a/src/test/ui/issues/issue-23080-2.stderr +++ b/src/test/ui/issues/issue-23080-2.stderr @@ -1,5 +1,5 @@ error[E0380]: auto traits cannot have methods or associated items - --> $DIR/issue-23080-2.rs:6:10 + --> $DIR/issue-23080-2.rs:7:10 | LL | unsafe auto trait Trait { | ----- auto trait cannot have items diff --git a/src/test/ui/issues/issue-23080.rs b/src/test/ui/issues/issue-23080.rs index fa5c35316bc28..035db82ba5de0 100644 --- a/src/test/ui/issues/issue-23080.rs +++ b/src/test/ui/issues/issue-23080.rs @@ -1,4 +1,5 @@ #![feature(optin_builtin_traits)] +#![feature(negative_impls)] unsafe auto trait Trait { fn method(&self) { //~ ERROR E0380 diff --git a/src/test/ui/issues/issue-23080.stderr b/src/test/ui/issues/issue-23080.stderr index dbb9861b5784a..73ecb1c362e17 100644 --- a/src/test/ui/issues/issue-23080.stderr +++ b/src/test/ui/issues/issue-23080.stderr @@ -1,5 +1,5 @@ error[E0380]: auto traits cannot have methods or associated items - --> $DIR/issue-23080.rs:4:8 + --> $DIR/issue-23080.rs:5:8 | LL | unsafe auto trait Trait { | ----- auto trait cannot have items diff --git a/src/test/ui/issues/issue-25386.rs b/src/test/ui/issues/issue-25386.rs index 607c9fceab84f..45775e0e4ae36 100644 --- a/src/test/ui/issues/issue-25386.rs +++ b/src/test/ui/issues/issue-25386.rs @@ -17,12 +17,12 @@ mod stuff { macro_rules! check_ptr_exist { ($var:expr, $member:ident) => ( (*$var.c_object).$member.is_some() - //~^ ERROR field `name` of struct `stuff::CObj` is private - //~^^ ERROR field `c_object` of struct `stuff::Item` is private + //~^ ERROR field `c_object` of struct `stuff::Item` is private ); } fn main() { let item = stuff::Item::new(); println!("{}", check_ptr_exist!(item, name)); + //~^ ERROR field `name` of struct `stuff::CObj` is private } diff --git a/src/test/ui/issues/issue-25386.stderr b/src/test/ui/issues/issue-25386.stderr index 76a4a5a493f59..6419e7a557194 100644 --- a/src/test/ui/issues/issue-25386.stderr +++ b/src/test/ui/issues/issue-25386.stderr @@ -1,8 +1,8 @@ error[E0616]: field `c_object` of struct `stuff::Item` is private - --> $DIR/issue-25386.rs:19:11 + --> $DIR/issue-25386.rs:19:16 | LL | (*$var.c_object).$member.is_some() - | ^^^^^^^^^^^^^ + | ^^^^^^^^ private field ... LL | println!("{}", check_ptr_exist!(item, name)); | ---------------------------- in this macro invocation @@ -10,15 +10,10 @@ LL | println!("{}", check_ptr_exist!(item, name)); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0616]: field `name` of struct `stuff::CObj` is private - --> $DIR/issue-25386.rs:19:9 + --> $DIR/issue-25386.rs:26:43 | -LL | (*$var.c_object).$member.is_some() - | ^^^^^^^^^^^^^^^^^^^^^^^^ -... LL | println!("{}", check_ptr_exist!(item, name)); - | ---------------------------- in this macro invocation - | - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + | ^^^^ private field error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-26472.stderr b/src/test/ui/issues/issue-26472.stderr index 245ebeaf972ed..f7df5b6232bda 100644 --- a/src/test/ui/issues/issue-26472.stderr +++ b/src/test/ui/issues/issue-26472.stderr @@ -1,16 +1,19 @@ error[E0616]: field `len` of struct `sub::S` is private - --> $DIR/issue-26472.rs:11:13 + --> $DIR/issue-26472.rs:11:15 | LL | let v = s.len; - | ^^--- - | | - | help: a method `len` also exists, call it with parentheses: `len()` + | ^^^ private field + | +help: a method `len` also exists, call it with parentheses + | +LL | let v = s.len(); + | ^^ error[E0616]: field `len` of struct `sub::S` is private - --> $DIR/issue-26472.rs:12:5 + --> $DIR/issue-26472.rs:12:7 | LL | s.len = v; - | ^^^^^ + | ^^^ private field error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-2823.rs b/src/test/ui/issues/issue-2823.rs index 7b443b4152613..f00c2304733ca 100644 --- a/src/test/ui/issues/issue-2823.rs +++ b/src/test/ui/issues/issue-2823.rs @@ -1,3 +1,8 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl + struct C { x: isize, } diff --git a/src/test/ui/issues/issue-2823.stderr b/src/test/ui/issues/issue-2823.stderr index aa720fd45895a..6e11dd4028836 100644 --- a/src/test/ui/issues/issue-2823.stderr +++ b/src/test/ui/issues/issue-2823.stderr @@ -1,11 +1,19 @@ error[E0599]: no method named `clone` found for struct `C` in the current scope - --> $DIR/issue-2823.rs:13:16 + --> $DIR/issue-2823.rs:18:16 | LL | struct C { | -------- method `clone` not found for this ... LL | let _d = c.clone(); | ^^^^^ method not found in `C` + | + ::: $SRC_DIR/libcore/clone.rs:LL:COL + | +LL | fn clone(&self) -> Self; + | ----- + | | + | the method is available for `std::sync::Arc` here + | the method is available for `std::rc::Rc` here | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: diff --git a/src/test/ui/issues/issue-28344.stderr b/src/test/ui/issues/issue-28344.stderr index 77bc829209440..e34ac45e69db6 100644 --- a/src/test/ui/issues/issue-28344.stderr +++ b/src/test/ui/issues/issue-28344.stderr @@ -11,7 +11,7 @@ LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8); | ^^^^^ | | | function or associated item not found in `dyn std::ops::BitXor<_>` - | help: there is a method with a similar name: `bitxor` + | help: there is an associated function with a similar name: `bitxor` error[E0191]: the value of the associated type `Output` (from trait `std::ops::BitXor`) must be specified --> $DIR/issue-28344.rs:8:13 @@ -26,7 +26,7 @@ LL | let g = BitXor::bitor; | ^^^^^ | | | function or associated item not found in `dyn std::ops::BitXor<_>` - | help: there is a method with a similar name: `bitxor` + | help: there is an associated function with a similar name: `bitxor` error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-28388-2.stderr b/src/test/ui/issues/issue-28388-2.stderr index 58bd775f295fc..1afaf622be7da 100644 --- a/src/test/ui/issues/issue-28388-2.stderr +++ b/src/test/ui/issues/issue-28388-2.stderr @@ -2,7 +2,7 @@ error[E0603]: module `n` is private --> $DIR/issue-28388-2.rs:7:8 | LL | use m::n::{}; - | ^ this module is private + | ^ private module | note: the module `n` is defined here --> $DIR/issue-28388-2.rs:4:5 diff --git a/src/test/ui/issues/issue-29161.stderr b/src/test/ui/issues/issue-29161.stderr index 1bfa211ef7962..7ce95e4b0df8b 100644 --- a/src/test/ui/issues/issue-29161.stderr +++ b/src/test/ui/issues/issue-29161.stderr @@ -8,7 +8,7 @@ error[E0603]: struct `A` is private --> $DIR/issue-29161.rs:13:8 | LL | a::A::default(); - | ^ this struct is private + | ^ private struct | note: the struct `A` is defined here --> $DIR/issue-29161.rs:2:5 diff --git a/src/test/ui/issues/issue-29516.rs b/src/test/ui/issues/issue-29516.rs index d43367e34529b..035f904b15bb3 100644 --- a/src/test/ui/issues/issue-29516.rs +++ b/src/test/ui/issues/issue-29516.rs @@ -1,5 +1,6 @@ // check-pass #![feature(optin_builtin_traits)] +#![feature(negative_impls)] auto trait NotSame {} diff --git a/src/test/ui/issues/issue-31845.stderr b/src/test/ui/issues/issue-31845.stderr index 75d8859961a04..fe51fa0699fb4 100644 --- a/src/test/ui/issues/issue-31845.stderr +++ b/src/test/ui/issues/issue-31845.stderr @@ -1,11 +1,10 @@ error[E0425]: cannot find function `g` in this scope --> $DIR/issue-31845.rs:7:12 | -LL | / fn h() { -LL | | g(); - | | ^ help: a function with a similar name exists: `h` -LL | | } - | |_________- similarly named function `h` defined here +LL | fn h() { + | ------ similarly named function `h` defined here +LL | g(); + | ^ help: a function with a similar name exists: `h` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-33140-hack-boundaries.rs b/src/test/ui/issues/issue-33140-hack-boundaries.rs index fbdef51c13255..5984a256a3086 100644 --- a/src/test/ui/issues/issue-33140-hack-boundaries.rs +++ b/src/test/ui/issues/issue-33140-hack-boundaries.rs @@ -1,11 +1,10 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] #![allow(order_dependent_trait_objects)] // Check that the issue #33140 hack does not allow unintended things. // OK -trait Trait0 { -} +trait Trait0 {} impl Trait0 for dyn Send {} impl Trait0 for dyn Send {} @@ -20,58 +19,49 @@ impl Trait1 for dyn Send {} //~^ ERROR E0119 // Problem 2: negative impl -trait Trait2 { -} +trait Trait2 {} impl Trait2 for dyn Send {} impl !Trait2 for dyn Send {} -//~^ ERROR E0119 - +//~^ ERROR E0748 // Problem 3: type parameter -trait Trait3 { -} +trait Trait3 {} impl Trait3 for dyn Send {} impl Trait3 for dyn Send {} //~^ ERROR E0119 // Problem 4a: not a trait object - generic -trait Trait4a { -} +trait Trait4a {} impl Trait4a for T {} impl Trait4a for dyn Send {} //~^ ERROR E0119 // Problem 4b: not a trait object - misc -trait Trait4b { -} +trait Trait4b {} impl Trait4b for () {} impl Trait4b for () {} //~^ ERROR E0119 // Problem 4c: not a principal-less trait object -trait Trait4c { -} +trait Trait4c {} impl Trait4c for dyn Trait1 + Send {} impl Trait4c for dyn Trait1 + Send {} //~^ ERROR E0119 // Problem 4d: lifetimes -trait Trait4d { -} +trait Trait4d {} impl<'a> Trait4d for dyn Send + 'a {} impl<'a> Trait4d for dyn Send + 'a {} //~^ ERROR E0119 - // Problem 5: where-clauses -trait Trait5 { -} +trait Trait5 {} impl Trait5 for dyn Send {} impl Trait5 for dyn Send where u32: Copy {} diff --git a/src/test/ui/issues/issue-33140-hack-boundaries.stderr b/src/test/ui/issues/issue-33140-hack-boundaries.stderr index 95aaa55ba7c67..b3bf34a2a9031 100644 --- a/src/test/ui/issues/issue-33140-hack-boundaries.stderr +++ b/src/test/ui/issues/issue-33140-hack-boundaries.stderr @@ -1,21 +1,21 @@ error[E0119]: conflicting implementations of trait `Trait1` for type `(dyn std::marker::Send + 'static)`: - --> $DIR/issue-33140-hack-boundaries.rs:19:1 + --> $DIR/issue-33140-hack-boundaries.rs:18:1 | LL | impl Trait1 for dyn Send {} | ------------------------ first implementation here LL | impl Trait1 for dyn Send {} | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)` -error[E0119]: conflicting implementations of trait `Trait2` for type `(dyn std::marker::Send + 'static)`: - --> $DIR/issue-33140-hack-boundaries.rs:27:1 +error[E0748]: found both positive and negative implementation of trait `Trait2` for type `(dyn std::marker::Send + 'static)`: + --> $DIR/issue-33140-hack-boundaries.rs:25:1 | LL | impl Trait2 for dyn Send {} - | ------------------------ first implementation here + | ------------------------ positive implementation here LL | impl !Trait2 for dyn Send {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here error[E0119]: conflicting implementations of trait `Trait3<(dyn std::marker::Sync + 'static)>` for type `(dyn std::marker::Send + 'static)`: - --> $DIR/issue-33140-hack-boundaries.rs:36:1 + --> $DIR/issue-33140-hack-boundaries.rs:32:1 | LL | impl Trait3 for dyn Send {} | ---------------------------------- first implementation here @@ -23,7 +23,7 @@ LL | impl Trait3 for dyn Send {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)` error[E0119]: conflicting implementations of trait `Trait4a` for type `(dyn std::marker::Send + 'static)`: - --> $DIR/issue-33140-hack-boundaries.rs:44:1 + --> $DIR/issue-33140-hack-boundaries.rs:39:1 | LL | impl Trait4a for T {} | ----------------------------- first implementation here @@ -31,7 +31,7 @@ LL | impl Trait4a for dyn Send {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)` error[E0119]: conflicting implementations of trait `Trait4b` for type `()`: - --> $DIR/issue-33140-hack-boundaries.rs:52:1 + --> $DIR/issue-33140-hack-boundaries.rs:46:1 | LL | impl Trait4b for () {} | ------------------- first implementation here @@ -39,7 +39,7 @@ LL | impl Trait4b for () {} | ^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` error[E0119]: conflicting implementations of trait `Trait4c` for type `(dyn Trait1 + std::marker::Send + 'static)`: - --> $DIR/issue-33140-hack-boundaries.rs:60:1 + --> $DIR/issue-33140-hack-boundaries.rs:53:1 | LL | impl Trait4c for dyn Trait1 + Send {} | ---------------------------------- first implementation here @@ -47,7 +47,7 @@ LL | impl Trait4c for dyn Trait1 + Send {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Trait1 + std::marker::Send + 'static)` error[E0119]: conflicting implementations of trait `Trait4d` for type `dyn std::marker::Send`: - --> $DIR/issue-33140-hack-boundaries.rs:68:1 + --> $DIR/issue-33140-hack-boundaries.rs:60:1 | LL | impl<'a> Trait4d for dyn Send + 'a {} | ---------------------------------- first implementation here @@ -55,7 +55,7 @@ LL | impl<'a> Trait4d for dyn Send + 'a {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `dyn std::marker::Send` error[E0119]: conflicting implementations of trait `Trait5` for type `(dyn std::marker::Send + 'static)`: - --> $DIR/issue-33140-hack-boundaries.rs:77:1 + --> $DIR/issue-33140-hack-boundaries.rs:67:1 | LL | impl Trait5 for dyn Send {} | ------------------------ first implementation here @@ -64,4 +64,5 @@ LL | impl Trait5 for dyn Send where u32: Copy {} error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0119`. +Some errors have detailed explanations: E0119, E0748. +For more information about an error, try `rustc --explain E0119`. diff --git a/src/test/ui/issues/issue-35241.stderr b/src/test/ui/issues/issue-35241.stderr index 4a52a292ef30a..b6045c993a958 100644 --- a/src/test/ui/issues/issue-35241.stderr +++ b/src/test/ui/issues/issue-35241.stderr @@ -5,14 +5,16 @@ LL | struct Foo(u32); | ---------------- fn(u32) -> Foo {Foo} defined here LL | LL | fn test() -> Foo { Foo } - | --- ^^^ - | | | - | | expected struct `Foo`, found fn item - | | help: use parentheses to instantiate this tuple struct: `Foo(_)` + | --- ^^^ expected struct `Foo`, found fn item + | | | expected `Foo` because of return type | = note: expected struct `Foo` found fn item `fn(u32) -> Foo {Foo}` +help: use parentheses to instantiate this tuple struct + | +LL | fn test() -> Foo { Foo(_) } + | ^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-3763.rs b/src/test/ui/issues/issue-3763.rs index 3494df37fe7f1..451321c55035d 100644 --- a/src/test/ui/issues/issue-3763.rs +++ b/src/test/ui/issues/issue-3763.rs @@ -21,9 +21,9 @@ fn main() { let _woohoo = (Box::new(my_struct)).priv_field; //~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private - (&my_struct).happyfun(); //~ ERROR method `happyfun` is private + (&my_struct).happyfun(); //~ ERROR associated function `happyfun` is private - (Box::new(my_struct)).happyfun(); //~ ERROR method `happyfun` is private + (Box::new(my_struct)).happyfun(); //~ ERROR associated function `happyfun` is private let nope = my_struct.priv_field; //~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private } diff --git a/src/test/ui/issues/issue-3763.stderr b/src/test/ui/issues/issue-3763.stderr index 873f69d390e67..b63967bb9dce3 100644 --- a/src/test/ui/issues/issue-3763.stderr +++ b/src/test/ui/issues/issue-3763.stderr @@ -1,32 +1,32 @@ error[E0616]: field `priv_field` of struct `my_mod::MyStruct` is private - --> $DIR/issue-3763.rs:18:19 + --> $DIR/issue-3763.rs:18:32 | LL | let _woohoo = (&my_struct).priv_field; - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ private field error[E0616]: field `priv_field` of struct `my_mod::MyStruct` is private - --> $DIR/issue-3763.rs:21:19 + --> $DIR/issue-3763.rs:21:41 | LL | let _woohoo = (Box::new(my_struct)).priv_field; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ private field -error[E0624]: method `happyfun` is private +error[E0624]: associated function `happyfun` is private --> $DIR/issue-3763.rs:24:18 | LL | (&my_struct).happyfun(); - | ^^^^^^^^ + | ^^^^^^^^ private associated function -error[E0624]: method `happyfun` is private +error[E0624]: associated function `happyfun` is private --> $DIR/issue-3763.rs:26:27 | LL | (Box::new(my_struct)).happyfun(); - | ^^^^^^^^ + | ^^^^^^^^ private associated function error[E0616]: field `priv_field` of struct `my_mod::MyStruct` is private - --> $DIR/issue-3763.rs:27:16 + --> $DIR/issue-3763.rs:27:26 | LL | let nope = my_struct.priv_field; - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ private field error: aborting due to 5 previous errors diff --git a/src/test/ui/issues/issue-38857.stderr b/src/test/ui/issues/issue-38857.stderr index ba0f1336ff09d..1a287e94bafd3 100644 --- a/src/test/ui/issues/issue-38857.stderr +++ b/src/test/ui/issues/issue-38857.stderr @@ -8,7 +8,7 @@ error[E0603]: module `sys` is private --> $DIR/issue-38857.rs:7:18 | LL | let a = std::sys::imp::process::process_common::StdioPipes { ..panic!() }; - | ^^^ this module is private + | ^^^ private module | note: the module `sys` is defined here --> $SRC_DIR/libstd/lib.rs:LL:COL diff --git a/src/test/ui/issues/issue-39559-2.rs b/src/test/ui/issues/issue-39559-2.rs index 3a52e4d6216a5..ec0275b2d6c12 100644 --- a/src/test/ui/issues/issue-39559-2.rs +++ b/src/test/ui/issues/issue-39559-2.rs @@ -17,4 +17,5 @@ fn main() { = [0; Dim3::dim()]; //~^ ERROR E0015 //~| ERROR E0080 + //~| ERROR mismatched types } diff --git a/src/test/ui/issues/issue-39559-2.stderr b/src/test/ui/issues/issue-39559-2.stderr index 586debbbe5353..7cbf63c2da0a9 100644 --- a/src/test/ui/issues/issue-39559-2.stderr +++ b/src/test/ui/issues/issue-39559-2.stderr @@ -22,7 +22,19 @@ error[E0080]: evaluation of constant value failed LL | = [0; Dim3::dim()]; | ^^^^^^^^^^^ calling non-const function `::dim` -error: aborting due to 4 previous errors +error[E0308]: mismatched types + --> $DIR/issue-39559-2.rs:17:11 + | +LL | let array: [usize; Dim3::dim()] + | -------------------- expected due to this +... +LL | = [0; Dim3::dim()]; + | ^^^^^^^^^^^^^^^^ expected `Dim3::dim()`, found `Dim3::dim()` + | + = note: expected array `[usize; _]` + found array `[usize; _]` + +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0015, E0080. +Some errors have detailed explanations: E0015, E0080, E0308. For more information about an error, try `rustc --explain E0015`. diff --git a/src/test/ui/issues/issue-3993.stderr b/src/test/ui/issues/issue-3993.stderr index 3fa8ed4af28fa..deecf7a9d752c 100644 --- a/src/test/ui/issues/issue-3993.stderr +++ b/src/test/ui/issues/issue-3993.stderr @@ -2,7 +2,7 @@ error[E0603]: function `fly` is private --> $DIR/issue-3993.rs:1:10 | LL | use zoo::fly; - | ^^^ this function is private + | ^^^ private function | note: the function `fly` is defined here --> $DIR/issue-3993.rs:4:5 diff --git a/src/test/ui/issues/issue-40883.rs b/src/test/ui/issues/issue-40883.rs index 37e61b1b0e603..8a4aef46dd514 100644 --- a/src/test/ui/issues/issue-40883.rs +++ b/src/test/ui/issues/issue-40883.rs @@ -71,15 +71,16 @@ pub fn supersize_me(out: &mut Vec) { #[inline(never)] fn verify_stack_usage(before_ptr: *mut Vec) { - // to check stack usage, create locals before and after + // To check stack usage, create locals before and after // and check the difference in addresses between them. let mut stack_var: Vec = vec![]; test::black_box(&mut stack_var); let stack_usage = isize::abs( (&mut stack_var as *mut _ as isize) - (before_ptr as isize)) as usize; - // give space for 2 copies of `Big` + 128 "misc" bytes. - if stack_usage > mem::size_of::() * 2 + 128 { + // Give space for 2 copies of `Big` + 272 "misc" bytes + // (value observed on x86_64-pc-windows-gnu). + if stack_usage > mem::size_of::() * 2 + 272 { panic!("used {} bytes of stack, but `struct Big` is only {} bytes", stack_usage, mem::size_of::()); } diff --git a/src/test/ui/issues/issue-46332.stderr b/src/test/ui/issues/issue-46332.stderr index 5d8a859a7379c..890ef8014b489 100644 --- a/src/test/ui/issues/issue-46332.stderr +++ b/src/test/ui/issues/issue-46332.stderr @@ -2,7 +2,7 @@ error[E0422]: cannot find struct, variant or union type `TyUInt` in this scope --> $DIR/issue-46332.rs:9:5 | LL | struct TyUint {} - | ---------------- similarly named struct `TyUint` defined here + | ------------- similarly named struct `TyUint` defined here ... LL | TyUInt {}; | ^^^^^^ help: a struct with a similar name exists (notice the capitalization): `TyUint` diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr index 5db521536a804..b97131a199227 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref` found for enum `std::option::Option<{in --> $DIR/option-as_deref.rs:2:29 | LL | let _result = &Some(42).as_deref(); - | ^^^^^^^^ help: there is a method with a similar name: `as_ref` + | ^^^^^^^^ help: there is an associated function with a similar name: `as_ref` | = note: the method `as_deref` exists but the following trait bounds were not satisfied: `{integer}: std::ops::Deref` diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr index 2dfc6d53750e7..f33e9c7823ee4 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref` found for enum `std::result::Result<{in --> $DIR/result-as_deref.rs:4:27 | LL | let _result = &Ok(42).as_deref(); - | ^^^^^^^^ help: there is a method with a similar name: `as_ref` + | ^^^^^^^^ help: there is an associated function with a similar name: `as_ref` | = note: the method `as_deref` exists but the following trait bounds were not satisfied: `{integer}: std::ops::Deref` diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr index 1d65c57e5e9ec..68ebfab95c47e 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref_err` found for enum `std::result::Result --> $DIR/result-as_deref_err.rs:4:28 | LL | let _result = &Err(41).as_deref_err(); - | ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut` + | ^^^^^^^^^^^^ help: there is an associated function with a similar name: `as_deref_mut` | = note: the method `as_deref_err` exists but the following trait bounds were not satisfied: `{integer}: std::ops::Deref` diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr index 2f4bf0c94b5cb..d2ba1049b76ba 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref_mut` found for enum `std::result::Result --> $DIR/result-as_deref_mut.rs:4:31 | LL | let _result = &mut Ok(42).as_deref_mut(); - | ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_err` + | ^^^^^^^^^^^^ help: there is an associated function with a similar name: `as_deref_err` | = note: the method `as_deref_mut` exists but the following trait bounds were not satisfied: `{integer}: std::ops::DerefMut` diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr index b76d36c804e5f..d724ae5c74bde 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref_mut_err` found for enum `std::result::Re --> $DIR/result-as_deref_mut_err.rs:4:32 | LL | let _result = &mut Err(41).as_deref_mut_err(); - | ^^^^^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut` + | ^^^^^^^^^^^^^^^^ help: there is an associated function with a similar name: `as_deref_mut` | = note: the method `as_deref_mut_err` exists but the following trait bounds were not satisfied: `{integer}: std::ops::DerefMut` diff --git a/src/test/ui/issues/issue-52060.rs b/src/test/ui/issues/issue-52060.rs index fed08902c8b9d..2688049fcc9ff 100644 --- a/src/test/ui/issues/issue-52060.rs +++ b/src/test/ui/issues/issue-52060.rs @@ -4,5 +4,6 @@ static A: &'static [u32] = &[1]; static B: [u32; 1] = [0; A.len()]; //~^ ERROR [E0013] //~| ERROR evaluation of constant value failed +//~| ERROR mismatched types fn main() {} diff --git a/src/test/ui/issues/issue-52060.stderr b/src/test/ui/issues/issue-52060.stderr index 502825e9766e3..e076e183937f2 100644 --- a/src/test/ui/issues/issue-52060.stderr +++ b/src/test/ui/issues/issue-52060.stderr @@ -12,7 +12,16 @@ error[E0080]: evaluation of constant value failed LL | static B: [u32; 1] = [0; A.len()]; | ^ constant accesses static -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/issue-52060.rs:4:22 + | +LL | static B: [u32; 1] = [0; A.len()]; + | ^^^^^^^^^^^^ expected `1usize`, found `A.len()` + | + = note: expected array `[u32; 1]` + found array `[u32; _]` + +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0013, E0080. +Some errors have detailed explanations: E0013, E0080, E0308. For more information about an error, try `rustc --explain E0013`. diff --git a/src/test/ui/issues/issue-53275.rs b/src/test/ui/issues/issue-53275.rs new file mode 100644 index 0000000000000..5ae6fb2d47249 --- /dev/null +++ b/src/test/ui/issues/issue-53275.rs @@ -0,0 +1,9 @@ +// build-pass + +#![crate_type = "lib"] +#![allow(unconditional_panic)] +struct S(u8); + +pub fn ice() { + S([][0]); +} diff --git a/src/test/ui/issues/issue-53498.rs b/src/test/ui/issues/issue-53498.rs index c87d423649233..9e0437c46f4bd 100644 --- a/src/test/ui/issues/issue-53498.rs +++ b/src/test/ui/issues/issue-53498.rs @@ -13,5 +13,5 @@ pub mod test { } fn main() { - test::Foo::::foo(); //~ ERROR method `foo` is private + test::Foo::::foo(); //~ ERROR associated function `foo` is private } diff --git a/src/test/ui/issues/issue-53498.stderr b/src/test/ui/issues/issue-53498.stderr index 3fd48233daeb4..3c0f7f2b55026 100644 --- a/src/test/ui/issues/issue-53498.stderr +++ b/src/test/ui/issues/issue-53498.stderr @@ -1,8 +1,8 @@ -error[E0624]: method `foo` is private - --> $DIR/issue-53498.rs:16:5 +error[E0624]: associated function `foo` is private + --> $DIR/issue-53498.rs:16:27 | LL | test::Foo::::foo(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^ private associated function error: aborting due to previous error diff --git a/src/test/ui/issues/issue-54062.stderr b/src/test/ui/issues/issue-54062.stderr index 5222e3ee95d59..f9aef08c353bb 100644 --- a/src/test/ui/issues/issue-54062.stderr +++ b/src/test/ui/issues/issue-54062.stderr @@ -1,8 +1,8 @@ error[E0616]: field `inner` of struct `std::sync::Mutex` is private - --> $DIR/issue-54062.rs:10:13 + --> $DIR/issue-54062.rs:10:24 | LL | let _ = test.comps.inner.lock().unwrap(); - | ^^^^^^^^^^^^^^^^ + | ^^^^^ private field error[E0599]: no method named `unwrap` found for struct `std::sys_common::mutex::MutexGuard<'_>` in the current scope --> $DIR/issue-54062.rs:10:37 diff --git a/src/test/ui/issues/issue-55587.stderr b/src/test/ui/issues/issue-55587.stderr index bb0d15a23d605..faf78cfe8d9f8 100644 --- a/src/test/ui/issues/issue-55587.stderr +++ b/src/test/ui/issues/issue-55587.stderr @@ -1,4 +1,4 @@ -error[E0164]: expected tuple struct or tuple variant, found method `Path::new` +error[E0164]: expected tuple struct or tuple variant, found associated function `Path::new` --> $DIR/issue-55587.rs:4:9 | LL | let Path::new(); diff --git a/src/test/ui/issues/issue-56685.stderr b/src/test/ui/issues/issue-56685.stderr index 2cef3126b9ee0..eccb71095acc7 100644 --- a/src/test/ui/issues/issue-56685.stderr +++ b/src/test/ui/issues/issue-56685.stderr @@ -9,7 +9,7 @@ note: the lint level is defined here | LL | #![deny(unused_variables)] | ^^^^^^^^^^^^^^^^ -help: consider prefixing with an underscore +help: if this is intentional, prefix it with an underscore | LL | E::A(_x) | E::B(_x) => {} | ^^ ^^ @@ -20,7 +20,7 @@ error: unused variable: `x` LL | F::A(x, y) | F::B(x, y) => { y }, | ^ ^ | -help: consider prefixing with an underscore +help: if this is intentional, prefix it with an underscore | LL | F::A(_x, y) | F::B(_x, y) => { y }, | ^^ ^^ @@ -29,13 +29,13 @@ error: unused variable: `a` --> $DIR/issue-56685.rs:27:14 | LL | F::C(a, b) => { 3 } - | ^ help: consider prefixing with an underscore: `_a` + | ^ help: if this is intentional, prefix it with an underscore: `_a` error: unused variable: `b` --> $DIR/issue-56685.rs:27:17 | LL | F::C(a, b) => { 3 } - | ^ help: consider prefixing with an underscore: `_b` + | ^ help: if this is intentional, prefix it with an underscore: `_b` error: unused variable: `x` --> $DIR/issue-56685.rs:32:25 @@ -43,7 +43,7 @@ error: unused variable: `x` LL | let _ = if let F::A(x, y) | F::B(x, y) = F::A(1, 2) { | ^ ^ | -help: consider prefixing with an underscore +help: if this is intentional, prefix it with an underscore | LL | let _ = if let F::A(_x, y) | F::B(_x, y) = F::A(1, 2) { | ^^ ^^ @@ -54,7 +54,7 @@ error: unused variable: `x` LL | while let F::A(x, y) | F::B(x, y) = F::A(1, 2) { | ^ ^ | -help: consider prefixing with an underscore +help: if this is intentional, prefix it with an underscore | LL | while let F::A(_x, y) | F::B(_x, y) = F::A(1, 2) { | ^^ ^^ diff --git a/src/test/ui/issues/issue-58319.rs b/src/test/ui/issues/issue-58319.rs new file mode 100644 index 0000000000000..757307d944f18 --- /dev/null +++ b/src/test/ui/issues/issue-58319.rs @@ -0,0 +1,621 @@ +// run-pass +fn main() {} +#[derive(Clone)] +pub struct Little; +#[derive(Clone)] +pub struct Big( + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, +); diff --git a/src/test/ui/issues/issue-63364.stderr b/src/test/ui/issues/issue-63364.stderr index 60ff318f35a1c..0375359aeaba6 100644 --- a/src/test/ui/issues/issue-63364.stderr +++ b/src/test/ui/issues/issue-63364.stderr @@ -5,6 +5,7 @@ LL | for n in 100_000.. { | ^^^^^^^ | = note: `#[deny(overflowing_literals)]` on by default + = note: the literal `100_000` does not fit into the type `u16` whose range is `0..=65535` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-65131.rs b/src/test/ui/issues/issue-65131.rs new file mode 100644 index 0000000000000..8b5345da900aa --- /dev/null +++ b/src/test/ui/issues/issue-65131.rs @@ -0,0 +1,18 @@ +fn get_pair(_a: &mut u32, _b: &mut u32) {} + +macro_rules! x10 { + ($($t:tt)*) => { + $($t)* $($t)* $($t)* $($t)* $($t)* + $($t)* $($t)* $($t)* $($t)* $($t)* + } +} + +#[allow(unused_assignments)] +fn main() { + let mut x = 1; + + get_pair(&mut x, &mut x); + //~^ ERROR: cannot borrow `x` as mutable more than once at a time + + x10! { x10!{ x10!{ if x > 0 { x += 2 } else { x += 1 } } } } +} diff --git a/src/test/ui/issues/issue-65131.stderr b/src/test/ui/issues/issue-65131.stderr new file mode 100644 index 0000000000000..e234e6da552a8 --- /dev/null +++ b/src/test/ui/issues/issue-65131.stderr @@ -0,0 +1,12 @@ +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/issue-65131.rs:14:22 + | +LL | get_pair(&mut x, &mut x); + | -------- ------ ^^^^^^ second mutable borrow occurs here + | | | + | | first mutable borrow occurs here + | first borrow later used by call + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs index d060f26fb2a08..2c5257ce063cb 100644 --- a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs +++ b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs @@ -19,5 +19,4 @@ impl TraitB for B { //~ ERROR not all trait items implemented, missing: `MyA` fn main() { let _ = [0; B::VALUE]; - //~^ ERROR array lengths can't depend on generic parameters } diff --git a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr index c6b2b4d27a208..8ae0f8b804c93 100644 --- a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr +++ b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr @@ -13,13 +13,7 @@ LL | type MyA: TraitA; LL | impl TraitB for B { | ^^^^^^^^^^^^^^^^^ missing `MyA` in implementation -error: array lengths can't depend on generic parameters - --> $DIR/issue-69602-type-err-during-codegen-ice.rs:21:17 - | -LL | let _ = [0; B::VALUE]; - | ^^^^^^^^ - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0046, E0437. For more information about an error, try `rustc --explain E0046`. diff --git a/src/test/ui/issues/issue-69725.rs b/src/test/ui/issues/issue-69725.rs index b8130b41f2167..a8e72e9459e33 100644 --- a/src/test/ui/issues/issue-69725.rs +++ b/src/test/ui/issues/issue-69725.rs @@ -1,3 +1,8 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl + // aux-build:issue-69725.rs extern crate issue_69725; diff --git a/src/test/ui/issues/issue-69725.stderr b/src/test/ui/issues/issue-69725.stderr index 667383e072a54..439fae9511167 100644 --- a/src/test/ui/issues/issue-69725.stderr +++ b/src/test/ui/issues/issue-69725.stderr @@ -1,5 +1,5 @@ error[E0599]: no method named `clone` found for struct `issue_69725::Struct` in the current scope - --> $DIR/issue-69725.rs:7:32 + --> $DIR/issue-69725.rs:12:32 | LL | let _ = Struct::::new().clone(); | ^^^^^ method not found in `issue_69725::Struct` @@ -8,6 +8,14 @@ LL | let _ = Struct::::new().clone(); | LL | pub struct Struct(A); | ------------------------ doesn't satisfy `issue_69725::Struct: std::clone::Clone` + | + ::: $SRC_DIR/libcore/clone.rs:LL:COL + | +LL | fn clone(&self) -> Self; + | ----- + | | + | the method is available for `std::sync::Arc>` here + | the method is available for `std::rc::Rc>` here | = note: the method `clone` exists but the following trait bounds were not satisfied: `A: std::clone::Clone` diff --git a/src/test/ui/issues/issue-70041.rs b/src/test/ui/issues/issue-70041.rs new file mode 100644 index 0000000000000..22e42295eedf3 --- /dev/null +++ b/src/test/ui/issues/issue-70041.rs @@ -0,0 +1,13 @@ +// compile-flags: --edition=2018 +// run-pass + +macro_rules! regex { + //~^ WARN unused macro definition + () => {}; +} + +#[allow(dead_code)] +use regex; +//~^ WARN unused import + +fn main() {} diff --git a/src/test/ui/issues/issue-70041.stderr b/src/test/ui/issues/issue-70041.stderr new file mode 100644 index 0000000000000..b180175c5ab76 --- /dev/null +++ b/src/test/ui/issues/issue-70041.stderr @@ -0,0 +1,19 @@ +warning: unused macro definition + --> $DIR/issue-70041.rs:4:1 + | +LL | / macro_rules! regex { +LL | | +LL | | () => {}; +LL | | } + | |_^ + | + = note: `#[warn(unused_macros)]` on by default + +warning: unused import: `regex` + --> $DIR/issue-70041.rs:10:5 + | +LL | use regex; + | ^^^^^ + | + = note: `#[warn(unused_imports)]` on by default + diff --git a/src/test/ui/json-bom-plus-crlf-multifile.stderr b/src/test/ui/json-bom-plus-crlf-multifile.stderr index ab0feb3c451ad..99f91cc881617 100644 --- a/src/test/ui/json-bom-plus-crlf-multifile.stderr +++ b/src/test/ui/json-bom-plus-crlf-multifile.stderr @@ -1,10 +1,6 @@ -{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a -variable. It can occur for several cases, the most common of which is a -mismatch in the expected type that the compiler inferred for a variable's -initializing expression, and the actual type explicitly assigned to the -variable. +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = \"I am not a number!\"; @@ -15,15 +11,17 @@ let x: i32 = \"I am not a number!\"; // | // type `i32` assigned to variable `x` ``` + +This error occurs when the compiler was unable to infer the concrete type of a +variable. It can happen in several cases, the most common being a mismatch +between the type that the compiler inferred for a variable based on its +initializing expression, on the one hand, and the type the author explicitly +assigned to the variable, on the other hand. "},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":612,"byte_end":618,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:17:22: error[E0308]: mismatched types "} -{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a -variable. It can occur for several cases, the most common of which is a -mismatch in the expected type that the compiler inferred for a variable's -initializing expression, and the actual type explicitly assigned to the -variable. +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = \"I am not a number!\"; @@ -34,15 +32,17 @@ let x: i32 = \"I am not a number!\"; // | // type `i32` assigned to variable `x` ``` + +This error occurs when the compiler was unable to infer the concrete type of a +variable. It can happen in several cases, the most common being a mismatch +between the type that the compiler inferred for a variable based on its +initializing expression, on the one hand, and the type the author explicitly +assigned to the variable, on the other hand. "},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":672,"byte_end":678,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:19:22: error[E0308]: mismatched types "} -{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a -variable. It can occur for several cases, the most common of which is a -mismatch in the expected type that the compiler inferred for a variable's -initializing expression, and the actual type explicitly assigned to the -variable. +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = \"I am not a number!\"; @@ -53,15 +53,17 @@ let x: i32 = \"I am not a number!\"; // | // type `i32` assigned to variable `x` ``` + +This error occurs when the compiler was unable to infer the concrete type of a +variable. It can happen in several cases, the most common being a mismatch +between the type that the compiler inferred for a variable based on its +initializing expression, on the one hand, and the type the author explicitly +assigned to the variable, on the other hand. "},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":735,"byte_end":741,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:23:1: error[E0308]: mismatched types "} -{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a -variable. It can occur for several cases, the most common of which is a -mismatch in the expected type that the compiler inferred for a variable's -initializing expression, and the actual type explicitly assigned to the -variable. +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = \"I am not a number!\"; @@ -72,6 +74,12 @@ let x: i32 = \"I am not a number!\"; // | // type `i32` assigned to variable `x` ``` + +This error occurs when the compiler was unable to infer the concrete type of a +variable. It can happen in several cases, the most common being a mismatch +between the type that the compiler inferred for a variable based on its +initializing expression, on the one hand, and the type the author explicitly +assigned to the variable, on the other hand. "},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":801,"byte_end":809,"line_start":25,"line_end":26,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected struct `std::string::String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":792,"byte_end":798,"line_start":25,"line_end":25,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:25:22: error[E0308]: mismatched types "} {"message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors diff --git a/src/test/ui/json-bom-plus-crlf.stderr b/src/test/ui/json-bom-plus-crlf.stderr index 1dd898db3ad8c..3e84f5ef54d2c 100644 --- a/src/test/ui/json-bom-plus-crlf.stderr +++ b/src/test/ui/json-bom-plus-crlf.stderr @@ -1,10 +1,6 @@ -{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a -variable. It can occur for several cases, the most common of which is a -mismatch in the expected type that the compiler inferred for a variable's -initializing expression, and the actual type explicitly assigned to the -variable. +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = \"I am not a number!\"; @@ -15,15 +11,17 @@ let x: i32 = \"I am not a number!\"; // | // type `i32` assigned to variable `x` ``` + +This error occurs when the compiler was unable to infer the concrete type of a +variable. It can happen in several cases, the most common being a mismatch +between the type that the compiler inferred for a variable based on its +initializing expression, on the one hand, and the type the author explicitly +assigned to the variable, on the other hand. "},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":597,"byte_end":603,"line_start":16,"line_end":16,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:16:22: error[E0308]: mismatched types "} -{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a -variable. It can occur for several cases, the most common of which is a -mismatch in the expected type that the compiler inferred for a variable's -initializing expression, and the actual type explicitly assigned to the -variable. +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = \"I am not a number!\"; @@ -34,15 +32,17 @@ let x: i32 = \"I am not a number!\"; // | // type `i32` assigned to variable `x` ``` + +This error occurs when the compiler was unable to infer the concrete type of a +variable. It can happen in several cases, the most common being a mismatch +between the type that the compiler inferred for a variable based on its +initializing expression, on the one hand, and the type the author explicitly +assigned to the variable, on the other hand. "},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":657,"byte_end":663,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:18:22: error[E0308]: mismatched types "} -{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a -variable. It can occur for several cases, the most common of which is a -mismatch in the expected type that the compiler inferred for a variable's -initializing expression, and the actual type explicitly assigned to the -variable. +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = \"I am not a number!\"; @@ -53,15 +53,17 @@ let x: i32 = \"I am not a number!\"; // | // type `i32` assigned to variable `x` ``` + +This error occurs when the compiler was unable to infer the concrete type of a +variable. It can happen in several cases, the most common being a mismatch +between the type that the compiler inferred for a variable based on its +initializing expression, on the one hand, and the type the author explicitly +assigned to the variable, on the other hand. "},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":720,"byte_end":726,"line_start":21,"line_end":21,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:22:1: error[E0308]: mismatched types "} -{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a -variable. It can occur for several cases, the most common of which is a -mismatch in the expected type that the compiler inferred for a variable's -initializing expression, and the actual type explicitly assigned to the -variable. +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = \"I am not a number!\"; @@ -72,6 +74,12 @@ let x: i32 = \"I am not a number!\"; // | // type `i32` assigned to variable `x` ``` + +This error occurs when the compiler was unable to infer the concrete type of a +variable. It can happen in several cases, the most common being a mismatch +between the type that the compiler inferred for a variable based on its +initializing expression, on the one hand, and the type the author explicitly +assigned to the variable, on the other hand. "},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":786,"byte_end":794,"line_start":24,"line_end":25,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected struct `std::string::String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":777,"byte_end":783,"line_start":24,"line_end":24,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf.rs:24:22: error[E0308]: mismatched types "} {"message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs index b07de3e341c41..a46ce67d40d5a 100644 --- a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs +++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs @@ -1,3 +1,4 @@ use extern::foo; //~ ERROR expected identifier, found keyword `extern` + //~| ERROR unresolved import `r#extern` fn main() {} diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr index 05802f2d36710..edbb36452b6ce 100644 --- a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr +++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr @@ -9,5 +9,12 @@ help: you can escape reserved keywords to use them as identifiers LL | use r#extern::foo; | ^^^^^^^^ -error: aborting due to previous error +error[E0432]: unresolved import `r#extern` + --> $DIR/keyword-extern-as-identifier-use.rs:1:5 + | +LL | use extern::foo; + | ^^^^^^ maybe a missing crate `r#extern`? + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/layout/debug.rs b/src/test/ui/layout/debug.rs new file mode 100644 index 0000000000000..70ae200e3e5aa --- /dev/null +++ b/src/test/ui/layout/debug.rs @@ -0,0 +1,15 @@ +// normalize-stderr-test "pref: Align \{\n *pow2: [1-3],\n *\}" -> "pref: $$PREF_ALIGN" +#![feature(never_type, rustc_attrs)] +#![crate_type = "lib"] + +#[rustc_layout(debug)] +enum E { Foo, Bar(!, i32, i32) } //~ ERROR: layout debugging + +#[rustc_layout(debug)] +struct S { f1: i32, f2: (), f3: i32 } //~ ERROR: layout debugging + +#[rustc_layout(debug)] +union U { f1: (i32, i32), f3: i32 } //~ ERROR: layout debugging + +#[rustc_layout(debug)] +type Test = Result; //~ ERROR: layout debugging diff --git a/src/test/ui/layout/debug.stderr b/src/test/ui/layout/debug.stderr new file mode 100644 index 0000000000000..ef88cf1e4c13a --- /dev/null +++ b/src/test/ui/layout/debug.stderr @@ -0,0 +1,319 @@ +error: layout debugging: Layout { + fields: Arbitrary { + offsets: [ + Size { + raw: 0, + }, + ], + memory_index: [ + 0, + ], + }, + variants: Multiple { + discr: Scalar { + value: Int( + I32, + false, + ), + valid_range: 0..=0, + }, + discr_kind: Tag, + discr_index: 0, + variants: [ + Layout { + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + variants: Single { + index: 0, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 0, + }, + pref: $PREF_ALIGN, + }, + size: Size { + raw: 4, + }, + }, + Layout { + fields: Arbitrary { + offsets: [ + Size { + raw: 4, + }, + Size { + raw: 4, + }, + Size { + raw: 8, + }, + ], + memory_index: [ + 0, + 1, + 2, + ], + }, + variants: Single { + index: 1, + }, + abi: Uninhabited, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: $PREF_ALIGN, + }, + size: Size { + raw: 12, + }, + }, + ], + }, + abi: Aggregate { + sized: true, + }, + largest_niche: Some( + Niche { + offset: Size { + raw: 0, + }, + scalar: Scalar { + value: Int( + I32, + false, + ), + valid_range: 0..=0, + }, + }, + ), + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: $PREF_ALIGN, + }, + size: Size { + raw: 12, + }, +} + --> $DIR/debug.rs:6:1 + | +LL | enum E { Foo, Bar(!, i32, i32) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: layout debugging: Layout { + fields: Arbitrary { + offsets: [ + Size { + raw: 0, + }, + Size { + raw: 0, + }, + Size { + raw: 4, + }, + ], + memory_index: [ + 1, + 0, + 2, + ], + }, + variants: Single { + index: 0, + }, + abi: ScalarPair( + Scalar { + value: Int( + I32, + true, + ), + valid_range: 0..=4294967295, + }, + Scalar { + value: Int( + I32, + true, + ), + valid_range: 0..=4294967295, + }, + ), + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: $PREF_ALIGN, + }, + size: Size { + raw: 8, + }, +} + --> $DIR/debug.rs:9:1 + | +LL | struct S { f1: i32, f2: (), f3: i32 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: layout debugging: Layout { + fields: Union( + 2, + ), + variants: Single { + index: 0, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: $PREF_ALIGN, + }, + size: Size { + raw: 8, + }, +} + --> $DIR/debug.rs:12:1 + | +LL | union U { f1: (i32, i32), f3: i32 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: layout debugging: Layout { + fields: Arbitrary { + offsets: [ + Size { + raw: 0, + }, + ], + memory_index: [ + 0, + ], + }, + variants: Multiple { + discr: Scalar { + value: Int( + I32, + false, + ), + valid_range: 0..=1, + }, + discr_kind: Tag, + discr_index: 0, + variants: [ + Layout { + fields: Arbitrary { + offsets: [ + Size { + raw: 4, + }, + ], + memory_index: [ + 0, + ], + }, + variants: Single { + index: 0, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: $PREF_ALIGN, + }, + size: Size { + raw: 8, + }, + }, + Layout { + fields: Arbitrary { + offsets: [ + Size { + raw: 4, + }, + ], + memory_index: [ + 0, + ], + }, + variants: Single { + index: 1, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: $PREF_ALIGN, + }, + size: Size { + raw: 8, + }, + }, + ], + }, + abi: ScalarPair( + Scalar { + value: Int( + I32, + false, + ), + valid_range: 0..=1, + }, + Scalar { + value: Int( + I32, + true, + ), + valid_range: 0..=4294967295, + }, + ), + largest_niche: Some( + Niche { + offset: Size { + raw: 0, + }, + scalar: Scalar { + value: Int( + I32, + false, + ), + valid_range: 0..=1, + }, + }, + ), + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: $PREF_ALIGN, + }, + size: Size { + raw: 8, + }, +} + --> $DIR/debug.rs:15:1 + | +LL | type Test = Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr index 291edc505cd1e..4c78821157670 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr @@ -7,7 +7,7 @@ LL | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { | lifetime `'a` defined here LL | LL | if x > y { x } else { y } - | ^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr index 15ee58574ecaa..11e7fa96d7ee9 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr @@ -7,7 +7,7 @@ LL | fn foo<'a>(&self, x: &'a i32) -> &i32 { | lifetime `'a` defined here LL | LL | x - | ^ method was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a` + | ^ associated function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a` error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr index a27a91e38f1e4..c41f08e691ac2 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr @@ -7,7 +7,7 @@ LL | fn foo<'a>(&self, x: &'a Foo) -> &'a Foo { | lifetime `'a` defined here LL | LL | if true { x } else { self } - | ^^^^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` + | ^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr index 5f922d8560b2a..1a19e81f235ba 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr @@ -6,7 +6,7 @@ LL | fn foo<'a>(&self, x: &i32) -> &i32 { | | | let's call the lifetime of this reference `'2` LL | x - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr index 91d7597c87fea..87b13dc15914b 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr @@ -6,7 +6,7 @@ LL | fn foo<'a>(&self, x: &Foo) -> &Foo { | | | let's call the lifetime of this reference `'2` LL | if true { x } else { self } - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: aborting due to previous error diff --git a/src/test/ui/lint/deny-overflowing-literals.stderr b/src/test/ui/lint/deny-overflowing-literals.stderr index 7f59495023e26..127dd4127c261 100644 --- a/src/test/ui/lint/deny-overflowing-literals.stderr +++ b/src/test/ui/lint/deny-overflowing-literals.stderr @@ -5,6 +5,7 @@ LL | let x: u8 = 256; | ^^^ | = note: `#[deny(overflowing_literals)]` on by default + = note: the literal `256` does not fit into the type `u8` whose range is `0..=255` error: range endpoint is out of range for `u8` --> $DIR/deny-overflowing-literals.rs:5:14 diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr index b07474bb48673..cc675a709a2c6 100644 --- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr +++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr @@ -2,7 +2,7 @@ warning: unused variable: `i_think_continually` --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:26:9 | LL | let i_think_continually = 2; - | ^^^^^^^^^^^^^^^^^^^ help: consider prefixing with an underscore: `_i_think_continually` + | ^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_i_think_continually` | note: the lint level is defined here --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:5:9 @@ -15,19 +15,19 @@ warning: unused variable: `mut_unused_var` --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:33:13 | LL | let mut mut_unused_var = 1; - | ^^^^^^^^^^^^^^ help: consider prefixing with an underscore: `_mut_unused_var` + | ^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_mut_unused_var` warning: unused variable: `var` --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:37:14 | LL | let (mut var, unused_var) = (1, 2); - | ^^^ help: consider prefixing with an underscore: `_var` + | ^^^ help: if this is intentional, prefix it with an underscore: `_var` warning: unused variable: `unused_var` --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:37:19 | LL | let (mut var, unused_var) = (1, 2); - | ^^^^^^^^^^ help: consider prefixing with an underscore: `_unused_var` + | ^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_var` warning: unused variable: `corridors_of_light` --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:45:26 diff --git a/src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs new file mode 100644 index 0000000000000..49d489d916837 --- /dev/null +++ b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs @@ -0,0 +1,10 @@ +// build-fail +// only-x86_64 + +fn main() { + Bug::V([0; !0]); //~ ERROR is too big for the current +} + +enum Bug { + V([u8; !0]), +} diff --git a/src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr new file mode 100644 index 0000000000000..d31ce9cfe0c2b --- /dev/null +++ b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr @@ -0,0 +1,8 @@ +error: the type `[u8; 18446744073709551615]` is too big for the current architecture + --> $DIR/issue-69485-var-size-diffs-too-large.rs:5:12 + | +LL | Bug::V([0; !0]); + | ^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/lint/lint-match-arms.stderr b/src/test/ui/lint/lint-match-arms.stderr index b124971f90512..1bc0e41fd550c 100644 --- a/src/test/ui/lint/lint-match-arms.stderr +++ b/src/test/ui/lint/lint-match-arms.stderr @@ -2,7 +2,7 @@ error: unused variable: `y` --> $DIR/lint-match-arms.rs:5:9 | LL | y => (), - | ^ help: consider prefixing with an underscore: `_y` + | ^ help: if this is intentional, prefix it with an underscore: `_y` | note: the lint level is defined here --> $DIR/lint-match-arms.rs:3:16 diff --git a/src/test/ui/lint/lint-missing-doc.rs b/src/test/ui/lint/lint-missing-doc.rs index 77f9a3770a339..bab6f4e9e5e15 100644 --- a/src/test/ui/lint/lint-missing-doc.rs +++ b/src/test/ui/lint/lint-missing-doc.rs @@ -50,8 +50,8 @@ trait B { } pub trait C { //~ ERROR: missing documentation for a trait - fn foo(&self); //~ ERROR: missing documentation for a trait method - fn foo_with_impl(&self) {} //~ ERROR: missing documentation for a trait method + fn foo(&self); //~ ERROR: missing documentation for an associated function + fn foo_with_impl(&self) {} //~ ERROR: missing documentation for an associated function } #[allow(missing_docs)] @@ -78,7 +78,7 @@ impl Foo { } impl PubFoo { - pub fn foo() {} //~ ERROR: missing documentation for a method + pub fn foo() {} //~ ERROR: missing documentation for an associated function /// dox pub fn foo1() {} fn foo2() {} diff --git a/src/test/ui/lint/lint-missing-doc.stderr b/src/test/ui/lint/lint-missing-doc.stderr index a18a97e5f7fb5..21da4fae4c161 100644 --- a/src/test/ui/lint/lint-missing-doc.stderr +++ b/src/test/ui/lint/lint-missing-doc.stderr @@ -40,13 +40,13 @@ error: missing documentation for a trait LL | pub trait C { | ^^^^^^^^^^^ -error: missing documentation for a trait method +error: missing documentation for an associated function --> $DIR/lint-missing-doc.rs:53:5 | LL | fn foo(&self); | ^^^^^^^^^^^^^^ -error: missing documentation for a trait method +error: missing documentation for an associated function --> $DIR/lint-missing-doc.rs:54:5 | LL | fn foo_with_impl(&self) {} @@ -64,7 +64,7 @@ error: missing documentation for an associated type LL | type AssociatedTypeDef = Self; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: missing documentation for a method +error: missing documentation for an associated function --> $DIR/lint-missing-doc.rs:81:5 | LL | pub fn foo() {} diff --git a/src/test/ui/lint/lint-pre-expansion-extern-module.rs b/src/test/ui/lint/lint-pre-expansion-extern-module.rs new file mode 100644 index 0000000000000..30e2ed8b7a623 --- /dev/null +++ b/src/test/ui/lint/lint-pre-expansion-extern-module.rs @@ -0,0 +1,7 @@ +// check-pass +// compile-flags: -W rust-2018-compatibility +// error-pattern: `try` is a keyword in the 2018 edition + +fn main() {} + +mod lint_pre_expansion_extern_module_aux; diff --git a/src/test/ui/lint/lint-pre-expansion-extern-module.stderr b/src/test/ui/lint/lint-pre-expansion-extern-module.stderr new file mode 100644 index 0000000000000..c683a3fa670ae --- /dev/null +++ b/src/test/ui/lint/lint-pre-expansion-extern-module.stderr @@ -0,0 +1,10 @@ +warning: `try` is a keyword in the 2018 edition + --> $DIR/lint_pre_expansion_extern_module_aux.rs:3:8 + | +LL | pub fn try() {} + | ^^^ help: you can use a raw identifier to stay compatible: `r#try` + | + = note: `-W keyword-idents` implied by `-W rust-2018-compatibility` + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue #49716 + diff --git a/src/test/ui/lint/lint-range-endpoint-overflow.stderr b/src/test/ui/lint/lint-range-endpoint-overflow.stderr index dff61e022ebb8..d2df73727412f 100644 --- a/src/test/ui/lint/lint-range-endpoint-overflow.stderr +++ b/src/test/ui/lint/lint-range-endpoint-overflow.stderr @@ -15,18 +15,24 @@ error: literal out of range for `u8` | LL | let range_c = 0..=256; | ^^^ + | + = note: the literal `256` does not fit into the type `u8` whose range is `0..=255` error: literal out of range for `u8` --> $DIR/lint-range-endpoint-overflow.rs:7:19 | LL | let range_d = 256..5; | ^^^ + | + = note: the literal `256` does not fit into the type `u8` whose range is `0..=255` error: literal out of range for `u8` --> $DIR/lint-range-endpoint-overflow.rs:8:22 | LL | let range_e = 0..257; | ^^^ + | + = note: the literal `257` does not fit into the type `u8` whose range is `0..=255` error: range endpoint is out of range for `u8` --> $DIR/lint-range-endpoint-overflow.rs:9:20 diff --git a/src/test/ui/lint/lint-removed-allow.stderr b/src/test/ui/lint/lint-removed-allow.stderr index 5ab95c89b9c7e..029334c2eb67c 100644 --- a/src/test/ui/lint/lint-removed-allow.stderr +++ b/src/test/ui/lint/lint-removed-allow.stderr @@ -2,7 +2,7 @@ error: unused variable: `unused` --> $DIR/lint-removed-allow.rs:8:17 | LL | fn main() { let unused = (); } - | ^^^^^^ help: consider prefixing with an underscore: `_unused` + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` | note: the lint level is defined here --> $DIR/lint-removed-allow.rs:7:8 diff --git a/src/test/ui/lint/lint-removed-cmdline.stderr b/src/test/ui/lint/lint-removed-cmdline.stderr index a9ebd3e32712c..4adc18cc2ce5d 100644 --- a/src/test/ui/lint/lint-removed-cmdline.stderr +++ b/src/test/ui/lint/lint-removed-cmdline.stderr @@ -18,7 +18,7 @@ error: unused variable: `unused` --> $DIR/lint-removed-cmdline.rs:12:17 | LL | fn main() { let unused = (); } - | ^^^^^^ help: consider prefixing with an underscore: `_unused` + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` | note: the lint level is defined here --> $DIR/lint-removed-cmdline.rs:11:8 diff --git a/src/test/ui/lint/lint-removed.stderr b/src/test/ui/lint/lint-removed.stderr index 2c043392f098c..190e10c8a9944 100644 --- a/src/test/ui/lint/lint-removed.stderr +++ b/src/test/ui/lint/lint-removed.stderr @@ -10,7 +10,7 @@ error: unused variable: `unused` --> $DIR/lint-removed.rs:8:17 | LL | fn main() { let unused = (); } - | ^^^^^^ help: consider prefixing with an underscore: `_unused` + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` | note: the lint level is defined here --> $DIR/lint-removed.rs:7:8 diff --git a/src/test/ui/lint/lint-renamed-allow.stderr b/src/test/ui/lint/lint-renamed-allow.stderr index 9da74f61b7569..46f6a10de2743 100644 --- a/src/test/ui/lint/lint-renamed-allow.stderr +++ b/src/test/ui/lint/lint-renamed-allow.stderr @@ -2,7 +2,7 @@ error: unused variable: `unused` --> $DIR/lint-renamed-allow.rs:8:17 | LL | fn main() { let unused = (); } - | ^^^^^^ help: consider prefixing with an underscore: `_unused` + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` | note: the lint level is defined here --> $DIR/lint-renamed-allow.rs:7:8 diff --git a/src/test/ui/lint/lint-renamed-cmdline.stderr b/src/test/ui/lint/lint-renamed-cmdline.stderr index 235215598a2bd..ef617dfe31f02 100644 --- a/src/test/ui/lint/lint-renamed-cmdline.stderr +++ b/src/test/ui/lint/lint-renamed-cmdline.stderr @@ -18,7 +18,7 @@ error: unused variable: `unused` --> $DIR/lint-renamed-cmdline.rs:8:17 | LL | fn main() { let unused = (); } - | ^^^^^^ help: consider prefixing with an underscore: `_unused` + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` | note: the lint level is defined here --> $DIR/lint-renamed-cmdline.rs:7:8 diff --git a/src/test/ui/lint/lint-renamed.stderr b/src/test/ui/lint/lint-renamed.stderr index dc43f2e4c46da..0225e22623424 100644 --- a/src/test/ui/lint/lint-renamed.stderr +++ b/src/test/ui/lint/lint-renamed.stderr @@ -10,7 +10,7 @@ error: unused variable: `unused` --> $DIR/lint-renamed.rs:4:17 | LL | fn main() { let unused = (); } - | ^^^^^^ help: consider prefixing with an underscore: `_unused` + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` | note: the lint level is defined here --> $DIR/lint-renamed.rs:3:8 diff --git a/src/test/ui/lint/lint-type-limits2.stderr b/src/test/ui/lint/lint-type-limits2.stderr index bf510823b568f..1e3c88dfc469c 100644 --- a/src/test/ui/lint/lint-type-limits2.stderr +++ b/src/test/ui/lint/lint-type-limits2.stderr @@ -17,6 +17,7 @@ note: the lint level is defined here | LL | #![warn(overflowing_literals)] | ^^^^^^^^^^^^^^^^^^^^ + = note: the literal `128` does not fit into the type `i8` whose range is `-128..=127` error: aborting due to previous error diff --git a/src/test/ui/lint/lint-type-limits3.stderr b/src/test/ui/lint/lint-type-limits3.stderr index 00441f99e60d9..150e9a2aa4792 100644 --- a/src/test/ui/lint/lint-type-limits3.stderr +++ b/src/test/ui/lint/lint-type-limits3.stderr @@ -17,6 +17,7 @@ note: the lint level is defined here | LL | #![warn(overflowing_literals)] | ^^^^^^^^^^^^^^^^^^^^ + = note: the literal `200` does not fit into the type `i8` whose range is `-128..=127` error: aborting due to previous error diff --git a/src/test/ui/lint/lint-type-overflow.stderr b/src/test/ui/lint/lint-type-overflow.stderr index ec15313158d5b..7715c0d3a4db9 100644 --- a/src/test/ui/lint/lint-type-overflow.stderr +++ b/src/test/ui/lint/lint-type-overflow.stderr @@ -9,108 +9,143 @@ note: the lint level is defined here | LL | #![deny(overflowing_literals)] | ^^^^^^^^^^^^^^^^^^^^ + = note: the literal `256` does not fit into the type `u8` whose range is `0..=255` error: literal out of range for `u8` --> $DIR/lint-type-overflow.rs:13:14 | LL | let x1 = 256_u8; | ^^^^^^ + | + = note: the literal `256_u8` does not fit into the type `u8` whose range is `0..=255` error: literal out of range for `i8` --> $DIR/lint-type-overflow.rs:16:18 | LL | let x1: i8 = 128; | ^^^ + | + = note: the literal `128` does not fit into the type `i8` whose range is `-128..=127` error: literal out of range for `i8` --> $DIR/lint-type-overflow.rs:18:19 | LL | let x3: i8 = -129; | ^^^ + | + = note: the literal `129` does not fit into the type `i8` whose range is `-128..=127` error: literal out of range for `i8` --> $DIR/lint-type-overflow.rs:19:19 | LL | let x3: i8 = -(129); | ^^^^^ + | + = note: the literal `129` does not fit into the type `i8` whose range is `-128..=127` error: literal out of range for `i8` --> $DIR/lint-type-overflow.rs:20:20 | LL | let x3: i8 = -{129}; | ^^^ + | + = note: the literal `129` does not fit into the type `i8` whose range is `-128..=127` error: literal out of range for `i8` --> $DIR/lint-type-overflow.rs:22:10 | LL | test(1000); | ^^^^ + | + = note: the literal `1000` does not fit into the type `i8` whose range is `-128..=127` error: literal out of range for `i8` --> $DIR/lint-type-overflow.rs:24:13 | LL | let x = 128_i8; | ^^^^^^ + | + = note: the literal `128_i8` does not fit into the type `i8` whose range is `-128..=127` error: literal out of range for `i8` --> $DIR/lint-type-overflow.rs:28:14 | LL | let x = -129_i8; | ^^^^^^ + | + = note: the literal `129_i8` does not fit into the type `i8` whose range is `-128..=127` error: literal out of range for `i32` --> $DIR/lint-type-overflow.rs:32:18 | LL | let x: i32 = 2147483648; | ^^^^^^^^^^ + | + = note: the literal `2147483648` does not fit into the type `i32` whose range is `-2147483648..=2147483647` error: literal out of range for `i32` --> $DIR/lint-type-overflow.rs:33:13 | LL | let x = 2147483648_i32; | ^^^^^^^^^^^^^^ + | + = note: the literal `2147483648_i32` does not fit into the type `i32` whose range is `-2147483648..=2147483647` error: literal out of range for `i32` --> $DIR/lint-type-overflow.rs:36:19 | LL | let x: i32 = -2147483649; | ^^^^^^^^^^ + | + = note: the literal `2147483649` does not fit into the type `i32` whose range is `-2147483648..=2147483647` error: literal out of range for `i32` --> $DIR/lint-type-overflow.rs:37:14 | LL | let x = -2147483649_i32; | ^^^^^^^^^^^^^^ + | + = note: the literal `2147483649_i32` does not fit into the type `i32` whose range is `-2147483648..=2147483647` error: literal out of range for `i32` --> $DIR/lint-type-overflow.rs:38:13 | LL | let x = 2147483648; | ^^^^^^^^^^ + | + = note: the literal `2147483648` does not fit into the type `i32` whose range is `-2147483648..=2147483647` error: literal out of range for `i64` --> $DIR/lint-type-overflow.rs:40:13 | LL | let x = 9223372036854775808_i64; | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `9223372036854775808_i64` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807` error: literal out of range for `i64` --> $DIR/lint-type-overflow.rs:42:13 | LL | let x = 18446744073709551615_i64; | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `18446744073709551615_i64` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807` error: literal out of range for `i64` --> $DIR/lint-type-overflow.rs:43:19 | LL | let x: i64 = -9223372036854775809; | ^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `9223372036854775809` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807` error: literal out of range for `i64` --> $DIR/lint-type-overflow.rs:44:14 | LL | let x = -9223372036854775809_i64; | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `9223372036854775809_i64` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807` error: aborting due to 18 previous errors diff --git a/src/test/ui/lint/lint-type-overflow2.stderr b/src/test/ui/lint/lint-type-overflow2.stderr index dfc691ab91043..61e33b7a260c9 100644 --- a/src/test/ui/lint/lint-type-overflow2.stderr +++ b/src/test/ui/lint/lint-type-overflow2.stderr @@ -9,30 +9,39 @@ note: the lint level is defined here | LL | #![deny(overflowing_literals)] | ^^^^^^^^^^^^^^^^^^^^ + = note: the literal `128` does not fit into the type `i8` whose range is `-128..=127` error: literal out of range for `f32` --> $DIR/lint-type-overflow2.rs:9:14 | LL | let x = -3.40282357e+38_f32; | ^^^^^^^^^^^^^^^^^^ + | + = note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `std::f32::INFINITY` error: literal out of range for `f32` --> $DIR/lint-type-overflow2.rs:10:14 | LL | let x = 3.40282357e+38_f32; | ^^^^^^^^^^^^^^^^^^ + | + = note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `std::f32::INFINITY` error: literal out of range for `f64` --> $DIR/lint-type-overflow2.rs:11:14 | LL | let x = -1.7976931348623159e+308_f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `std::f64::INFINITY` error: literal out of range for `f64` --> $DIR/lint-type-overflow2.rs:12:14 | LL | let x = 1.7976931348623159e+308_f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `std::f64::INFINITY` error: aborting due to 5 previous errors diff --git a/src/test/ui/lint/lint-unused-variables.stderr b/src/test/ui/lint/lint-unused-variables.stderr index 57389f8d12010..d6e684e830651 100644 --- a/src/test/ui/lint/lint-unused-variables.stderr +++ b/src/test/ui/lint/lint-unused-variables.stderr @@ -2,7 +2,7 @@ error: unused variable: `a` --> $DIR/lint-unused-variables.rs:8:5 | LL | a: i32, - | ^ help: consider prefixing with an underscore: `_a` + | ^ help: if this is intentional, prefix it with an underscore: `_a` | note: the lint level is defined here --> $DIR/lint-unused-variables.rs:5:9 @@ -14,61 +14,61 @@ error: unused variable: `b` --> $DIR/lint-unused-variables.rs:14:5 | LL | b: i32, - | ^ help: consider prefixing with an underscore: `_b` + | ^ help: if this is intentional, prefix it with an underscore: `_b` error: unused variable: `a` --> $DIR/lint-unused-variables.rs:68:9 | LL | a: i32, - | ^ help: consider prefixing with an underscore: `_a` + | ^ help: if this is intentional, prefix it with an underscore: `_a` error: unused variable: `b` --> $DIR/lint-unused-variables.rs:74:9 | LL | b: i32, - | ^ help: consider prefixing with an underscore: `_b` + | ^ help: if this is intentional, prefix it with an underscore: `_b` error: unused variable: `b` --> $DIR/lint-unused-variables.rs:42:9 | LL | b: i32, - | ^ help: consider prefixing with an underscore: `_b` + | ^ help: if this is intentional, prefix it with an underscore: `_b` error: unused variable: `b` --> $DIR/lint-unused-variables.rs:47:9 | LL | b: i32, - | ^ help: consider prefixing with an underscore: `_b` + | ^ help: if this is intentional, prefix it with an underscore: `_b` error: unused variable: `a` --> $DIR/lint-unused-variables.rs:22:9 | LL | a: i32, - | ^ help: consider prefixing with an underscore: `_a` + | ^ help: if this is intentional, prefix it with an underscore: `_a` error: unused variable: `b` --> $DIR/lint-unused-variables.rs:29:9 | LL | b: i32, - | ^ help: consider prefixing with an underscore: `_b` + | ^ help: if this is intentional, prefix it with an underscore: `_b` error: unused variable: `b` --> $DIR/lint-unused-variables.rs:34:9 | LL | b: i32, - | ^ help: consider prefixing with an underscore: `_b` + | ^ help: if this is intentional, prefix it with an underscore: `_b` error: unused variable: `b` --> $DIR/lint-unused-variables.rs:55:9 | LL | b: i32, - | ^ help: consider prefixing with an underscore: `_b` + | ^ help: if this is intentional, prefix it with an underscore: `_b` error: unused variable: `b` --> $DIR/lint-unused-variables.rs:60:9 | LL | b: i32, - | ^ help: consider prefixing with an underscore: `_b` + | ^ help: if this is intentional, prefix it with an underscore: `_b` error: aborting due to 11 previous errors diff --git a/src/test/ui/lint/lint-uppercase-variables.stderr b/src/test/ui/lint/lint-uppercase-variables.stderr index 7c2497758d955..1d7e0909e40ab 100644 --- a/src/test/ui/lint/lint-uppercase-variables.stderr +++ b/src/test/ui/lint/lint-uppercase-variables.stderr @@ -22,7 +22,7 @@ warning: unused variable: `Foo` --> $DIR/lint-uppercase-variables.rs:22:9 | LL | Foo => {} - | ^^^ help: consider prefixing with an underscore: `_Foo` + | ^^^ help: if this is intentional, prefix it with an underscore: `_Foo` | note: the lint level is defined here --> $DIR/lint-uppercase-variables.rs:1:9 @@ -35,13 +35,13 @@ warning: unused variable: `Foo` --> $DIR/lint-uppercase-variables.rs:28:9 | LL | let Foo = foo::Foo::Foo; - | ^^^ help: consider prefixing with an underscore: `_Foo` + | ^^^ help: if this is intentional, prefix it with an underscore: `_Foo` warning: unused variable: `Foo` --> $DIR/lint-uppercase-variables.rs:33:17 | LL | fn in_param(Foo: foo::Foo) {} - | ^^^ help: consider prefixing with an underscore: `_Foo` + | ^^^ help: if this is intentional, prefix it with an underscore: `_Foo` error: structure field `X` should have a snake case name --> $DIR/lint-uppercase-variables.rs:10:5 diff --git a/src/test/ui/lint/lint_pre_expansion_extern_module_aux.rs b/src/test/ui/lint/lint_pre_expansion_extern_module_aux.rs new file mode 100644 index 0000000000000..71dec40ea44f0 --- /dev/null +++ b/src/test/ui/lint/lint_pre_expansion_extern_module_aux.rs @@ -0,0 +1,3 @@ +// ignore-test: not a test + +pub fn try() {} diff --git a/src/test/ui/lint/lints-in-foreign-macros.rs b/src/test/ui/lint/lints-in-foreign-macros.rs index c96b8f1a5cf4a..1e8b6788a60bb 100644 --- a/src/test/ui/lint/lints-in-foreign-macros.rs +++ b/src/test/ui/lint/lints-in-foreign-macros.rs @@ -1,7 +1,7 @@ // aux-build:lints-in-foreign-macros.rs // check-pass -#![warn(unused_imports)] //~ missing documentation for crate [missing_docs] +#![warn(unused_imports)] //~ missing documentation for the crate [missing_docs] #![warn(missing_docs)] #[macro_use] diff --git a/src/test/ui/lint/lints-in-foreign-macros.stderr b/src/test/ui/lint/lints-in-foreign-macros.stderr index 207d85a89c723..dcea5adb863f6 100644 --- a/src/test/ui/lint/lints-in-foreign-macros.stderr +++ b/src/test/ui/lint/lints-in-foreign-macros.stderr @@ -26,7 +26,7 @@ warning: unused import: `std::string::ToString` LL | mod d { baz2!(use std::string::ToString;); } | ^^^^^^^^^^^^^^^^^^^^^ -warning: missing documentation for crate +warning: missing documentation for the crate --> $DIR/lints-in-foreign-macros.rs:4:1 | LL | / #![warn(unused_imports)] diff --git a/src/test/ui/lint/type-overflow.stderr b/src/test/ui/lint/type-overflow.stderr index 2432eb78b8732..a7a788b877a6d 100644 --- a/src/test/ui/lint/type-overflow.stderr +++ b/src/test/ui/lint/type-overflow.stderr @@ -9,6 +9,7 @@ note: the lint level is defined here | LL | #![warn(overflowing_literals)] | ^^^^^^^^^^^^^^^^^^^^ + = note: the literal `255i8` does not fit into the type `i8` whose range is `-128..=127` warning: literal out of range for i8 --> $DIR/type-overflow.rs:10:16 @@ -16,7 +17,7 @@ warning: literal out of range for i8 LL | let fail = 0b1000_0001i8; | ^^^^^^^^^^^^^ help: consider using `u8` instead: `0b1000_0001u8` | - = note: the literal `0b1000_0001i8` (decimal `129`) does not fit into an `i8` and will become `-127i8` + = note: the literal `0b1000_0001i8` (decimal `129`) does not fit into the type `i8` and will become `-127i8` warning: literal out of range for i64 --> $DIR/type-overflow.rs:12:16 @@ -24,7 +25,7 @@ warning: literal out of range for i64 LL | let fail = 0x8000_0000_0000_0000i64; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `u64` instead: `0x8000_0000_0000_0000u64` | - = note: the literal `0x8000_0000_0000_0000i64` (decimal `9223372036854775808`) does not fit into an `i64` and will become `-9223372036854775808i64` + = note: the literal `0x8000_0000_0000_0000i64` (decimal `9223372036854775808`) does not fit into the type `i64` and will become `-9223372036854775808i64` warning: literal out of range for u32 --> $DIR/type-overflow.rs:14:16 @@ -32,7 +33,7 @@ warning: literal out of range for u32 LL | let fail = 0x1_FFFF_FFFFu32; | ^^^^^^^^^^^^^^^^ help: consider using `u64` instead: `0x1_FFFF_FFFFu64` | - = note: the literal `0x1_FFFF_FFFFu32` (decimal `8589934591`) does not fit into an `u32` and will become `4294967295u32` + = note: the literal `0x1_FFFF_FFFFu32` (decimal `8589934591`) does not fit into the type `u32` and will become `4294967295u32` warning: literal out of range for i128 --> $DIR/type-overflow.rs:16:22 @@ -40,7 +41,7 @@ warning: literal out of range for i128 LL | let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0000` (decimal `170141183460469231731687303715884105728`) does not fit into an `i128` and will become `-170141183460469231731687303715884105728i128` + = note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0000` (decimal `170141183460469231731687303715884105728`) does not fit into the type `i128` and will become `-170141183460469231731687303715884105728i128` = help: consider using `u128` instead warning: literal out of range for i32 @@ -49,7 +50,7 @@ warning: literal out of range for i32 LL | let fail = 0x8FFF_FFFF_FFFF_FFFE; | ^^^^^^^^^^^^^^^^^^^^^ | - = note: the literal `0x8FFF_FFFF_FFFF_FFFE` (decimal `10376293541461622782`) does not fit into an `i32` and will become `-2i32` + = note: the literal `0x8FFF_FFFF_FFFF_FFFE` (decimal `10376293541461622782`) does not fit into the type `i32` and will become `-2i32` = help: consider using `i128` instead warning: literal out of range for i8 @@ -58,5 +59,5 @@ warning: literal out of range for i8 LL | let fail = -0b1111_1111i8; | ^^^^^^^^^^^^^ help: consider using `i16` instead: `0b1111_1111i16` | - = note: the literal `0b1111_1111i8` (decimal `255`) does not fit into an `i8` and will become `-1i8` + = note: the literal `0b1111_1111i8` (decimal `255`) does not fit into the type `i8` and will become `-1i8` diff --git a/src/test/ui/lint/uninitialized-zeroed.stderr b/src/test/ui/lint/uninitialized-zeroed.stderr index 6d669184deb3e..bf0562713a497 100644 --- a/src/test/ui/lint/uninitialized-zeroed.stderr +++ b/src/test/ui/lint/uninitialized-zeroed.stderr @@ -1,4 +1,4 @@ -error: the type `&'static T` does not permit zero-initialization +error: the type `&T` does not permit zero-initialization --> $DIR/uninitialized-zeroed.rs:29:32 | LL | let _val: &'static T = mem::zeroed(); @@ -14,7 +14,7 @@ LL | #![deny(invalid_value)] | ^^^^^^^^^^^^^ = note: references must be non-null -error: the type `&'static T` does not permit being left uninitialized +error: the type `&T` does not permit being left uninitialized --> $DIR/uninitialized-zeroed.rs:30:32 | LL | let _val: &'static T = mem::uninitialized(); @@ -25,7 +25,7 @@ LL | let _val: &'static T = mem::uninitialized(); | = note: references must be non-null -error: the type `Wrap<&'static T>` does not permit zero-initialization +error: the type `Wrap<&T>` does not permit zero-initialization --> $DIR/uninitialized-zeroed.rs:32:38 | LL | let _val: Wrap<&'static T> = mem::zeroed(); @@ -40,7 +40,7 @@ note: references must be non-null (in this struct field) LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ -error: the type `Wrap<&'static T>` does not permit being left uninitialized +error: the type `Wrap<&T>` does not permit being left uninitialized --> $DIR/uninitialized-zeroed.rs:33:38 | LL | let _val: Wrap<&'static T> = mem::uninitialized(); @@ -121,7 +121,7 @@ LL | let _val: Void = mem::uninitialized(); | = note: enums with no variants have no valid value -error: the type `&'static i32` does not permit zero-initialization +error: the type `&i32` does not permit zero-initialization --> $DIR/uninitialized-zeroed.rs:49:34 | LL | let _val: &'static i32 = mem::zeroed(); @@ -132,7 +132,7 @@ LL | let _val: &'static i32 = mem::zeroed(); | = note: references must be non-null -error: the type `&'static i32` does not permit being left uninitialized +error: the type `&i32` does not permit being left uninitialized --> $DIR/uninitialized-zeroed.rs:50:34 | LL | let _val: &'static i32 = mem::uninitialized(); @@ -366,7 +366,7 @@ LL | let _val: NonBig = mem::uninitialized(); | = note: `NonBig` must be initialized inside its custom valid range -error: the type `&'static i32` does not permit zero-initialization +error: the type `&i32` does not permit zero-initialization --> $DIR/uninitialized-zeroed.rs:84:34 | LL | let _val: &'static i32 = mem::transmute(0usize); @@ -377,7 +377,7 @@ LL | let _val: &'static i32 = mem::transmute(0usize); | = note: references must be non-null -error: the type `&'static [i32]` does not permit zero-initialization +error: the type `&[i32]` does not permit zero-initialization --> $DIR/uninitialized-zeroed.rs:85:36 | LL | let _val: &'static [i32] = mem::transmute((0usize, 0usize)); diff --git a/src/test/ui/lint/use_suggestion_json.stderr b/src/test/ui/lint/use_suggestion_json.stderr index 0dc0d247af5c1..7176f17bc3fab 100644 --- a/src/test/ui/lint/use_suggestion_json.stderr +++ b/src/test/ui/lint/use_suggestion_json.stderr @@ -2,7 +2,7 @@ "message": "cannot find type `Iter` in this scope", "code": { "code": "E0412", - "explanation": "The type name used is not in scope. + "explanation": "A used type name is not in scope. Erroneous code examples: diff --git a/src/test/ui/liveness/liveness-unused.stderr b/src/test/ui/liveness/liveness-unused.stderr index 7adb6a3295b0e..42187330a3eb1 100644 --- a/src/test/ui/liveness/liveness-unused.stderr +++ b/src/test/ui/liveness/liveness-unused.stderr @@ -17,7 +17,7 @@ error: unused variable: `x` --> $DIR/liveness-unused.rs:8:7 | LL | fn f1(x: isize) { - | ^ help: consider prefixing with an underscore: `_x` + | ^ help: if this is intentional, prefix it with an underscore: `_x` | note: the lint level is defined here --> $DIR/liveness-unused.rs:2:9 @@ -29,19 +29,19 @@ error: unused variable: `x` --> $DIR/liveness-unused.rs:12:8 | LL | fn f1b(x: &mut isize) { - | ^ help: consider prefixing with an underscore: `_x` + | ^ help: if this is intentional, prefix it with an underscore: `_x` error: unused variable: `x` --> $DIR/liveness-unused.rs:20:9 | LL | let x: isize; - | ^ help: consider prefixing with an underscore: `_x` + | ^ help: if this is intentional, prefix it with an underscore: `_x` error: unused variable: `x` --> $DIR/liveness-unused.rs:25:9 | LL | let x = 3; - | ^ help: consider prefixing with an underscore: `_x` + | ^ help: if this is intentional, prefix it with an underscore: `_x` error: variable `x` is assigned to, but never used --> $DIR/liveness-unused.rs:30:13 @@ -76,25 +76,25 @@ error: unused variable: `i` --> $DIR/liveness-unused.rs:59:12 | LL | Some(i) => { - | ^ help: consider prefixing with an underscore: `_i` + | ^ help: if this is intentional, prefix it with an underscore: `_i` error: unused variable: `x` --> $DIR/liveness-unused.rs:79:9 | LL | for x in 1..10 { } - | ^ help: consider prefixing with an underscore: `_x` + | ^ help: if this is intentional, prefix it with an underscore: `_x` error: unused variable: `x` --> $DIR/liveness-unused.rs:84:10 | LL | for (x, _) in [1, 2, 3].iter().enumerate() { } - | ^ help: consider prefixing with an underscore: `_x` + | ^ help: if this is intentional, prefix it with an underscore: `_x` error: unused variable: `x` --> $DIR/liveness-unused.rs:89:13 | LL | for (_, x) in [1, 2, 3].iter().enumerate() { - | ^ help: consider prefixing with an underscore: `_x` + | ^ help: if this is intentional, prefix it with an underscore: `_x` error: variable `x` is assigned to, but never used --> $DIR/liveness-unused.rs:112:9 diff --git a/src/test/ui/macros/issue-58490.rs b/src/test/ui/macros/issue-58490.rs new file mode 100644 index 0000000000000..97e71c9a1ce40 --- /dev/null +++ b/src/test/ui/macros/issue-58490.rs @@ -0,0 +1,26 @@ +// Regression test for #58490 + +macro_rules! a { + ( @1 $i:item ) => { + a! { @2 $i } + }; + ( @2 $i:item ) => { + $i + }; +} +mod b { + a! { + @1 + #[macro_export] + macro_rules! b { () => () } + } + #[macro_export] + macro_rules! b { () => () } + //~^ ERROR: the name `b` is defined multiple times +} +mod c { + #[allow(unused_imports)] + use crate::b; +} + +fn main() {} diff --git a/src/test/ui/macros/issue-58490.stderr b/src/test/ui/macros/issue-58490.stderr new file mode 100644 index 0000000000000..b1f0896f3b65c --- /dev/null +++ b/src/test/ui/macros/issue-58490.stderr @@ -0,0 +1,14 @@ +error[E0428]: the name `b` is defined multiple times + --> $DIR/issue-58490.rs:18:5 + | +LL | macro_rules! b { () => () } + | -------------- previous definition of the macro `b` here +... +LL | macro_rules! b { () => () } + | ^^^^^^^^^^^^^^ `b` redefined here + | + = note: `b` must be defined only once in the macro 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/ui/macros/issue-61033-1.rs b/src/test/ui/macros/issue-61033-1.rs index 8f85dec017f2a..18df3f6ee94c1 100644 --- a/src/test/ui/macros/issue-61033-1.rs +++ b/src/test/ui/macros/issue-61033-1.rs @@ -1,9 +1,10 @@ // Regression test for issue #61033. macro_rules! test1 { - ($x:ident, $($tt:tt)*) => { $($tt)+ } //~ERROR this must repeat at least once + ($x:ident, $($tt:tt)*) => { $($tt)+ } //~ ERROR this must repeat at least once } fn main() { test1!(x,); + let _recovery_witness: () = 0; //~ ERROR mismatched types } diff --git a/src/test/ui/macros/issue-61033-1.stderr b/src/test/ui/macros/issue-61033-1.stderr index f3c68f4928dbb..18205c3436b0b 100644 --- a/src/test/ui/macros/issue-61033-1.stderr +++ b/src/test/ui/macros/issue-61033-1.stderr @@ -4,5 +4,14 @@ error: this must repeat at least once LL | ($x:ident, $($tt:tt)*) => { $($tt)+ } | ^^^^^ -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/issue-61033-1.rs:9:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/macros/issue-61033-2.rs b/src/test/ui/macros/issue-61033-2.rs index 0799be10b96c7..1760ba1584d0b 100644 --- a/src/test/ui/macros/issue-61033-2.rs +++ b/src/test/ui/macros/issue-61033-2.rs @@ -5,7 +5,9 @@ macro_rules! test2 { $(* $id1:ident)* $(+ $id2:ident)* ) => { - $( //~ERROR meta-variable `id1` repeats 2 times + $( + //~^ ERROR meta-variable `id1` repeats 2 times + //~| ERROR meta-variable `id1` repeats 2 times $id1 + $id2 // $id1 and $id2 may repeat different numbers of times )* } @@ -16,4 +18,8 @@ fn main() { * a * b + a + b + c } + test2! { + * a * b + + a + b + c + d + } } diff --git a/src/test/ui/macros/issue-61033-2.stderr b/src/test/ui/macros/issue-61033-2.stderr index bf502919cf794..cdfe7934a0cac 100644 --- a/src/test/ui/macros/issue-61033-2.stderr +++ b/src/test/ui/macros/issue-61033-2.stderr @@ -3,9 +3,22 @@ error: meta-variable `id1` repeats 2 times, but `id2` repeats 3 times | LL | $( | __________^ +LL | | +LL | | LL | | $id1 + $id2 // $id1 and $id2 may repeat different numbers of times LL | | )* | |_________^ -error: aborting due to previous error +error: meta-variable `id1` repeats 2 times, but `id2` repeats 4 times + --> $DIR/issue-61033-2.rs:8:10 + | +LL | $( + | __________^ +LL | | +LL | | +LL | | $id1 + $id2 // $id1 and $id2 may repeat different numbers of times +LL | | )* + | |_________^ + +error: aborting due to 2 previous errors diff --git a/src/test/ui/macros/issue-69838-dir/bar.rs b/src/test/ui/macros/issue-69838-dir/bar.rs new file mode 100644 index 0000000000000..ec12f8c5cb442 --- /dev/null +++ b/src/test/ui/macros/issue-69838-dir/bar.rs @@ -0,0 +1,3 @@ +// ignore-test -- this is an auxiliary file as part of another test. + +pub fn i_am_in_bar() {} diff --git a/src/test/ui/macros/issue-69838-dir/included.rs b/src/test/ui/macros/issue-69838-dir/included.rs new file mode 100644 index 0000000000000..9900b8fd5092c --- /dev/null +++ b/src/test/ui/macros/issue-69838-dir/included.rs @@ -0,0 +1,3 @@ +// ignore-test -- this is an auxiliary file as part of another test. + +pub mod bar; diff --git a/src/test/ui/macros/issue-69838-mods-relative-to-included-path.rs b/src/test/ui/macros/issue-69838-mods-relative-to-included-path.rs new file mode 100644 index 0000000000000..2a4e97f0ef5f1 --- /dev/null +++ b/src/test/ui/macros/issue-69838-mods-relative-to-included-path.rs @@ -0,0 +1,7 @@ +// check-pass + +include!("issue-69838-dir/included.rs"); + +fn main() { + bar::i_am_in_bar(); +} diff --git a/src/test/ui/macros/local-ambiguity-multiple-parsing-options.rs b/src/test/ui/macros/local-ambiguity-multiple-parsing-options.rs new file mode 100644 index 0000000000000..3967481098cff --- /dev/null +++ b/src/test/ui/macros/local-ambiguity-multiple-parsing-options.rs @@ -0,0 +1,8 @@ +fn main() {} + +macro_rules! ambiguity { + ($($i:ident)* $j:ident) => {}; +} + +ambiguity!(error); //~ ERROR local ambiguity +ambiguity!(error); //~ ERROR local ambiguity diff --git a/src/test/ui/macros/local-ambiguity-multiple-parsing-options.stderr b/src/test/ui/macros/local-ambiguity-multiple-parsing-options.stderr new file mode 100644 index 0000000000000..0ae56c422213c --- /dev/null +++ b/src/test/ui/macros/local-ambiguity-multiple-parsing-options.stderr @@ -0,0 +1,14 @@ +error: local ambiguity: multiple parsing options: built-in NTs ident ('i') or ident ('j'). + --> $DIR/local-ambiguity-multiple-parsing-options.rs:7:12 + | +LL | ambiguity!(error); + | ^^^^^ + +error: local ambiguity: multiple parsing options: built-in NTs ident ('i') or ident ('j'). + --> $DIR/local-ambiguity-multiple-parsing-options.rs:8:12 + | +LL | ambiguity!(error); + | ^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/macros/macro-comma-behavior.core.stderr b/src/test/ui/macros/macro-comma-behavior.core.stderr index dd0cac659fd31..83a88ab3bd97c 100644 --- a/src/test/ui/macros/macro-comma-behavior.core.stderr +++ b/src/test/ui/macros/macro-comma-behavior.core.stderr @@ -1,41 +1,41 @@ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:21:23 + --> $DIR/macro-comma-behavior.rs:20:23 | LL | assert_eq!(1, 1, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:24:23 + --> $DIR/macro-comma-behavior.rs:23:23 | LL | assert_ne!(1, 2, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:30:29 + --> $DIR/macro-comma-behavior.rs:29:29 | LL | debug_assert_eq!(1, 1, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:33:29 + --> $DIR/macro-comma-behavior.rs:32:29 | LL | debug_assert_ne!(1, 2, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:54:19 + --> $DIR/macro-comma-behavior.rs:53:19 | LL | format_args!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:72:21 + --> $DIR/macro-comma-behavior.rs:71:21 | LL | unimplemented!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:81:24 + --> $DIR/macro-comma-behavior.rs:80:24 | LL | write!(f, "{}",)?; | ^^ diff --git a/src/test/ui/macros/macro-comma-behavior.rs b/src/test/ui/macros/macro-comma-behavior.rs index 006319aa9f5b2..04714c65b5cb7 100644 --- a/src/test/ui/macros/macro-comma-behavior.rs +++ b/src/test/ui/macros/macro-comma-behavior.rs @@ -9,7 +9,6 @@ #[cfg(std)] use std::fmt; #[cfg(core)] use core::fmt; #[cfg(core)] #[lang = "eh_personality"] fn eh_personality() {} -#[cfg(core)] #[lang = "eh_unwind_resume"] fn eh_unwind_resume() {} #[cfg(core)] #[lang = "panic_impl"] fn panic_impl(panic: &core::panic::PanicInfo) -> ! { loop {} } // (see documentation of the similarly-named test in run-pass) diff --git a/src/test/ui/macros/macro-comma-behavior.std.stderr b/src/test/ui/macros/macro-comma-behavior.std.stderr index 4372d89fbf522..26445f2c5c542 100644 --- a/src/test/ui/macros/macro-comma-behavior.std.stderr +++ b/src/test/ui/macros/macro-comma-behavior.std.stderr @@ -1,59 +1,59 @@ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:21:23 + --> $DIR/macro-comma-behavior.rs:20:23 | LL | assert_eq!(1, 1, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:24:23 + --> $DIR/macro-comma-behavior.rs:23:23 | LL | assert_ne!(1, 2, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:30:29 + --> $DIR/macro-comma-behavior.rs:29:29 | LL | debug_assert_eq!(1, 1, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:33:29 + --> $DIR/macro-comma-behavior.rs:32:29 | LL | debug_assert_ne!(1, 2, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:38:18 + --> $DIR/macro-comma-behavior.rs:37:18 | LL | eprint!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:50:18 + --> $DIR/macro-comma-behavior.rs:49:18 | LL | format!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:54:19 + --> $DIR/macro-comma-behavior.rs:53:19 | LL | format_args!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:61:17 + --> $DIR/macro-comma-behavior.rs:60:17 | LL | print!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:72:21 + --> $DIR/macro-comma-behavior.rs:71:21 | LL | unimplemented!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:81:24 + --> $DIR/macro-comma-behavior.rs:80:24 | LL | write!(f, "{}",)?; | ^^ diff --git a/src/test/ui/macros/macro-context.rs b/src/test/ui/macros/macro-context.rs index 9130c3d921c52..13e179578ad01 100644 --- a/src/test/ui/macros/macro-context.rs +++ b/src/test/ui/macros/macro-context.rs @@ -4,6 +4,8 @@ macro_rules! m { //~| ERROR macro expansion ignores token `typeof` //~| ERROR macro expansion ignores token `;` //~| ERROR macro expansion ignores token `;` + //~| ERROR cannot find type `i` in this scope + //~| ERROR cannot find value `i` in this scope } fn main() { diff --git a/src/test/ui/macros/macro-context.stderr b/src/test/ui/macros/macro-context.stderr index 2e712110689f8..17c7389812475 100644 --- a/src/test/ui/macros/macro-context.stderr +++ b/src/test/ui/macros/macro-context.stderr @@ -42,5 +42,29 @@ LL | m!(); | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 4 previous errors +error[E0412]: cannot find type `i` in this scope + --> $DIR/macro-context.rs:3:13 + | +LL | () => ( i ; typeof ); + | ^ help: a builtin type with a similar name exists: `i8` +... +LL | let a: m!(); + | ---- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `i` in this scope + --> $DIR/macro-context.rs:3:13 + | +LL | () => ( i ; typeof ); + | ^ help: a local variable with a similar name exists: `a` +... +LL | let i = m!(); + | ---- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 6 previous errors +Some errors have detailed explanations: E0412, E0425. +For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/macros/macro-local-data-key-priv.stderr b/src/test/ui/macros/macro-local-data-key-priv.stderr index c53a09aad5783..3092d76c268ad 100644 --- a/src/test/ui/macros/macro-local-data-key-priv.stderr +++ b/src/test/ui/macros/macro-local-data-key-priv.stderr @@ -2,7 +2,7 @@ error[E0603]: constant `baz` is private --> $DIR/macro-local-data-key-priv.rs:8:10 | LL | bar::baz.with(|_| ()); - | ^^^ this constant is private + | ^^^ private constant | note: the constant `baz` is defined here --> $DIR/macro-local-data-key-priv.rs:4:5 diff --git a/src/test/ui/macros/macro-match-nonterminal.rs b/src/test/ui/macros/macro-match-nonterminal.rs index 6d4b32c9bc9a0..b23e5c71c03f0 100644 --- a/src/test/ui/macros/macro-match-nonterminal.rs +++ b/src/test/ui/macros/macro-match-nonterminal.rs @@ -1,4 +1,11 @@ -macro_rules! test { ($a, $b) => (()); } //~ ERROR missing fragment +macro_rules! test { + ($a, $b) => { + //~^ ERROR missing fragment + //~| ERROR missing fragment + //~| WARN this was previously accepted + () + }; +} fn main() { test!() diff --git a/src/test/ui/macros/macro-match-nonterminal.stderr b/src/test/ui/macros/macro-match-nonterminal.stderr index 1de8c5bd4b472..674ce3434aac6 100644 --- a/src/test/ui/macros/macro-match-nonterminal.stderr +++ b/src/test/ui/macros/macro-match-nonterminal.stderr @@ -1,8 +1,18 @@ error: missing fragment specifier - --> $DIR/macro-match-nonterminal.rs:1:24 + --> $DIR/macro-match-nonterminal.rs:2:8 | -LL | macro_rules! test { ($a, $b) => (()); } - | ^ +LL | ($a, $b) => { + | ^ -error: aborting due to previous error +error: missing fragment specifier + --> $DIR/macro-match-nonterminal.rs:2:10 + | +LL | ($a, $b) => { + | ^^ + | + = note: `#[deny(missing_fragment_specifier)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #40107 + +error: aborting due to 2 previous errors diff --git a/src/test/ui/macros/macro_undefined.stderr b/src/test/ui/macros/macro_undefined.stderr index b2caba893e072..4ab16bd10173d 100644 --- a/src/test/ui/macros/macro_undefined.stderr +++ b/src/test/ui/macros/macro_undefined.stderr @@ -1,13 +1,11 @@ error: cannot find macro `k` in this scope --> $DIR/macro_undefined.rs:11:5 | -LL | / macro_rules! kl { -LL | | () => () -LL | | } - | |_____- similarly named macro `kl` defined here +LL | macro_rules! kl { + | --------------- similarly named macro `kl` defined here ... -LL | k!(); - | ^ help: a macro with a similar name exists: `kl` +LL | k!(); + | ^ help: a macro with a similar name exists: `kl` error: aborting due to previous error diff --git a/src/test/ui/macros/trace-macro.stderr b/src/test/ui/macros/trace-macro.stderr index 202a9235adbac..6217decd8ef88 100644 --- a/src/test/ui/macros/trace-macro.stderr +++ b/src/test/ui/macros/trace-macro.stderr @@ -5,5 +5,5 @@ LL | println!("Hello, World!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expanding `println! { "Hello, World!" }` - = note: to `{ $crate :: io :: _print ($crate :: format_args_nl ! ("Hello, World!")) ; }` + = note: to `{ $crate :: io :: _print($crate :: format_args_nl ! ("Hello, World!")) ; }` diff --git a/src/test/ui/macros/trace_faulty_macros.rs b/src/test/ui/macros/trace_faulty_macros.rs index 627d58abf4ca2..5a8e2f50ce33d 100644 --- a/src/test/ui/macros/trace_faulty_macros.rs +++ b/src/test/ui/macros/trace_faulty_macros.rs @@ -1,6 +1,6 @@ // compile-flags: -Z trace-macros -#![recursion_limit="4"] +#![recursion_limit = "4"] macro_rules! my_faulty_macro { () => { @@ -13,7 +13,7 @@ macro_rules! pat_macro { pat_macro!(A{a:a, b:0, c:_, ..}); }; ($a:pat) => { - $a + $a //~ ERROR expected expression }; } @@ -24,9 +24,7 @@ macro_rules! my_recursive_macro { } macro_rules! my_macro { - () => { - - }; + () => {}; } fn main() { @@ -39,7 +37,7 @@ fn main() { } #[my_macro] -fn use_bang_macro_as_attr(){} +fn use_bang_macro_as_attr() {} -#[derive(Debug)] -fn use_derive_macro_as_attr(){} +#[derive(Debug)] //~ ERROR `derive` may only be applied to structs +fn use_derive_macro_as_attr() {} diff --git a/src/test/ui/macros/trace_faulty_macros.stderr b/src/test/ui/macros/trace_faulty_macros.stderr index a18e22e07f8bc..aec9d1ab191af 100644 --- a/src/test/ui/macros/trace_faulty_macros.stderr +++ b/src/test/ui/macros/trace_faulty_macros.stderr @@ -13,7 +13,7 @@ LL | my_faulty_macro!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) note: trace_macro - --> $DIR/trace_faulty_macros.rs:33:5 + --> $DIR/trace_faulty_macros.rs:31:5 | LL | my_faulty_macro!(); | ^^^^^^^^^^^^^^^^^^^ @@ -35,7 +35,7 @@ LL | my_recursive_macro!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) note: trace_macro - --> $DIR/trace_faulty_macros.rs:34:5 + --> $DIR/trace_faulty_macros.rs:32:5 | LL | my_recursive_macro!(); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -49,5 +49,33 @@ LL | my_recursive_macro!(); = note: expanding `my_recursive_macro! { }` = note: to `my_recursive_macro ! () ;` -error: aborting due to 2 previous errors +error: expected expression, found `A { a: a, b: 0, c: _, .. }` + --> $DIR/trace_faulty_macros.rs:16:9 + | +LL | $a + | ^^ expected expression +... +LL | let a = pat_macro!(); + | ------------ in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: `derive` may only be applied to structs, enums and unions + --> $DIR/trace_faulty_macros.rs:42:1 + | +LL | #[derive(Debug)] + | ^^^^^^^^^^^^^^^^ + +note: trace_macro + --> $DIR/trace_faulty_macros.rs:36:13 + | +LL | let a = pat_macro!(); + | ^^^^^^^^^^^^ + | + = note: expanding `pat_macro! { }` + = note: to `pat_macro ! (A { a : a, b : 0, c : _, .. }) ;` + = note: expanding `pat_macro! { A { a : a, b : 0, c : _, .. } }` + = note: to `A { a: a, b: 0, c: _, .. }` + +error: aborting due to 4 previous errors diff --git a/src/test/ui/match/match-fn-call.stderr b/src/test/ui/match/match-fn-call.stderr index 2d7a0f1614197..297aa4cd95def 100644 --- a/src/test/ui/match/match-fn-call.stderr +++ b/src/test/ui/match/match-fn-call.stderr @@ -1,4 +1,4 @@ -error[E0164]: expected tuple struct or tuple variant, found method `Path::new` +error[E0164]: expected tuple struct or tuple variant, found associated function `Path::new` --> $DIR/match-fn-call.rs:6:9 | LL | Path::new("foo") => println!("foo"), @@ -6,7 +6,7 @@ LL | Path::new("foo") => println!("foo"), | = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html -error[E0164]: expected tuple struct or tuple variant, found method `Path::new` +error[E0164]: expected tuple struct or tuple variant, found associated function `Path::new` --> $DIR/match-fn-call.rs:8:9 | LL | Path::new("bar") => println!("bar"), diff --git a/src/test/ui/methods/assign-to-method.stderr b/src/test/ui/methods/assign-to-method.stderr index c0dd529b6818f..cafe9abae045d 100644 --- a/src/test/ui/methods/assign-to-method.stderr +++ b/src/test/ui/methods/assign-to-method.stderr @@ -2,7 +2,7 @@ error[E0615]: attempted to take value of method `speak` on type `Cat` --> $DIR/assign-to-method.rs:22:10 | LL | nyan.speak = || println!("meow"); - | ^^^^^ + | ^^^^^ method, not a field | = help: methods are immutable and cannot be assigned to @@ -10,7 +10,7 @@ error[E0615]: attempted to take value of method `speak` on type `Cat` --> $DIR/assign-to-method.rs:23:10 | LL | nyan.speak += || println!("meow"); - | ^^^^^ + | ^^^^^ method, not a field | = help: methods are immutable and cannot be assigned to diff --git a/src/test/ui/methods/method-ambig-two-traits-from-impls2.stderr b/src/test/ui/methods/method-ambig-two-traits-from-impls2.stderr index 44f85071505d2..249464108875c 100644 --- a/src/test/ui/methods/method-ambig-two-traits-from-impls2.stderr +++ b/src/test/ui/methods/method-ambig-two-traits-from-impls2.stderr @@ -1,8 +1,8 @@ error[E0034]: multiple applicable items in scope - --> $DIR/method-ambig-two-traits-from-impls2.rs:15:5 + --> $DIR/method-ambig-two-traits-from-impls2.rs:15:9 | LL | AB::foo(); - | ^^^^^^^ multiple `foo` found + | ^^^ multiple `foo` found | note: candidate #1 is defined in an impl of the trait `A` for the type `AB` --> $DIR/method-ambig-two-traits-from-impls2.rs:7:5 diff --git a/src/test/ui/methods/method-missing-call.stderr b/src/test/ui/methods/method-missing-call.stderr index 3ab5f66a0c3f6..bc8a1c85e561a 100644 --- a/src/test/ui/methods/method-missing-call.stderr +++ b/src/test/ui/methods/method-missing-call.stderr @@ -2,13 +2,23 @@ error[E0615]: attempted to take value of method `get_x` on type `Point` --> $DIR/method-missing-call.rs:22:26 | LL | .get_x; - | ^^^^^ help: use parentheses to call the method: `get_x()` + | ^^^^^ method, not a field + | +help: use parentheses to call the method + | +LL | .get_x(); + | ^^ error[E0615]: attempted to take value of method `filter_map` on type `std::iter::Filter, [closure@$DIR/method-missing-call.rs:27:20: 27:25]>, [closure@$DIR/method-missing-call.rs:28:23: 28:35]>` --> $DIR/method-missing-call.rs:29:16 | LL | .filter_map; - | ^^^^^^^^^^ help: use parentheses to call the method: `filter_map(...)` + | ^^^^^^^^^^ method, not a field + | +help: use parentheses to call the method + | +LL | .filter_map(_); + | ^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/methods/method-path-in-pattern.rs b/src/test/ui/methods/method-path-in-pattern.rs index f94be1734b7b1..40645309552ef 100644 --- a/src/test/ui/methods/method-path-in-pattern.rs +++ b/src/test/ui/methods/method-path-in-pattern.rs @@ -13,20 +13,20 @@ impl MyTrait for Foo {} fn main() { match 0u32 { Foo::bar => {} - //~^ ERROR expected unit struct, unit variant or constant, found method `Foo::bar` + //~^ ERROR expected unit struct, unit variant or constant, found associated function } match 0u32 { ::bar => {} - //~^ ERROR expected unit struct, unit variant or constant, found method `Foo::bar` + //~^ ERROR expected unit struct, unit variant or constant, found associated function } match 0u32 { ::trait_bar => {} - //~^ ERROR expected unit struct, unit variant or constant, found method `Foo::trait_bar` + //~^ ERROR expected unit struct, unit variant or constant, found associated function } if let Foo::bar = 0u32 {} - //~^ ERROR expected unit struct, unit variant or constant, found method `Foo::bar` + //~^ ERROR expected unit struct, unit variant or constant, found associated function if let ::bar = 0u32 {} - //~^ ERROR expected unit struct, unit variant or constant, found method `Foo::bar` + //~^ ERROR expected unit struct, unit variant or constant, found associated function if let Foo::trait_bar = 0u32 {} - //~^ ERROR expected unit struct, unit variant or constant, found method `Foo::trait_bar` + //~^ ERROR expected unit struct, unit variant or constant, found associated function } diff --git a/src/test/ui/methods/method-path-in-pattern.stderr b/src/test/ui/methods/method-path-in-pattern.stderr index 6b0c5946ff8d8..1d1bdb6b052a8 100644 --- a/src/test/ui/methods/method-path-in-pattern.stderr +++ b/src/test/ui/methods/method-path-in-pattern.stderr @@ -1,34 +1,34 @@ -error[E0533]: expected unit struct, unit variant or constant, found method `Foo::bar` +error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar` --> $DIR/method-path-in-pattern.rs:15:9 | LL | Foo::bar => {} | ^^^^^^^^ -error[E0533]: expected unit struct, unit variant or constant, found method `Foo::bar` +error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar` --> $DIR/method-path-in-pattern.rs:19:9 | LL | ::bar => {} | ^^^^^^^^^^ -error[E0533]: expected unit struct, unit variant or constant, found method `Foo::trait_bar` +error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::trait_bar` --> $DIR/method-path-in-pattern.rs:23:9 | LL | ::trait_bar => {} | ^^^^^^^^^^^^^^^^ -error[E0533]: expected unit struct, unit variant or constant, found method `Foo::bar` +error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar` --> $DIR/method-path-in-pattern.rs:26:12 | LL | if let Foo::bar = 0u32 {} | ^^^^^^^^ -error[E0533]: expected unit struct, unit variant or constant, found method `Foo::bar` +error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar` --> $DIR/method-path-in-pattern.rs:28:12 | LL | if let ::bar = 0u32 {} | ^^^^^^^^^^ -error[E0533]: expected unit struct, unit variant or constant, found method `Foo::trait_bar` +error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::trait_bar` --> $DIR/method-path-in-pattern.rs:30:12 | LL | if let Foo::trait_bar = 0u32 {} diff --git a/src/test/ui/methods/method-resolvable-path-in-pattern.rs b/src/test/ui/methods/method-resolvable-path-in-pattern.rs index c05160792d360..2973800a4d43b 100644 --- a/src/test/ui/methods/method-resolvable-path-in-pattern.rs +++ b/src/test/ui/methods/method-resolvable-path-in-pattern.rs @@ -9,6 +9,6 @@ impl MyTrait for Foo {} fn main() { match 0u32 { ::trait_bar => {} - //~^ ERROR expected unit struct, unit variant or constant, found method `MyTrait::trait_bar` + //~^ ERROR expected unit struct, unit variant or constant, found associated function } } diff --git a/src/test/ui/methods/method-resolvable-path-in-pattern.stderr b/src/test/ui/methods/method-resolvable-path-in-pattern.stderr index 4b25b694e13ac..7c454a9a777c5 100644 --- a/src/test/ui/methods/method-resolvable-path-in-pattern.stderr +++ b/src/test/ui/methods/method-resolvable-path-in-pattern.stderr @@ -1,4 +1,4 @@ -error[E0532]: expected unit struct, unit variant or constant, found method `MyTrait::trait_bar` +error[E0532]: expected unit struct, unit variant or constant, found associated function `MyTrait::trait_bar` --> $DIR/method-resolvable-path-in-pattern.rs:11:9 | LL | ::trait_bar => {} diff --git a/src/test/ui/mir/issue-60390.rs b/src/test/ui/mir/issue-60390.rs new file mode 100644 index 0000000000000..fd9d6b46dd444 --- /dev/null +++ b/src/test/ui/mir/issue-60390.rs @@ -0,0 +1,8 @@ +// check-pass +// compile-flags: --emit=mir,link +// Regression test for #60390, this ICE requires `--emit=mir` flag. + +fn main() { + enum Inner { Member(u32) }; + Inner::Member(0); +} diff --git a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr index 98b74e5f5cbca..91b3fe15c4be7 100644 --- a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr +++ b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr @@ -1,10 +1,10 @@ error[E0583]: file not found for module `missing` - --> $DIR/foo.rs:4:5 + --> $DIR/foo.rs:4:1 | LL | mod missing; - | ^^^^^^^ + | ^^^^^^^^^^^^ | - = help: name the file either foo/missing.rs or foo/missing/mod.rs inside the directory "$DIR" + = help: to create the module `missing`, create file "$DIR/foo/missing.rs" error: aborting due to previous error diff --git a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr index 457e8fcccbfb3..f519de46c767f 100644 --- a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr +++ b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr @@ -1,10 +1,10 @@ error[E0583]: file not found for module `missing` - --> $DIR/foo_inline.rs:4:9 + --> $DIR/foo_inline.rs:4:5 | LL | mod missing; - | ^^^^^^^ + | ^^^^^^^^^^^^ | - = help: name the file either missing.rs or missing/mod.rs inside the directory "$DIR/foo_inline/inline" + = help: to create the module `missing`, create file "$DIR/foo_inline/inline/missing.rs" error: aborting due to previous error diff --git a/src/test/ui/mod/mod_file_disambig.rs b/src/test/ui/mod/mod_file_disambig.rs index ef203ef082b22..7b182421d34e3 100644 --- a/src/test/ui/mod/mod_file_disambig.rs +++ b/src/test/ui/mod/mod_file_disambig.rs @@ -2,4 +2,5 @@ mod mod_file_disambig_aux; //~ ERROR file for module `mod_file_disambig_aux` fou fn main() { assert_eq!(mod_file_aux::bar(), 10); + //~^ ERROR failed to resolve: use of undeclared type or module `mod_file_aux` } diff --git a/src/test/ui/mod/mod_file_disambig.stderr b/src/test/ui/mod/mod_file_disambig.stderr index 2b77d866fb30b..490633a3fb0ab 100644 --- a/src/test/ui/mod/mod_file_disambig.stderr +++ b/src/test/ui/mod/mod_file_disambig.stderr @@ -1,11 +1,18 @@ error[E0584]: file for module `mod_file_disambig_aux` found at both mod_file_disambig_aux.rs and mod_file_disambig_aux/mod.rs - --> $DIR/mod_file_disambig.rs:1:5 + --> $DIR/mod_file_disambig.rs:1:1 | LL | mod mod_file_disambig_aux; - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: delete or rename one of them to remove the ambiguity -error: aborting due to previous error +error[E0433]: failed to resolve: use of undeclared type or module `mod_file_aux` + --> $DIR/mod_file_disambig.rs:4:16 + | +LL | assert_eq!(mod_file_aux::bar(), 10); + | ^^^^^^^^^^^^ use of undeclared type or module `mod_file_aux` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0584`. +Some errors have detailed explanations: E0433, E0584. +For more information about an error, try `rustc --explain E0433`. diff --git a/src/test/ui/mut/mutable-enum-indirect.rs b/src/test/ui/mut/mutable-enum-indirect.rs index 611ff0d66a24e..502859c041353 100644 --- a/src/test/ui/mut/mutable-enum-indirect.rs +++ b/src/test/ui/mut/mutable-enum-indirect.rs @@ -1,7 +1,7 @@ // Tests that an `&` pointer to something inherently mutable is itself // to be considered mutable. -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Sync; diff --git a/src/test/ui/never_type/auto-traits.rs b/src/test/ui/never_type/auto-traits.rs index 2d9689888cb30..84c8db4053e4f 100644 --- a/src/test/ui/never_type/auto-traits.rs +++ b/src/test/ui/never_type/auto-traits.rs @@ -1,6 +1,7 @@ // check-pass #![feature(optin_builtin_traits)] +#![feature(negative_impls)] #![feature(never_type)] fn main() { diff --git a/src/test/ui/never_type/never-assign-dead-code.stderr b/src/test/ui/never_type/never-assign-dead-code.stderr index 6002f8e1eb75e..5525802c2511a 100644 --- a/src/test/ui/never_type/never-assign-dead-code.stderr +++ b/src/test/ui/never_type/never-assign-dead-code.stderr @@ -25,7 +25,7 @@ warning: unused variable: `x` --> $DIR/never-assign-dead-code.rs:9:9 | LL | let x: ! = panic!("aah"); - | ^ help: consider prefixing with an underscore: `_x` + | ^ help: if this is intentional, prefix it with an underscore: `_x` | note: the lint level is defined here --> $DIR/never-assign-dead-code.rs:6:9 diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr index b4e18c229fdfd..f0d169f419c73 100644 --- a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr +++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr @@ -7,6 +7,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y); = note: defining type: test::{{closure}}#0 with closure substs [ i16, for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) mut &ReLateBound(DebruijnIndex(0), BrNamed('s)) i32, &ReLateBound(DebruijnIndex(0), BrNamed('t0)) i32)), + (), ] error: lifetime may not live long enough diff --git a/src/test/ui/nll/closure-requirements/escape-argument.stderr b/src/test/ui/nll/closure-requirements/escape-argument.stderr index 533a17bdd128b..e251e69997eba 100644 --- a/src/test/ui/nll/closure-requirements/escape-argument.stderr +++ b/src/test/ui/nll/closure-requirements/escape-argument.stderr @@ -7,6 +7,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y); = note: defining type: test::{{closure}}#0 with closure substs [ i16, for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) mut &ReLateBound(DebruijnIndex(0), BrNamed('s)) i32, &ReLateBound(DebruijnIndex(0), BrNamed('s)) i32)), + (), ] note: no external requirements diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr index 60d02066e2676..36257700bef0c 100644 --- a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr +++ b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr @@ -7,8 +7,7 @@ LL | let mut closure1 = || p = &y; = note: defining type: test::{{closure}}#0::{{closure}}#0 with closure substs [ i16, extern "rust-call" fn(()), - &'_#1r i32, - &'_#2r mut &'_#3r i32, + (&'_#1r i32, &'_#2r mut &'_#3r i32), ] = note: number of external vids: 4 = note: where '_#1r: '_#3r @@ -26,8 +25,7 @@ LL | | }; = note: defining type: test::{{closure}}#0 with closure substs [ i16, extern "rust-call" fn(()), - &'_#1r i32, - &'_#2r mut &'_#3r i32, + (&'_#1r i32, &'_#2r mut &'_#3r i32), ] = note: number of external vids: 4 = note: where '_#1r: '_#3r diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr index f64ccf14ac482..d1c64fac3c1e3 100644 --- a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr +++ b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr @@ -7,8 +7,7 @@ LL | let mut closure = || p = &y; = note: defining type: test::{{closure}}#0 with closure substs [ i16, extern "rust-call" fn(()), - &'_#1r i32, - &'_#2r mut &'_#3r i32, + (&'_#1r i32, &'_#2r mut &'_#3r i32), ] = note: number of external vids: 4 = note: where '_#1r: '_#3r diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr index e1e0cdc153a6c..549ebb78d7887 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr @@ -11,6 +11,7 @@ LL | | }, = note: defining type: supply::{{closure}}#0 with closure substs [ i16, for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>)), + (), ] = note: late-bound region is '_#4r = note: late-bound region is '_#5r diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr index b6535024a4a76..346b4af6caac8 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr @@ -12,6 +12,7 @@ LL | | }); = note: defining type: supply::{{closure}}#0 with closure substs [ i16, for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t1)) u32>)), + (), ] = note: late-bound region is '_#3r = note: late-bound region is '_#4r diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr index f5723ba5da5ba..3b1769ed3a2ee 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr @@ -11,6 +11,7 @@ LL | | }) = note: defining type: case1::{{closure}}#0 with closure substs [ i32, for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>)), + (), ] error[E0521]: borrowed data escapes outside of closure @@ -49,6 +50,7 @@ LL | | }) = note: defining type: case2::{{closure}}#0 with closure substs [ i32, for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>)), + (), ] = note: number of external vids: 2 = note: where '_#1r: '_#0r diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr index 17d33e82ba7e3..b167dafff0136 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -13,6 +13,7 @@ LL | | }); = note: defining type: supply::{{closure}}#0 with closure substs [ i16, for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t1)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t2)) u32>)), + (), ] = note: late-bound region is '_#2r = note: late-bound region is '_#3r diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr index 5dce8d087d6cd..91aacc3dff60f 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -13,6 +13,7 @@ LL | | }); = note: defining type: supply::{{closure}}#0 with closure substs [ i16, for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t0)) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed('t1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t1)) u32>)), + (), ] = note: late-bound region is '_#3r = note: late-bound region is '_#4r diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr index 5c5d510805bdf..ae447708621ed 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr @@ -12,6 +12,7 @@ LL | | }); = note: defining type: test::{{closure}}#0 with closure substs [ i16, for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>)), + (), ] = note: late-bound region is '_#3r = note: late-bound region is '_#4r diff --git a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr index c111e651832ba..256446a6e8d8d 100644 --- a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr @@ -11,6 +11,7 @@ LL | | }, = note: defining type: supply::{{closure}}#0 with closure substs [ i16, for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>)), + (), ] = note: late-bound region is '_#3r = note: number of external vids: 4 diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr index 52df46ed3453f..5c156d0d1e378 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr @@ -12,6 +12,7 @@ LL | | }); = note: defining type: supply::{{closure}}#0 with closure substs [ i16, for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>)), + (), ] = note: late-bound region is '_#2r = note: late-bound region is '_#3r diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr index 0270cc40de6fc..46e3f2e75f49e 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr @@ -12,6 +12,7 @@ LL | | }); = note: defining type: supply::{{closure}}#0 with closure substs [ i16, for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t1)) u32>)), + (), ] = note: late-bound region is '_#3r = note: late-bound region is '_#4r diff --git a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr index b705ad9009a29..ef941472894b2 100644 --- a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr @@ -14,6 +14,7 @@ LL | | }); = note: defining type: supply::<'_#1r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((T,)), + (), ] = note: number of external vids: 2 = note: where T: '_#1r diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr index 79ed1501524bd..2a382030f935c 100644 --- a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr +++ b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr @@ -7,6 +7,7 @@ LL | expect_sig(|a, b| b); // ought to return `a` = note: defining type: test::{{closure}}#0 with closure substs [ i16, for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) i32, &ReLateBound(DebruijnIndex(0), BrNamed('s)) i32)) -> &ReLateBound(DebruijnIndex(0), BrNamed('r)) i32, + (), ] error: lifetime may not live long enough diff --git a/src/test/ui/nll/outlives-suggestion-simple.rs b/src/test/ui/nll/outlives-suggestion-simple.rs index ee5a80ae6483f..41e4d83aa9213 100644 --- a/src/test/ui/nll/outlives-suggestion-simple.rs +++ b/src/test/ui/nll/outlives-suggestion-simple.rs @@ -70,7 +70,7 @@ pub struct Foo2<'a> { impl<'a> Foo2<'a> { // should not produce outlives suggestions to name 'self fn get_bar(&self) -> Bar2 { - Bar2::new(&self) //~ERROR borrowed data escapes outside of method + Bar2::new(&self) //~ERROR borrowed data escapes outside of associated function } } diff --git a/src/test/ui/nll/outlives-suggestion-simple.stderr b/src/test/ui/nll/outlives-suggestion-simple.stderr index cf55603cd71f5..6300ea66511fb 100644 --- a/src/test/ui/nll/outlives-suggestion-simple.stderr +++ b/src/test/ui/nll/outlives-suggestion-simple.stderr @@ -93,16 +93,16 @@ LL | self.x | = help: consider adding the following bound: `'b: 'a` -error[E0521]: borrowed data escapes outside of method +error[E0521]: borrowed data escapes outside of associated function --> $DIR/outlives-suggestion-simple.rs:73:9 | LL | fn get_bar(&self) -> Bar2 { | ----- | | - | `self` declared here, outside of the method body - | `self` is a reference that is only valid in the method body + | `self` declared here, outside of the associated function body + | `self` is a reference that is only valid in the associated function body LL | Bar2::new(&self) - | ^^^^^^^^^^^^^^^^ `self` escapes the method body here + | ^^^^^^^^^^^^^^^^ `self` escapes the associated function body here error: aborting due to 9 previous errors diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr index 84365465eda86..38e59ae3e26ba 100644 --- a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr @@ -7,6 +7,7 @@ LL | with_signature(x, |mut y| Box::new(y.next())) = note: defining type: no_region::<'_#1r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::boxed::Box,)) -> std::boxed::Box<(dyn Anything + '_#2r)>, + (), ] = note: number of external vids: 3 = note: where ::Item: '_#2r @@ -42,6 +43,7 @@ LL | with_signature(x, |mut y| Box::new(y.next())) = note: defining type: correct_region::<'_#1r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::boxed::Box,)) -> std::boxed::Box<(dyn Anything + '_#2r)>, + (), ] = note: number of external vids: 3 = note: where ::Item: '_#2r @@ -68,6 +70,7 @@ LL | with_signature(x, |mut y| Box::new(y.next())) = note: defining type: wrong_region::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::boxed::Box,)) -> std::boxed::Box<(dyn Anything + '_#3r)>, + (), ] = note: number of external vids: 4 = note: where ::Item: '_#3r @@ -103,6 +106,7 @@ LL | with_signature(x, |mut y| Box::new(y.next())) = note: defining type: outlives_region::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::boxed::Box,)) -> std::boxed::Box<(dyn Anything + '_#3r)>, + (), ] = note: number of external vids: 4 = note: where ::Item: '_#3r diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr index 118a849f98416..d551ccf9cf669 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr @@ -7,6 +7,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: defining type: no_relationships_late::<'_#1r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), ] = note: late-bound region is '_#3r = note: number of external vids: 4 @@ -57,6 +58,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), ] = note: number of external vids: 4 = note: where T: '_#3r @@ -106,9 +108,10 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: defining type: projection_outlives::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), ] = note: number of external vids: 4 - = note: where >::AssocType: '_#3r + = note: where >::AssocType: '_#3r note: no external requirements --> $DIR/projection-one-region-closure.rs:62:1 @@ -133,6 +136,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: defining type: elements_outlive::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), ] = note: number of external vids: 4 = note: where T: '_#3r diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr index 59d8aa484bdac..3e17de1bf0f56 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr @@ -7,6 +7,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: defining type: no_relationships_late::<'_#1r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), ] = note: late-bound region is '_#3r = note: number of external vids: 4 @@ -48,6 +49,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), ] = note: number of external vids: 4 = note: where '_#2r: '_#3r @@ -88,9 +90,10 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: defining type: projection_outlives::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), ] = note: number of external vids: 4 - = note: where >::AssocType: '_#3r + = note: where >::AssocType: '_#3r note: no external requirements --> $DIR/projection-one-region-trait-bound-closure.rs:52:1 @@ -115,6 +118,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: defining type: elements_outlive::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), ] = note: number of external vids: 4 = note: where '_#2r: '_#3r @@ -142,6 +146,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: defining type: one_region::<'_#1r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), ] = note: number of external vids: 3 = note: where '_#1r: '_#2r diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr index c3b924577ab47..3d9a01fec101d 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr @@ -7,6 +7,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: defining type: no_relationships_late::<'_#1r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), ] = note: late-bound region is '_#3r @@ -32,6 +33,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), ] note: no external requirements @@ -57,6 +59,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: defining type: projection_outlives::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), ] note: no external requirements @@ -82,6 +85,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: defining type: elements_outlive::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), ] note: no external requirements @@ -107,6 +111,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: defining type: one_region::<'_#1r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), ] note: no external requirements diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr index ff402f89ae861..e354f1b5f7e63 100644 --- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr @@ -7,10 +7,11 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: defining type: no_relationships_late::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), ] = note: late-bound region is '_#4r = note: number of external vids: 5 - = note: where >::AssocType: '_#3r + = note: where >::AssocType: '_#3r note: no external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:34:1 @@ -26,13 +27,13 @@ LL | | } | = note: defining type: no_relationships_late::<'_#1r, '_#2r, T> -error[E0309]: the associated type `>::AssocType` may not live long enough +error[E0309]: the associated type `>::AssocType` may not live long enough --> $DIR/projection-two-region-trait-bound-closure.rs:38:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: consider adding an explicit lifetime bound `>::AssocType: 'a`... + = help: consider adding an explicit lifetime bound `>::AssocType: 'a`... note: external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:48:29 @@ -43,9 +44,10 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: defining type: no_relationships_early::<'_#1r, '_#2r, '_#3r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)), + (), ] = note: number of external vids: 5 - = note: where >::AssocType: '_#4r + = note: where >::AssocType: '_#4r note: no external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:43:1 @@ -61,13 +63,13 @@ LL | | } | = note: defining type: no_relationships_early::<'_#1r, '_#2r, '_#3r, T> -error[E0309]: the associated type `>::AssocType` may not live long enough +error[E0309]: the associated type `>::AssocType` may not live long enough --> $DIR/projection-two-region-trait-bound-closure.rs:48:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: consider adding an explicit lifetime bound `>::AssocType: 'a`... + = help: consider adding an explicit lifetime bound `>::AssocType: 'a`... note: external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:61:29 @@ -78,9 +80,10 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: defining type: projection_outlives::<'_#1r, '_#2r, '_#3r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)), + (), ] = note: number of external vids: 5 - = note: where >::AssocType: '_#4r + = note: where >::AssocType: '_#4r note: no external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:53:1 @@ -105,9 +108,10 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: defining type: elements_outlive1::<'_#1r, '_#2r, '_#3r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)), + (), ] = note: number of external vids: 5 - = note: where >::AssocType: '_#4r + = note: where >::AssocType: '_#4r note: no external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:65:1 @@ -132,9 +136,10 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: defining type: elements_outlive2::<'_#1r, '_#2r, '_#3r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)), + (), ] = note: number of external vids: 5 - = note: where >::AssocType: '_#4r + = note: where >::AssocType: '_#4r note: no external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:74:1 @@ -159,10 +164,11 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: defining type: two_regions::<'_#1r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), ] = note: late-bound region is '_#3r = note: number of external vids: 4 - = note: where >::AssocType: '_#2r + = note: where >::AssocType: '_#2r note: no external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:83:1 @@ -200,9 +206,10 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: defining type: two_regions_outlive::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), ] = note: number of external vids: 4 - = note: where >::AssocType: '_#3r + = note: where >::AssocType: '_#3r note: no external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:92:1 @@ -227,9 +234,10 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: defining type: one_region::<'_#1r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), ] = note: number of external vids: 3 - = note: where >::AssocType: '_#2r + = note: where >::AssocType: '_#2r note: no external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:101:1 diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr index 9b08a10749673..167ca740c657c 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr @@ -7,6 +7,7 @@ LL | twice(cell, value, |a, b| invoke(a, b)); = note: defining type: generic::::{{closure}}#0 with closure substs [ i16, for<'r, 's> extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BrNamed('s)) T)), + (), ] = note: number of external vids: 2 = note: where T: '_#1r @@ -31,6 +32,7 @@ LL | twice(cell, value, |a, b| invoke(a, b)); = note: defining type: generic_fail::::{{closure}}#0 with closure substs [ i16, for<'r, 's> extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BrNamed('s)) T)), + (), ] = note: late-bound region is '_#2r = note: number of external vids: 3 diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr index 3cd1f4358710f..528da502b9d40 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr @@ -7,6 +7,7 @@ LL | with_signature(x, |y| y) = note: defining type: no_region::<'_#1r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::boxed::Box,)) -> std::boxed::Box<(dyn std::fmt::Debug + '_#2r)>, + (), ] = note: number of external vids: 3 = note: where T: '_#2r diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr index 4740ed645f1da..e341ee48291a9 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr @@ -14,6 +14,7 @@ LL | | }) = note: defining type: no_region::::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#1r ()>, T)), + (), ] = note: late-bound region is '_#2r = note: number of external vids: 3 @@ -64,6 +65,7 @@ LL | | }) = note: defining type: correct_region::<'_#1r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), ] = note: number of external vids: 3 = note: where T: '_#2r @@ -96,6 +98,7 @@ LL | | }) = note: defining type: wrong_region::<'_#1r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), ] = note: late-bound region is '_#3r = note: number of external vids: 4 @@ -141,6 +144,7 @@ LL | | }) = note: defining type: outlives_region::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [ i32, extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), ] = note: number of external vids: 4 = note: where T: '_#3r diff --git a/src/test/ui/no-landing-pads.rs b/src/test/ui/no-landing-pads.rs deleted file mode 100644 index d9d532106125a..0000000000000 --- a/src/test/ui/no-landing-pads.rs +++ /dev/null @@ -1,23 +0,0 @@ -// run-pass -// compile-flags: -Z no-landing-pads -C codegen-units=1 -// ignore-emscripten no threads support - -use std::thread; - -static mut HIT: bool = false; - -struct A; - -impl Drop for A { - fn drop(&mut self) { - unsafe { HIT = true; } - } -} - -fn main() { - thread::spawn(move|| -> () { - let _a = A; - panic!(); - }).join().unwrap_err(); - assert!(unsafe { !HIT }); -} diff --git a/src/test/ui/no_owned_box_lang_item.rs b/src/test/ui/no_owned_box_lang_item.rs index b76699c19ac80..58e45ff73a5e6 100644 --- a/src/test/ui/no_owned_box_lang_item.rs +++ b/src/test/ui/no_owned_box_lang_item.rs @@ -12,5 +12,4 @@ fn main() { } #[lang = "eh_personality"] extern fn eh_personality() {} -#[lang = "eh_unwind_resume"] extern fn eh_unwind_resume() {} #[lang = "panic_impl"] fn panic_impl(panic: &PanicInfo) -> ! { loop {} } diff --git a/src/test/ui/no_send-enum.rs b/src/test/ui/no_send-enum.rs index 4b4d06f1e32cd..bd560649b990e 100644 --- a/src/test/ui/no_send-enum.rs +++ b/src/test/ui/no_send-enum.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Send; diff --git a/src/test/ui/no_send-struct.rs b/src/test/ui/no_send-struct.rs index 67816bfee5d02..75a363f9f7639 100644 --- a/src/test/ui/no_send-struct.rs +++ b/src/test/ui/no_send-struct.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Send; diff --git a/src/test/ui/no_share-enum.rs b/src/test/ui/no_share-enum.rs index f5edb63cf86e9..44bf1913e7aac 100644 --- a/src/test/ui/no_share-enum.rs +++ b/src/test/ui/no_share-enum.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Sync; diff --git a/src/test/ui/no_share-struct.rs b/src/test/ui/no_share-struct.rs index 35867d0f2166d..7d8a36a76f274 100644 --- a/src/test/ui/no_share-struct.rs +++ b/src/test/ui/no_share-struct.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Sync; diff --git a/src/test/ui/non-copyable-void.rs b/src/test/ui/non-copyable-void.rs index ddaaee436ae23..186731f2e7233 100644 --- a/src/test/ui/non-copyable-void.rs +++ b/src/test/ui/non-copyable-void.rs @@ -1,3 +1,8 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl + // ignore-wasm32-bare no libc to test ffi with #![feature(rustc_private)] diff --git a/src/test/ui/non-copyable-void.stderr b/src/test/ui/non-copyable-void.stderr index 074ed66a26183..dd67a110d2218 100644 --- a/src/test/ui/non-copyable-void.stderr +++ b/src/test/ui/non-copyable-void.stderr @@ -1,8 +1,16 @@ error[E0599]: no method named `clone` found for enum `libc::c_void` in the current scope - --> $DIR/non-copyable-void.rs:11:23 + --> $DIR/non-copyable-void.rs:16:23 | LL | let _z = (*y).clone(); | ^^^^^ method not found in `libc::c_void` + | + ::: $SRC_DIR/libcore/clone.rs:LL:COL + | +LL | fn clone(&self) -> Self; + | ----- + | | + | the method is available for `std::sync::Arc` here + | the method is available for `std::rc::Rc` here error: aborting due to previous error diff --git a/src/test/ui/noncopyable-class.rs b/src/test/ui/noncopyable-class.rs index 11b6eb736e9db..731f4ab9c784a 100644 --- a/src/test/ui/noncopyable-class.rs +++ b/src/test/ui/noncopyable-class.rs @@ -1,3 +1,8 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl + // Test that a class with a non-copyable field can't be // copied diff --git a/src/test/ui/noncopyable-class.stderr b/src/test/ui/noncopyable-class.stderr index 6c3c4a6ac9888..472ce34870a0a 100644 --- a/src/test/ui/noncopyable-class.stderr +++ b/src/test/ui/noncopyable-class.stderr @@ -1,11 +1,19 @@ error[E0599]: no method named `clone` found for struct `Foo` in the current scope - --> $DIR/noncopyable-class.rs:34:16 + --> $DIR/noncopyable-class.rs:39:16 | LL | struct Foo { | ---------- method `clone` not found for this ... LL | let _y = x.clone(); | ^^^^^ method not found in `Foo` + | + ::: $SRC_DIR/libcore/clone.rs:LL:COL + | +LL | fn clone(&self) -> Self; + | ----- + | | + | the method is available for `std::sync::Arc` here + | the method is available for `std::rc::Rc` here | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: diff --git a/src/test/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs b/src/test/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs index abe34a39caf34..3e5cdad7ab936 100644 --- a/src/test/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs +++ b/src/test/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs @@ -11,5 +11,3 @@ use core::panic::PanicInfo; fn panic_impl(info: &PanicInfo) -> ! { loop {} } #[lang = "eh_personality"] fn eh_personality() {} -#[lang = "eh_unwind_resume"] -fn eh_unwind_resume() {} diff --git a/src/test/ui/panic-while-printing.rs b/src/test/ui/panic-while-printing.rs new file mode 100644 index 0000000000000..7e9fa16b0847a --- /dev/null +++ b/src/test/ui/panic-while-printing.rs @@ -0,0 +1,24 @@ +// run-pass +// ignore-emscripten no subprocess support + +#![feature(set_stdio)] + +use std::fmt; +use std::fmt::{Display, Formatter}; +use std::io::set_panic; + +pub struct A; + +impl Display for A { + fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result { + panic!(); + } +} + +fn main() { + set_panic(Some(Box::new(Vec::new()))); + assert!(std::panic::catch_unwind(|| { + eprintln!("{}", A); + }) + .is_err()); +} diff --git a/src/test/ui/paren-span.stderr b/src/test/ui/paren-span.stderr index 141378752d6f4..ca22401f45bb4 100644 --- a/src/test/ui/paren-span.stderr +++ b/src/test/ui/paren-span.stderr @@ -1,8 +1,8 @@ error[E0616]: field `x` of struct `m::S` is private - --> $DIR/paren-span.rs:19:12 + --> $DIR/paren-span.rs:19:14 | LL | paren!(s.x); - | ^^^ + | ^ private field error: aborting due to previous error diff --git a/src/test/ui/parser/chained-comparison-suggestion.rs b/src/test/ui/parser/chained-comparison-suggestion.rs index 0431196f1744e..bbd46082c9f90 100644 --- a/src/test/ui/parser/chained-comparison-suggestion.rs +++ b/src/test/ui/parser/chained-comparison-suggestion.rs @@ -37,4 +37,17 @@ fn comp8() { //~^ ERROR mismatched types } +fn comp9() { + 1 == 2 < 3; //~ ERROR comparison operators cannot be chained +} + +fn comp10() { + 1 > 2 == false; //~ ERROR comparison operators cannot be chained +} + +fn comp11() { + 1 == 2 == 3; //~ ERROR comparison operators cannot be chained + //~^ ERROR mismatched types +} + fn main() {} diff --git a/src/test/ui/parser/chained-comparison-suggestion.stderr b/src/test/ui/parser/chained-comparison-suggestion.stderr index 5c10a4599dd03..067920d12f486 100644 --- a/src/test/ui/parser/chained-comparison-suggestion.stderr +++ b/src/test/ui/parser/chained-comparison-suggestion.stderr @@ -2,127 +2,122 @@ error: comparison operators cannot be chained --> $DIR/chained-comparison-suggestion.rs:4:7 | LL | 1 < 2 <= 3; - | ^^^^^^ + | ^ ^^ | -help: split the comparison into two... +help: split the comparison into two | LL | 1 < 2 && 2 <= 3; - | ^^^^^^^^^^^^^ -help: ...or parenthesize one of the comparisons - | -LL | (1 < 2) <= 3; - | ^^^^^^^^^^ + | ^^^^ error: comparison operators cannot be chained --> $DIR/chained-comparison-suggestion.rs:9:7 | LL | 1 < 2 < 3; - | ^^^^^ + | ^ ^ | - = help: use `::<...>` instead of `<...>` to specify type arguments - = help: or use `(...)` if you meant to specify fn arguments -help: split the comparison into two... +help: split the comparison into two | LL | 1 < 2 && 2 < 3; - | ^^^^^^^^^^^^ -help: ...or parenthesize one of the comparisons - | -LL | (1 < 2) < 3; - | ^^^^^^^^^ + | ^^^^ error: comparison operators cannot be chained --> $DIR/chained-comparison-suggestion.rs:13:7 | LL | 1 <= 2 < 3; - | ^^^^^^ + | ^^ ^ | -help: split the comparison into two... +help: split the comparison into two | LL | 1 <= 2 && 2 < 3; - | ^^^^^^^^^^^^^ -help: ...or parenthesize one of the comparisons - | -LL | (1 <= 2) < 3; - | ^^^^^^^^^^ + | ^^^^ error: comparison operators cannot be chained --> $DIR/chained-comparison-suggestion.rs:18:7 | LL | 1 <= 2 <= 3; - | ^^^^^^^ + | ^^ ^^ | -help: split the comparison into two... +help: split the comparison into two | LL | 1 <= 2 && 2 <= 3; - | ^^^^^^^^^^^^^^ -help: ...or parenthesize one of the comparisons - | -LL | (1 <= 2) <= 3; - | ^^^^^^^^^^^ + | ^^^^ error: comparison operators cannot be chained --> $DIR/chained-comparison-suggestion.rs:23:7 | LL | 1 > 2 >= 3; - | ^^^^^^ + | ^ ^^ | -help: split the comparison into two... +help: split the comparison into two | LL | 1 > 2 && 2 >= 3; - | ^^^^^^^^^^^^^ -help: ...or parenthesize one of the comparisons - | -LL | (1 > 2) >= 3; - | ^^^^^^^^^^ + | ^^^^ error: comparison operators cannot be chained --> $DIR/chained-comparison-suggestion.rs:28:7 | LL | 1 > 2 > 3; - | ^^^^^ + | ^ ^ | - = help: use `::<...>` instead of `<...>` to specify type arguments - = help: or use `(...)` if you meant to specify fn arguments -help: split the comparison into two... +help: split the comparison into two | LL | 1 > 2 && 2 > 3; - | ^^^^^^^^^^^^ -help: ...or parenthesize one of the comparisons - | -LL | (1 > 2) > 3; - | ^^^^^^^^^ + | ^^^^ error: comparison operators cannot be chained --> $DIR/chained-comparison-suggestion.rs:32:7 | LL | 1 >= 2 > 3; - | ^^^^^^ + | ^^ ^ | - = help: use `::<...>` instead of `<...>` to specify type arguments - = help: or use `(...)` if you meant to specify fn arguments -help: split the comparison into two... +help: split the comparison into two | LL | 1 >= 2 && 2 > 3; - | ^^^^^^^^^^^^^ -help: ...or parenthesize one of the comparisons - | -LL | (1 >= 2) > 3; - | ^^^^^^^^^^ + | ^^^^ error: comparison operators cannot be chained --> $DIR/chained-comparison-suggestion.rs:36:7 | LL | 1 >= 2 >= 3; - | ^^^^^^^ + | ^^ ^^ | -help: split the comparison into two... +help: split the comparison into two | LL | 1 >= 2 && 2 >= 3; - | ^^^^^^^^^^^^^^ -help: ...or parenthesize one of the comparisons + | ^^^^ + +error: comparison operators cannot be chained + --> $DIR/chained-comparison-suggestion.rs:41:7 + | +LL | 1 == 2 < 3; + | ^^ ^ | -LL | (1 >= 2) >= 3; - | ^^^^^^^^^^^ +help: parenthesize the comparison + | +LL | 1 == (2 < 3); + | ^ ^ + +error: comparison operators cannot be chained + --> $DIR/chained-comparison-suggestion.rs:45:7 + | +LL | 1 > 2 == false; + | ^ ^^ + | +help: parenthesize the comparison + | +LL | (1 > 2) == false; + | ^ ^ + +error: comparison operators cannot be chained + --> $DIR/chained-comparison-suggestion.rs:49:7 + | +LL | 1 == 2 == 3; + | ^^ ^^ + | +help: split the comparison into two + | +LL | 1 == 2 && 2 == 3; + | ^^^^ error[E0308]: mismatched types --> $DIR/chained-comparison-suggestion.rs:4:14 @@ -154,6 +149,12 @@ error[E0308]: mismatched types LL | 1 >= 2 >= 3; | ^ expected `bool`, found integer -error: aborting due to 13 previous errors +error[E0308]: mismatched types + --> $DIR/chained-comparison-suggestion.rs:49:15 + | +LL | 1 == 2 == 3; + | ^ expected `bool`, found integer + +error: aborting due to 17 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/circular_modules_main.rs b/src/test/ui/parser/circular_modules_main.rs index b85003bf0910f..1ae36a1f7605e 100644 --- a/src/test/ui/parser/circular_modules_main.rs +++ b/src/test/ui/parser/circular_modules_main.rs @@ -6,5 +6,5 @@ pub fn hi_str() -> String { } fn main() { - circular_modules_hello::say_hello(); + circular_modules_hello::say_hello(); //~ ERROR cannot find function `say_hello` in module } diff --git a/src/test/ui/parser/circular_modules_main.stderr b/src/test/ui/parser/circular_modules_main.stderr index 33865fb7bca95..90f81c64835b7 100644 --- a/src/test/ui/parser/circular_modules_main.stderr +++ b/src/test/ui/parser/circular_modules_main.stderr @@ -1,8 +1,20 @@ error: circular modules: $DIR/circular_modules_hello.rs -> $DIR/circular_modules_main.rs -> $DIR/circular_modules_hello.rs - --> $DIR/circular_modules_main.rs:2:5 + --> $DIR/circular_modules_main.rs:2:1 | LL | mod circular_modules_hello; - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error[E0425]: cannot find function `say_hello` in module `circular_modules_hello` + --> $DIR/circular_modules_main.rs:9:29 + | +LL | circular_modules_hello::say_hello(); + | ^^^^^^^^^ not found in `circular_modules_hello` + | +help: possible candidate is found in another module, you can import it into scope + | +LL | use circular_modules_hello::say_hello; + | + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/parser/extern-abi-from-mac-literal-frag.rs b/src/test/ui/parser/extern-abi-from-mac-literal-frag.rs index cb23f2c808c34..4ecb21d26ab9b 100644 --- a/src/test/ui/parser/extern-abi-from-mac-literal-frag.rs +++ b/src/test/ui/parser/extern-abi-from-mac-literal-frag.rs @@ -1,7 +1,7 @@ // check-pass // In this test we check that the parser accepts an ABI string when it -// comes from a macro `literal` fragment as opposed to a hardcoded string. +// comes from a macro `literal` or `expr` fragment as opposed to a hardcoded string. fn main() {} @@ -17,6 +17,18 @@ macro_rules! abi_from_lit_frag { } } +macro_rules! abi_from_expr_frag { + ($abi:expr) => { + extern $abi { + fn _import(); + } + + extern $abi fn _export() {} + + type _PTR = extern $abi fn(); + }; +} + mod rust { abi_from_lit_frag!("Rust"); } @@ -24,3 +36,11 @@ mod rust { mod c { abi_from_lit_frag!("C"); } + +mod rust_expr { + abi_from_expr_frag!("Rust"); +} + +mod c_expr { + abi_from_expr_frag!("C"); +} diff --git a/src/test/ui/parser/issue-5806.stderr b/src/test/ui/parser/issue-5806.stderr index 6cf902ca86e79..bdb5c91ff91eb 100644 --- a/src/test/ui/parser/issue-5806.stderr +++ b/src/test/ui/parser/issue-5806.stderr @@ -1,8 +1,8 @@ error: couldn't read $DIR/../parser: $ACCESS_DENIED_MSG (os error $ACCESS_DENIED_CODE) - --> $DIR/issue-5806.rs:5:5 + --> $DIR/issue-5806.rs:5:1 | LL | mod foo; - | ^^^ + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/issue-62894.rs b/src/test/ui/parser/issue-62894.rs index b9c0bf834ddb2..e38b7b6508937 100644 --- a/src/test/ui/parser/issue-62894.rs +++ b/src/test/ui/parser/issue-62894.rs @@ -1,3 +1,8 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl + // Regression test for #62894, shouldn't crash. // error-pattern: this file contains an unclosed delimiter // error-pattern: expected one of `(`, `[`, or `{`, found keyword `fn` diff --git a/src/test/ui/parser/issue-62894.stderr b/src/test/ui/parser/issue-62894.stderr index 6db380f7a7fe2..4a1d7e275bed8 100644 --- a/src/test/ui/parser/issue-62894.stderr +++ b/src/test/ui/parser/issue-62894.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/issue-62894.rs:7:14 + --> $DIR/issue-62894.rs:12:14 | LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq! | - - - unclosed delimiter @@ -11,7 +11,7 @@ LL | fn main() {} | ^ error: this file contains an unclosed delimiter - --> $DIR/issue-62894.rs:7:14 + --> $DIR/issue-62894.rs:12:14 | LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq! | - - - unclosed delimiter @@ -23,7 +23,7 @@ LL | fn main() {} | ^ error: this file contains an unclosed delimiter - --> $DIR/issue-62894.rs:7:14 + --> $DIR/issue-62894.rs:12:14 | LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq! | - - - unclosed delimiter @@ -35,13 +35,18 @@ LL | fn main() {} | ^ error: expected one of `(`, `[`, or `{`, found keyword `fn` - --> $DIR/issue-62894.rs:7:1 + --> $DIR/issue-62894.rs:12:1 | LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq! | - expected one of `(`, `[`, or `{` LL | LL | fn main() {} | ^^ unexpected token + | + ::: $SRC_DIR/libcore/macros/mod.rs:LL:COL + | +LL | ($left:expr, $right:expr) => ({ + | ---------- while parsing argument for this `expr` macro fragment error: aborting due to 4 previous errors diff --git a/src/test/ui/parser/issue-68890-2.stderr b/src/test/ui/parser/issue-68890-2.stderr index d475c79cb27b4..967eee06e282f 100644 --- a/src/test/ui/parser/issue-68890-2.stderr +++ b/src/test/ui/parser/issue-68890-2.stderr @@ -20,3 +20,4 @@ LL | type X<'a> = (?'a) +; error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0224`. diff --git a/src/test/ui/parser/issue-70050-ntliteral-accepts-negated-lit.rs b/src/test/ui/parser/issue-70050-ntliteral-accepts-negated-lit.rs new file mode 100644 index 0000000000000..aca9d9eb0a5b4 --- /dev/null +++ b/src/test/ui/parser/issue-70050-ntliteral-accepts-negated-lit.rs @@ -0,0 +1,16 @@ +// check-pass + +macro_rules! foo { + ($a:literal) => { + bar!($a) + }; +} + +macro_rules! bar { + ($b:literal) => {}; +} + +fn main() { + foo!(-2); + bar!(-2); +} diff --git a/src/test/ui/parser/issue-70388-recover-dotdotdot-rest-pat.rs b/src/test/ui/parser/issue-70388-recover-dotdotdot-rest-pat.rs new file mode 100644 index 0000000000000..ca8abd78c47ac --- /dev/null +++ b/src/test/ui/parser/issue-70388-recover-dotdotdot-rest-pat.rs @@ -0,0 +1,7 @@ +struct Foo(i32); + +fn main() { + let Foo(...) = Foo(0); //~ ERROR unexpected `...` + let [_, ..., _] = [0, 1]; //~ ERROR unexpected `...` + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/src/test/ui/parser/issue-70388-recover-dotdotdot-rest-pat.stderr b/src/test/ui/parser/issue-70388-recover-dotdotdot-rest-pat.stderr new file mode 100644 index 0000000000000..4961e8fc0492d --- /dev/null +++ b/src/test/ui/parser/issue-70388-recover-dotdotdot-rest-pat.stderr @@ -0,0 +1,29 @@ +error: unexpected `...` + --> $DIR/issue-70388-recover-dotdotdot-rest-pat.rs:4:13 + | +LL | let Foo(...) = Foo(0); + | ^^^ + | | + | not a valid pattern + | help: for a rest pattern, use `..` instead of `...` + +error: unexpected `...` + --> $DIR/issue-70388-recover-dotdotdot-rest-pat.rs:5:13 + | +LL | let [_, ..., _] = [0, 1]; + | ^^^ + | | + | not a valid pattern + | help: for a rest pattern, use `..` instead of `...` + +error[E0308]: mismatched types + --> $DIR/issue-70388-recover-dotdotdot-rest-pat.rs:6:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/macro/issue-33569.rs b/src/test/ui/parser/macro/issue-33569.rs index 9ed53519ceb31..80e2d7c6545ba 100644 --- a/src/test/ui/parser/macro/issue-33569.rs +++ b/src/test/ui/parser/macro/issue-33569.rs @@ -6,3 +6,5 @@ macro_rules! foo { } foo!(); + +fn main() {} diff --git a/src/test/ui/parser/macro/macro-repeat.rs b/src/test/ui/parser/macro/macro-repeat.rs index 580a1daacbf31..3ffbea217e79e 100644 --- a/src/test/ui/parser/macro/macro-repeat.rs +++ b/src/test/ui/parser/macro/macro-repeat.rs @@ -1,9 +1,12 @@ macro_rules! mac { - ( $($v:tt)* ) => ( - $v //~ ERROR still repeating at this depth - ) + ( $($v:tt)* ) => { + $v + //~^ ERROR still repeating at this depth + //~| ERROR still repeating at this depth + }; } fn main() { mac!(0); + mac!(1); } diff --git a/src/test/ui/parser/macro/macro-repeat.stderr b/src/test/ui/parser/macro/macro-repeat.stderr index c86684de74432..63554b197b91c 100644 --- a/src/test/ui/parser/macro/macro-repeat.stderr +++ b/src/test/ui/parser/macro/macro-repeat.stderr @@ -4,5 +4,11 @@ error: variable 'v' is still repeating at this depth LL | $v | ^^ -error: aborting due to previous error +error: variable 'v' is still repeating at this depth + --> $DIR/macro-repeat.rs:3:9 + | +LL | $v + | ^^ + +error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/macro/pub-item-macro.stderr b/src/test/ui/parser/macro/pub-item-macro.stderr index 4ff96532e03a8..1c5613ac986c4 100644 --- a/src/test/ui/parser/macro/pub-item-macro.stderr +++ b/src/test/ui/parser/macro/pub-item-macro.stderr @@ -14,7 +14,7 @@ error[E0603]: static `x` is private --> $DIR/pub-item-macro.rs:20:23 | LL | let y: u32 = foo::x; - | ^ this static is private + | ^ private static | note: the static `x` is defined here --> $DIR/pub-item-macro.rs:5:9 diff --git a/src/test/ui/parser/macro/trait-object-macro-matcher.stderr b/src/test/ui/parser/macro/trait-object-macro-matcher.stderr index 230733371ddd8..a6fa9f8dddc27 100644 --- a/src/test/ui/parser/macro/trait-object-macro-matcher.stderr +++ b/src/test/ui/parser/macro/trait-object-macro-matcher.stderr @@ -20,3 +20,4 @@ LL | m!('static); error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0224`. diff --git a/src/test/ui/parser/mod_file_not_exist.rs b/src/test/ui/parser/mod_file_not_exist.rs index e662c707a38b9..f4a27b52ec5b4 100644 --- a/src/test/ui/parser/mod_file_not_exist.rs +++ b/src/test/ui/parser/mod_file_not_exist.rs @@ -1,8 +1,9 @@ // ignore-windows mod not_a_real_file; //~ ERROR file not found for module `not_a_real_file` -//~^ HELP name the file either not_a_real_file.rs or not_a_real_file/mod.rs inside the directory +//~^ HELP to create the module `not_a_real_file`, create file fn main() { assert_eq!(mod_file_aux::bar(), 10); + //~^ ERROR failed to resolve: use of undeclared type or module `mod_file_aux` } diff --git a/src/test/ui/parser/mod_file_not_exist.stderr b/src/test/ui/parser/mod_file_not_exist.stderr index dadf4b29dcf39..087ae9fe3e016 100644 --- a/src/test/ui/parser/mod_file_not_exist.stderr +++ b/src/test/ui/parser/mod_file_not_exist.stderr @@ -1,11 +1,18 @@ error[E0583]: file not found for module `not_a_real_file` - --> $DIR/mod_file_not_exist.rs:3:5 + --> $DIR/mod_file_not_exist.rs:3:1 | LL | mod not_a_real_file; - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ | - = help: name the file either not_a_real_file.rs or not_a_real_file/mod.rs inside the directory "$DIR" + = help: to create the module `not_a_real_file`, create file "$DIR/not_a_real_file.rs" -error: aborting due to previous error +error[E0433]: failed to resolve: use of undeclared type or module `mod_file_aux` + --> $DIR/mod_file_not_exist.rs:7:16 + | +LL | assert_eq!(mod_file_aux::bar(), 10); + | ^^^^^^^^^^^^ use of undeclared type or module `mod_file_aux` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0583`. +Some errors have detailed explanations: E0433, E0583. +For more information about an error, try `rustc --explain E0433`. diff --git a/src/test/ui/parser/mod_file_not_exist_windows.rs b/src/test/ui/parser/mod_file_not_exist_windows.rs index 0cd9e9c799f1d..4b7d7a02bbe78 100644 --- a/src/test/ui/parser/mod_file_not_exist_windows.rs +++ b/src/test/ui/parser/mod_file_not_exist_windows.rs @@ -1,8 +1,9 @@ // only-windows mod not_a_real_file; //~ ERROR file not found for module `not_a_real_file` -//~^ HELP name the file either not_a_real_file.rs or not_a_real_file\mod.rs inside the directory +//~^ HELP to create the module `not_a_real_file`, create file fn main() { assert_eq!(mod_file_aux::bar(), 10); + //~^ ERROR failed to resolve: use of undeclared type or module `mod_file_aux` } diff --git a/src/test/ui/parser/mod_file_not_exist_windows.stderr b/src/test/ui/parser/mod_file_not_exist_windows.stderr index 60ae00abab1ed..d67205cfdf100 100644 --- a/src/test/ui/parser/mod_file_not_exist_windows.stderr +++ b/src/test/ui/parser/mod_file_not_exist_windows.stderr @@ -1,11 +1,18 @@ error[E0583]: file not found for module `not_a_real_file` - --> $DIR/mod_file_not_exist_windows.rs:3:5 + --> $DIR/mod_file_not_exist_windows.rs:3:1 | LL | mod not_a_real_file; - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ | - = help: name the file either not_a_real_file.rs or not_a_real_file/mod.rs inside the directory "$DIR" + = help: to create the module `not_a_real_file`, create file "$DIR/not_a_real_file.rs" -error: aborting due to previous error +error[E0433]: failed to resolve: use of undeclared type or module `mod_file_aux` + --> $DIR/mod_file_not_exist_windows.rs:7:16 + | +LL | assert_eq!(mod_file_aux::bar(), 10); + | ^^^^^^^^^^^^ use of undeclared type or module `mod_file_aux` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0583`. +Some errors have detailed explanations: E0433, E0583. +For more information about an error, try `rustc --explain E0433`. diff --git a/src/test/ui/parser/mod_file_with_path_attr.stderr b/src/test/ui/parser/mod_file_with_path_attr.stderr index 004b5d7963a1d..cd1add73d5840 100644 --- a/src/test/ui/parser/mod_file_with_path_attr.stderr +++ b/src/test/ui/parser/mod_file_with_path_attr.stderr @@ -1,8 +1,8 @@ error: couldn't read $DIR/not_a_real_file.rs: $FILE_NOT_FOUND_MSG (os error 2) - --> $DIR/mod_file_with_path_attr.rs:4:5 + --> $DIR/mod_file_with_path_attr.rs:4:1 | LL | mod m; - | ^ + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/nt-parsing-has-recovery.rs b/src/test/ui/parser/nt-parsing-has-recovery.rs new file mode 100644 index 0000000000000..ccbeb398af5ba --- /dev/null +++ b/src/test/ui/parser/nt-parsing-has-recovery.rs @@ -0,0 +1,10 @@ +macro_rules! foo { + ($e:expr) => {} +} + +foo!(1 + @); //~ ERROR expected expression, found `@` +foo!(1 + @); //~ ERROR expected expression, found `@` + +fn main() { + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/src/test/ui/parser/nt-parsing-has-recovery.stderr b/src/test/ui/parser/nt-parsing-has-recovery.stderr new file mode 100644 index 0000000000000..263c4ad53612e --- /dev/null +++ b/src/test/ui/parser/nt-parsing-has-recovery.stderr @@ -0,0 +1,29 @@ +error: expected expression, found `@` + --> $DIR/nt-parsing-has-recovery.rs:5:10 + | +LL | ($e:expr) => {} + | ------- while parsing argument for this `expr` macro fragment +... +LL | foo!(1 + @); + | ^ expected expression + +error: expected expression, found `@` + --> $DIR/nt-parsing-has-recovery.rs:6:10 + | +LL | ($e:expr) => {} + | ------- while parsing argument for this `expr` macro fragment +... +LL | foo!(1 + @); + | ^ expected expression + +error[E0308]: mismatched types + --> $DIR/nt-parsing-has-recovery.rs:9:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/recover-quantified-closure.rs b/src/test/ui/parser/recover-quantified-closure.rs new file mode 100644 index 0000000000000..381324738f62b --- /dev/null +++ b/src/test/ui/parser/recover-quantified-closure.rs @@ -0,0 +1,10 @@ +fn main() { + for<'a> |x: &'a u8| *x + 1; + //~^ ERROR cannot introduce explicit parameters for a closure +} + +enum Foo { Bar } +fn foo(x: impl Iterator) { + for ::Bar in x {} + //~^ ERROR expected one of `move`, `static`, `|` +} diff --git a/src/test/ui/parser/recover-quantified-closure.stderr b/src/test/ui/parser/recover-quantified-closure.stderr new file mode 100644 index 0000000000000..0f01132651648 --- /dev/null +++ b/src/test/ui/parser/recover-quantified-closure.stderr @@ -0,0 +1,16 @@ +error: cannot introduce explicit parameters for a closure + --> $DIR/recover-quantified-closure.rs:2:5 + | +LL | for<'a> |x: &'a u8| *x + 1; + | ^^^^^^^ ------------------ the parameters are attached to this closure + | | + | help: remove the parameters + +error: expected one of `move`, `static`, `|`, or `||`, found `::` + --> $DIR/recover-quantified-closure.rs:8:14 + | +LL | for ::Bar in x {} + | ^^ expected one of `move`, `static`, `|`, or `||` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.rs b/src/test/ui/parser/require-parens-for-chained-comparison.rs index e27b03dddc5be..4e97904ed6d5f 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.rs +++ b/src/test/ui/parser/require-parens-for-chained-comparison.rs @@ -4,11 +4,11 @@ struct X; fn main() { false == false == false; //~^ ERROR comparison operators cannot be chained + //~| HELP split the comparison into two false == 0 < 2; //~^ ERROR comparison operators cannot be chained - //~| ERROR mismatched types - //~| ERROR mismatched types + //~| HELP parenthesize the comparison f(); //~^ ERROR comparison operators cannot be chained @@ -16,8 +16,6 @@ fn main() { f, Option>>(1, 2); //~^ ERROR comparison operators cannot be chained - //~| HELP split the comparison into two... - //~| ...or parenthesize one of the comparisons //~| HELP use `::<...>` instead of `<...>` to specify type arguments use std::convert::identity; diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.stderr b/src/test/ui/parser/require-parens-for-chained-comparison.stderr index 44edf2de7f8de..7001aa8e8a1d8 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.stderr +++ b/src/test/ui/parser/require-parens-for-chained-comparison.stderr @@ -2,19 +2,29 @@ error: comparison operators cannot be chained --> $DIR/require-parens-for-chained-comparison.rs:5:11 | LL | false == false == false; - | ^^^^^^^^^^^ + | ^^ ^^ + | +help: split the comparison into two + | +LL | false == false && false == false; + | ^^^^^^^^ error: comparison operators cannot be chained - --> $DIR/require-parens-for-chained-comparison.rs:8:11 + --> $DIR/require-parens-for-chained-comparison.rs:9:11 | LL | false == 0 < 2; - | ^^^^^^ + | ^^ ^ + | +help: parenthesize the comparison + | +LL | false == (0 < 2); + | ^ ^ error: comparison operators cannot be chained --> $DIR/require-parens-for-chained-comparison.rs:13:6 | LL | f(); - | ^^^ + | ^ ^ | help: use `::<...>` instead of `<...>` to specify type arguments | @@ -25,42 +35,21 @@ error: comparison operators cannot be chained --> $DIR/require-parens-for-chained-comparison.rs:17:6 | LL | f, Option>>(1, 2); - | ^^^^^^^^ - | -help: split the comparison into two... - | -LL | f < Result && Result , Option>>(1, 2); - | ^^^^^^^^^^^^^^^^^^^^^^ -help: ...or parenthesize one of the comparisons + | ^ ^ | -LL | (f < Result) , Option>>(1, 2); - | ^^^^^^^^^^^^^^ help: use `::<...>` instead of `<...>` to specify type arguments | LL | f::, Option>>(1, 2); | ^^ error: comparison operators cannot be chained - --> $DIR/require-parens-for-chained-comparison.rs:24:21 + --> $DIR/require-parens-for-chained-comparison.rs:22:21 | LL | let _ = identity; - | ^^^^ + | ^ ^ | = help: use `::<...>` instead of `<...>` to specify type arguments = help: or use `(...)` if you meant to specify fn arguments -error[E0308]: mismatched types - --> $DIR/require-parens-for-chained-comparison.rs:8:14 - | -LL | false == 0 < 2; - | ^ expected `bool`, found integer - -error[E0308]: mismatched types - --> $DIR/require-parens-for-chained-comparison.rs:8:18 - | -LL | false == 0 < 2; - | ^ expected `bool`, found integer - -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/stripped-nested-outline-mod-pass.rs b/src/test/ui/parser/stripped-nested-outline-mod-pass.rs new file mode 100644 index 0000000000000..1b4669a439ffe --- /dev/null +++ b/src/test/ui/parser/stripped-nested-outline-mod-pass.rs @@ -0,0 +1,13 @@ +// Expansion drives parsing, so conditional compilation will strip +// out outline modules and we will never attempt parsing them. + +// check-pass + +fn main() {} + +#[cfg(FALSE)] +mod foo { + mod bar { + mod baz; // This was an error before. + } +} diff --git a/src/test/ui/parser/trait-object-bad-parens.rs b/src/test/ui/parser/trait-object-bad-parens.rs index 048e028be1ca1..0a2836d691f5f 100644 --- a/src/test/ui/parser/trait-object-bad-parens.rs +++ b/src/test/ui/parser/trait-object-bad-parens.rs @@ -1,4 +1,5 @@ #![feature(optin_builtin_traits)] +#![feature(negative_impls)] #![allow(bare_trait_objects)] auto trait Auto {} diff --git a/src/test/ui/parser/trait-object-bad-parens.stderr b/src/test/ui/parser/trait-object-bad-parens.stderr index f53afdff5e7c2..74e484eebee1f 100644 --- a/src/test/ui/parser/trait-object-bad-parens.stderr +++ b/src/test/ui/parser/trait-object-bad-parens.stderr @@ -1,23 +1,23 @@ error[E0178]: expected a path on the left-hand side of `+`, not `((Auto))` - --> $DIR/trait-object-bad-parens.rs:7:16 + --> $DIR/trait-object-bad-parens.rs:8:16 | LL | let _: Box<((Auto)) + Auto>; | ^^^^^^^^^^^^^^^ expected a path error[E0178]: expected a path on the left-hand side of `+`, not `(Auto + Auto)` - --> $DIR/trait-object-bad-parens.rs:9:16 + --> $DIR/trait-object-bad-parens.rs:10:16 | LL | let _: Box<(Auto + Auto) + Auto>; | ^^^^^^^^^^^^^^^^^^^^ expected a path error[E0178]: expected a path on the left-hand side of `+`, not `(Auto)` - --> $DIR/trait-object-bad-parens.rs:11:16 + --> $DIR/trait-object-bad-parens.rs:12:16 | LL | let _: Box<(Auto +) + Auto>; | ^^^^^^^^^^^^^^^ expected a path error[E0178]: expected a path on the left-hand side of `+`, not `(dyn Auto)` - --> $DIR/trait-object-bad-parens.rs:13:16 + --> $DIR/trait-object-bad-parens.rs:14:16 | LL | let _: Box<(dyn Auto) + Auto>; | ^^^^^^^^^^^^^^^^^ expected a path 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 32c638bcbcca3..f1680e9e8884e 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 @@ -45,19 +45,19 @@ fn main() { *b = NC; let ref a @ box ref mut b = Box::new(NC); //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable - //~| ERROR cannot borrow `_` as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable *b = NC; drop(a); let ref mut a @ box ref b = Box::new(NC); //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable - //~| ERROR cannot borrow `_` as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable *a = Box::new(NC); drop(b); fn f5(ref mut a @ box ref b: Box) { //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable - //~| ERROR cannot borrow `_` as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable *a = Box::new(NC); drop(b); } @@ -65,7 +65,7 @@ fn main() { match Box::new(nc()) { ref mut a @ box ref b => { //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable - //~| ERROR cannot borrow `_` as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable *a = Box::new(NC); drop(b); } 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 5534d0a75e63d..5ce546f08bf6f 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 @@ -99,7 +99,7 @@ LL | a @ box b => {} | | value used here after move | value moved here -error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-at-and-box.rs:46:21 | LL | let ref a @ box ref mut b = Box::new(NC); @@ -111,7 +111,7 @@ LL | let ref a @ box ref mut b = Box::new(NC); LL | drop(a); | - immutable borrow later used here -error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-at-and-box.rs:52:25 | LL | let ref mut a @ box ref b = Box::new(NC); @@ -123,7 +123,7 @@ LL | let ref mut a @ box ref b = Box::new(NC); LL | *a = Box::new(NC); | -- mutable borrow later used here -error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-at-and-box.rs:66:25 | LL | ref mut a @ box ref b => { @@ -155,7 +155,7 @@ LL | fn f2(a @ box b: Box) {} | value moved here | move occurs because value has type `std::boxed::Box`, which does not implement the `Copy` trait -error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-at-and-box.rs:58:27 | LL | fn f5(ref mut a @ box ref b: Box) { 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 58d4a9b018cee..2b5e339c6396e 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 @@ -10,7 +10,7 @@ fn main() { match &mut Some(1) { ref mut z @ &mut Some(ref a) => { //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable - //~| ERROR cannot borrow `_` as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable **z = None; println!("{}", *a); } @@ -47,12 +47,12 @@ fn main() { let ref mut a @ ref b = u(); //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable - //~| ERROR cannot borrow `_` as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable *a = u(); drop(b); let ref a @ ref mut b = u(); //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable - //~| ERROR cannot borrow `_` as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable *b = u(); drop(a); @@ -78,8 +78,8 @@ fn main() { ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable - //~| ERROR cannot borrow `_` as mutable because it is also borrowed as immutable - //~| ERROR cannot borrow `_` as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable *b = U; drop(a); } @@ -123,15 +123,15 @@ fn main() { let ref a @ (ref mut b, ref mut c) = (U, U); //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable - //~| ERROR cannot borrow `_` as mutable because it is also borrowed as immutable - //~| ERROR cannot borrow `_` as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable *b = U; drop(a); let ref a @ (ref mut b, ref mut c) = (U, U); //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable - *b = U; //~| ERROR cannot borrow `_` as mutable because it is also borrowed as immutable - *c = U; //~| ERROR cannot borrow `_` as mutable because it is also borrowed as immutable + *b = U; //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + *c = U; //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable drop(a); let ref mut a @ (ref b, ref c) = (U, U); //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable 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 8c6ca888e0762..b161054414a30 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 @@ -294,7 +294,7 @@ LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {} | | value moved into `c` here | value borrowed, by `b`, here -error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:11:31 | LL | ref mut z @ &mut Some(ref a) => { @@ -306,7 +306,7 @@ LL | ref mut z @ &mut Some(ref a) => { LL | **z = None; | ---------- mutable borrow later used here -error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:48:21 | LL | let ref mut a @ ref b = u(); @@ -318,7 +318,7 @@ LL | let ref mut a @ ref b = u(); LL | *a = u(); | -------- mutable borrow later used here -error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:53:17 | LL | let ref a @ ref mut b = u(); @@ -330,7 +330,7 @@ LL | let ref a @ ref mut b = u(); LL | drop(a); | - immutable borrow later used here -error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:78:20 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { @@ -342,7 +342,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { LL | drop(a); | - immutable borrow later used here -error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:78:45 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { @@ -402,7 +402,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 +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:124:18 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); @@ -414,7 +414,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U); LL | drop(a); | - immutable borrow later used here -error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:124:29 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); @@ -426,7 +426,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U); LL | drop(a); | - immutable borrow later used here -error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:131:18 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); @@ -438,7 +438,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U); LL | drop(a); | - immutable borrow later used here -error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:131: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 f5c39a7ac5276..a208d0087ff53 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 @@ -27,7 +27,7 @@ fn main() { let ref mut a @ ref mut b = U; //~^ ERROR cannot borrow value as mutable more than once at a time - //~| ERROR cannot borrow `_` as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time drop(a); let ref mut a @ ref mut b = U; //~^ ERROR cannot borrow value as mutable more than once at a time @@ -37,7 +37,7 @@ fn main() { let ref mut a @ ref mut b = U; //~^ ERROR cannot borrow value as mutable more than once at a time - //~| ERROR cannot borrow `_` as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time *a = U; let ref mut a @ ref mut b = U; //~^ ERROR cannot borrow value as mutable more than once at a time @@ -95,11 +95,11 @@ fn main() { ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { //~^ ERROR cannot borrow value as mutable more than once at a time //~| ERROR cannot borrow value as mutable more than once at a time - //~| ERROR cannot borrow `_` as mutable more than once at a time - //~| ERROR cannot borrow `_` as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time *a = Err(U); - // FIXME: The binding name `_` used above makes for problematic diagnostics. + // FIXME: The binding name value used above makes for problematic diagnostics. // Resolve that somehow... } } @@ -107,8 +107,8 @@ fn main() { ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { //~^ ERROR cannot borrow value as mutable more than once at a time //~| ERROR cannot borrow value as mutable more than once at a time - //~| ERROR cannot borrow `_` as mutable more than once at a time - //~| ERROR cannot borrow `_` as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time drop(a); } } 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 e74f227b5e48c..ae7c8f38e1eb4 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 @@ -258,7 +258,7 @@ LL | fn f4_also_moved(ref mut a @ ref mut b @ c: U) {} | | value moved into `c` here | value borrowed, by `b`, here -error[E0499]: cannot borrow `_` as mutable more than once at a time +error[E0499]: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:28:21 | LL | let ref mut a @ ref mut b = U; @@ -270,7 +270,7 @@ LL | let ref mut a @ ref mut b = U; LL | drop(a); | - first borrow later used here -error[E0499]: cannot borrow `_` as mutable more than once at a time +error[E0499]: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:38:21 | LL | let ref mut a @ ref mut b = U; @@ -318,7 +318,7 @@ LL | let a @ &mut (ref mut b, ref mut c) = &mut (U, U); | | value borrowed here after move | value moved here -error[E0499]: cannot borrow `_` as mutable more than once at a time +error[E0499]: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:95:24 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { @@ -330,7 +330,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { LL | *a = Err(U); | ----------- first borrow later used here -error[E0499]: cannot borrow `_` as mutable more than once at a time +error[E0499]: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:95:53 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { @@ -342,7 +342,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { LL | *a = Err(U); | ----------- first borrow later used here -error[E0499]: cannot borrow `_` as mutable more than once at a time +error[E0499]: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:107:24 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { @@ -354,7 +354,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { LL | drop(a); | - first borrow later used here -error[E0499]: cannot borrow `_` as mutable more than once at a time +error[E0499]: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:107:53 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { diff --git a/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.rs b/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.rs index b40c3e3358aa3..a45497229ac9e 100644 --- a/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.rs +++ b/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.rs @@ -29,7 +29,7 @@ fn main() { let _a: &NotCopy = a; let _b: NotCopy = b; let ref mut a @ b = NotCopy; //~ ERROR cannot move out of value because it is borrowed - //~^ ERROR cannot move out of `_` because it is borrowed + //~^ ERROR cannot move out of value because it is borrowed let _a: &NotCopy = a; let _b: NotCopy = b; match Ok(NotCopy) { diff --git a/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr b/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr index 19e815a1ae8ad..141d667c7460c 100644 --- a/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr +++ b/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr @@ -44,7 +44,7 @@ LL | ref a @ b => { | | value moved into `b` here | value borrowed, by `a`, here -error[E0505]: cannot move out of `_` because it is borrowed +error[E0505]: cannot move out of value because it is borrowed --> $DIR/default-binding-modes-both-sides-independent.rs:31:21 | LL | let ref mut a @ b = NotCopy; diff --git a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.rs b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.rs index 11eae2af9c95f..7d1cac8a442f5 100644 --- a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.rs +++ b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.rs @@ -21,7 +21,7 @@ fn uninhab_union() -> Foo { fn match_on_uninhab() { match uninhab_ref() { - //~^ ERROR non-exhaustive patterns: type `&'static !` is non-empty + //~^ ERROR non-exhaustive patterns: type `&!` is non-empty } match uninhab_union() { diff --git a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr index 1b1096c977ad4..e1079f912d076 100644 --- a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr +++ b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr @@ -1,4 +1,4 @@ -error[E0004]: non-exhaustive patterns: type `&'static !` is non-empty +error[E0004]: non-exhaustive patterns: type `&!` is non-empty --> $DIR/always-inhabited-union-ref.rs:23:11 | LL | match uninhab_ref() { diff --git a/src/test/ui/pattern/usefulness/match-arm-statics-2.rs b/src/test/ui/pattern/usefulness/match-arm-statics-2.rs index 4c5f2d356491b..728d4a64495b1 100644 --- a/src/test/ui/pattern/usefulness/match-arm-statics-2.rs +++ b/src/test/ui/pattern/usefulness/match-arm-statics-2.rs @@ -1,3 +1,8 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl + use self::Direction::{North, East, South, West}; #[derive(PartialEq, Eq)] diff --git a/src/test/ui/pattern/usefulness/match-arm-statics-2.stderr b/src/test/ui/pattern/usefulness/match-arm-statics-2.stderr index 8521e37d3fddc..7bb6a700a3717 100644 --- a/src/test/ui/pattern/usefulness/match-arm-statics-2.stderr +++ b/src/test/ui/pattern/usefulness/match-arm-statics-2.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `(true, false)` not covered - --> $DIR/match-arm-statics-2.rs:17:11 + --> $DIR/match-arm-statics-2.rs:22:11 | LL | match (true, false) { | ^^^^^^^^^^^^^ pattern `(true, false)` not covered @@ -7,15 +7,23 @@ LL | match (true, false) { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `Some(Some(West))` not covered - --> $DIR/match-arm-statics-2.rs:29:11 + --> $DIR/match-arm-statics-2.rs:34:11 | LL | match Some(Some(North)) { | ^^^^^^^^^^^^^^^^^ pattern `Some(Some(West))` not covered + | + ::: $SRC_DIR/libcore/option.rs:LL:COL + | +LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T), + | ---- + | | + | not covered + | not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `Foo { bar: Some(North), baz: NewBool(true) }` not covered - --> $DIR/match-arm-statics-2.rs:48:11 + --> $DIR/match-arm-statics-2.rs:53:11 | LL | / struct Foo { LL | | bar: Option, diff --git a/src/test/ui/pattern/usefulness/match-privately-empty.rs b/src/test/ui/pattern/usefulness/match-privately-empty.rs index 315eb03d16564..c7cde468bb9bf 100644 --- a/src/test/ui/pattern/usefulness/match-privately-empty.rs +++ b/src/test/ui/pattern/usefulness/match-privately-empty.rs @@ -1,3 +1,8 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl + #![feature(never_type)] #![feature(exhaustive_patterns)] diff --git a/src/test/ui/pattern/usefulness/match-privately-empty.stderr b/src/test/ui/pattern/usefulness/match-privately-empty.stderr index f79d180a1b8b5..4dcbf05ecce2b 100644 --- a/src/test/ui/pattern/usefulness/match-privately-empty.stderr +++ b/src/test/ui/pattern/usefulness/match-privately-empty.stderr @@ -1,8 +1,13 @@ error[E0004]: non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered - --> $DIR/match-privately-empty.rs:13:11 + --> $DIR/match-privately-empty.rs:18:11 | LL | match private::DATA { | ^^^^^^^^^^^^^ pattern `Some(Private { misc: true, .. })` not covered + | + ::: $SRC_DIR/libcore/option.rs:LL:COL + | +LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T), + | ---- not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match.rs b/src/test/ui/pattern/usefulness/non-exhaustive-match.rs index 9947989dc1211..59f7bb892c68c 100644 --- a/src/test/ui/pattern/usefulness/non-exhaustive-match.rs +++ b/src/test/ui/pattern/usefulness/non-exhaustive-match.rs @@ -1,3 +1,8 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl + #![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 a06ad5788515c..dff2c8d9424c3 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:7:11 + --> $DIR/non-exhaustive-match.rs:12: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:8:11 + --> $DIR/non-exhaustive-match.rs:13:11 | LL | match true { | ^^^^ pattern `false` not covered @@ -21,15 +21,20 @@ 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:11:11 + --> $DIR/non-exhaustive-match.rs:16:11 | LL | match Some(10) { | ^^^^^^^^ pattern `Some(_)` not covered + | + ::: $SRC_DIR/libcore/option.rs:LL:COL + | +LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T), + | ---- not covered | = 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:14:11 + --> $DIR/non-exhaustive-match.rs:19:11 | LL | match (2, 3, 4) { | ^^^^^^^^^ patterns `(_, _, std::i32::MIN..=3i32)` and `(_, _, 5i32..=std::i32::MAX)` not covered @@ -37,7 +42,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:18:11 + --> $DIR/non-exhaustive-match.rs:23:11 | LL | match (T::A, T::A) { | ^^^^^^^^^^^^ pattern `(A, A)` not covered @@ -45,7 +50,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:22:11 + --> $DIR/non-exhaustive-match.rs:27:11 | LL | enum T { A, B } | --------------- @@ -59,7 +64,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:33:11 + --> $DIR/non-exhaustive-match.rs:38:11 | LL | match *vec { | ^^^^ pattern `[]` not covered @@ -67,7 +72,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:46:11 + --> $DIR/non-exhaustive-match.rs:51:11 | LL | match *vec { | ^^^^ pattern `[_, _, _, _, ..]` not covered diff --git a/src/test/ui/privacy/associated-item-privacy-inherent.stderr b/src/test/ui/privacy/associated-item-privacy-inherent.stderr index 88561568ea5a4..1e94e7c620d03 100644 --- a/src/test/ui/privacy/associated-item-privacy-inherent.stderr +++ b/src/test/ui/privacy/associated-item-privacy-inherent.stderr @@ -2,7 +2,7 @@ error: type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is p --> $DIR/associated-item-privacy-inherent.rs:13:21 | LL | let value = Pub::method; - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ private type ... LL | priv_nominal::mac!(); | --------------------- in this macro invocation @@ -13,7 +13,7 @@ error: type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is p --> $DIR/associated-item-privacy-inherent.rs:15:9 | LL | value; - | ^^^^^ + | ^^^^^ private type ... LL | priv_nominal::mac!(); | --------------------- in this macro invocation @@ -24,7 +24,7 @@ error: type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is p --> $DIR/associated-item-privacy-inherent.rs:17:13 | LL | Pub.method(); - | ^^^^^^ + | ^^^^^^ private type ... LL | priv_nominal::mac!(); | --------------------- in this macro invocation @@ -35,7 +35,7 @@ error: associated constant `CONST` is private --> $DIR/associated-item-privacy-inherent.rs:19:9 | LL | Pub::CONST; - | ^^^^^^^^^^ + | ^^^^^^^^^^ private associated constant ... LL | priv_nominal::mac!(); | --------------------- in this macro invocation @@ -46,7 +46,7 @@ error: type `priv_signature::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:37:21 | LL | let value = Pub::method; - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ private type ... LL | priv_signature::mac!(); | ----------------------- in this macro invocation @@ -57,7 +57,7 @@ error: type `priv_signature::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:39:9 | LL | value; - | ^^^^^ + | ^^^^^ private type ... LL | priv_signature::mac!(); | ----------------------- in this macro invocation @@ -68,7 +68,7 @@ error: type `priv_signature::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:41:13 | LL | Pub.method(loop {}); - | ^^^^^^ + | ^^^^^^ private type ... LL | priv_signature::mac!(); | ----------------------- in this macro invocation @@ -79,7 +79,7 @@ error: type `priv_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:57:21 | LL | let value = Pub::method::; - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_substs::mac!(); | -------------------- in this macro invocation @@ -90,7 +90,7 @@ error: type `priv_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:59:9 | LL | value; - | ^^^^^ + | ^^^^^ private type ... LL | priv_substs::mac!(); | -------------------- in this macro invocation @@ -101,7 +101,7 @@ error: type `priv_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:61:9 | LL | Pub.method::(); - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_substs::mac!(); | -------------------- in this macro invocation @@ -112,7 +112,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:80:21 | LL | let value = ::method; - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -123,7 +123,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:82:9 | LL | value; - | ^^^^^ + | ^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -134,7 +134,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:84:21 | LL | let value = Pub::method; - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -145,7 +145,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:86:9 | LL | value; - | ^^^^^ + | ^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -156,7 +156,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:88:21 | LL | let value = ::static_method; - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -167,7 +167,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:90:9 | LL | value; - | ^^^^^ + | ^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -178,7 +178,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:92:21 | LL | let value = Pub::static_method; - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -189,7 +189,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:94:9 | LL | value; - | ^^^^^ + | ^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -200,7 +200,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:96:19 | LL | Pub(Priv).method(); - | ^^^^^^ + | ^^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -211,7 +211,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:99:10 | LL | ::CONST; - | ^^^ + | ^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -222,7 +222,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:101:9 | LL | Pub::CONST; - | ^^^^^^^^^^ + | ^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation diff --git a/src/test/ui/privacy/associated-item-privacy-trait.stderr b/src/test/ui/privacy/associated-item-privacy-trait.stderr index db24e425a01f6..c30cc947d4508 100644 --- a/src/test/ui/privacy/associated-item-privacy-trait.stderr +++ b/src/test/ui/privacy/associated-item-privacy-trait.stderr @@ -2,7 +2,7 @@ error: type `for<'r> fn(&'r priv_trait::Pub) { $DIR/associated-item-privacy-trait.rs:17:21 | LL | let value = ::method; - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_trait::mac!(); | ------------------- in this macro invocation @@ -13,7 +13,7 @@ error: type `for<'r> fn(&'r priv_trait::Pub) { $DIR/associated-item-privacy-trait.rs:19:9 | LL | value; - | ^^^^^ + | ^^^^^ private type ... LL | priv_trait::mac!(); | ------------------- in this macro invocation @@ -24,7 +24,7 @@ error: type `for<'r> fn(&'r Self) {::method}` is pri --> $DIR/associated-item-privacy-trait.rs:21:13 | LL | Pub.method(); - | ^^^^^^ + | ^^^^^^ private type ... LL | priv_trait::mac!(); | ------------------- in this macro invocation @@ -35,7 +35,7 @@ error: associated constant `PrivTr::CONST` is private --> $DIR/associated-item-privacy-trait.rs:23:9 | LL | ::CONST; - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ private associated constant ... LL | priv_trait::mac!(); | ------------------- in this macro invocation @@ -46,7 +46,7 @@ error: associated type `PrivTr::AssocTy` is private --> $DIR/associated-item-privacy-trait.rs:25:16 | LL | let _: ::AssocTy; - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ private associated type ... LL | priv_trait::mac!(); | ------------------- in this macro invocation @@ -57,7 +57,7 @@ error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-trait.rs:27:34 | LL | pub type InSignatureTy = ::AssocTy; - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ private trait ... LL | priv_trait::mac!(); | ------------------- in this macro invocation @@ -68,7 +68,7 @@ error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-trait.rs:29:34 | LL | pub trait InSignatureTr: PrivTr {} - | ^^^^^^ + | ^^^^^^ private trait ... LL | priv_trait::mac!(); | ------------------- in this macro invocation @@ -79,7 +79,7 @@ error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-trait.rs:31:14 | LL | impl PrivTr for u8 {} - | ^^^^^^ + | ^^^^^^ private trait ... LL | priv_trait::mac!(); | ------------------- in this macro invocation @@ -90,7 +90,7 @@ error: type `priv_signature::Priv` is private --> $DIR/associated-item-privacy-trait.rs:48:21 | LL | let value = ::method; - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_signature::mac!(); | ----------------------- in this macro invocation @@ -101,7 +101,7 @@ error: type `priv_signature::Priv` is private --> $DIR/associated-item-privacy-trait.rs:50:9 | LL | value; - | ^^^^^ + | ^^^^^ private type ... LL | priv_signature::mac!(); | ----------------------- in this macro invocation @@ -112,7 +112,7 @@ error: type `priv_signature::Priv` is private --> $DIR/associated-item-privacy-trait.rs:52:13 | LL | Pub.method(loop {}); - | ^^^^^^ + | ^^^^^^ private type ... LL | priv_signature::mac!(); | ----------------------- in this macro invocation @@ -123,7 +123,7 @@ error: type `priv_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:69:21 | LL | let value = ::method::; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_substs::mac!(); | -------------------- in this macro invocation @@ -134,7 +134,7 @@ error: type `priv_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:71:9 | LL | value; - | ^^^^^ + | ^^^^^ private type ... LL | priv_substs::mac!(); | -------------------- in this macro invocation @@ -145,7 +145,7 @@ error: type `priv_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:73:9 | LL | Pub.method::(); - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_substs::mac!(); | -------------------- in this macro invocation @@ -156,7 +156,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:93:21 | LL | let value = ::method; - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -167,7 +167,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:95:9 | LL | value; - | ^^^^^ + | ^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -178,7 +178,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:97:21 | LL | let value = >::method; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -189,7 +189,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:99:9 | LL | value; - | ^^^^^ + | ^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -200,7 +200,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:101:9 | LL | Pub.method(); - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -211,7 +211,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:104:21 | LL | let value = >::method; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -222,7 +222,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:106:9 | LL | value; - | ^^^^^ + | ^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -233,7 +233,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:108:9 | LL | Priv.method(); - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -244,7 +244,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:111:9 | LL | ::CONST; - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -255,7 +255,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:113:9 | LL | >::CONST; - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -266,7 +266,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:115:9 | LL | >::CONST; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -277,7 +277,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:119:30 | LL | let _: >::AssocTy; - | ^ + | ^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -288,7 +288,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:121:17 | LL | let _: >::AssocTy; - | ^^^^ + | ^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -299,7 +299,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:124:35 | LL | pub type InSignatureTy1 = ::AssocTy; - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -310,7 +310,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:126:35 | LL | pub type InSignatureTy2 = >::AssocTy; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -321,7 +321,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:128:14 | LL | impl PubTr for u8 {} - | ^^^^^ + | ^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation diff --git a/src/test/ui/privacy/associated-item-privacy-type-binding.stderr b/src/test/ui/privacy/associated-item-privacy-type-binding.stderr index fd8b8cf0db652..d8515ccb66920 100644 --- a/src/test/ui/privacy/associated-item-privacy-type-binding.stderr +++ b/src/test/ui/privacy/associated-item-privacy-type-binding.stderr @@ -2,7 +2,7 @@ error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:11:13 | LL | let _: Box>; - | ^ + | ^ private trait ... LL | priv_trait::mac1!(); | -------------------- in this macro invocation @@ -13,7 +13,7 @@ error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:11:16 | LL | let _: Box>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private trait ... LL | priv_trait::mac1!(); | -------------------- in this macro invocation @@ -24,7 +24,7 @@ error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:14:31 | LL | type InSignatureTy2 = Box>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private trait ... LL | priv_trait::mac1!(); | -------------------- in this macro invocation @@ -35,7 +35,7 @@ error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:16:31 | LL | trait InSignatureTr2: PubTr {} - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ private trait ... LL | priv_trait::mac1!(); | -------------------- in this macro invocation @@ -46,7 +46,7 @@ error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:20:13 | LL | let _: Box>; - | ^ + | ^ private trait ... LL | priv_trait::mac2!(); | -------------------- in this macro invocation @@ -57,7 +57,7 @@ error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:20:16 | LL | let _: Box>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private trait ... LL | priv_trait::mac2!(); | -------------------- in this macro invocation @@ -68,7 +68,7 @@ error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:23:31 | LL | type InSignatureTy1 = Box>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private trait ... LL | priv_trait::mac2!(); | -------------------- in this macro invocation @@ -79,7 +79,7 @@ error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:25:31 | LL | trait InSignatureTr1: PrivTr {} - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ private trait ... LL | priv_trait::mac2!(); | -------------------- in this macro invocation @@ -90,7 +90,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-type-binding.rs:44:13 | LL | let _: Box>; - | ^ + | ^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -101,7 +101,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-type-binding.rs:44:16 | LL | let _: Box>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -112,7 +112,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-type-binding.rs:47:13 | LL | let _: Box>; - | ^ + | ^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -123,7 +123,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-type-binding.rs:47:16 | LL | let _: Box>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -134,7 +134,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-type-binding.rs:50:35 | LL | pub type InSignatureTy1 = Box>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -145,7 +145,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-type-binding.rs:52:35 | LL | pub type InSignatureTy2 = Box>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -156,7 +156,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-type-binding.rs:54:31 | LL | trait InSignatureTr1: PubTrWithParam {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -167,7 +167,7 @@ error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-type-binding.rs:56:31 | LL | trait InSignatureTr2: PubTr {} - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation diff --git a/src/test/ui/privacy/decl-macro.stderr b/src/test/ui/privacy/decl-macro.stderr index ae2e1b4b644a3..5bc6f07fffac3 100644 --- a/src/test/ui/privacy/decl-macro.stderr +++ b/src/test/ui/privacy/decl-macro.stderr @@ -2,7 +2,7 @@ error[E0603]: macro `mac` is private --> $DIR/decl-macro.rs:8:8 | LL | m::mac!(); - | ^^^ this macro is private + | ^^^ private macro | note: the macro `mac` is defined here --> $DIR/decl-macro.rs:4:5 diff --git a/src/test/ui/privacy/legacy-ctor-visibility.stderr b/src/test/ui/privacy/legacy-ctor-visibility.stderr index 74a1f1ceeffb4..4f0d72de6f1a4 100644 --- a/src/test/ui/privacy/legacy-ctor-visibility.stderr +++ b/src/test/ui/privacy/legacy-ctor-visibility.stderr @@ -1,12 +1,10 @@ error[E0423]: expected function, tuple struct or tuple variant, found struct `S` --> $DIR/legacy-ctor-visibility.rs:9:13 | -LL | / fn f() { -LL | | S(10); - | | ^ help: a function with a similar name exists: `f` -LL | | -LL | | } - | |_________- similarly named function `f` defined here +LL | fn f() { + | ------ similarly named function `f` defined here +LL | S(10); + | ^ help: a function with a similar name exists: `f` error: aborting due to previous error diff --git a/src/test/ui/privacy/privacy-in-paths.stderr b/src/test/ui/privacy/privacy-in-paths.stderr index 8860d8f15f748..2eb3ebb51c20a 100644 --- a/src/test/ui/privacy/privacy-in-paths.stderr +++ b/src/test/ui/privacy/privacy-in-paths.stderr @@ -2,7 +2,7 @@ error[E0603]: module `bar` is private --> $DIR/privacy-in-paths.rs:24:16 | LL | ::foo::bar::baz::f(); - | ^^^ this module is private + | ^^^ private module | note: the module `bar` is defined here --> $DIR/privacy-in-paths.rs:3:5 @@ -14,7 +14,7 @@ error[E0603]: module `bar` is private --> $DIR/privacy-in-paths.rs:25:16 | LL | ::foo::bar::S::f(); - | ^^^ this module is private + | ^^^ private module | note: the module `bar` is defined here --> $DIR/privacy-in-paths.rs:3:5 @@ -26,7 +26,7 @@ error[E0603]: trait `T` is private --> $DIR/privacy-in-paths.rs:26:23 | LL | <() as ::foo::T>::Assoc::f(); - | ^ this trait is private + | ^ private trait | note: the trait `T` is defined here --> $DIR/privacy-in-paths.rs:8:5 diff --git a/src/test/ui/privacy/privacy-ns2.stderr b/src/test/ui/privacy/privacy-ns2.stderr index 8b12109b37307..0c826147a1ca7 100644 --- a/src/test/ui/privacy/privacy-ns2.stderr +++ b/src/test/ui/privacy/privacy-ns2.stderr @@ -58,7 +58,7 @@ error[E0603]: trait `Bar` is private --> $DIR/privacy-ns2.rs:63:15 | LL | use foo3::Bar; - | ^^^ this trait is private + | ^^^ private trait | note: the trait `Bar` is defined here --> $DIR/privacy-ns2.rs:55:5 @@ -70,7 +70,7 @@ error[E0603]: trait `Bar` is private --> $DIR/privacy-ns2.rs:67:15 | LL | use foo3::Bar; - | ^^^ this trait is private + | ^^^ private trait | note: the trait `Bar` is defined here --> $DIR/privacy-ns2.rs:55:5 @@ -82,7 +82,7 @@ error[E0603]: trait `Bar` is private --> $DIR/privacy-ns2.rs:74:16 | LL | use foo3::{Bar,Baz}; - | ^^^ this trait is private + | ^^^ private trait | note: the trait `Bar` is defined here --> $DIR/privacy-ns2.rs:55:5 diff --git a/src/test/ui/privacy/privacy-sanity.rs b/src/test/ui/privacy/privacy-sanity.rs index f83b24c49a10a..8bbf1ab5d1f30 100644 --- a/src/test/ui/privacy/privacy-sanity.rs +++ b/src/test/ui/privacy/privacy-sanity.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] pub trait Tr { fn f(); diff --git a/src/test/ui/privacy/privacy-ufcs.stderr b/src/test/ui/privacy/privacy-ufcs.stderr index 08640b802a244..e93a458ce6cb6 100644 --- a/src/test/ui/privacy/privacy-ufcs.stderr +++ b/src/test/ui/privacy/privacy-ufcs.stderr @@ -2,7 +2,7 @@ error[E0603]: trait `Bar` is private --> $DIR/privacy-ufcs.rs:12:20 | LL | ::baz(); - | ^^^ this trait is private + | ^^^ private trait | note: the trait `Bar` is defined here --> $DIR/privacy-ufcs.rs:4:5 diff --git a/src/test/ui/privacy/privacy1.rs b/src/test/ui/privacy/privacy1.rs index fcf7b19572f1f..e28fd13b97f23 100644 --- a/src/test/ui/privacy/privacy1.rs +++ b/src/test/ui/privacy/privacy1.rs @@ -74,7 +74,7 @@ mod bar { } self::baz::A; self::baz::A::foo(); - self::baz::A::bar(); //~ ERROR: method `bar` is private + self::baz::A::bar(); //~ ERROR: associated function `bar` is private self::baz::A.foo2(); // this used to cause an ICE in privacy traversal. @@ -92,21 +92,21 @@ pub fn gpub() {} fn lol() { bar::A; bar::A::foo(); - bar::A::bar(); //~ ERROR: method `bar` is private + bar::A::bar(); //~ ERROR: associated function `bar` is private bar::A.foo2(); } mod foo { fn test() { ::bar::A::foo(); - ::bar::A::bar(); //~ ERROR: method `bar` is private + ::bar::A::bar(); //~ ERROR: associated function `bar` is private ::bar::A.foo2(); ::bar::baz::A::foo(); //~ ERROR: module `baz` is private ::bar::baz::A::bar(); //~ ERROR: module `baz` is private - //~^ ERROR: method `bar` is private + //~^ ERROR: associated function `bar` is private ::bar::baz::A.foo2(); //~ ERROR: module `baz` is private ::bar::baz::A.bar2(); //~ ERROR: module `baz` is private - //~^ ERROR: method `bar2` is private + //~^ ERROR: associated function `bar2` is private let _: isize = ::bar::B::foo(); //~ ERROR: trait `B` is private diff --git a/src/test/ui/privacy/privacy1.stderr b/src/test/ui/privacy/privacy1.stderr index 215df0dc75441..65c10a7bca75d 100644 --- a/src/test/ui/privacy/privacy1.stderr +++ b/src/test/ui/privacy/privacy1.stderr @@ -2,7 +2,7 @@ error[E0603]: module `baz` is private --> $DIR/privacy1.rs:132:18 | LL | use bar::baz::{foo, bar}; - | ^^^ this module is private + | ^^^ private module | note: the module `baz` is defined here --> $DIR/privacy1.rs:50:5 @@ -14,7 +14,7 @@ error[E0603]: module `baz` is private --> $DIR/privacy1.rs:132:18 | LL | use bar::baz::{foo, bar}; - | ^^^ this module is private + | ^^^ private module | note: the module `baz` is defined here --> $DIR/privacy1.rs:50:5 @@ -26,7 +26,7 @@ error[E0603]: module `baz` is private --> $DIR/privacy1.rs:141:18 | LL | use bar::baz; - | ^^^ this module is private + | ^^^ private module | note: the module `baz` is defined here --> $DIR/privacy1.rs:50:5 @@ -38,7 +38,7 @@ error[E0603]: module `i` is private --> $DIR/privacy1.rs:165:20 | LL | use self::foo::i::A; - | ^ this module is private + | ^ private module | note: the module `i` is defined here --> $DIR/privacy1.rs:170:9 @@ -50,7 +50,7 @@ error[E0603]: module `baz` is private --> $DIR/privacy1.rs:104:16 | LL | ::bar::baz::A::foo(); - | ^^^ this module is private + | ^^^ private module | note: the module `baz` is defined here --> $DIR/privacy1.rs:50:5 @@ -62,7 +62,7 @@ error[E0603]: module `baz` is private --> $DIR/privacy1.rs:105:16 | LL | ::bar::baz::A::bar(); - | ^^^ this module is private + | ^^^ private module | note: the module `baz` is defined here --> $DIR/privacy1.rs:50:5 @@ -74,7 +74,7 @@ error[E0603]: module `baz` is private --> $DIR/privacy1.rs:107:16 | LL | ::bar::baz::A.foo2(); - | ^^^ this module is private + | ^^^ private module | note: the module `baz` is defined here --> $DIR/privacy1.rs:50:5 @@ -86,7 +86,7 @@ error[E0603]: module `baz` is private --> $DIR/privacy1.rs:108:16 | LL | ::bar::baz::A.bar2(); - | ^^^ this module is private + | ^^^ private module | note: the module `baz` is defined here --> $DIR/privacy1.rs:50:5 @@ -98,7 +98,7 @@ error[E0603]: trait `B` is private --> $DIR/privacy1.rs:112:16 | LL | ::bar::B::foo(); - | ^ this trait is private + | ^ private trait | note: the trait `B` is defined here --> $DIR/privacy1.rs:40:5 @@ -110,7 +110,7 @@ error[E0603]: function `epriv` is private --> $DIR/privacy1.rs:118:20 | LL | ::bar::epriv(); - | ^^^^^ this function is private + | ^^^^^ private function | note: the function `epriv` is defined here --> $DIR/privacy1.rs:65:9 @@ -122,7 +122,7 @@ error[E0603]: module `baz` is private --> $DIR/privacy1.rs:127:16 | LL | ::bar::baz::foo(); - | ^^^ this module is private + | ^^^ private module | note: the module `baz` is defined here --> $DIR/privacy1.rs:50:5 @@ -134,7 +134,7 @@ error[E0603]: module `baz` is private --> $DIR/privacy1.rs:128:16 | LL | ::bar::baz::bar(); - | ^^^ this module is private + | ^^^ private module | note: the module `baz` is defined here --> $DIR/privacy1.rs:50:5 @@ -146,7 +146,7 @@ error[E0603]: trait `B` is private --> $DIR/privacy1.rs:157:17 | LL | impl ::bar::B for f32 { fn foo() -> f32 { 1.0 } } - | ^ this trait is private + | ^ private trait | note: the trait `B` is defined here --> $DIR/privacy1.rs:40:5 @@ -154,35 +154,35 @@ note: the trait `B` is defined here LL | trait B { | ^^^^^^^ -error[E0624]: method `bar` is private - --> $DIR/privacy1.rs:77:9 +error[E0624]: associated function `bar` is private + --> $DIR/privacy1.rs:77:23 | LL | self::baz::A::bar(); - | ^^^^^^^^^^^^^^^^^ + | ^^^ private associated function -error[E0624]: method `bar` is private - --> $DIR/privacy1.rs:95:5 +error[E0624]: associated function `bar` is private + --> $DIR/privacy1.rs:95:13 | LL | bar::A::bar(); - | ^^^^^^^^^^^ + | ^^^ private associated function -error[E0624]: method `bar` is private - --> $DIR/privacy1.rs:102:9 +error[E0624]: associated function `bar` is private + --> $DIR/privacy1.rs:102:19 | LL | ::bar::A::bar(); - | ^^^^^^^^^^^^^ + | ^^^ private associated function -error[E0624]: method `bar` is private - --> $DIR/privacy1.rs:105:9 +error[E0624]: associated function `bar` is private + --> $DIR/privacy1.rs:105:24 | LL | ::bar::baz::A::bar(); - | ^^^^^^^^^^^^^^^^^^ + | ^^^ private associated function -error[E0624]: method `bar2` is private +error[E0624]: associated function `bar2` is private --> $DIR/privacy1.rs:108:23 | LL | ::bar::baz::A.bar2(); - | ^^^^ + | ^^^^ private associated function error: aborting due to 18 previous errors diff --git a/src/test/ui/privacy/privacy2.stderr b/src/test/ui/privacy/privacy2.stderr index 719dc27ccf4d6..c2a33ce1f59b3 100644 --- a/src/test/ui/privacy/privacy2.stderr +++ b/src/test/ui/privacy/privacy2.stderr @@ -8,13 +8,18 @@ error[E0603]: function import `foo` is private --> $DIR/privacy2.rs:23:20 | LL | use bar::glob::foo; - | ^^^ this function import is private + | ^^^ private function import | -note: the function import `foo` is defined here +note: the function import `foo` is defined here... --> $DIR/privacy2.rs:10:13 | LL | use foo; | ^^^ +note: ...and refers to the function `foo` which is defined here + --> $DIR/privacy2.rs:14:1 + | +LL | pub fn foo() {} + | ^^^^^^^^^^^^ consider importing it directly error: requires `sized` lang_item diff --git a/src/test/ui/privacy/privacy4.stderr b/src/test/ui/privacy/privacy4.stderr index e34b2d5049b9e..7552fa71a3a3a 100644 --- a/src/test/ui/privacy/privacy4.stderr +++ b/src/test/ui/privacy/privacy4.stderr @@ -2,7 +2,7 @@ error[E0603]: module `glob` is private --> $DIR/privacy4.rs:21:14 | LL | use bar::glob::gpriv; - | ^^^^ this module is private + | ^^^^ private module | note: the module `glob` is defined here --> $DIR/privacy4.rs:13:5 diff --git a/src/test/ui/privacy/privacy5.stderr b/src/test/ui/privacy/privacy5.stderr index 197a857cc3dc4..216abfc68b812 100644 --- a/src/test/ui/privacy/privacy5.stderr +++ b/src/test/ui/privacy/privacy5.stderr @@ -5,7 +5,7 @@ LL | pub struct A(()); | -- a constructor is private if any of the fields is private ... LL | let a = a::A(()); - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `A` is defined here --> $DIR/privacy5.rs:6:5 @@ -20,7 +20,7 @@ LL | pub struct B(isize); | ----- a constructor is private if any of the fields is private ... LL | let b = a::B(2); - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `B` is defined here --> $DIR/privacy5.rs:7:5 @@ -35,7 +35,7 @@ LL | pub struct C(pub isize, isize); | ---------------- a constructor is private if any of the fields is private ... LL | let c = a::C(2, 3); - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `C` is defined here --> $DIR/privacy5.rs:8:5 @@ -50,7 +50,7 @@ LL | pub struct A(()); | -- a constructor is private if any of the fields is private ... LL | let a::A(()) = a; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `A` is defined here --> $DIR/privacy5.rs:6:5 @@ -65,7 +65,7 @@ LL | pub struct A(()); | -- a constructor is private if any of the fields is private ... LL | let a::A(_) = a; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `A` is defined here --> $DIR/privacy5.rs:6:5 @@ -80,7 +80,7 @@ LL | pub struct A(()); | -- a constructor is private if any of the fields is private ... LL | match a { a::A(()) => {} } - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `A` is defined here --> $DIR/privacy5.rs:6:5 @@ -95,7 +95,7 @@ LL | pub struct A(()); | -- a constructor is private if any of the fields is private ... LL | match a { a::A(_) => {} } - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `A` is defined here --> $DIR/privacy5.rs:6:5 @@ -110,7 +110,7 @@ LL | pub struct B(isize); | ----- a constructor is private if any of the fields is private ... LL | let a::B(_) = b; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `B` is defined here --> $DIR/privacy5.rs:7:5 @@ -125,7 +125,7 @@ LL | pub struct B(isize); | ----- a constructor is private if any of the fields is private ... LL | let a::B(_b) = b; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `B` is defined here --> $DIR/privacy5.rs:7:5 @@ -140,7 +140,7 @@ LL | pub struct B(isize); | ----- a constructor is private if any of the fields is private ... LL | match b { a::B(_) => {} } - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `B` is defined here --> $DIR/privacy5.rs:7:5 @@ -155,7 +155,7 @@ LL | pub struct B(isize); | ----- a constructor is private if any of the fields is private ... LL | match b { a::B(_b) => {} } - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `B` is defined here --> $DIR/privacy5.rs:7:5 @@ -170,7 +170,7 @@ LL | pub struct B(isize); | ----- a constructor is private if any of the fields is private ... LL | match b { a::B(1) => {} a::B(_) => {} } - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `B` is defined here --> $DIR/privacy5.rs:7:5 @@ -185,7 +185,7 @@ LL | pub struct B(isize); | ----- a constructor is private if any of the fields is private ... LL | match b { a::B(1) => {} a::B(_) => {} } - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `B` is defined here --> $DIR/privacy5.rs:7:5 @@ -200,7 +200,7 @@ LL | pub struct C(pub isize, isize); | ---------------- a constructor is private if any of the fields is private ... LL | let a::C(_, _) = c; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `C` is defined here --> $DIR/privacy5.rs:8:5 @@ -215,7 +215,7 @@ LL | pub struct C(pub isize, isize); | ---------------- a constructor is private if any of the fields is private ... LL | let a::C(_a, _) = c; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `C` is defined here --> $DIR/privacy5.rs:8:5 @@ -230,7 +230,7 @@ LL | pub struct C(pub isize, isize); | ---------------- a constructor is private if any of the fields is private ... LL | let a::C(_, _b) = c; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `C` is defined here --> $DIR/privacy5.rs:8:5 @@ -245,7 +245,7 @@ LL | pub struct C(pub isize, isize); | ---------------- a constructor is private if any of the fields is private ... LL | let a::C(_a, _b) = c; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `C` is defined here --> $DIR/privacy5.rs:8:5 @@ -260,7 +260,7 @@ LL | pub struct C(pub isize, isize); | ---------------- a constructor is private if any of the fields is private ... LL | match c { a::C(_, _) => {} } - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `C` is defined here --> $DIR/privacy5.rs:8:5 @@ -275,7 +275,7 @@ LL | pub struct C(pub isize, isize); | ---------------- a constructor is private if any of the fields is private ... LL | match c { a::C(_a, _) => {} } - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `C` is defined here --> $DIR/privacy5.rs:8:5 @@ -290,7 +290,7 @@ LL | pub struct C(pub isize, isize); | ---------------- a constructor is private if any of the fields is private ... LL | match c { a::C(_, _b) => {} } - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `C` is defined here --> $DIR/privacy5.rs:8:5 @@ -305,7 +305,7 @@ LL | pub struct C(pub isize, isize); | ---------------- a constructor is private if any of the fields is private ... LL | match c { a::C(_a, _b) => {} } - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `C` is defined here --> $DIR/privacy5.rs:8:5 @@ -320,7 +320,7 @@ LL | pub struct A(()); | -- a constructor is private if any of the fields is private ... LL | let a2 = a::A; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `A` is defined here --> $DIR/privacy5.rs:6:5 @@ -335,7 +335,7 @@ LL | pub struct B(isize); | ----- a constructor is private if any of the fields is private ... LL | let b2 = a::B; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `B` is defined here --> $DIR/privacy5.rs:7:5 @@ -350,7 +350,7 @@ LL | pub struct C(pub isize, isize); | ---------------- a constructor is private if any of the fields is private ... LL | let c2 = a::C; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `C` is defined here --> $DIR/privacy5.rs:8:5 @@ -362,7 +362,7 @@ error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:90:20 | LL | let a = other::A(()); - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 | @@ -379,7 +379,7 @@ error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:91:20 | LL | let b = other::B(2); - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | @@ -396,7 +396,7 @@ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:92:20 | LL | let c = other::C(2, 3); - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | @@ -413,7 +413,7 @@ error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:95:16 | LL | let other::A(()) = a; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 | @@ -430,7 +430,7 @@ error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:96:16 | LL | let other::A(_) = a; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 | @@ -447,7 +447,7 @@ error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:97:22 | LL | match a { other::A(()) => {} } - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 | @@ -464,7 +464,7 @@ error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:98:22 | LL | match a { other::A(_) => {} } - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 | @@ -481,7 +481,7 @@ error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:100:16 | LL | let other::B(_) = b; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | @@ -498,7 +498,7 @@ error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:101:16 | LL | let other::B(_b) = b; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | @@ -515,7 +515,7 @@ error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:102:22 | LL | match b { other::B(_) => {} } - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | @@ -532,7 +532,7 @@ error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:103:22 | LL | match b { other::B(_b) => {} } - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | @@ -549,7 +549,7 @@ error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:104:22 | LL | match b { other::B(1) => {} - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | @@ -566,7 +566,7 @@ error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:105:16 | LL | other::B(_) => {} } - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | @@ -583,7 +583,7 @@ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:107:16 | LL | let other::C(_, _) = c; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | @@ -600,7 +600,7 @@ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:108:16 | LL | let other::C(_a, _) = c; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | @@ -617,7 +617,7 @@ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:109:16 | LL | let other::C(_, _b) = c; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | @@ -634,7 +634,7 @@ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:110:16 | LL | let other::C(_a, _b) = c; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | @@ -651,7 +651,7 @@ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:111:22 | LL | match c { other::C(_, _) => {} } - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | @@ -668,7 +668,7 @@ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:112:22 | LL | match c { other::C(_a, _) => {} } - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | @@ -685,7 +685,7 @@ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:113:22 | LL | match c { other::C(_, _b) => {} } - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | @@ -702,7 +702,7 @@ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:114:22 | LL | match c { other::C(_a, _b) => {} } - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | @@ -719,7 +719,7 @@ error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:122:21 | LL | let a2 = other::A; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 | @@ -736,7 +736,7 @@ error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:123:21 | LL | let b2 = other::B; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | @@ -753,7 +753,7 @@ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:124:21 | LL | let c2 = other::C; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | diff --git a/src/test/ui/privacy/private-impl-method.rs b/src/test/ui/privacy/private-impl-method.rs index b5587920f1cc9..f7be6726c5eaa 100644 --- a/src/test/ui/privacy/private-impl-method.rs +++ b/src/test/ui/privacy/private-impl-method.rs @@ -17,5 +17,5 @@ fn f() { fn main() { let s = a::Foo { x: 1 }; s.bar(); - s.foo(); //~ ERROR method `foo` is private + s.foo(); //~ ERROR associated function `foo` is private } diff --git a/src/test/ui/privacy/private-impl-method.stderr b/src/test/ui/privacy/private-impl-method.stderr index e1da3f47a4ef7..444b9180b3f59 100644 --- a/src/test/ui/privacy/private-impl-method.stderr +++ b/src/test/ui/privacy/private-impl-method.stderr @@ -1,8 +1,8 @@ -error[E0624]: method `foo` is private +error[E0624]: associated function `foo` is private --> $DIR/private-impl-method.rs:20:7 | LL | s.foo(); - | ^^^ + | ^^^ private associated function error: aborting due to previous error diff --git a/src/test/ui/privacy/private-in-public-non-principal-2.rs b/src/test/ui/privacy/private-in-public-non-principal-2.rs index 8a59073fa6c7e..cd3d609ca3ea6 100644 --- a/src/test/ui/privacy/private-in-public-non-principal-2.rs +++ b/src/test/ui/privacy/private-in-public-non-principal-2.rs @@ -1,4 +1,5 @@ #![feature(optin_builtin_traits)] +#![feature(negative_impls)] #[allow(private_in_public)] mod m { diff --git a/src/test/ui/privacy/private-in-public-non-principal-2.stderr b/src/test/ui/privacy/private-in-public-non-principal-2.stderr index 2db4925722642..7850694aab207 100644 --- a/src/test/ui/privacy/private-in-public-non-principal-2.stderr +++ b/src/test/ui/privacy/private-in-public-non-principal-2.stderr @@ -1,8 +1,8 @@ error: trait `m::PrivNonPrincipal` is private - --> $DIR/private-in-public-non-principal-2.rs:11:5 + --> $DIR/private-in-public-non-principal-2.rs:12:5 | LL | m::leak_dyn_nonprincipal(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ private trait error: aborting due to previous error diff --git a/src/test/ui/privacy/private-in-public-non-principal.rs b/src/test/ui/privacy/private-in-public-non-principal.rs index 5d89d8105b119..aa946f5c0ac05 100644 --- a/src/test/ui/privacy/private-in-public-non-principal.rs +++ b/src/test/ui/privacy/private-in-public-non-principal.rs @@ -1,4 +1,5 @@ #![feature(optin_builtin_traits)] +#![feature(negative_impls)] pub trait PubPrincipal {} auto trait PrivNonPrincipal {} @@ -10,7 +11,7 @@ pub fn leak_dyn_nonprincipal() -> Box { loo #[deny(missing_docs)] fn container() { impl dyn PubPrincipal { - pub fn check_doc_lint() {} //~ ERROR missing documentation for a method + pub fn check_doc_lint() {} //~ ERROR missing documentation for an associated function } impl dyn PubPrincipal + PrivNonPrincipal { pub fn check_doc_lint() {} // OK, no missing doc lint diff --git a/src/test/ui/privacy/private-in-public-non-principal.stderr b/src/test/ui/privacy/private-in-public-non-principal.stderr index 2a41fae43c629..f7f8d71bdb5f2 100644 --- a/src/test/ui/privacy/private-in-public-non-principal.stderr +++ b/src/test/ui/privacy/private-in-public-non-principal.stderr @@ -1,5 +1,5 @@ warning: private trait `PrivNonPrincipal` in public interface (error E0445) - --> $DIR/private-in-public-non-principal.rs:6:1 + --> $DIR/private-in-public-non-principal.rs:7:1 | LL | pub fn leak_dyn_nonprincipal() -> Box { loop {} } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,14 +8,14 @@ LL | pub fn leak_dyn_nonprincipal() -> Box = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 -error: missing documentation for a method - --> $DIR/private-in-public-non-principal.rs:13:9 +error: missing documentation for an associated function + --> $DIR/private-in-public-non-principal.rs:14:9 | LL | pub fn check_doc_lint() {} | ^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/private-in-public-non-principal.rs:10:8 + --> $DIR/private-in-public-non-principal.rs:11:8 | LL | #[deny(missing_docs)] | ^^^^^^^^^^^^ diff --git a/src/test/ui/privacy/private-inferred-type-1.stderr b/src/test/ui/privacy/private-inferred-type-1.stderr index 097b8b9a61eff..576498b2cf8ef 100644 --- a/src/test/ui/privacy/private-inferred-type-1.stderr +++ b/src/test/ui/privacy/private-inferred-type-1.stderr @@ -2,13 +2,13 @@ error: type `m::Priv` is private --> $DIR/private-inferred-type-1.rs:16:5 | LL | [].arr0_secret(); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ private type error: type `m::Priv` is private --> $DIR/private-inferred-type-1.rs:17:5 | LL | None.ty_param_secret(); - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ private type error: aborting due to 2 previous errors diff --git a/src/test/ui/privacy/private-inferred-type-2.stderr b/src/test/ui/privacy/private-inferred-type-2.stderr index da95cc49241ae..f19e367ef110e 100644 --- a/src/test/ui/privacy/private-inferred-type-2.stderr +++ b/src/test/ui/privacy/private-inferred-type-2.stderr @@ -2,19 +2,19 @@ error: type `m::Priv` is private --> $DIR/private-inferred-type-2.rs:16:5 | LL | m::Pub::get_priv; - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ private type error: type `m::Priv` is private --> $DIR/private-inferred-type-2.rs:17:5 | LL | m::Pub::static_method; - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ private type error: type `ext::Priv` is private --> $DIR/private-inferred-type-2.rs:18:5 | LL | ext::Pub::static_method; - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ private type error: aborting due to 3 previous errors diff --git a/src/test/ui/privacy/private-inferred-type-3.stderr b/src/test/ui/privacy/private-inferred-type-3.stderr index 376f1334ff806..39ef6472526c3 100644 --- a/src/test/ui/privacy/private-inferred-type-3.stderr +++ b/src/test/ui/privacy/private-inferred-type-3.stderr @@ -2,7 +2,7 @@ error: type `fn() {ext::priv_fn}` is private --> $DIR/private-inferred-type-3.rs:16:5 | LL | ext::m!(); - | ^^^^^^^^^^ + | ^^^^^^^^^^ private type | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) @@ -10,7 +10,7 @@ error: static `PRIV_STATIC` is private --> $DIR/private-inferred-type-3.rs:16:5 | LL | ext::m!(); - | ^^^^^^^^^^ + | ^^^^^^^^^^ private static | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) @@ -18,7 +18,7 @@ error: type `ext::PrivEnum` is private --> $DIR/private-inferred-type-3.rs:16:5 | LL | ext::m!(); - | ^^^^^^^^^^ + | ^^^^^^^^^^ private type | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) @@ -26,7 +26,7 @@ error: type `fn() {::method}` is private --> $DIR/private-inferred-type-3.rs:16:5 | LL | ext::m!(); - | ^^^^^^^^^^ + | ^^^^^^^^^^ private type | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) @@ -34,7 +34,7 @@ error: type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct}` is private --> $DIR/private-inferred-type-3.rs:16:5 | LL | ext::m!(); - | ^^^^^^^^^^ + | ^^^^^^^^^^ private type | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) @@ -42,7 +42,7 @@ error: type `fn(u8) -> ext::PubTupleStruct {ext::PubTupleStruct}` is private --> $DIR/private-inferred-type-3.rs:16:5 | LL | ext::m!(); - | ^^^^^^^^^^ + | ^^^^^^^^^^ private type | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) @@ -50,7 +50,7 @@ error: type `for<'r> fn(&'r ext::Pub) {ext::Pub::::priv_method}` is priv --> $DIR/private-inferred-type-3.rs:16:5 | LL | ext::m!(); - | ^^^^^^^^^^ + | ^^^^^^^^^^ private type | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/privacy/private-inferred-type.stderr b/src/test/ui/privacy/private-inferred-type.stderr index 48c83c2186591..7d1f794bfe459 100644 --- a/src/test/ui/privacy/private-inferred-type.stderr +++ b/src/test/ui/privacy/private-inferred-type.stderr @@ -20,97 +20,97 @@ error: type `m::Priv` is private --> $DIR/private-inferred-type.rs:97:9 | LL | let _: m::Alias; - | ^ + | ^ private type error: type `m::Priv` is private --> $DIR/private-inferred-type.rs:97:12 | LL | let _: m::Alias; - | ^^^^^^^^ + | ^^^^^^^^ private type error: type `m::Priv` is private --> $DIR/private-inferred-type.rs:99:13 | LL | let _: ::AssocTy; - | ^^^^^^^^ + | ^^^^^^^^ private type error: type `m::Priv` is private --> $DIR/private-inferred-type.rs:100:5 | LL | m::Alias {}; - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ private type error: type `m::Priv` is private --> $DIR/private-inferred-type.rs:101:5 | LL | m::Pub { 0: m::Alias {} }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ private type error: type `m::Priv` is private --> $DIR/private-inferred-type.rs:103:5 | LL | m::Pub::static_method; - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ private type error: type `m::Priv` is private --> $DIR/private-inferred-type.rs:104:5 | LL | m::Pub::INHERENT_ASSOC_CONST; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type error: type `m::Priv` is private --> $DIR/private-inferred-type.rs:105:5 | LL | m::Pub(0u8).method_with_substs::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type error: type `m::Priv` is private --> $DIR/private-inferred-type.rs:106:17 | LL | m::Pub(0u8).method_with_priv_params(loop{}); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ private type error: type `m::Priv` is private --> $DIR/private-inferred-type.rs:107:5 | LL | ::TRAIT_ASSOC_CONST; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type error: type `m::Priv` is private --> $DIR/private-inferred-type.rs:108:6 | LL | >::INHERENT_ASSOC_CONST; - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ private type error: type `m::Priv` is private --> $DIR/private-inferred-type.rs:109:5 | LL | >::INHERENT_ASSOC_CONST_GENERIC_SELF; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type error: type `m::Priv` is private --> $DIR/private-inferred-type.rs:110:5 | LL | >::static_method_generic_self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type error: type `m::Priv` is private --> $DIR/private-inferred-type.rs:112:5 | LL | u8::pub_method; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ private type error: type `adjust::S2` is private --> $DIR/private-inferred-type.rs:114:5 | LL | adjust::S1.method_s3(); - | ^^^^^^^^^^ + | ^^^^^^^^^^ private type error: type `fn() {m::priv_fn}` is private --> $DIR/private-inferred-type.rs:39:9 | LL | priv_fn; - | ^^^^^^^ + | ^^^^^^^ private type ... LL | m::m!(); | -------- in this macro invocation @@ -121,7 +121,7 @@ error: type `m::PrivEnum` is private --> $DIR/private-inferred-type.rs:41:9 | LL | PrivEnum::Variant; - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ private type ... LL | m::m!(); | -------- in this macro invocation @@ -132,7 +132,7 @@ error: type `fn() {::method}` is private --> $DIR/private-inferred-type.rs:43:9 | LL | ::method; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | m::m!(); | -------- in this macro invocation @@ -143,7 +143,7 @@ error: type `fn(u8) -> m::PrivTupleStruct {m::PrivTupleStruct}` is private --> $DIR/private-inferred-type.rs:45:9 | LL | PrivTupleStruct; - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ private type ... LL | m::m!(); | -------- in this macro invocation @@ -154,7 +154,7 @@ error: type `fn(u8) -> m::PubTupleStruct {m::PubTupleStruct}` is private --> $DIR/private-inferred-type.rs:47:9 | LL | PubTupleStruct; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ private type ... LL | m::m!(); | -------- in this macro invocation @@ -165,7 +165,7 @@ error: type `for<'r> fn(&'r m::Pub) {m::Pub::::priv_method}` is private --> $DIR/private-inferred-type.rs:49:18 | LL | Pub(0u8).priv_method(); - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ private type ... LL | m::m!(); | -------- in this macro invocation @@ -176,61 +176,61 @@ error: trait `m::Trait` is private --> $DIR/private-inferred-type.rs:118:5 | LL | m::leak_anon1(); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ private trait error: type `m::Priv` is private --> $DIR/private-inferred-type.rs:119:5 | LL | m::leak_anon2(); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ private type error: type `m::Priv` is private --> $DIR/private-inferred-type.rs:120:5 | LL | m::leak_anon3(); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ private type error: trait `m::Trait` is private --> $DIR/private-inferred-type.rs:122:5 | LL | m::leak_dyn1(); - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ private trait error: type `m::Priv` is private --> $DIR/private-inferred-type.rs:123:5 | LL | m::leak_dyn2(); - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ private type error: type `m::Priv` is private --> $DIR/private-inferred-type.rs:124:5 | LL | m::leak_dyn3(); - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ private type error: type `m::Priv` is private --> $DIR/private-inferred-type.rs:127:13 | LL | let a = m::Alias {}; - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ private type error: type `m::Priv` is private --> $DIR/private-inferred-type.rs:128:17 | LL | let mut b = a; - | ^ + | ^ private type error: type `m::Priv` is private --> $DIR/private-inferred-type.rs:129:9 | LL | b = a; - | ^ + | ^ private type error: type `m::Priv` is private --> $DIR/private-inferred-type.rs:130:11 | LL | match a { - | ^ + | ^ private type error: aborting due to 33 previous errors diff --git a/src/test/ui/privacy/private-item-simple.stderr b/src/test/ui/privacy/private-item-simple.stderr index f51b74f6cb53b..e3d90150e2e3e 100644 --- a/src/test/ui/privacy/private-item-simple.stderr +++ b/src/test/ui/privacy/private-item-simple.stderr @@ -2,7 +2,7 @@ error[E0603]: function `f` is private --> $DIR/private-item-simple.rs:6:8 | LL | a::f(); - | ^ this function is private + | ^ private function | note: the function `f` is defined here --> $DIR/private-item-simple.rs:2:5 diff --git a/src/test/ui/privacy/private-method-cross-crate.rs b/src/test/ui/privacy/private-method-cross-crate.rs index 4da44e0682be9..ab3bbdfe49669 100644 --- a/src/test/ui/privacy/private-method-cross-crate.rs +++ b/src/test/ui/privacy/private-method-cross-crate.rs @@ -4,5 +4,5 @@ use cci_class_5::kitties::cat; fn main() { let nyan : cat = cat(52, 99); - nyan.nap(); //~ ERROR method `nap` is private + nyan.nap(); //~ ERROR associated function `nap` is private } diff --git a/src/test/ui/privacy/private-method-cross-crate.stderr b/src/test/ui/privacy/private-method-cross-crate.stderr index 10e0bfe5b1367..8a47846d667e3 100644 --- a/src/test/ui/privacy/private-method-cross-crate.stderr +++ b/src/test/ui/privacy/private-method-cross-crate.stderr @@ -1,8 +1,8 @@ -error[E0624]: method `nap` is private +error[E0624]: associated function `nap` is private --> $DIR/private-method-cross-crate.rs:7:8 | LL | nyan.nap(); - | ^^^ + | ^^^ private associated function error: aborting due to previous error diff --git a/src/test/ui/privacy/private-method-inherited.rs b/src/test/ui/privacy/private-method-inherited.rs index bc27027e886ba..2f6454288ae68 100644 --- a/src/test/ui/privacy/private-method-inherited.rs +++ b/src/test/ui/privacy/private-method-inherited.rs @@ -10,5 +10,5 @@ mod a { fn main() { let x = a::Foo; - x.f(); //~ ERROR method `f` is private + x.f(); //~ ERROR associated function `f` is private } diff --git a/src/test/ui/privacy/private-method-inherited.stderr b/src/test/ui/privacy/private-method-inherited.stderr index d2ba591ef0cc1..8083b197a5d78 100644 --- a/src/test/ui/privacy/private-method-inherited.stderr +++ b/src/test/ui/privacy/private-method-inherited.stderr @@ -1,8 +1,8 @@ -error[E0624]: method `f` is private +error[E0624]: associated function `f` is private --> $DIR/private-method-inherited.rs:13:7 | LL | x.f(); - | ^ + | ^ private associated function error: aborting due to previous error diff --git a/src/test/ui/privacy/private-method.rs b/src/test/ui/privacy/private-method.rs index a9bea520e7573..76a642cde1a8a 100644 --- a/src/test/ui/privacy/private-method.rs +++ b/src/test/ui/privacy/private-method.rs @@ -19,5 +19,5 @@ mod kitties { fn main() { let nyan : kitties::Cat = kitties::cat(52, 99); - nyan.nap(); //~ ERROR method `nap` is private + nyan.nap(); //~ ERROR associated function `nap` is private } diff --git a/src/test/ui/privacy/private-method.stderr b/src/test/ui/privacy/private-method.stderr index 61fc122e318ee..a15fce46877ce 100644 --- a/src/test/ui/privacy/private-method.stderr +++ b/src/test/ui/privacy/private-method.stderr @@ -1,8 +1,8 @@ -error[E0624]: method `nap` is private +error[E0624]: associated function `nap` is private --> $DIR/private-method.rs:22:8 | LL | nyan.nap(); - | ^^^ + | ^^^ private associated function error: aborting due to previous error diff --git a/src/test/ui/privacy/private-struct-field-cross-crate.stderr b/src/test/ui/privacy/private-struct-field-cross-crate.stderr index 857f2436aa829..ac00d82adab42 100644 --- a/src/test/ui/privacy/private-struct-field-cross-crate.stderr +++ b/src/test/ui/privacy/private-struct-field-cross-crate.stderr @@ -1,8 +1,8 @@ error[E0616]: field `meows` of struct `cci_class::kitties::cat` is private - --> $DIR/private-struct-field-cross-crate.rs:7:14 + --> $DIR/private-struct-field-cross-crate.rs:7:19 | LL | assert_eq!(nyan.meows, 52); - | ^^^^^^^^^^ + | ^^^^^ private field error: aborting due to previous error diff --git a/src/test/ui/privacy/private-struct-field-ctor.stderr b/src/test/ui/privacy/private-struct-field-ctor.stderr index 97585c1d8805b..7c32ebc2cf7b9 100644 --- a/src/test/ui/privacy/private-struct-field-ctor.stderr +++ b/src/test/ui/privacy/private-struct-field-ctor.stderr @@ -2,7 +2,7 @@ error[E0451]: field `x` of struct `a::Foo` is private --> $DIR/private-struct-field-ctor.rs:8:22 | LL | let s = a::Foo { x: 1 }; - | ^^^^ field `x` is private + | ^^^^ private field error: aborting due to previous error diff --git a/src/test/ui/privacy/private-struct-field-pattern.stderr b/src/test/ui/privacy/private-struct-field-pattern.stderr index 69bd58aacfc54..9190317403ec1 100644 --- a/src/test/ui/privacy/private-struct-field-pattern.stderr +++ b/src/test/ui/privacy/private-struct-field-pattern.stderr @@ -2,7 +2,7 @@ error[E0451]: field `x` of struct `a::Foo` is private --> $DIR/private-struct-field-pattern.rs:15:15 | LL | Foo { x: _ } => {} - | ^^^^ field `x` is private + | ^^^^ private field error: aborting due to previous error diff --git a/src/test/ui/privacy/private-struct-field.stderr b/src/test/ui/privacy/private-struct-field.stderr index da53c73b4311c..c89ae507ab5fd 100644 --- a/src/test/ui/privacy/private-struct-field.stderr +++ b/src/test/ui/privacy/private-struct-field.stderr @@ -1,8 +1,8 @@ error[E0616]: field `meows` of struct `cat::Cat` is private - --> $DIR/private-struct-field.rs:13:16 + --> $DIR/private-struct-field.rs:13:21 | LL | assert_eq!(nyan.meows, 52); - | ^^^^^^^^^^ + | ^^^^^ private field error: aborting due to previous error diff --git a/src/test/ui/privacy/private-type-in-interface.stderr b/src/test/ui/privacy/private-type-in-interface.stderr index aa4bfb7fc9a19..ea89035c3d006 100644 --- a/src/test/ui/privacy/private-type-in-interface.stderr +++ b/src/test/ui/privacy/private-type-in-interface.stderr @@ -2,55 +2,55 @@ error: type `m::Priv` is private --> $DIR/private-type-in-interface.rs:15:9 | LL | fn f(_: m::Alias) {} - | ^^^^^^^^ + | ^^^^^^^^ private type error: type `m::Priv` is private --> $DIR/private-type-in-interface.rs:15:6 | LL | fn f(_: m::Alias) {} - | ^ + | ^ private type error: type `ext::Priv` is private --> $DIR/private-type-in-interface.rs:17:13 | LL | fn f_ext(_: ext::Alias) {} - | ^^^^^^^^^^ + | ^^^^^^^^^^ private type error: type `ext::Priv` is private --> $DIR/private-type-in-interface.rs:17:10 | LL | fn f_ext(_: ext::Alias) {} - | ^ + | ^ private type error: type `m::Priv` is private --> $DIR/private-type-in-interface.rs:21:6 | LL | impl m::Alias {} - | ^^^^^^^^ + | ^^^^^^^^ private type error: type `ext::Priv` is private --> $DIR/private-type-in-interface.rs:22:14 | LL | impl Tr1 for ext::Alias {} - | ^^^^^^^^^^ + | ^^^^^^^^^^ private type error: type `m::Priv` is private --> $DIR/private-type-in-interface.rs:23:10 | LL | type A = ::X; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ private type error: type `m::Priv` is private --> $DIR/private-type-in-interface.rs:27:11 | LL | fn g() -> impl Tr2 { 0 } - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ private type error: type `ext::Priv` is private --> $DIR/private-type-in-interface.rs:28:15 | LL | fn g_ext() -> impl Tr2 { 0 } - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ private type error: aborting due to 9 previous errors diff --git a/src/test/ui/privacy/restricted/struct-literal-field.stderr b/src/test/ui/privacy/restricted/struct-literal-field.stderr index dd609944a4b3f..591980dc3450d 100644 --- a/src/test/ui/privacy/restricted/struct-literal-field.stderr +++ b/src/test/ui/privacy/restricted/struct-literal-field.stderr @@ -2,7 +2,7 @@ error[E0451]: field `x` of struct `foo::bar::S` is private --> $DIR/struct-literal-field.rs:18:9 | LL | S { x: 0 }; - | ^^^^ field `x` is private + | ^^^^ private field error: aborting due to previous error diff --git a/src/test/ui/privacy/restricted/test.stderr b/src/test/ui/privacy/restricted/test.stderr index aac444b8e3c98..40512a34bd959 100644 --- a/src/test/ui/privacy/restricted/test.stderr +++ b/src/test/ui/privacy/restricted/test.stderr @@ -26,7 +26,7 @@ error[E0603]: struct `Crate` is private --> $DIR/test.rs:38:25 | LL | use pub_restricted::Crate; - | ^^^^^ this struct is private + | ^^^^^ private struct | note: the struct `Crate` is defined here --> $DIR/auxiliary/pub_restricted.rs:3:1 @@ -38,7 +38,7 @@ error[E0603]: function `f` is private --> $DIR/test.rs:30:19 | LL | use foo::bar::f; - | ^ this function is private + | ^ private function | note: the function `f` is defined here --> $DIR/test.rs:8:9 @@ -47,46 +47,46 @@ LL | pub(super) fn f() {} | ^^^^^^^^^^^^^^^^^ error[E0616]: field `x` of struct `foo::bar::S` is private - --> $DIR/test.rs:31:5 + --> $DIR/test.rs:31:18 | LL | S::default().x; - | ^^^^^^^^^^^^^^ + | ^ private field -error[E0624]: method `f` is private +error[E0624]: associated function `f` is private --> $DIR/test.rs:32:18 | LL | S::default().f(); - | ^ + | ^ private associated function -error[E0624]: method `g` is private - --> $DIR/test.rs:33:5 +error[E0624]: associated function `g` is private + --> $DIR/test.rs:33:8 | LL | S::g(); - | ^^^^ + | ^ private associated function error[E0616]: field `y` of struct `pub_restricted::Universe` is private - --> $DIR/test.rs:42:13 + --> $DIR/test.rs:42:15 | LL | let _ = u.y; - | ^^^ + | ^ private field error[E0616]: field `z` of struct `pub_restricted::Universe` is private - --> $DIR/test.rs:43:13 + --> $DIR/test.rs:43:15 | LL | let _ = u.z; - | ^^^ + | ^ private field -error[E0624]: method `g` is private +error[E0624]: associated function `g` is private --> $DIR/test.rs:45:7 | LL | u.g(); - | ^ + | ^ private associated function -error[E0624]: method `h` is private +error[E0624]: associated function `h` is private --> $DIR/test.rs:46:7 | LL | u.h(); - | ^ + | ^ private associated function error: aborting due to 12 previous errors diff --git a/src/test/ui/privacy/union-field-privacy-1.stderr b/src/test/ui/privacy/union-field-privacy-1.stderr index 96a1d7ed5090a..15096eb113966 100644 --- a/src/test/ui/privacy/union-field-privacy-1.stderr +++ b/src/test/ui/privacy/union-field-privacy-1.stderr @@ -2,13 +2,13 @@ error[E0451]: field `c` of union `m::U` is private --> $DIR/union-field-privacy-1.rs:12:20 | LL | let u = m::U { c: 0 }; - | ^^^^ field `c` is private + | ^^^^ private field error[E0451]: field `c` of union `m::U` is private --> $DIR/union-field-privacy-1.rs:16:16 | LL | let m::U { c } = u; - | ^ field `c` is private + | ^ private field error: aborting due to 2 previous errors diff --git a/src/test/ui/privacy/union-field-privacy-2.stderr b/src/test/ui/privacy/union-field-privacy-2.stderr index 8789178caac26..a23cf90332b02 100644 --- a/src/test/ui/privacy/union-field-privacy-2.stderr +++ b/src/test/ui/privacy/union-field-privacy-2.stderr @@ -1,8 +1,8 @@ error[E0616]: field `c` of union `m::U` is private - --> $DIR/union-field-privacy-2.rs:14:13 + --> $DIR/union-field-privacy-2.rs:14:15 | LL | let c = u.c; - | ^^^ + | ^ private field error: aborting due to previous error diff --git a/src/test/ui/proc-macro/attribute-spans-preserved.stdout b/src/test/ui/proc-macro/attribute-spans-preserved.stdout index faf3171215665..cf9a97491f039 100644 --- a/src/test/ui/proc-macro/attribute-spans-preserved.stdout +++ b/src/test/ui/proc-macro/attribute-spans-preserved.stdout @@ -1 +1 @@ -fn main () { let y : u32 = "z" ; { let x : u32 = "y" ; } } +fn main() { let y : u32 = "z" ; { let x : u32 = "y" ; } } diff --git a/src/test/ui/proc-macro/attributes-included.stderr b/src/test/ui/proc-macro/attributes-included.stderr index 27a215de032aa..bfbcf68b6c7e6 100644 --- a/src/test/ui/proc-macro/attributes-included.stderr +++ b/src/test/ui/proc-macro/attributes-included.stderr @@ -2,7 +2,7 @@ warning: unused variable: `a` --> $DIR/attributes-included.rs:17:9 | LL | let a: i32 = "foo"; - | ^ help: consider prefixing with an underscore: `_a` + | ^ help: if this is intentional, prefix it with an underscore: `_a` | note: the lint level is defined here --> $DIR/attributes-included.rs:4:9 diff --git a/src/test/ui/proc-macro/auxiliary/derive-unstable.rs b/src/test/ui/proc-macro/auxiliary/derive-unstable.rs index f702df66db1b8..2ccd3f88200e3 100644 --- a/src/test/ui/proc-macro/auxiliary/derive-unstable.rs +++ b/src/test/ui/proc-macro/auxiliary/derive-unstable.rs @@ -10,5 +10,5 @@ use proc_macro::TokenStream; #[proc_macro_derive(Unstable)] pub fn derive(_input: TokenStream) -> TokenStream { - "unsafe fn foo() -> u32 { ::std::intrinsics::init() }".parse().unwrap() + "unsafe fn foo() -> u32 { ::std::intrinsics::abort() }".parse().unwrap() } diff --git a/src/test/ui/proc-macro/auxiliary/duplicate.rs b/src/test/ui/proc-macro/auxiliary/duplicate.rs new file mode 100644 index 0000000000000..b8f82b46f0945 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/duplicate.rs @@ -0,0 +1,32 @@ +// force-host +// no-prefer-dynamic + +#![deny(unused)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro_attribute] +pub fn duplicate(attr: TokenStream, item: TokenStream) -> TokenStream { + let mut new_name = Some(attr.into_iter().nth(0).unwrap()); + let mut encountered_idents = 0; + let input = item.to_string(); + let ret = item + .into_iter() + .map(move |token| match token { + TokenTree::Ident(_) if encountered_idents == 1 => { + encountered_idents += 1; + new_name.take().unwrap() + } + TokenTree::Ident(_) => { + encountered_idents += 1; + token + } + _ => token, + }) + .collect::(); + let mut input_again = input.parse::().unwrap(); + input_again.extend(ret); + input_again +} diff --git a/src/test/ui/proc-macro/crt-static.rs b/src/test/ui/proc-macro/crt-static.rs new file mode 100644 index 0000000000000..90e3d422b3cbc --- /dev/null +++ b/src/test/ui/proc-macro/crt-static.rs @@ -0,0 +1,16 @@ +// Test proc-macro crate can be built without addtional RUSTFLAGS +// on musl target +// override -Ctarget-feature=-crt-static from compiletest +// compile-flags: -Ctarget-feature= +// ignore-wasm32 +// build-pass +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Foo)] +pub fn derive_foo(input: TokenStream) -> TokenStream { + input +} diff --git a/src/test/ui/proc-macro/derive-bad.rs b/src/test/ui/proc-macro/derive-bad.rs index 62c0741b6697a..cb5188b5fb43f 100644 --- a/src/test/ui/proc-macro/derive-bad.rs +++ b/src/test/ui/proc-macro/derive-bad.rs @@ -3,11 +3,9 @@ #[macro_use] extern crate derive_bad; -#[derive( - A -)] -//~^^ ERROR proc-macro derive produced unparseable tokens +#[derive(A)] +//~^ ERROR proc-macro derive produced unparseable tokens //~| ERROR expected `:`, found `}` -struct A; +struct A; //~ ERROR the name `A` is defined multiple times fn main() {} diff --git a/src/test/ui/proc-macro/derive-bad.stderr b/src/test/ui/proc-macro/derive-bad.stderr index 8667396c98989..bc5ed9815238a 100644 --- a/src/test/ui/proc-macro/derive-bad.stderr +++ b/src/test/ui/proc-macro/derive-bad.stderr @@ -1,16 +1,28 @@ error: expected `:`, found `}` - --> $DIR/derive-bad.rs:7:5 + --> $DIR/derive-bad.rs:6:10 | -LL | A - | ^ expected `:` +LL | #[derive(A)] + | ^ expected `:` | = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error: proc-macro derive produced unparseable tokens - --> $DIR/derive-bad.rs:7:5 + --> $DIR/derive-bad.rs:6:10 | -LL | A - | ^ +LL | #[derive(A)] + | ^ -error: aborting due to 2 previous errors +error[E0428]: the name `A` is defined multiple times + --> $DIR/derive-bad.rs:9:1 + | +LL | #[derive(A)] + | - previous definition of the type `A` here +... +LL | struct A; + | ^^^^^^^^^ `A` redefined here + | + = note: `A` must be defined only once in the type namespace of this module + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0428`. diff --git a/src/test/ui/proc-macro/disappearing-resolution.stderr b/src/test/ui/proc-macro/disappearing-resolution.stderr index 3beaedf61d73a..ff7ddcde6e0c4 100644 --- a/src/test/ui/proc-macro/disappearing-resolution.stderr +++ b/src/test/ui/proc-macro/disappearing-resolution.stderr @@ -8,7 +8,7 @@ error[E0603]: derive macro import `Empty` is private --> $DIR/disappearing-resolution.rs:11:8 | LL | use m::Empty; - | ^^^^^ this derive macro import is private + | ^^^^^ private derive macro import | note: the derive macro import `Empty` is defined here --> $DIR/disappearing-resolution.rs:9:9 diff --git a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout index ea06f6c1acaf9..15433bebde967 100644 --- a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout +++ b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout @@ -1,4 +1,4 @@ -PRINT-BANG INPUT (DISPLAY): struct M ($crate :: S) ; +PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ; PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -39,7 +39,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ }, ] PRINT-ATTR INPUT (DISPLAY): struct A(crate::S); -PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ; +PRINT-ATTR RE-COLLECTED (DISPLAY): struct A($crate :: S) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", diff --git a/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout b/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout index 619b2fd5321ff..73e407918ec8c 100644 --- a/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout +++ b/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout @@ -1,5 +1,5 @@ PRINT-ATTR INPUT (DISPLAY): struct A(identity!(crate :: S)); -PRINT-ATTR RE-COLLECTED (DISPLAY): struct A (identity ! ($crate :: S)) ; +PRINT-ATTR RE-COLLECTED (DISPLAY): struct A(identity ! ($crate :: S)) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -55,7 +55,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ }, ] PRINT-ATTR INPUT (DISPLAY): struct B(identity!(::dollar_crate_external :: S)); -PRINT-ATTR RE-COLLECTED (DISPLAY): struct B (identity ! ($crate :: S)) ; +PRINT-ATTR RE-COLLECTED (DISPLAY): struct B(identity ! ($crate :: S)) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", diff --git a/src/test/ui/proc-macro/dollar-crate.stdout b/src/test/ui/proc-macro/dollar-crate.stdout index 5fdc6f8ee96ca..e125a3e7f1737 100644 --- a/src/test/ui/proc-macro/dollar-crate.stdout +++ b/src/test/ui/proc-macro/dollar-crate.stdout @@ -1,4 +1,4 @@ -PRINT-BANG INPUT (DISPLAY): struct M ($crate :: S) ; +PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ; PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -39,7 +39,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ }, ] PRINT-ATTR INPUT (DISPLAY): struct A(crate::S); -PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ; +PRINT-ATTR RE-COLLECTED (DISPLAY): struct A($crate :: S) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -80,7 +80,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ }, ] PRINT-DERIVE INPUT (DISPLAY): struct D(crate::S); -PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ($crate :: S) ; +PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D($crate :: S) ; PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -120,7 +120,7 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ span: #3 bytes(LO..HI), }, ] -PRINT-BANG INPUT (DISPLAY): struct M ($crate :: S) ; +PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ; PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -161,7 +161,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ }, ] PRINT-ATTR INPUT (DISPLAY): struct A(::dollar_crate_external::S); -PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ; +PRINT-ATTR RE-COLLECTED (DISPLAY): struct A($crate :: S) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -202,7 +202,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ }, ] PRINT-DERIVE INPUT (DISPLAY): struct D(::dollar_crate_external::S); -PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ($crate :: S) ; +PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D($crate :: S) ; PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", diff --git a/src/test/ui/proc-macro/expand-to-unstable-2.stderr b/src/test/ui/proc-macro/expand-to-unstable-2.stderr index 19144b210a127..5974fa4c554ca 100644 --- a/src/test/ui/proc-macro/expand-to-unstable-2.stderr +++ b/src/test/ui/proc-macro/expand-to-unstable-2.stderr @@ -1,12 +1,10 @@ -error[E0658]: attributes starting with `rustc` are reserved for use by the `rustc` compiler +error: attributes starting with `rustc` are reserved for use by the `rustc` compiler --> $DIR/expand-to-unstable-2.rs:10:10 | LL | #[derive(Unstable)] | ^^^^^^^^ | - = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/proc-macro/export-macro.stderr b/src/test/ui/proc-macro/export-macro.stderr index bc64caa07f972..36a6a9bb3e72b 100644 --- a/src/test/ui/proc-macro/export-macro.stderr +++ b/src/test/ui/proc-macro/export-macro.stderr @@ -1,10 +1,8 @@ error: cannot export macro_rules! macros from a `proc-macro` crate type currently --> $DIR/export-macro.rs:9:1 | -LL | / macro_rules! foo { -LL | | ($e:expr) => ($e) -LL | | } - | |_^ +LL | macro_rules! foo { + | ^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/proc-macro/exports.stderr b/src/test/ui/proc-macro/exports.stderr index 0ecbdf98dd31c..7b23d08f2a8a5 100644 --- a/src/test/ui/proc-macro/exports.stderr +++ b/src/test/ui/proc-macro/exports.stderr @@ -2,7 +2,7 @@ error: `proc-macro` crate types currently cannot export any items other than fun --> $DIR/exports.rs:7:1 | LL | pub fn a() {} - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^ error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]` --> $DIR/exports.rs:8:1 @@ -14,13 +14,13 @@ error: `proc-macro` crate types currently cannot export any items other than fun --> $DIR/exports.rs:9:1 | LL | pub enum C {} - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^ error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]` --> $DIR/exports.rs:10:1 | LL | pub mod d {} - | ^^^^^^^^^^^^ + | ^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/proc-macro/invalid-punct-ident-1.rs b/src/test/ui/proc-macro/invalid-punct-ident-1.rs index 9de57da5af434..3f78dea917b19 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-1.rs +++ b/src/test/ui/proc-macro/invalid-punct-ident-1.rs @@ -14,3 +14,5 @@ extern crate invalid_punct_ident; invalid_punct!(); //~ ERROR proc macro panicked + +fn main() {} diff --git a/src/test/ui/proc-macro/invalid-punct-ident-2.rs b/src/test/ui/proc-macro/invalid-punct-ident-2.rs index 79f72324b1d89..4e89e80ae7c41 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-2.rs +++ b/src/test/ui/proc-macro/invalid-punct-ident-2.rs @@ -14,3 +14,5 @@ extern crate invalid_punct_ident; invalid_ident!(); //~ ERROR proc macro panicked + +fn main() {} diff --git a/src/test/ui/proc-macro/invalid-punct-ident-3.rs b/src/test/ui/proc-macro/invalid-punct-ident-3.rs index d01e9b699cac5..8d8ce8f932e71 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-3.rs +++ b/src/test/ui/proc-macro/invalid-punct-ident-3.rs @@ -14,3 +14,5 @@ extern crate invalid_punct_ident; invalid_raw_ident!(); //~ ERROR proc macro panicked + +fn main() {} diff --git a/src/test/ui/proc-macro/invalid-punct-ident-4.rs b/src/test/ui/proc-macro/invalid-punct-ident-4.rs index e50f24deae343..59b347dac679c 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-4.rs +++ b/src/test/ui/proc-macro/invalid-punct-ident-4.rs @@ -3,5 +3,10 @@ #[macro_use] extern crate invalid_punct_ident; -lexer_failure!(); //~ ERROR proc macro panicked - //~| ERROR unexpected closing delimiter: `)` +lexer_failure!(); +//~^ ERROR proc macro panicked +//~| ERROR unexpected closing delimiter: `)` + +fn main() { + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/src/test/ui/proc-macro/invalid-punct-ident-4.stderr b/src/test/ui/proc-macro/invalid-punct-ident-4.stderr index fe3e55b31be5d..3b357aecea864 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-4.stderr +++ b/src/test/ui/proc-macro/invalid-punct-ident-4.stderr @@ -12,5 +12,14 @@ error: proc macro panicked LL | lexer_failure!(); | ^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/invalid-punct-ident-4.rs:11:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/proc-macro/issue-36935.rs b/src/test/ui/proc-macro/issue-36935.rs index f809592d5f449..5c43a564c00c2 100644 --- a/src/test/ui/proc-macro/issue-36935.rs +++ b/src/test/ui/proc-macro/issue-36935.rs @@ -5,6 +5,7 @@ extern crate test_macros; #[derive(Identity, Panic)] //~ ERROR proc-macro derive panicked struct Baz { + //~^ ERROR the name `Baz` is defined multiple times a: i32, b: i32, } diff --git a/src/test/ui/proc-macro/issue-36935.stderr b/src/test/ui/proc-macro/issue-36935.stderr index da4366eb668d6..2b2e28fdb2fda 100644 --- a/src/test/ui/proc-macro/issue-36935.stderr +++ b/src/test/ui/proc-macro/issue-36935.stderr @@ -6,5 +6,17 @@ LL | #[derive(Identity, Panic)] | = help: message: panic-derive -error: aborting due to previous error +error[E0428]: the name `Baz` is defined multiple times + --> $DIR/issue-36935.rs:7:1 + | +LL | struct Baz { + | ^^^^^^^^^^ + | | + | `Baz` redefined here + | previous definition of the type `Baz` here + | + = note: `Baz` must be defined only once in the type namespace of this module + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0428`. diff --git a/src/test/ui/proc-macro/issue-50493.stderr b/src/test/ui/proc-macro/issue-50493.stderr index 7997786b50bc9..e378a56713400 100644 --- a/src/test/ui/proc-macro/issue-50493.stderr +++ b/src/test/ui/proc-macro/issue-50493.stderr @@ -8,7 +8,7 @@ error[E0616]: field `field` of struct `Restricted` is private --> $DIR/issue-50493.rs:6:10 | LL | #[derive(Derive)] - | ^^^^^^ + | ^^^^^^ private field | = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) @@ -16,7 +16,7 @@ error[E0616]: field `field` of struct `Restricted` is private --> $DIR/issue-50493.rs:6:10 | LL | #[derive(Derive)] - | ^^^^^^ + | ^^^^^^ private field | = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui-fulldeps/macro-crate-multi-decorator.rs b/src/test/ui/proc-macro/macro-crate-multi-decorator.rs similarity index 52% rename from src/test/ui-fulldeps/macro-crate-multi-decorator.rs rename to src/test/ui/proc-macro/macro-crate-multi-decorator.rs index f21617be5d26f..ec57dec14ed20 100644 --- a/src/test/ui-fulldeps/macro-crate-multi-decorator.rs +++ b/src/test/ui/proc-macro/macro-crate-multi-decorator.rs @@ -1,36 +1,33 @@ -// check-pass -// aux-build:macro-crate-test.rs -// ignore-stage1 +// The duplicate macro will create a copy of the item with the given identifier. -#![feature(rustc_attrs)] +// check-pass +// aux-build:duplicate.rs #[macro_use] -extern crate macro_crate_test; - -// The duplicate macro will create a copy of the item with the given identifier. +extern crate duplicate; -#[rustc_duplicate(MyCopy)] +#[duplicate(MyCopy)] struct MyStruct { - number: i32 + number: i32, } trait TestTrait { - #[rustc_duplicate(TestType2)] + #[duplicate(TestType2)] type TestType; - #[rustc_duplicate(required_fn2)] + #[duplicate(required_fn2)] fn required_fn(&self); - #[rustc_duplicate(provided_fn2)] - fn provided_fn(&self) { } + #[duplicate(provided_fn2)] + fn provided_fn(&self) {} } impl TestTrait for MyStruct { - #[rustc_duplicate(TestType2)] + #[duplicate(TestType2)] type TestType = f64; - #[rustc_duplicate(required_fn2)] - fn required_fn(&self) { } + #[duplicate(required_fn2)] + fn required_fn(&self) {} } fn main() { diff --git a/src/test/ui/proc-macro/non-root.stderr b/src/test/ui/proc-macro/non-root.stderr index 8f84ddeeddb20..90f94b677e90f 100644 --- a/src/test/ui/proc-macro/non-root.stderr +++ b/src/test/ui/proc-macro/non-root.stderr @@ -2,7 +2,7 @@ error: functions tagged with `#[proc_macro]` must currently reside in the root o --> $DIR/non-root.rs:11:5 | LL | pub fn foo(arg: TokenStream) -> TokenStream { arg } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/proc-macro/out-of-line-mod.rs b/src/test/ui/proc-macro/out-of-line-mod.rs new file mode 100644 index 0000000000000..658ed6c18e05a --- /dev/null +++ b/src/test/ui/proc-macro/out-of-line-mod.rs @@ -0,0 +1,13 @@ +// Out-of-line module is found on the filesystem if passed through a proc macro (issue #58818). + +// check-pass +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +mod outer { + identity! { mod inner; } +} + +fn main() {} diff --git a/src/test/ui/proc-macro/pub-at-crate-root.stderr b/src/test/ui/proc-macro/pub-at-crate-root.stderr index 3b69b7875bde0..2e7536a0c4f09 100644 --- a/src/test/ui/proc-macro/pub-at-crate-root.stderr +++ b/src/test/ui/proc-macro/pub-at-crate-root.stderr @@ -1,32 +1,20 @@ error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]` --> $DIR/pub-at-crate-root.rs:8:1 | -LL | / pub mod a { -LL | | use proc_macro::TokenStream; -LL | | -LL | | #[proc_macro_derive(B)] -... | -LL | | } -LL | | } - | |_^ +LL | pub mod a { + | ^^^^^^^^^ error: functions tagged with `#[proc_macro_derive]` must currently reside in the root of the crate --> $DIR/pub-at-crate-root.rs:12:5 | -LL | / pub fn bar(a: TokenStream) -> TokenStream { -LL | | -LL | | a -LL | | } - | |_____^ +LL | pub fn bar(a: TokenStream) -> TokenStream { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: functions tagged with `#[proc_macro_derive]` must be `pub` --> $DIR/pub-at-crate-root.rs:19:1 | -LL | / fn bar(a: proc_macro::TokenStream) -> proc_macro::TokenStream { -LL | | -LL | | a -LL | | } - | |_^ +LL | fn bar(a: proc_macro::TokenStream) -> proc_macro::TokenStream { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/proc-macro/resolve-error.stderr b/src/test/ui/proc-macro/resolve-error.stderr index 73a6ab1cfb910..15a1d6d9479fe 100644 --- a/src/test/ui/proc-macro/resolve-error.stderr +++ b/src/test/ui/proc-macro/resolve-error.stderr @@ -18,24 +18,20 @@ LL | Dlona!(); error: cannot find macro `attr_proc_macra` in this scope --> $DIR/resolve-error.rs:58:5 | -LL | / macro_rules! attr_proc_mac { -LL | | () => {} -LL | | } - | |_- similarly named macro `attr_proc_mac` defined here +LL | macro_rules! attr_proc_mac { + | -------------------------- similarly named macro `attr_proc_mac` defined here ... -LL | attr_proc_macra!(); - | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `attr_proc_mac` +LL | attr_proc_macra!(); + | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `attr_proc_mac` error: cannot find macro `FooWithLongNama` in this scope --> $DIR/resolve-error.rs:55:5 | -LL | / macro_rules! FooWithLongNam { -LL | | () => {} -LL | | } - | |_- similarly named macro `FooWithLongNam` defined here +LL | macro_rules! FooWithLongNam { + | --------------------------- similarly named macro `FooWithLongNam` defined here ... -LL | FooWithLongNama!(); - | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `FooWithLongNam` +LL | FooWithLongNama!(); + | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `FooWithLongNam` error: cannot find derive macro `attr_proc_macra` in this scope --> $DIR/resolve-error.rs:49:10 diff --git a/src/test/ui/proc-macro/visibility-path.rs b/src/test/ui/proc-macro/visibility-path.rs new file mode 100644 index 0000000000000..a73430db2c19a --- /dev/null +++ b/src/test/ui/proc-macro/visibility-path.rs @@ -0,0 +1,25 @@ +// Proc macro defined with `pub(path)` doesn't ICEs due to resolving the `path` (issue #68921). + +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub(self) fn outer(input: TokenStream) -> TokenStream { + //~^ ERROR functions tagged with `#[proc_macro]` must be `pub` + input +} + +mod m { + use proc_macro::*; + + #[proc_macro] + pub(super) fn inner(input: TokenStream) -> TokenStream { + //~^ ERROR functions tagged with `#[proc_macro]` must currently reside in the root + input + } +} diff --git a/src/test/ui/proc-macro/visibility-path.stderr b/src/test/ui/proc-macro/visibility-path.stderr new file mode 100644 index 0000000000000..1a73cc1963f9c --- /dev/null +++ b/src/test/ui/proc-macro/visibility-path.stderr @@ -0,0 +1,14 @@ +error: functions tagged with `#[proc_macro]` must be `pub` + --> $DIR/visibility-path.rs:12:1 + | +LL | pub(self) fn outer(input: TokenStream) -> TokenStream { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: functions tagged with `#[proc_macro]` must currently reside in the root of the crate + --> $DIR/visibility-path.rs:21:5 + | +LL | pub(super) fn inner(input: TokenStream) -> TokenStream { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/qualified/qualified-path-params.rs b/src/test/ui/qualified/qualified-path-params.rs index b1b60b4b73fb9..65549d909d047 100644 --- a/src/test/ui/qualified/qualified-path-params.rs +++ b/src/test/ui/qualified/qualified-path-params.rs @@ -18,7 +18,7 @@ impl S { fn main() { match 10 { ::A::f:: => {} - //~^ ERROR expected unit struct, unit variant or constant, found method `<::A>::f` + //~^ ERROR expected unit struct, unit variant or constant, found associated function 0 ..= ::A::f:: => {} //~ ERROR only char and numeric types are allowed in range } } diff --git a/src/test/ui/qualified/qualified-path-params.stderr b/src/test/ui/qualified/qualified-path-params.stderr index 7a74a37021bdb..7ff43f4404c54 100644 --- a/src/test/ui/qualified/qualified-path-params.stderr +++ b/src/test/ui/qualified/qualified-path-params.stderr @@ -1,4 +1,4 @@ -error[E0533]: expected unit struct, unit variant or constant, found method `<::A>::f` +error[E0533]: expected unit struct, unit variant or constant, found associated function `<::A>::f` --> $DIR/qualified-path-params.rs:20:9 | LL | ::A::f:: => {} diff --git a/src/test/ui/question-mark-type-infer.stderr b/src/test/ui/question-mark-type-infer.stderr index 7911701946cd3..262344fba5999 100644 --- a/src/test/ui/question-mark-type-infer.stderr +++ b/src/test/ui/question-mark-type-infer.stderr @@ -2,12 +2,13 @@ error[E0284]: type annotations needed --> $DIR/question-mark-type-infer.rs:12:21 | LL | l.iter().map(f).collect()? - | ^^^^^^^ - | | - | cannot infer type - | help: consider specifying the type argument in the method call: `collect::` + | ^^^^^^^ cannot infer type | = note: cannot resolve `<_ as std::ops::Try>::Ok == _` +help: consider specifying the type argument in the method call + | +LL | l.iter().map(f).collect::()? + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/range/issue-54505-no-std.rs b/src/test/ui/range/issue-54505-no-std.rs index 22cf15fb2e4a1..c6a3cc346fc80 100644 --- a/src/test/ui/range/issue-54505-no-std.rs +++ b/src/test/ui/range/issue-54505-no-std.rs @@ -15,10 +15,6 @@ use core::ops::RangeBounds; #[lang = "eh_personality"] extern fn eh_personality() {} -#[cfg(target_os = "windows")] -#[lang = "eh_unwind_resume"] -extern fn eh_unwind_resume() {} - // take a reference to any built-in range fn take_range(_r: &impl RangeBounds) {} diff --git a/src/test/ui/range/issue-54505-no-std.stderr b/src/test/ui/range/issue-54505-no-std.stderr index aead80fa500a9..909340611328a 100644 --- a/src/test/ui/range/issue-54505-no-std.stderr +++ b/src/test/ui/range/issue-54505-no-std.stderr @@ -1,7 +1,7 @@ error: `#[panic_handler]` function required, but not found error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:28:16 + --> $DIR/issue-54505-no-std.rs:24:16 | LL | take_range(0..1); | ^^^^ @@ -13,7 +13,7 @@ LL | take_range(0..1); found struct `core::ops::Range<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:33:16 + --> $DIR/issue-54505-no-std.rs:29:16 | LL | take_range(1..); | ^^^ @@ -25,7 +25,7 @@ LL | take_range(1..); found struct `core::ops::RangeFrom<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:38:16 + --> $DIR/issue-54505-no-std.rs:34:16 | LL | take_range(..); | ^^ @@ -37,7 +37,7 @@ LL | take_range(..); found struct `core::ops::RangeFull` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:43:16 + --> $DIR/issue-54505-no-std.rs:39:16 | LL | take_range(0..=1); | ^^^^^ @@ -49,7 +49,7 @@ LL | take_range(0..=1); found struct `core::ops::RangeInclusive<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:48:16 + --> $DIR/issue-54505-no-std.rs:44:16 | LL | take_range(..5); | ^^^ @@ -61,7 +61,7 @@ LL | take_range(..5); found struct `core::ops::RangeTo<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:53:16 + --> $DIR/issue-54505-no-std.rs:49:16 | LL | take_range(..=42); | ^^^^^ diff --git a/src/test/ui/reachable/unreachable-variant.stderr b/src/test/ui/reachable/unreachable-variant.stderr index c2e1d774e28ac..6c27a2756f7fb 100644 --- a/src/test/ui/reachable/unreachable-variant.stderr +++ b/src/test/ui/reachable/unreachable-variant.stderr @@ -2,7 +2,7 @@ error[E0603]: module `super_sekrit` is private --> $DIR/unreachable-variant.rs:6:21 | LL | let _x = other::super_sekrit::sooper_sekrit::baz; - | ^^^^^^^^^^^^ this module is private + | ^^^^^^^^^^^^ private module | note: the module `super_sekrit` is defined here --> $DIR/auxiliary/unreachable_variant.rs:1:1 diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs b/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs index 4489303638358..5be426eb38278 100644 --- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs +++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs @@ -1,3 +1,8 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl + struct R<'a> { r: &'a R<'a>, } diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr index aa23aed4b425a..f371d460cf733 100644 --- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr +++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr @@ -1,8 +1,13 @@ error[E0005]: refutable pattern in local binding: `Err(_)` not covered - --> $DIR/recursive-types-are-not-uninhabited.rs:6:9 + --> $DIR/recursive-types-are-not-uninhabited.rs:11:9 | LL | let Ok(x) = res; | ^^^^^ pattern `Err(_)` not covered + | + ::: $SRC_DIR/libcore/result.rs:LL:COL + | +LL | Err(#[stable(feature = "rust1", since = "1.0.0")] E), + | --- not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.migrate.stderr b/src/test/ui/regions/regions-free-region-ordering-caller.migrate.stderr index a33d3583552dc..06e1b0f1ac262 100644 --- a/src/test/ui/regions/regions-free-region-ordering-caller.migrate.stderr +++ b/src/test/ui/regions/regions-free-region-ordering-caller.migrate.stderr @@ -1,32 +1,54 @@ -error[E0623]: lifetime mismatch +error[E0491]: in type `&'b &'a usize`, reference has a longer lifetime than the data it references --> $DIR/regions-free-region-ordering-caller.rs:11:12 | -LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) { - | --------- --------- - | | - | these two types are declared with different lifetimes... LL | let z: Option<&'b &'a usize> = None; - | ^^^^^^^^^^^^^^^^^^^^^ ...but data from `a` flows into `b` here + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the pointer is valid for the lifetime `'b` as defined on the function body at 10:14 + --> $DIR/regions-free-region-ordering-caller.rs:10:14 + | +LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) { + | ^^ +note: but the referenced data is only valid for the lifetime `'a` as defined on the function body at 10:10 + --> $DIR/regions-free-region-ordering-caller.rs:10:10 + | +LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) { + | ^^ -error[E0623]: lifetime mismatch +error[E0491]: in type `&'b Paramd<'a>`, reference has a longer lifetime than the data it references --> $DIR/regions-free-region-ordering-caller.rs:17:12 | -LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) { - | --------- --------- - | | - | these two types are declared with different lifetimes... -LL | let y: Paramd<'a> = Paramd { x: a }; LL | let z: Option<&'b Paramd<'a>> = None; - | ^^^^^^^^^^^^^^^^^^^^^^ ...but data from `a` flows into `b` here + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: the pointer is valid for the lifetime `'b` as defined on the function body at 15:14 + --> $DIR/regions-free-region-ordering-caller.rs:15:14 + | +LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) { + | ^^ +note: but the referenced data is only valid for the lifetime `'a` as defined on the function body at 15:10 + --> $DIR/regions-free-region-ordering-caller.rs:15:10 + | +LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) { + | ^^ -error[E0623]: lifetime mismatch +error[E0491]: in type `&'a &'b usize`, reference has a longer lifetime than the data it references --> $DIR/regions-free-region-ordering-caller.rs:22:12 | -LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) { - | --------- --------- these two types are declared with different lifetimes... LL | let z: Option<&'a &'b usize> = None; - | ^^^^^^^^^^^^^^^^^^^^^ ...but data from `b` flows into `a` here + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the pointer is valid for the lifetime `'a` as defined on the function body at 21:10 + --> $DIR/regions-free-region-ordering-caller.rs:21:10 + | +LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) { + | ^^ +note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 21:14 + --> $DIR/regions-free-region-ordering-caller.rs:21:14 + | +LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) { + | ^^ error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0623`. +For more information about this error, try `rustc --explain E0491`. diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.rs b/src/test/ui/regions/regions-free-region-ordering-caller.rs index c0b12f23cdba7..2bf4734cf7380 100644 --- a/src/test/ui/regions/regions-free-region-ordering-caller.rs +++ b/src/test/ui/regions/regions-free-region-ordering-caller.rs @@ -8,18 +8,18 @@ struct Paramd<'a> { x: &'a usize } fn call2<'a, 'b>(a: &'a usize, b: &'b usize) { - let z: Option<&'b &'a usize> = None;//[migrate]~ ERROR E0623 + let z: Option<&'b &'a usize> = None;//[migrate]~ ERROR E0491 //[nll]~^ ERROR lifetime may not live long enough } fn call3<'a, 'b>(a: &'a usize, b: &'b usize) { let y: Paramd<'a> = Paramd { x: a }; - let z: Option<&'b Paramd<'a>> = None;//[migrate]~ ERROR E0623 + let z: Option<&'b Paramd<'a>> = None;//[migrate]~ ERROR E0491 //[nll]~^ ERROR lifetime may not live long enough } fn call4<'a, 'b>(a: &'a usize, b: &'b usize) { - let z: Option<&'a &'b usize> = None;//[migrate]~ ERROR E0623 + let z: Option<&'a &'b usize> = None;//[migrate]~ ERROR E0491 //[nll]~^ ERROR lifetime may not live long enough } diff --git a/src/test/ui/reify-intrinsic.stderr b/src/test/ui/reify-intrinsic.stderr index 4defe12b1b37b..c4eee0f466119 100644 --- a/src/test/ui/reify-intrinsic.stderr +++ b/src/test/ui/reify-intrinsic.stderr @@ -2,14 +2,16 @@ error[E0308]: cannot coerce intrinsics to function pointers --> $DIR/reify-intrinsic.rs:6:64 | LL | let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::transmute; - | ------------------------------------------------- ^^^^^^^^^^^^^^^^^^^ - | | | - | | cannot coerce intrinsics to function pointers - | | help: use parentheses to call this function: `std::mem::transmute(...)` + | ------------------------------------------------- ^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers + | | | expected due to this | = note: expected fn pointer `unsafe extern "rust-intrinsic" fn(isize) -> usize` found fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` +help: use parentheses to call this function + | +LL | let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::transmute(...); + | ^^^^^ error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid --> $DIR/reify-intrinsic.rs:11:13 diff --git a/src/test/ui/repeat_count.stderr b/src/test/ui/repeat_count.stderr index efad00b272cdc..4a2d1d9f921cb 100644 --- a/src/test/ui/repeat_count.stderr +++ b/src/test/ui/repeat_count.stderr @@ -28,6 +28,12 @@ error[E0308]: mismatched types LL | let e = [0; "foo"]; | ^^^^^ expected `usize`, found `&str` +error[E0308]: mismatched types + --> $DIR/repeat_count.rs:28:17 + | +LL | let g = [0; G { g: () }]; + | ^^^^^^^^^^^ expected `usize`, found struct `main::G` + error[E0308]: mismatched types --> $DIR/repeat_count.rs:19:17 | @@ -50,12 +56,6 @@ help: you can convert an `isize` to `usize` and panic if the converted value wou LL | let f = [0_usize; (-1_isize).try_into().unwrap()]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0308]: mismatched types - --> $DIR/repeat_count.rs:28:17 - | -LL | let g = [0; G { g: () }]; - | ^^^^^^^^^^^ expected `usize`, found struct `main::G` - error: aborting due to 8 previous errors Some errors have detailed explanations: E0308, E0435. diff --git a/src/test/ui/repr/repr-align-assign.stderr b/src/test/ui/repr/repr-align-assign.stderr index 192312d165bc8..b878ae0d17337 100644 --- a/src/test/ui/repr/repr-align-assign.stderr +++ b/src/test/ui/repr/repr-align-assign.stderr @@ -24,3 +24,4 @@ LL | #[repr(align="8")] error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0693`. diff --git a/src/test/ui/reserved/reserved-attr-on-macro.stderr b/src/test/ui/reserved/reserved-attr-on-macro.stderr index c387bba0a1310..e55b58bef2855 100644 --- a/src/test/ui/reserved/reserved-attr-on-macro.stderr +++ b/src/test/ui/reserved/reserved-attr-on-macro.stderr @@ -1,10 +1,8 @@ -error[E0658]: attributes starting with `rustc` are reserved for use by the `rustc` compiler +error: attributes starting with `rustc` are reserved for use by the `rustc` compiler --> $DIR/reserved-attr-on-macro.rs:1:3 | LL | #[rustc_attribute_should_be_reserved] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable error: cannot determine resolution for the macro `foo` --> $DIR/reserved-attr-on-macro.rs:10:5 @@ -22,4 +20,3 @@ LL | #[rustc_attribute_should_be_reserved] error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/resolve/issue-3907-2.stderr b/src/test/ui/resolve/issue-3907-2.stderr index d0c278d12d70a..bd6e9d5950272 100644 --- a/src/test/ui/resolve/issue-3907-2.stderr +++ b/src/test/ui/resolve/issue-3907-2.stderr @@ -3,8 +3,11 @@ error[E0038]: the trait `issue_3907::Foo` cannot be made into an object | LL | fn bar(_x: Foo) {} | ^^^ the trait `issue_3907::Foo` cannot be made into an object + | + ::: $DIR/auxiliary/issue-3907.rs:2:8 | - = note: the trait cannot be made into an object because associated function `bar` has no `self` parameter +LL | fn bar(); + | --- the trait cannot be made into an object because associated function `bar` has no `self` parameter error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-5035.stderr b/src/test/ui/resolve/issue-5035.stderr index 1674c166ddacb..622f0dfcda4cb 100644 --- a/src/test/ui/resolve/issue-5035.stderr +++ b/src/test/ui/resolve/issue-5035.stderr @@ -8,7 +8,7 @@ error[E0404]: expected trait, found type alias `K` --> $DIR/issue-5035.rs:3:6 | LL | trait I {} - | ---------- similarly named trait `I` defined here + | ------- similarly named trait `I` defined here LL | type K = dyn I; LL | impl K for isize {} | ^ diff --git a/src/test/ui/resolve/issue-65035-static-with-parent-generics.rs b/src/test/ui/resolve/issue-65035-static-with-parent-generics.rs index 63d3431ec9b2f..708d72a2df756 100644 --- a/src/test/ui/resolve/issue-65035-static-with-parent-generics.rs +++ b/src/test/ui/resolve/issue-65035-static-with-parent-generics.rs @@ -24,6 +24,7 @@ fn i() { static a: [u8; N] = [0; N]; //~^ ERROR can't use generic parameters from outer function //~^^ ERROR can't use generic parameters from outer function + //~| ERROR mismatched types } fn main() {} diff --git a/src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr b/src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr index 82e2aa2db8e25..97c60c7229837 100644 --- a/src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr +++ b/src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr @@ -48,6 +48,16 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default -error: aborting due to 5 previous errors +error[E0308]: mismatched types + --> $DIR/issue-65035-static-with-parent-generics.rs:24:25 + | +LL | static a: [u8; N] = [0; N]; + | ^^^^^^ expected `N`, found `N` + | + = note: expected array `[u8; _]` + found array `[u8; _]` + +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0401`. +Some errors have detailed explanations: E0308, E0401. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/resolve/levenshtein.stderr b/src/test/ui/resolve/levenshtein.stderr index a622d6cb34948..ecdec3c24a1d8 100644 --- a/src/test/ui/resolve/levenshtein.stderr +++ b/src/test/ui/resolve/levenshtein.stderr @@ -8,7 +8,7 @@ error[E0412]: cannot find type `Baz` in this scope --> $DIR/levenshtein.rs:14:10 | LL | enum Bar { } - | ------------ similarly named enum `Bar` defined here + | -------- similarly named enum `Bar` defined here LL | LL | type A = Baz; // Misspelled type name. | ^^^ help: an enum with a similar name exists: `Bar` @@ -43,7 +43,7 @@ error[E0425]: cannot find function `foobar` in this scope --> $DIR/levenshtein.rs:30:5 | LL | fn foo_bar() {} - | --------------- similarly named function `foo_bar` defined here + | ------------ similarly named function `foo_bar` defined here ... LL | foobar(); // Misspelled function name. | ^^^^^^ help: a function with a similar name exists: `foo_bar` diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr index 08a1d790197a6..30ac783ea2f7e 100644 --- a/src/test/ui/resolve/privacy-enum-ctor.stderr +++ b/src/test/ui/resolve/privacy-enum-ctor.stderr @@ -16,15 +16,11 @@ LL | m::Z::Unit; error[E0423]: expected value, found enum `Z` --> $DIR/privacy-enum-ctor.rs:25:9 | -LL | / fn f() { -LL | | n::Z; -LL | | -LL | | Z; - | | ^ -... | -LL | | // This is ok, it is equivalent to not having braces -LL | | } - | |_____- similarly named function `f` defined here +LL | fn f() { + | ------ similarly named function `f` defined here +... +LL | Z; + | ^ | help: a function with a similar name exists | @@ -53,17 +49,11 @@ LL | let _: Z = Z::Struct; error[E0423]: expected value, found enum `m::E` --> $DIR/privacy-enum-ctor.rs:41:16 | -LL | / fn f() { -LL | | n::Z; -LL | | -LL | | Z; -... | -LL | | // This is ok, it is equivalent to not having braces -LL | | } - | |_____- similarly named function `f` defined here +LL | fn f() { + | ------ similarly named function `f` defined here ... -LL | let _: E = m::E; - | ^^^^ +LL | let _: E = m::E; + | ^^^^ | help: a function with a similar name exists | @@ -130,17 +120,11 @@ LL | let _: E = E::Struct; error[E0412]: cannot find type `Z` in this scope --> $DIR/privacy-enum-ctor.rs:57:12 | -LL | / pub enum E { -LL | | Fn(u8), -LL | | Struct { -LL | | s: u8, -LL | | }, -LL | | Unit, -LL | | } - | |_____- similarly named enum `E` defined here +LL | pub enum E { + | ---------- similarly named enum `E` defined here ... -LL | let _: Z = m::n::Z; - | ^ +LL | let _: Z = m::n::Z; + | ^ | help: an enum with a similar name exists | @@ -169,17 +153,11 @@ LL | let _: Z = m::Z::Unit; error[E0412]: cannot find type `Z` in this scope --> $DIR/privacy-enum-ctor.rs:61:12 | -LL | / pub enum E { -LL | | Fn(u8), -LL | | Struct { -LL | | s: u8, -LL | | }, -LL | | Unit, -LL | | } - | |_____- similarly named enum `E` defined here +LL | pub enum E { + | ---------- similarly named enum `E` defined here ... -LL | let _: Z = m::n::Z::Fn; - | ^ +LL | let _: Z = m::n::Z::Fn; + | ^ | help: an enum with a similar name exists | @@ -193,17 +171,11 @@ LL | use m::n::Z; error[E0412]: cannot find type `Z` in this scope --> $DIR/privacy-enum-ctor.rs:64:12 | -LL | / pub enum E { -LL | | Fn(u8), -LL | | Struct { -LL | | s: u8, -LL | | }, -LL | | Unit, -LL | | } - | |_____- similarly named enum `E` defined here +LL | pub enum E { + | ---------- similarly named enum `E` defined here ... -LL | let _: Z = m::n::Z::Struct; - | ^ +LL | let _: Z = m::n::Z::Struct; + | ^ | help: an enum with a similar name exists | @@ -228,17 +200,11 @@ LL | let _: Z = m::n::Z::Struct; error[E0412]: cannot find type `Z` in this scope --> $DIR/privacy-enum-ctor.rs:68:12 | -LL | / pub enum E { -LL | | Fn(u8), -LL | | Struct { -LL | | s: u8, -LL | | }, -LL | | Unit, -LL | | } - | |_____- similarly named enum `E` defined here +LL | pub enum E { + | ---------- similarly named enum `E` defined here ... -LL | let _: Z = m::n::Z::Unit {}; - | ^ +LL | let _: Z = m::n::Z::Unit {}; + | ^ | help: an enum with a similar name exists | @@ -253,7 +219,7 @@ error[E0603]: enum `Z` is private --> $DIR/privacy-enum-ctor.rs:57:22 | LL | let _: Z = m::n::Z; - | ^ this enum is private + | ^ private enum | note: the enum `Z` is defined here --> $DIR/privacy-enum-ctor.rs:11:9 @@ -265,7 +231,7 @@ error[E0603]: enum `Z` is private --> $DIR/privacy-enum-ctor.rs:61:22 | LL | let _: Z = m::n::Z::Fn; - | ^ this enum is private + | ^ private enum | note: the enum `Z` is defined here --> $DIR/privacy-enum-ctor.rs:11:9 @@ -277,7 +243,7 @@ error[E0603]: enum `Z` is private --> $DIR/privacy-enum-ctor.rs:64:22 | LL | let _: Z = m::n::Z::Struct; - | ^ this enum is private + | ^ private enum | note: the enum `Z` is defined here --> $DIR/privacy-enum-ctor.rs:11:9 @@ -289,7 +255,7 @@ error[E0603]: enum `Z` is private --> $DIR/privacy-enum-ctor.rs:68:22 | LL | let _: Z = m::n::Z::Unit {}; - | ^ this enum is private + | ^ private enum | note: the enum `Z` is defined here --> $DIR/privacy-enum-ctor.rs:11:9 @@ -304,14 +270,16 @@ LL | Fn(u8), | ------ fn(u8) -> m::n::Z {m::n::Z::Fn} defined here ... LL | let _: Z = Z::Fn; - | - ^^^^^ - | | | - | | expected enum `m::n::Z`, found fn item - | | help: use parentheses to instantiate this tuple variant: `Z::Fn(_)` + | - ^^^^^ expected enum `m::n::Z`, found fn item + | | | expected due to this | = note: expected enum `m::n::Z` found fn item `fn(u8) -> m::n::Z {m::n::Z::Fn}` +help: use parentheses to instantiate this tuple variant + | +LL | let _: Z = Z::Fn(_); + | ^^^ error[E0618]: expected function, found enum variant `Z::Unit` --> $DIR/privacy-enum-ctor.rs:31:17 @@ -336,14 +304,16 @@ LL | Fn(u8), | ------ fn(u8) -> m::E {m::E::Fn} defined here ... LL | let _: E = m::E::Fn; - | - ^^^^^^^^ - | | | - | | expected enum `m::E`, found fn item - | | help: use parentheses to instantiate this tuple variant: `m::E::Fn(_)` + | - ^^^^^^^^ expected enum `m::E`, found fn item + | | | expected due to this | = note: expected enum `m::E` found fn item `fn(u8) -> m::E {m::E::Fn}` +help: use parentheses to instantiate this tuple variant + | +LL | let _: E = m::E::Fn(_); + | ^^^ error[E0618]: expected function, found enum variant `m::E::Unit` --> $DIR/privacy-enum-ctor.rs:47:16 @@ -368,14 +338,16 @@ LL | Fn(u8), | ------ fn(u8) -> m::E {m::E::Fn} defined here ... LL | let _: E = E::Fn; - | - ^^^^^ - | | | - | | expected enum `m::E`, found fn item - | | help: use parentheses to instantiate this tuple variant: `E::Fn(_)` + | - ^^^^^ expected enum `m::E`, found fn item + | | | expected due to this | = note: expected enum `m::E` found fn item `fn(u8) -> m::E {m::E::Fn}` +help: use parentheses to instantiate this tuple variant + | +LL | let _: E = E::Fn(_); + | ^^^ error[E0618]: expected function, found enum variant `E::Unit` --> $DIR/privacy-enum-ctor.rs:55:16 diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr index 1673ec46ba488..baf7dd84eb09d 100644 --- a/src/test/ui/resolve/privacy-struct-ctor.stderr +++ b/src/test/ui/resolve/privacy-struct-ctor.stderr @@ -45,7 +45,7 @@ LL | pub(in m) struct Z(pub(in m::n) u8); | --------------- a constructor is private if any of the fields is private ... LL | n::Z; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `Z` is defined here --> $DIR/privacy-struct-ctor.rs:12:9 @@ -60,7 +60,7 @@ LL | pub struct S(u8); | -- a constructor is private if any of the fields is private ... LL | m::S; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `S` is defined here --> $DIR/privacy-struct-ctor.rs:6:5 @@ -75,7 +75,7 @@ LL | pub struct S(u8); | -- a constructor is private if any of the fields is private ... LL | let _: S = m::S(2); - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `S` is defined here --> $DIR/privacy-struct-ctor.rs:6:5 @@ -90,7 +90,7 @@ LL | pub(in m) struct Z(pub(in m::n) u8); | --------------- a constructor is private if any of the fields is private ... LL | m::n::Z; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | note: the tuple struct constructor `Z` is defined here --> $DIR/privacy-struct-ctor.rs:12:9 @@ -102,7 +102,7 @@ error[E0603]: tuple struct constructor `S` is private --> $DIR/privacy-struct-ctor.rs:41:16 | LL | xcrate::m::S; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy-struct-ctor.rs:2:18 | @@ -119,7 +119,7 @@ error[E0603]: tuple struct constructor `Z` is private --> $DIR/privacy-struct-ctor.rs:45:19 | LL | xcrate::m::n::Z; - | ^ this tuple struct constructor is private + | ^ private tuple struct constructor | ::: $DIR/auxiliary/privacy-struct-ctor.rs:5:28 | diff --git a/src/test/ui/resolve/raw-ident-in-path.rs b/src/test/ui/resolve/raw-ident-in-path.rs new file mode 100644 index 0000000000000..1bcbef5943741 --- /dev/null +++ b/src/test/ui/resolve/raw-ident-in-path.rs @@ -0,0 +1,5 @@ +// Regression test for issue #63882. + +type A = crate::r#break; //~ ERROR cannot find type `r#break` in module `crate` + +fn main() {} diff --git a/src/test/ui/resolve/raw-ident-in-path.stderr b/src/test/ui/resolve/raw-ident-in-path.stderr new file mode 100644 index 0000000000000..f2efcbc8e8586 --- /dev/null +++ b/src/test/ui/resolve/raw-ident-in-path.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `r#break` in module `crate` + --> $DIR/raw-ident-in-path.rs:3:17 + | +LL | type A = crate::r#break; + | ^^^^^^^ not found in `crate` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/resolve/resolve-hint-macro.stderr b/src/test/ui/resolve/resolve-hint-macro.stderr index ebe3c36f21eb1..361da4cc78e00 100644 --- a/src/test/ui/resolve/resolve-hint-macro.stderr +++ b/src/test/ui/resolve/resolve-hint-macro.stderr @@ -2,7 +2,12 @@ error[E0423]: expected function, found macro `assert` --> $DIR/resolve-hint-macro.rs:2:5 | LL | assert(true); - | ^^^^^^ help: use `!` to invoke the macro: `assert!` + | ^^^^^^ + | +help: use `!` to invoke the macro + | +LL | assert!(true); + | ^ error: aborting due to previous error diff --git a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr index f992988c93fcc..3bc38830537cf 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr @@ -14,7 +14,7 @@ error[E0603]: tuple struct constructor `TupleStruct` is private --> $DIR/struct.rs:23:32 | LL | let ts_explicit = structs::TupleStruct(640, 480); - | ^^^^^^^^^^^ this tuple struct constructor is private + | ^^^^^^^^^^^ private tuple struct constructor | ::: $DIR/auxiliary/structs.rs:11:24 | @@ -31,7 +31,7 @@ error[E0603]: unit struct `UnitStruct` is private --> $DIR/struct.rs:32:32 | LL | let us_explicit = structs::UnitStruct; - | ^^^^^^^^^^ this unit struct is private + | ^^^^^^^^^^ private unit struct | note: the unit struct `UnitStruct` is defined here --> $DIR/auxiliary/structs.rs:8:1 @@ -62,18 +62,33 @@ error[E0638]: `..` required with struct marked as non-exhaustive | LL | let NormalStruct { first_field, second_field } = ns; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add `..` at the end of the field list to ignore all other fields + | +LL | let NormalStruct { first_field, second_field , .. } = ns; + | ^^^^^^ error[E0638]: `..` required with struct marked as non-exhaustive --> $DIR/struct.rs:26:9 | LL | let TupleStruct { 0: first_field, 1: second_field } = ts; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add `..` at the end of the field list to ignore all other fields + | +LL | let TupleStruct { 0: first_field, 1: second_field , .. } = ts; + | ^^^^^^ error[E0638]: `..` required with struct marked as non-exhaustive --> $DIR/struct.rs:35:9 | LL | let UnitStruct { } = us; | ^^^^^^^^^^^^^^ + | +help: add `..` at the end of the field list to ignore all other fields + | +LL | let UnitStruct { .. } = us; + | ^^^^ error: aborting due to 9 previous errors diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr index ccc25a184e946..a214a652a387f 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr @@ -27,6 +27,13 @@ error[E0004]: non-exhaustive patterns: `Tuple(_)` and `Struct { .. }` not covere | LL | match x {} | ^ patterns `Tuple(_)` and `Struct { .. }` not covered + | + ::: $DIR/auxiliary/uninhabited.rs:17:23 + | +LL | #[non_exhaustive] Tuple(!), + | ----- not covered +LL | #[non_exhaustive] Struct { x: ! } + | ------ not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr index a54885c96e5ee..63564e9c3cc8c 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr @@ -27,6 +27,13 @@ error[E0004]: non-exhaustive patterns: `Tuple(_)` and `Struct { .. }` not covere | LL | match x {} | ^ patterns `Tuple(_)` and `Struct { .. }` not covered + | + ::: $DIR/auxiliary/uninhabited.rs:17:23 + | +LL | #[non_exhaustive] Tuple(!), + | ----- not covered +LL | #[non_exhaustive] Struct { x: ! } + | ------ not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms diff --git a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr index 2a438753a2c70..fbdbb0c9930a6 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr @@ -2,7 +2,7 @@ error[E0603]: tuple variant `Tuple` is private --> $DIR/variant.rs:11:48 | LL | let variant_tuple = NonExhaustiveVariants::Tuple(640); - | ^^^^^ this tuple variant is private + | ^^^^^ private tuple variant | note: the tuple variant `Tuple` is defined here --> $DIR/auxiliary/variants.rs:5:23 @@ -14,7 +14,7 @@ error[E0603]: unit variant `Unit` is private --> $DIR/variant.rs:14:47 | LL | let variant_unit = NonExhaustiveVariants::Unit; - | ^^^^ this unit variant is private + | ^^^^ private unit variant | note: the unit variant `Unit` is defined here --> $DIR/auxiliary/variants.rs:4:23 @@ -26,7 +26,7 @@ error[E0603]: unit variant `Unit` is private --> $DIR/variant.rs:18:32 | LL | NonExhaustiveVariants::Unit => "", - | ^^^^ this unit variant is private + | ^^^^ private unit variant | note: the unit variant `Unit` is defined here --> $DIR/auxiliary/variants.rs:4:23 @@ -38,7 +38,7 @@ error[E0603]: tuple variant `Tuple` is private --> $DIR/variant.rs:20:32 | LL | NonExhaustiveVariants::Tuple(fe_tpl) => "", - | ^^^^^ this tuple variant is private + | ^^^^^ private tuple variant | note: the tuple variant `Tuple` is defined here --> $DIR/auxiliary/variants.rs:5:23 @@ -50,7 +50,7 @@ error[E0603]: tuple variant `Tuple` is private --> $DIR/variant.rs:26:35 | LL | if let NonExhaustiveVariants::Tuple(fe_tpl) = variant_struct { - | ^^^^^ this tuple variant is private + | ^^^^^ private tuple variant | note: the tuple variant `Tuple` is defined here --> $DIR/auxiliary/variants.rs:5:23 @@ -69,12 +69,22 @@ error[E0638]: `..` required with variant marked as non-exhaustive | LL | NonExhaustiveVariants::Struct { field } => "" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add `..` at the end of the field list to ignore all other fields + | +LL | NonExhaustiveVariants::Struct { field , .. } => "" + | ^^^^^^ error[E0638]: `..` required with variant marked as non-exhaustive --> $DIR/variant.rs:30:12 | LL | if let NonExhaustiveVariants::Struct { field } = variant_struct { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add `..` at the end of the field list to ignore all other fields + | +LL | if let NonExhaustiveVariants::Struct { field , .. } = variant_struct { + | ^^^^^^ error: aborting due to 8 previous errors diff --git a/src/test/ui/rfc-2091-track-caller/error-extern-fn.rs b/src/test/ui/rfc-2091-track-caller/error-extern-fn.rs new file mode 100644 index 0000000000000..9f6a69a51c0ce --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/error-extern-fn.rs @@ -0,0 +1,9 @@ +#![feature(track_caller)] +#![allow(dead_code)] + +extern "Rust" { + #[track_caller] //~ ERROR: `#[track_caller]` is not supported on foreign functions + fn bar(); +} + +fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.stderr b/src/test/ui/rfc-2091-track-caller/error-extern-fn.stderr similarity index 60% rename from src/test/ui/rfc-2091-track-caller/error-with-trait-decl.stderr rename to src/test/ui/rfc-2091-track-caller/error-extern-fn.stderr index ded721d278253..b03f5fbbdb20e 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-extern-fn.stderr @@ -1,5 +1,5 @@ -error[E0738]: `#[track_caller]` may not be used on trait methods - --> $DIR/error-with-trait-decl.rs:4:5 +error[E0738]: `#[track_caller]` is not supported on foreign functions + --> $DIR/error-extern-fn.rs:5:5 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs b/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs deleted file mode 100644 index ef037ab62aa3e..0000000000000 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![feature(track_caller)] - -trait Trait { - #[track_caller] //~ ERROR: `#[track_caller]` may not be used on trait methods - fn unwrap(&self); -} - -impl Trait for u64 { - fn unwrap(&self) {} -} - -fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.rs b/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.rs deleted file mode 100644 index 17e4bf41ddb53..0000000000000 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![feature(track_caller)] - -trait Trait { - #[track_caller] //~ ERROR: `#[track_caller]` may not be used on trait methods - fn unwrap(&self) {} -} - -fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr b/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr deleted file mode 100644 index 867eb918b6e08..0000000000000 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0738]: `#[track_caller]` may not be used on trait methods - --> $DIR/error-with-trait-default-impl.rs:4:5 - | -LL | #[track_caller] - | ^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0738`. diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.rs b/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.rs deleted file mode 100644 index 75f20f76e660d..0000000000000 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.rs +++ /dev/null @@ -1,21 +0,0 @@ -// check-fail - -#![feature(track_caller)] - -trait Trait { - fn unwrap(&self); -} - -impl Trait for u64 { - #[track_caller] //~ ERROR: `#[track_caller]` may not be used on trait methods - fn unwrap(&self) {} -} - -struct S; - -impl S { - #[track_caller] // ok - fn foo() {} -} - -fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr b/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr deleted file mode 100644 index fafceefbfd839..0000000000000 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0738]: `#[track_caller]` may not be used on trait methods - --> $DIR/error-with-trait-fn-impl.rs:10:5 - | -LL | #[track_caller] - | ^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0738`. diff --git a/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs b/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs index be13076b8af52..35a2956ee26b8 100644 --- a/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs +++ b/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs @@ -2,10 +2,14 @@ // ignore-wasm32-bare compiled with panic=abort by default #![feature(option_expect_none, option_unwrap_none)] +#![allow(unconditional_panic)] //! Test that panic locations for `#[track_caller]` functions in std have the correct //! location reported. +use std::collections::{BTreeMap, HashMap, VecDeque}; +use std::ops::{Index, IndexMut}; + fn main() { // inspect the `PanicInfo` we receive to ensure the right file is the source std::panic::set_hook(Box::new(|info| { @@ -35,4 +39,22 @@ fn main() { let fine: Result<(), ()> = Ok(()); assert_panicked(|| fine.unwrap_err()); assert_panicked(|| fine.expect_err("")); + + let mut small = [0]; // the implementation backing str, vec, etc + assert_panicked(move || { small.index(1); }); + assert_panicked(move || { small[1]; }); + assert_panicked(move || { small.index_mut(1); }); + assert_panicked(move || { small[1] += 1; }); + + let sorted: BTreeMap = Default::default(); + assert_panicked(|| { sorted.index(&false); }); + assert_panicked(|| { sorted[&false]; }); + + let unsorted: HashMap = Default::default(); + assert_panicked(|| { unsorted.index(&false); }); + assert_panicked(|| { unsorted[&false]; }); + + let weirdo: VecDeque<()> = Default::default(); + assert_panicked(|| { weirdo.index(1); }); + assert_panicked(|| { weirdo[1]; }); } 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 index 0407eafbfd41c..b17c1efb3d38c 100644 --- 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 @@ -14,6 +14,49 @@ fn tracked_unit(_: ()) { assert_eq!(location.line(), expected_line, "call shims report location as fn definition"); } +trait Trait { + fn trait_tracked_unit(_: ()); +} + +impl Trait for () { + #[track_caller] + fn trait_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"); + } +} + +trait TrackedTrait { + #[track_caller] + fn trait_tracked_unit_default(_: ()) { + 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"); + } +} + +impl TrackedTrait for () {} + +trait BlanketTrackedTrait { + #[track_caller] + fn tracked_blanket(_: ()); +} + +impl BlanketTrackedTrait for () { + fn tracked_blanket(_: ()) { + 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, ()); + pass_to_ptr_call(<() as Trait>::trait_tracked_unit, ()); + pass_to_ptr_call(<() as TrackedTrait>::trait_tracked_unit_default, ()); + pass_to_ptr_call(<() as BlanketTrackedTrait>::tracked_blanket, ()); } 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 index a4baaa26ced1e..8ee4d4fa16871 100644 --- a/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs +++ b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs @@ -14,6 +14,49 @@ fn tracked() { assert_eq!(location.line(), expected_line, "call shims report location as fn definition"); } +trait Trait { + fn trait_tracked(); +} + +impl Trait for () { + #[track_caller] + fn trait_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"); + } +} + +trait TrackedTrait { + #[track_caller] + fn trait_tracked_default() { + 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"); + } +} + +impl TrackedTrait for () {} + +trait TraitBlanketTracked { + #[track_caller] + fn tracked_blanket(); +} + +impl TraitBlanketTracked for () { + fn tracked_blanket() { + 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); + ptr_call(<() as Trait>::trait_tracked); + ptr_call(<() as TrackedTrait>::trait_tracked_default); + ptr_call(<() as TraitBlanketTracked>::tracked_blanket); } diff --git a/src/test/ui/rfc-2091-track-caller/tracked-trait-impls.rs b/src/test/ui/rfc-2091-track-caller/tracked-trait-impls.rs new file mode 100644 index 0000000000000..0a5f92bb635e5 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/tracked-trait-impls.rs @@ -0,0 +1,79 @@ +// run-pass + +#![feature(track_caller)] + +macro_rules! assert_expansion_site_is_tracked { + () => {{ + let location = std::panic::Location::caller(); + assert_eq!(location.file(), file!()); + assert_ne!(location.line(), line!(), "line should be outside this fn"); + }} +} + +trait Tracked { + fn local_tracked(&self); + + #[track_caller] + fn blanket_tracked(&self); + + #[track_caller] + fn default_tracked(&self) { + assert_expansion_site_is_tracked!(); + } +} + +impl Tracked for () { + #[track_caller] + fn local_tracked(&self) { + assert_expansion_site_is_tracked!(); + } + + fn blanket_tracked(&self) { + assert_expansion_site_is_tracked!(); + } +} + +impl Tracked for bool { + #[track_caller] + fn local_tracked(&self) { + assert_expansion_site_is_tracked!(); + } + + fn blanket_tracked(&self) { + assert_expansion_site_is_tracked!(); + } + + fn default_tracked(&self) { + assert_expansion_site_is_tracked!(); + } +} + +impl Tracked for u8 { + #[track_caller] + fn local_tracked(&self) { + assert_expansion_site_is_tracked!(); + } + + fn blanket_tracked(&self) { + assert_expansion_site_is_tracked!(); + } + + #[track_caller] + fn default_tracked(&self) { + assert_expansion_site_is_tracked!(); + } +} + +fn main() { + ().local_tracked(); + ().default_tracked(); + ().blanket_tracked(); + + true.local_tracked(); + true.default_tracked(); + true.blanket_tracked(); + + 0u8.local_tracked(); + 0u8.default_tracked(); + 0u8.blanket_tracked(); +} diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr b/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr index 82099066a89d2..1ced8d8a14a53 100644 --- a/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr @@ -2,7 +2,7 @@ error: unused variable: `a` --> $DIR/param-attrs-cfg.rs:24:23 | LL | #[cfg(something)] a: i32, - | ^ help: consider prefixing with an underscore: `_a` + | ^ help: if this is intentional, prefix it with an underscore: `_a` | note: the lint level is defined here --> $DIR/param-attrs-cfg.rs:5:9 @@ -14,109 +14,109 @@ error: unused variable: `b` --> $DIR/param-attrs-cfg.rs:30:23 | LL | #[cfg(something)] b: i32, - | ^ help: consider prefixing with an underscore: `_b` + | ^ help: if this is intentional, prefix it with an underscore: `_b` error: unused variable: `c` --> $DIR/param-attrs-cfg.rs:32:40 | LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, - | ^ help: consider prefixing with an underscore: `_c` + | ^ help: if this is intentional, prefix it with an underscore: `_c` error: unused variable: `a` --> $DIR/param-attrs-cfg.rs:107:27 | LL | #[cfg(something)] a: i32, - | ^ help: consider prefixing with an underscore: `_a` + | ^ help: if this is intentional, prefix it with an underscore: `_a` error: unused variable: `b` --> $DIR/param-attrs-cfg.rs:113:27 | LL | #[cfg(something)] b: i32, - | ^ help: consider prefixing with an underscore: `_b` + | ^ help: if this is intentional, prefix it with an underscore: `_b` error: unused variable: `c` --> $DIR/param-attrs-cfg.rs:115:44 | LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, - | ^ help: consider prefixing with an underscore: `_c` + | ^ help: if this is intentional, prefix it with an underscore: `_c` error: unused variable: `b` --> $DIR/param-attrs-cfg.rs:67:27 | LL | #[cfg(something)] b: i32, - | ^ help: consider prefixing with an underscore: `_b` + | ^ help: if this is intentional, prefix it with an underscore: `_b` error: unused variable: `c` --> $DIR/param-attrs-cfg.rs:69:44 | LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, - | ^ help: consider prefixing with an underscore: `_c` + | ^ help: if this is intentional, prefix it with an underscore: `_c` error: unused variable: `b` --> $DIR/param-attrs-cfg.rs:75:27 | LL | #[cfg(something)] b: i32, - | ^ help: consider prefixing with an underscore: `_b` + | ^ help: if this is intentional, prefix it with an underscore: `_b` error: unused variable: `c` --> $DIR/param-attrs-cfg.rs:77:44 | LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, - | ^ help: consider prefixing with an underscore: `_c` + | ^ help: if this is intentional, prefix it with an underscore: `_c` error: unused variable: `a` --> $DIR/param-attrs-cfg.rs:41:27 | LL | #[cfg(something)] a: i32, - | ^ help: consider prefixing with an underscore: `_a` + | ^ help: if this is intentional, prefix it with an underscore: `_a` error: unused variable: `b` --> $DIR/param-attrs-cfg.rs:48:27 | LL | #[cfg(something)] b: i32, - | ^ help: consider prefixing with an underscore: `_b` + | ^ help: if this is intentional, prefix it with an underscore: `_b` error: unused variable: `c` --> $DIR/param-attrs-cfg.rs:50:44 | LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, - | ^ help: consider prefixing with an underscore: `_c` + | ^ help: if this is intentional, prefix it with an underscore: `_c` error: unused variable: `b` --> $DIR/param-attrs-cfg.rs:56:27 | LL | #[cfg(something)] b: i32, - | ^ help: consider prefixing with an underscore: `_b` + | ^ help: if this is intentional, prefix it with an underscore: `_b` error: unused variable: `c` --> $DIR/param-attrs-cfg.rs:58:44 | LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, - | ^ help: consider prefixing with an underscore: `_c` + | ^ help: if this is intentional, prefix it with an underscore: `_c` error: unused variable: `b` --> $DIR/param-attrs-cfg.rs:86:27 | LL | #[cfg(something)] b: i32, - | ^ help: consider prefixing with an underscore: `_b` + | ^ help: if this is intentional, prefix it with an underscore: `_b` error: unused variable: `c` --> $DIR/param-attrs-cfg.rs:88:44 | LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, - | ^ help: consider prefixing with an underscore: `_c` + | ^ help: if this is intentional, prefix it with an underscore: `_c` error: unused variable: `b` --> $DIR/param-attrs-cfg.rs:94:27 | LL | #[cfg(something)] b: i32, - | ^ help: consider prefixing with an underscore: `_b` + | ^ help: if this is intentional, prefix it with an underscore: `_b` error: unused variable: `c` --> $DIR/param-attrs-cfg.rs:96:44 | LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, - | ^ help: consider prefixing with an underscore: `_c` + | ^ help: if this is intentional, prefix it with an underscore: `_c` error: aborting due to 19 previous errors diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr index 6afcf24cd3e1e..57374b7e3bb27 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr @@ -2,7 +2,7 @@ error: lifetime may not live long enough --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:8:52 | LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } - | - - ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | - - ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` | | | | | let's call the lifetime of this reference `'1` | let's call the lifetime of this reference `'2` @@ -11,7 +11,7 @@ error: lifetime may not live long enough --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:75 | LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } - | - - ^^^^^^^^^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | - - ^^^^^^^^^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` | | | | | let's call the lifetime of this reference `'1` | let's call the lifetime of this reference `'2` @@ -20,7 +20,7 @@ error: lifetime may not live long enough --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:64 | LL | async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } - | -- - ^^^ method was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a` + | -- - ^^^ associated function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a` | | | | | let's call the lifetime of this reference `'1` | lifetime `'a` defined here diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr index a659e4487856c..17099201d1110 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr @@ -2,7 +2,7 @@ error: lifetime may not live long enough --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:6:46 | LL | fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } - | - - ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | - - ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` | | | | | let's call the lifetime of this reference `'1` | let's call the lifetime of this reference `'2` @@ -11,7 +11,7 @@ error: lifetime may not live long enough --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:8:69 | LL | fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } - | - - ^^^^^^^^^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | - - ^^^^^^^^^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` | | | | | let's call the lifetime of this reference `'1` | let's call the lifetime of this reference `'2` @@ -20,7 +20,7 @@ error: lifetime may not live long enough --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:13:58 | LL | fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } - | -- ---- has type `std::pin::Pin<&'1 Foo>` ^^^ method was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a` + | -- ---- has type `std::pin::Pin<&'1 Foo>` ^^^ associated function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a` | | | lifetime `'a` defined here diff --git a/src/test/ui/self/elision/lt-ref-self-async.nll.stderr b/src/test/ui/self/elision/lt-ref-self-async.nll.stderr index 57d0929c50a79..c10b8824e6d63 100644 --- a/src/test/ui/self/elision/lt-ref-self-async.nll.stderr +++ b/src/test/ui/self/elision/lt-ref-self-async.nll.stderr @@ -6,7 +6,7 @@ LL | async fn ref_self(&self, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/lt-ref-self-async.rs:19:9 @@ -16,7 +16,7 @@ LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/lt-ref-self-async.rs:23:9 @@ -26,7 +26,7 @@ LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/lt-ref-self-async.rs:27:9 @@ -36,7 +36,7 @@ LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/lt-ref-self-async.rs:31:9 @@ -46,7 +46,7 @@ LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/lt-ref-self-async.rs:35:9 @@ -56,7 +56,7 @@ LL | async fn box_pin_Self(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: aborting due to 6 previous errors diff --git a/src/test/ui/self/elision/lt-ref-self.nll.stderr b/src/test/ui/self/elision/lt-ref-self.nll.stderr index b51b5a0ba38f2..e2de743b8f63e 100644 --- a/src/test/ui/self/elision/lt-ref-self.nll.stderr +++ b/src/test/ui/self/elision/lt-ref-self.nll.stderr @@ -6,7 +6,7 @@ LL | fn ref_self(&self, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/lt-ref-self.rs:17:9 @@ -16,7 +16,7 @@ LL | fn ref_Self(self: &Self, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/lt-ref-self.rs:21:9 @@ -26,7 +26,7 @@ LL | fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/lt-ref-self.rs:25:9 @@ -36,7 +36,7 @@ LL | fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/lt-ref-self.rs:29:9 @@ -46,7 +46,7 @@ LL | fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/lt-ref-self.rs:33:9 @@ -56,7 +56,7 @@ LL | fn box_pin_Self(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: aborting due to 6 previous errors diff --git a/src/test/ui/self/elision/ref-mut-self-async.nll.stderr b/src/test/ui/self/elision/ref-mut-self-async.nll.stderr index 46e828390b0fc..19496a5ef6d32 100644 --- a/src/test/ui/self/elision/ref-mut-self-async.nll.stderr +++ b/src/test/ui/self/elision/ref-mut-self-async.nll.stderr @@ -6,7 +6,7 @@ LL | async fn ref_self(&mut self, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-self-async.rs:19:9 @@ -16,7 +16,7 @@ LL | async fn ref_Self(self: &mut Self, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-self-async.rs:23:9 @@ -26,7 +26,7 @@ LL | async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-self-async.rs:27:9 @@ -36,7 +36,7 @@ LL | async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-self-async.rs:31:9 @@ -46,7 +46,7 @@ LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-self-async.rs:35:9 @@ -56,7 +56,7 @@ LL | async fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: aborting due to 6 previous errors diff --git a/src/test/ui/self/elision/ref-mut-self.nll.stderr b/src/test/ui/self/elision/ref-mut-self.nll.stderr index 6c8c030e5fffa..94bfc5f4a8186 100644 --- a/src/test/ui/self/elision/ref-mut-self.nll.stderr +++ b/src/test/ui/self/elision/ref-mut-self.nll.stderr @@ -6,7 +6,7 @@ LL | fn ref_self(&mut self, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-self.rs:17:9 @@ -16,7 +16,7 @@ LL | fn ref_Self(self: &mut Self, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-self.rs:21:9 @@ -26,7 +26,7 @@ LL | fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-self.rs:25:9 @@ -36,7 +36,7 @@ LL | fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-self.rs:29:9 @@ -46,7 +46,7 @@ LL | fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-self.rs:33:9 @@ -56,7 +56,7 @@ LL | fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: aborting due to 6 previous errors diff --git a/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr b/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr index 99340800790ec..94671c7c87a5e 100644 --- a/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr +++ b/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr @@ -6,7 +6,7 @@ LL | async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-struct-async.rs:17:9 @@ -16,7 +16,7 @@ LL | async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-struct-async.rs:21:9 @@ -26,7 +26,7 @@ LL | async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-struct-async.rs:25:9 @@ -36,7 +36,7 @@ LL | async fn box_box_ref_Struct(self: Box>, f: &u32) -> &u | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-struct-async.rs:29:9 @@ -46,7 +46,7 @@ LL | async fn box_pin_ref_Struct(self: Box>, f: &u32) -> &u | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: aborting due to 5 previous errors diff --git a/src/test/ui/self/elision/ref-mut-struct.nll.stderr b/src/test/ui/self/elision/ref-mut-struct.nll.stderr index e3886444db2ad..c9e7479ea5dff 100644 --- a/src/test/ui/self/elision/ref-mut-struct.nll.stderr +++ b/src/test/ui/self/elision/ref-mut-struct.nll.stderr @@ -6,7 +6,7 @@ LL | fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-struct.rs:15:9 @@ -16,7 +16,7 @@ LL | fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-struct.rs:19:9 @@ -26,7 +26,7 @@ LL | fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-struct.rs:23:9 @@ -36,7 +36,7 @@ LL | fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-struct.rs:27:9 @@ -46,7 +46,7 @@ LL | fn box_pin_ref_Struct(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: aborting due to 5 previous errors diff --git a/src/test/ui/self/elision/ref-self-async.nll.stderr b/src/test/ui/self/elision/ref-self-async.nll.stderr index 541e49543221e..bd1f80811b542 100644 --- a/src/test/ui/self/elision/ref-self-async.nll.stderr +++ b/src/test/ui/self/elision/ref-self-async.nll.stderr @@ -1,13 +1,72 @@ -error[E0658]: `Wrap<&Struct, Struct>` cannot be used as the type of `self` without the `arbitrary_self_types` feature - --> $DIR/ref-self-async.rs:47:39 +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:23:9 | -LL | async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { - | ^^^^^^^^^^^^^^^^^ +LL | async fn ref_self(&self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:29:9 + | +LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:33:9 | - = note: see issue #44874 for more information - = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable - = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) +LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:37:9 + | +LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:41:9 + | +LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:45:9 + | +LL | async fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:49:9 + | +LL | async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` -error: aborting due to previous error +error: aborting due to 7 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/self/elision/ref-self-async.rs b/src/test/ui/self/elision/ref-self-async.rs index 6a98b79cb3bba..0fbbd95c975d6 100644 --- a/src/test/ui/self/elision/ref-self-async.rs +++ b/src/test/ui/self/elision/ref-self-async.rs @@ -1,6 +1,7 @@ // edition:2018 #![allow(non_snake_case)] +#![feature(arbitrary_self_types)] use std::marker::PhantomData; use std::ops::Deref; diff --git a/src/test/ui/self/elision/ref-self-async.stderr b/src/test/ui/self/elision/ref-self-async.stderr index b73290b024f8f..bda958241b67b 100644 --- a/src/test/ui/self/elision/ref-self-async.stderr +++ b/src/test/ui/self/elision/ref-self-async.stderr @@ -1,5 +1,5 @@ error[E0623]: lifetime mismatch - --> $DIR/ref-self-async.rs:22:9 + --> $DIR/ref-self-async.rs:23:9 | LL | async fn ref_self(&self, f: &u32) -> &u32 { | ----- ---- @@ -9,7 +9,7 @@ LL | f | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-self-async.rs:28:9 + --> $DIR/ref-self-async.rs:29:9 | LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { | ----- ---- @@ -19,7 +19,7 @@ LL | f | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-self-async.rs:32:9 + --> $DIR/ref-self-async.rs:33:9 | LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { | ----- ---- @@ -29,7 +29,7 @@ LL | f | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-self-async.rs:36:9 + --> $DIR/ref-self-async.rs:37:9 | LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { | ----- ---- @@ -39,7 +39,7 @@ LL | f | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-self-async.rs:40:9 + --> $DIR/ref-self-async.rs:41:9 | LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { | ----- ---- @@ -49,7 +49,7 @@ LL | f | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-self-async.rs:44:9 + --> $DIR/ref-self-async.rs:45:9 | LL | async fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { | ----- ---- @@ -59,7 +59,7 @@ LL | f | ^ ...but data from `f` is returned here error[E0623]: lifetime mismatch - --> $DIR/ref-self-async.rs:48:9 + --> $DIR/ref-self-async.rs:49:9 | LL | async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { | ----- --- diff --git a/src/test/ui/self/elision/ref-self.nll.stderr b/src/test/ui/self/elision/ref-self.nll.stderr index ecac1ce3378d6..d1fd209102e69 100644 --- a/src/test/ui/self/elision/ref-self.nll.stderr +++ b/src/test/ui/self/elision/ref-self.nll.stderr @@ -6,7 +6,7 @@ LL | fn ref_self(&self, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-self.rs:27:9 @@ -16,7 +16,7 @@ LL | fn ref_Self(self: &Self, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-self.rs:31:9 @@ -26,7 +26,7 @@ LL | fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-self.rs:35:9 @@ -36,7 +36,7 @@ LL | fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-self.rs:39:9 @@ -46,7 +46,7 @@ LL | fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-self.rs:43:9 @@ -56,7 +56,7 @@ LL | fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-self.rs:47:9 @@ -66,7 +66,7 @@ LL | fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: aborting due to 7 previous errors diff --git a/src/test/ui/self/elision/ref-struct-async.nll.stderr b/src/test/ui/self/elision/ref-struct-async.nll.stderr index bcbf79bc039fd..9361b6f3f81f4 100644 --- a/src/test/ui/self/elision/ref-struct-async.nll.stderr +++ b/src/test/ui/self/elision/ref-struct-async.nll.stderr @@ -6,7 +6,7 @@ LL | async fn ref_Struct(self: &Struct, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-struct-async.rs:17:9 @@ -16,7 +16,7 @@ LL | async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-struct-async.rs:21:9 @@ -26,7 +26,7 @@ LL | async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-struct-async.rs:25:9 @@ -36,7 +36,7 @@ LL | async fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-struct-async.rs:29:9 @@ -46,7 +46,7 @@ LL | async fn box_pin_Struct(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: aborting due to 5 previous errors diff --git a/src/test/ui/self/elision/ref-struct.nll.stderr b/src/test/ui/self/elision/ref-struct.nll.stderr index 39e7631f31e7b..e1cc38b7c952f 100644 --- a/src/test/ui/self/elision/ref-struct.nll.stderr +++ b/src/test/ui/self/elision/ref-struct.nll.stderr @@ -6,7 +6,7 @@ LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-struct.rs:15:9 @@ -16,7 +16,7 @@ LL | fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-struct.rs:19:9 @@ -26,7 +26,7 @@ LL | fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-struct.rs:23:9 @@ -36,7 +36,7 @@ LL | fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-struct.rs:27:9 @@ -46,7 +46,7 @@ LL | fn box_pin_Struct(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: aborting due to 5 previous errors diff --git a/src/test/ui/shadowed/shadowed-use-visibility.stderr b/src/test/ui/shadowed/shadowed-use-visibility.stderr index cd8ec13794c6f..1a642ae6e8ed8 100644 --- a/src/test/ui/shadowed/shadowed-use-visibility.stderr +++ b/src/test/ui/shadowed/shadowed-use-visibility.stderr @@ -2,25 +2,35 @@ error[E0603]: module import `bar` is private --> $DIR/shadowed-use-visibility.rs:9:14 | LL | use foo::bar::f as g; - | ^^^ this module import is private + | ^^^ private module import | -note: the module import `bar` is defined here +note: the module import `bar` is defined here... --> $DIR/shadowed-use-visibility.rs:4:9 | LL | use foo as bar; | ^^^^^^^^^^ +note: ...and refers to the module `foo` which is defined here + --> $DIR/shadowed-use-visibility.rs:1:1 + | +LL | mod foo { + | ^^^^^^^ error[E0603]: module import `f` is private --> $DIR/shadowed-use-visibility.rs:15:10 | LL | use bar::f::f; - | ^ this module import is private + | ^ private module import | -note: the module import `f` is defined here +note: the module import `f` is defined here... --> $DIR/shadowed-use-visibility.rs:11:9 | LL | use foo as f; | ^^^^^^^^ +note: ...and refers to the module `foo` which is defined here + --> $DIR/shadowed-use-visibility.rs:1:1 + | +LL | mod foo { + | ^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/span/auxiliary/transitive_dep_three.rs b/src/test/ui/span/auxiliary/transitive_dep_three.rs new file mode 100644 index 0000000000000..99b51625ac3ec --- /dev/null +++ b/src/test/ui/span/auxiliary/transitive_dep_three.rs @@ -0,0 +1,9 @@ +#[macro_export] +macro_rules! define_parse_error { + () => { + #[macro_export] + macro_rules! parse_error { + () => { parse error } + } + } +} diff --git a/src/test/ui/span/auxiliary/transitive_dep_two.rs b/src/test/ui/span/auxiliary/transitive_dep_two.rs new file mode 100644 index 0000000000000..5110c42765b6d --- /dev/null +++ b/src/test/ui/span/auxiliary/transitive_dep_two.rs @@ -0,0 +1,3 @@ +extern crate transitive_dep_three; + +transitive_dep_three::define_parse_error!(); diff --git a/src/test/ui/span/issue-24690.stderr b/src/test/ui/span/issue-24690.stderr index 69d1150abba47..2a090f442cc5f 100644 --- a/src/test/ui/span/issue-24690.stderr +++ b/src/test/ui/span/issue-24690.stderr @@ -2,7 +2,7 @@ warning: unused variable: `theOtherTwo` --> $DIR/issue-24690.rs:13:9 | LL | let theOtherTwo = 2; - | ^^^^^^^^^^^ help: consider prefixing with an underscore: `_theOtherTwo` + | ^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_theOtherTwo` | note: the lint level is defined here --> $DIR/issue-24690.rs:8:9 diff --git a/src/test/ui/span/transitive-dep-span.rs b/src/test/ui/span/transitive-dep-span.rs new file mode 100644 index 0000000000000..2d46f74ad9bc9 --- /dev/null +++ b/src/test/ui/span/transitive-dep-span.rs @@ -0,0 +1,15 @@ +// Tests that we properly serialize/deserialize spans from transitive dependencies +// (e.g. imported SourceFiles) +// +// The order of these next lines is important, since we need +// transitive_dep_two.rs to be able to reference transitive_dep_three.rs +// +// aux-build: transitive_dep_three.rs +// aux-build: transitive_dep_two.rs +// compile-flags: -Z macro-backtrace + +extern crate transitive_dep_two; + +transitive_dep_two::parse_error!(); //~ ERROR expected one of + +fn main() {} diff --git a/src/test/ui/span/transitive-dep-span.stderr b/src/test/ui/span/transitive-dep-span.stderr new file mode 100644 index 0000000000000..68d8911a4351c --- /dev/null +++ b/src/test/ui/span/transitive-dep-span.stderr @@ -0,0 +1,19 @@ +error: expected one of `!` or `::`, found `error` + --> $DIR/auxiliary/transitive_dep_three.rs:6:27 + | +LL | / macro_rules! parse_error { +LL | | () => { parse error } + | | ^^^^^ expected one of `!` or `::` +LL | | } + | |_________- in this expansion of `transitive_dep_two::parse_error!` + | + ::: $DIR/transitive-dep-span.rs:13:1 + | +LL | transitive_dep_two::parse_error!(); + | ----------------------------------- + | | + | in this macro invocation + | in this macro invocation + +error: aborting due to previous error + diff --git a/src/test/ui/span/type-annotations-needed-expr.stderr b/src/test/ui/span/type-annotations-needed-expr.stderr index 2b92f9b93bff2..3e6d350b36c33 100644 --- a/src/test/ui/span/type-annotations-needed-expr.stderr +++ b/src/test/ui/span/type-annotations-needed-expr.stderr @@ -2,12 +2,13 @@ error[E0282]: type annotations needed --> $DIR/type-annotations-needed-expr.rs:2:39 | LL | let _ = (vec![1,2,3]).into_iter().sum() as f64; - | ^^^ - | | - | cannot infer type for type parameter `S` declared on the method `sum` - | help: consider specifying the type argument in the method call: `sum::` + | ^^^ cannot infer type for type parameter `S` declared on the associated function `sum` | = note: type must be known at this point +help: consider specifying the type argument in the method call + | +LL | let _ = (vec![1,2,3]).into_iter().sum::() as f64; + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/specialization/defaultimpl/validation.rs b/src/test/ui/specialization/defaultimpl/validation.rs index 26b3f1ec41491..8134333c58f73 100644 --- a/src/test/ui/specialization/defaultimpl/validation.rs +++ b/src/test/ui/specialization/defaultimpl/validation.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] #![feature(specialization)] struct S; @@ -8,8 +8,9 @@ default impl S {} //~ ERROR inherent impls cannot be `default` default unsafe impl Send for S {} //~ ERROR impls of auto traits cannot be default default impl !Send for Z {} //~ ERROR impls of auto traits cannot be default + //~^ ERROR negative impls cannot be default impls trait Tr {} -default impl !Tr for S {} //~ ERROR negative impls are only allowed for auto traits +default impl !Tr for S {} //~ ERROR negative impls cannot be default impls fn main() {} diff --git a/src/test/ui/specialization/defaultimpl/validation.stderr b/src/test/ui/specialization/defaultimpl/validation.stderr index 6e19d79e48f6b..9bf59bd4f636a 100644 --- a/src/test/ui/specialization/defaultimpl/validation.stderr +++ b/src/test/ui/specialization/defaultimpl/validation.stderr @@ -9,23 +9,33 @@ LL | default impl S {} = note: only trait implementations may be annotated with `default` error: impls of auto traits cannot be default - --> $DIR/validation.rs:9:1 + --> $DIR/validation.rs:9:21 | LL | default unsafe impl Send for S {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------- ^^^^ auto trait + | | + | default because of this error: impls of auto traits cannot be default - --> $DIR/validation.rs:10:1 + --> $DIR/validation.rs:10:15 + | +LL | default impl !Send for Z {} + | ------- ^^^^ auto trait + | | + | default because of this + +error[E0750]: negative impls cannot be default impls + --> $DIR/validation.rs:10:14 | LL | default impl !Send for Z {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^ ^ -error[E0192]: negative impls are only allowed for auto traits (e.g., `Send` and `Sync`) - --> $DIR/validation.rs:13:1 +error[E0750]: negative impls cannot be default impls + --> $DIR/validation.rs:14:14 | LL | default impl !Tr for S {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^ ^ -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0192`. +For more information about this error, try `rustc --explain E0750`. diff --git a/src/test/ui/specialization/min_specialization/auxiliary/specialization-trait.rs b/src/test/ui/specialization/min_specialization/auxiliary/specialization-trait.rs new file mode 100644 index 0000000000000..6ec0d261d518a --- /dev/null +++ b/src/test/ui/specialization/min_specialization/auxiliary/specialization-trait.rs @@ -0,0 +1,6 @@ +#![feature(rustc_attrs)] + +#[rustc_specialization_trait] +pub trait SpecTrait { + fn method(&self); +} diff --git a/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.rs b/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.rs new file mode 100644 index 0000000000000..03cab00b0fb96 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.rs @@ -0,0 +1,32 @@ +// Test that associated types in trait objects are not considered to be +// constrained. + +#![feature(min_specialization)] + +trait Specializable { + fn f(); +} + +trait B { + type Y; +} + +trait C { + type Y; +} + +impl Specializable for A { + default fn f() {} +} + +impl<'a, T> Specializable for dyn B + 'a { + //~^ ERROR specializing impl repeats parameter `T` + fn f() {} +} + +impl<'a, T> Specializable for dyn C + 'a { + //~^ ERROR specializing impl repeats parameter `T` + fn f() {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr b/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr new file mode 100644 index 0000000000000..6345cee2c3781 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr @@ -0,0 +1,20 @@ +error: specializing impl repeats parameter `T` + --> $DIR/dyn-trait-assoc-types.rs:22:1 + | +LL | / impl<'a, T> Specializable for dyn B + 'a { +LL | | +LL | | fn f() {} +LL | | } + | |_^ + +error: specializing impl repeats parameter `T` + --> $DIR/dyn-trait-assoc-types.rs:27:1 + | +LL | / impl<'a, T> Specializable for dyn C + 'a { +LL | | +LL | | fn f() {} +LL | | } + | |_^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/specialization/min_specialization/impl_specialization_trait.rs b/src/test/ui/specialization/min_specialization/impl_specialization_trait.rs new file mode 100644 index 0000000000000..723ed71c3e95d --- /dev/null +++ b/src/test/ui/specialization/min_specialization/impl_specialization_trait.rs @@ -0,0 +1,16 @@ +// Check that specialization traits can't be implemented without a feature. + +// gate-test-min_specialization + +// aux-build:specialization-trait.rs + +extern crate specialization_trait; + +struct A {} + +impl specialization_trait::SpecTrait for A { + //~^ ERROR implementing `rustc_specialization_trait` traits is unstable + fn method(&self) {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/impl_specialization_trait.stderr b/src/test/ui/specialization/min_specialization/impl_specialization_trait.stderr new file mode 100644 index 0000000000000..934103d49dc0e --- /dev/null +++ b/src/test/ui/specialization/min_specialization/impl_specialization_trait.stderr @@ -0,0 +1,10 @@ +error: implementing `rustc_specialization_trait` traits is unstable + --> $DIR/impl_specialization_trait.rs:11:1 + | +LL | impl specialization_trait::SpecTrait for A { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(min_specialization)]` to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/ui/specialization/min_specialization/implcit-well-formed-bounds.rs b/src/test/ui/specialization/min_specialization/implcit-well-formed-bounds.rs new file mode 100644 index 0000000000000..98d7f9194351c --- /dev/null +++ b/src/test/ui/specialization/min_specialization/implcit-well-formed-bounds.rs @@ -0,0 +1,30 @@ +// Test that specializing on the well-formed predicates of the trait and +// self-type of an impl is allowed. + +// check-pass + +#![feature(min_specialization)] + +struct OrdOnly(T); + +trait SpecTrait { + fn f(); +} + +impl SpecTrait for T { + default fn f() {} +} + +impl SpecTrait<()> for OrdOnly { + fn f() {} +} + +impl SpecTrait> for () { + fn f() {} +} + +impl SpecTrait<(OrdOnly, OrdOnly)> for &[OrdOnly] { + fn f() {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/repeated_projection_type.rs b/src/test/ui/specialization/min_specialization/repeated_projection_type.rs new file mode 100644 index 0000000000000..f21f39f066981 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/repeated_projection_type.rs @@ -0,0 +1,24 @@ +// Test that projection bounds can't be specialized on. + +#![feature(min_specialization)] + +trait X { + fn f(); +} +trait Id { + type This; +} +impl Id for T { + type This = T; +} + +impl X for T { + default fn f() {} +} + +impl> X for V { + //~^ ERROR cannot specialize on + fn f() {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr new file mode 100644 index 0000000000000..7cc4357a704c0 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr @@ -0,0 +1,11 @@ +error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[317d]::Id[0]::This[0]) }, (I,)))` + --> $DIR/repeated_projection_type.rs:19:1 + | +LL | / impl> X for V { +LL | | +LL | | fn f() {} +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/ui/specialization/min_specialization/repeating_lifetimes.rs b/src/test/ui/specialization/min_specialization/repeating_lifetimes.rs new file mode 100644 index 0000000000000..49bfacec0ae12 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/repeating_lifetimes.rs @@ -0,0 +1,19 @@ +// Test that directly specializing on repeated lifetime parameters is not +// allowed. + +#![feature(min_specialization)] + +trait X { + fn f(); +} + +impl X for T { + default fn f() {} +} + +impl<'a> X for (&'a u8, &'a u8) { + //~^ ERROR specializing impl repeats parameter `'a` + fn f() {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/repeating_lifetimes.stderr b/src/test/ui/specialization/min_specialization/repeating_lifetimes.stderr new file mode 100644 index 0000000000000..ce9309f70122b --- /dev/null +++ b/src/test/ui/specialization/min_specialization/repeating_lifetimes.stderr @@ -0,0 +1,11 @@ +error: specializing impl repeats parameter `'a` + --> $DIR/repeating_lifetimes.rs:14:1 + | +LL | / impl<'a> X for (&'a u8, &'a u8) { +LL | | +LL | | fn f() {} +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/ui/specialization/min_specialization/repeating_param.rs b/src/test/ui/specialization/min_specialization/repeating_param.rs new file mode 100644 index 0000000000000..5a1c97fd321a9 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/repeating_param.rs @@ -0,0 +1,17 @@ +// Test that specializing on two type parameters being equal is not allowed. + +#![feature(min_specialization)] + +trait X { + fn f(); +} + +impl X for T { + default fn f() {} +} +impl X for (T, T) { + //~^ ERROR specializing impl repeats parameter `T` + fn f() {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/repeating_param.stderr b/src/test/ui/specialization/min_specialization/repeating_param.stderr new file mode 100644 index 0000000000000..8b4be1c499537 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/repeating_param.stderr @@ -0,0 +1,11 @@ +error: specializing impl repeats parameter `T` + --> $DIR/repeating_param.rs:12:1 + | +LL | / impl X for (T, T) { +LL | | +LL | | fn f() {} +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/ui/specialization/min_specialization/spec-iter.rs b/src/test/ui/specialization/min_specialization/spec-iter.rs new file mode 100644 index 0000000000000..e17e9dd5f133c --- /dev/null +++ b/src/test/ui/specialization/min_specialization/spec-iter.rs @@ -0,0 +1,20 @@ +// Check that we can specialize on a concrete iterator type. This requires us +// to consider which parameters in the parent impl are constrained. + +// check-pass + +#![feature(min_specialization)] + +trait SpecFromIter { + fn f(&self); +} + +impl<'a, T: 'a, I: Iterator> SpecFromIter for I { + default fn f(&self) {} +} + +impl<'a, T> SpecFromIter for std::slice::Iter<'a, T> { + fn f(&self) {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/spec-reference.rs b/src/test/ui/specialization/min_specialization/spec-reference.rs new file mode 100644 index 0000000000000..377889e2ccad2 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/spec-reference.rs @@ -0,0 +1,19 @@ +// Check that lifetime parameters are allowed in specializing impls. + +// check-pass + +#![feature(min_specialization)] + +trait MySpecTrait { + fn f(); +} + +impl MySpecTrait for T { + default fn f() {} +} + +impl<'a, T: ?Sized> MySpecTrait for &'a T { + fn f() {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/specialization_marker.rs b/src/test/ui/specialization/min_specialization/specialization_marker.rs new file mode 100644 index 0000000000000..93462d02ea578 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/specialization_marker.rs @@ -0,0 +1,17 @@ +// Test that `rustc_unsafe_specialization_marker` is only allowed on marker traits. + +#![feature(rustc_attrs)] + +#[rustc_unsafe_specialization_marker] +trait SpecMarker { + fn f(); + //~^ ERROR marker traits +} + +#[rustc_unsafe_specialization_marker] +trait SpecMarker2 { + type X; + //~^ ERROR marker traits +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/specialization_marker.stderr b/src/test/ui/specialization/min_specialization/specialization_marker.stderr new file mode 100644 index 0000000000000..ffeced198211f --- /dev/null +++ b/src/test/ui/specialization/min_specialization/specialization_marker.stderr @@ -0,0 +1,15 @@ +error[E0714]: marker traits cannot have associated items + --> $DIR/specialization_marker.rs:7:5 + | +LL | fn f(); + | ^^^^^^^ + +error[E0714]: marker traits cannot have associated items + --> $DIR/specialization_marker.rs:13:5 + | +LL | type X; + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0714`. diff --git a/src/test/ui/specialization/min_specialization/specialization_super_trait.rs b/src/test/ui/specialization/min_specialization/specialization_super_trait.rs new file mode 100644 index 0000000000000..145f376edf938 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/specialization_super_trait.rs @@ -0,0 +1,18 @@ +// Test that supertraits can't be assumed in impls of +// `rustc_specialization_trait`, as such impls would +// allow specializing on the supertrait. + +#![feature(min_specialization)] +#![feature(rustc_attrs)] + +#[rustc_specialization_trait] +trait SpecMarker: Default { + fn f(); +} + +impl SpecMarker for T { + //~^ ERROR cannot specialize + fn f() {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/specialization_super_trait.stderr b/src/test/ui/specialization/min_specialization/specialization_super_trait.stderr new file mode 100644 index 0000000000000..154c839c6da6e --- /dev/null +++ b/src/test/ui/specialization/min_specialization/specialization_super_trait.stderr @@ -0,0 +1,11 @@ +error: cannot specialize on trait `std::default::Default` + --> $DIR/specialization_super_trait.rs:13:1 + | +LL | / impl SpecMarker for T { +LL | | +LL | | fn f() {} +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/ui/specialization/min_specialization/specialization_trait.rs b/src/test/ui/specialization/min_specialization/specialization_trait.rs new file mode 100644 index 0000000000000..d597278d29693 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/specialization_trait.rs @@ -0,0 +1,26 @@ +// Test that `rustc_specialization_trait` requires always applicable impls. + +#![feature(min_specialization)] +#![feature(rustc_attrs)] + +#[rustc_specialization_trait] +trait SpecMarker { + fn f(); +} + +impl SpecMarker for &'static u8 { + //~^ ERROR cannot specialize + fn f() {} +} + +impl SpecMarker for (T, T) { + //~^ ERROR specializing impl + fn f() {} +} + +impl SpecMarker for [T] { + //~^ ERROR cannot specialize + fn f() {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/specialization_trait.stderr b/src/test/ui/specialization/min_specialization/specialization_trait.stderr new file mode 100644 index 0000000000000..4357d2318fc5d --- /dev/null +++ b/src/test/ui/specialization/min_specialization/specialization_trait.stderr @@ -0,0 +1,29 @@ +error: cannot specialize on `'static` lifetime + --> $DIR/specialization_trait.rs:11:1 + | +LL | / impl SpecMarker for &'static u8 { +LL | | +LL | | fn f() {} +LL | | } + | |_^ + +error: specializing impl repeats parameter `T` + --> $DIR/specialization_trait.rs:16:1 + | +LL | / impl SpecMarker for (T, T) { +LL | | +LL | | fn f() {} +LL | | } + | |_^ + +error: cannot specialize on trait `std::clone::Clone` + --> $DIR/specialization_trait.rs:21:1 + | +LL | / impl SpecMarker for [T] { +LL | | +LL | | fn f() {} +LL | | } + | |_^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/specialization/min_specialization/specialize_on_marker.rs b/src/test/ui/specialization/min_specialization/specialize_on_marker.rs new file mode 100644 index 0000000000000..4219bd13b1816 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/specialize_on_marker.rs @@ -0,0 +1,24 @@ +// Test that specializing on a `rustc_unsafe_specialization_marker` trait is +// allowed. + +// check-pass + +#![feature(min_specialization)] +#![feature(rustc_attrs)] + +#[rustc_unsafe_specialization_marker] +trait SpecMarker {} + +trait X { + fn f(); +} + +impl X for T { + default fn f() {} +} + +impl X for T { + fn f() {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/specialize_on_spec_trait.rs b/src/test/ui/specialization/min_specialization/specialize_on_spec_trait.rs new file mode 100644 index 0000000000000..abbab5c23dbb7 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/specialize_on_spec_trait.rs @@ -0,0 +1,27 @@ +// Test that specializing on a `rustc_specialization_trait` trait is allowed. + +// check-pass + +#![feature(min_specialization)] +#![feature(rustc_attrs)] + +#[rustc_specialization_trait] +trait SpecTrait { + fn g(&self); +} + +trait X { + fn f(&self); +} + +impl X for T { + default fn f(&self) {} +} + +impl X for T { + fn f(&self) { + self.g(); + } +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/specialize_on_static.rs b/src/test/ui/specialization/min_specialization/specialize_on_static.rs new file mode 100644 index 0000000000000..dd1b05401e6e7 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/specialize_on_static.rs @@ -0,0 +1,18 @@ +// Test that directly specializing on `'static` is not allowed. + +#![feature(min_specialization)] + +trait X { + fn f(); +} + +impl X for &'_ T { + default fn f() {} +} + +impl X for &'static u8 { + //~^ ERROR cannot specialize on `'static` lifetime + fn f() {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/specialize_on_static.stderr b/src/test/ui/specialization/min_specialization/specialize_on_static.stderr new file mode 100644 index 0000000000000..d1809d6dfbb52 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/specialize_on_static.stderr @@ -0,0 +1,11 @@ +error: cannot specialize on `'static` lifetime + --> $DIR/specialize_on_static.rs:13:1 + | +LL | / impl X for &'static u8 { +LL | | +LL | | fn f() {} +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/ui/specialization/min_specialization/specialize_on_trait.rs b/src/test/ui/specialization/min_specialization/specialize_on_trait.rs new file mode 100644 index 0000000000000..0588442c32080 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/specialize_on_trait.rs @@ -0,0 +1,20 @@ +// Test that specializing on a trait is not allowed in general. + +#![feature(min_specialization)] + +trait SpecMarker {} + +trait X { + fn f(); +} + +impl X for T { + default fn f() {} +} + +impl X for T { + //~^ ERROR cannot specialize on trait `SpecMarker` + fn f() {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/specialize_on_trait.stderr b/src/test/ui/specialization/min_specialization/specialize_on_trait.stderr new file mode 100644 index 0000000000000..35445fd09b949 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/specialize_on_trait.stderr @@ -0,0 +1,11 @@ +error: cannot specialize on trait `SpecMarker` + --> $DIR/specialize_on_trait.rs:15:1 + | +LL | / impl X for T { +LL | | +LL | | fn f() {} +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/ui/specialization/specialization-overlap-negative.rs b/src/test/ui/specialization/specialization-overlap-negative.rs index af80d6686e3a1..dff2b28bf003c 100644 --- a/src/test/ui/specialization/specialization-overlap-negative.rs +++ b/src/test/ui/specialization/specialization-overlap-negative.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] #![feature(specialization)] trait MyTrait {} @@ -6,6 +6,6 @@ trait MyTrait {} struct TestType(::std::marker::PhantomData); unsafe impl Send for TestType {} -impl !Send for TestType {} //~ ERROR E0119 +impl !Send for TestType {} //~ ERROR E0748 fn main() {} diff --git a/src/test/ui/specialization/specialization-overlap-negative.stderr b/src/test/ui/specialization/specialization-overlap-negative.stderr index 947aad824ea88..cbc7271b199a6 100644 --- a/src/test/ui/specialization/specialization-overlap-negative.stderr +++ b/src/test/ui/specialization/specialization-overlap-negative.stderr @@ -1,11 +1,11 @@ -error[E0119]: conflicting implementations of trait `std::marker::Send` for type `TestType<_>`: +error[E0748]: found both positive and negative implementation of trait `std::marker::Send` for type `TestType<_>`: --> $DIR/specialization-overlap-negative.rs:9:1 | LL | unsafe impl Send for TestType {} - | ------------------------------------------ first implementation here + | ------------------------------------------ positive implementation here LL | impl !Send for TestType {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here error: aborting due to previous error -For more information about this error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0748`. diff --git a/src/test/ui/specialization/specialization-polarity.rs b/src/test/ui/specialization/specialization-polarity.rs index d574480674571..4a733fb3c497e 100644 --- a/src/test/ui/specialization/specialization-polarity.rs +++ b/src/test/ui/specialization/specialization-polarity.rs @@ -1,16 +1,17 @@ // Make sure specialization cannot change impl polarity #![feature(optin_builtin_traits)] +#![feature(negative_impls)] #![feature(specialization)] auto trait Foo {} impl Foo for T {} -impl !Foo for u8 {} //~ ERROR E0119 +impl !Foo for u8 {} //~ ERROR E0748 auto trait Bar {} impl !Bar for T {} -impl Bar for u8 {} //~ ERROR E0119 +impl Bar for u8 {} //~ ERROR E0748 fn main() {} diff --git a/src/test/ui/specialization/specialization-polarity.stderr b/src/test/ui/specialization/specialization-polarity.stderr index bc1b2aeb70fc7..30655d87d5500 100644 --- a/src/test/ui/specialization/specialization-polarity.stderr +++ b/src/test/ui/specialization/specialization-polarity.stderr @@ -1,19 +1,19 @@ -error[E0119]: conflicting implementations of trait `Foo` for type `u8`: - --> $DIR/specialization-polarity.rs:9:1 +error[E0748]: found both positive and negative implementation of trait `Foo` for type `u8`: + --> $DIR/specialization-polarity.rs:10:1 | LL | impl Foo for T {} - | ----------------- first implementation here + | ----------------- positive implementation here LL | impl !Foo for u8 {} - | ^^^^^^^^^^^^^^^^ conflicting implementation for `u8` + | ^^^^^^^^^^^^^^^^ negative implementation here -error[E0119]: conflicting implementations of trait `Bar` for type `u8`: - --> $DIR/specialization-polarity.rs:14:1 +error[E0748]: found both positive and negative implementation of trait `Bar` for type `u8`: + --> $DIR/specialization-polarity.rs:15:1 | LL | impl !Bar for T {} - | ------------------ first implementation here + | ------------------ negative implementation here LL | impl Bar for u8 {} - | ^^^^^^^^^^^^^^^ conflicting implementation for `u8` + | ^^^^^^^^^^^^^^^ positive implementation here error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0748`. diff --git a/src/test/ui/stability-in-private-module.stderr b/src/test/ui/stability-in-private-module.stderr index 3a974164f9473..35a09b2199591 100644 --- a/src/test/ui/stability-in-private-module.stderr +++ b/src/test/ui/stability-in-private-module.stderr @@ -2,7 +2,7 @@ error[E0603]: module `thread_info` is private --> $DIR/stability-in-private-module.rs:7:26 | LL | let _ = std::thread::thread_info::current_thread(); - | ^^^^^^^^^^^ this module is private + | ^^^^^^^^^^^ private module | note: the module `thread_info` is defined here --> $SRC_DIR/libstd/thread/mod.rs:LL:COL diff --git a/src/test/ui/static/static-method-privacy.rs b/src/test/ui/static/static-method-privacy.rs index b637037f60e8f..9ee59b320edcd 100644 --- a/src/test/ui/static/static-method-privacy.rs +++ b/src/test/ui/static/static-method-privacy.rs @@ -6,5 +6,5 @@ mod a { } fn main() { - let _ = a::S::new(); //~ ERROR method `new` is private + let _ = a::S::new(); //~ ERROR associated function `new` is private } diff --git a/src/test/ui/static/static-method-privacy.stderr b/src/test/ui/static/static-method-privacy.stderr index 14ca9f58301e2..569608780def9 100644 --- a/src/test/ui/static/static-method-privacy.stderr +++ b/src/test/ui/static/static-method-privacy.stderr @@ -1,8 +1,8 @@ -error[E0624]: method `new` is private - --> $DIR/static-method-privacy.rs:9:13 +error[E0624]: associated function `new` is private + --> $DIR/static-method-privacy.rs:9:19 | LL | let _ = a::S::new(); - | ^^^^^^^^^ + | ^^^ private associated function error: aborting due to previous error diff --git a/src/test/ui/static/static-priv-by-default2.stderr b/src/test/ui/static/static-priv-by-default2.stderr index f6cd40412dd84..d731da79246ee 100644 --- a/src/test/ui/static/static-priv-by-default2.stderr +++ b/src/test/ui/static/static-priv-by-default2.stderr @@ -2,7 +2,7 @@ error[E0603]: static `private` is private --> $DIR/static-priv-by-default2.rs:15:30 | LL | use child::childs_child::private; - | ^^^^^^^ this static is private + | ^^^^^^^ private static | note: the static `private` is defined here --> $DIR/static-priv-by-default2.rs:7:9 @@ -14,7 +14,7 @@ error[E0603]: static `private` is private --> $DIR/static-priv-by-default2.rs:23:33 | LL | use static_priv_by_default::private; - | ^^^^^^^ this static is private + | ^^^^^^^ private static | note: the static `private` is defined here --> $DIR/auxiliary/static_priv_by_default.rs:3:1 diff --git a/src/test/ui/str/str-mut-idx.stderr b/src/test/ui/str/str-mut-idx.stderr index a9ec6b9c02fe8..d0afb2ae7af74 100644 --- a/src/test/ui/str/str-mut-idx.stderr +++ b/src/test/ui/str/str-mut-idx.stderr @@ -2,15 +2,17 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t --> $DIR/str-mut-idx.rs:4:15 | LL | fn bot() -> T { loop {} } - | --- -- help: consider relaxing the implicit `Sized` restriction: `: ?Sized` - | | - | required by this bound in `bot` + | --- - required by this bound in `bot` ... LL | s[1..2] = bot(); | ^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `str` = note: to learn more, visit +help: consider relaxing the implicit `Sized` restriction + | +LL | fn bot() -> T { loop {} } + | ^^^^^^^^ error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/str-mut-idx.rs:4:5 diff --git a/src/test/ui/structs/struct-field-privacy.stderr b/src/test/ui/structs/struct-field-privacy.stderr index 91d000b8672e0..f8b16ec0d01b3 100644 --- a/src/test/ui/structs/struct-field-privacy.stderr +++ b/src/test/ui/structs/struct-field-privacy.stderr @@ -1,32 +1,32 @@ error[E0616]: field `a` of struct `inner::A` is private - --> $DIR/struct-field-privacy.rs:23:5 + --> $DIR/struct-field-privacy.rs:23:7 | LL | b.a; - | ^^^ + | ^ private field error[E0616]: field `b` of struct `inner::B` is private - --> $DIR/struct-field-privacy.rs:26:5 + --> $DIR/struct-field-privacy.rs:26:7 | LL | c.b; - | ^^^ + | ^ private field error[E0616]: field `a` of struct `xc::A` is private - --> $DIR/struct-field-privacy.rs:28:5 + --> $DIR/struct-field-privacy.rs:28:7 | LL | d.a; - | ^^^ + | ^ private field error[E0616]: field `b` of struct `xc::B` is private - --> $DIR/struct-field-privacy.rs:32:5 + --> $DIR/struct-field-privacy.rs:32:7 | LL | e.b; - | ^^^ + | ^ private field error[E0616]: field `1` of struct `inner::Z` is private - --> $DIR/struct-field-privacy.rs:35:5 + --> $DIR/struct-field-privacy.rs:35:7 | LL | z.1; - | ^^^ + | ^ private field error: aborting due to 5 previous errors diff --git a/src/test/ui/structs/struct-variant-privacy-xc.stderr b/src/test/ui/structs/struct-variant-privacy-xc.stderr index 0203b7b5242e5..4e022cef1b2d3 100644 --- a/src/test/ui/structs/struct-variant-privacy-xc.stderr +++ b/src/test/ui/structs/struct-variant-privacy-xc.stderr @@ -2,7 +2,7 @@ error[E0603]: enum `Bar` is private --> $DIR/struct-variant-privacy-xc.rs:4:33 | LL | fn f(b: struct_variant_privacy::Bar) { - | ^^^ this enum is private + | ^^^ private enum | note: the enum `Bar` is defined here --> $DIR/auxiliary/struct_variant_privacy.rs:1:1 @@ -14,7 +14,7 @@ error[E0603]: enum `Bar` is private --> $DIR/struct-variant-privacy-xc.rs:6:33 | LL | struct_variant_privacy::Bar::Baz { a: _a } => {} - | ^^^ this enum is private + | ^^^ private enum | note: the enum `Bar` is defined here --> $DIR/auxiliary/struct_variant_privacy.rs:1:1 diff --git a/src/test/ui/structs/struct-variant-privacy.stderr b/src/test/ui/structs/struct-variant-privacy.stderr index d1b603f9d46fc..a6bc381ff6b38 100644 --- a/src/test/ui/structs/struct-variant-privacy.stderr +++ b/src/test/ui/structs/struct-variant-privacy.stderr @@ -2,7 +2,7 @@ error[E0603]: enum `Bar` is private --> $DIR/struct-variant-privacy.rs:7:14 | LL | fn f(b: foo::Bar) { - | ^^^ this enum is private + | ^^^ private enum | note: the enum `Bar` is defined here --> $DIR/struct-variant-privacy.rs:2:5 @@ -14,7 +14,7 @@ error[E0603]: enum `Bar` is private --> $DIR/struct-variant-privacy.rs:9:14 | LL | foo::Bar::Baz { a: _a } => {} - | ^^^ this enum is private + | ^^^ private enum | note: the enum `Bar` is defined here --> $DIR/struct-variant-privacy.rs:2:5 diff --git a/src/test/ui/substs-ppaux.normal.stderr b/src/test/ui/substs-ppaux.normal.stderr index 4423f3c130e2a..3ad2a1414f969 100644 --- a/src/test/ui/substs-ppaux.normal.stderr +++ b/src/test/ui/substs-ppaux.normal.stderr @@ -5,14 +5,16 @@ LL | fn bar<'a, T>() where T: 'a {} | --------------------------- fn() {>::bar::<'static, char>} defined here ... LL | let x: () = >::bar::<'static, char>; - | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | | - | | expected `()`, found fn item - | | help: use parentheses to call this function: `>::bar::<'static, char>()` + | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item + | | | expected due to this | = note: expected unit type `()` found fn item `fn() {>::bar::<'static, char>}` +help: use parentheses to call this function + | +LL | let x: () = >::bar::<'static, char>(); + | ^^ error[E0308]: mismatched types --> $DIR/substs-ppaux.rs:25:17 @@ -21,14 +23,16 @@ LL | fn bar<'a, T>() where T: 'a {} | --------------------------- fn() {>::bar::<'static, char>} defined here ... LL | let x: () = >::bar::<'static, char>; - | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | | - | | expected `()`, found fn item - | | help: use parentheses to call this function: `>::bar::<'static, char>()` + | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item + | | | expected due to this | = note: expected unit type `()` found fn item `fn() {>::bar::<'static, char>}` +help: use parentheses to call this function + | +LL | let x: () = >::bar::<'static, char>(); + | ^^ error[E0308]: mismatched types --> $DIR/substs-ppaux.rs:33:17 @@ -37,14 +41,16 @@ LL | fn baz() {} | -------- fn() {>::baz} defined here ... LL | let x: () = >::baz; - | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | | - | | expected `()`, found fn item - | | help: use parentheses to call this function: `>::baz()` + | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item + | | | expected due to this | = note: expected unit type `()` found fn item `fn() {>::baz}` +help: use parentheses to call this function + | +LL | let x: () = >::baz(); + | ^^ error[E0308]: mismatched types --> $DIR/substs-ppaux.rs:41:17 @@ -53,14 +59,16 @@ LL | fn foo<'z>() where &'z (): Sized { | -------------------------------- fn() {foo::<'static>} defined here ... LL | let x: () = foo::<'static>; - | -- ^^^^^^^^^^^^^^ - | | | - | | expected `()`, found fn item - | | help: use parentheses to call this function: `foo::<'static>()` + | -- ^^^^^^^^^^^^^^ expected `()`, found fn item + | | | expected due to this | = note: expected unit type `()` found fn item `fn() {foo::<'static>}` +help: use parentheses to call this function + | +LL | let x: () = foo::<'static>(); + | ^^ error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/substs-ppaux.rs:49:5 diff --git a/src/test/ui/substs-ppaux.verbose.stderr b/src/test/ui/substs-ppaux.verbose.stderr index 2aebdebee72c1..e23f06a3ef590 100644 --- a/src/test/ui/substs-ppaux.verbose.stderr +++ b/src/test/ui/substs-ppaux.verbose.stderr @@ -5,14 +5,16 @@ LL | fn bar<'a, T>() where T: 'a {} | --------------------------- fn() {>::bar::} defined here ... LL | let x: () = >::bar::<'static, char>; - | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | | - | | expected `()`, found fn item - | | help: use parentheses to call this function: `>::bar::<'static, char>()` + | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item + | | | expected due to this | = note: expected unit type `()` found fn item `fn() {>::bar::}` +help: use parentheses to call this function + | +LL | let x: () = >::bar::<'static, char>(); + | ^^ error[E0308]: mismatched types --> $DIR/substs-ppaux.rs:25:17 @@ -21,14 +23,16 @@ LL | fn bar<'a, T>() where T: 'a {} | --------------------------- fn() {>::bar::} defined here ... LL | let x: () = >::bar::<'static, char>; - | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | | - | | expected `()`, found fn item - | | help: use parentheses to call this function: `>::bar::<'static, char>()` + | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item + | | | expected due to this | = note: expected unit type `()` found fn item `fn() {>::bar::}` +help: use parentheses to call this function + | +LL | let x: () = >::bar::<'static, char>(); + | ^^ error[E0308]: mismatched types --> $DIR/substs-ppaux.rs:33:17 @@ -37,14 +41,16 @@ LL | fn baz() {} | -------- fn() {>::baz} defined here ... LL | let x: () = >::baz; - | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | | - | | expected `()`, found fn item - | | help: use parentheses to call this function: `>::baz()` + | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item + | | | expected due to this | = note: expected unit type `()` found fn item `fn() {>::baz}` +help: use parentheses to call this function + | +LL | let x: () = >::baz(); + | ^^ error[E0308]: mismatched types --> $DIR/substs-ppaux.rs:41:17 @@ -53,14 +59,16 @@ LL | fn foo<'z>() where &'z (): Sized { | -------------------------------- fn() {foo::} defined here ... LL | let x: () = foo::<'static>; - | -- ^^^^^^^^^^^^^^ - | | | - | | expected `()`, found fn item - | | help: use parentheses to call this function: `foo::<'static>()` + | -- ^^^^^^^^^^^^^^ expected `()`, found fn item + | | | expected due to this | = note: expected unit type `()` found fn item `fn() {foo::}` +help: use parentheses to call this function + | +LL | let x: () = foo::<'static>(); + | ^^ error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/substs-ppaux.rs:49:5 diff --git a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr index 05583876a066c..638d504d7feab 100644 --- a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr +++ b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -8,10 +8,12 @@ LL | fn bar(f: impl Future) {} | --- ----------------- required by this bound in `bar` ... LL | bar(foo); - | ^^^ - | | - | the trait `std::future::Future` is not implemented for `fn() -> impl std::future::Future {foo}` - | help: use parentheses to call the function: `foo()` + | ^^^ the trait `std::future::Future` is not implemented for `fn() -> impl std::future::Future {foo}` + | +help: use parentheses to call the function + | +LL | bar(foo()); + | ^^ error[E0277]: the trait bound `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36]: std::future::Future` is not satisfied --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:12:9 @@ -22,10 +24,12 @@ LL | fn bar(f: impl Future) {} LL | let async_closure = async || (); | -------- consider calling this closure LL | bar(async_closure); - | ^^^^^^^^^^^^^ - | | - | the trait `std::future::Future` is not implemented for `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36]` - | help: use parentheses to call the closure: `async_closure()` + | ^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36]` + | +help: use parentheses to call the closure + | +LL | bar(async_closure()); + | ^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/suggestions/attribute-typos.stderr b/src/test/ui/suggestions/attribute-typos.stderr index c7c257ba5fe53..1c307f0e2c19c 100644 --- a/src/test/ui/suggestions/attribute-typos.stderr +++ b/src/test/ui/suggestions/attribute-typos.stderr @@ -1,10 +1,8 @@ -error[E0658]: attributes starting with `rustc` are reserved for use by the `rustc` compiler +error: attributes starting with `rustc` are reserved for use by the `rustc` compiler --> $DIR/attribute-typos.rs:11:3 | LL | #[rustc_err] | ^^^^^^^^^ - | - = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable error: cannot find attribute `rustc_err` in this scope --> $DIR/attribute-typos.rs:11:3 @@ -31,4 +29,3 @@ LL | #[deprcated] error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/suggestions/const-in-struct-pat.stderr b/src/test/ui/suggestions/const-in-struct-pat.stderr index 0a010dcab4c26..ab336b14d2948 100644 --- a/src/test/ui/suggestions/const-in-struct-pat.stderr +++ b/src/test/ui/suggestions/const-in-struct-pat.stderr @@ -9,7 +9,11 @@ LL | let Thing { foo } = t; | | | expected struct `std::string::String`, found struct `foo` | `foo` is interpreted as a unit struct, not a new binding - | help: bind the struct field to a different name instead: `foo: other_foo` + | +help: bind the struct field to a different name instead + | +LL | let Thing { foo: other_foo } = t; + | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/suggestions/const-no-type.rs b/src/test/ui/suggestions/const-no-type.rs index 99200a965dd21..6b79697e9839e 100644 --- a/src/test/ui/suggestions/const-no-type.rs +++ b/src/test/ui/suggestions/const-no-type.rs @@ -43,4 +43,4 @@ static S = Vec::::new(); static mut SM = "abc"; //~^ ERROR missing type for `static mut` item //~| HELP provide a type for the item -//~| SUGGESTION &'static str +//~| SUGGESTION &str diff --git a/src/test/ui/suggestions/const-no-type.stderr b/src/test/ui/suggestions/const-no-type.stderr index c4f17109dc5c7..a7b5aa5e5b124 100644 --- a/src/test/ui/suggestions/const-no-type.stderr +++ b/src/test/ui/suggestions/const-no-type.stderr @@ -14,7 +14,7 @@ error: missing type for `static mut` item --> $DIR/const-no-type.rs:43:12 | LL | static mut SM = "abc"; - | ^^ help: provide a type for the item: `SM: &'static str` + | ^^ help: provide a type for the item: `SM: &str` error: missing type for `const` item --> $DIR/const-no-type.rs:14:7 diff --git a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr index 91f60e8f426c4..ed4a0b8487dff 100644 --- a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr +++ b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -8,10 +8,12 @@ LL | fn bar(f: impl T) {} | --- ------- required by this bound in `bar` ... LL | bar(foo); - | ^^^ - | | - | the trait `T` is not implemented for `fn() -> impl T {foo}` - | help: use parentheses to call the function: `foo()` + | ^^^ the trait `T` is not implemented for `fn() -> impl T {foo}` + | +help: use parentheses to call the function + | +LL | bar(foo()); + | ^^ error[E0277]: the trait bound `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:23]: T` is not satisfied --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:19:9 @@ -22,10 +24,12 @@ LL | fn bar(f: impl T) {} LL | let closure = || S; | -- consider calling this closure LL | bar(closure); - | ^^^^^^^ - | | - | the trait `T` is not implemented for `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:23]` - | help: use parentheses to call the closure: `closure()` + | ^^^^^^^ the trait `T` is not implemented for `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:23]` + | +help: use parentheses to call the closure + | +LL | bar(closure()); + | ^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr index 232e54b5d37b2..b03bea1eddbf0 100644 --- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr +++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr @@ -19,14 +19,16 @@ LL | fn foo(a: usize, b: usize) -> usize { a } | ----------------------------------- fn(usize, usize) -> usize {foo} defined here ... LL | let _: usize = foo; - | ----- ^^^ - | | | - | | expected `usize`, found fn item - | | help: use parentheses to call this function: `foo(a, b)` + | ----- ^^^ expected `usize`, found fn item + | | | expected due to this | = note: expected type `usize` found fn item `fn(usize, usize) -> usize {foo}` +help: use parentheses to call this function + | +LL | let _: usize = foo(a, b); + | ^^^^^^ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:30:16 @@ -35,14 +37,16 @@ LL | struct S(usize, usize); | ----------------------- fn(usize, usize) -> S {S} defined here ... LL | let _: S = S; - | - ^ - | | | - | | expected struct `S`, found fn item - | | help: use parentheses to instantiate this tuple struct: `S(_, _)` + | - ^ expected struct `S`, found fn item + | | | expected due to this | = note: expected struct `S` found fn item `fn(usize, usize) -> S {S}` +help: use parentheses to instantiate this tuple struct + | +LL | let _: S = S(_, _); + | ^^^^^^ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:31:20 @@ -51,14 +55,16 @@ LL | fn bar() -> usize { 42 } | ----------------- fn() -> usize {bar} defined here ... LL | let _: usize = bar; - | ----- ^^^ - | | | - | | expected `usize`, found fn item - | | help: use parentheses to call this function: `bar()` + | ----- ^^^ expected `usize`, found fn item + | | | expected due to this | = note: expected type `usize` found fn item `fn() -> usize {bar}` +help: use parentheses to call this function + | +LL | let _: usize = bar(); + | ^^ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:32:16 @@ -67,14 +73,16 @@ LL | struct V(); | ----------- fn() -> V {V} defined here ... LL | let _: V = V; - | - ^ - | | | - | | expected struct `V`, found fn item - | | help: use parentheses to instantiate this tuple struct: `V()` + | - ^ expected struct `V`, found fn item + | | | expected due to this | = note: expected struct `V` found fn item `fn() -> V {V}` +help: use parentheses to instantiate this tuple struct + | +LL | let _: V = V(); + | ^^ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:33:20 @@ -83,14 +91,16 @@ LL | fn baz(x: usize, y: usize) -> usize { x } | ----------------------------------- fn(usize, usize) -> usize {<_ as T>::baz} defined here ... LL | let _: usize = T::baz; - | ----- ^^^^^^ - | | | - | | expected `usize`, found fn item - | | help: use parentheses to call this function: `T::baz(x, y)` + | ----- ^^^^^^ expected `usize`, found fn item + | | | expected due to this | = note: expected type `usize` found fn item `fn(usize, usize) -> usize {<_ as T>::baz}` +help: use parentheses to call this function + | +LL | let _: usize = T::baz(x, y); + | ^^^^^^ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:34:20 @@ -99,14 +109,16 @@ LL | fn bat(x: usize) -> usize { 42 } | ------------------------- fn(usize) -> usize {<_ as T>::bat} defined here ... LL | let _: usize = T::bat; - | ----- ^^^^^^ - | | | - | | expected `usize`, found fn item - | | help: use parentheses to call this function: `T::bat(x)` + | ----- ^^^^^^ expected `usize`, found fn item + | | | expected due to this | = note: expected type `usize` found fn item `fn(usize) -> usize {<_ as T>::bat}` +help: use parentheses to call this function + | +LL | let _: usize = T::bat(x); + | ^^^ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:35:16 @@ -115,14 +127,16 @@ LL | A(usize), | -------- fn(usize) -> E {E::A} defined here ... LL | let _: E = E::A; - | - ^^^^ - | | | - | | expected enum `E`, found fn item - | | help: use parentheses to instantiate this tuple variant: `E::A(_)` + | - ^^^^ expected enum `E`, found fn item + | | | expected due to this | = note: expected enum `E` found fn item `fn(usize) -> E {E::A}` +help: use parentheses to instantiate this tuple variant + | +LL | let _: E = E::A(_); + | ^^^ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:37:20 @@ -131,14 +145,16 @@ LL | fn baz(x: usize, y: usize) -> usize { x } | ----------------------------------- fn(usize, usize) -> usize {::baz} defined here ... LL | let _: usize = X::baz; - | ----- ^^^^^^ - | | | - | | expected `usize`, found fn item - | | help: use parentheses to call this function: `X::baz(x, y)` + | ----- ^^^^^^ expected `usize`, found fn item + | | | expected due to this | = note: expected type `usize` found fn item `fn(usize, usize) -> usize {::baz}` +help: use parentheses to call this function + | +LL | let _: usize = X::baz(x, y); + | ^^^^^^ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:38:20 @@ -147,14 +163,16 @@ LL | fn bat(x: usize) -> usize { 42 } | ------------------------- fn(usize) -> usize {::bat} defined here ... LL | let _: usize = X::bat; - | ----- ^^^^^^ - | | | - | | expected `usize`, found fn item - | | help: use parentheses to call this function: `X::bat(x)` + | ----- ^^^^^^ expected `usize`, found fn item + | | | expected due to this | = note: expected type `usize` found fn item `fn(usize) -> usize {::bat}` +help: use parentheses to call this function + | +LL | let _: usize = X::bat(x); + | ^^^ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:39:20 @@ -163,14 +181,16 @@ LL | fn bax(x: usize) -> usize { 42 } | ------------------------- fn(usize) -> usize {::bax} defined here ... LL | let _: usize = X::bax; - | ----- ^^^^^^ - | | | - | | expected `usize`, found fn item - | | help: use parentheses to call this function: `X::bax(x)` + | ----- ^^^^^^ expected `usize`, found fn item + | | | expected due to this | = note: expected type `usize` found fn item `fn(usize) -> usize {::bax}` +help: use parentheses to call this function + | +LL | let _: usize = X::bax(x); + | ^^^ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:40:20 @@ -179,14 +199,16 @@ LL | fn bach(x: usize) -> usize; | --------------------------- fn(usize) -> usize {::bach} defined here ... LL | let _: usize = X::bach; - | ----- ^^^^^^^ - | | | - | | expected `usize`, found fn item - | | help: use parentheses to call this function: `X::bach(x)` + | ----- ^^^^^^^ expected `usize`, found fn item + | | | expected due to this | = note: expected type `usize` found fn item `fn(usize) -> usize {::bach}` +help: use parentheses to call this function + | +LL | let _: usize = X::bach(x); + | ^^^ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:41:20 @@ -195,14 +217,16 @@ LL | fn ban(&self) -> usize { 42 } | ---------------------- for<'r> fn(&'r X) -> usize {::ban} defined here ... LL | let _: usize = X::ban; - | ----- ^^^^^^ - | | | - | | expected `usize`, found fn item - | | help: use parentheses to call this function: `X::ban(_)` + | ----- ^^^^^^ expected `usize`, found fn item + | | | expected due to this | = note: expected type `usize` found fn item `for<'r> fn(&'r X) -> usize {::ban}` +help: use parentheses to call this function + | +LL | let _: usize = X::ban(_); + | ^^^ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:42:20 @@ -211,26 +235,38 @@ LL | fn bal(&self) -> usize; | ----------------------- for<'r> fn(&'r X) -> usize {::bal} defined here ... LL | let _: usize = X::bal; - | ----- ^^^^^^ - | | | - | | expected `usize`, found fn item - | | help: use parentheses to call this function: `X::bal(_)` + | ----- ^^^^^^ expected `usize`, found fn item + | | | expected due to this | = note: expected type `usize` found fn item `for<'r> fn(&'r X) -> usize {::bal}` +help: use parentheses to call this function + | +LL | let _: usize = X::bal(_); + | ^^^ error[E0615]: attempted to take value of method `ban` on type `X` --> $DIR/fn-or-tuple-struct-without-args.rs:43:22 | LL | let _: usize = X.ban; - | ^^^ help: use parentheses to call the method: `ban()` + | ^^^ method, not a field + | +help: use parentheses to call the method + | +LL | let _: usize = X.ban(); + | ^^ error[E0615]: attempted to take value of method `bal` on type `X` --> $DIR/fn-or-tuple-struct-without-args.rs:44:22 | LL | let _: usize = X.bal; - | ^^^ help: use parentheses to call the method: `bal()` + | ^^^ method, not a field + | +help: use parentheses to call the method + | +LL | let _: usize = X.bal(); + | ^^ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:46:20 @@ -238,14 +274,16 @@ error[E0308]: mismatched types LL | let closure = || 42; | ----- the found closure LL | let _: usize = closure; - | ----- ^^^^^^^ - | | | - | | expected `usize`, found closure - | | help: use parentheses to call this closure: `closure()` + | ----- ^^^^^^^ expected `usize`, found closure + | | | expected due to this | = note: expected type `usize` found closure `[closure@$DIR/fn-or-tuple-struct-without-args.rs:45:19: 45:24]` +help: use parentheses to call this closure + | +LL | let _: usize = closure(); + | ^^ error: aborting due to 17 previous errors diff --git a/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr b/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr index ccaceefacd739..84ba935191b48 100644 --- a/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr +++ b/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr @@ -5,13 +5,14 @@ LL | fn foo(_: X) {} | --- ----- required by this bound in `foo` ... LL | foo(&s); - | -^ - | | - | the trait `Trait` is not implemented for `&S` - | help: consider changing this borrow's mutability: `&mut` + | ^^ the trait `Trait` is not implemented for `&S` | = help: the following implementations were found: <&'a mut S as Trait> +help: consider changing this borrow's mutability + | +LL | foo(&mut s); + | ^^^^ error[E0277]: the trait bound `S: Trait` is not satisfied --> $DIR/imm-ref-trait-object-literal.rs:13:7 diff --git a/src/test/ui/suggestions/method-missing-parentheses.stderr b/src/test/ui/suggestions/method-missing-parentheses.stderr index 6e4f7a84724bf..04c67ec6a06b6 100644 --- a/src/test/ui/suggestions/method-missing-parentheses.stderr +++ b/src/test/ui/suggestions/method-missing-parentheses.stderr @@ -8,9 +8,12 @@ error[E0615]: attempted to take value of method `collect` on type `std::vec::Int --> $DIR/method-missing-parentheses.rs:2:32 | LL | let _ = vec![].into_iter().collect::; - | ^^^^^^^--------- - | | - | help: use parentheses to call the method: `collect::()` + | ^^^^^^^ method, not a field + | +help: use parentheses to call the method + | +LL | let _ = vec![].into_iter().collect::(); + | ^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/suggestions/suggest-methods.stderr b/src/test/ui/suggestions/suggest-methods.stderr index a715c565946e0..c343071ac3e0c 100644 --- a/src/test/ui/suggestions/suggest-methods.stderr +++ b/src/test/ui/suggestions/suggest-methods.stderr @@ -5,19 +5,19 @@ LL | struct Foo; | ----------- method `bat` not found for this ... LL | f.bat(1.0); - | ^^^ help: there is a method with a similar name: `bar` + | ^^^ help: there is an associated function with a similar name: `bar` error[E0599]: no method named `is_emtpy` found for struct `std::string::String` in the current scope --> $DIR/suggest-methods.rs:21:15 | LL | let _ = s.is_emtpy(); - | ^^^^^^^^ help: there is a method with a similar name: `is_empty` + | ^^^^^^^^ help: there is an associated function with a similar name: `is_empty` error[E0599]: no method named `count_eos` found for type `u32` in the current scope --> $DIR/suggest-methods.rs:25:19 | LL | let _ = 63u32.count_eos(); - | ^^^^^^^^^ help: there is a method with a similar name: `count_zeros` + | ^^^^^^^^^ help: there is an associated function with a similar name: `count_zeros` error[E0599]: no method named `count_o` found for type `u32` in the current scope --> $DIR/suggest-methods.rs:28:19 diff --git a/src/test/ui/suggestions/unused-closure-argument.stderr b/src/test/ui/suggestions/unused-closure-argument.stderr index d83ab08e71efc..55195ce50a13e 100644 --- a/src/test/ui/suggestions/unused-closure-argument.stderr +++ b/src/test/ui/suggestions/unused-closure-argument.stderr @@ -14,7 +14,7 @@ error: unused variable: `x` --> $DIR/unused-closure-argument.rs:17:15 | LL | .map(|x| 4) - | ^ help: consider prefixing with an underscore: `_x` + | ^ help: if this is intentional, prefix it with an underscore: `_x` error: aborting due to 2 previous errors diff --git a/src/test/ui/syntax-trait-polarity-feature-gate.stderr b/src/test/ui/syntax-trait-polarity-feature-gate.stderr index 5d4c1b354f700..3562deecbd522 100644 --- a/src/test/ui/syntax-trait-polarity-feature-gate.stderr +++ b/src/test/ui/syntax-trait-polarity-feature-gate.stderr @@ -4,8 +4,8 @@ error[E0658]: negative trait bounds are not yet fully implemented; use marker ty LL | impl !Send for TestType {} | ^^^^^ | - = note: see issue #13231 for more information - = help: add `#![feature(optin_builtin_traits)]` to the crate attributes to enable + = note: see issue #68318 for more information + = help: add `#![feature(negative_impls)]` to the crate attributes to enable error: aborting due to previous error diff --git a/src/test/ui/syntax-trait-polarity.rs b/src/test/ui/syntax-trait-polarity.rs index 1b7fc1587e6d2..ed2947493b02c 100644 --- a/src/test/ui/syntax-trait-polarity.rs +++ b/src/test/ui/syntax-trait-polarity.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Send; @@ -12,7 +12,6 @@ trait TestTrait {} unsafe impl !Send for TestType {} //~^ ERROR negative impls cannot be unsafe impl !TestTrait for TestType {} -//~^ ERROR negative impls are only allowed for auto traits struct TestType2(T); @@ -22,6 +21,5 @@ impl !TestType2 {} unsafe impl !Send for TestType2 {} //~^ ERROR negative impls cannot be unsafe impl !TestTrait for TestType2 {} -//~^ ERROR negative impls are only allowed for auto traits fn main() {} diff --git a/src/test/ui/syntax-trait-polarity.stderr b/src/test/ui/syntax-trait-polarity.stderr index 5777e0ade908e..1fd40fb66570d 100644 --- a/src/test/ui/syntax-trait-polarity.stderr +++ b/src/test/ui/syntax-trait-polarity.stderr @@ -16,7 +16,7 @@ LL | unsafe impl !Send for TestType {} | unsafe because of this error: inherent impls cannot be negative - --> $DIR/syntax-trait-polarity.rs:19:10 + --> $DIR/syntax-trait-polarity.rs:18:10 | LL | impl !TestType2 {} | -^^^^^^^^^^^^ inherent impl for this type @@ -24,7 +24,7 @@ LL | impl !TestType2 {} | negative because of this error[E0198]: negative impls cannot be unsafe - --> $DIR/syntax-trait-polarity.rs:22:16 + --> $DIR/syntax-trait-polarity.rs:21:16 | LL | unsafe impl !Send for TestType2 {} | ------ -^^^^ @@ -32,19 +32,6 @@ LL | unsafe impl !Send for TestType2 {} | | negative because of this | unsafe because of this -error[E0192]: negative impls are only allowed for auto traits (e.g., `Send` and `Sync`) - --> $DIR/syntax-trait-polarity.rs:14:1 - | -LL | impl !TestTrait for TestType {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0192]: negative impls are only allowed for auto traits (e.g., `Send` and `Sync`) - --> $DIR/syntax-trait-polarity.rs:24:1 - | -LL | impl !TestTrait for TestType2 {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0192, E0198. -For more information about an error, try `rustc --explain E0192`. +For more information about this error, try `rustc --explain E0198`. diff --git a/src/test/ui/test-attrs/test-attr-non-associated-functions.rs b/src/test/ui/test-attrs/test-attr-non-associated-functions.rs index e475f5b4a75a5..31e567c396067 100644 --- a/src/test/ui/test-attrs/test-attr-non-associated-functions.rs +++ b/src/test/ui/test-attrs/test-attr-non-associated-functions.rs @@ -6,7 +6,13 @@ struct A {} impl A { #[test] - fn new() -> A { //~ ERROR `#[test]` attribute is only allowed on non associated functions + fn new() -> A { + //~^ ERROR `#[test]` attribute is only allowed on non associated functions + A {} + } + #[test] + fn recovery_witness() -> A { + //~^ ERROR `#[test]` attribute is only allowed on non associated functions A {} } } diff --git a/src/test/ui/test-attrs/test-attr-non-associated-functions.stderr b/src/test/ui/test-attrs/test-attr-non-associated-functions.stderr index cb3ae51823e45..a81b8f3980c37 100644 --- a/src/test/ui/test-attrs/test-attr-non-associated-functions.stderr +++ b/src/test/ui/test-attrs/test-attr-non-associated-functions.stderr @@ -2,9 +2,19 @@ error: `#[test]` attribute is only allowed on non associated functions --> $DIR/test-attr-non-associated-functions.rs:9:5 | LL | / fn new() -> A { +LL | | LL | | A {} LL | | } | |_____^ -error: aborting due to previous error +error: `#[test]` attribute is only allowed on non associated functions + --> $DIR/test-attr-non-associated-functions.rs:14:5 + | +LL | / fn recovery_witness() -> A { +LL | | +LL | | A {} +LL | | } + | |_____^ + +error: aborting due to 2 previous errors diff --git a/src/test/ui/test-panic-while-printing.rs b/src/test/ui/test-panic-while-printing.rs new file mode 100644 index 0000000000000..23f45407c1af3 --- /dev/null +++ b/src/test/ui/test-panic-while-printing.rs @@ -0,0 +1,24 @@ +// compile-flags:--test +// run-pass +// ignore-emscripten no subprocess support + +use std::fmt; +use std::fmt::{Display, Formatter}; + +pub struct A(Vec); + +impl Display for A { + fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result { + self.0[0]; + Ok(()) + } +} + +#[test] +fn main() { + let result = std::panic::catch_unwind(|| { + let a = A(vec![]); + eprintln!("{}", a); + }); + assert!(result.is_err()); +} diff --git a/src/test/ui/tool_lints.stderr b/src/test/ui/tool_lints.stderr index 86f87784eaf86..1bcd7fd735de8 100644 --- a/src/test/ui/tool_lints.stderr +++ b/src/test/ui/tool_lints.stderr @@ -18,3 +18,4 @@ LL | #[warn(foo::bar)] error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0710`. diff --git a/src/test/ui/traits/auto-traits.rs b/src/test/ui/traits/auto-traits.rs index c495b97b25bfe..15fdddc5f3f5c 100644 --- a/src/test/ui/traits/auto-traits.rs +++ b/src/test/ui/traits/auto-traits.rs @@ -1,6 +1,7 @@ // run-pass #![allow(unused_doc_comments)] #![feature(optin_builtin_traits)] +#![feature(negative_impls)] auto trait Auto {} unsafe auto trait AutoUnsafe {} diff --git a/src/test/ui/traits/negative-impls/auxiliary/foreign_trait.rs b/src/test/ui/traits/negative-impls/auxiliary/foreign_trait.rs new file mode 100644 index 0000000000000..681f26438e695 --- /dev/null +++ b/src/test/ui/traits/negative-impls/auxiliary/foreign_trait.rs @@ -0,0 +1,6 @@ +#![feature(negative_impls)] + +pub trait ForeignTrait {} + +impl ForeignTrait for u32 {} +impl !ForeignTrait for String {} diff --git a/src/test/ui/traits/negative-impls/feature-gate-negative_impls.rs b/src/test/ui/traits/negative-impls/feature-gate-negative_impls.rs new file mode 100644 index 0000000000000..683fd6db6f29d --- /dev/null +++ b/src/test/ui/traits/negative-impls/feature-gate-negative_impls.rs @@ -0,0 +1,3 @@ +trait MyTrait {} +impl !MyTrait for u32 {} //~ ERROR negative trait bounds are not yet fully implemented +fn main() {} diff --git a/src/test/ui/traits/negative-impls/feature-gate-negative_impls.stderr b/src/test/ui/traits/negative-impls/feature-gate-negative_impls.stderr new file mode 100644 index 0000000000000..b253fbd0da7f9 --- /dev/null +++ b/src/test/ui/traits/negative-impls/feature-gate-negative_impls.stderr @@ -0,0 +1,12 @@ +error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now + --> $DIR/feature-gate-negative_impls.rs:2:6 + | +LL | impl !MyTrait for u32 {} + | ^^^^^^^^ + | + = note: see issue #68318 for more information + = help: add `#![feature(negative_impls)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/traits/traits-negative-impls.rs b/src/test/ui/traits/negative-impls/negated-auto-traits-error.rs similarity index 98% rename from src/test/ui/traits/traits-negative-impls.rs rename to src/test/ui/traits/negative-impls/negated-auto-traits-error.rs index fb9a3a99748d0..4bdad5dc591c5 100644 --- a/src/test/ui/traits/traits-negative-impls.rs +++ b/src/test/ui/traits/negative-impls/negated-auto-traits-error.rs @@ -3,7 +3,7 @@ // errors are not reported. This way, we make sure that, for each function, different // typeck phases are involved and all errors are reported. -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Send; diff --git a/src/test/ui/traits/traits-negative-impls.stderr b/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr similarity index 92% rename from src/test/ui/traits/traits-negative-impls.stderr rename to src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr index 599bbfe222546..69a91b09e3ee0 100644 --- a/src/test/ui/traits/traits-negative-impls.stderr +++ b/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr @@ -1,5 +1,5 @@ error[E0277]: `dummy::TestType` cannot be sent between threads safely - --> $DIR/traits-negative-impls.rs:23:11 + --> $DIR/negated-auto-traits-error.rs:23:11 | LL | struct Outer(T); | ------------------------- required by `Outer` @@ -10,7 +10,7 @@ LL | Outer(TestType); = help: the trait `std::marker::Send` is not implemented for `dummy::TestType` error[E0277]: `dummy::TestType` cannot be sent between threads safely - --> $DIR/traits-negative-impls.rs:23:5 + --> $DIR/negated-auto-traits-error.rs:23:5 | LL | struct Outer(T); | ------------------------- required by `Outer` @@ -21,7 +21,7 @@ LL | Outer(TestType); = help: the trait `std::marker::Send` is not implemented for `dummy::TestType` error[E0277]: `dummy1b::TestType` cannot be sent between threads safely - --> $DIR/traits-negative-impls.rs:32:13 + --> $DIR/negated-auto-traits-error.rs:32:13 | LL | fn is_send(_: T) {} | ------- ---- required by this bound in `is_send` @@ -32,7 +32,7 @@ LL | is_send(TestType); = help: the trait `std::marker::Send` is not implemented for `dummy1b::TestType` error[E0277]: `dummy1c::TestType` cannot be sent between threads safely - --> $DIR/traits-negative-impls.rs:40:13 + --> $DIR/negated-auto-traits-error.rs:40:13 | LL | fn is_send(_: T) {} | ------- ---- required by this bound in `is_send` @@ -44,7 +44,7 @@ LL | is_send((8, TestType)); = note: required because it appears within the type `({integer}, dummy1c::TestType)` error[E0277]: `dummy2::TestType` cannot be sent between threads safely - --> $DIR/traits-negative-impls.rs:48:13 + --> $DIR/negated-auto-traits-error.rs:48:13 | LL | fn is_send(_: T) {} | ------- ---- required by this bound in `is_send` @@ -60,7 +60,7 @@ LL | is_send(Box::new(TestType)); = note: required because it appears within the type `std::boxed::Box` error[E0277]: `dummy3::TestType` cannot be sent between threads safely - --> $DIR/traits-negative-impls.rs:56:13 + --> $DIR/negated-auto-traits-error.rs:56:13 | LL | fn is_send(_: T) {} | ------- ---- required by this bound in `is_send` @@ -74,7 +74,7 @@ LL | is_send(Box::new(Outer2(TestType))); = note: required because it appears within the type `std::boxed::Box>` error[E0277]: `main::TestType` cannot be sent between threads safely - --> $DIR/traits-negative-impls.rs:66:13 + --> $DIR/negated-auto-traits-error.rs:66:13 | LL | fn is_sync(_: T) {} | ------- ---- required by this bound in `is_sync` diff --git a/src/test/ui/traits/traits-negative-impls-rpass.rs b/src/test/ui/traits/negative-impls/negated-auto-traits-rpass.rs similarity index 91% rename from src/test/ui/traits/traits-negative-impls-rpass.rs rename to src/test/ui/traits/negative-impls/negated-auto-traits-rpass.rs index 8664b6a6a6e36..010dbf2466403 100644 --- a/src/test/ui/traits/traits-negative-impls-rpass.rs +++ b/src/test/ui/traits/negative-impls/negated-auto-traits-rpass.rs @@ -1,6 +1,6 @@ // run-pass #![allow(unused_variables)] -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::marker::Send; diff --git a/src/test/ui/traits/negative-impls/negative-default-impls.rs b/src/test/ui/traits/negative-impls/negative-default-impls.rs new file mode 100644 index 0000000000000..2d50bc83ec304 --- /dev/null +++ b/src/test/ui/traits/negative-impls/negative-default-impls.rs @@ -0,0 +1,10 @@ +#![feature(negative_impls)] +#![feature(specialization)] + +trait MyTrait { + type Foo; +} + +default impl !MyTrait for u32 {} //~ ERROR negative impls cannot be default impls + +fn main() {} diff --git a/src/test/ui/traits/negative-impls/negative-default-impls.stderr b/src/test/ui/traits/negative-impls/negative-default-impls.stderr new file mode 100644 index 0000000000000..d2423d01a9afa --- /dev/null +++ b/src/test/ui/traits/negative-impls/negative-default-impls.stderr @@ -0,0 +1,9 @@ +error[E0750]: negative impls cannot be default impls + --> $DIR/negative-default-impls.rs:8:14 + | +LL | default impl !MyTrait for u32 {} + | ^^^^^^^ ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0750`. diff --git a/src/test/ui/traits/negative-impls/negative-impls-basic.rs b/src/test/ui/traits/negative-impls/negative-impls-basic.rs new file mode 100644 index 0000000000000..474e0381799bd --- /dev/null +++ b/src/test/ui/traits/negative-impls/negative-impls-basic.rs @@ -0,0 +1,17 @@ +// A simple test that we are able to create negative impls, when the +// feature gate is given. +// +// run-pass + +#![feature(negative_impls)] +#![allow(dead_code)] + +struct TestType; + +trait TestTrait { + fn dummy(&self) {} +} + +impl !TestTrait for TestType {} + +fn main() {} diff --git a/src/test/ui/traits/negative-impls/negative-specializes-negative.rs b/src/test/ui/traits/negative-impls/negative-specializes-negative.rs new file mode 100644 index 0000000000000..877c3e8af4f1a --- /dev/null +++ b/src/test/ui/traits/negative-impls/negative-specializes-negative.rs @@ -0,0 +1,13 @@ +#![feature(specialization)] +#![feature(negative_impls)] + +// Test a negative impl that "specializes" another negative impl. +// +// run-pass + +trait MyTrait {} + +impl !MyTrait for T {} +impl !MyTrait for u32 {} + +fn main() {} diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs new file mode 100644 index 0000000000000..043273e624189 --- /dev/null +++ b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs @@ -0,0 +1,13 @@ +#![feature(specialization)] +#![feature(negative_impls)] + +// Negative impl for u32 cannot "specialize" the base impl. +trait MyTrait { + fn foo(); +} +impl MyTrait for T { + default fn foo() {} +} +impl !MyTrait for u32 {} //~ ERROR E0748 + +fn main() {} diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr new file mode 100644 index 0000000000000..21fd08251d474 --- /dev/null +++ b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr @@ -0,0 +1,12 @@ +error[E0748]: found both positive and negative implementation of trait `MyTrait` for type `u32`: + --> $DIR/negative-specializes-positive-item.rs:11:1 + | +LL | impl MyTrait for T { + | --------------------- positive implementation here +... +LL | impl !MyTrait for u32 {} + | ^^^^^^^^^^^^^^^^^^^^^ negative implementation here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0748`. diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive.rs b/src/test/ui/traits/negative-impls/negative-specializes-positive.rs new file mode 100644 index 0000000000000..ac0fac10eef50 --- /dev/null +++ b/src/test/ui/traits/negative-impls/negative-specializes-positive.rs @@ -0,0 +1,14 @@ +#![feature(specialization)] +#![feature(negative_impls)] + +// Negative impl for u32 cannot "specialize" the base impl. +trait MyTrait {} +impl MyTrait for T {} +impl !MyTrait for u32 {} //~ ERROR E0748 + +// The second impl specializes the first, no error. +trait MyTrait2 {} +impl MyTrait2 for T {} +impl MyTrait2 for u32 {} + +fn main() {} diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr b/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr new file mode 100644 index 0000000000000..0e7426c826028 --- /dev/null +++ b/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr @@ -0,0 +1,11 @@ +error[E0748]: found both positive and negative implementation of trait `MyTrait` for type `u32`: + --> $DIR/negative-specializes-positive.rs:7:1 + | +LL | impl MyTrait for T {} + | --------------------- positive implementation here +LL | impl !MyTrait for u32 {} + | ^^^^^^^^^^^^^^^^^^^^^ negative implementation here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0748`. diff --git a/src/test/ui/traits/negative-impls/no-items.rs b/src/test/ui/traits/negative-impls/no-items.rs new file mode 100644 index 0000000000000..5fc6be9b30007 --- /dev/null +++ b/src/test/ui/traits/negative-impls/no-items.rs @@ -0,0 +1,11 @@ +#![feature(negative_impls)] + +trait MyTrait { + type Foo; +} + +impl !MyTrait for u32 { + type Foo = i32; //~ ERROR negative impls cannot have any items +} + +fn main() {} diff --git a/src/test/ui/traits/negative-impls/no-items.stderr b/src/test/ui/traits/negative-impls/no-items.stderr new file mode 100644 index 0000000000000..67b94bba12143 --- /dev/null +++ b/src/test/ui/traits/negative-impls/no-items.stderr @@ -0,0 +1,9 @@ +error[E0749]: negative impls cannot have any items + --> $DIR/no-items.rs:8:5 + | +LL | type Foo = i32; + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0749`. diff --git a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs new file mode 100644 index 0000000000000..d9c498fca6645 --- /dev/null +++ b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs @@ -0,0 +1,26 @@ +use std::cell::Cell; +use std::marker::PhantomPinned; +use std::pin::Pin; + +struct MyType<'a>(Cell>>, PhantomPinned); + +impl<'a> Clone for &'a mut MyType<'a> { + //~^ ERROR E0748 + fn clone(&self) -> &'a mut MyType<'a> { + self.0.replace(None).unwrap() + } +} + +fn main() { + let mut unpinned = MyType(Cell::new(None), PhantomPinned); + let bad_addr = &unpinned as *const MyType<'_> as usize; + let mut p = Box::pin(MyType(Cell::new(Some(&mut unpinned)), PhantomPinned)); + + // p_mut1 is okay: it does not point to the bad_addr + let p_mut1: Pin<&mut MyType<'_>> = p.as_mut(); + assert_ne!(bad_addr, &*p_mut1 as *const _ as usize); + + // but p_mut2 does point to bad_addr! this is unsound + let p_mut2: Pin<&mut MyType<'_>> = p_mut1.clone(); + assert_eq!(bad_addr, &*p_mut2 as *const _ as usize); +} diff --git a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr new file mode 100644 index 0000000000000..f3305722cf2d3 --- /dev/null +++ b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr @@ -0,0 +1,11 @@ +error[E0748]: found both positive and negative implementation of trait `std::clone::Clone` for type `&mut MyType<'_>`: + --> $DIR/pin-unsound-issue-66544-clone.rs:7:1 + | +LL | impl<'a> Clone for &'a mut MyType<'a> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ positive implementation here + | + = note: negative implementation in crate `core` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0748`. diff --git a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs new file mode 100644 index 0000000000000..cc27c301ffa9d --- /dev/null +++ b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs @@ -0,0 +1,33 @@ +// Demonstrate that "rogue" `DerefMut` impls for `&T` are not allowed. +// +// https://github.com/rust-lang/rust/issues/66544 + +use std::cell::Cell; +use std::marker::PhantomPinned; +use std::ops::DerefMut; +use std::pin::Pin; + +struct MyType<'a>(Cell>>, PhantomPinned); + +impl<'a> DerefMut for &'a MyType<'a> { + //~^ ERROR E0748 + fn deref_mut(&mut self) -> &mut MyType<'a> { + self.0.replace(None).unwrap() + } +} + +fn main() { + let mut unpinned = MyType(Cell::new(None), PhantomPinned); + let bad_addr = &unpinned as *const MyType<'_> as usize; + let p = Box::pin(MyType(Cell::new(Some(&mut unpinned)), PhantomPinned)); + + // p_ref is okay: it does not point to the bad_addr + let mut p_ref: Pin<&MyType<'_>> = p.as_ref(); + assert_ne!(bad_addr, &*p_ref as *const _ as usize); + + // but p_mut does point to bad_addr! this is unsound + let p_mut: Pin<&mut MyType<'_>> = p_ref.as_mut(); + assert_eq!(bad_addr, &*p_mut as *const _ as usize); + + println!("oh no!"); +} diff --git a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr new file mode 100644 index 0000000000000..4e71c2468246b --- /dev/null +++ b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr @@ -0,0 +1,11 @@ +error[E0748]: found both positive and negative implementation of trait `std::ops::DerefMut` for type `&MyType<'_>`: + --> $DIR/pin-unsound-issue-66544-derefmut.rs:12:1 + | +LL | impl<'a> DerefMut for &'a MyType<'a> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ positive implementation here + | + = note: negative implementation in crate `core` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0748`. diff --git a/src/test/ui/traits/negative-impls/positive-specializes-negative.rs b/src/test/ui/traits/negative-impls/positive-specializes-negative.rs new file mode 100644 index 0000000000000..eac4c24d5d3d0 --- /dev/null +++ b/src/test/ui/traits/negative-impls/positive-specializes-negative.rs @@ -0,0 +1,9 @@ +#![feature(specialization)] +#![feature(negative_impls)] + +trait MyTrait {} + +impl !MyTrait for T {} +impl MyTrait for u32 {} //~ ERROR E0748 + +fn main() {} diff --git a/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr b/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr new file mode 100644 index 0000000000000..ab371945a7eab --- /dev/null +++ b/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr @@ -0,0 +1,11 @@ +error[E0748]: found both positive and negative implementation of trait `MyTrait` for type `u32`: + --> $DIR/positive-specializes-negative.rs:7:1 + | +LL | impl !MyTrait for T {} + | ---------------------- negative implementation here +LL | impl MyTrait for u32 {} + | ^^^^^^^^^^^^^^^^^^^^ positive implementation here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0748`. diff --git a/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs b/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs new file mode 100644 index 0000000000000..db72aaf18034f --- /dev/null +++ b/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs @@ -0,0 +1,21 @@ +#![feature(negative_impls)] + +// aux-build: foreign_trait.rs + +// Test that we cannot implement `LocalTrait` for `String`, +// even though there is a `String: !ForeignTrait` impl. +// +// This may not be the behavior we want long term, but it's the +// current semantics that we implemented so as to land `!Foo` impls +// quickly. See internals thread: +// +// https://internals.rust-lang.org/t/foo/11587/ + +extern crate foreign_trait; +use foreign_trait::ForeignTrait; + +trait LocalTrait { } +impl LocalTrait for T { } +impl LocalTrait for String { } //~ ERROR conflicting implementations + +fn main() { } diff --git a/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.stderr b/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.stderr new file mode 100644 index 0000000000000..7cce45d2c8f8f --- /dev/null +++ b/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.stderr @@ -0,0 +1,11 @@ +error[E0119]: conflicting implementations of trait `LocalTrait` for type `std::string::String`: + --> $DIR/rely-on-negative-impl-in-coherence.rs:19:1 + | +LL | impl LocalTrait for T { } + | -------------------------------------- first implementation here +LL | impl LocalTrait for String { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `std::string::String` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/traits/overlap-not-permitted-for-builtin-trait.rs b/src/test/ui/traits/overlap-not-permitted-for-builtin-trait.rs index 86029473b513b..4106f56d64ac6 100644 --- a/src/test/ui/traits/overlap-not-permitted-for-builtin-trait.rs +++ b/src/test/ui/traits/overlap-not-permitted-for-builtin-trait.rs @@ -1,5 +1,5 @@ #![allow(dead_code)] -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] // Overlapping negative impls for `MyStruct` are not permitted: struct MyStruct; @@ -7,5 +7,4 @@ impl !Send for MyStruct {} impl !Send for MyStruct {} //~^ ERROR conflicting implementations of trait -fn main() { -} +fn main() {} diff --git a/src/test/ui/traits/overlap-permitted-for-marker-traits.rs b/src/test/ui/traits/overlap-permitted-for-marker-traits.rs new file mode 100644 index 0000000000000..00823d13b3696 --- /dev/null +++ b/src/test/ui/traits/overlap-permitted-for-marker-traits.rs @@ -0,0 +1,28 @@ +// run-pass +// Tests for RFC 1268: we allow overlapping impls of marker traits, +// that is, traits without items. In this case, a type `T` is +// `MyMarker` if it is either `Debug` or `Display`. + +#![feature(marker_trait_attr)] +#![feature(negative_impls)] + +use std::fmt::{Debug, Display}; + +#[marker] +trait MyMarker {} + +impl MyMarker for T {} +impl MyMarker for T {} + +fn foo(t: T) -> T { + t +} + +fn main() { + // Debug && Display: + assert_eq!(1, foo(1)); + assert_eq!(2.0, foo(2.0)); + + // Debug && !Display: + assert_eq!(vec![1], foo(vec![1])); +} diff --git a/src/test/ui/traits/syntax-trait-polarity.rs b/src/test/ui/traits/syntax-trait-polarity.rs index c6524f5c8e782..c809f9e89f934 100644 --- a/src/test/ui/traits/syntax-trait-polarity.rs +++ b/src/test/ui/traits/syntax-trait-polarity.rs @@ -2,7 +2,7 @@ #![allow(dead_code)] // pretty-expanded FIXME #23616 -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] struct TestType; diff --git a/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.stderr b/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.stderr index 6de79fa917b16..594115d980c8b 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.stderr +++ b/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.stderr @@ -12,3 +12,4 @@ LL | type _T1 = dyn _2; error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0224`. diff --git a/src/test/ui/traits/trait-impl-for-module.stderr b/src/test/ui/traits/trait-impl-for-module.stderr index 4b3c930dccd45..cd2713a5bd50c 100644 --- a/src/test/ui/traits/trait-impl-for-module.stderr +++ b/src/test/ui/traits/trait-impl-for-module.stderr @@ -1,12 +1,11 @@ error[E0573]: expected type, found module `a` --> $DIR/trait-impl-for-module.rs:7:12 | -LL | / trait A { -LL | | } - | |_- similarly named trait `A` defined here -LL | -LL | impl A for a { - | ^ help: a trait with a similar name exists: `A` +LL | trait A { + | ------- similarly named trait `A` defined here +... +LL | impl A for a { + | ^ help: a trait with a similar name exists: `A` error: aborting due to previous error diff --git a/src/test/ui/traits/trait-item-privacy.rs b/src/test/ui/traits/trait-item-privacy.rs index 8507d8ef17e36..1ea1d65df627c 100644 --- a/src/test/ui/traits/trait-item-privacy.rs +++ b/src/test/ui/traits/trait-item-privacy.rs @@ -69,7 +69,7 @@ fn check_method() { S.c(); // OK // a, b, c are resolved as inherent items, their traits don't need to be in scope let c = &S as &dyn C; - c.a(); //~ ERROR method `a` is private + c.a(); //~ ERROR associated function `a` is private c.b(); // OK c.c(); // OK @@ -81,7 +81,7 @@ fn check_method() { //~^ ERROR no function or associated item named `b` found S::c(&S); // OK // a, b, c are resolved as inherent items, their traits don't need to be in scope - C::a(&S); //~ ERROR method `a` is private + C::a(&S); //~ ERROR associated function `a` is private C::b(&S); // OK C::c(&S); // OK } diff --git a/src/test/ui/traits/trait-item-privacy.stderr b/src/test/ui/traits/trait-item-privacy.stderr index 2c0591c95f690..7fd5c11fcf090 100644 --- a/src/test/ui/traits/trait-item-privacy.stderr +++ b/src/test/ui/traits/trait-item-privacy.stderr @@ -36,11 +36,11 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f LL | use method::B; | -error[E0624]: method `a` is private +error[E0624]: associated function `a` is private --> $DIR/trait-item-privacy.rs:72:7 | LL | c.a(); - | ^ + | ^ private associated function error[E0599]: no function or associated item named `a` found for struct `S` in the current scope --> $DIR/trait-item-privacy.rs:78:8 @@ -73,11 +73,11 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f LL | use method::B; | -error[E0624]: method `a` is private - --> $DIR/trait-item-privacy.rs:84:5 +error[E0624]: associated function `a` is private + --> $DIR/trait-item-privacy.rs:84:8 | LL | C::a(&S); - | ^^^^ + | ^ private associated function error[E0599]: no associated item named `A` found for struct `S` in the current scope --> $DIR/trait-item-privacy.rs:97:8 @@ -111,10 +111,10 @@ LL | use assoc_const::B; | error[E0624]: associated constant `A` is private - --> $DIR/trait-item-privacy.rs:101:5 + --> $DIR/trait-item-privacy.rs:101:8 | LL | C::A; - | ^^^^ + | ^ private associated constant error[E0038]: the trait `assoc_const::C` cannot be made into an object --> $DIR/trait-item-privacy.rs:101:5 @@ -159,13 +159,13 @@ error: associated type `A` is private --> $DIR/trait-item-privacy.rs:119:12 | LL | let _: T::A; - | ^^^^ + | ^^^^ private associated type error: associated type `A` is private --> $DIR/trait-item-privacy.rs:128:9 | LL | A = u8, - | ^^^^^^ + | ^^^^^^ private associated type error: aborting due to 15 previous errors diff --git a/src/test/ui/traits/trait-method-private.stderr b/src/test/ui/traits/trait-method-private.stderr index 10552acb348be..c33673aea4d79 100644 --- a/src/test/ui/traits/trait-method-private.stderr +++ b/src/test/ui/traits/trait-method-private.stderr @@ -1,8 +1,8 @@ -error[E0624]: method `method` is private +error[E0624]: associated function `method` is private --> $DIR/trait-method-private.rs:19:9 | LL | foo.method(); - | ^^^^^^ + | ^^^^^^ private associated function | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope; perhaps add a `use` for it: diff --git a/src/test/ui/traits/trait-object-macro-matcher.stderr b/src/test/ui/traits/trait-object-macro-matcher.stderr index a8511f63c16a5..cb48bd1258ea2 100644 --- a/src/test/ui/traits/trait-object-macro-matcher.stderr +++ b/src/test/ui/traits/trait-object-macro-matcher.stderr @@ -14,4 +14,5 @@ LL | m!(dyn Copy + Send + 'static); error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0038`. +Some errors have detailed explanations: E0038, E0224. +For more information about an error, try `rustc --explain E0038`. diff --git a/src/test/ui/traits/trait-object-vs-lifetime-2.stderr b/src/test/ui/traits/trait-object-vs-lifetime-2.stderr index 014d380b63ca5..28b8e11f1330c 100644 --- a/src/test/ui/traits/trait-object-vs-lifetime-2.stderr +++ b/src/test/ui/traits/trait-object-vs-lifetime-2.stderr @@ -6,3 +6,4 @@ LL | dyn 'static +: 'static + Copy, error: aborting due to previous error +For more information about this error, try `rustc --explain E0224`. diff --git a/src/test/ui/traits/trait-object-vs-lifetime.stderr b/src/test/ui/traits/trait-object-vs-lifetime.stderr index 04529fb8cfab3..ff3fc2a197c66 100644 --- a/src/test/ui/traits/trait-object-vs-lifetime.stderr +++ b/src/test/ui/traits/trait-object-vs-lifetime.stderr @@ -32,5 +32,5 @@ LL | let _: S; error: aborting due to 5 previous errors -Some errors have detailed explanations: E0107, E0747. +Some errors have detailed explanations: E0107, E0224, E0747. For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.rs b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.rs index c65242b1bb1c3..571f934fc5bc7 100644 --- a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.rs +++ b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.rs @@ -3,6 +3,7 @@ // to be synthesized. #![feature(optin_builtin_traits)] +#![feature(negative_impls)] auto trait Magic: Copy {} //~ ERROR E0568 diff --git a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr index a83ff3701511d..f44986da0e230 100644 --- a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr +++ b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr @@ -1,5 +1,5 @@ error[E0568]: auto traits cannot have super traits - --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:7:19 + --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:8:19 | LL | auto trait Magic: Copy {} | ----- ^^^^ help: remove the super traits @@ -7,7 +7,7 @@ LL | auto trait Magic: Copy {} | auto trait cannot have super traits error[E0277]: the trait bound `NoClone: std::marker::Copy` is not satisfied - --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:15:23 + --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:16:23 | LL | fn copy(x: T) -> (T, T) { (x, x) } | ---- ----- required by this bound in `copy` diff --git a/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr b/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr index 8cc97addc7dd4..482410886329e 100644 --- a/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr +++ b/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr @@ -12,3 +12,4 @@ LL | type _0 = dyn ?Sized; error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0224`. diff --git a/src/test/ui/transmute/main.stderr b/src/test/ui/transmute/main.stderr index c72876e050f05..4e781318329bf 100644 --- a/src/test/ui/transmute/main.stderr +++ b/src/test/ui/transmute/main.stderr @@ -4,8 +4,7 @@ error[E0512]: cannot transmute between types of different sizes, or dependently- LL | transmute(x) | ^^^^^^^^^ | - = note: source type: `>::T` (size can vary because of ::T) - = note: target type: `>::T` (size can vary because of ::T) + = note: `::T` does not have a fixed size error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/main.rs:20:17 diff --git a/src/test/ui/try-block/try-block-in-edition2015.stderr b/src/test/ui/try-block/try-block-in-edition2015.stderr index 9b4fe2c1205db..fe870ab737cc8 100644 --- a/src/test/ui/try-block/try-block-in-edition2015.stderr +++ b/src/test/ui/try-block/try-block-in-edition2015.stderr @@ -11,9 +11,13 @@ error[E0574]: expected struct, variant or union type, found macro `try` --> $DIR/try-block-in-edition2015.rs:4:33 | LL | let try_result: Option<_> = try { - | ^^^ help: use `!` to invoke the macro: `try!` + | ^^^ | = note: if you want the `try` keyword, you need to be in the 2018 edition +help: use `!` to invoke the macro + | +LL | let try_result: Option<_> = try! { + | ^ error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs b/src/test/ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs new file mode 100644 index 0000000000000..8e8508cdd6f30 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs @@ -0,0 +1,28 @@ +// check-pass +// Regression test for issue #55099 +// Tests that we don't incorrectly consider a lifetime to part +// of the concrete type + +#![feature(type_alias_impl_trait)] + +trait Future { +} + +struct AndThen(F); + +impl Future for AndThen { +} + +struct Foo<'a> { + x: &'a mut (), +} + +type F = impl Future; + +impl<'a> Foo<'a> { + fn reply(&mut self) -> F { + AndThen(|| ()) + } +} + +fn main() {} diff --git a/src/test/ui/type-inference/or_else-multiple-type-params.stderr b/src/test/ui/type-inference/or_else-multiple-type-params.stderr index b9258b20f5add..047728dc1ea4e 100644 --- a/src/test/ui/type-inference/or_else-multiple-type-params.stderr +++ b/src/test/ui/type-inference/or_else-multiple-type-params.stderr @@ -2,10 +2,12 @@ error[E0282]: type annotations needed --> $DIR/or_else-multiple-type-params.rs:7:10 | LL | .or_else(|err| { - | ^^^^^^^ - | | - | cannot infer type for type parameter `F` declared on the method `or_else` - | help: consider specifying the type arguments in the method call: `or_else::` + | ^^^^^^^ cannot infer type for type parameter `F` declared on the associated function `or_else` + | +help: consider specifying the type arguments in the method call + | +LL | .or_else::(|err| { + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/type-inference/sort_by_key.stderr b/src/test/ui/type-inference/sort_by_key.stderr index e74c0dfa5e20c..0b6630ec89423 100644 --- a/src/test/ui/type-inference/sort_by_key.stderr +++ b/src/test/ui/type-inference/sort_by_key.stderr @@ -2,9 +2,12 @@ error[E0282]: type annotations needed --> $DIR/sort_by_key.rs:3:9 | LL | lst.sort_by_key(|&(v, _)| v.iter().sum()); - | ^^^^^^^^^^^ --- help: consider specifying the type argument in the method call: `sum::` - | | - | cannot infer type for type parameter `K` declared on the method `sort_by_key` + | ^^^^^^^^^^^ cannot infer type for type parameter `K` declared on the associated function `sort_by_key` + | +help: consider specifying the type argument in the method call + | +LL | lst.sort_by_key(|&(v, _)| v.iter().sum::()); + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/type-sizes.rs b/src/test/ui/type-sizes.rs index 27433fd770b05..1d332cc3bf7ba 100644 --- a/src/test/ui/type-sizes.rs +++ b/src/test/ui/type-sizes.rs @@ -74,6 +74,11 @@ enum NicheFilledEnumWithAbsentVariant { C, } +enum Option2 { + Some(A, B), + None +} + pub fn main() { assert_eq!(size_of::(), 1 as usize); assert_eq!(size_of::(), 4 as usize); @@ -113,4 +118,6 @@ pub fn main() { assert_eq!(size_of::>>(), size_of::<(bool, &())>()); assert_eq!(size_of::>>(), size_of::<(bool, &())>()); + assert_eq!(size_of::>>(), size_of::<(bool, &())>()); + assert_eq!(size_of::>>(), size_of::<(bool, &())>()); } diff --git a/src/test/ui/type/ascription/issue-47666.rs b/src/test/ui/type/ascription/issue-47666.rs index ceb1dd89daea9..8035de4a48a92 100644 --- a/src/test/ui/type/ascription/issue-47666.rs +++ b/src/test/ui/type/ascription/issue-47666.rs @@ -1,5 +1,7 @@ fn main() { let _ = Option:Some(vec![0, 1]); //~ ERROR expected type, found + //~^ ERROR expected value, found enum `Option` + //~| ERROR expected type, found variant `Some` } // This case isn't currently being handled gracefully due to the macro invocation. diff --git a/src/test/ui/type/ascription/issue-47666.stderr b/src/test/ui/type/ascription/issue-47666.stderr index f4c9240ab5372..3cd3be70aa75b 100644 --- a/src/test/ui/type/ascription/issue-47666.stderr +++ b/src/test/ui/type/ascription/issue-47666.stderr @@ -13,5 +13,35 @@ LL | let _ = Option:Some(vec![0, 1]); = note: see issue #23416 for more information = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error[E0423]: expected value, found enum `Option` + --> $DIR/issue-47666.rs:2:13 + | +LL | let _ = Option:Some(vec![0, 1]); + | ^^^^^^ + | +help: try using one of the enum's variants + | +LL | let _ = std::option::Option::None:Some(vec![0, 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _ = std::option::Option::Some:Some(vec![0, 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0573]: expected type, found variant `Some` + --> $DIR/issue-47666.rs:2:20 + | +LL | let _ = Option:Some(vec![0, 1]); + | ^^^^^^^^^^^^^^^^ not a type + | +help: try using the variant's enum + | +LL | let _ = Option:std::option::Option; + | ^^^^^^^^^^^^^^^^^^^ +help: maybe you meant to write a path separator here + | +LL | let _ = Option::Some(vec![0, 1]); + | ^^ + +error: aborting due to 3 previous errors +Some errors have detailed explanations: E0423, E0573. +For more information about an error, try `rustc --explain E0423`. diff --git a/src/test/ui/type/type-annotation-needed.stderr b/src/test/ui/type/type-annotation-needed.stderr index c6a811e836342..df7d73d7a7c1d 100644 --- a/src/test/ui/type/type-annotation-needed.stderr +++ b/src/test/ui/type/type-annotation-needed.stderr @@ -5,12 +5,13 @@ LL | fn foo>(x: i32) {} | --- ------------ required by this bound in `foo` ... LL | foo(42); - | ^^^ - | | - | cannot infer type for type parameter `T` declared on the function `foo` - | help: consider specifying the type argument in the function call: `foo::` + | ^^^ cannot infer type for type parameter `T` declared on the function `foo` | = note: cannot resolve `_: std::convert::Into` +help: consider specifying the type argument in the function call + | +LL | foo::(42); + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.rs b/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.rs index 92d8ba887270e..8824a6d2767f7 100644 --- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.rs +++ b/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.rs @@ -1,4 +1,5 @@ #![feature(optin_builtin_traits)] +#![feature(negative_impls)] auto trait Magic : Sized where Option : Magic {} //~ ERROR E0568 impl Magic for T {} diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr b/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr index e397629327754..63b3300f6dbf4 100644 --- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr +++ b/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr @@ -1,5 +1,5 @@ error[E0568]: auto traits cannot have super traits - --> $DIR/typeck-auto-trait-no-supertraits-2.rs:3:20 + --> $DIR/typeck-auto-trait-no-supertraits-2.rs:4:20 | LL | auto trait Magic : Sized where Option : Magic {} | ----- ^^^^^ help: remove the super traits diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.rs b/src/test/ui/typeck/typeck-auto-trait-no-supertraits.rs index e48017acfc718..edbca91512486 100644 --- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.rs +++ b/src/test/ui/typeck/typeck-auto-trait-no-supertraits.rs @@ -23,6 +23,7 @@ // } #![feature(optin_builtin_traits)] +#![feature(negative_impls)] auto trait Magic: Copy {} //~ ERROR E0568 impl Magic for T {} diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr b/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr index b1602e3642ecb..796638fc54dce 100644 --- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr +++ b/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr @@ -1,5 +1,5 @@ error[E0568]: auto traits cannot have super traits - --> $DIR/typeck-auto-trait-no-supertraits.rs:27:19 + --> $DIR/typeck-auto-trait-no-supertraits.rs:28:19 | LL | auto trait Magic: Copy {} | ----- ^^^^ help: remove the super traits diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.rs b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.rs index 6c170fb5bae7d..71ac2b466c10a 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.rs +++ b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.rs @@ -1,4 +1,5 @@ #![feature(optin_builtin_traits)] +#![feature(negative_impls)] auto trait MyTrait {} diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr index f060afea24e7f..23401ca308676 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `MyS2: MyTrait` is not satisfied in `(MyS2, MyS)` - --> $DIR/typeck-default-trait-impl-constituent-types-2.rs:16:5 + --> $DIR/typeck-default-trait-impl-constituent-types-2.rs:17:5 | LL | fn is_mytrait() {} | ---------- ------- required by this bound in `is_mytrait` diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.rs b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.rs index d72f676121875..6483b9213dc53 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.rs +++ b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.rs @@ -1,4 +1,5 @@ #![feature(optin_builtin_traits)] +#![feature(negative_impls)] auto trait MyTrait {} diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr index 22a2cb3e0ecb8..a30b29a3893cc 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `MyS2: MyTrait` is not satisfied - --> $DIR/typeck-default-trait-impl-constituent-types.rs:20:18 + --> $DIR/typeck-default-trait-impl-constituent-types.rs:21:18 | LL | fn is_mytrait() {} | ---------- ------- required by this bound in `is_mytrait` diff --git a/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.rs b/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.rs index 212e165151d81..772ac322032ec 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.rs +++ b/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.rs @@ -3,7 +3,7 @@ // Test that we do not consider associated types to be sendable without // some applicable trait bound (and we don't ICE). -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] extern crate tdticc_coherence_lib as lib; diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation-send.rs b/src/test/ui/typeck/typeck-default-trait-impl-negation-send.rs index 617d0f3b565a8..3a2fc39d409d9 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-negation-send.rs +++ b/src/test/ui/typeck/typeck-default-trait-impl-negation-send.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] struct MySendable { t: *mut u8 diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.rs b/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.rs index e4487fb110cf1..2734b761e61b7 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.rs +++ b/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.rs @@ -1,4 +1,4 @@ -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] struct Managed; impl !Send for Managed {} diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation.rs b/src/test/ui/typeck/typeck-default-trait-impl-negation.rs index 0b6e13be6e108..47cab60625dce 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-negation.rs +++ b/src/test/ui/typeck/typeck-default-trait-impl-negation.rs @@ -1,4 +1,5 @@ #![feature(optin_builtin_traits)] +#![feature(negative_impls)] auto trait MyTrait {} diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr b/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr index 4b13fcc885a0d..e31bb81074469 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `ThisImplsUnsafeTrait: MyTrait` is not satisfied - --> $DIR/typeck-default-trait-impl-negation.rs:21:19 + --> $DIR/typeck-default-trait-impl-negation.rs:22:19 | LL | fn is_my_trait() {} | ----------- ------- required by this bound in `is_my_trait` @@ -11,7 +11,7 @@ LL | is_my_trait::(); error[E0277]: the trait bound `ThisImplsTrait: MyUnsafeTrait` is not satisfied - --> $DIR/typeck-default-trait-impl-negation.rs:24:26 + --> $DIR/typeck-default-trait-impl-negation.rs:25:26 | LL | fn is_my_unsafe_trait() {} | ------------------ ------------- required by this bound in `is_my_unsafe_trait` diff --git a/src/test/ui/typeck/typeck-default-trait-impl-precedence.rs b/src/test/ui/typeck/typeck-default-trait-impl-precedence.rs index 9b228f706465b..614a5ff55b1ed 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-precedence.rs +++ b/src/test/ui/typeck/typeck-default-trait-impl-precedence.rs @@ -4,6 +4,7 @@ // impls whose types unify. #![feature(optin_builtin_traits)] +#![feature(negative_impls)] auto trait Defaulted { } impl<'a,T:Signed> Defaulted for &'a T { } diff --git a/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr b/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr index 1587730441820..0d256094c60e0 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `u32: Signed` is not satisfied - --> $DIR/typeck-default-trait-impl-precedence.rs:18:5 + --> $DIR/typeck-default-trait-impl-precedence.rs:19:5 | LL | fn is_defaulted() { } | ------------ --------- required by this bound in `is_defaulted` diff --git a/src/test/ui/typeck/typeck-negative-impls-builtin.rs b/src/test/ui/typeck/typeck-negative-impls-builtin.rs deleted file mode 100644 index 7bdd1035a1bf2..0000000000000 --- a/src/test/ui/typeck/typeck-negative-impls-builtin.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![feature(optin_builtin_traits)] - -struct TestType; - -trait TestTrait { - fn dummy(&self) { } -} - -impl !TestTrait for TestType {} -//~^ ERROR negative impls are only allowed for auto traits (e.g., `Send` and `Sync`) - -fn main() {} diff --git a/src/test/ui/typeck/typeck-negative-impls-builtin.stderr b/src/test/ui/typeck/typeck-negative-impls-builtin.stderr deleted file mode 100644 index 4e3d054ff6fad..0000000000000 --- a/src/test/ui/typeck/typeck-negative-impls-builtin.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0192]: negative impls are only allowed for auto traits (e.g., `Send` and `Sync`) - --> $DIR/typeck-negative-impls-builtin.rs:9:1 - | -LL | impl !TestTrait for TestType {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0192`. diff --git a/src/test/ui/typeck/typeck-unsafe-always-share.rs b/src/test/ui/typeck/typeck-unsafe-always-share.rs index 7d1ff732983fe..dc5ddf5156302 100644 --- a/src/test/ui/typeck/typeck-unsafe-always-share.rs +++ b/src/test/ui/typeck/typeck-unsafe-always-share.rs @@ -1,6 +1,6 @@ // Verify that UnsafeCell is *always* !Sync regardless if `T` is sync. -#![feature(optin_builtin_traits)] +#![feature(negative_impls)] use std::cell::UnsafeCell; use std::marker::Sync; diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.rs b/src/test/ui/typeck/typeck_type_placeholder_item.rs index 6cd2b8c75b639..99a7023089283 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.rs +++ b/src/test/ui/typeck/typeck_type_placeholder_item.rs @@ -32,7 +32,6 @@ fn test7(x: _) { let _x: usize = x; } fn test8(_f: fn() -> _) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures struct Test9; @@ -99,7 +98,6 @@ pub fn main() { fn fn_test8(_f: fn() -> _) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures struct FnTest9; @@ -158,12 +156,9 @@ trait BadTrait<_> {} //~^ ERROR expected identifier, found reserved identifier `_` impl BadTrait<_> for BadStruct<_> {} //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn impl_trait() -> impl BadTrait<_> { //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures unimplemented!() } @@ -178,14 +173,12 @@ struct BadStruct2<_, T>(_, T); type X = Box<_>; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures struct Struct; trait Trait {} impl Trait for Struct {} type Y = impl Trait<_>; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn foo() -> Y { Struct } diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr index f2d02f70f4a66..db67e0c9b7d98 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr @@ -1,35 +1,35 @@ error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:154:18 + --> $DIR/typeck_type_placeholder_item.rs:152:18 | LL | struct BadStruct<_>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:157:16 + --> $DIR/typeck_type_placeholder_item.rs:155:16 | LL | trait BadTrait<_> {} | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:170:19 + --> $DIR/typeck_type_placeholder_item.rs:165:19 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:170:22 + --> $DIR/typeck_type_placeholder_item.rs:165:22 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:175:19 + --> $DIR/typeck_type_placeholder_item.rs:170:19 | LL | struct BadStruct2<_, T>(_, T); | ^ expected identifier, found reserved identifier error: associated constant in `impl` without body - --> $DIR/typeck_type_placeholder_item.rs:208:5 + --> $DIR/typeck_type_placeholder_item.rs:201:5 | LL | const C: _; | ^^^^^^^^^^- @@ -37,7 +37,7 @@ LL | const C: _; | help: provide a definition for the constant: `= ;` error[E0403]: the name `_` is already used for a generic parameter in this item's generic parameters - --> $DIR/typeck_type_placeholder_item.rs:170:22 + --> $DIR/typeck_type_placeholder_item.rs:165:22 | LL | struct BadStruct1<_, _>(_); | - ^ already used @@ -70,7 +70,7 @@ LL | static TEST3: _ = "test"; | ^ | | | not allowed in type signatures - | help: replace `_` with the correct type: `&'static str` + | help: replace `_` with the correct type: `&str` error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item.rs:15:15 @@ -131,12 +131,6 @@ help: use type parameters instead LL | fn test7(x: T) { let _x: usize = x; } | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:33:22 - | -LL | fn test8(_f: fn() -> _) { } - | ^ not allowed in type signatures - error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item.rs:33:22 | @@ -149,7 +143,7 @@ LL | fn test8(_f: fn() -> T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:47:26 + --> $DIR/typeck_type_placeholder_item.rs:46:26 | LL | fn test11(x: &usize) -> &_ { | -^ @@ -158,7 +152,7 @@ LL | fn test11(x: &usize) -> &_ { | help: replace with the correct return type: `&&usize` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:52:52 + --> $DIR/typeck_type_placeholder_item.rs:51:52 | LL | unsafe fn test12(x: *const usize) -> *const *const _ { | --------------^ @@ -167,7 +161,7 @@ LL | unsafe fn test12(x: *const usize) -> *const *const _ { | help: replace with the correct return type: `*const *const usize` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:66:8 + --> $DIR/typeck_type_placeholder_item.rs:65:8 | LL | a: _, | ^ not allowed in type signatures @@ -186,13 +180,13 @@ LL | b: (T, T), | error: missing type for `static` item - --> $DIR/typeck_type_placeholder_item.rs:72:12 + --> $DIR/typeck_type_placeholder_item.rs:71:12 | LL | static A = 42; | ^ help: provide a type for the item: `A: i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:74:15 + --> $DIR/typeck_type_placeholder_item.rs:73:15 | LL | static B: _ = 42; | ^ @@ -201,13 +195,13 @@ LL | static B: _ = 42; | help: replace `_` with the correct type: `i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:76:15 + --> $DIR/typeck_type_placeholder_item.rs:75:15 | LL | static C: Option<_> = Some(42); | ^^^^^^^^^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:79:21 + --> $DIR/typeck_type_placeholder_item.rs:78:21 | LL | fn fn_test() -> _ { 5 } | ^ @@ -216,7 +210,7 @@ LL | fn fn_test() -> _ { 5 } | help: replace with the correct return type: `i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:82:23 + --> $DIR/typeck_type_placeholder_item.rs:81:23 | LL | fn fn_test2() -> (_, _) { (5, 5) } | -^--^- @@ -226,16 +220,16 @@ LL | fn fn_test2() -> (_, _) { (5, 5) } | help: replace with the correct return type: `(i32, i32)` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:85:22 + --> $DIR/typeck_type_placeholder_item.rs:84:22 | LL | static FN_TEST3: _ = "test"; | ^ | | | not allowed in type signatures - | help: replace `_` with the correct type: `&'static str` + | help: replace `_` with the correct type: `&str` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:88:22 + --> $DIR/typeck_type_placeholder_item.rs:87:22 | LL | static FN_TEST4: _ = 145; | ^ @@ -244,13 +238,13 @@ LL | static FN_TEST4: _ = 145; | help: replace `_` with the correct type: `i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:91:22 + --> $DIR/typeck_type_placeholder_item.rs:90:22 | LL | static FN_TEST5: (_, _) = (1, 2); | ^^^^^^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:94:20 + --> $DIR/typeck_type_placeholder_item.rs:93:20 | LL | fn fn_test6(_: _) { } | ^ not allowed in type signatures @@ -261,7 +255,7 @@ LL | fn fn_test6(_: T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:97:20 + --> $DIR/typeck_type_placeholder_item.rs:96:20 | LL | fn fn_test7(x: _) { let _x: usize = x; } | ^ not allowed in type signatures @@ -272,13 +266,7 @@ LL | fn fn_test7(x: T) { let _x: usize = x; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:100:29 - | -LL | fn fn_test8(_f: fn() -> _) { } - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:100:29 + --> $DIR/typeck_type_placeholder_item.rs:99:29 | LL | fn fn_test8(_f: fn() -> _) { } | ^ not allowed in type signatures @@ -289,7 +277,7 @@ LL | fn fn_test8(_f: fn() -> T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:123:12 + --> $DIR/typeck_type_placeholder_item.rs:121:12 | LL | a: _, | ^ not allowed in type signatures @@ -308,13 +296,13 @@ LL | b: (T, T), | error[E0282]: type annotations needed - --> $DIR/typeck_type_placeholder_item.rs:128:18 + --> $DIR/typeck_type_placeholder_item.rs:126:18 | LL | fn fn_test11(_: _) -> (_, _) { panic!() } | ^ cannot infer type error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:128:28 + --> $DIR/typeck_type_placeholder_item.rs:126:28 | LL | fn fn_test11(_: _) -> (_, _) { panic!() } | ^ ^ not allowed in type signatures @@ -322,7 +310,7 @@ LL | fn fn_test11(_: _) -> (_, _) { panic!() } | not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:132:30 + --> $DIR/typeck_type_placeholder_item.rs:130:30 | LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } | -^--^- @@ -332,7 +320,7 @@ LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } | help: replace with the correct return type: `(i32, i32)` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:135:33 + --> $DIR/typeck_type_placeholder_item.rs:133:33 | LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } | ------^- @@ -341,7 +329,7 @@ LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } | help: replace with the correct return type: `(i32, i32)` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:154:21 + --> $DIR/typeck_type_placeholder_item.rs:152:21 | LL | struct BadStruct<_>(_); | ^ not allowed in type signatures @@ -352,19 +340,7 @@ LL | struct BadStruct(T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:159:32 - | -LL | impl BadTrait<_> for BadStruct<_> {} - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:159:15 - | -LL | impl BadTrait<_> for BadStruct<_> {} - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:159:15 + --> $DIR/typeck_type_placeholder_item.rs:157:15 | LL | impl BadTrait<_> for BadStruct<_> {} | ^ ^ not allowed in type signatures @@ -377,13 +353,13 @@ LL | impl BadTrait for BadStruct {} | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:164:34 + --> $DIR/typeck_type_placeholder_item.rs:160:34 | LL | fn impl_trait() -> impl BadTrait<_> { | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:170:25 + --> $DIR/typeck_type_placeholder_item.rs:165:25 | LL | struct BadStruct1<_, _>(_); | ^ not allowed in type signatures @@ -394,7 +370,7 @@ LL | struct BadStruct1(T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:175:25 + --> $DIR/typeck_type_placeholder_item.rs:170:25 | LL | struct BadStruct2<_, T>(_, T); | ^ not allowed in type signatures @@ -405,19 +381,13 @@ LL | struct BadStruct2(K, T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:179:14 - | -LL | type X = Box<_>; - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:179:14 + --> $DIR/typeck_type_placeholder_item.rs:174:14 | LL | type X = Box<_>; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:43:27 + --> $DIR/typeck_type_placeholder_item.rs:42:27 | LL | fn test10(&self, _x : _) { } | ^ not allowed in type signatures @@ -428,7 +398,7 @@ LL | fn test10(&self, _x : T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:140:31 + --> $DIR/typeck_type_placeholder_item.rs:138:31 | LL | fn method_test1(&self, x: _); | ^ not allowed in type signatures @@ -439,7 +409,7 @@ LL | fn method_test1(&self, x: T); | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:142:31 + --> $DIR/typeck_type_placeholder_item.rs:140:31 | LL | fn method_test2(&self, x: _) -> _; | ^ ^ not allowed in type signatures @@ -452,7 +422,7 @@ LL | fn method_test2(&self, x: T) -> T; | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:144:31 + --> $DIR/typeck_type_placeholder_item.rs:142:31 | LL | fn method_test3(&self) -> _; | ^ not allowed in type signatures @@ -463,7 +433,7 @@ LL | fn method_test3(&self) -> T; | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:146:26 + --> $DIR/typeck_type_placeholder_item.rs:144:26 | LL | fn assoc_fn_test1(x: _); | ^ not allowed in type signatures @@ -474,7 +444,7 @@ LL | fn assoc_fn_test1(x: T); | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:148:26 + --> $DIR/typeck_type_placeholder_item.rs:146:26 | LL | fn assoc_fn_test2(x: _) -> _; | ^ ^ not allowed in type signatures @@ -487,7 +457,7 @@ LL | fn assoc_fn_test2(x: T) -> T; | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:150:28 + --> $DIR/typeck_type_placeholder_item.rs:148:28 | LL | fn assoc_fn_test3() -> _; | ^ not allowed in type signatures @@ -498,7 +468,7 @@ LL | fn assoc_fn_test3() -> T; | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:61:37 + --> $DIR/typeck_type_placeholder_item.rs:60:37 | LL | fn clone_from(&mut self, other: _) { *self = Test9; } | ^ not allowed in type signatures @@ -509,7 +479,7 @@ LL | fn clone_from(&mut self, other: T) { *self = Test9; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:110:34 + --> $DIR/typeck_type_placeholder_item.rs:108:34 | LL | fn fn_test10(&self, _x : _) { } | ^ not allowed in type signatures @@ -520,7 +490,7 @@ LL | fn fn_test10(&self, _x : T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:118:41 + --> $DIR/typeck_type_placeholder_item.rs:116:41 | LL | fn clone_from(&mut self, other: _) { *self = FnTest9; } | ^ not allowed in type signatures @@ -531,37 +501,25 @@ LL | fn clone_from(&mut self, other: T) { *self = FnTest9; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:164:34 - | -LL | fn impl_trait() -> impl BadTrait<_> { - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:186:21 - | -LL | type Y = impl Trait<_>; - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:186:21 + --> $DIR/typeck_type_placeholder_item.rs:180:21 | LL | type Y = impl Trait<_>; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:195:14 + --> $DIR/typeck_type_placeholder_item.rs:188:14 | LL | type B = _; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:197:14 + --> $DIR/typeck_type_placeholder_item.rs:190:14 | LL | const C: _; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:199:14 + --> $DIR/typeck_type_placeholder_item.rs:192:14 | LL | const D: _ = 42; | ^ @@ -570,7 +528,7 @@ LL | const D: _ = 42; | help: replace `_` with the correct type: `i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:40:24 + --> $DIR/typeck_type_placeholder_item.rs:39:24 | LL | fn test9(&self) -> _ { () } | ^ @@ -579,7 +537,7 @@ LL | fn test9(&self) -> _ { () } | help: replace with the correct return type: `()` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:58:24 + --> $DIR/typeck_type_placeholder_item.rs:57:24 | LL | fn clone(&self) -> _ { Test9 } | ^ @@ -588,7 +546,7 @@ LL | fn clone(&self) -> _ { Test9 } | help: replace with the correct return type: `Test9` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:107:31 + --> $DIR/typeck_type_placeholder_item.rs:105:31 | LL | fn fn_test9(&self) -> _ { () } | ^ @@ -597,7 +555,7 @@ LL | fn fn_test9(&self) -> _ { () } | help: replace with the correct return type: `()` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:115:28 + --> $DIR/typeck_type_placeholder_item.rs:113:28 | LL | fn clone(&self) -> _ { FnTest9 } | ^ @@ -606,25 +564,25 @@ LL | fn clone(&self) -> _ { FnTest9 } | help: replace with the correct return type: `main::FnTest9` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:204:14 + --> $DIR/typeck_type_placeholder_item.rs:197:14 | LL | type A = _; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:206:14 + --> $DIR/typeck_type_placeholder_item.rs:199:14 | LL | type B = _; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:208:14 + --> $DIR/typeck_type_placeholder_item.rs:201:14 | LL | const C: _; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:211:14 + --> $DIR/typeck_type_placeholder_item.rs:204:14 | LL | const D: _ = 42; | ^ @@ -632,7 +590,7 @@ LL | const D: _ = 42; | not allowed in type signatures | help: replace `_` with the correct type: `i32` -error: aborting due to 71 previous errors +error: aborting due to 64 previous errors Some errors have detailed explanations: E0121, E0282, E0403. For more information about an error, try `rustc --explain E0121`. diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.rs b/src/test/ui/ufcs/ufcs-partially-resolved.rs index e8c767b13e9cf..e6470aa6d64f0 100644 --- a/src/test/ui/ufcs/ufcs-partially-resolved.rs +++ b/src/test/ui/ufcs/ufcs-partially-resolved.rs @@ -49,8 +49,8 @@ fn main() { ::NN; //~ ERROR cannot find method or associated constant `NN` in `Tr::Y` ::NN; //~ ERROR failed to resolve: `Y` is a variant, not a module - let _: ::Z; //~ ERROR expected associated type, found method `Dr::Z` + let _: ::Z; //~ ERROR expected associated type, found associated function `Dr::Z` ::X; //~ ERROR expected method or associated constant, found associated type `Dr::X` - let _: ::Z::N; //~ ERROR expected associated type, found method `Dr::Z` + let _: ::Z::N; //~ ERROR expected associated type, found associated function `Dr::Z` ::X::N; //~ ERROR no associated item named `N` found for type `u16` } diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.stderr b/src/test/ui/ufcs/ufcs-partially-resolved.stderr index e5e6ed9fac911..3950dc9877cd8 100644 --- a/src/test/ui/ufcs/ufcs-partially-resolved.stderr +++ b/src/test/ui/ufcs/ufcs-partially-resolved.stderr @@ -35,10 +35,10 @@ error[E0576]: cannot find method or associated constant `N` in trait `Tr` --> $DIR/ufcs-partially-resolved.rs:22:17 | LL | fn Y() {} - | --------- similarly named method `Y` defined here + | ------ similarly named associated function `Y` defined here ... LL | ::N; - | ^ help: a method with a similar name exists: `Y` + | ^ help: an associated function with a similar name exists: `Y` error[E0576]: cannot find method or associated constant `N` in enum `E` --> $DIR/ufcs-partially-resolved.rs:23:16 @@ -166,7 +166,7 @@ error[E0576]: cannot find method or associated constant `NN` in `Tr::Y` LL | ::NN; | ^^ not found in `Tr::Y` -error[E0575]: expected associated type, found method `Dr::Z` +error[E0575]: expected associated type, found associated function `Dr::Z` --> $DIR/ufcs-partially-resolved.rs:52:12 | LL | type X = u16; @@ -181,16 +181,16 @@ error[E0575]: expected method or associated constant, found associated type `Dr: --> $DIR/ufcs-partially-resolved.rs:53:5 | LL | fn Z() {} - | --------- similarly named method `Z` defined here + | ------ similarly named associated function `Z` defined here ... LL | ::X; | ^^^^^^^^^^^^- | | - | help: a method with a similar name exists: `Z` + | help: an associated function with a similar name exists: `Z` | = note: can't use a type alias as a constructor -error[E0575]: expected associated type, found method `Dr::Z` +error[E0575]: expected associated type, found associated function `Dr::Z` --> $DIR/ufcs-partially-resolved.rs:54:12 | LL | type X = u16; diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.rs b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.rs index e804afcf9ed99..a959aaae05568 100644 --- a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.rs +++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.rs @@ -1,3 +1,8 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl + use std::mem::zeroed; enum Void {} diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr index a667e1fe2da3a..9245e293caa85 100644 --- a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr +++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr @@ -1,13 +1,18 @@ error[E0004]: non-exhaustive patterns: `Err(_)` not covered - --> $DIR/uninhabited-matches-feature-gated.rs:6:19 + --> $DIR/uninhabited-matches-feature-gated.rs:11:19 | LL | let _ = match x { | ^ pattern `Err(_)` not covered + | + ::: $SRC_DIR/libcore/result.rs:LL:COL + | +LL | Err(#[stable(feature = "rust1", since = "1.0.0")] E), + | --- not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: type `&Void` is non-empty - --> $DIR/uninhabited-matches-feature-gated.rs:15:19 + --> $DIR/uninhabited-matches-feature-gated.rs:20:19 | LL | enum Void {} | ------------ `Void` defined here @@ -18,7 +23,7 @@ LL | let _ = match x {}; = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: type `(Void,)` is non-empty - --> $DIR/uninhabited-matches-feature-gated.rs:18:19 + --> $DIR/uninhabited-matches-feature-gated.rs:23:19 | LL | let _ = match x {}; | ^ @@ -26,7 +31,7 @@ LL | let _ = match x {}; = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: type `[Void; 1]` is non-empty - --> $DIR/uninhabited-matches-feature-gated.rs:21:19 + --> $DIR/uninhabited-matches-feature-gated.rs:26:19 | LL | let _ = match x {}; | ^ @@ -34,7 +39,7 @@ LL | let _ = match x {}; = 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/uninhabited-matches-feature-gated.rs:24:19 + --> $DIR/uninhabited-matches-feature-gated.rs:29:19 | LL | let _ = match x { | ^ pattern `&[_, ..]` not covered @@ -42,18 +47,28 @@ LL | let _ = match x { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `Err(_)` not covered - --> $DIR/uninhabited-matches-feature-gated.rs:32:19 + --> $DIR/uninhabited-matches-feature-gated.rs:37:19 | LL | let _ = match x { | ^ pattern `Err(_)` not covered + | + ::: $SRC_DIR/libcore/result.rs:LL:COL + | +LL | Err(#[stable(feature = "rust1", since = "1.0.0")] E), + | --- not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0005]: refutable pattern in local binding: `Err(_)` not covered - --> $DIR/uninhabited-matches-feature-gated.rs:37:9 + --> $DIR/uninhabited-matches-feature-gated.rs:42:9 | LL | let Ok(x) = x; | ^^^^^ pattern `Err(_)` not covered + | + ::: $SRC_DIR/libcore/result.rs:LL:COL + | +LL | Err(#[stable(feature = "rust1", since = "1.0.0")] E), + | --- not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html diff --git a/src/test/ui/union/union-derive-clone.rs b/src/test/ui/union/union-derive-clone.rs index 4a106cc940a18..4b92475f1e4cd 100644 --- a/src/test/ui/union/union-derive-clone.rs +++ b/src/test/ui/union/union-derive-clone.rs @@ -1,3 +1,8 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl + #![feature(untagged_unions)] use std::mem::ManuallyDrop; diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr index 01c8e8471aac2..d0a82a96c165c 100644 --- a/src/test/ui/union/union-derive-clone.stderr +++ b/src/test/ui/union/union-derive-clone.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `U1: std::marker::Copy` is not satisfied - --> $DIR/union-derive-clone.rs:5:10 + --> $DIR/union-derive-clone.rs:10:10 | LL | #[derive(Clone)] | ^^^^^ the trait `std::marker::Copy` is not implemented for `U1` @@ -8,7 +8,7 @@ LL | #[derive(Clone)] = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0599]: no method named `clone` found for union `U5` in the current scope - --> $DIR/union-derive-clone.rs:37:15 + --> $DIR/union-derive-clone.rs:42:15 | LL | union U5 { | ----------- @@ -21,6 +21,14 @@ LL | struct CloneNoCopy; ... LL | let w = u.clone(); | ^^^^^ method not found in `U5` + | + ::: $SRC_DIR/libcore/clone.rs:LL:COL + | +LL | fn clone(&self) -> Self; + | ----- + | | + | the method is available for `std::sync::Arc>` here + | the method is available for `std::rc::Rc>` here | = note: the method `clone` exists but the following trait bounds were not satisfied: `CloneNoCopy: std::marker::Copy` diff --git a/src/test/ui/union/union-suggest-field.rs b/src/test/ui/union/union-suggest-field.rs index d84a22cee5ab2..71b93e873c220 100644 --- a/src/test/ui/union/union-suggest-field.rs +++ b/src/test/ui/union/union-suggest-field.rs @@ -17,5 +17,5 @@ fn main() { let y = u.calculate; //~ ERROR attempted to take value of method `calculate` on type `U` //~| HELP use parentheses to call the method - //~| SUGGESTION calculate() + //~| SUGGESTION () } diff --git a/src/test/ui/union/union-suggest-field.stderr b/src/test/ui/union/union-suggest-field.stderr index 5050e4a986499..461db1712064f 100644 --- a/src/test/ui/union/union-suggest-field.stderr +++ b/src/test/ui/union/union-suggest-field.stderr @@ -14,7 +14,12 @@ error[E0615]: attempted to take value of method `calculate` on type `U` --> $DIR/union-suggest-field.rs:18:15 | LL | let y = u.calculate; - | ^^^^^^^^^ help: use parentheses to call the method: `calculate()` + | ^^^^^^^^^ method, not a field + | +help: use parentheses to call the method + | +LL | let y = u.calculate(); + | ^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index fb78095224b90..2e81e7cf83200 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -14,6 +14,14 @@ LL | let _z = y.clone(); | LL | pub struct Box(Unique); | ------------------------------------- doesn't satisfy `std::boxed::Box: std::clone::Clone` + | + ::: $SRC_DIR/libcore/clone.rs:LL:COL + | +LL | fn clone(&self) -> Self; + | ----- + | | + | the method is available for `std::sync::Arc>` here + | the method is available for `std::rc::Rc>` here | = note: the method `clone` exists but the following trait bounds were not satisfied: `dyn Foo: std::marker::Sized` diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr index ea6575d1d85dc..06c4b95baef56 100644 --- a/src/test/ui/unique-pinned-nocopy.stderr +++ b/src/test/ui/unique-pinned-nocopy.stderr @@ -11,6 +11,14 @@ LL | let _j = i.clone(); | LL | pub struct Box(Unique); | ------------------------------------- doesn't satisfy `std::boxed::Box: std::clone::Clone` + | + ::: $SRC_DIR/libcore/clone.rs:LL:COL + | +LL | fn clone(&self) -> Self; + | ----- + | | + | the method is available for `std::sync::Arc>` here + | the method is available for `std::rc::Rc>` here | = note: the method `clone` exists but the following trait bounds were not satisfied: `R: std::clone::Clone` diff --git a/src/test/ui/unknown-lint-tool-name.stderr b/src/test/ui/unknown-lint-tool-name.stderr index 1940f61a47b68..414816d229cdb 100644 --- a/src/test/ui/unknown-lint-tool-name.stderr +++ b/src/test/ui/unknown-lint-tool-name.stderr @@ -36,3 +36,4 @@ LL | #[allow(foo::bar)] error: aborting due to 6 previous errors +For more information about this error, try `rustc --explain E0710`. diff --git a/src/test/ui/unsized3.stderr b/src/test/ui/unsized3.stderr index e97d00fc4741d..083c74ba1e05d 100644 --- a/src/test/ui/unsized3.stderr +++ b/src/test/ui/unsized3.stderr @@ -7,12 +7,14 @@ LL | f2::(x); | ^ doesn't have a size known at compile-time ... LL | fn f2(x: &X) { - | -- -- help: consider relaxing the implicit `Sized` restriction: `: ?Sized` - | | - | required by this bound in `f2` + | -- - required by this bound in `f2` | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit +help: consider relaxing the implicit `Sized` restriction + | +LL | fn f2(x: &X) { + | ^^^^^^^^ error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized3.rs:18:13 @@ -23,12 +25,14 @@ LL | f4::(x); | ^ doesn't have a size known at compile-time ... LL | fn f4(x: &X) { - | -- - - help: consider relaxing the implicit `Sized` restriction: `+ ?Sized` - | | - | required by this bound in `f4` + | -- - required by this bound in `f4` | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit +help: consider relaxing the implicit `Sized` restriction + | +LL | fn f4(x: &X) { + | ^^^^^^^^^ error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized3.rs:33:8 diff --git a/src/test/ui/use/use-from-trait-xc.stderr b/src/test/ui/use/use-from-trait-xc.stderr index 3f38a6cae7b81..37b4e61c8085e 100644 --- a/src/test/ui/use/use-from-trait-xc.stderr +++ b/src/test/ui/use/use-from-trait-xc.stderr @@ -44,7 +44,7 @@ error[E0603]: struct `Foo` is private --> $DIR/use-from-trait-xc.rs:14:24 | LL | use use_from_trait_xc::Foo::new; - | ^^^ this struct is private + | ^^^ private struct | note: the struct `Foo` is defined here --> $DIR/auxiliary/use-from-trait-xc.rs:9:1 @@ -56,7 +56,7 @@ error[E0603]: struct `Foo` is private --> $DIR/use-from-trait-xc.rs:17:24 | LL | use use_from_trait_xc::Foo::C; - | ^^^ this struct is private + | ^^^ private struct | note: the struct `Foo` is defined here --> $DIR/auxiliary/use-from-trait-xc.rs:9:1 diff --git a/src/test/ui/use/use-mod/use-mod-3.stderr b/src/test/ui/use/use-mod/use-mod-3.stderr index 4852759286ae6..1b12b3c6fa09a 100644 --- a/src/test/ui/use/use-mod/use-mod-3.stderr +++ b/src/test/ui/use/use-mod/use-mod-3.stderr @@ -2,7 +2,7 @@ error[E0603]: module `bar` is private --> $DIR/use-mod-3.rs:1:10 | LL | use foo::bar::{ - | ^^^ this module is private + | ^^^ private module | note: the module `bar` is defined here --> $DIR/use-mod-3.rs:9:5 @@ -14,7 +14,7 @@ error[E0603]: module `bar` is private --> $DIR/use-mod-3.rs:4:10 | LL | use foo::bar::{ - | ^^^ this module is private + | ^^^ private module | note: the module `bar` is defined here --> $DIR/use-mod-3.rs:9:5 diff --git a/src/test/ui/write-to-static-mut-in-static.stderr b/src/test/ui/write-to-static-mut-in-static.stderr index 4349f6e89c119..6c2bd13d433ad 100644 --- a/src/test/ui/write-to-static-mut-in-static.stderr +++ b/src/test/ui/write-to-static-mut-in-static.stderr @@ -2,7 +2,7 @@ error[E0080]: could not evaluate static initializer --> $DIR/write-to-static-mut-in-static.rs:2:33 | LL | pub static mut B: () = unsafe { A = 1; }; - | ^^^^^ tried to modify a static's initial value from another static's initializer + | ^^^^^ modifying a static's initial value from another static's initializer error[E0391]: cycle detected when const-evaluating `C` --> $DIR/write-to-static-mut-in-static.rs:5:34 diff --git a/src/test/ui/xc-private-method.rs b/src/test/ui/xc-private-method.rs index e95cab93d750e..f05994646b3c4 100644 --- a/src/test/ui/xc-private-method.rs +++ b/src/test/ui/xc-private-method.rs @@ -4,8 +4,8 @@ extern crate xc_private_method_lib; fn main() { let _ = xc_private_method_lib::Struct::static_meth_struct(); - //~^ ERROR: method `static_meth_struct` is private + //~^ ERROR: associated function `static_meth_struct` is private let _ = xc_private_method_lib::Enum::static_meth_enum(); - //~^ ERROR: method `static_meth_enum` is private + //~^ ERROR: associated function `static_meth_enum` is private } diff --git a/src/test/ui/xc-private-method.stderr b/src/test/ui/xc-private-method.stderr index 91bec2551c1e0..8b7e43ccc04e9 100644 --- a/src/test/ui/xc-private-method.stderr +++ b/src/test/ui/xc-private-method.stderr @@ -1,14 +1,14 @@ -error[E0624]: method `static_meth_struct` is private - --> $DIR/xc-private-method.rs:6:13 +error[E0624]: associated function `static_meth_struct` is private + --> $DIR/xc-private-method.rs:6:44 | LL | let _ = xc_private_method_lib::Struct::static_meth_struct(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ private associated function -error[E0624]: method `static_meth_enum` is private - --> $DIR/xc-private-method.rs:9:13 +error[E0624]: associated function `static_meth_enum` is private + --> $DIR/xc-private-method.rs:9:42 | LL | let _ = xc_private_method_lib::Enum::static_meth_enum(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ private associated function error: aborting due to 2 previous errors diff --git a/src/test/ui/xc-private-method2.rs b/src/test/ui/xc-private-method2.rs index f11b251082bf2..92946923f6e70 100644 --- a/src/test/ui/xc-private-method2.rs +++ b/src/test/ui/xc-private-method2.rs @@ -4,8 +4,8 @@ extern crate xc_private_method_lib; fn main() { let _ = xc_private_method_lib::Struct{ x: 10 }.meth_struct(); - //~^ ERROR method `meth_struct` is private + //~^ ERROR associated function `meth_struct` is private let _ = xc_private_method_lib::Enum::Variant1(20).meth_enum(); - //~^ ERROR method `meth_enum` is private + //~^ ERROR associated function `meth_enum` is private } diff --git a/src/test/ui/xc-private-method2.stderr b/src/test/ui/xc-private-method2.stderr index 36ad850fb1919..0ebdb0a06d82b 100644 --- a/src/test/ui/xc-private-method2.stderr +++ b/src/test/ui/xc-private-method2.stderr @@ -1,14 +1,14 @@ -error[E0624]: method `meth_struct` is private +error[E0624]: associated function `meth_struct` is private --> $DIR/xc-private-method2.rs:6:52 | LL | let _ = xc_private_method_lib::Struct{ x: 10 }.meth_struct(); - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ private associated function -error[E0624]: method `meth_enum` is private +error[E0624]: associated function `meth_enum` is private --> $DIR/xc-private-method2.rs:9:55 | LL | let _ = xc_private_method_lib::Enum::Variant1(20).meth_enum(); - | ^^^^^^^^^ + | ^^^^^^^^^ private associated function error: aborting due to 2 previous errors diff --git a/src/test/ui/xcrate/xcrate-private-by-default.stderr b/src/test/ui/xcrate/xcrate-private-by-default.stderr index 842069d6135cb..a97f55de5f833 100644 --- a/src/test/ui/xcrate/xcrate-private-by-default.stderr +++ b/src/test/ui/xcrate/xcrate-private-by-default.stderr @@ -2,7 +2,7 @@ error[E0603]: static `j` is private --> $DIR/xcrate-private-by-default.rs:23:29 | LL | static_priv_by_default::j; - | ^ this static is private + | ^ private static | note: the static `j` is defined here --> $DIR/auxiliary/static_priv_by_default.rs:47:1 @@ -14,7 +14,7 @@ error[E0603]: function `k` is private --> $DIR/xcrate-private-by-default.rs:25:29 | LL | static_priv_by_default::k; - | ^ this function is private + | ^ private function | note: the function `k` is defined here --> $DIR/auxiliary/static_priv_by_default.rs:48:1 @@ -26,7 +26,7 @@ error[E0603]: unit struct `l` is private --> $DIR/xcrate-private-by-default.rs:27:29 | LL | static_priv_by_default::l; - | ^ this unit struct is private + | ^ private unit struct | note: the unit struct `l` is defined here --> $DIR/auxiliary/static_priv_by_default.rs:49:1 @@ -38,7 +38,7 @@ error[E0603]: enum `m` is private --> $DIR/xcrate-private-by-default.rs:29:35 | LL | foo::(); - | ^ this enum is private + | ^ private enum | note: the enum `m` is defined here --> $DIR/auxiliary/static_priv_by_default.rs:50:1 @@ -50,7 +50,7 @@ error[E0603]: type alias `n` is private --> $DIR/xcrate-private-by-default.rs:31:35 | LL | foo::(); - | ^ this type alias is private + | ^ private type alias | note: the type alias `n` is defined here --> $DIR/auxiliary/static_priv_by_default.rs:51:1 @@ -62,7 +62,7 @@ error[E0603]: module `foo` is private --> $DIR/xcrate-private-by-default.rs:35:29 | LL | static_priv_by_default::foo::a; - | ^^^ this module is private + | ^^^ private module | note: the module `foo` is defined here --> $DIR/auxiliary/static_priv_by_default.rs:12:1 @@ -74,7 +74,7 @@ error[E0603]: module `foo` is private --> $DIR/xcrate-private-by-default.rs:37:29 | LL | static_priv_by_default::foo::b; - | ^^^ this module is private + | ^^^ private module | note: the module `foo` is defined here --> $DIR/auxiliary/static_priv_by_default.rs:12:1 @@ -86,7 +86,7 @@ error[E0603]: module `foo` is private --> $DIR/xcrate-private-by-default.rs:39:29 | LL | static_priv_by_default::foo::c; - | ^^^ this module is private + | ^^^ private module | note: the module `foo` is defined here --> $DIR/auxiliary/static_priv_by_default.rs:12:1 @@ -98,7 +98,7 @@ error[E0603]: module `foo` is private --> $DIR/xcrate-private-by-default.rs:41:35 | LL | foo::(); - | ^^^ this module is private + | ^^^ private module | note: the module `foo` is defined here --> $DIR/auxiliary/static_priv_by_default.rs:12:1 @@ -110,7 +110,7 @@ error[E0603]: module `foo` is private --> $DIR/xcrate-private-by-default.rs:43:35 | LL | foo::(); - | ^^^ this module is private + | ^^^ private module | note: the module `foo` is defined here --> $DIR/auxiliary/static_priv_by_default.rs:12:1 diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 98e9fe7a8b221..fc6bc3c5df367 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -45,6 +45,7 @@ static HOSTS: &[&str] = &[ "x86_64-unknown-linux-gnu", "x86_64-unknown-linux-musl", "x86_64-unknown-netbsd", + "x86_64-sun-solaris", ]; static TARGETS: &[&str] = &[ @@ -129,6 +130,7 @@ static TARGETS: &[&str] = &[ "x86_64-apple-ios", "x86_64-fortanix-unknown-sgx", "x86_64-fuchsia", + "x86_64-illumos", "x86_64-linux-android", "x86_64-pc-windows-gnu", "x86_64-pc-windows-msvc", diff --git a/src/tools/cargo b/src/tools/cargo index bda50510d1daf..8a0d4d9c9abc7 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit bda50510d1daf6e9c53ad6ccf603da6e0fa8103f +Subproject commit 8a0d4d9c9abc74fd670353094387d62028b40ae9 diff --git a/src/tools/clippy b/src/tools/clippy index 329923edec41d..1ff81c1b6d7ab 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 329923edec41d0ddbea7f30ab12fca0436d459ae +Subproject commit 1ff81c1b6d7abdcc9ee47f4a8ab175082cad4421 diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 2a24a8c3c9485..cb648db8830ef 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -191,6 +191,7 @@ impl EarlyProps { return true; } if let Some(ref actual_version) = config.llvm_version { + let actual_version = version_to_int(actual_version); if line.starts_with("min-llvm-version") { let min_version = line .trim_end() @@ -199,7 +200,7 @@ impl EarlyProps { .expect("Malformed llvm version directive"); // Ignore if actual version is smaller the minimum required // version - &actual_version[..] < min_version + actual_version < version_to_int(min_version) } else if line.starts_with("min-system-llvm-version") { let min_version = line .trim_end() @@ -208,7 +209,7 @@ impl EarlyProps { .expect("Malformed llvm version directive"); // Ignore if using system LLVM and actual version // is smaller the minimum required version - config.system_llvm && &actual_version[..] < min_version + config.system_llvm && actual_version < version_to_int(min_version) } else if line.starts_with("ignore-llvm-version") { // Syntax is: "ignore-llvm-version [- ]" let range_components = line @@ -219,15 +220,15 @@ impl EarlyProps { .take(3) // 3 or more = invalid, so take at most 3. .collect::>(); match range_components.len() { - 1 => &actual_version[..] == range_components[0], + 1 => actual_version == version_to_int(range_components[0]), 2 => { - let v_min = range_components[0]; - let v_max = range_components[1]; + let v_min = version_to_int(range_components[0]); + let v_max = version_to_int(range_components[1]); if v_max < v_min { panic!("Malformed LLVM version range: max < min") } // Ignore if version lies inside of range. - &actual_version[..] >= v_min && &actual_version[..] <= v_max + actual_version >= v_min && actual_version <= v_max } _ => panic!("Malformed LLVM version directive"), } @@ -238,6 +239,20 @@ impl EarlyProps { false } } + + fn version_to_int(version: &str) -> u32 { + let version_without_suffix = version.split('-').next().unwrap(); + let components: Vec = version_without_suffix + .split('.') + .map(|s| s.parse().expect("Malformed version component")) + .collect(); + match components.len() { + 1 => components[0] * 10000, + 2 => components[0] * 10000 + components[1] * 100, + 3 => components[0] * 10000 + components[1] * 100 + components[2], + _ => panic!("Malformed version"), + } + } } } diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 6c478f7e29da4..31d991e0c2f87 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -122,9 +122,8 @@ fn llvm_version() { config.llvm_version = Some("9.3.1-rust-1.43.0-dev".to_owned()); assert!(!parse_rs(&config, "// min-llvm-version 9.2").ignore); - // FIXME. - // config.llvm_version = Some("10.0.0-rust".to_owned()); - // assert!(!parse_rs(&config, "// min-llvm-version 9.0").ignore); + config.llvm_version = Some("10.0.0-rust".to_owned()); + assert!(!parse_rs(&config, "// min-llvm-version 9.0").ignore); } #[test] diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 680c32c92af4b..4508f5b7f95f4 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1852,7 +1852,6 @@ impl<'test> TestCx<'test> { if let Some(ref incremental_dir) = self.props.incremental_dir { rustc.args(&["-C", &format!("incremental={}", incremental_dir.display())]); rustc.args(&["-Z", "incremental-verify-ich"]); - rustc.args(&["-Z", "incremental-queries"]); } if self.config.mode == CodegenUnits { @@ -2571,12 +2570,12 @@ impl<'test> TestCx<'test> { // - if `cfail`, expect compilation to fail // - if `rfail`, expect execution to fail // - create a directory build/foo/bar.incremental - // - compile foo/bar.rs with -Z incremental=.../foo/bar.incremental and -C rpass1 + // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C rpass1 // - because name of revision starts with "rpass", expect success - // - compile foo/bar.rs with -Z incremental=.../foo/bar.incremental and -C cfail2 + // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C cfail2 // - because name of revision starts with "cfail", expect an error // - load expected errors as usual, but filter for those that end in `[rfail2]` - // - compile foo/bar.rs with -Z incremental=.../foo/bar.incremental and -C rpass3 + // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C rpass3 // - because name of revision starts with "rpass", expect success // - execute build/foo/bar.exe and save output // @@ -2779,7 +2778,7 @@ impl<'test> TestCx<'test> { Command::new(&nodejs) .arg(root.join("src/tools/rustdoc-js/tester.js")) .arg(out_dir.parent().expect("no parent")) - .arg(&self.testpaths.file.file_stem().expect("couldn't get file stem")), + .arg(self.testpaths.file.with_extension("js")), ); if !res.status.success() { self.fatal_proc_rec("rustdoc-js test failed!", &res); diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 2663b3d160a7a..c61bee0f8d9ea 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -21,6 +21,7 @@ const OS_TABLE: &'static [(&'static str, &'static str)] = &[ ("fuchsia", "fuchsia"), ("haiku", "haiku"), ("hermit", "hermit"), + ("illumos", "illumos"), ("ios", "ios"), ("l4re", "l4re"), ("linux", "linux"), diff --git a/src/tools/expand-yaml-anchors/Cargo.toml b/src/tools/expand-yaml-anchors/Cargo.toml new file mode 100644 index 0000000000000..2c63e28b693da --- /dev/null +++ b/src/tools/expand-yaml-anchors/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "expand-yaml-anchors" +version = "0.1.0" +authors = ["Pietro Albini "] +edition = "2018" + +[dependencies] +yaml-rust = "0.4.3" +yaml-merge-keys = "0.4.0" diff --git a/src/tools/expand-yaml-anchors/src/main.rs b/src/tools/expand-yaml-anchors/src/main.rs new file mode 100644 index 0000000000000..f2ed8aa409a36 --- /dev/null +++ b/src/tools/expand-yaml-anchors/src/main.rs @@ -0,0 +1,202 @@ +use std::error::Error; +use std::path::{Path, PathBuf}; +use yaml_rust::{Yaml, YamlEmitter, YamlLoader}; + +/// List of directories containing files to expand. The first tuple element is the source +/// directory, while the second tuple element is the destination directory. +#[rustfmt::skip] +static TO_EXPAND: &[(&str, &str)] = &[ + ("src/ci/github-actions", ".github/workflows"), +]; + +/// Name of a special key that will be removed from all the maps in expanded configuration files. +/// This key can then be used to contain shared anchors. +static REMOVE_MAP_KEY: &str = "x--expand-yaml-anchors--remove"; + +/// Message that will be included at the top of all the expanded files. {source} will be replaced +/// with the source filename relative to the base path. +static HEADER_MESSAGE: &str = "\ +############################################################# +# WARNING: automatically generated file, DO NOT CHANGE! # +############################################################# + +# This file was automatically generated by the expand-yaml-anchors tool. The +# source file that generated this one is: +# +# {source} +# +# Once you make changes to that file you need to run: +# +# ./x.py run src/tools/expand-yaml-anchors/ +# +# The CI build will fail if the tool is not run after changes to this file. + +"; + +enum Mode { + Check, + Generate, +} + +struct App { + mode: Mode, + base: PathBuf, +} + +impl App { + fn from_args() -> Result> { + // Parse CLI arguments + let args = std::env::args().skip(1).collect::>(); + let (mode, base) = match args.iter().map(|s| s.as_str()).collect::>().as_slice() { + &["generate", ref base] => (Mode::Generate, PathBuf::from(base)), + &["check", ref base] => (Mode::Check, PathBuf::from(base)), + _ => { + eprintln!("usage: expand-yaml-anchors "); + std::process::exit(1); + } + }; + + Ok(App { mode, base }) + } + + fn run(&self) -> Result<(), Box> { + for (source, dest) in TO_EXPAND { + let source = self.base.join(source); + let dest = self.base.join(dest); + for entry in std::fs::read_dir(&source)? { + let path = entry?.path(); + if !path.is_file() || path.extension().and_then(|e| e.to_str()) != Some("yml") { + continue; + } + + let dest_path = dest.join(path.file_name().unwrap()); + self.expand(&path, &dest_path).with_context(|| match self.mode { + Mode::Generate => format!( + "failed to expand {} into {}", + self.path(&path), + self.path(&dest_path) + ), + Mode::Check => format!("{} is not up to date", self.path(&dest_path)), + })?; + } + } + Ok(()) + } + + fn expand(&self, source: &Path, dest: &Path) -> Result<(), Box> { + let content = std::fs::read_to_string(source) + .with_context(|| format!("failed to read {}", self.path(source)))?; + + let mut buf = HEADER_MESSAGE.replace("{source}", &self.path(source).to_string()); + + let documents = YamlLoader::load_from_str(&content) + .with_context(|| format!("failed to parse {}", self.path(source)))?; + for mut document in documents.into_iter() { + document = yaml_merge_keys::merge_keys(document) + .with_context(|| format!("failed to expand {}", self.path(source)))?; + document = filter_document(document); + + YamlEmitter::new(&mut buf).dump(&document).map_err(|err| WithContext { + context: "failed to serialize the expanded yaml".into(), + source: Box::new(err), + })?; + buf.push('\n'); + } + + match self.mode { + Mode::Check => { + let old = std::fs::read_to_string(dest) + .with_context(|| format!("failed to read {}", self.path(dest)))?; + if old != buf { + return Err(Box::new(StrError(format!( + "{} and {} are different", + self.path(source), + self.path(dest), + )))); + } + } + Mode::Generate => { + std::fs::write(dest, buf.as_bytes()) + .with_context(|| format!("failed to write to {}", self.path(dest)))?; + } + } + Ok(()) + } + + fn path<'a>(&self, path: &'a Path) -> impl std::fmt::Display + 'a { + path.strip_prefix(&self.base).unwrap_or(path).display() + } +} + +fn filter_document(document: Yaml) -> Yaml { + match document { + Yaml::Hash(map) => Yaml::Hash( + map.into_iter() + .filter(|(key, _)| { + if let Yaml::String(string) = &key { string != REMOVE_MAP_KEY } else { true } + }) + .map(|(key, value)| (filter_document(key), filter_document(value))) + .collect(), + ), + Yaml::Array(vec) => { + Yaml::Array(vec.into_iter().map(|item| filter_document(item)).collect()) + } + other => other, + } +} + +fn main() { + if let Err(err) = App::from_args().and_then(|app| app.run()) { + eprintln!("error: {}", err); + + let mut source = err.as_ref() as &dyn Error; + while let Some(err) = source.source() { + eprintln!("caused by: {}", err); + source = err; + } + + std::process::exit(1); + } +} + +#[derive(Debug)] +struct StrError(String); + +impl Error for StrError {} + +impl std::fmt::Display for StrError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + std::fmt::Display::fmt(&self.0, f) + } +} + +#[derive(Debug)] +struct WithContext { + context: String, + source: Box, +} + +impl std::fmt::Display for WithContext { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.context) + } +} + +impl Error for WithContext { + fn source(&self) -> Option<&(dyn Error + 'static)> { + Some(self.source.as_ref()) + } +} + +pub(crate) trait ResultExt { + fn with_context String>(self, f: F) -> Result>; +} + +impl>> ResultExt for Result { + fn with_context String>(self, f: F) -> Result> { + match self { + Ok(ok) => Ok(ok), + Err(err) => Err(WithContext { source: err.into(), context: f() }.into()), + } + } +} diff --git a/src/tools/miri b/src/tools/miri index 974c8be95ec17..0d0a457c8b175 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 974c8be95ec17cd986251d7700cd432a39576939 +Subproject commit 0d0a457c8b1750e82f19527b18b313f3514633f0 diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py index b389cd0373cc4..6cc20a241ac3f 100755 --- a/src/tools/publish_toolstate.py +++ b/src/tools/publish_toolstate.py @@ -153,7 +153,6 @@ def issue( )), 'title': '`{}` no longer builds after {}'.format(tool, relevant_pr_number), 'assignees': list(assignees), - 'labels': ['T-compiler', 'I-nominated'], }) print("Creating issue:\n{}".format(request)) response = urllib2.urlopen(urllib2.Request( diff --git a/src/tools/rustdoc-js-std/tester.js b/src/tools/rustdoc-js-std/tester.js index d5f0ab9f4292d..08930ff122797 100644 --- a/src/tools/rustdoc-js-std/tester.js +++ b/src/tools/rustdoc-js-std/tester.js @@ -1,6 +1,5 @@ const fs = require('fs'); - -const TEST_FOLDER = 'src/test/rustdoc-js-std/'; +const path = require('path'); function getNextStep(content, pos, stop) { while (pos < content.length && content[pos] !== stop && @@ -246,17 +245,16 @@ function readFileMatching(dir, name, extension) { } function main(argv) { - if (argv.length !== 3) { - console.error("Expected toolchain to check as argument (for example \ - 'x86_64-apple-darwin')"); + if (argv.length !== 4) { + console.error("USAGE: node tester.js STD_DOCS TEST_FOLDER"); return 1; } - var toolchain = argv[2]; + var std_docs = argv[2]; + var test_folder = argv[3]; - var mainJs = readFileMatching("build/" + toolchain + "/doc/", "main", ".js"); - var ALIASES = readFileMatching("build/" + toolchain + "/doc/", "aliases", ".js"); - var searchIndex = readFileMatching("build/" + toolchain + "/doc/", - "search-index", ".js").split("\n"); + var mainJs = readFileMatching(std_docs, "main", ".js"); + var ALIASES = readFileMatching(std_docs, "aliases", ".js"); + var searchIndex = readFileMatching(std_docs, "search-index", ".js").split("\n"); if (searchIndex[searchIndex.length - 1].length === 0) { searchIndex.pop(); } @@ -265,7 +263,7 @@ function main(argv) { finalJS = ""; var arraysToLoad = ["itemTypes"]; - var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS", + var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS", "NO_TYPE_FILTER", "GENERICS_DATA", "NAME", "INPUTS_DATA", "OUTPUT_DATA", "TY_PRIMITIVE", "TY_KEYWORD", "levenshtein_row2"]; @@ -287,8 +285,8 @@ function main(argv) { var errors = 0; - fs.readdirSync(TEST_FOLDER).forEach(function(file) { - var loadedFile = loadContent(readFile(TEST_FOLDER + file) + + fs.readdirSync(test_folder).forEach(function(file) { + var loadedFile = loadContent(readFile(path.join(test_folder, file)) + 'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;'); const expected = loadedFile.EXPECTED; const query = loadedFile.QUERY; @@ -338,7 +336,7 @@ function main(argv) { console.log("OK"); } }); - return errors; + return errors > 0 ? 1 : 0; } process.exit(main(process.argv)); diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index 833ce5d137047..143e1a7480d3d 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -1,8 +1,7 @@ const fs = require('fs'); +const path = require('path'); const { spawnSync } = require('child_process'); -const TEST_FOLDER = 'src/test/rustdoc-js/'; - function getNextStep(content, pos, stop) { while (pos < content.length && content[pos] !== stop && (content[pos] === ' ' || content[pos] === '\t' || content[pos] === '\n')) { @@ -232,7 +231,7 @@ function load_files(out_folder, crate) { finalJS = ""; var arraysToLoad = ["itemTypes"]; - var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS", + var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS", "NO_TYPE_FILTER", "GENERICS_DATA", "NAME", "INPUTS_DATA", "OUTPUT_DATA", "TY_PRIMITIVE", "TY_KEYWORD", "levenshtein_row2"]; @@ -266,10 +265,11 @@ function main(argv) { var errors = 0; for (var j = 3; j < argv.length; ++j) { - const test_name = argv[j]; + const test_file = argv[j]; + const test_name = path.basename(test_file, ".js"); process.stdout.write('Checking "' + test_name + '" ... '); - if (!fs.existsSync(TEST_FOLDER + test_name + ".js")) { + if (!fs.existsSync(test_file)) { errors += 1; console.error("FAILED"); console.error("==> Missing '" + test_name + ".js' file..."); @@ -279,7 +279,7 @@ function main(argv) { const test_out_folder = out_folder + test_name; var [loaded, index] = load_files(test_out_folder, test_name); - var loadedFile = loadContent(readFile(TEST_FOLDER + test_name + ".js") + + var loadedFile = loadContent(readFile(test_file) + 'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;'); const expected = loadedFile.EXPECTED; const query = loadedFile.QUERY; @@ -328,7 +328,7 @@ function main(argv) { console.log("OK"); } } - return errors; + return errors > 0 ? 1 : 0; } process.exit(main(process.argv)); diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml index 43cae31f33f1f..f984e5b61a5fd 100644 --- a/src/tools/tidy/Cargo.toml +++ b/src/tools/tidy/Cargo.toml @@ -5,8 +5,7 @@ authors = ["Alex Crichton "] edition = "2018" [dependencies] +cargo_metadata = "0.9.1" regex = "1" -serde = { version = "1.0.8", features = ["derive"] } -serde_json = "1.0.2" lazy_static = "1" walkdir = "2" diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 7a20a96130ccb..1ffc415fb2497 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -1,13 +1,11 @@ -//! Checks the licenses of third-party dependencies by inspecting vendors. +//! Checks the licenses of third-party dependencies. -use std::collections::{BTreeSet, HashMap, HashSet}; -use std::fs; +use cargo_metadata::{Metadata, Package, PackageId, Resolve}; +use std::collections::{BTreeSet, HashSet}; use std::path::Path; -use std::process::Command; - -use serde::Deserialize; -use serde_json; +/// These are licenses that are allowed for all crates, including the runtime, +/// rustc, tools, etc. const LICENSES: &[&str] = &[ "MIT/Apache-2.0", "MIT / Apache-2.0", @@ -25,261 +23,268 @@ const LICENSES: &[&str] = &[ /// should be considered bugs. Exceptions are only allowed in Rust /// tooling. It is _crucial_ that no exception crates be dependencies /// of the Rust runtime (std/test). -const EXCEPTIONS: &[&str] = &[ - "mdbook", // MPL2, mdbook - "openssl", // BSD+advertising clause, cargo, mdbook - "pest", // MPL2, mdbook via handlebars - "arrayref", // BSD-2-Clause, mdbook via handlebars via pest - "thread-id", // Apache-2.0, mdbook - "toml-query", // MPL-2.0, mdbook - "is-match", // MPL-2.0, mdbook - "cssparser", // MPL-2.0, rustdoc - "smallvec", // MPL-2.0, rustdoc - "rdrand", // ISC, mdbook, rustfmt - "fuchsia-cprng", // BSD-3-Clause, mdbook, rustfmt - "fuchsia-zircon-sys", // BSD-3-Clause, rustdoc, rustc, cargo - "fuchsia-zircon", // BSD-3-Clause, rustdoc, rustc, cargo (jobserver & tempdir) - "cssparser-macros", // MPL-2.0, rustdoc - "selectors", // MPL-2.0, rustdoc - "clippy_lints", // MPL-2.0, rls - "colored", // MPL-2.0, rustfmt - "ordslice", // Apache-2.0, rls - "cloudabi", // BSD-2-Clause, (rls -> crossbeam-channel 0.2 -> rand 0.5) - "ryu", // Apache-2.0, rls/cargo/... (because of serde) - "bytesize", // Apache-2.0, cargo - "im-rc", // MPL-2.0+, cargo - "adler32", // BSD-3-Clause AND Zlib, cargo dep that isn't used - "constant_time_eq", // CC0-1.0, rustfmt - "utf8parse", // Apache-2.0 OR MIT, cargo via strip-ansi-escapes - "vte", // Apache-2.0 OR MIT, cargo via strip-ansi-escapes - "sized-chunks", // MPL-2.0+, cargo via im-rc - "bitmaps", // MPL-2.0+, cargo via im-rc +const EXCEPTIONS: &[(&str, &str)] = &[ + ("mdbook", "MPL-2.0"), // mdbook + ("openssl", "Apache-2.0"), // cargo, mdbook + ("arrayref", "BSD-2-Clause"), // mdbook via handlebars via pest + ("toml-query", "MPL-2.0"), // mdbook + ("toml-query_derive", "MPL-2.0"), // mdbook + ("is-match", "MPL-2.0"), // mdbook + ("rdrand", "ISC"), // mdbook, rustfmt + ("fuchsia-cprng", "BSD-3-Clause"), // mdbook, rustfmt + ("fuchsia-zircon-sys", "BSD-3-Clause"), // rustdoc, rustc, cargo + ("fuchsia-zircon", "BSD-3-Clause"), // rustdoc, rustc, cargo (jobserver & tempdir) + ("colored", "MPL-2.0"), // rustfmt + ("ordslice", "Apache-2.0"), // rls + ("cloudabi", "BSD-2-Clause"), // (rls -> crossbeam-channel 0.2 -> rand 0.5) + ("ryu", "Apache-2.0 OR BSL-1.0"), // rls/cargo/... (because of serde) + ("bytesize", "Apache-2.0"), // cargo + ("im-rc", "MPL-2.0+"), // cargo + ("adler32", "BSD-3-Clause AND Zlib"), // cargo dep that isn't used + ("constant_time_eq", "CC0-1.0"), // rustfmt + ("sized-chunks", "MPL-2.0+"), // cargo via im-rc + ("bitmaps", "MPL-2.0+"), // cargo via im-rc // FIXME: this dependency violates the documentation comment above: - "fortanix-sgx-abi", // MPL-2.0+, libstd but only for `sgx` target - "dunce", // CC0-1.0 mdbook-linkcheck - "codespan-reporting", // Apache-2.0 mdbook-linkcheck - "codespan", // Apache-2.0 mdbook-linkcheck - "crossbeam-channel", // MIT/Apache-2.0 AND BSD-2-Clause, cargo + ("fortanix-sgx-abi", "MPL-2.0"), // libstd but only for `sgx` target + ("dunce", "CC0-1.0"), // mdbook-linkcheck + ("codespan-reporting", "Apache-2.0"), // mdbook-linkcheck + ("codespan", "Apache-2.0"), // mdbook-linkcheck + ("crossbeam-channel", "MIT/Apache-2.0 AND BSD-2-Clause"), // cargo ]; +/// These are the root crates that are part of the runtime. The licenses for +/// these and all their dependencies *must not* be in the exception list. +const RUNTIME_CRATES: &[&str] = &["std", "core", "alloc", "test", "panic_abort", "panic_unwind"]; + /// Which crates to check against the whitelist? -const WHITELIST_CRATES: &[CrateVersion<'_>] = - &[CrateVersion("rustc", "0.0.0"), CrateVersion("rustc_codegen_llvm", "0.0.0")]; +const WHITELIST_CRATES: &[&str] = &["rustc", "rustc_codegen_llvm"]; /// Whitelist of crates rustc is allowed to depend on. Avoid adding to the list if possible. -const WHITELIST: &[Crate<'_>] = &[ - Crate("adler32"), - Crate("aho-corasick"), - Crate("annotate-snippets"), - Crate("ansi_term"), - Crate("arrayvec"), - Crate("atty"), - Crate("autocfg"), - Crate("backtrace"), - Crate("backtrace-sys"), - Crate("bitflags"), - Crate("build_const"), - Crate("byteorder"), - Crate("c2-chacha"), - Crate("cc"), - Crate("cfg-if"), - Crate("chalk-engine"), - Crate("chalk-macros"), - Crate("cloudabi"), - Crate("cmake"), - Crate("compiler_builtins"), - Crate("crc"), - Crate("crc32fast"), - Crate("crossbeam-deque"), - Crate("crossbeam-epoch"), - Crate("crossbeam-queue"), - Crate("crossbeam-utils"), - Crate("datafrog"), - Crate("dlmalloc"), - Crate("either"), - Crate("ena"), - Crate("env_logger"), - Crate("filetime"), - Crate("flate2"), - Crate("fortanix-sgx-abi"), - Crate("fuchsia-zircon"), - Crate("fuchsia-zircon-sys"), - Crate("getopts"), - Crate("getrandom"), - Crate("hashbrown"), - Crate("humantime"), - Crate("indexmap"), - Crate("itertools"), - Crate("jobserver"), - Crate("kernel32-sys"), - Crate("lazy_static"), - Crate("libc"), - Crate("libz-sys"), - Crate("lock_api"), - Crate("log"), - Crate("log_settings"), - Crate("measureme"), - Crate("memchr"), - Crate("memmap"), - Crate("memoffset"), - Crate("miniz-sys"), - Crate("miniz_oxide"), - Crate("miniz_oxide_c_api"), - Crate("nodrop"), - Crate("num_cpus"), - Crate("owning_ref"), - Crate("parking_lot"), - Crate("parking_lot_core"), - Crate("pkg-config"), - Crate("polonius-engine"), - Crate("ppv-lite86"), - Crate("proc-macro2"), - Crate("punycode"), - Crate("quick-error"), - Crate("quote"), - Crate("rand"), - Crate("rand_chacha"), - Crate("rand_core"), - Crate("rand_hc"), - Crate("rand_isaac"), - Crate("rand_pcg"), - Crate("rand_xorshift"), - Crate("redox_syscall"), - Crate("redox_termios"), - Crate("regex"), - Crate("regex-syntax"), - Crate("remove_dir_all"), - Crate("rustc-demangle"), - Crate("rustc-hash"), - Crate("rustc-rayon"), - Crate("rustc-rayon-core"), - Crate("rustc_version"), - Crate("scoped-tls"), - Crate("scopeguard"), - Crate("semver"), - Crate("semver-parser"), - Crate("serde"), - Crate("serde_derive"), - Crate("smallvec"), - Crate("stable_deref_trait"), - Crate("syn"), - Crate("synstructure"), - Crate("tempfile"), - Crate("termcolor"), - Crate("terminon"), - Crate("termion"), - Crate("termize"), - Crate("thread_local"), - Crate("ucd-util"), - Crate("unicode-normalization"), - Crate("unicode-script"), - Crate("unicode-security"), - Crate("unicode-width"), - Crate("unicode-xid"), - Crate("unreachable"), - Crate("utf8-ranges"), - Crate("vcpkg"), - Crate("version_check"), - Crate("void"), - Crate("wasi"), - Crate("winapi"), - Crate("winapi-build"), - Crate("winapi-i686-pc-windows-gnu"), - Crate("winapi-util"), - Crate("winapi-x86_64-pc-windows-gnu"), - Crate("wincolor"), - Crate("hermit-abi"), +/// +/// This list is here to provide a speed-bump to adding a new dependency to +/// rustc. Please check with the compiler team before adding an entry. +const WHITELIST: &[&str] = &[ + "adler32", + "aho-corasick", + "annotate-snippets", + "ansi_term", + "arrayvec", + "atty", + "autocfg", + "backtrace", + "backtrace-sys", + "bitflags", + "byteorder", + "c2-chacha", + "cc", + "cfg-if", + "cloudabi", + "cmake", + "compiler_builtins", + "crc32fast", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", + "datafrog", + "dlmalloc", + "either", + "ena", + "env_logger", + "filetime", + "flate2", + "fortanix-sgx-abi", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "getopts", + "getrandom", + "hashbrown", + "hermit-abi", + "humantime", + "indexmap", + "itertools", + "jobserver", + "kernel32-sys", + "lazy_static", + "libc", + "libz-sys", + "lock_api", + "log", + "log_settings", + "measureme", + "memchr", + "memmap", + "memoffset", + "miniz_oxide", + "nodrop", + "num_cpus", + "parking_lot", + "parking_lot_core", + "pkg-config", + "polonius-engine", + "ppv-lite86", + "proc-macro2", + "punycode", + "quick-error", + "quote", + "rand", + "rand_chacha", + "rand_core", + "rand_hc", + "rand_isaac", + "rand_pcg", + "rand_xorshift", + "redox_syscall", + "redox_termios", + "regex", + "regex-syntax", + "remove_dir_all", + "rustc-demangle", + "rustc-hash", + "rustc-rayon", + "rustc-rayon-core", + "rustc_version", + "scoped-tls", + "scopeguard", + "semver", + "semver-parser", + "serde", + "serde_derive", + "smallvec", + "stable_deref_trait", + "syn", + "synstructure", + "tempfile", + "termcolor", + "termion", + "termize", + "thread_local", + "ucd-util", + "unicode-normalization", + "unicode-script", + "unicode-security", + "unicode-width", + "unicode-xid", + "utf8-ranges", + "vcpkg", + "version_check", + "wasi", + "winapi", + "winapi-build", + "winapi-i686-pc-windows-gnu", + "winapi-util", + "winapi-x86_64-pc-windows-gnu", + "wincolor", ]; -// Some types for Serde to deserialize the output of `cargo metadata` to. - -#[derive(Deserialize)] -struct Output { - resolve: Resolve, -} - -#[derive(Deserialize)] -struct Resolve { - nodes: Vec, -} - -#[derive(Deserialize)] -struct ResolveNode { - id: String, - dependencies: Vec, -} - -/// A unique identifier for a crate. -#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug, Hash)] -struct Crate<'a>(&'a str); // (name) - -#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug, Hash)] -struct CrateVersion<'a>(&'a str, &'a str); // (name, version) - -impl Crate<'_> { - pub fn id_str(&self) -> String { - format!("{} ", self.0) - } -} - -impl<'a> CrateVersion<'a> { - /// Returns the struct and whether or not the dependency is in-tree. - pub fn from_str(s: &'a str) -> (Self, bool) { - let mut parts = s.split(' '); - let name = parts.next().unwrap(); - let version = parts.next().unwrap(); - let path = parts.next().unwrap(); - - let is_path_dep = path.starts_with("(path+"); - - (CrateVersion(name, version), is_path_dep) - } - - pub fn id_str(&self) -> String { - format!("{} {}", self.0, self.1) - } +/// Dependency checks. +/// +/// `path` is path to the `src` directory, `cargo` is path to the cargo executable. +pub fn check(path: &Path, cargo: &Path, bad: &mut bool) { + let mut cmd = cargo_metadata::MetadataCommand::new(); + cmd.cargo_path(cargo) + .manifest_path(path.parent().unwrap().join("Cargo.toml")) + .features(cargo_metadata::CargoOpt::AllFeatures); + let metadata = t!(cmd.exec()); + check_exceptions(&metadata, bad); + check_whitelist(&metadata, bad); + check_crate_duplicate(&metadata, bad); } -impl<'a> From> for Crate<'a> { - fn from(cv: CrateVersion<'a>) -> Crate<'a> { - Crate(cv.0) +/// Check that all licenses are in the valid list in `LICENSES`. +/// +/// Packages listed in `EXCEPTIONS` are allowed for tools. +fn check_exceptions(metadata: &Metadata, bad: &mut bool) { + // Validate the EXCEPTIONS list hasn't changed. + for (name, license) in EXCEPTIONS { + // Check that the package actually exists. + if !metadata.packages.iter().any(|p| p.name == *name) { + println!( + "could not find exception package `{}`\n\ + Remove from EXCEPTIONS list if it is no longer used.", + name + ); + *bad = true; + } + // Check that the license hasn't changed. + for pkg in metadata.packages.iter().filter(|p| p.name == *name) { + if pkg.name == "fuchsia-cprng" { + // This package doesn't declare a license expression. Manual + // inspection of the license file is necessary, which appears + // to be BSD-3-Clause. + assert!(pkg.license.is_none()); + continue; + } + match &pkg.license { + None => { + println!( + "dependency exception `{}` does not declare a license expression", + pkg.id + ); + *bad = true; + } + Some(pkg_license) => { + if pkg_license.as_str() != *license { + println!("dependency exception `{}` license has changed", name); + println!(" previously `{}` now `{}`", license, pkg_license); + println!(" update EXCEPTIONS for the new license"); + *bad = true; + } + } + } + } } -} -/// Checks the dependency at the given path. Changes `bad` to `true` if a check failed. -/// -/// Specifically, this checks that the license is correct. -pub fn check(path: &Path, bad: &mut bool) { - // Check licences. - let path = path.join("../vendor"); - assert!(path.exists(), "vendor directory missing"); - let mut saw_dir = false; - for dir in t!(path.read_dir()) { - saw_dir = true; - let dir = t!(dir); + let exception_names: Vec<_> = EXCEPTIONS.iter().map(|(name, _license)| *name).collect(); + let runtime_ids = compute_runtime_crates(metadata); - // Skip our exceptions. - let is_exception = EXCEPTIONS.iter().any(|exception| { - dir.path().to_str().unwrap().contains(&format!("vendor/{}", exception)) - }); - if is_exception { + // Check if any package does not have a valid license. + for pkg in &metadata.packages { + if pkg.source.is_none() { + // No need to check local packages. continue; } - - let toml = dir.path().join("Cargo.toml"); - *bad = !check_license(&toml) || *bad; + if !runtime_ids.contains(&pkg.id) && exception_names.contains(&pkg.name.as_str()) { + continue; + } + let license = match &pkg.license { + Some(license) => license, + None => { + println!("dependency `{}` does not define a license expression", pkg.id,); + *bad = true; + continue; + } + }; + if !LICENSES.contains(&license.as_str()) { + if pkg.name == "fortanix-sgx-abi" { + // This is a specific exception because SGX is considered + // "third party". See + // https://github.com/rust-lang/rust/issues/62620 for more. In + // general, these should never be added. + continue; + } + println!("invalid license `{}` in `{}`", license, pkg.id); + *bad = true; + } } - assert!(saw_dir, "no vendored source"); } /// Checks the dependency of `WHITELIST_CRATES` at the given path. Changes `bad` to `true` if a /// check failed. /// /// Specifically, this checks that the dependencies are on the `WHITELIST`. -pub fn check_whitelist(path: &Path, cargo: &Path, bad: &mut bool) { - // Get dependencies from Cargo metadata. - let resolve = get_deps(path, cargo); - +fn check_whitelist(metadata: &Metadata, bad: &mut bool) { + // Check that the WHITELIST does not have unused entries. + for name in WHITELIST { + if !metadata.packages.iter().any(|p| p.name == *name) { + println!( + "could not find whitelisted package `{}`\n\ + Remove from WHITELIST list if it is no longer used.", + name + ); + *bad = true; + } + } // Get the whitelist in a convenient form. let whitelist: HashSet<_> = WHITELIST.iter().cloned().collect(); @@ -287,122 +292,59 @@ pub fn check_whitelist(path: &Path, cargo: &Path, bad: &mut bool) { let mut visited = BTreeSet::new(); let mut unapproved = BTreeSet::new(); for &krate in WHITELIST_CRATES.iter() { - let mut bad = check_crate_whitelist(&whitelist, &resolve, &mut visited, krate, false); + let pkg = pkg_from_name(metadata, krate); + let mut bad = check_crate_whitelist(&whitelist, metadata, &mut visited, pkg); unapproved.append(&mut bad); } if !unapproved.is_empty() { println!("Dependencies not on the whitelist:"); for dep in unapproved { - println!("* {}", dep.id_str()); + println!("* {}", dep); } *bad = true; } - - check_crate_duplicate(&resolve, bad); -} - -fn check_license(path: &Path) -> bool { - if !path.exists() { - panic!("{} does not exist", path.display()); - } - let contents = t!(fs::read_to_string(&path)); - - let mut found_license = false; - for line in contents.lines() { - if !line.starts_with("license") { - continue; - } - let license = extract_license(line); - if !LICENSES.contains(&&*license) { - println!("invalid license {} in {}", license, path.display()); - return false; - } - found_license = true; - break; - } - if !found_license { - println!("no license in {}", path.display()); - return false; - } - - true -} - -fn extract_license(line: &str) -> String { - let first_quote = line.find('"'); - let last_quote = line.rfind('"'); - if let (Some(f), Some(l)) = (first_quote, last_quote) { - let license = &line[f + 1..l]; - license.into() - } else { - "bad-license-parse".into() - } -} - -/// Gets the dependencies of the crate at the given path using `cargo metadata`. -fn get_deps(path: &Path, cargo: &Path) -> Resolve { - // Run `cargo metadata` to get the set of dependencies. - let output = Command::new(cargo) - .arg("metadata") - .arg("--format-version") - .arg("1") - .arg("--manifest-path") - .arg(path.join("../Cargo.toml")) - .output() - .expect("Unable to run `cargo metadata`") - .stdout; - let output = String::from_utf8_lossy(&output); - let output: Output = serde_json::from_str(&output).unwrap(); - - output.resolve } /// Checks the dependencies of the given crate from the given cargo metadata to see if they are on /// the whitelist. Returns a list of illegal dependencies. fn check_crate_whitelist<'a>( - whitelist: &'a HashSet>, - resolve: &'a Resolve, - visited: &mut BTreeSet>, - krate: CrateVersion<'a>, - must_be_on_whitelist: bool, -) -> BTreeSet> { + whitelist: &'a HashSet<&'static str>, + metadata: &'a Metadata, + visited: &mut BTreeSet<&'a PackageId>, + krate: &'a Package, +) -> BTreeSet<&'a PackageId> { // This will contain bad deps. let mut unapproved = BTreeSet::new(); // Check if we have already visited this crate. - if visited.contains(&krate) { + if visited.contains(&krate.id) { return unapproved; } - visited.insert(krate); + visited.insert(&krate.id); // If this path is in-tree, we don't require it to be on the whitelist. - if must_be_on_whitelist { + if krate.source.is_some() { // If this dependency is not on `WHITELIST`, add to bad set. - if !whitelist.contains(&krate.into()) { - unapproved.insert(krate.into()); + if !whitelist.contains(krate.name.as_str()) { + unapproved.insert(&krate.id); } } - // Do a DFS in the crate graph (it's a DAG, so we know we have no cycles!). - let to_check = resolve - .nodes - .iter() - .find(|n| n.id.starts_with(&krate.id_str())) - .expect("crate does not exist"); + // Do a DFS in the crate graph. + let to_check = deps_of(metadata, &krate.id); - for dep in to_check.dependencies.iter() { - let (krate, is_path_dep) = CrateVersion::from_str(dep); - - let mut bad = check_crate_whitelist(whitelist, resolve, visited, krate, !is_path_dep); + for dep in to_check { + let mut bad = check_crate_whitelist(whitelist, metadata, visited, dep); unapproved.append(&mut bad); } unapproved } -fn check_crate_duplicate(resolve: &Resolve, bad: &mut bool) { +/// Prevents multiple versions of some expensive crates. +fn check_crate_duplicate(metadata: &Metadata, bad: &mut bool) { const FORBIDDEN_TO_HAVE_DUPLICATES: &[&str] = &[ // These two crates take quite a long time to build, so don't allow two versions of them // to accidentally sneak into our dependency graph, in order to ensure we keep our CI times @@ -410,19 +352,97 @@ fn check_crate_duplicate(resolve: &Resolve, bad: &mut bool) { "cargo", "rustc-ap-syntax", ]; - let mut name_to_id: HashMap<_, Vec<_>> = HashMap::new(); - for node in resolve.nodes.iter() { - name_to_id.entry(node.id.split_whitespace().next().unwrap()).or_default().push(&node.id); - } - for name in FORBIDDEN_TO_HAVE_DUPLICATES { - if name_to_id[name].len() <= 1 { - continue; - } - println!("crate `{}` is duplicated in `Cargo.lock`", name); - for id in name_to_id[name].iter() { - println!(" * {}", id); + for &name in FORBIDDEN_TO_HAVE_DUPLICATES { + let matches: Vec<_> = metadata.packages.iter().filter(|pkg| pkg.name == name).collect(); + match matches.len() { + 0 => { + println!( + "crate `{}` is missing, update `check_crate_duplicate` \ + if it is no longer used", + name + ); + *bad = true; + } + 1 => {} + _ => { + println!( + "crate `{}` is duplicated in `Cargo.lock`, \ + it is too expensive to build multiple times, \ + so make sure only one version appears across all dependencies", + name + ); + for pkg in matches { + println!(" * {}", pkg.id); + } + *bad = true; + } } - *bad = true; + } +} + +/// Returns a list of dependencies for the given package. +fn deps_of<'a>(metadata: &'a Metadata, pkg_id: &'a PackageId) -> Vec<&'a Package> { + let resolve = metadata.resolve.as_ref().unwrap(); + let node = resolve + .nodes + .iter() + .find(|n| &n.id == pkg_id) + .unwrap_or_else(|| panic!("could not find `{}` in resolve", pkg_id)); + node.deps + .iter() + .map(|dep| { + metadata.packages.iter().find(|pkg| pkg.id == dep.pkg).unwrap_or_else(|| { + panic!("could not find dep `{}` for pkg `{}` in resolve", dep.pkg, pkg_id) + }) + }) + .collect() +} + +/// Finds a package with the given name. +fn pkg_from_name<'a>(metadata: &'a Metadata, name: &'static str) -> &'a Package { + let mut i = metadata.packages.iter().filter(|p| p.name == name); + let result = + i.next().unwrap_or_else(|| panic!("could not find package `{}` in package list", name)); + assert!(i.next().is_none(), "more than one package found for `{}`", name); + result +} + +/// Finds all the packages that are in the rust runtime. +fn compute_runtime_crates<'a>(metadata: &'a Metadata) -> HashSet<&'a PackageId> { + let resolve = metadata.resolve.as_ref().unwrap(); + let mut result = HashSet::new(); + for name in RUNTIME_CRATES { + let id = &pkg_from_name(metadata, name).id; + normal_deps_of_r(resolve, id, &mut result); + } + result +} + +/// Recursively find all normal dependencies. +fn normal_deps_of_r<'a>( + resolve: &'a Resolve, + pkg_id: &'a PackageId, + result: &mut HashSet<&'a PackageId>, +) { + if !result.insert(pkg_id) { + return; + } + let node = resolve + .nodes + .iter() + .find(|n| &n.id == pkg_id) + .unwrap_or_else(|| panic!("could not find `{}` in resolve", pkg_id)); + // Don't care about dev-dependencies. + // Build dependencies *shouldn't* matter unless they do some kind of + // codegen. For now we'll assume they don't. + let deps = node.deps.iter().filter(|node_dep| { + node_dep + .dep_kinds + .iter() + .any(|kind_info| kind_info.kind == cargo_metadata::DependencyKind::Normal) + }); + for dep in deps { + normal_deps_of_r(resolve, &dep.pkg, result); } } diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 909529d730784..e2856c690550a 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -30,10 +30,7 @@ fn main() { pal::check(&path, &mut bad); unstable_book::check(&path, collected, &mut bad); unit_tests::check(&path, &mut bad); - if !args.iter().any(|s| *s == "--no-vendor") { - deps::check(&path, &mut bad); - } - deps::check_whitelist(&path, &cargo, &mut bad); + deps::check(&path, &cargo, &mut bad); extdeps::check(&path, &mut bad); ui_tests::check(&path, &mut bad); error_codes_check::check(&path, &mut bad); diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index 349829d872507..247e85603cfc2 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -59,6 +59,8 @@ const EXCEPTION_PATHS: &[&str] = &[ "src/libstd/sys_common/mod.rs", "src/libstd/sys_common/net.rs", "src/libstd/sys_common/backtrace.rs", + // panic_unwind shims + "src/libstd/panicking.rs", "src/libterm", // Not sure how to make this crate portable, but test crate needs it. "src/libtest", // Probably should defer to unstable `std::sys` APIs. "src/libstd/sync/mpsc", // some tests are only run on non-emscripten diff --git a/triagebot.toml b/triagebot.toml index 13777d7a6c47d..2476f414e0e03 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -11,6 +11,7 @@ allow-unauthenticated = [ [assign] [ping.icebreakers-llvm] +alias = ["llvm", "llvms"] message = """\ Hey LLVM ICE-breakers! This bug has been identified as a good "LLVM ICE-breaking candidate". In case it's useful, here are some @@ -22,6 +23,7 @@ Thanks! <3 label = "ICEBreaker-LLVM" [ping.icebreakers-cleanup-crew] +alias = ["cleanup", "cleanups", "cleanup-crew", "shrink", "reduce", "bisect"] message = """\ Hey Cleanup Crew ICE-breakers! This bug has been identified as a good "Cleanup ICE-breaking candidate". In case it's useful, here are some