diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bf3c22744f165..7b9f87c079e3a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -152,10 +152,6 @@ jobs: - 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: @@ -373,35 +369,6 @@ jobs: 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" @@ -584,6 +551,135 @@ jobs: 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')" + auto-fallible: + name: auto-fallible + 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 + CACHE_DOMAIN: ci-caches-gha.rust-lang.org + if: "github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'" + strategy: + matrix: + include: + - 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 + 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 && github.ref != 'refs/heads/try'" + - name: add extra environment variables + run: src/ci/scripts/setup-environment.sh + env: + EXTRA_VARIABLES: "${{ toJson(matrix.env) }}" + if: success() && !env.SKIP_JOB + - name: decide whether to skip this job + run: src/ci/scripts/should-skip-this.sh + if: success() && !env.SKIP_JOB + - name: collect CPU statistics + run: src/ci/scripts/collect-cpu-stats.sh + if: success() && !env.SKIP_JOB + - name: show the current environment + run: src/ci/scripts/dump-environment.sh + if: success() && !env.SKIP_JOB + - name: install awscli + run: src/ci/scripts/install-awscli.sh + if: success() && !env.SKIP_JOB + - name: install sccache + run: src/ci/scripts/install-sccache.sh + if: success() && !env.SKIP_JOB + - name: install clang + run: src/ci/scripts/install-clang.sh + if: success() && !env.SKIP_JOB + - name: install WIX + run: src/ci/scripts/install-wix.sh + if: success() && !env.SKIP_JOB + - name: install InnoSetup + run: src/ci/scripts/install-innosetup.sh + if: success() && !env.SKIP_JOB + - name: ensure the build happens on a partition with enough space + run: src/ci/scripts/symlink-build-dir.sh + if: success() && !env.SKIP_JOB + - name: disable git crlf conversion + run: src/ci/scripts/disable-git-crlf-conversion.sh + if: success() && !env.SKIP_JOB + - name: install MSYS2 + run: src/ci/scripts/install-msys2.sh + if: success() && !env.SKIP_JOB + - name: install MinGW + run: src/ci/scripts/install-mingw.sh + if: success() && !env.SKIP_JOB + - name: install ninja + run: src/ci/scripts/install-ninja.sh + if: success() && !env.SKIP_JOB + - name: enable ipv6 on Docker + run: src/ci/scripts/enable-docker-ipv6.sh + if: success() && !env.SKIP_JOB + - name: disable git crlf conversion + run: src/ci/scripts/disable-git-crlf-conversion.sh + if: success() && !env.SKIP_JOB + - name: checkout submodules + run: src/ci/scripts/checkout-submodules.sh + if: success() && !env.SKIP_JOB + - name: ensure line endings are correct + run: src/ci/scripts/verify-line-endings.sh + 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 }}" + 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')" master: name: master runs-on: ubuntu-latest diff --git a/Cargo.lock b/Cargo.lock index 009767934d447..b54566e7176b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -434,9 +434,9 @@ dependencies = [ [[package]] name = "chalk-derive" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d4620afad4d4d9e63f915cfa10c930b7a3c9c3ca5cd88dd771ff8e5bf04ea10" +checksum = "5b9bd01eab87277d973183a1d2e56bace1c11f8242c52c20636fb7dddf343ac9" dependencies = [ "proc-macro2 1.0.3", "quote 1.0.2", @@ -446,58 +446,35 @@ dependencies = [ [[package]] name = "chalk-engine" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ca6e5cef10197789da0b4ec310eda58da4c55530613b2323432642a97372735" +checksum = "6c7a637c3d17ed555aef16e16952a5d1e127bd55178cc30be22afeb92da90c7d" dependencies = [ - "chalk-macros", + "chalk-derive", + "chalk-ir", "rustc-hash", ] [[package]] name = "chalk-ir" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d45df5fb6328527f976e8a32c9e1c9970084d937ebe93d0d34f5bbf4231cb956" +checksum = "595e5735ded16c3f3dc348f7b15bbb2521a0080b1863cac38ad5271589944670" dependencies = [ "chalk-derive", - "chalk-engine", - "chalk-macros", -] - -[[package]] -name = "chalk-macros" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e4782d108e420a1fcf94d8a919cf248db33c5071678e87d9c2d4f20ed1feb32" -dependencies = [ "lazy_static", ] -[[package]] -name = "chalk-rust-ir" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0ec96dbe0ab5fdbadfca4179ec2e1d35f0439c3b53a74988b1aec239c63eb08" -dependencies = [ - "chalk-derive", - "chalk-engine", - "chalk-ir", - "chalk-macros", -] - [[package]] name = "chalk-solve" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb99fa9530f0e101475fb60adc931f51bdea05b4642a48928b814d7f0141a6b" +checksum = "5d9d938139db425867a30cc0cfec0269406d8238d0571d829041eaa7a8455d11" dependencies = [ "chalk-derive", "chalk-engine", "chalk-ir", - "chalk-macros", - "chalk-rust-ir", - "ena 0.13.1", + "ena", "itertools 0.9.0", "petgraph", "rustc-hash", @@ -1061,15 +1038,6 @@ dependencies = [ "strum_macros", ] -[[package]] -name = "ena" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8944dc8fa28ce4a38f778bd46bf7d923fe73eed5a439398507246c8e017e6f36" -dependencies = [ - "log", -] - [[package]] name = "ena" version = "0.14.0" @@ -1181,9 +1149,9 @@ dependencies = [ [[package]] name = "fixedbitset" -version = "0.1.9" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" +checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" [[package]] name = "flate2" @@ -2370,12 +2338,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "ordermap" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" - [[package]] name = "ordslice" version = "0.3.0" @@ -2546,12 +2508,12 @@ dependencies = [ [[package]] name = "petgraph" -version = "0.4.13" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f" +checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" dependencies = [ "fixedbitset", - "ordermap", + "indexmap", ] [[package]] @@ -2780,9 +2742,9 @@ dependencies = [ [[package]] name = "racer" -version = "2.1.34" +version = "2.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc9caecf1286a3ed28d3ae35207a178ba12e58de95540781e5c6cba05e0f0833" +checksum = "421174f19211ba9e5fda34aa0cbc292188aae8e0cfbff4aebbae23f1a416bfb3" dependencies = [ "bitflags", "clap", @@ -3207,43 +3169,38 @@ dependencies = [ ] [[package]] -name = "rustc-ap-arena" -version = "659.0.0" +name = "rustc-ap-rustc_arena" +version = "664.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdaf0295fc40b10ec1091aad1a1760b4bb3b4e7c4f77d543d1a2e9d50a01e6b1" +checksum = "0c6683b49209f8b132bec33dc6b6c8f9958c8c94eb3586d4cb495e092b61c1da" dependencies = [ "rustc-ap-rustc_data_structures", "smallvec 1.4.0", ] -[[package]] -name = "rustc-ap-graphviz" -version = "659.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8028e8cdb4eb71810d0c22a5a5e1e3106c81123be63ce7f044b6d4ac100d8941" - [[package]] name = "rustc-ap-rustc_ast" -version = "659.0.0" +version = "664.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e9e502bb3a5568433db1cf2fb1f1e1074934636069cf744ad7c77b58e1428e" +checksum = "5b21784d92fb2d584800f528866f00fe814f73abda794f406bfd1fbb2f1ca7f7" dependencies = [ + "bitflags", "log", "rustc-ap-rustc_data_structures", "rustc-ap-rustc_index", "rustc-ap-rustc_lexer", "rustc-ap-rustc_macros", + "rustc-ap-rustc_serialize", "rustc-ap-rustc_span", - "rustc-ap-serialize", "scoped-tls", "smallvec 1.4.0", ] [[package]] name = "rustc-ap-rustc_ast_passes" -version = "659.0.0" +version = "664.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faf35ffecab28f97f7ac01cf6a13afaca6408529d15eb95f317a43b2ffb88933" +checksum = "820c46fde7ef1df0432073090d775f097b7279ca75ea34ba954081ce4b884d4c" dependencies = [ "itertools 0.8.0", "log", @@ -3260,20 +3217,21 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_ast_pretty" -version = "659.0.0" +version = "664.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3684ed43dc552f1e030e3f7a5a300a7a834bdda4e9e00ab80284be4220d8c603" +checksum = "013db7dd198fe95962d2cefa5bd0b350cf2028af77c169b17b4baa9c3bbf77d1" dependencies = [ "log", "rustc-ap-rustc_ast", "rustc-ap-rustc_span", + "rustc-ap-rustc_target", ] [[package]] name = "rustc-ap-rustc_attr" -version = "659.0.0" +version = "664.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31b413927daa666983b3b49227f9ac218aa29254546abdb585f20cd71c391870" +checksum = "35b5a85c90eb341eec543600ffdd9e262da5ea72a73a23ae4ca2f4ab8cd1a188" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_ast_pretty", @@ -3281,32 +3239,33 @@ dependencies = [ "rustc-ap-rustc_errors", "rustc-ap-rustc_feature", "rustc-ap-rustc_macros", + "rustc-ap-rustc_serialize", "rustc-ap-rustc_session", "rustc-ap-rustc_span", - "rustc-ap-serialize", "version_check", ] [[package]] name = "rustc-ap-rustc_data_structures" -version = "659.0.0" +version = "664.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b1c6069e5c522657f1c6f5ab33074e097092f48e804cc896d337e319aacbd60" +checksum = "b92e4c6cb6c43ee9031a71709dc12853b358253c2b41d12a26379994fab625e0" dependencies = [ "bitflags", "cfg-if", "crossbeam-utils 0.7.2", - "ena 0.14.0", + "ena", "indexmap", "jobserver", "lazy_static", "libc", "log", "measureme", + "once_cell", "parking_lot 0.10.2", - "rustc-ap-graphviz", + "rustc-ap-rustc_graphviz", "rustc-ap-rustc_index", - "rustc-ap-serialize", + "rustc-ap-rustc_serialize", "rustc-hash", "rustc-rayon", "rustc-rayon-core", @@ -3318,16 +3277,16 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "659.0.0" +version = "664.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c374e89b3c9714869ef86076942155383804ba6778c26be2169d324563c31f9" +checksum = "6b0aa79423260c1b9e2f856e144e040f606b0f5d43644408375becf9d7bcdf86" dependencies = [ - "annotate-snippets 0.6.1", + "annotate-snippets 0.8.0", "atty", "log", "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_serialize", "rustc-ap-rustc_span", - "rustc-ap-serialize", "termcolor", "termize", "unicode-width", @@ -3336,9 +3295,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_expand" -version = "659.0.0" +version = "664.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "259d2a7aa7a12f3c99a4ce4123643ec065f1a26f8e89be1f9bedd9757ea53fdc" +checksum = "c07d76ba2a1b7d4325a2ed21d6345ccebd89ddc6666a1535a6edd489fb4cbc11" dependencies = [ "log", "rustc-ap-rustc_ast", @@ -3350,17 +3309,17 @@ dependencies = [ "rustc-ap-rustc_feature", "rustc-ap-rustc_lexer", "rustc-ap-rustc_parse", + "rustc-ap-rustc_serialize", "rustc-ap-rustc_session", "rustc-ap-rustc_span", - "rustc-ap-serialize", "smallvec 1.4.0", ] [[package]] name = "rustc-ap-rustc_feature" -version = "659.0.0" +version = "664.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0296fbc29b629d5ae2ebee1bbf0407bb22de04d26d87216c20899b79579ccb3" +checksum = "1bbd625705c1db42a0c7503736292813d7b76ada5da20578fb55c63228c80ab5" dependencies = [ "lazy_static", "rustc-ap-rustc_data_structures", @@ -3369,34 +3328,40 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_fs_util" -version = "659.0.0" +version = "664.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34734f6cc681399630acd836a14207c6b5b9671a290cc7cad0354b0a4d71b3c9" +checksum = "34cca6e2942fa0b059c582437ead666d5bcf20fa7c242599e2bbea9b609f29ae" + +[[package]] +name = "rustc-ap-rustc_graphviz" +version = "664.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13d6a029b81f5e02da85763f82c135507f278a4a0c776432c728520563059529" [[package]] name = "rustc-ap-rustc_index" -version = "659.0.0" +version = "664.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1e4508753d71d3523209c2ca5086db15a1413e71ebf17ad5412bb7ced5e44c2" +checksum = "bae50852d303e230b2781c994513788136dc6c2fe4ebe032959f0b990a425767" dependencies = [ - "rustc-ap-serialize", + "rustc-ap-rustc_serialize", "smallvec 1.4.0", ] [[package]] name = "rustc-ap-rustc_lexer" -version = "659.0.0" +version = "664.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42b9fcd8407e322908a721262fbc0b35b5f3c35bb173a26dd1e0070bde336e33" +checksum = "b7186e74aa2d31bf0e2454325fefcdf0a3da77d9344134592144b9e40d45b15d" dependencies = [ "unicode-xid 0.2.0", ] [[package]] name = "rustc-ap-rustc_macros" -version = "659.0.0" +version = "664.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d104115a689367d2e0bcd99f37e0ebd6b9c8c78bab0d9cbea5bae86323601b5" +checksum = "4fc1add04e9d2301164118660ee0bc3266e9a7b1973fc2303fdbe002a12e5401" dependencies = [ "proc-macro2 1.0.3", "quote 1.0.2", @@ -3406,9 +3371,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_parse" -version = "659.0.0" +version = "664.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afaaab91853fc5a3916785ccae727a4433359d9787c260d42b96a2265fe5b287" +checksum = "9cd7fc4968bd60084f2fa4f280fa450b0cf98660a7983d6b93a7ae41b6d1d322" dependencies = [ "bitflags", "log", @@ -3423,11 +3388,21 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "rustc-ap-rustc_serialize" +version = "664.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00bf4c110271d9a2b7dfd2c6eb82e56fd80606a8bad6c102e158c54e44044046" +dependencies = [ + "indexmap", + "smallvec 1.4.0", +] + [[package]] name = "rustc-ap-rustc_session" -version = "659.0.0" +version = "664.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86e756a57ce6ce1b868e35e64a7e10ab28d49ece80d7c661b07aff5afc6e5d2d" +checksum = "431cf962de71d4c03fb877d54f331ec36eca77350b0539017abc40a4410d6501" dependencies = [ "getopts", "log", @@ -3437,26 +3412,25 @@ dependencies = [ "rustc-ap-rustc_errors", "rustc-ap-rustc_feature", "rustc-ap-rustc_fs_util", - "rustc-ap-rustc_index", + "rustc-ap-rustc_serialize", "rustc-ap-rustc_span", "rustc-ap-rustc_target", - "rustc-ap-serialize", ] [[package]] name = "rustc-ap-rustc_span" -version = "659.0.0" +version = "664.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21031c3396ee452f4c6e994b67513a633055c57c86d00336afd9d63149518f34" +checksum = "b912039640597624f4bcb75f1e1fcfa5710267d715a7f73a6336baef341b23d1" dependencies = [ "cfg-if", "log", "md-5", - "rustc-ap-arena", + "rustc-ap-rustc_arena", "rustc-ap-rustc_data_structures", "rustc-ap-rustc_index", "rustc-ap-rustc_macros", - "rustc-ap-serialize", + "rustc-ap-rustc_serialize", "scoped-tls", "sha-1", "unicode-width", @@ -3464,27 +3438,17 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_target" -version = "659.0.0" +version = "664.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff21badfbead5b0050391eaad8840f2e4fcb03b6b0fc6006f447443529e9ae6e" +checksum = "51347a9dadc5ad0b5916cc12d42624b31955285ad13745dbe72f0140038b84e9" dependencies = [ "bitflags", "log", "rustc-ap-rustc_data_structures", "rustc-ap-rustc_index", "rustc-ap-rustc_macros", + "rustc-ap-rustc_serialize", "rustc-ap-rustc_span", - "rustc-ap-serialize", -] - -[[package]] -name = "rustc-ap-serialize" -version = "659.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "768b5a305669d934522712bc13502962edfde5128ea63b9e7db4000410be1dc6" -dependencies = [ - "indexmap", - "smallvec 1.4.0", ] [[package]] @@ -3499,12 +3463,9 @@ dependencies = [ [[package]] name = "rustc-hash" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" -dependencies = [ - "byteorder", -] +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-main" @@ -3571,7 +3532,6 @@ dependencies = [ "serde_json", "smallvec 0.6.10", "smallvec 1.4.0", - "syn 0.15.35", "syn 1.0.11", "url 2.1.0", "winapi 0.3.8", @@ -3755,7 +3715,7 @@ dependencies = [ "bitflags", "cfg-if", "crossbeam-utils 0.7.2", - "ena 0.14.0", + "ena", "indexmap", "jobserver", "lazy_static", @@ -4240,6 +4200,7 @@ dependencies = [ "rustc_expand", "rustc_feature", "rustc_hir", + "rustc_index", "rustc_metadata", "rustc_middle", "rustc_session", @@ -4278,6 +4239,7 @@ dependencies = [ name = "rustc_session" version = "0.0.0" dependencies = [ + "bitflags", "getopts", "log", "num_cpus", @@ -4373,7 +4335,6 @@ name = "rustc_traits" version = "0.0.0" dependencies = [ "chalk-ir", - "chalk-rust-ir", "chalk-solve", "log", "rustc_ast", @@ -4481,16 +4442,16 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.4.15" +version = "1.4.18" dependencies = [ "annotate-snippets 0.6.1", + "anyhow", "bytecount", "cargo_metadata 0.8.0", "derive-new", "diff", "dirs", "env_logger 0.6.2", - "failure", "getopts", "ignore", "itertools 0.8.0", @@ -4512,6 +4473,7 @@ dependencies = [ "serde_json", "structopt", "term 0.6.0", + "thiserror", "toml", "unicode-segmentation", "unicode-width", diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 969d16d11e81b..82a755c7892b1 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -893,15 +893,18 @@ def bootstrap(help_triggered): build.verbose = args.verbose build.clean = args.clean - try: - toml_path = os.getenv('RUST_BOOTSTRAP_CONFIG') or args.config or 'config.toml' + # Read from `RUST_BOOTSTRAP_CONFIG`, then `--config`, then fallback to `config.toml` (if it + # exists). + toml_path = os.getenv('RUST_BOOTSTRAP_CONFIG') or args.config + if not toml_path and os.path.exists('config.toml'): + toml_path = 'config.toml' + + if toml_path: if not os.path.exists(toml_path): toml_path = os.path.join(build.rust_root, toml_path) with open(toml_path) as config: build.config_toml = config.read() - except (OSError, IOError): - pass config_verbose = build.get_toml('verbose', 'build') if config_verbose is not None: @@ -947,11 +950,12 @@ def bootstrap(help_triggered): env["SRC"] = build.rust_root env["BOOTSTRAP_PARENT_ID"] = str(os.getpid()) env["BOOTSTRAP_PYTHON"] = sys.executable - env["BOOTSTRAP_CONFIG"] = toml_path env["BUILD_DIR"] = build.build_dir env["RUSTC_BOOTSTRAP"] = '1' env["CARGO"] = build.cargo() env["RUSTC"] = build.rustc() + if toml_path: + env["BOOTSTRAP_CONFIG"] = toml_path if build.rustfmt(): env["RUSTFMT"] = build.rustfmt() run(args, env=env, verbose=build.verbose) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 58e4bef677efb..8f0a245a5658a 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1206,7 +1206,7 @@ impl<'a> Builder<'a> { ); } - // If Control Flow Guard is enabled, pass the `control_flow_guard=checks` flag to rustc + // If Control Flow Guard is enabled, pass the `control-flow-guard` flag to rustc // when compiling the standard library, since this might be linked into the final outputs // produced by rustc. Since this mitigation is only available on Windows, only enable it // for the standard library in case the compiler is run on a non-Windows platform. @@ -1217,7 +1217,7 @@ impl<'a> Builder<'a> { && self.config.control_flow_guard && compiler.stage >= 1 { - rustflags.arg("-Zcontrol_flow_guard=checks"); + rustflags.arg("-Zcontrol-flow-guard"); } // For `cargo doc` invocations, make rustdoc print the Rust version into the docs diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index d1e53db573e4c..47673ce1e8703 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -141,6 +141,8 @@ def v(*args): "rootfs in qemu testing, you probably don't want to use this") v("qemu-aarch64-rootfs", "target.aarch64-unknown-linux-gnu.qemu-rootfs", "rootfs in qemu testing, you probably don't want to use this") +v("qemu-riscv64-rootfs", "target.riscv64gc-unknown-linux-gnu.qemu-rootfs", + "rootfs in qemu testing, you probably don't want to use this") v("experimental-targets", "llvm.experimental-targets", "experimental LLVM targets to build") v("release-channel", "rust.channel", "the name of the release channel to build") diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 252a6316e574b..106db90b2d0f0 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -158,7 +158,6 @@ impl Step for Llvm { .define("LLVM_INCLUDE_TESTS", "OFF") .define("LLVM_INCLUDE_DOCS", "OFF") .define("LLVM_INCLUDE_BENCHMARKS", "OFF") - .define("LLVM_ENABLE_ZLIB", "OFF") .define("WITH_POLLY", "OFF") .define("LLVM_ENABLE_TERMINFO", "OFF") .define("LLVM_ENABLE_LIBEDIT", "OFF") @@ -168,6 +167,14 @@ impl Step for Llvm { .define("LLVM_TARGET_ARCH", target.split('-').next().unwrap()) .define("LLVM_DEFAULT_TARGET_TRIPLE", target); + if !target.contains("netbsd") { + cfg.define("LLVM_ENABLE_ZLIB", "ON"); + } else { + // FIXME: Enable zlib on NetBSD too + // https://github.com/rust-lang/rust/pull/72696#issuecomment-641517185 + cfg.define("LLVM_ENABLE_ZLIB", "OFF"); + } + if builder.config.llvm_thin_lto { cfg.define("LLVM_ENABLE_LTO", "Thin"); if !target.contains("apple") { @@ -689,48 +696,41 @@ fn supported_sanitizers( target: Interned, channel: &str, ) -> Vec { - let mut result = Vec::new(); + let darwin_libs = |os: &str, components: &[&str]| -> Vec { + components + .into_iter() + .map(move |c| SanitizerRuntime { + cmake_target: format!("clang_rt.{}_{}_dynamic", c, os), + path: out_dir + .join(&format!("build/lib/darwin/libclang_rt.{}_{}_dynamic.dylib", c, os)), + name: format!("librustc-{}_rt.{}.dylib", channel, c), + }) + .collect() + }; + + let common_libs = |os: &str, arch: &str, components: &[&str]| -> Vec { + components + .into_iter() + .map(move |c| SanitizerRuntime { + cmake_target: format!("clang_rt.{}-{}", c, arch), + path: out_dir.join(&format!("build/lib/{}/libclang_rt.{}-{}.a", os, c, arch)), + name: format!("librustc-{}_rt.{}.a", channel, c), + }) + .collect() + }; + match &*target { - "x86_64-apple-darwin" => { - for s in &["asan", "lsan", "tsan"] { - result.push(SanitizerRuntime { - cmake_target: format!("clang_rt.{}_osx_dynamic", s), - path: out_dir - .join(&format!("build/lib/darwin/libclang_rt.{}_osx_dynamic.dylib", s)), - name: format!("librustc-{}_rt.{}.dylib", channel, s), - }); - } + "aarch64-fuchsia" => common_libs("fuchsia", "aarch64", &["asan"]), + "aarch64-unknown-linux-gnu" => { + common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan"]) } + "x86_64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]), + "x86_64-fuchsia" => common_libs("fuchsia", "x86_64", &["asan"]), "x86_64-unknown-linux-gnu" => { - for s in &["asan", "lsan", "msan", "tsan"] { - result.push(SanitizerRuntime { - cmake_target: format!("clang_rt.{}-x86_64", s), - path: out_dir.join(&format!("build/lib/linux/libclang_rt.{}-x86_64.a", s)), - name: format!("librustc-{}_rt.{}.a", channel, s), - }); - } - } - "x86_64-fuchsia" => { - for s in &["asan"] { - result.push(SanitizerRuntime { - cmake_target: format!("clang_rt.{}-x86_64", s), - path: out_dir.join(&format!("build/lib/fuchsia/libclang_rt.{}-x86_64.a", s)), - name: format!("librustc-{}_rt.{}.a", channel, s), - }); - } - } - "aarch64-fuchsia" => { - for s in &["asan"] { - result.push(SanitizerRuntime { - cmake_target: format!("clang_rt.{}-aarch64", s), - path: out_dir.join(&format!("build/lib/fuchsia/libclang_rt.{}-aarch64.a", s)), - name: format!("librustc-{}_rt.{}.a", channel, s), - }); - } + common_libs("linux", "x86_64", &["asan", "lsan", "msan", "tsan"]) } - _ => {} + _ => Vec::new(), } - result } struct HashStamp { diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 8a37a70d60d9a..bb35203c82604 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -554,10 +554,7 @@ impl Step for Clippy { builder.add_rustc_lib_path(compiler, &mut cargo); - // FIXME: Disable clippy tests for now, they're failing on master - // (generally this would mean a toolstate failure but we don't have - // toolstate for clippy anymore). - // builder.run(&mut cargo.into()); + builder.run(&mut cargo.into()); } } diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 9c95de0a81eae..c92082a942316 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -481,7 +481,7 @@ impl Step for Rustdoc { const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src/tools/rustdoc") + run.path("src/tools/rustdoc").path("src/librustdoc") } fn make_run(run: RunConfig<'_>) { diff --git a/src/ci/azure-pipelines/try.yml b/src/ci/azure-pipelines/try.yml index 38a0685e0f75a..818306a009229 100644 --- a/src/ci/azure-pipelines/try.yml +++ b/src/ci/azure-pipelines/try.yml @@ -26,8 +26,6 @@ jobs: strategy: matrix: dist-x86_64-linux: {} - dist-x86_64-linux-alt: - IMAGE: dist-x86_64-linux # The macOS and Windows builds here are currently disabled due to them not being # overly necessary on `try` builds. We also don't actually have anything that diff --git a/src/ci/docker/disabled/riscv64gc-linux/0001-Remove-stime-function-calls.patch b/src/ci/docker/disabled/riscv64gc-linux/0001-Remove-stime-function-calls.patch new file mode 100644 index 0000000000000..08d0c5b2cac1e --- /dev/null +++ b/src/ci/docker/disabled/riscv64gc-linux/0001-Remove-stime-function-calls.patch @@ -0,0 +1,96 @@ +From c820da85c65c7f3aa9e9cb3ed71ada69bf9b783e Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Tue, 19 Nov 2019 13:06:40 +0100 +Subject: [PATCH] Remove stime() function calls + +stime() has been deprecated in glibc 2.31 and replaced with +clock_settime(). Let's replace the stime() function calls with +clock_settime() in preperation. + +function old new delta +rdate_main 197 224 +27 +clock_settime - 27 +27 +date_main 926 941 +15 +stime 37 - -37 +------------------------------------------------------------------------------ +(add/remove: 2/2 grow/shrink: 2/0 up/down: 69/-37) Total: 32 bytes + +Signed-off-by: Alistair Francis +Signed-off-by: Denys Vlasenko + +[Tom Eccles: adjust patch context to apply on top of 1.31.1-stable] +Signed-off-by: Tom Eccles +--- + coreutils/date.c | 6 +++++- + libbb/missing_syscalls.c | 8 -------- + util-linux/rdate.c | 8 ++++++-- + 3 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/coreutils/date.c b/coreutils/date.c +index 3414d38ae..4ade6abb4 100644 +--- a/coreutils/date.c ++++ b/coreutils/date.c +@@ -279,6 +279,9 @@ int date_main(int argc UNUSED_PARAM, char **argv) + time(&ts.tv_sec); + #endif + } ++#if !ENABLE_FEATURE_DATE_NANO ++ ts.tv_nsec = 0; ++#endif + localtime_r(&ts.tv_sec, &tm_time); + + /* If date string is given, update tm_time, and maybe set date */ +@@ -301,9 +304,10 @@ int date_main(int argc UNUSED_PARAM, char **argv) + if (date_str[0] != '@') + tm_time.tm_isdst = -1; + ts.tv_sec = validate_tm_time(date_str, &tm_time); ++ ts.tv_nsec = 0; + + /* if setting time, set it */ +- if ((opt & OPT_SET) && stime(&ts.tv_sec) < 0) { ++ if ((opt & OPT_SET) && clock_settime(CLOCK_REALTIME, &ts) < 0) { + bb_perror_msg("can't set date"); + } + } +diff --git a/libbb/missing_syscalls.c b/libbb/missing_syscalls.c +index 87cf59b3d..dc40d9155 100644 +--- a/libbb/missing_syscalls.c ++++ b/libbb/missing_syscalls.c +@@ -15,14 +15,6 @@ pid_t getsid(pid_t pid) + return syscall(__NR_getsid, pid); + } + +-int stime(const time_t *t) +-{ +- struct timeval tv; +- tv.tv_sec = *t; +- tv.tv_usec = 0; +- return settimeofday(&tv, NULL); +-} +- + int sethostname(const char *name, size_t len) + { + return syscall(__NR_sethostname, name, len); +diff --git a/util-linux/rdate.c b/util-linux/rdate.c +index 70f829e7f..878375d78 100644 +--- a/util-linux/rdate.c ++++ b/util-linux/rdate.c +@@ -95,9 +95,13 @@ int rdate_main(int argc UNUSED_PARAM, char **argv) + if (!(flags & 2)) { /* no -p (-s may be present) */ + if (time(NULL) == remote_time) + bb_error_msg("current time matches remote time"); +- else +- if (stime(&remote_time) < 0) ++ else { ++ struct timespec ts; ++ ts.tv_sec = remote_time; ++ ts.tv_nsec = 0; ++ if (clock_settime(CLOCK_REALTIME, &ts) < 0) + bb_perror_msg_and_die("can't set time of day"); ++ } + } + + if (flags != 1) /* not lone -s */ +-- +2.25.1 + diff --git a/src/ci/docker/disabled/riscv64gc-linux/Dockerfile b/src/ci/docker/disabled/riscv64gc-linux/Dockerfile new file mode 100644 index 0000000000000..f21dc2ba309b8 --- /dev/null +++ b/src/ci/docker/disabled/riscv64gc-linux/Dockerfile @@ -0,0 +1,102 @@ +# based on armhf-gnu/Dockerfile +FROM ubuntu:20.04 + +RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections +RUN apt-get update -y && apt-get install -y --no-install-recommends \ + bc \ + bison \ + ca-certificates \ + cmake \ + cpio \ + curl \ + debian-ports-archive-keyring \ + debootstrap \ + flex \ + gcc \ + gcc-riscv64-linux-gnu \ + git \ + g++-riscv64-linux-gnu \ + g++ \ + libc6-dev \ + libc6-dev-riscv64-cross \ + make \ + patch \ + python3 \ + qemu-system-misc \ + xz-utils + +ENV ARCH=riscv +ENV CROSS_COMPILE=riscv64-linux-gnu- + +WORKDIR /build + +# From https://github.com/michaeljclark/busybear-linux/blob/master/conf/linux.config +COPY riscv64gc-linux/linux.config /build + +# Compile the kernel that we're going to be emulating with. This is +# basically just done to be compatible with the QEMU target that we're going +# to be using when running tests. +RUN curl https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.6.16.tar.xz | tar xJf - && \ + cp linux.config linux-5.6.16/.config && \ + cd /build/linux-5.6.16 && \ + make olddefconfig && \ + make -j$(nproc) vmlinux +RUN cp linux-5.6.16/vmlinux /tmp +RUN rm -rf linux-5.6.16 + +# Compile an instance of busybox as this provides a lightweight system and init +# binary which we will boot into. Only trick here is configuring busybox to +# build static binaries. +RUN curl https://busybox.net/downloads/busybox-1.31.1.tar.bz2 | tar xjf - +COPY riscv64gc-linux/0001-Remove-stime-function-calls.patch /build/busybox-1.31.1/ +RUN cd /build/busybox-1.31.1 && \ + patch -p1 -i 0001-Remove-stime-function-calls.patch && \ + make defconfig && \ + sed -i 's/.*CONFIG_STATIC.*/CONFIG_STATIC=y/' .config && \ + make -j$(nproc) && \ + make install && \ + mv _install /tmp/rootfs && \ + cd /build && \ + rm -rf busybox-1.31.1 + +# Download the ubuntu rootfs, which we'll use as a chroot for all our tests +# This is only needed to provide /lib/* and /usr/lib/* +WORKDIR /tmp +RUN debootstrap --variant=minbase --arch=riscv64 --foreign focal /tmp/rootfs/ubuntu +RUN cd rootfs && mkdir proc sys dev etc etc/init.d +# rootfs/ubuntu/proc is in a weird state (access fails with ELOOP) until +# rootfs/ubuntu/debootstrap/debootstrap --second-stage is run (under emulation), +# but this takes ages. Instead hack it into a good enough state. +# /proc is used by std::env::current_exe() (which is roughly +# `readlink /proc/self/exe`) +RUN cd rootfs/ubuntu && rm -rf proc && mkdir proc + +# Copy over our init script, which starts up our test server and also a few other +# misc tasks +COPY scripts/qemu-bare-bones-rcS rootfs/etc/init.d/rcS +RUN chmod +x rootfs/etc/init.d/rcS + +# Helper to quickly fill the entropy pool in the kernel +COPY scripts/qemu-bare-bones-addentropy.c /tmp/addentropy.c +RUN riscv64-linux-gnu-gcc addentropy.c -o rootfs/addentropy -static + +# download and build the riscv bootloader +RUN git clone https://github.com/riscv/riscv-pk +WORKDIR /tmp/riscv-pk +# nothing special about this revision: it is just master at the time of writing +# v1.0.0 doesn't build +RUN git checkout 5d9ed238e1cabfbca3c47f50d32894ce94bfc304 +RUN mkdir build && cd build && \ + ../configure --with-payload=/tmp/vmlinux --host=riscv64-linux-gnu && \ + make -j$(nproc) && \ + cp bbl /tmp +WORKDIR /tmp +RUN rm -rf /tmp/riscv-pk + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +ENV RUST_CONFIGURE_ARGS --qemu-riscv64-rootfs=/tmp/rootfs +ENV SCRIPT python3 ../x.py test --target riscv64gc-unknown-linux-gnu + +ENV NO_CHANGE_USER=1 diff --git a/src/ci/docker/disabled/riscv64gc-linux/linux.config b/src/ci/docker/disabled/riscv64gc-linux/linux.config new file mode 100644 index 0000000000000..5142664742f20 --- /dev/null +++ b/src/ci/docker/disabled/riscv64gc-linux/linux.config @@ -0,0 +1,51 @@ +CONFIG_DEFAULT_HOSTNAME="busybear" +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_CGROUPS=y +CONFIG_CGROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y +CONFIG_CGROUP_BPF=y +CONFIG_NAMESPACES=y +CONFIG_USER_NS=y +CONFIG_CHECKPOINT_RESTORE=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_EXPERT=y +CONFIG_BPF_SYSCALL=y +CONFIG_SMP=y +CONFIG_MODULES=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_PACKET_DIAG=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_NETLINK_DIAG=y +# CONFIG_WIRELESS is not set +CONFIG_PCI=y +CONFIG_DEVTMPFS=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_VIRTIO_BLK=y +CONFIG_NETDEVICES=y +CONFIG_VIRTIO_NET=y +# CONFIG_ETHERNET is not set +# CONFIG_WLAN is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_HVC_RISCV_SBI=y +# CONFIG_HW_RANDOM is not set +# CONFIG_USB_SUPPORT is not set +CONFIG_VIRTIO_MMIO=y +CONFIG_SIFIVE_PLIC=y +CONFIG_RAS=y +CONFIG_EXT2_FS=y +CONFIG_EXT3_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_AUTOFS4_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +# CONFIG_CRYPTO_ECHAINIV is not set +# CONFIG_CRYPTO_HW is not set +CONFIG_PRINTK_TIME=y diff --git a/src/ci/docker/dist-aarch64-linux/Dockerfile b/src/ci/docker/dist-aarch64-linux/Dockerfile index 74766dc970d9f..fd764965ef21b 100644 --- a/src/ci/docker/dist-aarch64-linux/Dockerfile +++ b/src/ci/docker/dist-aarch64-linux/Dockerfile @@ -35,5 +35,6 @@ ENV HOSTS=aarch64-unknown-linux-gnu ENV RUST_CONFIGURE_ARGS \ --enable-full-tools \ --enable-profiler \ + --enable-sanitizers \ --disable-docs ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index a052d0879a3db..5e67567c76b4f 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -281,11 +281,6 @@ jobs: - 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 @@ -419,42 +414,6 @@ jobs: 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 # ###################### @@ -600,6 +559,51 @@ jobs: SCRIPT: python x.py dist <<: *job-windows-xl + auto-fallible: + <<: *base-ci-job + name: auto-fallible + env: + <<: [*shared-ci-variables, *prod-variables] + if: github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust' + strategy: + matrix: + include: + #################### + # 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 + master: name: master runs-on: ubuntu-latest diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index 7a7838d965bc7..30b18eb56a125 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -273,10 +273,18 @@ This flag, when combined with other flags, makes them produce extra output. This flag allows you to pass the name and location for an external crate of a direct dependency. Indirect dependencies (dependencies of dependencies) are located using the [`-L` flag](#option-l-search-path). The given crate name is -added to the [extern prelude], which is the same as specifying `extern crate` -within the root module. The given crate name does not need to match the name +added to the [extern prelude], similar to specifying `extern crate` within the +root module. The given crate name does not need to match the name the library was built with. +Specifying `--extern` has one behavior difference from `extern crate`: +`--extern` merely makes the crate a _candidate_ for being linked; it does not +actually link it unless it's actively used. In rare occasions you may wish +to ensure a crate is linked even if you don't actively use it from your +code: for example, if it changes the global allocator or if it contains +`#[no_mangle]` symbols for use by other programming languages. In such +cases you'll need to use `extern crate`. + This flag may be specified multiple times. This flag takes an argument with either of the following formats: diff --git a/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md b/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md index 48dea213e8cee..4115825e92083 100644 --- a/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md +++ b/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md @@ -1,10 +1,10 @@ -# `control_flow_guard` +# `control-flow-guard` The tracking issue for this feature is: [#68793](https://github.com/rust-lang/rust/issues/68793). ------------------------ -The rustc flag `-Z control_flow_guard=checks` enables the Windows [Control Flow Guard](https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard) (CFG) platform security feature. +The rustc flag `-Z control-flow-guard` enables the Windows [Control Flow Guard](https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard) (CFG) platform security feature. CFG is an exploit mitigation designed to enforce control-flow integrity for software running on supported Windows platforms (Windows 8.1 onwards). Specifically, CFG uses runtime checks to validate the target address of every indirect call/jump before allowing the call to complete. @@ -29,7 +29,7 @@ The CFG checks and metadata can potentially increase binary size and runtime ove ## Testing Control Flow Guard -The rustc flag `-Z control_flow_guard=nochecks` instructs LLVM to emit the list of valid call targets without inserting runtime checks. This flag should only be used for testing purposes as it does not provide security enforcement. +The rustc flag `-Z control-flow-guard=nochecks` instructs LLVM to emit the list of valid call targets without inserting runtime checks. This flag should only be used for testing purposes as it does not provide security enforcement. ## Control Flow Guard in libraries @@ -44,14 +44,14 @@ For example: ```cmd rustup toolchain install --force nightly rustup component add rust-src -SET RUSTFLAGS=-Z control_flow_guard=checks +SET RUSTFLAGS=-Z control-flow-guard cargo +nightly build -Z build-std --target x86_64-pc-windows-msvc ``` ```PowerShell rustup toolchain install --force nightly rustup component add rust-src -$Env:RUSTFLAGS = "-Z control_flow_guard=checks" +$Env:RUSTFLAGS = "-Z control-flow-guard" cargo +nightly build -Z build-std --target x86_64-pc-windows-msvc ``` diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md index 7ebd8054ba0b0..5e2e04c063bc4 100644 --- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -12,8 +12,7 @@ This feature allows for use of one of following sanitizers: * [ThreadSanitizer][clang-tsan] a fast data race detector. To enable a sanitizer compile with `-Zsanitizer=address`, `-Zsanitizer=leak`, -`-Zsanitizer=memory` or `-Zsanitizer=thread`. Only a single sanitizer can be -enabled at a time. +`-Zsanitizer=memory` or `-Zsanitizer=thread`. # AddressSanitizer diff --git a/src/doc/unstable-book/src/library-features/asm.md b/src/doc/unstable-book/src/library-features/asm.md index fbb40f1d2f3d4..a941bc9348f2c 100644 --- a/src/doc/unstable-book/src/library-features/asm.md +++ b/src/doc/unstable-book/src/library-features/asm.md @@ -68,10 +68,13 @@ Let us see another example that also uses an input: let i: u64 = 3; let o: u64; unsafe { - asm!(" - mov {0}, {1} - add {0}, {number} - ", out(reg) o, in(reg) i, number = const 5); + asm!( + "mov {0}, {1}", + "add {0}, {number}", + out(reg) o, + in(reg) i, + number = const 5, + ); } assert_eq!(o, 8); ``` @@ -82,13 +85,18 @@ and then adding `5` to it. The example shows a few things: -First we can see that inputs are declared by writing `in` instead of `out`. +First, we can see that `asm!` allows multiple template string arguments; each +one is treated as a separate line of assembly code, as if they were all joined +together with newlines between them. This makes it easy to format assembly +code. + +Second, we can see that inputs are declared by writing `in` instead of `out`. -Second one of our operands has a type we haven't seen yet, `const`. +Third, one of our operands has a type we haven't seen yet, `const`. This tells the compiler to expand this argument to value directly inside the assembly template. This is only possible for constants and literals. -Third we can see that we can specify an argument number, or name as in any format string. +Fourth, we can see that we can specify an argument number, or name as in any format string. For inline assembly templates this is particularly useful as arguments are often used more than once. For more complex inline assembly using this facility is generally recommended, as it improves readability, and allows reordering instructions without changing the argument order. @@ -137,10 +145,13 @@ let mut a: u64 = 4; let b: u64 = 4; let c: u64 = 4; unsafe { - asm!(" - add {0}, {1} - add {0}, {2} - ", inout(reg) a, in(reg) b, in(reg) c); + asm!( + "add {0}, {1}", + "add {0}, {2}", + inout(reg) a, + in(reg) b, + in(reg) c, + ); } assert_eq!(a, 12); ``` @@ -233,7 +244,7 @@ unsafe { // ECX 0 selects the L0 cache information. inout("ecx") 0 => ecx, lateout("ebx") ebx, - lateout("edx") _ + lateout("edx") _, ); } @@ -255,12 +266,14 @@ This can also be used with a general register class (e.g. `reg`) to obtain a scr // Multiply x by 6 using shifts and adds let mut x: u64 = 4; unsafe { - asm!(" - mov {tmp}, {x} - shl {tmp}, 1 - shl {x}, 2 - add {x}, {tmp} - ", x = inout(reg) x, tmp = out(reg) _); + asm!( + "mov {tmp}, {x}", + "shl {tmp}, 1", + "shl {x}, 2", + "add {x}, {tmp}", + x = inout(reg) x, + tmp = out(reg) _, + ); } assert_eq!(x, 4 * 6); ``` @@ -338,7 +351,7 @@ unsafe { asm!( "add {0}, {1}", inlateout(reg) a, in(reg) b, - options(pure, nomem, nostack) + options(pure, nomem, nostack), ); } assert_eq!(a, 8); @@ -371,24 +384,26 @@ reg_operand := dir_spec "(" reg_spec ")" operand_expr operand := reg_operand / "const" const_expr / "sym" path option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "att_syntax" options := "options(" option *["," option] [","] ")" -asm := "asm!(" format_string *("," [ident "="] operand) ["," options] [","] ")" +asm := "asm!(" format_string *("," format_string) *("," [ident "="] operand) ["," options] [","] ")" ``` -The macro will initially be supported only on ARM, AArch64, x86, x86-64 and RISC-V targets. Support for more targets may be added in the future. The compiler will emit an error if `asm!` is used on an unsupported target. +The macro will initially be supported only on ARM, AArch64, Hexagon, x86, x86-64 and RISC-V targets. Support for more targets may be added in the future. The compiler will emit an error if `asm!` is used on an unsupported target. [format-syntax]: https://doc.rust-lang.org/std/fmt/#syntax -## Template string +## Template string arguments The assembler template uses the same syntax as [format strings][format-syntax] (i.e. placeholders are specified by curly braces). The corresponding arguments are accessed in order, by index, or by name. However, implicit named arguments (introduced by [RFC #2795][rfc-2795]) are not supported. +An `asm!` invocation may have one or more template string arguments; an `asm!` with multiple template string arguments is treated as if all the strings were concatenated with a `\n` between them. The expected usage is for each template string argument to correspond to a line of assembly code. All template string arguments must appear before any other arguments. + As with format strings, named arguments must appear after positional arguments. Explicit register operands must appear at the end of the operand list, after named arguments if any. Explicit register operands cannot be used by placeholders in the template string. All other named and positional operands must appear at least once in the template string, otherwise a compiler error is generated. The exact assembly code syntax is target-specific and opaque to the compiler except for the way operands are substituted into the template string to form the code passed to the assembler. -The 4 targets specified in this RFC (x86, ARM, AArch64, RISC-V) all use the assembly code syntax of the GNU assembler (GAS). On x86, the `.intel_syntax noprefix` mode of GAS is used by default. On ARM, the `.syntax unified` mode is used. These targets impose an additional restriction on the assembly code: any assembler state (e.g. the current section which can be changed with `.section`) must be restored to its original value at the end of the asm string. Assembly code that does not conform to the GAS syntax will result in assembler-specific behavior. +The 5 targets specified in this RFC (x86, ARM, AArch64, RISC-V, Hexagon) all use the assembly code syntax of the GNU assembler (GAS). On x86, the `.intel_syntax noprefix` mode of GAS is used by default. On ARM, the `.syntax unified` mode is used. These targets impose an additional restriction on the assembly code: any assembler state (e.g. the current section which can be changed with `.section`) must be restored to its original value at the end of the asm string. Assembly code that does not conform to the GAS syntax will result in assembler-specific behavior. [rfc-2795]: https://github.com/rust-lang/rfcs/pull/2795 @@ -475,6 +490,7 @@ Here is the list of currently supported register classes: | NVPTX | `reg64` | None\* | `l` | | RISC-V | `reg` | `x1`, `x[5-7]`, `x[9-15]`, `x[16-31]` (non-RV32E) | `r` | | RISC-V | `freg` | `f[0-31]` | `f` | +| Hexagon | `reg` | `r[0-28]` | `r` | > **Note**: On x86 we treat `reg_byte` differently from `reg` because the compiler can allocate `al` and `ah` separately whereas `reg` reserves the whole register. > @@ -509,6 +525,7 @@ Each register class has constraints on which value types they can be used with. | RISC-V64 | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | | RISC-V | `freg` | `f` | `f32` | | RISC-V | `freg` | `d` | `f64` | +| Hexagon | `reg` | None | `i8`, `i16`, `i32`, `f32` | > **Note**: For the purposes of the above table pointers, function pointers and `isize`/`usize` are treated as the equivalent integer type (`i16`/`i32`/`i64` depending on the target). @@ -565,13 +582,16 @@ Some registers have multiple names. These are all treated by the compiler as ide | RISC-V | `f[10-17]` | `fa[0-7]` | | RISC-V | `f[18-27]` | `fs[2-11]` | | RISC-V | `f[28-31]` | `ft[8-11]` | +| Hexagon | `r29` | `sp` | +| Hexagon | `r30` | `fr` | +| Hexagon | `r31` | `lr` | Some registers cannot be used for input or output operands: | Architecture | Unsupported register | Reason | | ------------ | -------------------- | ------ | | All | `sp` | The stack pointer must be restored to its original value at the end of an asm code block. | -| All | `bp` (x86), `r11` (ARM), `x29` (AArch64), `x8` (RISC-V) | The frame pointer cannot be used as an input or output. | +| All | `bp` (x86), `r11` (ARM), `x29` (AArch64), `x8` (RISC-V), `fr` (Hexagon) | The frame pointer cannot be used as an input or output. | | x86 | `k0` | This is a constant zero register which can't be modified. | | x86 | `ip` | This is the program counter, not a real register. | | x86 | `mm[0-7]` | MMX registers are not currently supported (but may be in the future). | @@ -580,6 +600,7 @@ Some registers cannot be used for input or output operands: | ARM | `pc` | This is the program counter, not a real register. | | RISC-V | `x0` | This is a constant zero register which can't be modified. | | RISC-V | `gp`, `tp` | These registers are reserved and cannot be used as inputs or outputs. | +| Hexagon | `lr` | This is the link register which cannot be used as an input or output. | ## Template modifiers @@ -625,6 +646,7 @@ The supported modifiers are a subset of LLVM's (and GCC's) [asm template argumen | NVPTX | `reg64` | None | `rd0` | None | | RISC-V | `reg` | None | `x1` | None | | RISC-V | `freg` | None | `f0` | None | +| Hexagon | `reg` | None | `r0` | None | > Notes: > - on ARM `e` / `f`: this prints the low or high doubleword register name of a NEON quad (128-bit) register. diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index d31c73cc1bd8d..98c7ac3f2ef17 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/alloc.rs @@ -77,7 +77,7 @@ pub struct Global; #[stable(feature = "global_alloc", since = "1.28.0")] #[inline] pub unsafe fn alloc(layout: Layout) -> *mut u8 { - __rust_alloc(layout.size(), layout.align()) + unsafe { __rust_alloc(layout.size(), layout.align()) } } /// Deallocate memory with the global allocator. @@ -99,7 +99,7 @@ pub unsafe fn alloc(layout: Layout) -> *mut u8 { #[stable(feature = "global_alloc", since = "1.28.0")] #[inline] pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { - __rust_dealloc(ptr, layout.size(), layout.align()) + unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) } } /// Reallocate memory with the global allocator. @@ -121,7 +121,7 @@ pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { #[stable(feature = "global_alloc", since = "1.28.0")] #[inline] pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - __rust_realloc(ptr, layout.size(), layout.align(), new_size) + unsafe { __rust_realloc(ptr, layout.size(), layout.align(), new_size) } } /// Allocate zero-initialized memory with the global allocator. @@ -158,7 +158,7 @@ pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 #[stable(feature = "global_alloc", since = "1.28.0")] #[inline] pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { - __rust_alloc_zeroed(layout.size(), layout.align()) + unsafe { __rust_alloc_zeroed(layout.size(), layout.align()) } } #[unstable(feature = "allocator_api", issue = "32838")] @@ -183,7 +183,7 @@ unsafe impl AllocRef for Global { #[inline] unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout) { if layout.size() != 0 { - dealloc(ptr.as_ptr(), layout) + unsafe { dealloc(ptr.as_ptr(), layout) } } } @@ -209,16 +209,21 @@ unsafe impl AllocRef for Global { match placement { ReallocPlacement::InPlace => Err(AllocErr), ReallocPlacement::MayMove if layout.size() == 0 => { - let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); + let new_layout = + unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) }; self.alloc(new_layout, init) } ReallocPlacement::MayMove => { // `realloc` probably checks for `new_size > size` or something similar. - intrinsics::assume(new_size > size); - let ptr = realloc(ptr.as_ptr(), layout, new_size); + let ptr = unsafe { + intrinsics::assume(new_size > size); + realloc(ptr.as_ptr(), layout, new_size) + }; let memory = MemoryBlock { ptr: NonNull::new(ptr).ok_or(AllocErr)?, size: new_size }; - init.init_offset(memory, size); + unsafe { + init.init_offset(memory, size); + } Ok(memory) } } @@ -245,13 +250,17 @@ unsafe impl AllocRef for Global { match placement { ReallocPlacement::InPlace => Err(AllocErr), ReallocPlacement::MayMove if new_size == 0 => { - self.dealloc(ptr, layout); + unsafe { + self.dealloc(ptr, layout); + } Ok(MemoryBlock { ptr: layout.dangling(), size: 0 }) } ReallocPlacement::MayMove => { // `realloc` probably checks for `new_size < size` or something similar. - intrinsics::assume(new_size < size); - let ptr = realloc(ptr.as_ptr(), layout, new_size); + let ptr = unsafe { + intrinsics::assume(new_size < size); + realloc(ptr.as_ptr(), layout, new_size) + }; Ok(MemoryBlock { ptr: NonNull::new(ptr).ok_or(AllocErr)?, size: new_size }) } } @@ -264,7 +273,7 @@ unsafe impl AllocRef for Global { #[lang = "exchange_malloc"] #[inline] unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { - let layout = Layout::from_size_align_unchecked(size, align); + let layout = unsafe { Layout::from_size_align_unchecked(size, align) }; match Global.alloc(layout, AllocInit::Uninitialized) { Ok(memory) => memory.ptr.as_ptr(), Err(_) => handle_alloc_error(layout), @@ -279,10 +288,12 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { // For example if `Box` is changed to `struct Box(Unique, A)`, // this function has to be changed to `fn box_free(Unique, A)` as well. pub(crate) unsafe fn box_free(ptr: Unique) { - let size = size_of_val(ptr.as_ref()); - let align = min_align_of_val(ptr.as_ref()); - let layout = Layout::from_size_align_unchecked(size, align); - Global.dealloc(ptr.cast().into(), layout) + unsafe { + let size = size_of_val(ptr.as_ref()); + let align = min_align_of_val(ptr.as_ref()); + let layout = Layout::from_size_align_unchecked(size, align); + Global.dealloc(ptr.cast().into(), layout) + } } /// Abort on memory allocation error or failure. diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index ab0dde0ada660..d10cbf1afab30 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -311,7 +311,7 @@ impl Box> { #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Box { - Box::from_raw(Box::into_raw(self) as *mut T) + unsafe { Box::from_raw(Box::into_raw(self) as *mut T) } } } @@ -349,7 +349,7 @@ impl Box<[mem::MaybeUninit]> { #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Box<[T]> { - Box::from_raw(Box::into_raw(self) as *mut [T]) + unsafe { Box::from_raw(Box::into_raw(self) as *mut [T]) } } } @@ -393,7 +393,7 @@ impl Box { #[stable(feature = "box_raw", since = "1.4.0")] #[inline] pub unsafe fn from_raw(raw: *mut T) -> Self { - Box(Unique::new_unchecked(raw)) + Box(unsafe { Unique::new_unchecked(raw) }) } /// Consumes the `Box`, returning a wrapped raw pointer. diff --git a/src/liballoc/collections/binary_heap.rs b/src/liballoc/collections/binary_heap.rs index c2fe4691b34c0..15313e333ce73 100644 --- a/src/liballoc/collections/binary_heap.rs +++ b/src/liballoc/collections/binary_heap.rs @@ -1003,7 +1003,7 @@ impl<'a, T> Hole<'a, T> { unsafe fn new(data: &'a mut [T], pos: usize) -> Self { debug_assert!(pos < data.len()); // SAFE: pos should be inside the slice - let elt = ptr::read(data.get_unchecked(pos)); + let elt = unsafe { ptr::read(data.get_unchecked(pos)) }; Hole { data, elt: ManuallyDrop::new(elt), pos } } @@ -1025,7 +1025,7 @@ impl<'a, T> Hole<'a, T> { unsafe fn get(&self, index: usize) -> &T { debug_assert!(index != self.pos); debug_assert!(index < self.data.len()); - self.data.get_unchecked(index) + unsafe { self.data.get_unchecked(index) } } /// Move hole to new location @@ -1035,9 +1035,11 @@ impl<'a, T> Hole<'a, T> { unsafe fn move_to(&mut self, index: usize) { debug_assert!(index != self.pos); debug_assert!(index < self.data.len()); - let index_ptr: *const _ = self.data.get_unchecked(index); - let hole_ptr = self.data.get_unchecked_mut(self.pos); - ptr::copy_nonoverlapping(index_ptr, hole_ptr, 1); + unsafe { + let index_ptr: *const _ = self.data.get_unchecked(index); + let hole_ptr = self.data.get_unchecked_mut(self.pos); + ptr::copy_nonoverlapping(index_ptr, hole_ptr, 1); + } self.pos = index; } } diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index fa1c09d9ece87..350249f5db519 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -490,6 +490,8 @@ struct MergeIter> { impl BTreeMap { /// Makes a new empty BTreeMap with a reasonable choice for B. /// + /// Does not allocate anything on its own. + /// /// # Examples /// /// Basic usage: @@ -1725,7 +1727,7 @@ impl<'a, K: 'a, V: 'a> DrainFilterInner<'a, K, V> { &mut self, ) -> Option, K, V, marker::LeafOrInternal>, marker::KV>> { let edge = self.cur_leaf_edge.as_ref()?; - ptr::read(edge).next_kv().ok() + unsafe { ptr::read(edge).next_kv().ok() } } /// Implementation of a typical `DrainFilter::next` method, given the predicate. @@ -1808,7 +1810,7 @@ impl<'a, K, V> Range<'a, K, V> { } unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) { - unwrap_unchecked(self.front.as_mut()).next_unchecked() + unsafe { unwrap_unchecked(self.front.as_mut()).next_unchecked() } } } @@ -1821,7 +1823,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) { - unwrap_unchecked(self.back.as_mut()).next_back_unchecked() + unsafe { unwrap_unchecked(self.back.as_mut()).next_back_unchecked() } } } @@ -1859,7 +1861,7 @@ impl<'a, K, V> RangeMut<'a, K, V> { } unsafe fn next_unchecked(&mut self) -> (&'a mut K, &'a mut V) { - unwrap_unchecked(self.front.as_mut()).next_unchecked() + unsafe { unwrap_unchecked(self.front.as_mut()).next_unchecked() } } } @@ -1880,7 +1882,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) { - unwrap_unchecked(self.back.as_mut()).next_back_unchecked() + unsafe { unwrap_unchecked(self.back.as_mut()).next_back_unchecked() } } } diff --git a/src/liballoc/collections/btree/mod.rs b/src/liballoc/collections/btree/mod.rs index fb5825ee21a9e..543ff41a4d48d 100644 --- a/src/liballoc/collections/btree/mod.rs +++ b/src/liballoc/collections/btree/mod.rs @@ -19,7 +19,9 @@ pub unsafe fn unwrap_unchecked(val: Option) -> T { if cfg!(debug_assertions) { panic!("'unchecked' unwrap on None in BTreeMap"); } else { - core::intrinsics::unreachable(); + unsafe { + core::intrinsics::unreachable(); + } } }) } diff --git a/src/liballoc/collections/btree/navigate.rs b/src/liballoc/collections/btree/navigate.rs index 5e8dcf247ae59..5478d822438b1 100644 --- a/src/liballoc/collections/btree/navigate.rs +++ b/src/liballoc/collections/btree/navigate.rs @@ -64,8 +64,10 @@ macro_rules! def_next_kv_uncheched_dealloc { edge = match edge.$adjacent_kv() { Ok(internal_kv) => return internal_kv, Err(last_edge) => { - let parent_edge = last_edge.into_node().deallocate_and_ascend(); - unwrap_unchecked(parent_edge).forget_node_type() + unsafe { + let parent_edge = last_edge.into_node().deallocate_and_ascend(); + unwrap_unchecked(parent_edge).forget_node_type() + } } } } @@ -82,9 +84,11 @@ def_next_kv_uncheched_dealloc! {unsafe fn next_back_kv_unchecked_dealloc: left_k /// Safety: The change closure must not panic. #[inline] unsafe fn replace(v: &mut T, change: impl FnOnce(T) -> (T, R)) -> R { - let value = ptr::read(v); + let value = unsafe { ptr::read(v) }; let (new_value, ret) = change(value); - ptr::write(v, new_value); + unsafe { + ptr::write(v, new_value); + } ret } @@ -93,22 +97,26 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::Ed /// key and value in between. /// Unsafe because the caller must ensure that the leaf edge is not the last one in the tree. pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) { - replace(self, |leaf_edge| { - let kv = leaf_edge.next_kv(); - let kv = unwrap_unchecked(kv.ok()); - (kv.next_leaf_edge(), kv.into_kv()) - }) + unsafe { + replace(self, |leaf_edge| { + let kv = leaf_edge.next_kv(); + let kv = unwrap_unchecked(kv.ok()); + (kv.next_leaf_edge(), kv.into_kv()) + }) + } } /// Moves the leaf edge handle to the previous leaf edge and returns references to the /// key and value in between. /// Unsafe because the caller must ensure that the leaf edge is not the first one in the tree. pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) { - replace(self, |leaf_edge| { - let kv = leaf_edge.next_back_kv(); - let kv = unwrap_unchecked(kv.ok()); - (kv.next_back_leaf_edge(), kv.into_kv()) - }) + unsafe { + replace(self, |leaf_edge| { + let kv = leaf_edge.next_back_kv(); + let kv = unwrap_unchecked(kv.ok()); + (kv.next_back_leaf_edge(), kv.into_kv()) + }) + } } } @@ -119,14 +127,16 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::Edge /// - The caller must ensure that the leaf edge is not the last one in the tree. /// - Using the updated handle may well invalidate the returned references. pub unsafe fn next_unchecked(&mut self) -> (&'a mut K, &'a mut V) { - let kv = replace(self, |leaf_edge| { - let kv = leaf_edge.next_kv(); - let kv = unwrap_unchecked(kv.ok()); - (ptr::read(&kv).next_leaf_edge(), kv) - }); - // Doing the descend (and perhaps another move) invalidates the references - // returned by `into_kv_mut`, so we have to do this last. - kv.into_kv_mut() + unsafe { + let kv = replace(self, |leaf_edge| { + let kv = leaf_edge.next_kv(); + let kv = unwrap_unchecked(kv.ok()); + (ptr::read(&kv).next_leaf_edge(), kv) + }); + // Doing the descend (and perhaps another move) invalidates the references + // returned by `into_kv_mut`, so we have to do this last. + kv.into_kv_mut() + } } /// Moves the leaf edge handle to the previous leaf and returns references to the @@ -135,14 +145,16 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::Edge /// - The caller must ensure that the leaf edge is not the first one in the tree. /// - Using the updated handle may well invalidate the returned references. pub unsafe fn next_back_unchecked(&mut self) -> (&'a mut K, &'a mut V) { - let kv = replace(self, |leaf_edge| { - let kv = leaf_edge.next_back_kv(); - let kv = unwrap_unchecked(kv.ok()); - (ptr::read(&kv).next_back_leaf_edge(), kv) - }); - // Doing the descend (and perhaps another move) invalidates the references - // returned by `into_kv_mut`, so we have to do this last. - kv.into_kv_mut() + unsafe { + let kv = replace(self, |leaf_edge| { + let kv = leaf_edge.next_back_kv(); + let kv = unwrap_unchecked(kv.ok()); + (ptr::read(&kv).next_back_leaf_edge(), kv) + }); + // Doing the descend (and perhaps another move) invalidates the references + // returned by `into_kv_mut`, so we have to do this last. + kv.into_kv_mut() + } } } @@ -159,12 +171,14 @@ impl Handle, marker::Edge> { /// if the two preconditions above hold. /// - Using the updated handle may well invalidate the returned references. pub unsafe fn next_unchecked(&mut self) -> (K, V) { - replace(self, |leaf_edge| { - let kv = next_kv_unchecked_dealloc(leaf_edge); - let k = ptr::read(kv.reborrow().into_kv().0); - let v = ptr::read(kv.reborrow().into_kv().1); - (kv.next_leaf_edge(), (k, v)) - }) + unsafe { + replace(self, |leaf_edge| { + let kv = next_kv_unchecked_dealloc(leaf_edge); + let k = ptr::read(kv.reborrow().into_kv().0); + let v = ptr::read(kv.reborrow().into_kv().1); + (kv.next_leaf_edge(), (k, v)) + }) + } } /// Moves the leaf edge handle to the previous leaf edge and returns the key @@ -179,12 +193,14 @@ impl Handle, marker::Edge> { /// if the two preconditions above hold. /// - Using the updated handle may well invalidate the returned references. pub unsafe fn next_back_unchecked(&mut self) -> (K, V) { - replace(self, |leaf_edge| { - let kv = next_back_kv_unchecked_dealloc(leaf_edge); - let k = ptr::read(kv.reborrow().into_kv().0); - let v = ptr::read(kv.reborrow().into_kv().1); - (kv.next_back_leaf_edge(), (k, v)) - }) + unsafe { + replace(self, |leaf_edge| { + let kv = next_back_kv_unchecked_dealloc(leaf_edge); + let k = ptr::read(kv.reborrow().into_kv().0); + let v = ptr::read(kv.reborrow().into_kv().1); + (kv.next_back_leaf_edge(), (k, v)) + }) + } } } diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs index 5569c293e2f66..a4b6cf12a23bd 100644 --- a/src/liballoc/collections/btree/node.rs +++ b/src/liballoc/collections/btree/node.rs @@ -107,7 +107,7 @@ impl InternalNode { /// `len` of 0), there must be one initialized and valid edge. This function does not set up /// such an edge. unsafe fn new() -> Self { - InternalNode { data: LeafNode::new(), edges: [MaybeUninit::UNINIT; 2 * B] } + InternalNode { data: unsafe { LeafNode::new() }, edges: [MaybeUninit::UNINIT; 2 * B] } } } @@ -131,7 +131,7 @@ impl BoxedNode { } unsafe fn from_ptr(ptr: NonNull>) -> Self { - BoxedNode { ptr: Unique::new_unchecked(ptr.as_ptr()) } + BoxedNode { ptr: unsafe { Unique::new_unchecked(ptr.as_ptr()) } } } fn as_ptr(&self) -> NonNull> { @@ -392,14 +392,16 @@ impl NodeRef { let height = self.height; let node = self.node; let ret = self.ascend().ok(); - Global.dealloc( - node.cast(), - if height > 0 { - Layout::new::>() - } else { - Layout::new::>() - }, - ); + unsafe { + Global.dealloc( + node.cast(), + if height > 0 { + Layout::new::>() + } else { + Layout::new::>() + }, + ); + } ret } } @@ -565,7 +567,7 @@ impl<'a, K, V> NodeRef, K, V, marker::Internal> { debug_assert!(first <= self.len()); debug_assert!(after_last <= self.len() + 1); for i in first..after_last { - Handle::new_edge(self.reborrow_mut(), i).correct_parent_link(); + unsafe { Handle::new_edge(self.reborrow_mut(), i) }.correct_parent_link(); } } @@ -789,7 +791,7 @@ impl<'a, K, V, NodeType, HandleType> Handle, K, V, NodeT &mut self, ) -> Handle, K, V, NodeType>, HandleType> { // We can't use Handle::new_kv or Handle::new_edge because we don't know our type - Handle { node: self.node.reborrow_mut(), idx: self.idx, _marker: PhantomData } + Handle { node: unsafe { self.node.reborrow_mut() }, idx: self.idx, _marker: PhantomData } } } @@ -885,7 +887,7 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: unsafe fn cast_unchecked( &mut self, ) -> Handle, K, V, NewType>, marker::Edge> { - Handle::new_edge(self.node.cast_unchecked(), self.idx) + unsafe { Handle::new_edge(self.node.cast_unchecked(), self.idx) } } /// Inserts a new key/value pair and an edge that will go to the right of that new pair @@ -1330,8 +1332,10 @@ unsafe fn move_kv( dest_offset: usize, count: usize, ) { - ptr::copy_nonoverlapping(source.0.add(source_offset), dest.0.add(dest_offset), count); - ptr::copy_nonoverlapping(source.1.add(source_offset), dest.1.add(dest_offset), count); + unsafe { + ptr::copy_nonoverlapping(source.0.add(source_offset), dest.0.add(dest_offset), count); + ptr::copy_nonoverlapping(source.1.add(source_offset), dest.1.add(dest_offset), count); + } } // Source and destination must have the same height. @@ -1344,8 +1348,10 @@ unsafe fn move_edges( ) { let source_ptr = source.as_internal_mut().edges.as_mut_ptr(); let dest_ptr = dest.as_internal_mut().edges.as_mut_ptr(); - ptr::copy_nonoverlapping(source_ptr.add(source_offset), dest_ptr.add(dest_offset), count); - dest.correct_childrens_parent_links(dest_offset, dest_offset + count); + unsafe { + ptr::copy_nonoverlapping(source_ptr.add(source_offset), dest_ptr.add(dest_offset), count); + dest.correct_childrens_parent_links(dest_offset, dest_offset + count); + } } impl Handle, marker::Edge> { @@ -1459,12 +1465,16 @@ pub mod marker { } unsafe fn slice_insert(slice: &mut [T], idx: usize, val: T) { - ptr::copy(slice.as_ptr().add(idx), slice.as_mut_ptr().add(idx + 1), slice.len() - idx); - ptr::write(slice.get_unchecked_mut(idx), val); + unsafe { + ptr::copy(slice.as_ptr().add(idx), slice.as_mut_ptr().add(idx + 1), slice.len() - idx); + ptr::write(slice.get_unchecked_mut(idx), val); + } } unsafe fn slice_remove(slice: &mut [T], idx: usize) -> T { - let ret = ptr::read(slice.get_unchecked(idx)); - ptr::copy(slice.as_ptr().add(idx + 1), slice.as_mut_ptr().add(idx), slice.len() - idx - 1); - ret + unsafe { + let ret = ptr::read(slice.get_unchecked(idx)); + ptr::copy(slice.as_ptr().add(idx + 1), slice.as_mut_ptr().add(idx), slice.len() - idx - 1); + ret + } } diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs index 85f2505f756aa..36b5785fdf6c5 100644 --- a/src/liballoc/collections/linked_list.rs +++ b/src/liballoc/collections/linked_list.rs @@ -225,17 +225,17 @@ impl LinkedList { /// maintain validity of aliasing pointers. #[inline] unsafe fn unlink_node(&mut self, mut node: NonNull>) { - let node = node.as_mut(); // this one is ours now, we can create an &mut. + let node = unsafe { node.as_mut() }; // this one is ours now, we can create an &mut. // Not creating new mutable (unique!) references overlapping `element`. match node.prev { - Some(prev) => (*prev.as_ptr()).next = node.next, + Some(prev) => unsafe { (*prev.as_ptr()).next = node.next }, // this node is the head node None => self.head = node.next, }; match node.next { - Some(next) => (*next.as_ptr()).prev = node.prev, + Some(next) => unsafe { (*next.as_ptr()).prev = node.prev }, // this node is the tail node None => self.tail = node.prev, }; @@ -258,17 +258,23 @@ impl LinkedList { // This method takes care not to create multiple mutable references to whole nodes at the same time, // to maintain validity of aliasing pointers into `element`. if let Some(mut existing_prev) = existing_prev { - existing_prev.as_mut().next = Some(splice_start); + unsafe { + existing_prev.as_mut().next = Some(splice_start); + } } else { self.head = Some(splice_start); } if let Some(mut existing_next) = existing_next { - existing_next.as_mut().prev = Some(splice_end); + unsafe { + existing_next.as_mut().prev = Some(splice_end); + } } else { self.tail = Some(splice_end); } - splice_start.as_mut().prev = existing_prev; - splice_end.as_mut().next = existing_next; + unsafe { + splice_start.as_mut().prev = existing_prev; + splice_end.as_mut().next = existing_next; + } self.len += splice_length; } @@ -297,9 +303,13 @@ impl LinkedList { if let Some(mut split_node) = split_node { let first_part_head; let first_part_tail; - first_part_tail = split_node.as_mut().prev.take(); + unsafe { + first_part_tail = split_node.as_mut().prev.take(); + } if let Some(mut tail) = first_part_tail { - tail.as_mut().next = None; + unsafe { + tail.as_mut().next = None; + } first_part_head = self.head; } else { first_part_head = None; @@ -333,9 +343,13 @@ impl LinkedList { if let Some(mut split_node) = split_node { let second_part_head; let second_part_tail; - second_part_head = split_node.as_mut().next.take(); + unsafe { + second_part_head = split_node.as_mut().next.take(); + } if let Some(mut head) = second_part_head { - head.as_mut().prev = None; + unsafe { + head.as_mut().prev = None; + } second_part_tail = self.tail; } else { second_part_tail = None; diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index ae54d3971baac..15f3a94ca2d6a 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -7,6 +7,8 @@ #![stable(feature = "rust1", since = "1.0.0")] +// ignore-tidy-filelength + use core::array::LengthAtMost32; use core::cmp::{self, Ordering}; use core::fmt; @@ -201,25 +203,27 @@ impl VecDeque { /// Turn ptr into a slice #[inline] unsafe fn buffer_as_slice(&self) -> &[T] { - slice::from_raw_parts(self.ptr(), self.cap()) + unsafe { slice::from_raw_parts(self.ptr(), self.cap()) } } /// Turn ptr into a mut slice #[inline] unsafe fn buffer_as_mut_slice(&mut self) -> &mut [T] { - slice::from_raw_parts_mut(self.ptr(), self.cap()) + unsafe { slice::from_raw_parts_mut(self.ptr(), self.cap()) } } /// Moves an element out of the buffer #[inline] unsafe fn buffer_read(&mut self, off: usize) -> T { - ptr::read(self.ptr().add(off)) + unsafe { ptr::read(self.ptr().add(off)) } } /// Writes an element into the buffer, moving it. #[inline] unsafe fn buffer_write(&mut self, off: usize, value: T) { - ptr::write(self.ptr().add(off), value); + unsafe { + ptr::write(self.ptr().add(off), value); + } } /// Returns `true` if the buffer is at full capacity. @@ -268,7 +272,9 @@ impl VecDeque { len, self.cap() ); - ptr::copy(self.ptr().add(src), self.ptr().add(dst), len); + unsafe { + ptr::copy(self.ptr().add(src), self.ptr().add(dst), len); + } } /// Copies a contiguous block of memory len long from src to dst @@ -290,7 +296,9 @@ impl VecDeque { len, self.cap() ); - ptr::copy_nonoverlapping(self.ptr().add(src), self.ptr().add(dst), len); + unsafe { + ptr::copy_nonoverlapping(self.ptr().add(src), self.ptr().add(dst), len); + } } /// Copies a potentially wrapping block of memory len long from src to dest. @@ -330,7 +338,9 @@ impl VecDeque { // 2 [_ _ A A A A B B _] // D . . . // - self.copy(dst, src, len); + unsafe { + self.copy(dst, src, len); + } } (false, false, true) => { // dst before src, src doesn't wrap, dst wraps @@ -341,8 +351,10 @@ impl VecDeque { // 3 [B B B B _ _ _ A A] // . . D . // - self.copy(dst, src, dst_pre_wrap_len); - self.copy(0, src + dst_pre_wrap_len, len - dst_pre_wrap_len); + unsafe { + self.copy(dst, src, dst_pre_wrap_len); + self.copy(0, src + dst_pre_wrap_len, len - dst_pre_wrap_len); + } } (true, false, true) => { // src before dst, src doesn't wrap, dst wraps @@ -353,8 +365,10 @@ impl VecDeque { // 3 [B B _ _ _ A A A A] // . . D . // - self.copy(0, src + dst_pre_wrap_len, len - dst_pre_wrap_len); - self.copy(dst, src, dst_pre_wrap_len); + unsafe { + self.copy(0, src + dst_pre_wrap_len, len - dst_pre_wrap_len); + self.copy(dst, src, dst_pre_wrap_len); + } } (false, true, false) => { // dst before src, src wraps, dst doesn't wrap @@ -365,8 +379,10 @@ impl VecDeque { // 3 [C C _ _ _ B B C C] // D . . . // - self.copy(dst, src, src_pre_wrap_len); - self.copy(dst + src_pre_wrap_len, 0, len - src_pre_wrap_len); + unsafe { + self.copy(dst, src, src_pre_wrap_len); + self.copy(dst + src_pre_wrap_len, 0, len - src_pre_wrap_len); + } } (true, true, false) => { // src before dst, src wraps, dst doesn't wrap @@ -377,8 +393,10 @@ impl VecDeque { // 3 [C C A A _ _ _ C C] // D . . . // - self.copy(dst + src_pre_wrap_len, 0, len - src_pre_wrap_len); - self.copy(dst, src, src_pre_wrap_len); + unsafe { + self.copy(dst + src_pre_wrap_len, 0, len - src_pre_wrap_len); + self.copy(dst, src, src_pre_wrap_len); + } } (false, true, true) => { // dst before src, src wraps, dst wraps @@ -392,9 +410,11 @@ impl VecDeque { // debug_assert!(dst_pre_wrap_len > src_pre_wrap_len); let delta = dst_pre_wrap_len - src_pre_wrap_len; - self.copy(dst, src, src_pre_wrap_len); - self.copy(dst + src_pre_wrap_len, 0, delta); - self.copy(0, delta, len - dst_pre_wrap_len); + unsafe { + self.copy(dst, src, src_pre_wrap_len); + self.copy(dst + src_pre_wrap_len, 0, delta); + self.copy(0, delta, len - dst_pre_wrap_len); + } } (true, true, true) => { // src before dst, src wraps, dst wraps @@ -408,9 +428,11 @@ impl VecDeque { // debug_assert!(src_pre_wrap_len > dst_pre_wrap_len); let delta = src_pre_wrap_len - dst_pre_wrap_len; - self.copy(delta, 0, len - src_pre_wrap_len); - self.copy(0, self.cap() - delta, delta); - self.copy(dst, src, dst_pre_wrap_len); + unsafe { + self.copy(delta, 0, len - src_pre_wrap_len); + self.copy(0, self.cap() - delta, delta); + self.copy(dst, src, dst_pre_wrap_len); + } } } } @@ -440,13 +462,17 @@ impl VecDeque { // Nop } else if self.head < old_capacity - self.tail { // B - self.copy_nonoverlapping(old_capacity, 0, self.head); + unsafe { + self.copy_nonoverlapping(old_capacity, 0, self.head); + } self.head += old_capacity; debug_assert!(self.head > self.tail); } else { // C let new_tail = new_capacity - (old_capacity - self.tail); - self.copy_nonoverlapping(new_tail, self.tail, old_capacity - self.tail); + unsafe { + self.copy_nonoverlapping(new_tail, self.tail, old_capacity - self.tail); + } self.tail = new_tail; debug_assert!(self.head < self.tail); } @@ -2297,7 +2323,9 @@ impl VecDeque { unsafe fn rotate_left_inner(&mut self, mid: usize) { debug_assert!(mid * 2 <= self.len()); - self.wrap_copy(self.head, self.tail, mid); + unsafe { + self.wrap_copy(self.head, self.tail, mid); + } self.head = self.wrap_add(self.head, mid); self.tail = self.wrap_add(self.tail, mid); } @@ -2306,7 +2334,9 @@ impl VecDeque { debug_assert!(k * 2 <= self.len()); self.head = self.wrap_sub(self.head, k); self.tail = self.wrap_sub(self.tail, k); - self.wrap_copy(self.tail, self.head, k); + unsafe { + self.wrap_copy(self.tail, self.head, k); + } } } diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 9bcfc9457f50e..41c2b221704e6 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -72,6 +72,7 @@ #![deny(intra_doc_link_resolution_failure)] // rustdoc is run without -D warnings #![allow(explicit_outlives_requirements)] #![allow(incomplete_features)] +#![deny(unsafe_op_in_unsafe_fn)] #![cfg_attr(not(test), feature(generator_trait))] #![cfg_attr(test, feature(test))] #![feature(allocator_api)] @@ -118,6 +119,7 @@ #![feature(try_reserve)] #![feature(unboxed_closures)] #![feature(unicode_internals)] +#![feature(unsafe_block_in_unsafe_fn)] #![feature(unsize)] #![feature(unsized_locals)] #![feature(allocator_internals)] diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 805dbfe277584..67ebdcc9f33b1 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -60,7 +60,7 @@ impl RawVec { /// `#[rustc_force_min_const_fn]` attribute which requires conformance /// with `min_const_fn` but does not necessarily allow calling it in /// `stable(...) const fn` / user code not enabling `foo` when - /// `#[rustc_const_unstable(feature = "foo", ..)]` is present. + /// `#[rustc_const_unstable(feature = "foo", issue = "01234")]` is present. pub const NEW: Self = Self::new(); /// Creates the biggest possible `RawVec` (on the system heap) @@ -108,7 +108,7 @@ impl RawVec { /// If the `ptr` and `capacity` come from a `RawVec`, then this is guaranteed. #[inline] pub unsafe fn from_raw_parts(ptr: *mut T, capacity: usize) -> Self { - Self::from_raw_parts_in(ptr, capacity, Global) + unsafe { Self::from_raw_parts_in(ptr, capacity, Global) } } /// Converts a `Box<[T]>` into a `RawVec`. @@ -139,8 +139,10 @@ impl RawVec { ); let me = ManuallyDrop::new(self); - let slice = slice::from_raw_parts_mut(me.ptr() as *mut MaybeUninit, len); - Box::from_raw(slice) + unsafe { + let slice = slice::from_raw_parts_mut(me.ptr() as *mut MaybeUninit, len); + Box::from_raw(slice) + } } } @@ -192,7 +194,7 @@ impl RawVec { /// If the `ptr` and `capacity` come from a `RawVec` created via `a`, then this is guaranteed. #[inline] pub unsafe fn from_raw_parts_in(ptr: *mut T, capacity: usize, a: A) -> Self { - Self { ptr: Unique::new_unchecked(ptr), cap: capacity, alloc: a } + Self { ptr: unsafe { Unique::new_unchecked(ptr) }, cap: capacity, alloc: a } } /// Gets a raw pointer to the start of the allocation. Note that this is diff --git a/src/liballoc/raw_vec/tests.rs b/src/liballoc/raw_vec/tests.rs index 17622d72a059c..6418c4a9823f2 100644 --- a/src/liballoc/raw_vec/tests.rs +++ b/src/liballoc/raw_vec/tests.rs @@ -35,7 +35,7 @@ fn allocator_param() { } } unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout) { - Global.dealloc(ptr, layout) + unsafe { Global.dealloc(ptr, layout) } } } diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 0327a9f9a96e5..4d50ae9efca95 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -304,7 +304,7 @@ impl Rc { } unsafe fn from_ptr(ptr: *mut RcBox) -> Self { - Self::from_inner(NonNull::new_unchecked(ptr)) + Self::from_inner(unsafe { NonNull::new_unchecked(ptr) }) } } @@ -544,7 +544,7 @@ impl Rc<[mem::MaybeUninit]> { #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Rc<[T]> { - Rc::from_ptr(mem::ManuallyDrop::new(self).ptr.as_ptr() as _) + unsafe { Rc::from_ptr(mem::ManuallyDrop::new(self).ptr.as_ptr() as _) } } } @@ -643,13 +643,13 @@ impl Rc { /// ``` #[stable(feature = "rc_raw", since = "1.17.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { - let offset = data_offset(ptr); + let offset = unsafe { data_offset(ptr) }; // Reverse the offset to find the original RcBox. let fake_ptr = ptr as *mut RcBox; - let rc_ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset)); + let rc_ptr = unsafe { set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset)) }; - Self::from_ptr(rc_ptr) + unsafe { Self::from_ptr(rc_ptr) } } /// Consumes the `Rc`, returning the wrapped pointer as `NonNull`. @@ -805,7 +805,7 @@ impl Rc { #[inline] #[unstable(feature = "get_mut_unchecked", issue = "63292")] pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { - &mut this.ptr.as_mut().value + unsafe { &mut this.ptr.as_mut().value } } #[inline] @@ -964,10 +964,12 @@ impl Rc { // Initialize the RcBox let inner = mem_to_rcbox(mem.ptr.as_ptr()); - debug_assert_eq!(Layout::for_value(&*inner), layout); + unsafe { + debug_assert_eq!(Layout::for_value(&*inner), layout); - ptr::write(&mut (*inner).strong, Cell::new(1)); - ptr::write(&mut (*inner).weak, Cell::new(1)); + ptr::write(&mut (*inner).strong, Cell::new(1)); + ptr::write(&mut (*inner).weak, Cell::new(1)); + } inner } @@ -975,9 +977,11 @@ impl Rc { /// Allocates an `RcBox` with sufficient space for an unsized inner value unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox { // Allocate for the `RcBox` using the given value. - Self::allocate_for_layout(Layout::for_value(&*ptr), |mem| { - set_data_ptr(ptr as *mut T, mem) as *mut RcBox - }) + unsafe { + Self::allocate_for_layout(Layout::for_value(&*ptr), |mem| { + set_data_ptr(ptr as *mut T, mem) as *mut RcBox + }) + } } fn from_box(v: Box) -> Rc { @@ -1006,9 +1010,11 @@ impl Rc { impl Rc<[T]> { /// Allocates an `RcBox<[T]>` with the given length. unsafe fn allocate_for_slice(len: usize) -> *mut RcBox<[T]> { - Self::allocate_for_layout(Layout::array::(len).unwrap(), |mem| { - ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut RcBox<[T]> - }) + unsafe { + Self::allocate_for_layout(Layout::array::(len).unwrap(), |mem| { + ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut RcBox<[T]> + }) + } } } @@ -1017,7 +1023,9 @@ impl Rc<[T]> { /// For a slice/trait object, this sets the `data` field and leaves the rest /// unchanged. For a sized raw pointer, this simply sets the pointer. unsafe fn set_data_ptr(mut ptr: *mut T, data: *mut U) -> *mut T { - ptr::write(&mut ptr as *mut _ as *mut *mut u8, data as *mut u8); + unsafe { + ptr::write(&mut ptr as *mut _ as *mut *mut u8, data as *mut u8); + } ptr } @@ -1026,11 +1034,11 @@ impl Rc<[T]> { /// /// Unsafe because the caller must either take ownership or bind `T: Copy` unsafe fn copy_from_slice(v: &[T]) -> Rc<[T]> { - let ptr = Self::allocate_for_slice(v.len()); - - ptr::copy_nonoverlapping(v.as_ptr(), &mut (*ptr).value as *mut [T] as *mut T, v.len()); - - Self::from_ptr(ptr) + unsafe { + let ptr = Self::allocate_for_slice(v.len()); + ptr::copy_nonoverlapping(v.as_ptr(), &mut (*ptr).value as *mut [T] as *mut T, v.len()); + Self::from_ptr(ptr) + } } /// Constructs an `Rc<[T]>` from an iterator known to be of a certain size. @@ -1058,25 +1066,27 @@ impl Rc<[T]> { } } - let ptr = Self::allocate_for_slice(len); + unsafe { + let ptr = Self::allocate_for_slice(len); - let mem = ptr as *mut _ as *mut u8; - let layout = Layout::for_value(&*ptr); + let mem = ptr as *mut _ as *mut u8; + let layout = Layout::for_value(&*ptr); - // Pointer to first element - let elems = &mut (*ptr).value as *mut [T] as *mut T; + // Pointer to first element + let elems = &mut (*ptr).value as *mut [T] as *mut T; - let mut guard = Guard { mem: NonNull::new_unchecked(mem), elems, layout, n_elems: 0 }; + let mut guard = Guard { mem: NonNull::new_unchecked(mem), elems, layout, n_elems: 0 }; - for (i, item) in iter.enumerate() { - ptr::write(elems.add(i), item); - guard.n_elems += 1; - } + for (i, item) in iter.enumerate() { + ptr::write(elems.add(i), item); + guard.n_elems += 1; + } - // All clear. Forget the guard so it doesn't free the new RcBox. - forget(guard); + // All clear. Forget the guard so it doesn't free the new RcBox. + forget(guard); - Self::from_ptr(ptr) + Self::from_ptr(ptr) + } } } @@ -1786,10 +1796,12 @@ impl Weak { Self::new() } else { // See Rc::from_raw for details - let offset = data_offset(ptr); - let fake_ptr = ptr as *mut RcBox; - let ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset)); - Weak { ptr: NonNull::new(ptr).expect("Invalid pointer passed to from_raw") } + unsafe { + let offset = data_offset(ptr); + let fake_ptr = ptr as *mut RcBox; + let ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset)); + Weak { ptr: NonNull::new(ptr).expect("Invalid pointer passed to from_raw") } + } } } } @@ -2106,7 +2118,7 @@ unsafe fn data_offset(ptr: *const T) -> isize { // Because it is ?Sized, it will always be the last field in memory. // Note: This is a detail of the current implementation of the compiler, // and is not a guaranteed language detail. Do not rely on it outside of std. - data_offset_align(align_of_val(&*ptr)) + unsafe { data_offset_align(align_of_val(&*ptr)) } } /// Computes the offset of the data field within `RcBox`. diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 53477288b59ee..d7dc2174d665f 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -831,8 +831,7 @@ where { let len = v.len(); let v = v.as_mut_ptr(); - let v_mid = v.add(mid); - let v_end = v.add(len); + let (v_mid, v_end) = unsafe { (v.add(mid), v.add(len)) }; // The merge process first copies the shorter run into `buf`. Then it traces the newly copied // run and the longer run forwards (or backwards), comparing their next unconsumed elements and @@ -855,8 +854,10 @@ where if mid <= len - mid { // The left run is shorter. - ptr::copy_nonoverlapping(v, buf, mid); - hole = MergeHole { start: buf, end: buf.add(mid), dest: v }; + unsafe { + ptr::copy_nonoverlapping(v, buf, mid); + hole = MergeHole { start: buf, end: buf.add(mid), dest: v }; + } // Initially, these pointers point to the beginnings of their arrays. let left = &mut hole.start; @@ -866,17 +867,21 @@ where while *left < hole.end && right < v_end { // Consume the lesser side. // If equal, prefer the left run to maintain stability. - let to_copy = if is_less(&*right, &**left) { - get_and_increment(&mut right) - } else { - get_and_increment(left) - }; - ptr::copy_nonoverlapping(to_copy, get_and_increment(out), 1); + unsafe { + let to_copy = if is_less(&*right, &**left) { + get_and_increment(&mut right) + } else { + get_and_increment(left) + }; + ptr::copy_nonoverlapping(to_copy, get_and_increment(out), 1); + } } } else { // The right run is shorter. - ptr::copy_nonoverlapping(v_mid, buf, len - mid); - hole = MergeHole { start: buf, end: buf.add(len - mid), dest: v_mid }; + unsafe { + ptr::copy_nonoverlapping(v_mid, buf, len - mid); + hole = MergeHole { start: buf, end: buf.add(len - mid), dest: v_mid }; + } // Initially, these pointers point past the ends of their arrays. let left = &mut hole.dest; @@ -886,12 +891,14 @@ where while v < *left && buf < *right { // Consume the greater side. // If equal, prefer the right run to maintain stability. - let to_copy = if is_less(&*right.offset(-1), &*left.offset(-1)) { - decrement_and_get(left) - } else { - decrement_and_get(right) - }; - ptr::copy_nonoverlapping(to_copy, decrement_and_get(&mut out), 1); + unsafe { + let to_copy = if is_less(&*right.offset(-1), &*left.offset(-1)) { + decrement_and_get(left) + } else { + decrement_and_get(right) + }; + ptr::copy_nonoverlapping(to_copy, decrement_and_get(&mut out), 1); + } } } // Finally, `hole` gets dropped. If the shorter run was not fully consumed, whatever remains of @@ -899,12 +906,12 @@ where unsafe fn get_and_increment(ptr: &mut *mut T) -> *mut T { let old = *ptr; - *ptr = ptr.offset(1); + *ptr = unsafe { ptr.offset(1) }; old } unsafe fn decrement_and_get(ptr: &mut *mut T) -> *mut T { - *ptr = ptr.offset(-1); + *ptr = unsafe { ptr.offset(-1) }; *ptr } diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index 70860c09a2c31..57927c688479b 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -583,5 +583,5 @@ impl str { #[stable(feature = "str_box_extras", since = "1.20.0")] #[inline] pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box { - Box::from_raw(Box::into_raw(v) as *mut str) + unsafe { Box::from_raw(Box::into_raw(v) as *mut str) } } diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 0378ff5362a8b..64d9692244dde 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -724,7 +724,7 @@ impl String { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts(buf: *mut u8, length: usize, capacity: usize) -> String { - String { vec: Vec::from_raw_parts(buf, length, capacity) } + unsafe { String { vec: Vec::from_raw_parts(buf, length, capacity) } } } /// Converts a vector of bytes to a `String` without checking that the @@ -1329,9 +1329,11 @@ impl String { let amt = bytes.len(); self.vec.reserve(amt); - ptr::copy(self.vec.as_ptr().add(idx), self.vec.as_mut_ptr().add(idx + amt), len - idx); - ptr::copy(bytes.as_ptr(), self.vec.as_mut_ptr().add(idx), amt); - self.vec.set_len(len + amt); + unsafe { + ptr::copy(self.vec.as_ptr().add(idx), self.vec.as_mut_ptr().add(idx + amt), len - idx); + ptr::copy(bytes.as_ptr(), self.vec.as_mut_ptr().add(idx), amt); + self.vec.set_len(len + amt); + } } /// Inserts a string slice into this `String` at a byte position. @@ -2228,6 +2230,14 @@ impl ToString for T { } } +#[stable(feature = "char_to_string_specialization", since = "1.46.0")] +impl ToString for char { + #[inline] + fn to_string(&self) -> String { + String::from(self.encode_utf8(&mut [0; 4])) + } +} + #[stable(feature = "str_to_string_specialization", since = "1.9.0")] impl ToString for str { #[inline] diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index cd4172d6a2d24..826f0c8fa833f 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -232,7 +232,7 @@ impl Arc { } unsafe fn from_ptr(ptr: *mut ArcInner) -> Self { - Self::from_inner(NonNull::new_unchecked(ptr)) + unsafe { Self::from_inner(NonNull::new_unchecked(ptr)) } } } @@ -543,7 +543,7 @@ impl Arc<[mem::MaybeUninit]> { #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Arc<[T]> { - Arc::from_ptr(mem::ManuallyDrop::new(self).ptr.as_ptr() as _) + unsafe { Arc::from_ptr(mem::ManuallyDrop::new(self).ptr.as_ptr() as _) } } } @@ -642,13 +642,15 @@ impl Arc { /// ``` #[stable(feature = "rc_raw", since = "1.17.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { - let offset = data_offset(ptr); + unsafe { + let offset = data_offset(ptr); - // Reverse the offset to find the original ArcInner. - let fake_ptr = ptr as *mut ArcInner; - let arc_ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset)); + // Reverse the offset to find the original ArcInner. + let fake_ptr = ptr as *mut ArcInner; + let arc_ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset)); - Self::from_ptr(arc_ptr) + Self::from_ptr(arc_ptr) + } } /// Consumes the `Arc`, returning the wrapped pointer as `NonNull`. @@ -807,7 +809,7 @@ impl Arc { #[unstable(feature = "arc_mutate_strong_count", issue = "71983")] pub unsafe fn incr_strong_count(ptr: *const T) { // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop - let arc = mem::ManuallyDrop::new(Arc::::from_raw(ptr)); + let arc = unsafe { mem::ManuallyDrop::new(Arc::::from_raw(ptr)) }; // Now increase refcount, but don't drop new refcount either let _arc_clone: mem::ManuallyDrop<_> = arc.clone(); } @@ -847,7 +849,7 @@ impl Arc { #[inline] #[unstable(feature = "arc_mutate_strong_count", issue = "71983")] pub unsafe fn decr_strong_count(ptr: *const T) { - mem::drop(Arc::from_raw(ptr)); + unsafe { mem::drop(Arc::from_raw(ptr)) }; } #[inline] @@ -865,7 +867,7 @@ impl Arc { unsafe fn drop_slow(&mut self) { // Destroy the data at this time, even though we may not free the box // allocation itself (there may still be weak pointers lying around). - ptr::drop_in_place(Self::get_mut_unchecked(self)); + unsafe { ptr::drop_in_place(Self::get_mut_unchecked(self)) }; // Drop the weak ref collectively held by all strong references drop(Weak { ptr: self.ptr }); @@ -917,10 +919,12 @@ impl Arc { // Initialize the ArcInner let inner = mem_to_arcinner(mem.ptr.as_ptr()); - debug_assert_eq!(Layout::for_value(&*inner), layout); + debug_assert_eq!(unsafe { Layout::for_value(&*inner) }, layout); - ptr::write(&mut (*inner).strong, atomic::AtomicUsize::new(1)); - ptr::write(&mut (*inner).weak, atomic::AtomicUsize::new(1)); + unsafe { + ptr::write(&mut (*inner).strong, atomic::AtomicUsize::new(1)); + ptr::write(&mut (*inner).weak, atomic::AtomicUsize::new(1)); + } inner } @@ -928,9 +932,11 @@ impl Arc { /// Allocates an `ArcInner` with sufficient space for an unsized inner value. unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner { // Allocate for the `ArcInner` using the given value. - Self::allocate_for_layout(Layout::for_value(&*ptr), |mem| { - set_data_ptr(ptr as *mut T, mem) as *mut ArcInner - }) + unsafe { + Self::allocate_for_layout(Layout::for_value(&*ptr), |mem| { + set_data_ptr(ptr as *mut T, mem) as *mut ArcInner + }) + } } fn from_box(v: Box) -> Arc { @@ -959,9 +965,11 @@ impl Arc { impl Arc<[T]> { /// Allocates an `ArcInner<[T]>` with the given length. unsafe fn allocate_for_slice(len: usize) -> *mut ArcInner<[T]> { - Self::allocate_for_layout(Layout::array::(len).unwrap(), |mem| { - ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut ArcInner<[T]> - }) + unsafe { + Self::allocate_for_layout(Layout::array::(len).unwrap(), |mem| { + ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut ArcInner<[T]> + }) + } } } @@ -970,7 +978,9 @@ impl Arc<[T]> { /// For a slice/trait object, this sets the `data` field and leaves the rest /// unchanged. For a sized raw pointer, this simply sets the pointer. unsafe fn set_data_ptr(mut ptr: *mut T, data: *mut U) -> *mut T { - ptr::write(&mut ptr as *mut _ as *mut *mut u8, data as *mut u8); + unsafe { + ptr::write(&mut ptr as *mut _ as *mut *mut u8, data as *mut u8); + } ptr } @@ -979,11 +989,13 @@ impl Arc<[T]> { /// /// Unsafe because the caller must either take ownership or bind `T: Copy`. unsafe fn copy_from_slice(v: &[T]) -> Arc<[T]> { - let ptr = Self::allocate_for_slice(v.len()); + unsafe { + let ptr = Self::allocate_for_slice(v.len()); - ptr::copy_nonoverlapping(v.as_ptr(), &mut (*ptr).data as *mut [T] as *mut T, v.len()); + ptr::copy_nonoverlapping(v.as_ptr(), &mut (*ptr).data as *mut [T] as *mut T, v.len()); - Self::from_ptr(ptr) + Self::from_ptr(ptr) + } } /// Constructs an `Arc<[T]>` from an iterator known to be of a certain size. @@ -1011,25 +1023,27 @@ impl Arc<[T]> { } } - let ptr = Self::allocate_for_slice(len); + unsafe { + let ptr = Self::allocate_for_slice(len); - let mem = ptr as *mut _ as *mut u8; - let layout = Layout::for_value(&*ptr); + let mem = ptr as *mut _ as *mut u8; + let layout = Layout::for_value(&*ptr); - // Pointer to first element - let elems = &mut (*ptr).data as *mut [T] as *mut T; + // Pointer to first element + let elems = &mut (*ptr).data as *mut [T] as *mut T; - let mut guard = Guard { mem: NonNull::new_unchecked(mem), elems, layout, n_elems: 0 }; + let mut guard = Guard { mem: NonNull::new_unchecked(mem), elems, layout, n_elems: 0 }; - for (i, item) in iter.enumerate() { - ptr::write(elems.add(i), item); - guard.n_elems += 1; - } + for (i, item) in iter.enumerate() { + ptr::write(elems.add(i), item); + guard.n_elems += 1; + } - // All clear. Forget the guard so it doesn't free the new ArcInner. - mem::forget(guard); + // All clear. Forget the guard so it doesn't free the new ArcInner. + mem::forget(guard); - Self::from_ptr(ptr) + Self::from_ptr(ptr) + } } } @@ -1274,7 +1288,7 @@ impl Arc { pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { // We are careful to *not* create a reference covering the "count" fields, as // this would alias with concurrent access to the reference counts (e.g. by `Weak`). - &mut (*this.ptr.as_ptr()).data + unsafe { &mut (*this.ptr.as_ptr()).data } } /// Determine whether this is the unique reference (including weak refs) to @@ -1551,10 +1565,12 @@ impl Weak { Self::new() } else { // See Arc::from_raw for details - let offset = data_offset(ptr); - let fake_ptr = ptr as *mut ArcInner; - let ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset)); - Weak { ptr: NonNull::new(ptr).expect("Invalid pointer passed to from_raw") } + unsafe { + let offset = data_offset(ptr); + let fake_ptr = ptr as *mut ArcInner; + let ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset)); + Weak { ptr: NonNull::new(ptr).expect("Invalid pointer passed to from_raw") } + } } } } @@ -2260,7 +2276,7 @@ unsafe fn data_offset(ptr: *const T) -> isize { // Because it is `?Sized`, it will always be the last field in memory. // Note: This is a detail of the current implementation of the compiler, // and is not a guaranteed language detail. Do not rely on it outside of std. - data_offset_align(align_of_val(&*ptr)) + unsafe { data_offset_align(align_of_val(&*ptr)) } } /// Computes the offset of the data field within `ArcInner`. diff --git a/src/liballoc/task.rs b/src/liballoc/task.rs index 745444a152e1b..0d1cc99df47c5 100644 --- a/src/liballoc/task.rs +++ b/src/liballoc/task.rs @@ -60,7 +60,7 @@ impl From> for RawWaker { fn raw_waker(waker: Arc) -> RawWaker { // Increment the reference count of the arc to clone it. unsafe fn clone_waker(waker: *const ()) -> RawWaker { - Arc::incr_strong_count(waker as *const W); + unsafe { Arc::incr_strong_count(waker as *const W) }; RawWaker::new( waker as *const (), &RawWakerVTable::new(clone_waker::, wake::, wake_by_ref::, drop_waker::), @@ -69,19 +69,20 @@ fn raw_waker(waker: Arc) -> RawWaker { // 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); + let waker: Arc = unsafe { 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)); + let waker: ManuallyDrop> = + unsafe { 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 ()) { - Arc::decr_strong_count(waker as *const W); + unsafe { Arc::decr_strong_count(waker as *const W) }; } RawWaker::new( diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index f3da46bd0cc4e..e2dc816b01526 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -12,7 +12,6 @@ #![feature(associated_type_bounds)] #![feature(binary_heap_into_iter_sorted)] #![feature(binary_heap_drain_sorted)] -#![feature(vec_remove_item)] #![feature(split_inclusive)] #![feature(binary_heap_retain)] diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs index a9813a8704f30..ffff543b07fe5 100644 --- a/src/liballoc/tests/vec.rs +++ b/src/liballoc/tests/vec.rs @@ -1,5 +1,6 @@ use std::borrow::Cow; use std::collections::TryReserveError::*; +use std::fmt::Debug; use std::mem::size_of; use std::panic::{catch_unwind, AssertUnwindSafe}; use std::vec::{Drain, IntoIter}; @@ -131,21 +132,6 @@ fn test_extend_ref() { assert_eq!(v, [1, 2, 3, 4, 5, 6, 7]); } -#[test] -fn test_remove_item() { - let mut v = vec![1, 2, 3]; - v.remove_item(&1); - - assert_eq!(v.len(), 2); - assert_eq!(v, [2, 3]); - - let mut w = vec![1, 2, 3]; - w.remove_item(&4); - - assert_eq!(w.len(), 3); - w.remove_item(&4); -} - #[test] fn test_slice_from_mut() { let mut values = vec![1, 2, 3, 4, 5]; @@ -1588,3 +1574,56 @@ fn test_push_growth_strategy() { } } } + +macro_rules! generate_assert_eq_vec_and_prim { + ($name:ident<$B:ident>($type:ty)) => { + fn $name + Debug, $B: Debug>(a: Vec, b: $type) { + assert!(a == b); + assert_eq!(a, b); + } + }; +} + +generate_assert_eq_vec_and_prim! { assert_eq_vec_and_slice (&[B]) } +generate_assert_eq_vec_and_prim! { assert_eq_vec_and_array_3([B; 3]) } + +#[test] +fn partialeq_vec_and_prim() { + assert_eq_vec_and_slice(vec![1, 2, 3], &[1, 2, 3]); + assert_eq_vec_and_array_3(vec![1, 2, 3], [1, 2, 3]); +} + +macro_rules! assert_partial_eq_valid { + ($a2:ident, $a3:ident; $b2:ident, $b3: ident) => { + assert!($a2 == $b2); + assert!($a2 != $b3); + assert!($a3 != $b2); + assert!($a3 == $b3); + assert_eq!($a2, $b2); + assert_ne!($a2, $b3); + assert_ne!($a3, $b2); + assert_eq!($a3, $b3); + }; +} + +#[test] +fn partialeq_vec_full() { + let vec2: Vec<_> = vec![1, 2]; + let vec3: Vec<_> = vec![1, 2, 3]; + let slice2: &[_] = &[1, 2]; + let slice3: &[_] = &[1, 2, 3]; + let slicemut2: &[_] = &mut [1, 2]; + let slicemut3: &[_] = &mut [1, 2, 3]; + let array2: [_; 2] = [1, 2]; + let array3: [_; 3] = [1, 2, 3]; + let arrayref2: &[_; 2] = &[1, 2]; + let arrayref3: &[_; 3] = &[1, 2, 3]; + + assert_partial_eq_valid!(vec2,vec3; vec2,vec3); + assert_partial_eq_valid!(vec2,vec3; slice2,slice3); + assert_partial_eq_valid!(vec2,vec3; slicemut2,slicemut3); + assert_partial_eq_valid!(slice2,slice3; vec2,vec3); + assert_partial_eq_valid!(slicemut2,slicemut3; vec2,vec3); + assert_partial_eq_valid!(vec2,vec3; array2,array3); + assert_partial_eq_valid!(vec2,vec3; arrayref2,arrayref3); +} diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index f16cac05ea039..fc8a992e1701b 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -465,7 +465,7 @@ impl Vec { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Vec { - Vec { buf: RawVec::from_raw_parts(ptr, capacity), len: length } + unsafe { Vec { buf: RawVec::from_raw_parts(ptr, capacity), len: length } } } /// Returns the number of elements the vector can hold without @@ -1264,10 +1264,10 @@ impl Vec { /// Appends elements to `Self` from other buffer. #[inline] unsafe fn append_elements(&mut self, other: *const [T]) { - let count = (*other).len(); + let count = unsafe { (*other).len() }; self.reserve(count); let len = self.len(); - ptr::copy_nonoverlapping(other as *const T, self.as_mut_ptr().add(len), count); + unsafe { ptr::copy_nonoverlapping(other as *const T, self.as_mut_ptr().add(len), count) }; self.len += count; } @@ -1760,17 +1760,15 @@ impl Vec { impl Vec { /// Removes the first instance of `item` from the vector if the item exists. /// - /// # Examples - /// - /// ``` - /// # #![feature(vec_remove_item)] - /// let mut vec = vec![1, 2, 3, 1]; - /// - /// vec.remove_item(&1); - /// - /// assert_eq!(vec, vec![2, 3, 1]); - /// ``` + /// This method will be removed soon. #[unstable(feature = "vec_remove_item", reason = "recently added", issue = "40062")] + #[rustc_deprecated( + reason = "Removing the first item equal to a needle is already easily possible \ + with iterators and the current Vec methods. Furthermore, having a method for \ + one particular case of removal (linear search, only the first item, no swap remove) \ + but not for others is inconsistent. This method will be removed soon.", + since = "1.46.0" + )] pub fn remove_item(&mut self, item: &V) -> Option where T: PartialEq, @@ -2344,12 +2342,12 @@ impl<'a, T: 'a + Copy> Extend<&'a T> for Vec { } macro_rules! __impl_slice_eq1 { - ([$($vars:tt)*] $lhs:ty, $rhs:ty, $($constraints:tt)*) => { - #[stable(feature = "rust1", since = "1.0.0")] + ([$($vars:tt)*] $lhs:ty, $rhs:ty $(where $ty:ty: $bound:ident)?, #[$stability:meta]) => { + #[$stability] impl PartialEq<$rhs> for $lhs where A: PartialEq, - $($constraints)* + $($ty: $bound)? { #[inline] fn eq(&self, other: &$rhs) -> bool { self[..] == other[..] } @@ -2359,18 +2357,23 @@ macro_rules! __impl_slice_eq1 { } } -__impl_slice_eq1! { [] Vec, Vec, } -__impl_slice_eq1! { [] Vec, &[B], } -__impl_slice_eq1! { [] Vec, &mut [B], } -__impl_slice_eq1! { [] Cow<'_, [A]>, Vec, A: Clone } -__impl_slice_eq1! { [] Cow<'_, [A]>, &[B], A: Clone } -__impl_slice_eq1! { [] Cow<'_, [A]>, &mut [B], A: Clone } -__impl_slice_eq1! { [const N: usize] Vec, [B; N], [B; N]: LengthAtMost32 } -__impl_slice_eq1! { [const N: usize] Vec, &[B; N], [B; N]: LengthAtMost32 } +__impl_slice_eq1! { [] Vec, Vec, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [] Vec, &[B], #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [] Vec, &mut [B], #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [] &[A], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] } +__impl_slice_eq1! { [] &mut [A], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] } +__impl_slice_eq1! { [] Cow<'_, [A]>, Vec where A: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [] Cow<'_, [A]>, &[B] where A: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [] Cow<'_, [A]>, &mut [B] where A: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [const N: usize] Vec, [B; N] where [B; N]: LengthAtMost32, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [const N: usize] Vec, &[B; N] where [B; N]: LengthAtMost32, #[stable(feature = "rust1", since = "1.0.0")] } // NOTE: some less important impls are omitted to reduce code bloat // FIXME(Centril): Reconsider this? //__impl_slice_eq1! { [const N: usize] Vec, &mut [B; N], [B; N]: LengthAtMost32 } +//__impl_slice_eq1! { [const N: usize] [A; N], Vec, [A; N]: LengthAtMost32 } +//__impl_slice_eq1! { [const N: usize] &[A; N], Vec, [A; N]: LengthAtMost32 } +//__impl_slice_eq1! { [const N: usize] &mut [A; N], Vec, [A; N]: LengthAtMost32 } //__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, [B; N], [B; N]: LengthAtMost32 } //__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &[B; N], [B; N]: LengthAtMost32 } //__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &mut [B; N], [B; N]: LengthAtMost32 } @@ -2965,15 +2968,16 @@ impl Drain<'_, T> { /// Fill that range as much as possible with new elements from the `replace_with` iterator. /// Returns `true` if we filled the entire range. (`replace_with.next()` didn’t return `None`.) unsafe fn fill>(&mut self, replace_with: &mut I) -> bool { - let vec = self.vec.as_mut(); + let vec = unsafe { self.vec.as_mut() }; let range_start = vec.len; let range_end = self.tail_start; - let range_slice = - slice::from_raw_parts_mut(vec.as_mut_ptr().add(range_start), range_end - range_start); + let range_slice = unsafe { + slice::from_raw_parts_mut(vec.as_mut_ptr().add(range_start), range_end - range_start) + }; for place in range_slice { if let Some(new_item) = replace_with.next() { - ptr::write(place, new_item); + unsafe { ptr::write(place, new_item) }; vec.len += 1; } else { return false; @@ -2984,14 +2988,16 @@ impl Drain<'_, T> { /// Makes room for inserting more elements before the tail. unsafe fn move_tail(&mut self, additional: usize) { - let vec = self.vec.as_mut(); + let vec = unsafe { self.vec.as_mut() }; let len = self.tail_start + self.tail_len; vec.buf.reserve(len, additional); let new_tail_start = self.tail_start + additional; - let src = vec.as_ptr().add(self.tail_start); - let dst = vec.as_mut_ptr().add(new_tail_start); - ptr::copy(src, dst, self.tail_len); + unsafe { + let src = vec.as_ptr().add(self.tail_start); + let dst = vec.as_mut_ptr().add(new_tail_start); + ptr::copy(src, dst, self.tail_len); + } self.tail_start = new_tail_start; } } diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 9061145a695f8..2298958b88101 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1012,7 +1012,7 @@ extern "rust-intrinsic" { /// /// The stabilized version of this intrinsic is /// [`std::any::type_name`](../../std/any/fn.type_name.html) - #[rustc_const_unstable(feature = "const_type_name", issue = "none")] + #[rustc_const_unstable(feature = "const_type_name", issue = "63084")] pub fn type_name() -> &'static str; /// Gets an identifier which is globally unique to the specified type. This @@ -1021,7 +1021,7 @@ extern "rust-intrinsic" { /// /// The stabilized version of this intrinsic is /// [`std::any::TypeId::of`](../../std/any/struct.TypeId.html#method.of) - #[rustc_const_unstable(feature = "const_type_id", issue = "none")] + #[rustc_const_unstable(feature = "const_type_id", issue = "41875")] pub fn type_id() -> u64; /// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited: @@ -1291,7 +1291,7 @@ extern "rust-intrinsic" { /// implements `Copy`. /// /// If the actual type neither requires drop glue nor implements - /// `Copy`, then may return `true` or `false`. + /// `Copy`, then the return value of this function is unspecified. /// /// The stabilized version of this intrinsic is /// [`std::mem::needs_drop`](../../std/mem/fn.needs_drop.html). @@ -1931,7 +1931,7 @@ extern "rust-intrinsic" { pub fn nontemporal_store(ptr: *mut T, val: T); /// See documentation of `<*const T>::offset_from` for details. - #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "none")] + #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")] pub fn ptr_offset_from(ptr: *const T, base: *const T) -> isize; /// Internal hook used by Miri to implement unwinding. @@ -1948,6 +1948,16 @@ extern "rust-intrinsic" { #[cfg(not(bootstrap))] #[lang = "count_code_region"] pub fn count_code_region(index: u32); + + /// See documentation of `<*const T>::guaranteed_eq` for details. + #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[cfg(not(bootstrap))] + pub fn ptr_guaranteed_eq(ptr: *const T, other: *const T) -> bool; + + /// See documentation of `<*const T>::guaranteed_ne` for details. + #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[cfg(not(bootstrap))] + pub fn ptr_guaranteed_ne(ptr: *const T, other: *const T) -> bool; } // Some functions are defined here because they accidentally got made diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index fbfcdc3c1a9ea..530cf881f29da 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -2265,7 +2265,7 @@ pub trait Iterator { } /// Applies function to the elements of iterator and returns - /// the first non-none result or the first error. + /// the first true result or the first error. /// /// # Examples /// @@ -2286,19 +2286,26 @@ pub trait Iterator { /// ``` #[inline] #[unstable(feature = "try_find", reason = "new API", issue = "63178")] - fn try_find(&mut self, mut f: F) -> Result, E> + fn try_find(&mut self, f: F) -> Result, R::Error> where Self: Sized, F: FnMut(&Self::Item) -> R, - R: Try, - { - self.try_fold((), move |(), x| match f(&x).into_result() { - Ok(false) => LoopState::Continue(()), - Ok(true) => LoopState::Break(Ok(x)), - Err(x) => LoopState::Break(Err(x)), - }) - .break_value() - .transpose() + R: Try, + { + #[inline] + fn check(mut f: F) -> impl FnMut((), T) -> LoopState<(), Result> + where + F: FnMut(&T) -> R, + R: Try, + { + move |(), x| match f(&x).into_result() { + Ok(false) => LoopState::Continue(()), + Ok(true) => LoopState::Break(Ok(x)), + Err(x) => LoopState::Break(Err(x)), + } + } + + self.try_fold((), check(f)).break_value().transpose() } /// Searches for an element in an iterator, returning its index. diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index fe05e914e6d44..4eb2fdbd07868 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -87,6 +87,7 @@ #![feature(const_generics)] #![feature(const_ptr_offset)] #![feature(const_ptr_offset_from)] +#![cfg_attr(not(bootstrap), feature(const_raw_ptr_comparison))] #![feature(const_result)] #![feature(const_slice_from_raw_parts)] #![feature(const_slice_ptr_len)] @@ -277,6 +278,9 @@ pub mod primitive; // crate uses the this crate as its libcore. #[path = "../stdarch/crates/core_arch/src/mod.rs"] #[allow(missing_docs, missing_debug_implementations, dead_code, unused_imports)] +// FIXME: This annotation should be moved into rust-lang/stdarch after clashing_extern_decl is +// merged. It currently cannot because bootstrap fails as the lint hasn't been defined yet. +#[cfg_attr(not(bootstrap), allow(clashing_extern_decl))] #[unstable(feature = "stdsimd", issue = "48556")] mod core_arch; diff --git a/src/libcore/ptr/const_ptr.rs b/src/libcore/ptr/const_ptr.rs index e39d18d7733a2..395b3879cfd0c 100644 --- a/src/libcore/ptr/const_ptr.rs +++ b/src/libcore/ptr/const_ptr.rs @@ -295,6 +295,72 @@ impl *const T { intrinsics::ptr_offset_from(self, origin) } + /// Returns whether two pointers are guaranteed to be equal. + /// + /// At runtime this function behaves like `self == other`. + /// However, in some contexts (e.g., compile-time evaluation), + /// it is not always possible to determine equality of two pointers, so this function may + /// spuriously return `false` for pointers that later actually turn out to be equal. + /// But when it returns `true`, the pointers are guaranteed to be equal. + /// + /// This function is the mirror of [`guaranteed_ne`], but not its inverse. There are pointer + /// comparisons for which both functions return `false`. + /// + /// [`guaranteed_ne`]: #method.guaranteed_ne + /// + /// The return value may change depending on the compiler version and unsafe code may not + /// rely on the result of this function for soundness. It is suggested to only use this function + /// for performance optimizations where spurious `false` return values by this function do not + /// affect the outcome, but just the performance. + /// The consequences of using this method to make runtime and compile-time code behave + /// differently have not been explored. This method should not be used to introduce such + /// differences, and it should also not be stabilized before we have a better understanding + /// of this issue. + /// ``` + #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[inline] + #[cfg(not(bootstrap))] + pub const fn guaranteed_eq(self, other: *const T) -> bool + where + T: Sized, + { + intrinsics::ptr_guaranteed_eq(self, other) + } + + /// Returns whether two pointers are guaranteed to be inequal. + /// + /// At runtime this function behaves like `self != other`. + /// However, in some contexts (e.g., compile-time evaluation), + /// it is not always possible to determine the inequality of two pointers, so this function may + /// spuriously return `false` for pointers that later actually turn out to be inequal. + /// But when it returns `true`, the pointers are guaranteed to be inequal. + /// + /// This function is the mirror of [`guaranteed_eq`], but not its inverse. There are pointer + /// comparisons for which both functions return `false`. + /// + /// [`guaranteed_eq`]: #method.guaranteed_eq + /// + /// The return value may change depending on the compiler version and unsafe code may not + /// rely on the result of this function for soundness. It is suggested to only use this function + /// for performance optimizations where spurious `false` return values by this function do not + /// affect the outcome, but just the performance. + /// The consequences of using this method to make runtime and compile-time code behave + /// differently have not been explored. This method should not be used to introduce such + /// differences, and it should also not be stabilized before we have a better understanding + /// of this issue. + /// ``` + #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[inline] + #[cfg(not(bootstrap))] + pub const fn guaranteed_ne(self, other: *const T) -> bool + where + T: Sized, + { + intrinsics::ptr_guaranteed_ne(self, other) + } + /// Calculates the distance between two pointers. The returned value is in /// units of T: the distance in bytes is divided by `mem::size_of::()`. /// @@ -330,6 +396,12 @@ impl *const T { /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2); /// ``` #[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")] + #[rustc_deprecated( + since = "1.46.0", + reason = "Pointer distances across allocation \ + boundaries are not typically meaningful. \ + Use integer subtraction if you really need this." + )] #[inline] pub fn wrapping_offset_from(self, origin: *const T) -> isize where diff --git a/src/libcore/ptr/mut_ptr.rs b/src/libcore/ptr/mut_ptr.rs index 40b5e4e22340e..b86ef5b13b353 100644 --- a/src/libcore/ptr/mut_ptr.rs +++ b/src/libcore/ptr/mut_ptr.rs @@ -273,6 +273,72 @@ impl *mut T { if self.is_null() { None } else { Some(&mut *self) } } + /// Returns whether two pointers are guaranteed to be equal. + /// + /// At runtime this function behaves like `self == other`. + /// However, in some contexts (e.g., compile-time evaluation), + /// it is not always possible to determine equality of two pointers, so this function may + /// spuriously return `false` for pointers that later actually turn out to be equal. + /// But when it returns `true`, the pointers are guaranteed to be equal. + /// + /// This function is the mirror of [`guaranteed_ne`], but not its inverse. There are pointer + /// comparisons for which both functions return `false`. + /// + /// [`guaranteed_ne`]: #method.guaranteed_ne + /// + /// The return value may change depending on the compiler version and unsafe code may not + /// rely on the result of this function for soundness. It is suggested to only use this function + /// for performance optimizations where spurious `false` return values by this function do not + /// affect the outcome, but just the performance. + /// The consequences of using this method to make runtime and compile-time code behave + /// differently have not been explored. This method should not be used to introduce such + /// differences, and it should also not be stabilized before we have a better understanding + /// of this issue. + /// ``` + #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[inline] + #[cfg(not(bootstrap))] + pub const fn guaranteed_eq(self, other: *mut T) -> bool + where + T: Sized, + { + intrinsics::ptr_guaranteed_eq(self as *const _, other as *const _) + } + + /// Returns whether two pointers are guaranteed to be inequal. + /// + /// At runtime this function behaves like `self != other`. + /// However, in some contexts (e.g., compile-time evaluation), + /// it is not always possible to determine the inequality of two pointers, so this function may + /// spuriously return `false` for pointers that later actually turn out to be inequal. + /// But when it returns `true`, the pointers are guaranteed to be inequal. + /// + /// This function is the mirror of [`guaranteed_eq`], but not its inverse. There are pointer + /// comparisons for which both functions return `false`. + /// + /// [`guaranteed_eq`]: #method.guaranteed_eq + /// + /// The return value may change depending on the compiler version and unsafe code may not + /// rely on the result of this function for soundness. It is suggested to only use this function + /// for performance optimizations where spurious `false` return values by this function do not + /// affect the outcome, but just the performance. + /// The consequences of using this method to make runtime and compile-time code behave + /// differently have not been explored. This method should not be used to introduce such + /// differences, and it should also not be stabilized before we have a better understanding + /// of this issue. + /// ``` + #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[inline] + #[cfg(not(bootstrap))] + pub const unsafe fn guaranteed_ne(self, other: *mut T) -> bool + where + T: Sized, + { + intrinsics::ptr_guaranteed_ne(self as *const _, other as *const _) + } + /// Calculates the distance between two pointers. The returned value is in /// units of T: the distance in bytes is divided by `mem::size_of::()`. /// @@ -380,11 +446,18 @@ impl *mut T { /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2); /// ``` #[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")] + #[rustc_deprecated( + since = "1.46.0", + reason = "Pointer distances across allocation \ + boundaries are not typically meaningful. \ + Use integer subtraction if you really need this." + )] #[inline] pub fn wrapping_offset_from(self, origin: *const T) -> isize where T: Sized, { + #[allow(deprecated_in_future, deprecated)] (self as *const T).wrapping_offset_from(origin) } diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 2080ae193667e..0c0e6d291bb92 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -1155,6 +1155,7 @@ impl Result { /// # Examples /// /// ``` + /// #![feature(inner_deref)] /// let x: Result = Ok("hello".to_string()); /// let y: Result<&str, &u32> = Ok("hello"); /// assert_eq!(x.as_deref(), y); @@ -1189,12 +1190,15 @@ impl Result { /// # Examples /// /// ``` + /// #![feature(inner_deref)] + /// let mut s = "HELLO".to_string(); /// let mut x: Result = Ok("hello".to_string()); - /// let y: Result<&mut str, &mut u32> = Ok("HELLO"); + /// let y: Result<&mut str, &mut u32> = Ok(&mut s); /// assert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y); /// + /// let mut i = 42; /// let mut x: Result = Err(42); - /// let y: Result<&mut str, &mut u32> = Err(&42); + /// let y: Result<&mut str, &mut u32> = Err(&mut i); /// assert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y); /// ``` pub fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E> { diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 21ba2b5abcfb6..c69aafe687cf8 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -5956,10 +5956,18 @@ where return false; } + #[cfg(bootstrap)] if self.as_ptr() == other.as_ptr() { return true; } + // While performance would suffer if `guaranteed_eq` just returned `false` + // for all arguments, correctness and return value of this function are not affected. + #[cfg(not(bootstrap))] + if self.as_ptr().guaranteed_eq(other.as_ptr()) { + return true; + } + self.iter().zip(other.iter()).all(|(x, y)| x == y) } } @@ -5973,9 +5981,18 @@ where if self.len() != other.len() { return false; } + + #[cfg(bootstrap)] if self.as_ptr() == other.as_ptr() { return true; } + + // While performance would suffer if `guaranteed_eq` just returned `false` + // for all arguments, correctness and return value of this function are not affected. + #[cfg(not(bootstrap))] + if self.as_ptr().guaranteed_eq(other.as_ptr()) { + return true; + } unsafe { let size = mem::size_of_val(self); memcmp(self.as_ptr() as *const u8, other.as_ptr() as *const u8, size) == 0 diff --git a/src/libcore/slice/sort.rs b/src/libcore/slice/sort.rs index be3e7aaa2e89a..8b2ac294764ff 100644 --- a/src/libcore/slice/sort.rs +++ b/src/libcore/slice/sort.rs @@ -1,6 +1,6 @@ //! Slice sorting //! -//! This module contains an sort algorithm based on Orson Peters' pattern-defeating quicksort, +//! This module contains a sorting algorithm based on Orson Peters' pattern-defeating quicksort, //! published at: https://github.com/orlp/pdqsort //! //! Unstable sorting is compatible with libcore because it doesn't allocate memory, unlike our @@ -20,6 +20,9 @@ struct CopyOnDrop { impl Drop for CopyOnDrop { fn drop(&mut self) { + // SAFETY: This is a helper class. + // Please refer to its usage for correctness. + // Namely, one must be sure that `src` and `dst` does not overlap as required by `ptr::copy_nonoverlapping`. unsafe { ptr::copy_nonoverlapping(self.src, self.dest, 1); } @@ -32,6 +35,21 @@ where F: FnMut(&T, &T) -> bool, { let len = v.len(); + // SAFETY: The unsafe operations below involves indexing without a bound check (`get_unchecked` and `get_unchecked_mut`) + // and copying memory (`ptr::copy_nonoverlapping`). + // + // a. Indexing: + // 1. We checked the size of the array to >=2. + // 2. All the indexing that we will do is always between {0 <= index < len} at most. + // + // b. Memory copying + // 1. We are obtaining pointers to references which are guaranteed to be valid. + // 2. They cannot overlap because we obtain pointers to difference indices of the slice. + // Namely, `i` and `i-1`. + // 3. If the slice is properly aligned, the elements are properly aligned. + // It is the caller's responsibility to make sure the slice is properly aligned. + // + // See comments below for further detail. unsafe { // If the first two elements are out-of-order... if len >= 2 && is_less(v.get_unchecked(1), v.get_unchecked(0)) { @@ -62,6 +80,21 @@ where F: FnMut(&T, &T) -> bool, { let len = v.len(); + // SAFETY: The unsafe operations below involves indexing without a bound check (`get_unchecked` and `get_unchecked_mut`) + // and copying memory (`ptr::copy_nonoverlapping`). + // + // a. Indexing: + // 1. We checked the size of the array to >= 2. + // 2. All the indexing that we will do is always between `0 <= index < len-1` at most. + // + // b. Memory copying + // 1. We are obtaining pointers to references which are guaranteed to be valid. + // 2. They cannot overlap because we obtain pointers to difference indices of the slice. + // Namely, `i` and `i+1`. + // 3. If the slice is properly aligned, the elements are properly aligned. + // It is the caller's responsibility to make sure the slice is properly aligned. + // + // See comments below for further detail. unsafe { // If the last two elements are out-of-order... if len >= 2 && is_less(v.get_unchecked(len - 1), v.get_unchecked(len - 2)) { @@ -103,6 +136,8 @@ where let mut i = 1; for _ in 0..MAX_STEPS { + // SAFETY: We already explicitly did the bound checking with `i < len`. + // All our subsequent indexing is only in the range `0 <= index < len` unsafe { // Find the next pair of adjacent out-of-order elements. while i < len && !is_less(v.get_unchecked(i), v.get_unchecked(i - 1)) { @@ -220,6 +255,7 @@ where let mut offsets_l = [MaybeUninit::::uninit(); BLOCK]; // The current block on the right side (from `r.sub(block_r)` to `r`). + // SAFETY: The documentation for .add() specifically mention that `vec.as_ptr().add(vec.len())` is always safe` let mut r = unsafe { l.add(v.len()) }; let mut block_r = BLOCK; let mut start_r = ptr::null_mut(); @@ -268,6 +304,16 @@ where let mut elem = l; for i in 0..block_l { + // SAFETY: The unsafety operations below involve the usage of the `offset`. + // According to the conditions required by the function, we satisfy them because: + // 1. `offsets_l` is stack-allocated, and thus considered separate allocated object. + // 2. The function `is_less` returns a `bool`. + // Casting a `bool` will never overflow `isize`. + // 3. We have guaranteed that `block_l` will be `<= BLOCK`. + // Plus, `end_l` was initially set to the begin pointer of `offsets_` which was declared on the stack. + // Thus, we know that even in the worst case (all invocations of `is_less` returns false) we will only be at most 1 byte pass the end. + // Another unsafety operation here is dereferencing `elem`. + // However, `elem` was initially the begin pointer to the slice which is always valid. unsafe { // Branchless comparison. *end_l = i as u8; @@ -284,6 +330,17 @@ where let mut elem = r; for i in 0..block_r { + // SAFETY: The unsafety operations below involve the usage of the `offset`. + // According to the conditions required by the function, we satisfy them because: + // 1. `offsets_r` is stack-allocated, and thus considered separate allocated object. + // 2. The function `is_less` returns a `bool`. + // Casting a `bool` will never overflow `isize`. + // 3. We have guaranteed that `block_r` will be `<= BLOCK`. + // Plus, `end_r` was initially set to the begin pointer of `offsets_` which was declared on the stack. + // Thus, we know that even in the worst case (all invocations of `is_less` returns true) we will only be at most 1 byte pass the end. + // Another unsafety operation here is dereferencing `elem`. + // However, `elem` was initially `1 * sizeof(T)` past the end and we decrement it by `1 * sizeof(T)` before accessing it. + // Plus, `block_r` was asserted to be less than `BLOCK` and `elem` will therefore at most be pointing to the beginning of the slice. unsafe { // Branchless comparison. elem = elem.offset(-1); @@ -404,8 +461,13 @@ where // Find the first pair of out-of-order elements. let mut l = 0; let mut r = v.len(); + + // SAFETY: The unsafety below involves indexing an array. + // For the first one: We already do the bounds checking here with `l < r`. + // For the second one: We initially have `l == 0` and `r == v.len()` and we checked that `l < r` at every indexing operation. + // From here we know that `r` must be at least `r == l` which was shown to be valid from the first one. unsafe { - // Find the first element greater then or equal to the pivot. + // Find the first element greater than or equal to the pivot. while l < r && is_less(v.get_unchecked(l), pivot) { l += 1; } @@ -444,6 +506,7 @@ where // Read the pivot into a stack-allocated variable for efficiency. If a following comparison // operation panics, the pivot will be automatically written back into the slice. + // SAFETY: The pointer here is valid because it is obtained from a reference to a slice. let mut tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) }); let _pivot_guard = CopyOnDrop { src: &mut *tmp, dest: pivot }; let pivot = &*tmp; @@ -452,8 +515,12 @@ where let mut l = 0; let mut r = v.len(); loop { + // SAFETY: The unsafety below involves indexing an array. + // For the first one: We already do the bounds checking here with `l < r`. + // For the second one: We initially have `l == 0` and `r == v.len()` and we checked that `l < r` at every indexing operation. + // From here we know that `r` must be at least `r == l` which was shown to be valid from the first one. unsafe { - // Find the first element greater that the pivot. + // Find the first element greater than the pivot. while l < r && !is_less(pivot, v.get_unchecked(l)) { l += 1; } diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 37ebf4112808e..4e55452a4c31b 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -19,7 +19,7 @@ #![feature(raw)] #![feature(sort_internals)] #![feature(slice_partition_at_index)] -#![feature(specialization)] +#![feature(min_specialization)] #![feature(step_trait)] #![feature(step_trait_ext)] #![feature(str_internals)] diff --git a/src/libcore/time.rs b/src/libcore/time.rs index e2ceaf80c0cda..3b6dafeee2540 100644 --- a/src/libcore/time.rs +++ b/src/libcore/time.rs @@ -31,7 +31,7 @@ const MICROS_PER_SEC: u64 = 1_000_000; /// the number of nanoseconds. /// /// `Duration`s implement many common traits, including [`Add`], [`Sub`], and other -/// [`ops`] traits. +/// [`ops`] traits. It implements `Default` by returning a zero-length `Duration`. /// /// [`Add`]: ../../std/ops/trait.Add.html /// [`Sub`]: ../../std/ops/trait.Sub.html @@ -138,6 +138,24 @@ impl Duration { Duration { secs, nanos } } + /// Creates a new `Duration` that spans no time. + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_zero)] + /// use std::time::Duration; + /// + /// let duration = Duration::zero(); + /// assert!(duration.is_zero()); + /// assert_eq!(duration.as_nanos(), 0); + /// ``` + #[unstable(feature = "duration_zero", issue = "73544")] + #[inline] + pub const fn zero() -> Duration { + Duration { secs: 0, nanos: 0 } + } + /// Creates a new `Duration` from the specified number of whole seconds. /// /// # Examples @@ -223,6 +241,29 @@ impl Duration { } } + /// Returns true if this `Duration` spans no time. + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_zero)] + /// use std::time::Duration; + /// + /// assert!(Duration::zero().is_zero()); + /// assert!(Duration::new(0, 0).is_zero()); + /// assert!(Duration::from_nanos(0).is_zero()); + /// assert!(Duration::from_secs(0).is_zero()); + /// + /// assert!(!Duration::new(1, 1).is_zero()); + /// assert!(!Duration::from_nanos(1).is_zero()); + /// assert!(!Duration::from_secs(1).is_zero()); + /// ``` + #[unstable(feature = "duration_zero", issue = "73544")] + #[inline] + pub const fn is_zero(&self) -> bool { + self.secs == 0 && self.nanos == 0 + } + /// Returns the number of _whole_ seconds contained by this `Duration`. /// /// The returned value does not include the fractional (nanosecond) part of the diff --git a/src/librustc_arena/lib.rs b/src/librustc_arena/lib.rs index 66c31cbebcc1e..5cf4f97fb8863 100644 --- a/src/librustc_arena/lib.rs +++ b/src/librustc_arena/lib.rs @@ -22,6 +22,7 @@ extern crate alloc; use rustc_data_structures::cold_path; use smallvec::SmallVec; +use std::alloc::Layout; use std::cell::{Cell, RefCell}; use std::cmp; use std::intrinsics; @@ -363,13 +364,15 @@ impl DroplessArena { } } - /// Allocates a byte slice with specified size and alignment from the - /// current memory chunk. Returns `None` if there is no free space left to - /// satisfy the request. + /// Allocates a byte slice with specified layout from the current memory + /// chunk. Returns `None` if there is no free space left to satisfy the + /// request. #[inline] - fn alloc_raw_without_grow(&self, bytes: usize, align: usize) -> Option<*mut u8> { + fn alloc_raw_without_grow(&self, layout: Layout) -> Option<*mut u8> { let ptr = self.ptr.get() as usize; let end = self.end.get() as usize; + let align = layout.align(); + let bytes = layout.size(); // The allocation request fits into the current chunk iff: // // let aligned = align_to(ptr, align); @@ -390,15 +393,15 @@ impl DroplessArena { } #[inline] - pub fn alloc_raw(&self, bytes: usize, align: usize) -> *mut u8 { - assert!(bytes != 0); + pub fn alloc_raw(&self, layout: Layout) -> *mut u8 { + assert!(layout.size() != 0); loop { - if let Some(a) = self.alloc_raw_without_grow(bytes, align) { + if let Some(a) = self.alloc_raw_without_grow(layout) { break a; } // No free space left. Allocate a new chunk to satisfy the request. // On failure the grow will panic or abort. - self.grow(bytes); + self.grow(layout.size()); } } @@ -406,7 +409,7 @@ impl DroplessArena { pub fn alloc(&self, object: T) -> &mut T { assert!(!mem::needs_drop::()); - let mem = self.alloc_raw(mem::size_of::(), mem::align_of::()) as *mut T; + let mem = self.alloc_raw(Layout::for_value::(&object)) as *mut T; unsafe { // Write into uninitialized memory. @@ -431,7 +434,7 @@ impl DroplessArena { assert!(mem::size_of::() != 0); assert!(!slice.is_empty()); - let mem = self.alloc_raw(slice.len() * mem::size_of::(), mem::align_of::()) as *mut T; + let mem = self.alloc_raw(Layout::for_value::<[T]>(slice)) as *mut T; unsafe { mem.copy_from_nonoverlapping(slice.as_ptr(), slice.len()); @@ -477,8 +480,8 @@ impl DroplessArena { if len == 0 { return &mut []; } - let size = len.checked_mul(mem::size_of::()).unwrap(); - let mem = self.alloc_raw(size, mem::align_of::()) as *mut T; + + let mem = self.alloc_raw(Layout::array::(len).unwrap()) as *mut T; unsafe { self.write_from_iter(iter, len, mem) } } (_, _) => { @@ -491,9 +494,8 @@ impl DroplessArena { // the content of the SmallVec unsafe { let len = vec.len(); - let start_ptr = self - .alloc_raw(len * mem::size_of::(), mem::align_of::()) - as *mut T; + let start_ptr = + self.alloc_raw(Layout::for_value::<[T]>(vec.as_slice())) as *mut T; vec.as_ptr().copy_to_nonoverlapping(start_ptr, len); vec.set_len(0); slice::from_raw_parts_mut(start_ptr, len) @@ -537,7 +539,7 @@ pub struct DropArena { 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 T; + let mem = self.arena.alloc_raw(Layout::new::()) as *mut T; // Write into uninitialized memory. ptr::write(mem, object); let result = &mut *mem; @@ -557,10 +559,7 @@ impl DropArena { } let len = vec.len(); - let start_ptr = self - .arena - .alloc_raw(len.checked_mul(mem::size_of::()).unwrap(), mem::align_of::()) - as *mut T; + let start_ptr = self.arena.alloc_raw(Layout::array::(len).unwrap()) as *mut T; let mut destructors = self.destructors.borrow_mut(); // Reserve space for the destructors so we can't panic while adding them @@ -612,7 +611,11 @@ macro_rules! which_arena_for_type { #[macro_export] macro_rules! declare_arena { - ([], [$($a:tt $name:ident: $ty:ty, $gen_ty:ty;)*], $tcx:lifetime) => { + // This macro has to take the same input as + // `impl_arena_allocatable_decoders` which requires a second version of + // each type. We ignore that type until we can fix + // `impl_arena_allocatable_decoders`. + ([], [$($a:tt $name:ident: $ty:ty, $_gen_ty:ty;)*], $tcx:lifetime) => { #[derive(Default)] pub struct Arena<$tcx> { pub dropless: $crate::DroplessArena, @@ -620,39 +623,56 @@ macro_rules! declare_arena { $($name: $crate::arena_for_type!($a[$ty]),)* } - #[marker] - pub trait ArenaAllocatable<'tcx> {} - - impl<'tcx, T: Copy> ArenaAllocatable<'tcx> for T {} - - unsafe trait ArenaField<'tcx>: Sized + ArenaAllocatable<'tcx> { - /// 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>; + pub trait ArenaAllocatable<'tcx, T = Self>: Sized { + fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self; + fn allocate_from_iter<'a>( + arena: &'a Arena<'tcx>, + iter: impl ::std::iter::IntoIterator, + ) -> &'a mut [Self]; } - unsafe impl<'tcx, T: ArenaAllocatable<'tcx>> ArenaField<'tcx> for T { + impl<'tcx, T: Copy> ArenaAllocatable<'tcx, ()> for T { #[inline] - default fn arena<'a>(_: &'a Arena<'tcx>) -> Option<&'a $crate::TypedArena> { - panic!() + fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self { + arena.dropless.alloc(self) + } + #[inline] + fn allocate_from_iter<'a>( + arena: &'a Arena<'tcx>, + iter: impl ::std::iter::IntoIterator, + ) -> &'a mut [Self] { + arena.dropless.alloc_from_iter(iter) } - } + } $( - #[allow(unused_lifetimes)] - impl<$tcx> ArenaAllocatable<$tcx> for $ty {} - unsafe impl<$tcx, '_x, '_y, '_z, '_w> ArenaField<$tcx> for $gen_ty where Self: ArenaAllocatable<$tcx> { + impl<$tcx> ArenaAllocatable<$tcx, $ty> for $ty { #[inline] - fn arena<'a>(_arena: &'a Arena<$tcx>) -> Option<&'a $crate::TypedArena> { - // SAFETY: We only implement `ArenaAllocatable<$tcx>` for - // `$ty`, so `$ty` and Self are the same type - unsafe { - ::std::mem::transmute::< - Option<&'a $crate::TypedArena<$ty>>, - Option<&'a $crate::TypedArena>, - >( - $crate::which_arena_for_type!($a[&_arena.$name]) - ) + fn allocate_on<'a>(self, arena: &'a Arena<$tcx>) -> &'a mut Self { + if !::std::mem::needs_drop::() { + return arena.dropless.alloc(self); + } + match $crate::which_arena_for_type!($a[&arena.$name]) { + ::std::option::Option::<&$crate::TypedArena>::Some(ty_arena) => { + ty_arena.alloc(self) + } + ::std::option::Option::None => unsafe { arena.drop.alloc(self) }, + } + } + + #[inline] + fn allocate_from_iter<'a>( + arena: &'a Arena<$tcx>, + iter: impl ::std::iter::IntoIterator, + ) -> &'a mut [Self] { + if !::std::mem::needs_drop::() { + return arena.dropless.alloc_from_iter(iter); + } + match $crate::which_arena_for_type!($a[&arena.$name]) { + ::std::option::Option::<&$crate::TypedArena>::Some(ty_arena) => { + ty_arena.alloc_from_iter(iter) + } + ::std::option::Option::None => unsafe { arena.drop.alloc_from_iter(iter) }, } } } @@ -660,14 +680,8 @@ macro_rules! declare_arena { 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) }, - } + pub fn alloc, U>(&self, value: T) -> &mut T { + value.allocate_on(self) } #[inline] @@ -678,17 +692,11 @@ macro_rules! declare_arena { self.dropless.alloc_slice(value) } - pub fn alloc_from_iter<'a, T: ArenaAllocatable<'tcx>>( + pub fn alloc_from_iter<'a, T: ArenaAllocatable<'tcx, U>, U>( &'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) }, - } + T::allocate_from_iter(self, iter) } } } diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs index ce186c4834d72..e98d709539d79 100644 --- a/src/librustc_ast/ast.rs +++ b/src/librustc_ast/ast.rs @@ -1905,7 +1905,7 @@ impl fmt::Display for InlineAsmTemplatePiece { match c { '{' => f.write_str("{{")?, '}' => f.write_str("}}")?, - _ => write!(f, "{}", c.escape_debug())?, + _ => c.fmt(f)?, } } Ok(()) diff --git a/src/librustc_ast_lowering/expr.rs b/src/librustc_ast_lowering/expr.rs index e59cacfffc926..b7894eb145b0a 100644 --- a/src/librustc_ast_lowering/expr.rs +++ b/src/librustc_ast_lowering/expr.rs @@ -9,7 +9,7 @@ use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::Res; -use rustc_span::source_map::{respan, DesugaringKind, ForLoopLoc, Span, Spanned}; +use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned}; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_target::asm; use std::collections::hash_map::Entry; @@ -25,7 +25,6 @@ impl<'hir> LoweringContext<'_, 'hir> { } pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> { - let mut span = e.span; ensure_sufficient_stack(|| { let kind = match e.kind { ExprKind::Box(ref inner) => hir::ExprKind::Box(self.lower_expr(inner)), @@ -54,7 +53,6 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ExprKind::MethodCall(hir_seg, seg.ident.span, args, span) } ExprKind::Binary(binop, ref lhs, ref rhs) => { - span = self.mark_span_with_reason(DesugaringKind::Operator, e.span, None); let binop = self.lower_binop(binop); let lhs = self.lower_expr(lhs); let rhs = self.lower_expr(rhs); @@ -224,7 +222,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::Expr { hir_id: self.lower_node_id(e.id), kind, - span, + span: e.span, attrs: e.attrs.iter().map(|a| self.lower_attr(a)).collect::>().into(), } }) @@ -239,7 +237,6 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_binop(&mut self, b: BinOp) -> hir::BinOp { - let span = self.mark_span_with_reason(DesugaringKind::Operator, b.span, None); Spanned { node: match b.node { BinOpKind::Add => hir::BinOpKind::Add, @@ -261,7 +258,7 @@ impl<'hir> LoweringContext<'_, 'hir> { BinOpKind::Ge => hir::BinOpKind::Ge, BinOpKind::Gt => hir::BinOpKind::Gt, }, - span, + span: b.span, } } @@ -1363,14 +1360,9 @@ impl<'hir> LoweringContext<'_, 'hir> { body: &Block, opt_label: Option = fn(A); - /// type MetaFunc = for<'a> fn(Func<&'a int>) + /// type MetaFunc = for<'a> fn(Func<&'a i32>) /// ``` /// /// The type `MetaFunc`, when fully expanded, will be /// - /// for<'a> fn(fn(&'a int)) + /// for<'a> fn(fn(&'a i32)) /// ^~ ^~ ^~~ /// | | | /// | | DebruijnIndex of 2 @@ -613,7 +624,7 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> { /// Here the `'a` lifetime is bound in the outer function, but appears as an argument of the /// inner one. Therefore, that appearance will have a DebruijnIndex of 2, because we must skip /// over the inner binder (remember that we count De Bruijn indices from 1). However, in the - /// definition of `MetaFunc`, the binder is not visible, so the type `&'a int` will have a + /// definition of `MetaFunc`, the binder is not visible, so the type `&'a i32` will have a /// De Bruijn index of 1. It's only during the substitution that we can see we must increase the /// depth by 1 to account for the binder that we passed through. /// @@ -621,18 +632,18 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> { /// /// ``` /// type FuncTuple = (A,fn(A)); - /// type MetaFuncTuple = for<'a> fn(FuncTuple<&'a int>) + /// type MetaFuncTuple = for<'a> fn(FuncTuple<&'a i32>) /// ``` /// /// Here the final type will be: /// - /// for<'a> fn((&'a int, fn(&'a int))) + /// for<'a> fn((&'a i32, fn(&'a i32))) /// ^~~ ^~~ /// | | /// DebruijnIndex of 1 | /// DebruijnIndex of 2 /// - /// As indicated in the diagram, here the same type `&'a int` is substituted once, but in the + /// As indicated in the diagram, here the same type `&'a i32` is substituted once, but in the /// first case we do not increase the De Bruijn index and in the second case we do. The reason /// is that only in the second case have we passed through a fn binder. fn shift_vars_through_binders>(&self, val: T) -> T { diff --git a/src/librustc_middle/ty/util.rs b/src/librustc_middle/ty/util.rs index 47110be53b252..67ad7ee708267 100644 --- a/src/librustc_middle/ty/util.rs +++ b/src/librustc_middle/ty/util.rs @@ -681,11 +681,10 @@ impl<'tcx> ty::TyS<'tcx> { /// winds up being reported as an error during NLL borrow check. pub fn is_copy_modulo_regions( &'tcx self, - tcx: TyCtxt<'tcx>, + tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>, - span: Span, ) -> bool { - tcx.at(span).is_copy_raw(param_env.and(self)) + tcx_at.is_copy_raw(param_env.and(self)) } /// Checks whether values of this type `T` have a size known at @@ -706,13 +705,8 @@ impl<'tcx> ty::TyS<'tcx> { /// that the `Freeze` trait is not exposed to end users and is /// effectively an implementation detail. // FIXME: use `TyCtxtAt` instead of separate `Span`. - pub fn is_freeze( - &'tcx self, - tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - span: Span, - ) -> bool { - self.is_trivially_freeze() || tcx.at(span).is_freeze_raw(param_env.and(self)) + pub fn is_freeze(&'tcx self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + self.is_trivially_freeze() || tcx_at.is_freeze_raw(param_env.and(self)) } /// Fast path helper for testing if a type is `Freeze`. diff --git a/src/librustc_middle/ty/walk.rs b/src/librustc_middle/ty/walk.rs index d6f504fdb338b..633d4fda8a46d 100644 --- a/src/librustc_middle/ty/walk.rs +++ b/src/librustc_middle/ty/walk.rs @@ -22,13 +22,13 @@ impl<'tcx> TypeWalker<'tcx> { /// Skips the subtree corresponding to the last type /// returned by `next()`. /// - /// Example: Imagine you are walking `Foo, usize>`. + /// Example: Imagine you are walking `Foo, usize>`. /// /// ``` /// let mut iter: TypeWalker = ...; /// iter.next(); // yields Foo - /// iter.next(); // yields Bar - /// iter.skip_current_subtree(); // skips int + /// iter.next(); // yields Bar + /// iter.skip_current_subtree(); // skips i32 /// iter.next(); // yields usize /// ``` pub fn skip_current_subtree(&mut self) { diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs index 2e897647a3beb..8d7944004c75e 100644 --- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs @@ -24,8 +24,7 @@ use crate::borrow_check::{ }; use super::{ - explain_borrow::BorrowExplanation, FnSelfUseKind, IncludingDowncast, RegionName, - RegionNameSource, UseSpans, + explain_borrow::BorrowExplanation, IncludingDowncast, RegionName, RegionNameSource, UseSpans, }; #[derive(Debug)] @@ -139,7 +138,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let move_msg = if move_spans.for_closure() { " into closure" } else { "" }; - if span == move_span { + if location == move_out.source { err.span_label( span, format!("value moved{} here, in previous iteration of loop", move_msg), @@ -151,70 +150,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { format!("value moved{} here, in previous iteration of loop", move_msg), ); } else { - if let UseSpans::FnSelfUse { var_span, fn_call_span, fn_span, kind } = - move_spans - { - let place_name = self - .describe_place(moved_place.as_ref()) - .map(|n| format!("`{}`", n)) - .unwrap_or_else(|| "value".to_owned()); - match kind { - FnSelfUseKind::FnOnceCall => { - err.span_label( - fn_call_span, - &format!("{} moved due to this call", place_name), - ); - err.span_note( - var_span, - "this value implements `FnOnce`, which causes it to be moved when called", - ); - } - FnSelfUseKind::Operator { self_arg } => { - err.span_label( - fn_call_span, - &format!("{} moved due to usage in operator", place_name), - ); - if self.fn_self_span_reported.insert(fn_span) { - err.span_note( - self_arg.span, - "calling this operator moves the left-hand side", - ); - } - } - FnSelfUseKind::Normal { self_arg, implicit_into_iter } => { - if implicit_into_iter { - err.span_label( - fn_call_span, - &format!( - "{} moved due to this implicit call to `.into_iter()`", - place_name - ), - ); - } else { - err.span_label( - fn_call_span, - &format!("{} moved due to this method call", place_name), - ); - } - // Avoid pointing to the same function in multiple different - // error messages - if self.fn_self_span_reported.insert(self_arg.span) { - err.span_note( - self_arg.span, - &format!("this function consumes the receiver `self` by taking ownership of it, which moves {}", place_name) - ); - } - } - } - } else { - err.span_label(move_span, format!("value moved{} here", move_msg)); - move_spans.var_span_label( - &mut err, - format!("variable moved due to use{}", move_spans.describe()), - ); - } + err.span_label(move_span, format!("value moved{} here", move_msg)); + move_spans.var_span_label( + &mut err, + format!("variable moved due to use{}", move_spans.describe()), + ); } - if let Some(DesugaringKind::ForLoop(_)) = move_span.desugaring_kind() { + if Some(DesugaringKind::ForLoop) == move_span.desugaring_kind() { let sess = self.infcx.tcx.sess; if let Ok(snippet) = sess.source_map().span_to_snippet(move_span) { err.span_suggestion( diff --git a/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs b/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs index d04059ff0fc7f..5253acbba7f1c 100644 --- a/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs +++ b/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs @@ -509,7 +509,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // Used in a closure. (LaterUseKind::ClosureCapture, var_span) } - UseSpans::OtherUse(span) | UseSpans::FnSelfUse { var_span: span, .. } => { + UseSpans::OtherUse(span) => { let block = &self.body.basic_blocks()[location.block]; let kind = if let Some(&Statement { diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs index 04f48cd658230..ca8e54ea28649 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mod.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs @@ -11,11 +11,7 @@ use rustc_middle::mir::{ }; use rustc_middle::ty::print::Print; use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt}; -use rustc_span::{ - hygiene::{DesugaringKind, ForLoopLoc}, - symbol::sym, - Span, -}; +use rustc_span::{symbol::sym, Span}; use rustc_target::abi::VariantIdx; use super::borrow_set::BorrowData; @@ -37,7 +33,6 @@ crate use mutability_errors::AccessKind; crate use outlives_suggestion::OutlivesSuggestionBuilder; crate use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionErrors}; crate use region_name::{RegionName, RegionNameSource}; -use rustc_span::symbol::Ident; pub(super) struct IncludingDowncast(pub(super) bool); @@ -534,58 +529,33 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } -/// The span(s) associated to a use of a place. +// The span(s) associated to a use of a place. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub(super) enum UseSpans { - /// The access is caused by capturing a variable for a closure. + // The access is caused by capturing a variable for a closure. ClosureUse { - /// This is true if the captured variable was from a generator. + // This is true if the captured variable was from a generator. generator_kind: Option, - /// The span of the args of the closure, including the `move` keyword if - /// it's present. + // The span of the args of the closure, including the `move` keyword if + // it's present. args_span: Span, - /// The span of the first use of the captured variable inside the closure. - var_span: Span, - }, - /// The access is caused by using a variable as the receiver of a method - /// that takes 'self' - FnSelfUse { - /// The span of the variable being moved + // The span of the first use of the captured variable inside the closure. var_span: Span, - /// The span of the method call on the variable - fn_call_span: Span, - /// The definition span of the method being called - fn_span: Span, - kind: FnSelfUseKind, }, // This access has a single span associated to it: common case. OtherUse(Span), } -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub(super) enum FnSelfUseKind { - /// A normal method call of the form `receiver.foo(a, b, c)` - Normal { self_arg: Ident, implicit_into_iter: bool }, - /// A call to `FnOnce::call_once`, desugared from `my_closure(a, b, c)` - FnOnceCall, - /// A call to an operator trait, desuraged from operator syntax (e.g. `a << b`) - Operator { self_arg: Ident }, -} - impl UseSpans { pub(super) fn args_or_use(self) -> Span { match self { - UseSpans::ClosureUse { args_span: span, .. } - | UseSpans::FnSelfUse { var_span: span, .. } - | UseSpans::OtherUse(span) => span, + UseSpans::ClosureUse { args_span: span, .. } | UseSpans::OtherUse(span) => span, } } pub(super) fn var_or_use(self) -> Span { match self { - UseSpans::ClosureUse { var_span: span, .. } - | UseSpans::FnSelfUse { var_span: span, .. } - | UseSpans::OtherUse(span) => span, + UseSpans::ClosureUse { var_span: span, .. } | UseSpans::OtherUse(span) => span, } } @@ -654,7 +624,6 @@ impl UseSpans { { match self { closure @ UseSpans::ClosureUse { .. } => closure, - fn_self @ UseSpans::FnSelfUse { .. } => fn_self, UseSpans::OtherUse(_) => if_other(), } } @@ -758,100 +727,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt); if let StatementKind::Assign(box (_, Rvalue::Aggregate(ref kind, ref places))) = stmt.kind { - match kind { + let def_id = match kind { box AggregateKind::Closure(def_id, _) - | box AggregateKind::Generator(def_id, _, _) => { - debug!("move_spans: def_id={:?} places={:?}", def_id, places); - if let Some((args_span, generator_kind, var_span)) = - self.closure_span(*def_id, moved_place, places) - { - return ClosureUse { generator_kind, args_span, var_span }; - } - } - _ => {} - } - } - - let normal_ret = OtherUse(stmt.source_info.span); - - // We are trying to find MIR of the form: - // ``` - // _temp = _moved_val; - // ... - // FnSelfCall(_temp, ...) - // ``` - // - // where `_moved_val` is the place we generated the move error for, - // `_temp` is some other local, and `FnSelfCall` is a function - // that has a `self` parameter. - - let target_temp = match stmt.kind { - StatementKind::Assign(box (temp, _)) if temp.as_local().is_some() => { - temp.as_local().unwrap() - } - _ => return normal_ret, - }; - - debug!("move_spans: target_temp = {:?}", target_temp); - - if let Some(Terminator { kind: TerminatorKind::Call { func, args, fn_span, .. }, .. }) = - &self.body[location.block].terminator - { - let mut method_did = None; - if let Operand::Constant(box Constant { literal: ty::Const { ty, .. }, .. }) = func { - if let ty::FnDef(def_id, _) = ty.kind { - debug!("move_spans: fn = {:?}", def_id); - if let Some(ty::AssocItem { fn_has_self_parameter, .. }) = - self.infcx.tcx.opt_associated_item(def_id) - { - if *fn_has_self_parameter { - method_did = Some(def_id); - } - } - } - } + | box AggregateKind::Generator(def_id, _, _) => def_id, + _ => return OtherUse(stmt.source_info.span), + }; - let tcx = self.infcx.tcx; - let method_did = if let Some(did) = method_did { did } else { return normal_ret }; - - if let [Operand::Move(self_place), ..] = **args { - if self_place.as_local() == Some(target_temp) { - let is_fn_once = tcx.parent(method_did) == tcx.lang_items().fn_once_trait(); - let fn_call_span = *fn_span; - - let self_arg = tcx.fn_arg_names(method_did)[0]; - - let kind = if is_fn_once { - FnSelfUseKind::FnOnceCall - } else if fn_call_span.is_desugaring(DesugaringKind::Operator) { - FnSelfUseKind::Operator { self_arg } - } else { - debug!( - "move_spans: method_did={:?}, fn_call_span={:?}", - method_did, fn_call_span - ); - let implicit_into_iter = matches!( - fn_call_span.desugaring_kind(), - Some(DesugaringKind::ForLoop(ForLoopLoc::IntoIter)) - ); - FnSelfUseKind::Normal { self_arg, implicit_into_iter } - }; - - return FnSelfUse { - var_span: stmt.source_info.span, - fn_call_span, - fn_span: self - .infcx - .tcx - .sess - .source_map() - .guess_head_span(self.infcx.tcx.def_span(method_did)), - kind, - }; - } + debug!("move_spans: def_id={:?} places={:?}", def_id, places); + if let Some((args_span, generator_kind, var_span)) = + self.closure_span(*def_id, moved_place, places) + { + return ClosureUse { generator_kind, args_span, var_span }; } } - return normal_ret; + + OtherUse(stmt.source_info.span) } /// Finds the span of arguments of a closure (within `maybe_closure_span`) diff --git a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs index 4883b08e42442..b49e4187fb810 100644 --- a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs @@ -408,7 +408,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { format!("{}.as_ref()", snippet), Applicability::MaybeIncorrect, ); - } else if matches!(span.desugaring_kind(), Some(DesugaringKind::ForLoop(_))) + } else if span.is_desugaring(DesugaringKind::ForLoop) && self.infcx.tcx.is_diagnostic_item(Symbol::intern("vec_type"), def_id) { // FIXME: suggest for anything that implements `IntoIterator`. diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs index b4bc89e827daa..4d4b6fb9386db 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs @@ -365,7 +365,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { 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(( + Some(DesugaringKind::ForLoop) => Some(( false, opt_assignment_rhs_span.unwrap(), format!( diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 83691d439eb81..03b663eb75056 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -278,7 +278,6 @@ fn do_mir_borrowck<'a, 'tcx>( move_data: &move_data, location_table: &LocationTable::new(promoted_body), movable_generator, - fn_self_span_reported: Default::default(), locals_are_invalidated_at_exit, access_place_error_reported: Default::default(), reservation_error_reported: Default::default(), @@ -312,7 +311,6 @@ fn do_mir_borrowck<'a, 'tcx>( location_table, movable_generator, locals_are_invalidated_at_exit, - fn_self_span_reported: Default::default(), access_place_error_reported: Default::default(), reservation_error_reported: Default::default(), reservation_warnings: Default::default(), @@ -489,10 +487,6 @@ crate struct MirBorrowckCtxt<'cx, 'tcx> { // but it is currently inconvenient to track down the `BorrowIndex` // at the time we detect and report a reservation error. reservation_error_reported: FxHashSet>, - /// This fields keeps track of the `Span`s that we have - /// used to report extra information for `FnSelfUse`, to avoid - /// unnecessarily verbose errors. - fn_self_span_reported: FxHashSet, /// Migration warnings to be reported for #56254. We delay reporting these /// so that we can suppress the warning if there's a corresponding error /// for the activation of the borrow. 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 7ff12820db815..285d9ed64691a 100644 --- a/src/librustc_mir/borrow_check/type_check/relate_tys.rs +++ b/src/librustc_mir/borrow_check/type_check/relate_tys.rs @@ -25,7 +25,7 @@ pub(super) fn relate_types<'tcx>( category: ConstraintCategory, borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>, ) -> Fallible<()> { - debug!("eq_types(a={:?}, b={:?}, locations={:?})", a, b, locations); + debug!("relate_types(a={:?}, v={:?}, b={:?}, locations={:?})", a, v, b, locations); TypeRelating::new( infcx, NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category), diff --git a/src/librustc_mir/const_eval/mod.rs b/src/librustc_mir/const_eval/mod.rs index 3539ccf5de038..ed992a5983954 100644 --- a/src/librustc_mir/const_eval/mod.rs +++ b/src/librustc_mir/const_eval/mod.rs @@ -30,8 +30,10 @@ pub(crate) fn const_caller_location( ConstValue::Scalar(loc_place.ptr) } -// this function uses `unwrap` copiously, because an already validated constant -// must have valid fields and can thus never fail outside of compiler bugs +/// This function uses `unwrap` copiously, because an already validated constant +/// must have valid fields and can thus never fail outside of compiler bugs. However, it is +/// invoked from the pretty printer, where it can receive enums with no variants and e.g. +/// `read_discriminant` needs to be able to handle that. pub(crate) fn destructure_const<'tcx>( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -41,17 +43,21 @@ pub(crate) fn destructure_const<'tcx>( let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false); let op = ecx.eval_const_to_op(val, None).unwrap(); - 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) => usize::try_from(len.eval_usize(tcx, param_env)).unwrap(), - ty::Adt(def, _) => def.variants[variant].fields.len(), - ty::Tuple(substs) => substs.len(), + let (field_count, variant, down) = match val.ty.kind { + ty::Array(_, len) => (usize::try_from(len.eval_usize(tcx, param_env)).unwrap(), None, op), + ty::Adt(def, _) if def.variants.is_empty() => { + return mir::DestructuredConst { variant: None, fields: tcx.arena.alloc_slice(&[]) }; + } + ty::Adt(def, _) => { + let variant = ecx.read_discriminant(op).unwrap().1; + let down = ecx.operand_downcast(op, variant).unwrap(); + (def.variants[variant].fields.len(), Some(variant), down) + } + ty::Tuple(substs) => (substs.len(), None, op), _ => bug!("cannot destructure constant {:?}", val), }; - let down = ecx.operand_downcast(op, variant).unwrap(); let fields_iter = (0..field_count).map(|i| { let field_op = ecx.operand_field(down, i).unwrap(); let val = op_to_const(&ecx, field_op); diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs index 70c916a089270..a3fc51cad656b 100644 --- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs +++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs @@ -233,7 +233,7 @@ impl MutBorrow<'mir, 'tcx> { /// /// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134 fn shared_borrow_allows_mutation(&self, place: Place<'tcx>) -> bool { - !place.ty(self.body, self.tcx).ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) + !place.ty(self.body, self.tcx).ty.is_freeze(self.tcx.at(DUMMY_SP), self.param_env) } } diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index cfe856abe36dd..60cf21552e9e9 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -52,7 +52,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } if self.tcx.has_attr(def_id, sym::rustc_args_required_const) { - bug!("reifying a fn ptr that requires const arguments"); + span_bug!( + self.cur_span(), + "reifying a fn ptr that requires const arguments" + ); } let instance = ty::Instance::resolve_for_fn_ptr( @@ -66,7 +69,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance)); self.write_scalar(fn_ptr, dest)?; } - _ => bug!("reify fn pointer on {:?}", src.layout.ty), + _ => span_bug!(self.cur_span(), "reify fn pointer on {:?}", src.layout.ty), } } @@ -77,7 +80,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // No change to value self.write_immediate(*src, dest)?; } - _ => bug!("fn to unsafe fn cast on {:?}", cast_ty), + _ => span_bug!(self.cur_span(), "fn to unsafe fn cast on {:?}", cast_ty), } } @@ -99,7 +102,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance)); self.write_scalar(fn_ptr, dest)?; } - _ => bug!("closure fn pointer on {:?}", src.layout.ty), + _ => span_bug!(self.cur_span(), "closure fn pointer on {:?}", src.layout.ty), } } } @@ -162,7 +165,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { assert!(src.layout.ty.is_unsafe_ptr()); return match *src { Immediate::ScalarPair(data, _) => Ok(data.into()), - Immediate::Scalar(..) => bug!( + Immediate::Scalar(..) => span_bug!( + self.cur_span(), "{:?} input to a fat-to-thin cast ({:?} -> {:?})", *src, src.layout.ty, @@ -216,7 +220,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } // Casts to bool are not permitted by rustc, no need to handle them here. - _ => bug!("invalid int to {:?} cast", cast_ty), + _ => span_bug!(self.cur_span(), "invalid int to {:?} cast", cast_ty), } } @@ -248,7 +252,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // float -> f64 Float(FloatTy::F64) => Scalar::from_f64(f.convert(&mut false).value), // That's it. - _ => bug!("invalid float to {:?} cast", dest_ty), + _ => span_bug!(self.cur_span(), "invalid float to {:?} cast", dest_ty), } } @@ -287,7 +291,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.write_immediate(val, dest) } - _ => bug!("invalid unsizing {:?} -> {:?}", src.layout.ty, cast_ty), + _ => { + span_bug!(self.cur_span(), "invalid unsizing {:?} -> {:?}", src.layout.ty, cast_ty) + } } } @@ -307,7 +313,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { assert_eq!(def_a, def_b); if def_a.is_box() || def_b.is_box() { if !def_a.is_box() || !def_b.is_box() { - bug!("invalid unsizing between {:?} -> {:?}", src.layout.ty, cast_ty.ty); + span_bug!( + self.cur_span(), + "invalid unsizing between {:?} -> {:?}", + src.layout.ty, + cast_ty.ty + ); } return self.unsize_into_ptr( src, @@ -335,7 +346,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } Ok(()) } - _ => bug!("unsize_into: invalid conversion: {:?} -> {:?}", src.layout, dest.layout), + _ => span_bug!( + self.cur_span(), + "unsize_into: invalid conversion: {:?} -> {:?}", + src.layout, + dest.layout + ), } } } diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 22f4691c22b3d..95e193b625354 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -391,7 +391,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { #[inline] pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool { - ty.is_freeze(*self.tcx, self.param_env, self.tcx.span) + ty.is_freeze(self.tcx, self.param_env) } pub fn load_mir( @@ -536,7 +536,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if sized_size == Size::ZERO { return Ok(None); } else { - bug!("Fields cannot be extern types, unless they are at offset 0") + span_bug!( + self.cur_span(), + "Fields cannot be extern types, unless they are at offset 0" + ) } } }; @@ -584,7 +587,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ty::Foreign(_) => Ok(None), - _ => bug!("size_and_align_of::<{:?}> not supported", layout.ty), + _ => span_bug!(self.cur_span(), "size_and_align_of::<{:?}> not supported", layout.ty), } } #[inline] diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index cab13d379a2cc..dffbc969c21b8 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -111,7 +111,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>( if let InternMode::Static(mutability) = mode { // For this, we need to take into account `UnsafeCell`. When `ty` is `None`, we assume // no interior mutability. - let frozen = ty.map_or(true, |ty| ty.is_freeze(*ecx.tcx, ecx.param_env, ecx.tcx.span)); + let frozen = ty.map_or(true, |ty| ty.is_freeze(ecx.tcx, ecx.param_env)); // For statics, allocation mutability is the combination of the place mutability and // the type mutability. // The entire allocation needs to be mutable if it contains an `UnsafeCell` anywhere. diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index ac28ccd181520..6ac1e6be03674 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -135,7 +135,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let bits = self.force_bits(val, layout_of.size)?; let kind = match layout_of.abi { Abi::Scalar(ref scalar) => scalar.value, - _ => bug!("{} called on invalid type {:?}", intrinsic_name, ty), + _ => span_bug!( + self.cur_span(), + "{} called on invalid type {:?}", + intrinsic_name, + ty + ), }; let (nonzero, intrinsic_name) = match intrinsic_name { sym::cttz_nonzero => (true, sym::cttz), @@ -291,6 +296,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let offset_ptr = ptr.ptr_wrapping_signed_offset(offset_bytes, self); self.write_scalar(offset_ptr, dest)?; } + sym::ptr_guaranteed_eq | sym::ptr_guaranteed_ne => { + // FIXME: return `true` for at least some comparisons where we can reliably + // determine the result of runtime (in)equality tests at compile-time. + self.write_scalar(Scalar::from_bool(false), dest)?; + } sym::ptr_offset_from => { let a = self.read_immediate(args[0])?.to_scalar()?; let b = self.read_immediate(args[1])?.to_scalar()?; diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 35e433c4bd5cd..38948ee53846a 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -311,7 +311,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if let Ok(imm) = self.try_read_immediate(op)? { Ok(imm) } else { - bug!("primitive read failed for type: {:?}", op.layout.ty); + span_bug!(self.cur_span(), "primitive read failed for type: {:?}", op.layout.ty); } } @@ -360,9 +360,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let val = if offset.bytes() == 0 { a } else { b }; Immediate::from(val) } - Immediate::Scalar(val) => { - bug!("field access on non aggregate {:#?}, {:#?}", val, op.layout) - } + Immediate::Scalar(val) => span_bug!( + self.cur_span(), + "field access on non aggregate {:#?}, {:#?}", + val, + op.layout + ), }; Ok(OpTy { op: Operand::Immediate(immediate), layout: field_layout }) } @@ -545,7 +548,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ty::ConstKind::Infer(..) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(..) => { - bug!("eval_const_to_op: Unexpected ConstKind {:?}", val) + span_bug!(self.cur_span(), "eval_const_to_op: Unexpected ConstKind {:?}", val) } ty::ConstKind::Value(val_val) => val_val, }; @@ -656,7 +659,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .discriminants(def_id, *self.tcx) .find(|(_, var)| var.val == discr_bits) } - _ => bug!("tagged layout for non-adt non-generator"), + _ => span_bug!(self.cur_span(), "tagged layout for non-adt non-generator"), } .ok_or_else(|| err_ub!(InvalidTag(tag_val.erase_tag())))?; // Return the cast value, and the index. diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index d651267f82b79..607122935347e 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -61,7 +61,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Le => l <= r, Gt => l > r, Ge => l >= r, - _ => bug!("Invalid operation on char: {:?}", bin_op), + _ => span_bug!(self.cur_span(), "Invalid operation on char: {:?}", bin_op), }; (Scalar::from_bool(res), false, self.tcx.types.bool) } @@ -84,7 +84,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { BitAnd => l & r, BitOr => l | r, BitXor => l ^ r, - _ => bug!("Invalid operation on bool: {:?}", bin_op), + _ => span_bug!(self.cur_span(), "Invalid operation on bool: {:?}", bin_op), }; (Scalar::from_bool(res), false, self.tcx.types.bool) } @@ -110,7 +110,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Mul => ((l * r).value.into(), ty), Div => ((l / r).value.into(), ty), Rem => ((l % r).value.into(), ty), - _ => bug!("invalid float op: `{:?}`", bin_op), + _ => span_bug!(self.cur_span(), "invalid float op: `{:?}`", bin_op), }; (val, false, ty) } @@ -154,7 +154,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // For the remaining ops, the types must be the same on both sides if left_layout.ty != right_layout.ty { - bug!( + span_bug!( + self.cur_span(), "invalid asymmetric binary op {:?}: {:?} ({:?}), {:?} ({:?})", bin_op, l, @@ -251,7 +252,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { )); } - _ => bug!( + _ => span_bug!( + self.cur_span(), "invalid binary op {:?}: {:?}, {:?} (both {:?})", bin_op, l, @@ -333,7 +335,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { M::binary_ptr_op(self, bin_op, left, right) } - _ => bug!("Invalid MIR: bad LHS type for binop: {:?}", left.layout.ty), + _ => span_bug!( + self.cur_span(), + "Invalid MIR: bad LHS type for binop: {:?}", + left.layout.ty + ), } } @@ -367,7 +373,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let val = val.to_bool()?; let res = match un_op { Not => !val, - _ => bug!("Invalid bool op {:?}", un_op), + _ => span_bug!(self.cur_span(), "Invalid bool op {:?}", un_op), }; Ok((Scalar::from_bool(res), false, self.tcx.types.bool)) } @@ -375,7 +381,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let res = match (un_op, fty) { (Neg, FloatTy::F32) => Scalar::from_f32(-val.to_f32()?), (Neg, FloatTy::F64) => Scalar::from_f64(-val.to_f64()?), - _ => bug!("Invalid float op {:?}", un_op), + _ => span_bug!(self.cur_span(), "Invalid float op {:?}", un_op), }; Ok((res, false, layout.ty)) } diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 1d57fce39734e..4681079a22ddf 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -24,9 +24,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Goto { target } => self.go_to_block(target), - SwitchInt { ref discr, ref values, ref targets, .. } => { + SwitchInt { ref discr, ref values, ref targets, switch_ty } => { let discr = self.read_immediate(self.eval_operand(discr, None)?)?; trace!("SwitchInt({:?})", *discr); + assert_eq!(discr.layout.ty, switch_ty); // Branch to the `otherwise` case by default, if no match is found. assert!(!targets.is_empty()); @@ -50,14 +51,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.go_to_block(target_block); } - Call { - ref func, - ref args, - destination, - ref cleanup, - from_hir_call: _from_hir_call, - fn_span: _, - } => { + Call { ref func, ref args, destination, ref cleanup, from_hir_call: _, fn_span: _ } => { let old_stack = self.frame_idx(); let old_loc = self.frame().loc; let func = self.eval_operand(func, None)?; @@ -232,7 +226,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ty::FnDef(..) => instance_ty.fn_sig(*self.tcx).abi(), ty::Closure(..) => Abi::RustCall, ty::Generator(..) => Abi::Rust, - _ => bug!("unexpected callee ty: {:?}", instance_ty), + _ => span_bug!(self.cur_span(), "unexpected callee ty: {:?}", instance_ty), } }; let normalize_abi = |abi| match abi { diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 36f3947d83017..f9b3c319c1f66 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -1,7 +1,7 @@ //! Mono Item Collection //! ==================== //! -//! This module is responsible for discovering all items that will contribute to +//! This module is responsible for discovering all items that will contribute //! to code generation of the crate. The important part here is that it not only //! needs to find syntax-level items (functions, structs, etc) but also all //! their monomorphized instantiations. Every non-generic, non-const function @@ -79,7 +79,7 @@ //! function or method call (represented by a CALL terminator in MIR). But //! calls are not the only thing that might introduce a reference between two //! function mono items, and as we will see below, they are just a -//! specialized of the form described next, and consequently will don't get any +//! specialization of the form described next, and consequently will not get any //! special treatment in the algorithm. //! //! #### Taking a reference to a function or method @@ -158,7 +158,7 @@ //! - Eager mode is meant to be used in conjunction with incremental compilation //! where a stable set of mono items is more important than a minimal //! one. Thus, eager mode will instantiate drop-glue for every drop-able type -//! in the crate, even of no drop call for that type exists (yet). It will +//! in the crate, even if no drop call for that type exists (yet). It will //! also instantiate default implementations of trait methods, something that //! otherwise is only done on demand. //! @@ -178,7 +178,7 @@ use crate::monomorphize; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator}; -use rustc_errors::ErrorReported; +use rustc_errors::{ErrorReported, FatalError}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; @@ -195,6 +195,7 @@ use rustc_middle::ty::print::obsolete::DefPathBasedNames; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; use rustc_middle::ty::{self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable}; use rustc_session::config::EntryFnType; +use rustc_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP}; use smallvec::SmallVec; use std::iter; @@ -294,7 +295,13 @@ pub fn collect_crate_mono_items( tcx.sess.time("monomorphization_collector_graph_walk", || { par_iter(roots).for_each(|root| { let mut recursion_depths = DefIdMap::default(); - collect_items_rec(tcx, root, visited, &mut recursion_depths, inlining_map); + collect_items_rec( + tcx, + dummy_spanned(root), + visited, + &mut recursion_depths, + inlining_map, + ); }); }); } @@ -323,29 +330,30 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec( tcx: TyCtxt<'tcx>, - starting_point: MonoItem<'tcx>, + starting_point: Spanned>, visited: MTRef<'_, MTLock>>>, recursion_depths: &mut DefIdMap, inlining_map: MTRef<'_, MTLock>>, ) { - if !visited.lock_mut().insert(starting_point) { + if !visited.lock_mut().insert(starting_point.node) { // We've been here already, no need to search again. return; } - debug!("BEGIN collect_items_rec({})", starting_point.to_string(tcx, true)); + debug!("BEGIN collect_items_rec({})", starting_point.node.to_string(tcx, true)); let mut neighbors = Vec::new(); let recursion_depth_reset; - match starting_point { + match starting_point.node { MonoItem::Static(def_id) => { let instance = Instance::mono(tcx, def_id); @@ -353,7 +361,7 @@ fn collect_items_rec<'tcx>( debug_assert!(should_monomorphize_locally(tcx, &instance)); let ty = instance.monomorphic_ty(tcx); - visit_drop_use(tcx, ty, true, &mut neighbors); + visit_drop_use(tcx, ty, true, starting_point.span, &mut neighbors); recursion_depth_reset = None; @@ -366,7 +374,8 @@ fn collect_items_rec<'tcx>( debug_assert!(should_monomorphize_locally(tcx, &instance)); // Keep track of the monomorphization recursion depth - recursion_depth_reset = Some(check_recursion_limit(tcx, instance, recursion_depths)); + recursion_depth_reset = + Some(check_recursion_limit(tcx, instance, starting_point.span, recursion_depths)); check_type_length_limit(tcx, instance); rustc_data_structures::stack::ensure_sufficient_stack(|| { @@ -378,7 +387,7 @@ fn collect_items_rec<'tcx>( } } - record_accesses(tcx, starting_point, &neighbors[..], inlining_map); + record_accesses(tcx, starting_point.node, neighbors.iter().map(|i| &i.node), inlining_map); for neighbour in neighbors { collect_items_rec(tcx, neighbour, visited, recursion_depths, inlining_map); @@ -388,13 +397,13 @@ fn collect_items_rec<'tcx>( recursion_depths.insert(def_id, depth); } - debug!("END collect_items_rec({})", starting_point.to_string(tcx, true)); + debug!("END collect_items_rec({})", starting_point.node.to_string(tcx, true)); } -fn record_accesses<'tcx>( +fn record_accesses<'a, 'tcx: 'a>( tcx: TyCtxt<'tcx>, caller: MonoItem<'tcx>, - callees: &[MonoItem<'tcx>], + callees: impl Iterator>, inlining_map: MTRef<'_, MTLock>>, ) { let is_inlining_candidate = |mono_item: &MonoItem<'tcx>| { @@ -405,7 +414,7 @@ fn record_accesses<'tcx>( // FIXME: Call `is_inlining_candidate` when pushing to `neighbors` in `collect_items_rec` // instead to avoid creating this `SmallVec`. let accesses: SmallVec<[_; 128]> = - callees.iter().map(|mono_item| (*mono_item, is_inlining_candidate(mono_item))).collect(); + callees.map(|mono_item| (*mono_item, is_inlining_candidate(mono_item))).collect(); inlining_map.lock_mut().record_accesses(caller, &accesses); } @@ -413,6 +422,7 @@ fn record_accesses<'tcx>( fn check_recursion_limit<'tcx>( tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, + span: Span, recursion_depths: &mut DefIdMap, ) -> (DefId, usize) { let def_id = instance.def_id(); @@ -432,12 +442,13 @@ fn check_recursion_limit<'tcx>( // infinite expansion. if !tcx.sess.recursion_limit().value_within_limit(adjusted_recursion_depth) { let error = format!("reached the recursion limit while instantiating `{}`", instance); - if let Some(def_id) = def_id.as_local() { - let hir_id = tcx.hir().as_local_hir_id(def_id); - tcx.sess.span_fatal(tcx.hir().span(hir_id), &error); - } else { - tcx.sess.fatal(&error); - } + let mut err = tcx.sess.struct_span_fatal(span, &error); + err.span_note( + tcx.def_span(def_id), + &format!("`{}` defined here", tcx.def_path_str(def_id)), + ); + err.emit(); + FatalError.raise(); } recursion_depths.insert(def_id, recursion_depth + 1); @@ -498,7 +509,7 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { struct MirNeighborCollector<'a, 'tcx> { tcx: TyCtxt<'tcx>, body: &'a mir::Body<'tcx>, - output: &'a mut Vec>, + output: &'a mut Vec>>, instance: Instance<'tcx>, } @@ -520,6 +531,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) { debug!("visiting rvalue {:?}", *rvalue); + let span = self.body.source_info(location).span; + match *rvalue { // When doing an cast from a regular pointer to a fat pointer, we // have to instantiate all methods of the trait being cast to, so we @@ -542,6 +555,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { self.tcx, target_ty, source_ty, + span, self.output, ); } @@ -553,7 +567,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { ) => { let fn_ty = operand.ty(self.body, self.tcx); let fn_ty = self.monomorphize(fn_ty); - visit_fn_use(self.tcx, fn_ty, false, &mut self.output); + visit_fn_use(self.tcx, fn_ty, false, span, &mut self.output); } mir::Rvalue::Cast( mir::CastKind::Pointer(PointerCast::ClosureFnPointer(_)), @@ -571,7 +585,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { ty::ClosureKind::FnOnce, ); if should_monomorphize_locally(self.tcx, &instance) { - self.output.push(create_fn_mono_item(instance)); + self.output.push(create_fn_mono_item(instance, span)); } } _ => bug!(), @@ -583,7 +597,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { tcx.require_lang_item(ExchangeMallocFnLangItem, None); let instance = Instance::mono(tcx, exchange_malloc_fn_def_id); if should_monomorphize_locally(tcx, &instance) { - self.output.push(create_fn_mono_item(instance)); + self.output.push(create_fn_mono_item(instance, span)); } } mir::Rvalue::ThreadLocalRef(def_id) => { @@ -591,7 +605,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { let instance = Instance::mono(self.tcx, def_id); if should_monomorphize_locally(self.tcx, &instance) { trace!("collecting thread-local static {:?}", def_id); - self.output.push(MonoItem::Static(def_id)); + self.output.push(respan(span, MonoItem::Static(def_id))); } } _ => { /* not interesting */ } @@ -626,32 +640,33 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Location) { debug!("visiting terminator {:?} @ {:?}", terminator, location); + let source = self.body.source_info(location).span; let tcx = self.tcx; match terminator.kind { mir::TerminatorKind::Call { ref func, .. } => { let callee_ty = func.ty(self.body, tcx); let callee_ty = self.monomorphize(callee_ty); - visit_fn_use(self.tcx, callee_ty, true, &mut self.output); + visit_fn_use(self.tcx, callee_ty, true, source, &mut self.output); } mir::TerminatorKind::Drop { ref place, .. } | mir::TerminatorKind::DropAndReplace { ref place, .. } => { let ty = place.ty(self.body, self.tcx).ty; let ty = self.monomorphize(ty); - visit_drop_use(self.tcx, ty, true, self.output); + visit_drop_use(self.tcx, ty, true, source, self.output); } mir::TerminatorKind::InlineAsm { ref operands, .. } => { for op in operands { match *op { mir::InlineAsmOperand::SymFn { ref value } => { let fn_ty = self.monomorphize(value.literal.ty); - visit_fn_use(self.tcx, fn_ty, false, &mut self.output); + visit_fn_use(self.tcx, fn_ty, false, source, &mut self.output); } mir::InlineAsmOperand::SymStatic { def_id } => { let instance = Instance::mono(self.tcx, def_id); if should_monomorphize_locally(self.tcx, &instance) { trace!("collecting asm sym static {:?}", def_id); - self.output.push(MonoItem::Static(def_id)); + self.output.push(respan(source, MonoItem::Static(def_id))); } } _ => {} @@ -687,17 +702,19 @@ fn visit_drop_use<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, is_direct_call: bool, - output: &mut Vec>, + source: Span, + output: &mut Vec>>, ) { let instance = Instance::resolve_drop_in_place(tcx, ty); - visit_instance_use(tcx, instance, is_direct_call, output); + visit_instance_use(tcx, instance, is_direct_call, source, output); } fn visit_fn_use<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, is_direct_call: bool, - output: &mut Vec>, + source: Span, + output: &mut Vec>>, ) { if let ty::FnDef(def_id, substs) = ty.kind { let instance = if is_direct_call { @@ -706,7 +723,7 @@ fn visit_fn_use<'tcx>( ty::Instance::resolve_for_fn_ptr(tcx, ty::ParamEnv::reveal_all(), def_id, substs) .unwrap() }; - visit_instance_use(tcx, instance, is_direct_call, output); + visit_instance_use(tcx, instance, is_direct_call, source, output); } } @@ -714,7 +731,8 @@ fn visit_instance_use<'tcx>( tcx: TyCtxt<'tcx>, instance: ty::Instance<'tcx>, is_direct_call: bool, - output: &mut Vec>, + source: Span, + output: &mut Vec>>, ) { debug!("visit_item_use({:?}, is_direct_call={:?})", instance, is_direct_call); if !should_monomorphize_locally(tcx, &instance) { @@ -730,7 +748,7 @@ fn visit_instance_use<'tcx>( ty::InstanceDef::DropGlue(_, None) => { // Don't need to emit noop drop glue if we are calling directly. if !is_direct_call { - output.push(create_fn_mono_item(instance)); + output.push(create_fn_mono_item(instance, source)); } } ty::InstanceDef::DropGlue(_, Some(_)) @@ -740,7 +758,7 @@ fn visit_instance_use<'tcx>( | ty::InstanceDef::Item(..) | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::CloneShim(..) => { - output.push(create_fn_mono_item(instance)); + output.push(create_fn_mono_item(instance, source)); } } } @@ -832,7 +850,6 @@ fn find_vtable_types_for_unsizing<'tcx>( let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| { let param_env = ty::ParamEnv::reveal_all(); let type_has_metadata = |ty: Ty<'tcx>| -> bool { - use rustc_span::DUMMY_SP; if ty.is_sized(tcx.at(DUMMY_SP), param_env) { return false; } @@ -886,9 +903,9 @@ fn find_vtable_types_for_unsizing<'tcx>( } } -fn create_fn_mono_item(instance: Instance<'_>) -> MonoItem<'_> { +fn create_fn_mono_item(instance: Instance<'_>, source: Span) -> Spanned> { debug!("create_fn_mono_item(instance={})", instance); - MonoItem::Fn(instance) + respan(source, MonoItem::Fn(instance)) } /// Creates a `MonoItem` for each method that is referenced by the vtable for @@ -897,7 +914,8 @@ fn create_mono_items_for_vtable_methods<'tcx>( tcx: TyCtxt<'tcx>, trait_ty: Ty<'tcx>, impl_ty: Ty<'tcx>, - output: &mut Vec>, + source: Span, + output: &mut Vec>>, ) { assert!( !trait_ty.needs_subst() @@ -927,12 +945,12 @@ fn create_mono_items_for_vtable_methods<'tcx>( .unwrap() }) .filter(|&instance| should_monomorphize_locally(tcx, &instance)) - .map(create_fn_mono_item); + .map(|item| create_fn_mono_item(item, source)); output.extend(methods); } // Also add the destructor. - visit_drop_use(tcx, impl_ty, false, output); + visit_drop_use(tcx, impl_ty, false, source, output); } } @@ -943,7 +961,7 @@ fn create_mono_items_for_vtable_methods<'tcx>( struct RootCollector<'a, 'tcx> { tcx: TyCtxt<'tcx>, mode: MonoItemCollectionMode, - output: &'a mut Vec>, + output: &'a mut Vec>>, entry_fn: Option<(LocalDefId, EntryFnType)>, } @@ -980,7 +998,7 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> { let ty = Instance::new(def_id.to_def_id(), InternalSubsts::empty()) .monomorphic_ty(self.tcx); - visit_drop_use(self.tcx, ty, true, self.output); + visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output); } } } @@ -989,12 +1007,12 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> { "RootCollector: ItemKind::GlobalAsm({})", def_id_to_string(self.tcx, self.tcx.hir().local_def_id(item.hir_id)) ); - self.output.push(MonoItem::GlobalAsm(item.hir_id)); + self.output.push(dummy_spanned(MonoItem::GlobalAsm(item.hir_id))); } hir::ItemKind::Static(..) => { let def_id = self.tcx.hir().local_def_id(item.hir_id); debug!("RootCollector: ItemKind::Static({})", def_id_to_string(self.tcx, def_id)); - self.output.push(MonoItem::Static(def_id.to_def_id())); + self.output.push(dummy_spanned(MonoItem::Static(def_id.to_def_id()))); } hir::ItemKind::Const(..) => { // const items only generate mono items if they are @@ -1051,7 +1069,7 @@ impl RootCollector<'_, 'v> { debug!("RootCollector::push_if_root: found root def_id={:?}", def_id); let instance = Instance::mono(self.tcx, def_id.to_def_id()); - self.output.push(create_fn_mono_item(instance)); + self.output.push(create_fn_mono_item(instance, DUMMY_SP)); } } @@ -1088,7 +1106,7 @@ impl RootCollector<'_, 'v> { .unwrap() .unwrap(); - self.output.push(create_fn_mono_item(start_instance)); + self.output.push(create_fn_mono_item(start_instance, DUMMY_SP)); } } @@ -1100,7 +1118,7 @@ fn item_requires_monomorphization(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { fn create_mono_items_for_default_impls<'tcx>( tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>, - output: &mut Vec>, + output: &mut Vec>>, ) { match item.kind { hir::ItemKind::Impl { ref generics, ref items, .. } => { @@ -1145,8 +1163,9 @@ fn create_mono_items_for_default_impls<'tcx>( .unwrap() .unwrap(); - let mono_item = create_fn_mono_item(instance); - if mono_item.is_instantiable(tcx) && should_monomorphize_locally(tcx, &instance) + let mono_item = create_fn_mono_item(instance, DUMMY_SP); + if mono_item.node.is_instantiable(tcx) + && should_monomorphize_locally(tcx, &instance) { output.push(mono_item); } @@ -1158,14 +1177,18 @@ fn create_mono_items_for_default_impls<'tcx>( } /// Scans the miri alloc in order to find function calls, closures, and drop-glue. -fn collect_miri<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut Vec>) { +fn collect_miri<'tcx>( + tcx: TyCtxt<'tcx>, + alloc_id: AllocId, + output: &mut Vec>>, +) { match tcx.global_alloc(alloc_id) { GlobalAlloc::Static(def_id) => { assert!(!tcx.is_thread_local_static(def_id)); let instance = Instance::mono(tcx, def_id); if should_monomorphize_locally(tcx, &instance) { trace!("collecting static {:?}", def_id); - output.push(MonoItem::Static(def_id)); + output.push(dummy_spanned(MonoItem::Static(def_id))); } } GlobalAlloc::Memory(alloc) => { @@ -1179,7 +1202,7 @@ fn collect_miri<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut Vec { if should_monomorphize_locally(tcx, &fn_instance) { trace!("collecting {:?} with {:#?}", alloc_id, fn_instance); - output.push(create_fn_mono_item(fn_instance)); + output.push(create_fn_mono_item(fn_instance, DUMMY_SP)); } } } @@ -1189,7 +1212,7 @@ fn collect_miri<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut Vec( tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, - output: &mut Vec>, + output: &mut Vec>>, ) { debug!("collect_neighbours: {:?}", instance.def_id()); let body = tcx.instance_mir(instance.def); @@ -1207,7 +1230,7 @@ fn def_id_to_string(tcx: TyCtxt<'_>, def_id: LocalDefId) -> String { fn collect_const_value<'tcx>( tcx: TyCtxt<'tcx>, value: ConstValue<'tcx>, - output: &mut Vec>, + output: &mut Vec>>, ) { match value { ConstValue::Scalar(Scalar::Ptr(ptr)) => collect_miri(tcx, ptr.alloc_id, output), diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 71fff85153141..8327affd982ed 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -32,13 +32,9 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' let mut result = match instance { ty::InstanceDef::Item(..) => bug!("item {:?} passed to make_shim", instance), - ty::InstanceDef::VtableShim(def_id) => build_call_shim( - tcx, - instance, - Some(Adjustment::DerefMove), - CallKind::Direct(def_id), - None, - ), + ty::InstanceDef::VtableShim(def_id) => { + build_call_shim(tcx, instance, Some(Adjustment::Deref), CallKind::Direct(def_id), 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 @@ -60,7 +56,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' let sig = tcx.erase_late_bound_regions(&ty.fn_sig(tcx)); let arg_tys = sig.inputs(); - build_call_shim(tcx, instance, Some(adjustment), CallKind::Indirect, Some(arg_tys)) + build_call_shim(tcx, instance, Some(adjustment), CallKind::Indirect(ty), Some(arg_tys)) } // We are generating a call back to our def-id, which the // codegen backend knows to turn to an actual call, be it @@ -134,15 +130,28 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' #[derive(Copy, Clone, Debug, PartialEq)] enum Adjustment { + /// Pass the receiver as-is. Identity, + + /// We get passed `&[mut] self` and call the target with `*self`. + /// + /// This either copies `self` (if `Self: Copy`, eg. for function items), or moves out of it + /// (for `VtableShim`, which effectively is passed `&own Self`). Deref, - DerefMove, + + /// We get passed `self: Self` and call the target with `&mut self`. + /// + /// In this case we need to ensure that the `Self` is dropped after the call, as the callee + /// won't do it for us. RefMut, } #[derive(Copy, Clone, Debug, PartialEq)] -enum CallKind { - Indirect, +enum CallKind<'tcx> { + /// Call the `FnPtr` that was passed as the receiver. + Indirect(Ty<'tcx>), + + /// Call a known `FnDef`. Direct(DefId), } @@ -318,7 +327,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) - let param_env = tcx.param_env(def_id); let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty); - let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env, builder.span); + let is_copy = self_ty.is_copy_modulo_regions(tcx.at(builder.span), param_env); let dest = Place::return_place(); let src = tcx.mk_place_deref(Place::from(Local::new(1 + 0))); @@ -662,7 +671,7 @@ fn build_call_shim<'tcx>( tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>, rcvr_adjustment: Option, - call_kind: CallKind, + call_kind: CallKind<'tcx>, untuple_args: Option<&[Ty<'tcx>]>, ) -> Body<'tcx> { debug!( @@ -675,6 +684,29 @@ fn build_call_shim<'tcx>( let sig = tcx.fn_sig(def_id); let mut sig = tcx.erase_late_bound_regions(&sig); + if let CallKind::Indirect(fnty) = call_kind { + // `sig` determines our local decls, and thus the callee type in the `Call` terminator. This + // can only be an `FnDef` or `FnPtr`, but currently will be `Self` since the types come from + // the implemented `FnX` trait. + + // Apply the opposite adjustment to the MIR input. + let mut inputs_and_output = sig.inputs_and_output.to_vec(); + + // Initial signature is `fn(&? Self, Args) -> Self::Output` where `Args` is a tuple of the + // fn arguments. `Self` may be passed via (im)mutable reference or by-value. + assert_eq!(inputs_and_output.len(), 3); + + // `Self` is always the original fn type `ty`. The MIR call terminator is only defined for + // `FnDef` and `FnPtr` callees, not the `Self` type param. + let self_arg = &mut inputs_and_output[0]; + *self_arg = match rcvr_adjustment.unwrap() { + Adjustment::Identity => fnty, + Adjustment::Deref => tcx.mk_imm_ptr(fnty), + Adjustment::RefMut => tcx.mk_mut_ptr(fnty), + }; + sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output); + } + // FIXME(eddyb) avoid having this snippet both here and in // `Instance::fn_sig` (introduce `InstanceDef::fn_sig`?). if let ty::InstanceDef::VtableShim(..) = instance { @@ -701,8 +733,7 @@ fn build_call_shim<'tcx>( let rcvr = rcvr_adjustment.map(|rcvr_adjustment| match rcvr_adjustment { Adjustment::Identity => Operand::Move(rcvr_place()), - Adjustment::Deref => Operand::Move(tcx.mk_place_deref(rcvr_place())), // Can't copy `&mut` - Adjustment::DerefMove => Operand::Move(tcx.mk_place_deref(rcvr_place())), + Adjustment::Deref => Operand::Move(tcx.mk_place_deref(rcvr_place())), Adjustment::RefMut => { // let rcvr = &mut rcvr; let ref_rcvr = local_decls.push( @@ -728,7 +759,10 @@ fn build_call_shim<'tcx>( }); let (callee, mut args) = match call_kind { - CallKind::Indirect => (rcvr.unwrap(), vec![]), + // `FnPtr` call has no receiver. Args are untupled below. + CallKind::Indirect(_) => (rcvr.unwrap(), vec![]), + + // `FnDef` call with optional receiver. CallKind::Direct(def_id) => { let ty = tcx.type_of(def_id); ( diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs index d5059c98c9511..676688daf1c6d 100644 --- a/src/librustc_mir/transform/check_consts/ops.rs +++ b/src/librustc_mir/transform/check_consts/ops.rs @@ -160,17 +160,20 @@ pub struct InlineAsm; impl NonConstOp for InlineAsm {} #[derive(Debug)] -pub struct LiveDrop; +pub struct LiveDrop(pub Option); impl NonConstOp for LiveDrop { fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) { - struct_span_err!( + let mut diagnostic = struct_span_err!( ccx.tcx.sess, span, E0493, "destructors cannot be evaluated at compile-time" - ) - .span_label(span, format!("{}s cannot evaluate destructors", ccx.const_kind())) - .emit(); + ); + diagnostic.span_label(span, format!("{}s cannot evaluate destructors", ccx.const_kind())); + if let Some(span) = self.0 { + diagnostic.span_label(span, "value is dropped here"); + } + diagnostic.emit(); } } @@ -205,22 +208,34 @@ impl NonConstOp for CellBorrow { #[derive(Debug)] pub struct MutBorrow; impl NonConstOp for MutBorrow { + fn is_allowed_in_item(&self, ccx: &ConstCx<'_, '_>) -> bool { + // Forbid everywhere except in const fn + ccx.const_kind() == hir::ConstContext::ConstFn + && ccx.tcx.features().enabled(Self::feature_gate().unwrap()) + } + fn feature_gate() -> Option { Some(sym::const_mut_refs) } fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) { - let mut err = feature_err( - &ccx.tcx.sess.parse_sess, - sym::const_mut_refs, - span, - &format!( - "references in {}s may only refer \ - to immutable values", - ccx.const_kind() - ), - ); - err.span_label(span, format!("{}s require immutable values", ccx.const_kind())); + let mut err = if ccx.const_kind() == hir::ConstContext::ConstFn { + feature_err( + &ccx.tcx.sess.parse_sess, + sym::const_mut_refs, + span, + &format!("mutable references are not allowed in {}s", ccx.const_kind()), + ) + } else { + struct_span_err!( + ccx.tcx.sess, + span, + E0764, + "mutable references are not allowed in {}s", + ccx.const_kind(), + ) + }; + err.span_label(span, "`&mut` is only allowed in `const fn`".to_string()); if ccx.tcx.sess.teach(&err.get_code().unwrap()) { err.note( "References in statics and constants may only refer \ @@ -284,18 +299,16 @@ impl NonConstOp for Panic { #[derive(Debug)] pub struct RawPtrComparison; impl NonConstOp for RawPtrComparison { - fn feature_gate() -> Option { - Some(sym::const_compare_raw_pointers) - } - fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) { - feature_err( - &ccx.tcx.sess.parse_sess, - sym::const_compare_raw_pointers, - span, - &format!("comparing raw pointers inside {}", ccx.const_kind()), - ) - .emit(); + let mut err = ccx + .tcx + .sess + .struct_span_err(span, "pointers cannot be reliably compared during const eval."); + err.note( + "see issue #53020 \ + for more information", + ); + err.emit(); } } diff --git a/src/librustc_mir/transform/check_consts/post_drop_elaboration.rs b/src/librustc_mir/transform/check_consts/post_drop_elaboration.rs index 124606fb423e6..1fd907f89fe18 100644 --- a/src/librustc_mir/transform/check_consts/post_drop_elaboration.rs +++ b/src/librustc_mir/transform/check_consts/post_drop_elaboration.rs @@ -58,7 +58,7 @@ impl std::ops::Deref for CheckLiveDrops<'mir, 'tcx> { impl CheckLiveDrops<'mir, 'tcx> { fn check_live_drop(&self, span: Span) { - ops::non_const(self.ccx, ops::LiveDrop, span); + ops::non_const(self.ccx, ops::LiveDrop(None), span); } } diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs index 936c1a84e142e..e2893e81a2ce6 100644 --- a/src/librustc_mir/transform/check_consts/qualifs.rs +++ b/src/librustc_mir/transform/check_consts/qualifs.rs @@ -77,7 +77,7 @@ impl Qualif for HasMutInterior { } fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { - !ty.is_freeze(cx.tcx, cx.param_env, DUMMY_SP) + !ty.is_freeze(cx.tcx.at(DUMMY_SP), cx.param_env) } fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &'tcx AdtDef, _: SubstsRef<'tcx>) -> bool { diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index 35a8df62cb83a..d263bf12e8868 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -588,7 +588,10 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { }; if needs_drop { - self.check_op_spanned(ops::LiveDrop, err_span); + self.check_op_spanned( + ops::LiveDrop(Some(terminator.source_info.span)), + err_span, + ); } } diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 7dbb2ebad8b99..b8f725e967ddb 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -171,21 +171,6 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { _ => {} } } - // raw pointer and fn pointer operations are unsafe as it is not clear whether one - // pointer would be "less" or "equal" to another, because we cannot know where llvm - // or the linker will place various statics in memory. Without this information the - // result of a comparison of addresses would differ between runtime and compile-time. - Rvalue::BinaryOp(_, ref lhs, _) - if self.const_context && self.tcx.features().const_compare_raw_pointers => - { - if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body, self.tcx).kind { - self.require_unsafe( - "pointer operation", - "operations on pointers in constants", - UnsafetyViolationKind::General, - ); - } - } _ => {} } self.super_rvalue(rvalue, location); @@ -282,9 +267,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { ), }; if !elem_ty.is_copy_modulo_regions( - self.tcx, + self.tcx.at(self.source_info.span), self.param_env, - self.source_info.span, ) { self.require_unsafe( "assignment to non-`Copy` union field", @@ -459,11 +443,11 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { // Check `is_freeze` as late as possible to avoid cycle errors // with opaque types. - } else if !place.ty(self.body, self.tcx).ty.is_freeze( - self.tcx, - self.param_env, - self.source_info.span, - ) { + } else if !place + .ty(self.body, self.tcx) + .ty + .is_freeze(self.tcx.at(self.source_info.span), self.param_env) + { ( "borrow of layout constrained field with interior \ mutability", diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 17ca918d32c9f..eb614170baae5 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -505,7 +505,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // This is basically `force_bits`. let r_bits = r_bits.and_then(|r| r.to_bits_or_ptr(right_size, &self.tcx).ok()); if r_bits.map_or(false, |b| b >= left_size_bits as u128) { - debug!("check_binary_op: reporting assert for {:?}", source_info); self.report_assert_as_lint( lint::builtin::ARITHMETIC_OVERFLOW, source_info, @@ -575,8 +574,16 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } // Do not try creating references (#67862) - Rvalue::Ref(_, _, place_ref) => { - trace!("skipping Ref({:?})", place_ref); + Rvalue::AddressOf(_, place) | Rvalue::Ref(_, _, place) => { + trace!("skipping AddressOf | Ref for {:?}", place); + + // This may be creating mutable references or immutable references to cells. + // If that happens, the pointed to value could be mutated via that reference. + // Since we aren't tracking references, the const propagator loses track of what + // value the local has right now. + // Thus, all locals that have their reference taken + // must not take part in propagation. + Self::remove_const(&mut self.ecx, place.local); return None; } @@ -716,7 +723,8 @@ enum ConstPropMode { OnlyInsideOwnBlock, /// The `Local` can be propagated into but reads cannot be propagated. OnlyPropagateInto, - /// No propagation is allowed at all. + /// The `Local` cannot be part of propagation at all. Any statement + /// referencing it either for reading or writing will not get propagated. NoPropagation, } @@ -783,12 +791,14 @@ impl<'tcx> Visitor<'tcx> for CanConstProp { // end of the block anyway, and inside the block we overwrite previous // states as applicable. ConstPropMode::OnlyInsideOwnBlock => {} - other => { + ConstPropMode::NoPropagation => {} + ConstPropMode::OnlyPropagateInto => {} + other @ ConstPropMode::FullConstProp => { trace!( "local {:?} can't be propagated because of multiple assignments", local, ); - *other = ConstPropMode::NoPropagation; + *other = ConstPropMode::OnlyPropagateInto; } } } @@ -847,35 +857,35 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { if let Ok(place_layout) = self.tcx.layout_of(self.param_env.and(place_ty)) { let can_const_prop = self.can_const_prop[place.local]; if let Some(()) = self.const_prop(rval, place_layout, source_info, place) { - if can_const_prop != ConstPropMode::NoPropagation { - // This will return None for variables that are from other blocks, - // so it should be okay to propagate from here on down. - if let Some(value) = self.get_const(place) { - if self.should_const_prop(value) { - trace!("replacing {:?} with {:?}", rval, value); - self.replace_with_const(rval, value, source_info); - if can_const_prop == ConstPropMode::FullConstProp - || can_const_prop == ConstPropMode::OnlyInsideOwnBlock - { - trace!("propagated into {:?}", place); - } - } - if can_const_prop == ConstPropMode::OnlyInsideOwnBlock { - trace!( - "found local restricted to its block. Will remove it from const-prop after block is finished. Local: {:?}", - place.local - ); - self.locals_of_current_block.insert(place.local); + // This will return None for variables that are from other blocks, + // so it should be okay to propagate from here on down. + if let Some(value) = self.get_const(place) { + if self.should_const_prop(value) { + trace!("replacing {:?} with {:?}", rval, value); + self.replace_with_const(rval, value, source_info); + if can_const_prop == ConstPropMode::FullConstProp + || can_const_prop == ConstPropMode::OnlyInsideOwnBlock + { + trace!("propagated into {:?}", place); } } } - if can_const_prop == ConstPropMode::OnlyPropagateInto - || can_const_prop == ConstPropMode::NoPropagation - { - trace!("can't propagate into {:?}", place); - if place.local != RETURN_PLACE { - Self::remove_const(&mut self.ecx, place.local); + match can_const_prop { + ConstPropMode::OnlyInsideOwnBlock => { + trace!( + "found local restricted to its block. \ + Will remove it from const-prop after block is finished. Local: {:?}", + place.local + ); + self.locals_of_current_block.insert(place.local); + } + ConstPropMode::OnlyPropagateInto | ConstPropMode::NoPropagation => { + trace!("can't propagate into {:?}", place); + if place.local != RETURN_PLACE { + Self::remove_const(&mut self.ecx, place.local); + } } + ConstPropMode::FullConstProp => {} } } else { // Const prop failed, so erase the destination, ensuring that whatever happens @@ -895,6 +905,12 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { ); Self::remove_const(&mut self.ecx, place.local); } + } else { + trace!( + "cannot propagate into {:?}, because the type of the local is generic.", + place, + ); + Self::remove_const(&mut self.ecx, place.local); } } else { match statement.kind { diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index c8702eeae1d5b..59be8dc224dee 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -64,7 +64,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::lang_items::{GeneratorStateLangItem, PinTypeLangItem}; use rustc_index::bit_set::{BitMatrix, BitSet}; use rustc_index::vec::{Idx, IndexVec}; -use rustc_middle::mir::visit::{MutVisitor, PlaceContext}; +use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::GeneratorSubsts; @@ -72,7 +72,7 @@ use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt}; use rustc_target::abi::VariantIdx; use rustc_target::spec::PanicStrategy; use std::borrow::Cow; -use std::iter; +use std::{iter, ops}; pub struct StateTransform; @@ -417,11 +417,7 @@ fn replace_local<'tcx>( struct LivenessInfo { /// Which locals are live across any suspension point. - /// - /// GeneratorSavedLocal is indexed in terms of the elements in this set; - /// i.e. GeneratorSavedLocal::new(1) corresponds to the second local - /// included in this set. - live_locals: BitSet, + saved_locals: GeneratorSavedLocals, /// The set of saved locals live at each suspension point. live_locals_at_suspension_points: Vec>, @@ -524,49 +520,75 @@ fn locals_live_across_suspend_points( live_locals_at_suspension_points.push(live_locals); } } + debug!("live_locals_anywhere = {:?}", live_locals_at_any_suspension_point); + let saved_locals = GeneratorSavedLocals(live_locals_at_any_suspension_point); // Renumber our liveness_map bitsets to include only the locals we are // saving. let live_locals_at_suspension_points = live_locals_at_suspension_points .iter() - .map(|live_here| renumber_bitset(&live_here, &live_locals_at_any_suspension_point)) + .map(|live_here| saved_locals.renumber_bitset(&live_here)) .collect(); let storage_conflicts = compute_storage_conflicts( body_ref, - &live_locals_at_any_suspension_point, + &saved_locals, always_live_locals.clone(), requires_storage_results, ); LivenessInfo { - live_locals: live_locals_at_any_suspension_point, + saved_locals, live_locals_at_suspension_points, storage_conflicts, storage_liveness: storage_liveness_map, } } -/// Renumbers the items present in `stored_locals` and applies the renumbering -/// to 'input`. +/// The set of `Local`s that must be saved across yield points. /// -/// For example, if `stored_locals = [1, 3, 5]`, this would be renumbered to -/// `[0, 1, 2]`. Thus, if `input = [3, 5]` we would return `[1, 2]`. -fn renumber_bitset( - input: &BitSet, - stored_locals: &BitSet, -) -> BitSet { - assert!(stored_locals.superset(&input), "{:?} not a superset of {:?}", stored_locals, input); - let mut out = BitSet::new_empty(stored_locals.count()); - for (idx, local) in stored_locals.iter().enumerate() { - let saved_local = GeneratorSavedLocal::from(idx); - if input.contains(local) { - out.insert(saved_local); +/// `GeneratorSavedLocal` is indexed in terms of the elements in this set; +/// i.e. `GeneratorSavedLocal::new(1)` corresponds to the second local +/// included in this set. +struct GeneratorSavedLocals(BitSet); + +impl GeneratorSavedLocals { + /// Returns an iterator over each `GeneratorSavedLocal` along with the `Local` it corresponds + /// to. + fn iter_enumerated(&self) -> impl '_ + Iterator { + self.iter().enumerate().map(|(i, l)| (GeneratorSavedLocal::from(i), l)) + } + + /// Transforms a `BitSet` that contains only locals saved across yield points to the + /// equivalent `BitSet`. + fn renumber_bitset(&self, input: &BitSet) -> BitSet { + assert!(self.superset(&input), "{:?} not a superset of {:?}", self.0, input); + let mut out = BitSet::new_empty(self.count()); + for (saved_local, local) in self.iter_enumerated() { + if input.contains(local) { + out.insert(saved_local); + } } + out + } + + fn get(&self, local: Local) -> Option { + if !self.contains(local) { + return None; + } + + let idx = self.iter().take_while(|&l| l < local).count(); + Some(GeneratorSavedLocal::new(idx)) + } +} + +impl ops::Deref for GeneratorSavedLocals { + type Target = BitSet; + + fn deref(&self) -> &Self::Target { + &self.0 } - debug!("renumber_bitset({:?}, {:?}) => {:?}", input, stored_locals, out); - out } /// For every saved local, looks for which locals are StorageLive at the same @@ -575,11 +597,11 @@ fn renumber_bitset( /// computation; see `GeneratorLayout` for more. fn compute_storage_conflicts( body: &'mir Body<'tcx>, - stored_locals: &BitSet, + saved_locals: &GeneratorSavedLocals, always_live_locals: storage::AlwaysLiveLocals, requires_storage: dataflow::Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>, ) -> BitMatrix { - assert_eq!(body.local_decls.len(), stored_locals.domain_size()); + assert_eq!(body.local_decls.len(), saved_locals.domain_size()); debug!("compute_storage_conflicts({:?})", body.span); debug!("always_live = {:?}", always_live_locals); @@ -587,12 +609,12 @@ fn compute_storage_conflicts( // Locals that are always live or ones that need to be stored across // suspension points are not eligible for overlap. let mut ineligible_locals = always_live_locals.into_inner(); - ineligible_locals.intersect(stored_locals); + ineligible_locals.intersect(saved_locals); // Compute the storage conflicts for all eligible locals. let mut visitor = StorageConflictVisitor { body, - stored_locals: &stored_locals, + saved_locals: &saved_locals, local_conflicts: BitMatrix::from_row_n(&ineligible_locals, body.local_decls.len()), }; @@ -609,16 +631,14 @@ fn compute_storage_conflicts( // However, in practice these bitsets are not usually large. The layout code // also needs to keep track of how many conflicts each local has, so it's // simpler to keep it this way for now. - let mut storage_conflicts = BitMatrix::new(stored_locals.count(), stored_locals.count()); - for (idx_a, local_a) in stored_locals.iter().enumerate() { - let saved_local_a = GeneratorSavedLocal::new(idx_a); + let mut storage_conflicts = BitMatrix::new(saved_locals.count(), saved_locals.count()); + for (saved_local_a, local_a) in saved_locals.iter_enumerated() { if ineligible_locals.contains(local_a) { // Conflicts with everything. storage_conflicts.insert_all_into_row(saved_local_a); } else { // Keep overlap information only for stored locals. - for (idx_b, local_b) in stored_locals.iter().enumerate() { - let saved_local_b = GeneratorSavedLocal::new(idx_b); + for (saved_local_b, local_b) in saved_locals.iter_enumerated() { if local_conflicts.contains(local_a, local_b) { storage_conflicts.insert(saved_local_a, saved_local_b); } @@ -630,7 +650,7 @@ fn compute_storage_conflicts( struct StorageConflictVisitor<'mir, 'tcx, 's> { body: &'mir Body<'tcx>, - stored_locals: &'s BitSet, + saved_locals: &'s GeneratorSavedLocals, // FIXME(tmandry): Consider using sparse bitsets here once we have good // benchmarks for generators. local_conflicts: BitMatrix, @@ -666,7 +686,7 @@ impl<'body, 'tcx, 's> StorageConflictVisitor<'body, 'tcx, 's> { } let mut eligible_storage_live = flow_state.clone(); - eligible_storage_live.intersect(&self.stored_locals); + eligible_storage_live.intersect(&self.saved_locals); for local in eligible_storage_live.iter() { self.local_conflicts.union_row_with(&eligible_storage_live, local); @@ -678,7 +698,7 @@ impl<'body, 'tcx, 's> StorageConflictVisitor<'body, 'tcx, 's> { } } -/// Validates the typeck view of the generator against the actual set of types retained between +/// Validates the typeck view of the generator against the actual set of types saved between /// yield points. fn sanitize_witness<'tcx>( tcx: TyCtxt<'tcx>, @@ -686,7 +706,7 @@ fn sanitize_witness<'tcx>( did: DefId, witness: Ty<'tcx>, upvars: &Vec>, - retained: &BitSet, + saved_locals: &GeneratorSavedLocals, ) { let allowed_upvars = tcx.erase_regions(upvars); let allowed = match witness.kind { @@ -703,8 +723,8 @@ fn sanitize_witness<'tcx>( let param_env = tcx.param_env(did); for (local, decl) in body.local_decls.iter_enumerated() { - // Ignore locals which are internal or not retained between yields. - if !retained.contains(local) || decl.internal { + // Ignore locals which are internal or not saved between yields. + if !saved_locals.contains(local) || decl.internal { continue; } let decl_ty = tcx.normalize_erasing_regions(param_env, decl.ty); @@ -724,35 +744,27 @@ fn sanitize_witness<'tcx>( } fn compute_layout<'tcx>( - tcx: TyCtxt<'tcx>, - source: MirSource<'tcx>, - upvars: &Vec>, - interior: Ty<'tcx>, - always_live_locals: &storage::AlwaysLiveLocals, - movable: bool, + liveness: LivenessInfo, body: &mut Body<'tcx>, ) -> ( FxHashMap, VariantIdx, usize)>, GeneratorLayout<'tcx>, IndexVec>>, ) { - // Use a liveness analysis to compute locals which are live across a suspension point let LivenessInfo { - live_locals, + saved_locals, live_locals_at_suspension_points, storage_conflicts, storage_liveness, - } = locals_live_across_suspend_points(tcx, body, source, always_live_locals, movable); - - sanitize_witness(tcx, body, source.def_id(), interior, upvars, &live_locals); + } = liveness; // Gather live local types and their indices. let mut locals = IndexVec::::new(); let mut tys = IndexVec::::new(); - for (idx, local) in live_locals.iter().enumerate() { + for (saved_local, local) in saved_locals.iter_enumerated() { locals.push(local); tys.push(body.local_decls[local].ty); - debug!("generator saved local {:?} => {:?}", GeneratorSavedLocal::from(idx), local); + debug!("generator saved local {:?} => {:?}", saved_local, local); } // Leave empty variants for the UNRESUMED, RETURNED, and POISONED states. @@ -1260,11 +1272,25 @@ impl<'tcx> MirPass<'tcx> for StateTransform { let always_live_locals = storage::AlwaysLiveLocals::new(&body); + let liveness_info = + locals_live_across_suspend_points(tcx, body, source, &always_live_locals, movable); + + sanitize_witness(tcx, body, def_id, interior, &upvars, &liveness_info.saved_locals); + + if tcx.sess.opts.debugging_opts.validate_mir { + let mut vis = EnsureGeneratorFieldAssignmentsNeverAlias { + assigned_local: None, + saved_locals: &liveness_info.saved_locals, + storage_conflicts: &liveness_info.storage_conflicts, + }; + + vis.visit_body(body); + } + // Extract locals which are live across suspension point into `layout` // `remap` gives a mapping from local indices onto generator struct indices // `storage_liveness` tells us which locals have live storage at suspension points - let (remap, layout, storage_liveness) = - compute_layout(tcx, source, &upvars, interior, &always_live_locals, movable, body); + let (remap, layout, storage_liveness) = compute_layout(liveness_info, body); let can_return = can_return(tcx, body); @@ -1315,3 +1341,134 @@ impl<'tcx> MirPass<'tcx> for StateTransform { create_generator_resume_function(tcx, transform, source, body, can_return); } } + +/// Looks for any assignments between locals (e.g., `_4 = _5`) that will both be converted to fields +/// in the generator state machine but whose storage is not marked as conflicting +/// +/// Validation needs to happen immediately *before* `TransformVisitor` is invoked, not after. +/// +/// This condition would arise when the assignment is the last use of `_5` but the initial +/// definition of `_4` if we weren't extra careful to mark all locals used inside a statement as +/// conflicting. Non-conflicting generator saved locals may be stored at the same location within +/// the generator state machine, which would result in ill-formed MIR: the left-hand and right-hand +/// sides of an assignment may not alias. This caused a miscompilation in [#73137]. +/// +/// [#73137]: https://github.com/rust-lang/rust/issues/73137 +struct EnsureGeneratorFieldAssignmentsNeverAlias<'a> { + saved_locals: &'a GeneratorSavedLocals, + storage_conflicts: &'a BitMatrix, + assigned_local: Option, +} + +impl EnsureGeneratorFieldAssignmentsNeverAlias<'_> { + fn saved_local_for_direct_place(&self, place: Place<'_>) -> Option { + if place.is_indirect() { + return None; + } + + self.saved_locals.get(place.local) + } + + fn check_assigned_place(&mut self, place: Place<'tcx>, f: impl FnOnce(&mut Self)) { + if let Some(assigned_local) = self.saved_local_for_direct_place(place) { + assert!(self.assigned_local.is_none(), "`check_assigned_place` must not recurse"); + + self.assigned_local = Some(assigned_local); + f(self); + self.assigned_local = None; + } + } +} + +impl Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> { + fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) { + let lhs = match self.assigned_local { + Some(l) => l, + None => { + // This visitor only invokes `visit_place` for the right-hand side of an assignment + // and only after setting `self.assigned_local`. However, the default impl of + // `Visitor::super_body` may call `visit_place` with a `NonUseContext` for places + // with debuginfo. Ignore them here. + assert!(!context.is_use()); + return; + } + }; + + let rhs = match self.saved_local_for_direct_place(*place) { + Some(l) => l, + None => return, + }; + + if !self.storage_conflicts.contains(lhs, rhs) { + bug!( + "Assignment between generator saved locals whose storage is not \ + marked as conflicting: {:?}: {:?} = {:?}", + location, + lhs, + rhs, + ); + } + } + + fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { + match &statement.kind { + StatementKind::Assign(box (lhs, rhs)) => { + self.check_assigned_place(*lhs, |this| this.visit_rvalue(rhs, location)); + } + + // FIXME: Does `llvm_asm!` have any aliasing requirements? + StatementKind::LlvmInlineAsm(_) => {} + + StatementKind::FakeRead(..) + | StatementKind::SetDiscriminant { .. } + | StatementKind::StorageLive(_) + | StatementKind::StorageDead(_) + | StatementKind::Retag(..) + | StatementKind::AscribeUserType(..) + | StatementKind::Nop => {} + } + } + + fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { + // Checking for aliasing in terminators is probably overkill, but until we have actual + // semantics, we should be conservative here. + match &terminator.kind { + TerminatorKind::Call { + func, + args, + destination: Some((dest, _)), + cleanup: _, + from_hir_call: _, + fn_span: _, + } => { + self.check_assigned_place(*dest, |this| { + this.visit_operand(func, location); + for arg in args { + this.visit_operand(arg, location); + } + }); + } + + TerminatorKind::Yield { value, resume: _, resume_arg, drop: _ } => { + self.check_assigned_place(*resume_arg, |this| this.visit_operand(value, location)); + } + + // FIXME: Does `asm!` have any aliasing requirements? + TerminatorKind::InlineAsm { .. } => {} + + TerminatorKind::Call { .. } + | TerminatorKind::Goto { .. } + | TerminatorKind::SwitchInt { .. } + | TerminatorKind::Resume + | TerminatorKind::Abort + | TerminatorKind::Return + | TerminatorKind::Unreachable + | TerminatorKind::Drop { .. } + | TerminatorKind::DropAndReplace { .. } + | TerminatorKind::Assert { .. } + | TerminatorKind::GeneratorDrop + | TerminatorKind::FalseEdge { .. } + | TerminatorKind::FalseUnwind { .. } => {} + } + } +} diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index db909494aed6b..068d055fa78f8 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -9,7 +9,6 @@ use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::subst::{Subst, SubstsRef}; use rustc_middle::ty::{self, ConstKind, Instance, InstanceDef, ParamEnv, Ty, TyCtxt}; -use rustc_session::config::Sanitizer; use rustc_target::spec::abi::Abi; use super::simplify::{remove_dead_blocks, CfgSimplifier}; @@ -232,24 +231,8 @@ impl Inliner<'tcx> { // Avoid inlining functions marked as no_sanitize if sanitizer is enabled, // since instrumentation might be enabled and performed on the caller. - match self.tcx.sess.opts.debugging_opts.sanitizer { - Some(Sanitizer::Address) => { - if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_SANITIZE_ADDRESS) { - return false; - } - } - Some(Sanitizer::Memory) => { - if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_SANITIZE_MEMORY) { - return false; - } - } - Some(Sanitizer::Thread) => { - if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_SANITIZE_THREAD) { - return false; - } - } - Some(Sanitizer::Leak) => {} - None => {} + if self.tcx.sess.opts.debugging_opts.sanitizer.intersects(codegen_fn_attrs.no_sanitize) { + return false; } let hinted = match codegen_fn_attrs.inline { diff --git a/src/librustc_mir/transform/instrument_coverage.rs b/src/librustc_mir/transform/instrument_coverage.rs index c36614938e10f..06b648ab5a908 100644 --- a/src/librustc_mir/transform/instrument_coverage.rs +++ b/src/librustc_mir/transform/instrument_coverage.rs @@ -1,10 +1,19 @@ use crate::transform::{MirPass, MirSource}; use crate::util::patch::MirPatch; +use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::lang_items; -use rustc_middle::mir::interpret::Scalar; -use rustc_middle::mir::*; +use rustc_middle::hir; +use rustc_middle::ich::StableHashingContext; +use rustc_middle::mir::interpret::{ConstValue, Scalar}; +use rustc_middle::mir::{ + self, traversal, BasicBlock, BasicBlockData, CoverageData, Operand, Place, SourceInfo, + StatementKind, Terminator, TerminatorKind, START_BLOCK, +}; use rustc_middle::ty; +use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{ConstKind, FnDef}; use rustc_span::def_id::DefId; use rustc_span::Span; @@ -12,64 +21,139 @@ use rustc_span::Span; /// the intrinsic llvm.instrprof.increment. pub struct InstrumentCoverage; +/// The `query` provider for `CoverageData`, requested by `codegen_intrinsic_call()` when +/// constructing the arguments for `llvm.instrprof.increment`. +pub(crate) fn provide(providers: &mut Providers<'_>) { + providers.coverage_data = |tcx, def_id| { + let mir_body = tcx.optimized_mir(def_id); + // FIXME(richkadel): The current implementation assumes the MIR for the given DefId + // represents a single function. Validate and/or correct if inlining and/or monomorphization + // invalidates these assumptions. + let count_code_region_fn = + tcx.require_lang_item(lang_items::CountCodeRegionFnLangItem, None); + let mut num_counters: u32 = 0; + // The `num_counters` argument to `llvm.instrprof.increment` is the number of injected + // counters, with each counter having an index from `0..num_counters-1`. MIR optimization + // may split and duplicate some BasicBlock sequences. Simply counting the calls may not + // not work; but computing the num_counters by adding `1` to the highest index (for a given + // instrumented function) is valid. + for (_, data) in traversal::preorder(mir_body) { + if let Some(terminator) = &data.terminator { + if let TerminatorKind::Call { func: Operand::Constant(func), args, .. } = + &terminator.kind + { + if let FnDef(called_fn_def_id, _) = func.literal.ty.kind { + if called_fn_def_id == count_code_region_fn { + if let Operand::Constant(constant) = + args.get(0).expect("count_code_region has at least one arg") + { + if let ConstKind::Value(ConstValue::Scalar(value)) = + constant.literal.val + { + let index = value + .to_u32() + .expect("count_code_region index at arg0 is u32"); + num_counters = std::cmp::max(num_counters, index + 1); + } + } + } + } + } + } + } + let hash = if num_counters > 0 { hash_mir_source(tcx, def_id) } else { 0 }; + CoverageData { num_counters, hash } + }; +} + +struct Instrumentor<'tcx> { + tcx: TyCtxt<'tcx>, + num_counters: u32, +} + impl<'tcx> MirPass<'tcx> for InstrumentCoverage { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, mir_body: &mut mir::Body<'tcx>) { if tcx.sess.opts.debugging_opts.instrument_coverage { - debug!("instrumenting {:?}", src.def_id()); - instrument_coverage(tcx, body); + // If the InstrumentCoverage pass is called on promoted MIRs, skip them. + // See: https://github.com/rust-lang/rust/pull/73011#discussion_r438317601 + if src.promoted.is_none() { + debug!( + "instrumenting {:?}, span: {}", + src.def_id(), + tcx.sess.source_map().span_to_string(mir_body.span) + ); + Instrumentor::new(tcx).inject_counters(mir_body); + } } } } -// The first counter (start of the function) is index zero. -const INIT_FUNCTION_COUNTER: u32 = 0; - -/// Injects calls to placeholder function `count_code_region()`. -// FIXME(richkadel): As a first step, counters are only injected at the top of each function. -// The complete solution will inject counters at each conditional code branch. -pub fn instrument_coverage<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let span = body.span.shrink_to_lo(); - - let count_code_region_fn = function_handle( - tcx, - tcx.require_lang_item(lang_items::CountCodeRegionFnLangItem, None), - span, - ); - let counter_index = Operand::const_from_scalar( - tcx, - tcx.types.u32, - Scalar::from_u32(INIT_FUNCTION_COUNTER), - span, - ); - - let mut patch = MirPatch::new(body); - - let new_block = patch.new_block(placeholder_block(SourceInfo::outermost(body.span))); - let next_block = START_BLOCK; - - let temp = patch.new_temp(tcx.mk_unit(), body.span); - patch.patch_terminator( - new_block, - TerminatorKind::Call { - func: count_code_region_fn, - args: vec![counter_index], - // new_block will swapped with the next_block, after applying patch - destination: Some((Place::from(temp), new_block)), - cleanup: None, - from_hir_call: false, - fn_span: span, - }, - ); - - patch.add_statement(new_block.start_location(), StatementKind::StorageLive(temp)); - patch.add_statement(next_block.start_location(), StatementKind::StorageDead(temp)); - - patch.apply(body); - - // To insert the `new_block` in front of the first block in the counted branch (for example, - // the START_BLOCK, at the top of the function), just swap the indexes, leaving the rest of the - // graph unchanged. - body.basic_blocks_mut().swap(next_block, new_block); +impl<'tcx> Instrumentor<'tcx> { + fn new(tcx: TyCtxt<'tcx>) -> Self { + Self { tcx, num_counters: 0 } + } + + fn next_counter(&mut self) -> u32 { + let next = self.num_counters; + self.num_counters += 1; + next + } + + fn inject_counters(&mut self, mir_body: &mut mir::Body<'tcx>) { + // FIXME(richkadel): As a first step, counters are only injected at the top of each + // function. The complete solution will inject counters at each conditional code branch. + let top_of_function = START_BLOCK; + let entire_function = mir_body.span; + + self.inject_counter(mir_body, top_of_function, entire_function); + } + + fn inject_counter( + &mut self, + mir_body: &mut mir::Body<'tcx>, + next_block: BasicBlock, + code_region: Span, + ) { + let injection_point = code_region.shrink_to_lo(); + + let count_code_region_fn = function_handle( + self.tcx, + self.tcx.require_lang_item(lang_items::CountCodeRegionFnLangItem, None), + injection_point, + ); + let counter_index = Operand::const_from_scalar( + self.tcx, + self.tcx.types.u32, + Scalar::from_u32(self.next_counter()), + injection_point, + ); + + let mut patch = MirPatch::new(mir_body); + + let temp = patch.new_temp(self.tcx.mk_unit(), code_region); + let new_block = patch.new_block(placeholder_block(code_region)); + patch.patch_terminator( + new_block, + TerminatorKind::Call { + func: count_code_region_fn, + args: vec![counter_index], + // new_block will swapped with the next_block, after applying patch + destination: Some((Place::from(temp), new_block)), + cleanup: None, + from_hir_call: false, + fn_span: injection_point, + }, + ); + + patch.add_statement(new_block.start_location(), StatementKind::StorageLive(temp)); + patch.add_statement(next_block.start_location(), StatementKind::StorageDead(temp)); + + patch.apply(mir_body); + + // To insert the `new_block` in front of the first block in the counted branch (the + // `next_block`), just swap the indexes, leaving the rest of the graph unchanged. + mir_body.basic_blocks_mut().swap(next_block, new_block); + } } fn function_handle<'tcx>(tcx: TyCtxt<'tcx>, fn_def_id: DefId, span: Span) -> Operand<'tcx> { @@ -79,14 +163,31 @@ fn function_handle<'tcx>(tcx: TyCtxt<'tcx>, fn_def_id: DefId, span: Span) -> Ope Operand::function_handle(tcx, fn_def_id, substs, span) } -fn placeholder_block<'tcx>(source_info: SourceInfo) -> BasicBlockData<'tcx> { +fn placeholder_block(span: Span) -> BasicBlockData<'tcx> { BasicBlockData { statements: vec![], terminator: Some(Terminator { - source_info, + source_info: SourceInfo::outermost(span), // this gets overwritten by the counter Call kind: TerminatorKind::Unreachable, }), is_cleanup: false, } } + +fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> u64 { + let hir_node = tcx.hir().get_if_local(def_id).expect("DefId is local"); + let fn_body_id = hir::map::associated_body(hir_node).expect("HIR node is a function with body"); + let hir_body = tcx.hir().body(fn_body_id); + let mut hcx = tcx.create_no_span_stable_hashing_context(); + hash(&mut hcx, &hir_body.value).to_smaller_hash() +} + +fn hash( + hcx: &mut StableHashingContext<'tcx>, + node: &impl HashStable>, +) -> Fingerprint { + let mut stable_hasher = StableHasher::new(); + node.hash_stable(hcx, &mut stable_hasher); + stable_hasher.finish() +} diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 846ed1f86d8d6..8ca240d2c7da7 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -56,6 +56,7 @@ pub(crate) fn provide(providers: &mut Providers<'_>) { promoted_mir, ..*providers }; + instrument_coverage::provide(providers); } fn is_mir_available(tcx: TyCtxt<'_>, def_id: DefId) -> bool { diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 330f6c1640ff4..8bcbcd79ae60b 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -341,7 +341,7 @@ impl<'tcx> Validator<'_, 'tcx> { Place::ty_from(place.local, proj_base, self.body, self.tcx) .projection_ty(self.tcx, elem) .ty; - if ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) { + if ty.is_freeze(self.tcx.at(DUMMY_SP), self.param_env) { has_mut_interior = false; break; } @@ -678,7 +678,7 @@ impl<'tcx> Validator<'_, 'tcx> { let ty = Place::ty_from(place.local, proj_base, self.body, self.tcx) .projection_ty(self.tcx, elem) .ty; - if ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) { + if ty.is_freeze(self.tcx.at(DUMMY_SP), self.param_env) { has_mut_interior = false; break; } diff --git a/src/librustc_mir/transform/validate.rs b/src/librustc_mir/transform/validate.rs index 8150c328316cb..c5343d9b5d014 100644 --- a/src/librustc_mir/transform/validate.rs +++ b/src/librustc_mir/transform/validate.rs @@ -9,7 +9,6 @@ use rustc_middle::{ }, ty::{self, ParamEnv, TyCtxt}, }; -use rustc_span::def_id::DefId; #[derive(Copy, Clone, Debug)] enum EdgeKind { @@ -24,15 +23,14 @@ pub struct Validator { impl<'tcx> MirPass<'tcx> for Validator { fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { - let def_id = source.def_id(); - let param_env = tcx.param_env(def_id); - TypeChecker { when: &self.when, def_id, body, tcx, param_env }.visit_body(body); + let param_env = tcx.param_env(source.def_id()); + TypeChecker { when: &self.when, source, body, tcx, param_env }.visit_body(body); } } struct TypeChecker<'a, 'tcx> { when: &'a str, - def_id: DefId, + source: MirSource<'tcx>, body: &'a Body<'tcx>, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, @@ -47,7 +45,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { span, &format!( "broken MIR in {:?} ({}) at {:?}:\n{}", - self.def_id, + self.source.instance, self.when, location, msg.as_ref() @@ -92,7 +90,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { let ty = place.ty(&self.body.local_decls, self.tcx).ty; let span = self.body.source_info(location).span; - if !ty.is_copy_modulo_regions(self.tcx, self.param_env, span) { + if !ty.is_copy_modulo_regions(self.tcx.at(span), self.param_env) { self.fail(location, format!("`Operand::Copy` with non-`Copy` type {}", ty)); } } @@ -123,7 +121,17 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { TerminatorKind::Goto { target } => { self.check_edge(location, *target, EdgeKind::Normal); } - TerminatorKind::SwitchInt { targets, values, .. } => { + TerminatorKind::SwitchInt { targets, values, switch_ty, discr } => { + let ty = discr.ty(&self.body.local_decls, self.tcx); + if ty != *switch_ty { + self.fail( + location, + format!( + "encountered `SwitchInt` terminator with type mismatch: {:?} != {:?}", + ty, switch_ty, + ), + ); + } if targets.len() != values.len() + 1 { self.fail( location, diff --git a/src/librustc_mir_build/build/expr/as_operand.rs b/src/librustc_mir_build/build/expr/as_operand.rs index 9a75f3afe8f08..5949fd1e22ce8 100644 --- a/src/librustc_mir_build/build/expr/as_operand.rs +++ b/src/librustc_mir_build/build/expr/as_operand.rs @@ -172,7 +172,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if !ty.is_sized(tcx.at(span), param_env) { // !sized means !copy, so this is an unsized move - assert!(!ty.is_copy_modulo_regions(tcx, param_env, span)); + assert!(!ty.is_copy_modulo_regions(tcx.at(span), param_env)); // As described above, detect the case where we are passing a value of unsized // type, and that value is coming from the deref of a box. diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index 4a4de6c420bd8..6ac5d41ec6135 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -800,7 +800,11 @@ impl<'tcx> Constructor<'tcx> { assert!(!adt.is_enum()); VariantIdx::new(0) } - ConstantValue(c) => cx.tcx.destructure_const(cx.param_env.and(c)).variant, + ConstantValue(c) => cx + .tcx + .destructure_const(cx.param_env.and(c)) + .variant + .expect("destructed const of adt without variant id"), _ => bug!("bad constructor {:?} for adt {:?}", self, adt), } } diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs index 4d97a19f4086b..6fc447a87f57a 100644 --- a/src/librustc_mir_build/hair/pattern/check_match.rs +++ b/src/librustc_mir_build/hair/pattern/check_match.rs @@ -579,7 +579,7 @@ fn maybe_point_at_variant(ty: Ty<'_>, patterns: &[super::Pat<'_>]) -> Vec /// Check if a by-value binding is by-value. That is, check if the binding's type is not `Copy`. fn is_binding_by_move(cx: &MatchVisitor<'_, '_>, hir_id: HirId, span: Span) -> bool { - !cx.tables.node_type(hir_id).is_copy_modulo_regions(cx.tcx, cx.param_env, span) + !cx.tables.node_type(hir_id).is_copy_modulo_regions(cx.tcx.at(span), cx.param_env) } /// Check the legality of legality of by-move bindings. 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 1aed8e844b60b..6dd7e0871b45e 100644 --- a/src/librustc_mir_build/hair/pattern/const_to_pat.rs +++ b/src/librustc_mir_build/hair/pattern/const_to_pat.rs @@ -275,7 +275,9 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { PatKind::Variant { adt_def, substs, - variant_index: destructured.variant, + variant_index: destructured + .variant + .expect("destructed const of adt without variant id"), subpatterns: field_pats(destructured.fields), } } diff --git a/src/librustc_parse/lexer/mod.rs b/src/librustc_parse/lexer/mod.rs index 2e3cf4e746ae9..8e74c3847bc90 100644 --- a/src/librustc_parse/lexer/mod.rs +++ b/src/librustc_parse/lexer/mod.rs @@ -353,8 +353,15 @@ impl<'a> StringReader<'a> { } rustc_lexer::LiteralKind::Str { terminated } => { if !terminated { - self.fatal_span_(start, suffix_start, "unterminated double quote string") - .raise() + self.sess + .span_diagnostic + .struct_span_fatal_with_code( + self.mk_sp(start, suffix_start), + "unterminated double quote string", + error_code!(E0765), + ) + .emit(); + FatalError.raise(); } (token::Str, Mode::Str, 1, 1) // " " } diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 47ae92c48bd88..7811d5fb741b2 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -1151,7 +1151,7 @@ impl<'a> Parser<'a> { /// This restriction shouldn't be an issue in practice, /// since this function is used to record the tokens for /// a parsed AST item, which always has matching delimiters. - fn collect_tokens( + pub fn collect_tokens( &mut self, f: impl FnOnce(&mut Self) -> PResult<'a, R>, ) -> PResult<'a, (R, TokenStream)> { diff --git a/src/librustc_parse_format/lib.rs b/src/librustc_parse_format/lib.rs index 23bf7b35419db..a5b5a1090cbfd 100644 --- a/src/librustc_parse_format/lib.rs +++ b/src/librustc_parse_format/lib.rs @@ -178,7 +178,7 @@ pub struct Parser<'a> { /// Error messages accumulated during parsing pub errors: Vec, /// Current position of implicit positional argument pointer - curarg: usize, + pub curarg: usize, /// `Some(raw count)` when the string is "raw", used to position spans correctly style: Option, /// Start and end byte offset of every successfully parsed argument @@ -243,11 +243,13 @@ impl<'a> Iterator for Parser<'a> { _ => Some(String(self.string(pos))), } } else { - if self.is_literal && self.cur_line_start != self.input.len() { + if self.is_literal { let start = self.to_span_index(self.cur_line_start); let end = self.to_span_index(self.input.len()); - self.line_spans.push(start.to(end)); - self.cur_line_start = self.input.len(); + let span = start.to(end); + if self.line_spans.last() != Some(&span) { + self.line_spans.push(span); + } } None } diff --git a/src/librustc_passes/intrinsicck.rs b/src/librustc_passes/intrinsicck.rs index 88fb78f85e423..c8666ba1fd078 100644 --- a/src/librustc_passes/intrinsicck.rs +++ b/src/librustc_passes/intrinsicck.rs @@ -214,7 +214,7 @@ impl ExprVisitor<'tcx> { // Check that the type implements Copy. The only case where this can // possibly fail is for SIMD types which don't #[derive(Copy)]. - if !ty.is_copy_modulo_regions(self.tcx, self.param_env, DUMMY_SP) { + if !ty.is_copy_modulo_regions(self.tcx.at(DUMMY_SP), self.param_env) { let msg = "arguments for inline assembly must be copyable"; let mut err = self.tcx.sess.struct_span_err(expr.span, msg); err.note(&format!("`{}` does not implement the Copy trait", ty)); diff --git a/src/librustc_query_system/lib.rs b/src/librustc_query_system/lib.rs index 12450a4ccd3eb..3afc4565933e5 100644 --- a/src/librustc_query_system/lib.rs +++ b/src/librustc_query_system/lib.rs @@ -6,7 +6,6 @@ #![feature(hash_raw_entry)] #![feature(min_specialization)] #![feature(stmt_expr_attributes)] -#![feature(vec_remove_item)] #[macro_use] extern crate log; diff --git a/src/librustc_query_system/query/job.rs b/src/librustc_query_system/query/job.rs index 5150b278a7722..190312bb33001 100644 --- a/src/librustc_query_system/query/job.rs +++ b/src/librustc_query_system/query/job.rs @@ -452,7 +452,9 @@ fn remove_cycle( // Remove the queries in our cycle from the list of jobs to look at for r in &stack { - jobs.remove_item(&r.1); + if let Some(pos) = jobs.iter().position(|j| j == &r.1) { + jobs.remove(pos); + } } // Find the queries in the cycle which are diff --git a/src/librustc_resolve/Cargo.toml b/src/librustc_resolve/Cargo.toml index fa5c557b5d9c6..6f6104c3d6932 100644 --- a/src/librustc_resolve/Cargo.toml +++ b/src/librustc_resolve/Cargo.toml @@ -24,6 +24,7 @@ rustc_errors = { path = "../librustc_errors" } rustc_expand = { path = "../librustc_expand" } rustc_feature = { path = "../librustc_feature" } rustc_hir = { path = "../librustc_hir" } +rustc_index = { path = "../librustc_index" } 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 8432e34a5271c..ef43f597eab47 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -19,6 +19,7 @@ use rustc_ast::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, use rustc_ast::ast::{AssocItem, AssocItemKind, MetaItemKind, StmtKind}; use rustc_ast::token::{self, Token}; use rustc_ast::visit::{self, AssocCtxt, Visitor}; +use rustc_ast_lowering::Resolver as ResolverAstLowering; use rustc_attr as attr; use rustc_data_structures::sync::Lrc; use rustc_errors::{struct_span_err, Applicability}; @@ -171,7 +172,7 @@ impl<'a> Resolver<'a> { fragment: &AstFragment, parent_scope: ParentScope<'a>, ) -> MacroRulesScope<'a> { - collect_definitions(&mut self.definitions, fragment, parent_scope.expansion); + collect_definitions(self, fragment, parent_scope.expansion); let mut visitor = BuildReducedGraphVisitor { r: self, parent_scope }; fragment.visit_with(&mut visitor); visitor.parent_scope.macro_rules @@ -647,9 +648,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } else if orig_name == Some(kw::SelfLower) { self.r.graph_root } else { - let def_id = self.r.definitions.local_def_id(item.id); + let def_id = self.r.local_def_id(item.id); let crate_id = - self.r.crate_loader.process_extern_crate(item, &self.r.definitions); + self.r.crate_loader.process_extern_crate(item, &self.r.definitions, def_id); self.r.extern_crate_map.insert(def_id, crate_id); self.r.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }) }; @@ -704,7 +705,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { ItemKind::Mod(..) if ident.name == kw::Invalid => {} // Crate root ItemKind::Mod(..) => { - let def_id = self.r.definitions.local_def_id(item.id); + let def_id = self.r.local_def_id(item.id); let module_kind = ModuleKind::Def(DefKind::Mod, def_id.to_def_id(), ident.name); let module = self.r.arenas.alloc_module(ModuleData { no_implicit_prelude: parent.no_implicit_prelude || { @@ -727,18 +728,15 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { // These items live in the value namespace. ItemKind::Static(..) => { - let res = - Res::Def(DefKind::Static, self.r.definitions.local_def_id(item.id).to_def_id()); + let res = Res::Def(DefKind::Static, self.r.local_def_id(item.id).to_def_id()); self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion)); } ItemKind::Const(..) => { - let res = - Res::Def(DefKind::Const, self.r.definitions.local_def_id(item.id).to_def_id()); + let res = Res::Def(DefKind::Const, self.r.local_def_id(item.id).to_def_id()); self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion)); } ItemKind::Fn(..) => { - let res = - Res::Def(DefKind::Fn, self.r.definitions.local_def_id(item.id).to_def_id()); + let res = Res::Def(DefKind::Fn, self.r.local_def_id(item.id).to_def_id()); self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion)); // Functions introducing procedural macros reserve a slot @@ -748,15 +746,12 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { // These items live in the type namespace. ItemKind::TyAlias(..) => { - let res = Res::Def( - DefKind::TyAlias, - self.r.definitions.local_def_id(item.id).to_def_id(), - ); + let res = Res::Def(DefKind::TyAlias, self.r.local_def_id(item.id).to_def_id()); self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion)); } ItemKind::Enum(_, _) => { - let def_id = self.r.definitions.local_def_id(item.id).to_def_id(); + let def_id = self.r.local_def_id(item.id).to_def_id(); self.r.variant_vis.insert(def_id, vis); let module_kind = ModuleKind::Def(DefKind::Enum, def_id, ident.name); let module = self.r.new_module( @@ -771,17 +766,14 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } ItemKind::TraitAlias(..) => { - let res = Res::Def( - DefKind::TraitAlias, - self.r.definitions.local_def_id(item.id).to_def_id(), - ); + let res = Res::Def(DefKind::TraitAlias, self.r.local_def_id(item.id).to_def_id()); self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion)); } // These items live in both the type and value namespaces. ItemKind::Struct(ref vdata, _) => { // Define a name in the type namespace. - let def_id = self.r.definitions.local_def_id(item.id).to_def_id(); + let def_id = self.r.local_def_id(item.id).to_def_id(); let res = Res::Def(DefKind::Struct, def_id); self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion)); @@ -814,7 +806,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } let ctor_res = Res::Def( DefKind::Ctor(CtorOf::Struct, CtorKind::from_ast(vdata)), - self.r.definitions.local_def_id(ctor_node_id).to_def_id(), + self.r.local_def_id(ctor_node_id).to_def_id(), ); self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, sp, expansion)); self.r.struct_constructors.insert(def_id, (ctor_res, ctor_vis)); @@ -822,7 +814,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } ItemKind::Union(ref vdata, _) => { - let def_id = self.r.definitions.local_def_id(item.id).to_def_id(); + let def_id = self.r.local_def_id(item.id).to_def_id(); let res = Res::Def(DefKind::Union, def_id); self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion)); @@ -831,7 +823,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } ItemKind::Trait(..) => { - let def_id = self.r.definitions.local_def_id(item.id).to_def_id(); + let def_id = self.r.local_def_id(item.id).to_def_id(); // Add all the items within to a new module. let module_kind = ModuleKind::Def(DefKind::Trait, def_id, ident.name); @@ -856,18 +848,15 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { /// Constructs the reduced graph for one foreign item. fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem) { let (res, ns) = match item.kind { - ForeignItemKind::Fn(..) => ( - Res::Def(DefKind::Fn, self.r.definitions.local_def_id(item.id).to_def_id()), - ValueNS, - ), - ForeignItemKind::Static(..) => ( - Res::Def(DefKind::Static, self.r.definitions.local_def_id(item.id).to_def_id()), - ValueNS, - ), - ForeignItemKind::TyAlias(..) => ( - Res::Def(DefKind::ForeignTy, self.r.definitions.local_def_id(item.id).to_def_id()), - TypeNS, - ), + ForeignItemKind::Fn(..) => { + (Res::Def(DefKind::Fn, self.r.local_def_id(item.id).to_def_id()), ValueNS) + } + ForeignItemKind::Static(..) => { + (Res::Def(DefKind::Static, self.r.local_def_id(item.id).to_def_id()), ValueNS) + } + ForeignItemKind::TyAlias(..) => { + (Res::Def(DefKind::ForeignTy, self.r.local_def_id(item.id).to_def_id()), TypeNS) + } ForeignItemKind::MacCall(_) => unreachable!(), }; let parent = self.parent_scope.module; @@ -1170,7 +1159,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScope<'a> { let parent_scope = self.parent_scope; let expansion = parent_scope.expansion; - let def_id = self.r.definitions.local_def_id(item.id); + let def_id = self.r.local_def_id(item.id); 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())); @@ -1315,7 +1304,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { } // Add the item to the trait info. - let item_def_id = self.r.definitions.local_def_id(item.id).to_def_id(); + let item_def_id = self.r.local_def_id(item.id).to_def_id(); let (res, ns) = match item.kind { AssocItemKind::Const(..) => (Res::Def(DefKind::AssocConst, item_def_id), ValueNS), AssocItemKind::Fn(_, ref sig, _, _) => { @@ -1417,7 +1406,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { let ident = variant.ident; // Define a name in the type namespace. - let def_id = self.r.definitions.local_def_id(variant.id).to_def_id(); + let def_id = self.r.local_def_id(variant.id).to_def_id(); let res = Res::Def(DefKind::Variant, def_id); self.r.define(parent, ident, TypeNS, (res, vis, variant.span, expn_id)); @@ -1435,7 +1424,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { // It's ok to use the variant's id as a ctor id since an // error will be reported on any use of such resolution anyway. let ctor_node_id = variant.data.ctor_id().unwrap_or(variant.id); - let ctor_def_id = self.r.definitions.local_def_id(ctor_node_id).to_def_id(); + let ctor_def_id = self.r.local_def_id(ctor_node_id).to_def_id(); let ctor_kind = CtorKind::from_ast(&variant.data); let ctor_res = Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id); self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, variant.span, expn_id)); diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index cc0e97aeb1430..0ca01a384e73e 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -29,6 +29,7 @@ use crate::Resolver; use rustc_ast::ast; use rustc_ast::node_id::NodeMap; use rustc_ast::visit::{self, Visitor}; +use rustc_ast_lowering::Resolver as ResolverAstLowering; use rustc_data_structures::fx::FxHashSet; use rustc_errors::pluralize; use rustc_middle::ty; @@ -64,7 +65,7 @@ impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> { fn check_import(&mut self, id: ast::NodeId) { let mut used = false; self.r.per_ns(|this, ns| used |= this.used_imports.contains(&(id, ns))); - let def_id = self.r.definitions.local_def_id(id); + let def_id = self.r.local_def_id(id); if !used { if self.r.maybe_unused_trait_imports.contains(&def_id) { // Check later. @@ -246,7 +247,7 @@ impl Resolver<'_> { } } ImportKind::ExternCrate { .. } => { - let def_id = self.definitions.local_def_id(import.id); + let def_id = self.local_def_id(import.id); self.maybe_unused_extern_crates.push((def_id, import.span)); } ImportKind::MacroUse => { diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs index 71cedb208fcf2..f1063f42c91ec 100644 --- a/src/librustc_resolve/def_collector.rs +++ b/src/librustc_resolve/def_collector.rs @@ -1,8 +1,10 @@ +use crate::Resolver; use log::debug; use rustc_ast::ast::*; use rustc_ast::token::{self, Token}; use rustc_ast::visit::{self, FnKind}; use rustc_ast::walk_list; +use rustc_ast_lowering::Resolver as ResolverAstLowering; use rustc_expand::expand::AstFragment; use rustc_hir::def_id::LocalDefId; use rustc_hir::definitions::*; @@ -11,26 +13,26 @@ use rustc_span::symbol::{kw, sym}; use rustc_span::Span; crate fn collect_definitions( - definitions: &mut Definitions, + resolver: &mut Resolver<'_>, fragment: &AstFragment, expansion: ExpnId, ) { - let parent_def = definitions.invocation_parent(expansion); - fragment.visit_with(&mut DefCollector { definitions, parent_def, expansion }); + let parent_def = resolver.invocation_parents[&expansion]; + fragment.visit_with(&mut DefCollector { resolver, parent_def, expansion }); } /// Creates `DefId`s for nodes in the AST. -struct DefCollector<'a> { - definitions: &'a mut Definitions, +struct DefCollector<'a, 'b> { + resolver: &'a mut Resolver<'b>, parent_def: LocalDefId, expansion: ExpnId, } -impl<'a> DefCollector<'a> { +impl<'a, 'b> DefCollector<'a, 'b> { 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) + self.resolver.create_def(parent_def, node_id, data, self.expansion, span) } fn with_parent(&mut self, parent_def: LocalDefId, f: F) { @@ -43,12 +45,13 @@ impl<'a> DefCollector<'a> { let index = |this: &Self| { index.unwrap_or_else(|| { let node_id = NodeId::placeholder_from_expn_id(this.expansion); - this.definitions.placeholder_field_index(node_id) + this.resolver.placeholder_field_indices[&node_id] }) }; if field.is_placeholder { - self.definitions.set_placeholder_field_index(field.id, index(self)); + let old_index = self.resolver.placeholder_field_indices.insert(field.id, index(self)); + assert!(old_index.is_none(), "placeholder field index is reset for a node ID"); self.visit_macro_invoc(field.id); } else { let name = field.ident.map_or_else(|| sym::integer(index(self)), |ident| ident.name); @@ -58,11 +61,13 @@ impl<'a> DefCollector<'a> { } fn visit_macro_invoc(&mut self, id: NodeId) { - self.definitions.set_invocation_parent(id.placeholder_to_expn_id(), self.parent_def); + let old_parent = + self.resolver.invocation_parents.insert(id.placeholder_to_expn_id(), self.parent_def); + assert!(old_parent.is_none(), "parent `LocalDefId` is reset for an invocation"); } } -impl<'a> visit::Visitor<'a> for DefCollector<'a> { +impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> { fn visit_item(&mut self, i: &'a Item) { debug!("visit_item: {:?}", i); diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index bd2ce5a72e8d9..afe96ca700781 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -49,6 +49,7 @@ crate struct ImportSuggestion { pub did: Option, pub descr: &'static str, pub path: Path, + pub accessible: bool, } /// Adjust the impl span so that just the `impl` keyword is taken by removing @@ -107,7 +108,7 @@ impl<'a> Resolver<'a> { match outer_res { Res::SelfTy(maybe_trait_defid, maybe_impl_defid) => { if let Some(impl_span) = - maybe_impl_defid.and_then(|def_id| self.definitions.opt_span(def_id)) + maybe_impl_defid.and_then(|def_id| self.opt_span(def_id)) { err.span_label( reduce_impl_span_to_impl_keyword(sm, impl_span), @@ -126,12 +127,12 @@ impl<'a> Resolver<'a> { return err; } Res::Def(DefKind::TyParam, def_id) => { - if let Some(span) = self.definitions.opt_span(def_id) { + if let Some(span) = self.opt_span(def_id) { err.span_label(span, "type parameter from outer function"); } } Res::Def(DefKind::ConstParam, def_id) => { - if let Some(span) = self.definitions.opt_span(def_id) { + if let Some(span) = self.opt_span(def_id) { err.span_label(span, "const parameter from outer function"); } } @@ -640,9 +641,11 @@ impl<'a> Resolver<'a> { let mut candidates = Vec::new(); let mut seen_modules = FxHashSet::default(); let not_local_module = crate_name.name != kw::Crate; - let mut worklist = vec![(start_module, Vec::::new(), not_local_module)]; + let mut worklist = + vec![(start_module, Vec::::new(), true, not_local_module)]; - while let Some((in_module, path_segments, in_module_is_extern)) = worklist.pop() { + while let Some((in_module, path_segments, accessible, in_module_is_extern)) = worklist.pop() + { // We have to visit module children in deterministic order to avoid // instabilities in reported imports (#43552). in_module.for_each_child(self, |this, ident, ns, name_binding| { @@ -650,11 +653,20 @@ impl<'a> Resolver<'a> { if name_binding.is_import() && !name_binding.is_extern_crate() { return; } + // avoid non-importable candidates as well if !name_binding.is_importable() { return; } + let child_accessible = + accessible && this.is_accessible_from(name_binding.vis, parent_scope.module); + + // do not venture inside inaccessible items of other crates + if in_module_is_extern && !child_accessible { + return; + } + // collect results based on the filter function // avoid suggesting anything from the same module in which we are resolving if ident.name == lookup_ident.name @@ -673,22 +685,29 @@ impl<'a> Resolver<'a> { segms.push(ast::PathSegment::from_ident(ident)); let path = Path { span: name_binding.span, segments: segms }; - // the entity is accessible in the following cases: - // 1. if it's defined in the same crate, it's always - // accessible (since private entities can be made public) - // 2. if it's defined in another crate, it's accessible - // only if both the module is public and the entity is - // declared as public (due to pruning, we don't explore - // outside crate private modules => no need to check this) - if !in_module_is_extern || name_binding.vis == ty::Visibility::Public { - let did = match res { - Res::Def(DefKind::Ctor(..), did) => this.parent(did), - _ => res.opt_def_id(), - }; - if candidates.iter().all(|v: &ImportSuggestion| v.did != did) { - candidates.push(ImportSuggestion { did, descr: res.descr(), path }); + let did = match res { + Res::Def(DefKind::Ctor(..), did) => this.parent(did), + _ => res.opt_def_id(), + }; + + if child_accessible { + // Remove invisible match if exists + if let Some(idx) = candidates + .iter() + .position(|v: &ImportSuggestion| v.did == did && !v.accessible) + { + candidates.remove(idx); } } + + if candidates.iter().all(|v: &ImportSuggestion| v.did != did) { + candidates.push(ImportSuggestion { + did, + descr: res.descr(), + path, + accessible: child_accessible, + }); + } } } @@ -701,20 +720,22 @@ impl<'a> Resolver<'a> { let is_extern_crate_that_also_appears_in_prelude = name_binding.is_extern_crate() && lookup_ident.span.rust_2018(); - let is_visible_to_user = - !in_module_is_extern || name_binding.vis == ty::Visibility::Public; - - if !is_extern_crate_that_also_appears_in_prelude && is_visible_to_user { - // add the module to the lookup + if !is_extern_crate_that_also_appears_in_prelude { let is_extern = in_module_is_extern || name_binding.is_extern_crate(); + // add the module to the lookup if seen_modules.insert(module.def_id().unwrap()) { - worklist.push((module, path_segments, is_extern)); + worklist.push((module, path_segments, child_accessible, is_extern)); } } } }) } + // If only some candidates are accessible, take just them + if !candidates.iter().all(|v: &ImportSuggestion| !v.accessible) { + candidates = candidates.into_iter().filter(|x| x.accessible).collect(); + } + candidates } @@ -825,7 +846,7 @@ impl<'a> Resolver<'a> { Applicability::MaybeIncorrect, ); let def_span = suggestion.res.opt_def_id().and_then(|def_id| match def_id.krate { - LOCAL_CRATE => self.definitions.opt_span(def_id), + LOCAL_CRATE => self.opt_span(def_id), _ => Some( self.session .source_map() diff --git a/src/librustc_resolve/imports.rs b/src/librustc_resolve/imports.rs index 74a8b7e2f556d..8a6541b399e38 100644 --- a/src/librustc_resolve/imports.rs +++ b/src/librustc_resolve/imports.rs @@ -12,6 +12,7 @@ use crate::{NameBinding, NameBindingKind, PathResult, PrivacyError, ToNameBindin use rustc_ast::ast::NodeId; use rustc_ast::unwrap_or; use rustc_ast::util::lev_distance::find_best_match_for_name; +use rustc_ast_lowering::Resolver as ResolverAstLowering; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::ptr_key::PtrKey; use rustc_errors::{pluralize, struct_span_err, Applicability}; @@ -1393,7 +1394,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let is_good_import = binding.is_import() && !binding.is_ambiguity() && !ident.span.from_expansion(); if is_good_import || binding.is_macro_def() { - let res = binding.res().map_id(|id| this.definitions.local_def_id(id)); + let res = binding.res().map_id(|id| this.local_def_id(id)); if res != def::Res::Err { reexports.push(Export { ident, res, span: binding.span, vis: binding.vis }); } diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 7166fef2d1395..6f769c3c59cae 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -16,6 +16,7 @@ use rustc_ast::ptr::P; use rustc_ast::util::lev_distance::find_best_match_for_name; use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; use rustc_ast::{unwrap_or, walk_list}; +use rustc_ast_lowering::Resolver as ResolverAstLowering; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::DiagnosticId; use rustc_hir::def::Namespace::{self, *}; @@ -24,6 +25,7 @@ use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_hir::TraitCandidate; use rustc_middle::{bug, span_bug}; use rustc_session::lint; +use rustc_span::def_id::LocalDefId; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use smallvec::{smallvec, SmallVec}; @@ -706,7 +708,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } fn with_scope(&mut self, id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T { - let id = self.r.definitions.local_def_id(id); + let id = self.r.local_def_id(id); let module = self.r.module_map.get(&id).cloned(); // clones a reference if let Some(module) = module { // Move down in the graph. @@ -758,7 +760,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { debug!("resolve_adt"); self.with_current_self_item(item, |this| { this.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { - let item_def_id = this.r.definitions.local_def_id(item.id).to_def_id(); + let item_def_id = this.r.local_def_id(item.id).to_def_id(); this.with_self_rib(Res::SelfTy(None, Some(item_def_id)), |this| { visit::walk_item(this, item); }); @@ -838,7 +840,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ItemKind::Trait(.., ref generics, ref bounds, ref trait_items) => { // Create a new rib for the trait-wide type parameters. self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { - let local_def_id = this.r.definitions.local_def_id(item.id).to_def_id(); + let local_def_id = this.r.local_def_id(item.id).to_def_id(); this.with_self_rib(Res::SelfTy(Some(local_def_id), None), |this| { this.visit_generics(generics); walk_list!(this, visit_param_bound, bounds); @@ -879,7 +881,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ItemKind::TraitAlias(ref generics, ref bounds) => { // Create a new rib for the trait-wide type parameters. self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { - let local_def_id = this.r.definitions.local_def_id(item.id).to_def_id(); + let local_def_id = this.r.local_def_id(item.id).to_def_id(); this.with_self_rib(Res::SelfTy(Some(local_def_id), None), |this| { this.visit_generics(generics); walk_list!(this, visit_param_bound, bounds); @@ -960,7 +962,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { seen_bindings.entry(ident).or_insert(param.ident.span); // Plain insert (no renaming). - let res = Res::Def(def_kind, self.r.definitions.local_def_id(param.id).to_def_id()); + let res = Res::Def(def_kind, self.r.local_def_id(param.id).to_def_id()); match param.kind { GenericParamKind::Type { .. } => { @@ -1110,7 +1112,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { this.with_self_rib(Res::SelfTy(None, None), |this| { // Resolve the trait reference, if necessary. this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| { - let item_def_id = this.r.definitions.local_def_id(item_id).to_def_id(); + let item_def_id = this.r.local_def_id(item_id).to_def_id(); this.with_self_rib(Res::SelfTy(trait_id, Some(item_def_id)), |this| { if let Some(trait_ref) = opt_trait_reference.as_ref() { // Resolve type arguments in the trait path. @@ -2001,7 +2003,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { if let StmtKind::Item(ref item) = stmt.kind { if let ItemKind::MacroDef(..) = item.kind { num_macro_definition_ribs += 1; - let res = self.r.definitions.local_def_id(item.id).to_def_id(); + let res = self.r.local_def_id(item.id).to_def_id(); self.ribs[ValueNS].push(Rib::new(MacroDefinition(res))); self.label_ribs.push(Rib::new(MacroDefinition(res))); } @@ -2188,7 +2190,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { &mut self, mut ident: Ident, ns: Namespace, - ) -> Vec> { + ) -> Vec { debug!("(getting traits containing item) looking for '{}'", ident.name); let mut found_traits = Vec::new(); @@ -2233,7 +2235,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ident: Ident, ns: Namespace, module: Module<'a>, - found_traits: &mut Vec>, + found_traits: &mut Vec, ) { assert!(ns == TypeNS || ns == ValueNS); let mut traits = module.traits.borrow_mut(); @@ -2292,13 +2294,13 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { &mut self, mut kind: &NameBindingKind<'_>, trait_name: Ident, - ) -> SmallVec<[NodeId; 1]> { + ) -> SmallVec<[LocalDefId; 1]> { let mut import_ids = smallvec![]; while let NameBindingKind::Import { import, binding, .. } = kind { - let id = self.r.definitions.local_def_id(import.id); + let id = self.r.local_def_id(import.id); self.r.maybe_unused_trait_imports.insert(id); self.r.add_to_glob_map(&import, trait_name); - import_ids.push(import.id); + import_ids.push(id); kind = &binding.kind; } import_ids diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index 05ef0aa0bb689..1bce160acb610 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -512,7 +512,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { _ => {} } if !suggested { - if let Some(span) = self.r.definitions.opt_span(def_id) { + if let Some(span) = self.r.opt_span(def_id) { err.span_label(span, &format!("`{}` defined here", path_str)); } err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?", path_str)); @@ -536,7 +536,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { if nightly_options::is_nightly_build() { let msg = "you might have meant to use `#![feature(trait_alias)]` instead of a \ `type` alias"; - if let Some(span) = self.r.definitions.opt_span(def_id) { + if let Some(span) = self.r.opt_span(def_id) { err.span_help(span, msg); } else { err.help(msg); @@ -593,7 +593,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { bad_struct_syntax_suggestion(def_id); } (Res::Def(DefKind::Ctor(_, CtorKind::Fn), def_id), _) if ns == ValueNS => { - if let Some(span) = self.r.definitions.opt_span(def_id) { + if let Some(span) = self.r.opt_span(def_id) { err.span_label(span, &format!("`{}` defined here", path_str)); } err.span_label(span, format!("did you mean `{}( /* fields */ )`?", path_str)); @@ -887,7 +887,12 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { let path = Path { span: name_binding.span, segments: path_segments }; result = Some(( module, - ImportSuggestion { did: Some(def_id), descr: "module", path }, + ImportSuggestion { + did: Some(def_id), + descr: "module", + path, + accessible: true, + }, )); } else { // add the module to the lookup diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs index 5bbf8703f0b60..903eee672cf1f 100644 --- a/src/librustc_resolve/late/lifetimes.rs +++ b/src/librustc_resolve/late/lifetimes.rs @@ -883,7 +883,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }) .collect(); if !lifetimes.is_empty() { - self.trait_ref_hack = true; let next_early_index = self.next_early_index(); let scope = Scope::Binder { lifetimes, @@ -895,9 +894,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let result = self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &bound_generic_params); this.visit_ty(&bounded_ty); + this.trait_ref_hack = true; walk_list!(this, visit_param_bound, bounds); + this.trait_ref_hack = false; }); - self.trait_ref_hack = false; result } else { self.visit_ty(&bounded_ty); @@ -932,13 +932,15 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref); let should_pop_missing_lt = self.is_trait_ref_fn_scope(trait_ref); - if !self.trait_ref_hack + + let trait_ref_hack = take(&mut self.trait_ref_hack); + if !trait_ref_hack || trait_ref.bound_generic_params.iter().any(|param| match param.kind { GenericParamKind::Lifetime { .. } => true, _ => false, }) { - if self.trait_ref_hack { + if trait_ref_hack { struct_span_err!( self.tcx.sess, trait_ref.span, @@ -968,10 +970,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { this.check_lifetime_params(old_scope, &trait_ref.bound_generic_params); walk_list!(this, visit_generic_param, trait_ref.bound_generic_params); this.visit_trait_ref(&trait_ref.trait_ref); - }) + }); } else { self.visit_trait_ref(&trait_ref.trait_ref); } + self.trait_ref_hack = trait_ref_hack; if should_pop_missing_lt { self.missing_named_lifetime_spots.pop(); } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index cca9eabe7bcf8..ce068b8ac69a4 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -27,6 +27,7 @@ use rustc_ast::attr; use rustc_ast::node_id::NodeMap; use rustc_ast::unwrap_or; use rustc_ast::visit::{self, Visitor}; +use rustc_ast_lowering::Resolver as ResolverAstLowering; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::ptr_key::PtrKey; @@ -36,9 +37,10 @@ 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, LocalDefId, CRATE_DEF_INDEX}; -use rustc_hir::definitions::{DefKey, Definitions}; +use rustc_hir::definitions::{DefKey, DefPathData, Definitions}; use rustc_hir::PrimTy::{self, Bool, Char, Float, Int, Str, Uint}; -use rustc_hir::TraitMap; +use rustc_hir::TraitCandidate; +use rustc_index::vec::IndexVec; use rustc_metadata::creader::{CStore, CrateLoader}; use rustc_middle::hir::exports::ExportMap; use rustc_middle::middle::cstore::{CrateStore, MetadataLoaderDyn}; @@ -256,31 +258,21 @@ impl<'a> From<&'a ast::PathSegment> for Segment { } } -struct UsePlacementFinder<'d> { - definitions: &'d Definitions, - target_module: LocalDefId, +struct UsePlacementFinder { + target_module: NodeId, span: Option, found_use: bool, } -impl<'d> UsePlacementFinder<'d> { - fn check( - definitions: &'d Definitions, - krate: &Crate, - target_module: DefId, - ) -> (Option, bool) { - if let Some(target_module) = target_module.as_local() { - let mut finder = - UsePlacementFinder { definitions, target_module, span: None, found_use: false }; - visit::walk_crate(&mut finder, krate); - (finder.span, finder.found_use) - } else { - (None, false) - } +impl UsePlacementFinder { + fn check(krate: &Crate, target_module: NodeId) -> (Option, bool) { + let mut finder = UsePlacementFinder { target_module, span: None, found_use: false }; + visit::walk_crate(&mut finder, krate); + (finder.span, finder.found_use) } } -impl<'tcx, 'd> Visitor<'tcx> for UsePlacementFinder<'d> { +impl<'tcx> Visitor<'tcx> for UsePlacementFinder { fn visit_mod( &mut self, module: &'tcx ast::Mod, @@ -291,7 +283,7 @@ impl<'tcx, 'd> Visitor<'tcx> for UsePlacementFinder<'d> { if self.span.is_some() { return; } - if self.definitions.local_def_id(node_id) != self.target_module { + if node_id != self.target_module { visit::walk_mod(self, module); return; } @@ -881,7 +873,7 @@ pub struct Resolver<'a> { /// `CrateNum` resolutions of `extern crate` items. extern_crate_map: FxHashMap, export_map: ExportMap, - trait_map: TraitMap, + trait_map: NodeMap>, /// A map from nodes to anonymous modules. /// Anonymous modules are pseudo-modules that are implicitly created around items @@ -979,6 +971,19 @@ pub struct Resolver<'a> { lint_buffer: LintBuffer, next_node_id: NodeId, + + def_id_to_span: IndexVec, + + node_id_to_def_id: FxHashMap, + def_id_to_node_id: IndexVec, + + /// Indices of unnamed struct or variant fields with unresolved attributes. + placeholder_field_indices: FxHashMap, + /// 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, + + next_disambiguator: FxHashMap<(LocalDefId, DefPathData), u32>, } /// Nothing really interesting here; it just provides memory for the rest of the crate. @@ -1042,7 +1047,7 @@ impl<'a, 'b> DefIdTree for &'a Resolver<'b> { /// This interface is used through the AST→HIR step, to embed full paths into the HIR. After that /// the resolver is no longer needed as all the relevant information is inline. -impl rustc_ast_lowering::Resolver for Resolver<'_> { +impl ResolverAstLowering for Resolver<'_> { fn def_key(&mut self, id: DefId) -> DefKey { if let Some(id) = id.as_local() { self.definitions().def_key(id) @@ -1109,6 +1114,60 @@ impl rustc_ast_lowering::Resolver for Resolver<'_> { fn next_node_id(&mut self) -> NodeId { self.next_node_id() } + + fn trait_map(&self) -> &NodeMap> { + &self.trait_map + } + + fn opt_local_def_id(&self, node: NodeId) -> Option { + self.node_id_to_def_id.get(&node).copied() + } + + fn local_def_id(&self, node: NodeId) -> LocalDefId { + self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{:?}`", node)) + } + + /// Adds a definition with a parent definition. + fn create_def( + &mut self, + parent: LocalDefId, + node_id: ast::NodeId, + data: DefPathData, + expn_id: ExpnId, + span: Span, + ) -> LocalDefId { + assert!( + !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.definitions.def_key(self.node_id_to_def_id[&node_id]), + ); + + // Find the next free disambiguator for this key. + let next_disambiguator = &mut self.next_disambiguator; + let next_disambiguator = |parent, data| { + let next_disamb = next_disambiguator.entry((parent, data)).or_insert(0); + let disambiguator = *next_disamb; + *next_disamb = next_disamb.checked_add(1).expect("disambiguator overflow"); + disambiguator + }; + + let def_id = self.definitions.create_def(parent, data, expn_id, next_disambiguator); + + assert_eq!(self.def_id_to_span.push(span), def_id); + + // 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 `LocalDefId`. + if node_id != ast::DUMMY_NODE_ID { + debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id); + self.node_id_to_def_id.insert(node_id, def_id); + } + assert_eq!(self.def_id_to_node_id.push(node_id), def_id); + + def_id + } } impl<'a> Resolver<'a> { @@ -1139,8 +1198,18 @@ impl<'a> Resolver<'a> { let mut module_map = FxHashMap::default(); module_map.insert(LocalDefId { local_def_index: CRATE_DEF_INDEX }, graph_root); - let mut definitions = Definitions::default(); - definitions.create_root_def(crate_name, session.local_crate_disambiguator()); + let definitions = Definitions::new(crate_name, session.local_crate_disambiguator()); + let root = definitions.get_root_def(); + + let mut def_id_to_span = IndexVec::default(); + assert_eq!(def_id_to_span.push(rustc_span::DUMMY_SP), root); + let mut def_id_to_node_id = IndexVec::default(); + assert_eq!(def_id_to_node_id.push(CRATE_NODE_ID), root); + let mut node_id_to_def_id = FxHashMap::default(); + node_id_to_def_id.insert(CRATE_NODE_ID, root); + + let mut invocation_parents = FxHashMap::default(); + invocation_parents.insert(ExpnId::root(), root); let mut extern_prelude: FxHashMap> = session .opts @@ -1259,6 +1328,12 @@ impl<'a> Resolver<'a> { variant_vis: Default::default(), lint_buffer: LintBuffer::default(), next_node_id: NodeId::from_u32(1), + def_id_to_span, + node_id_to_def_id, + def_id_to_node_id, + placeholder_field_indices: Default::default(), + invocation_parents, + next_disambiguator: Default::default(), } } @@ -1284,18 +1359,6 @@ impl<'a> Resolver<'a> { let definitions = self.definitions; let extern_crate_map = self.extern_crate_map; let export_map = self.export_map; - let trait_map = self - .trait_map - .into_iter() - .map(|(k, v)| { - ( - definitions.node_id_to_hir_id(k), - v.into_iter() - .map(|tc| tc.map_import_ids(|id| definitions.node_id_to_hir_id(id))) - .collect(), - ) - }) - .collect(); let maybe_unused_trait_imports = self.maybe_unused_trait_imports; let maybe_unused_extern_crates = self.maybe_unused_extern_crates; let glob_map = self.glob_map; @@ -1304,7 +1367,6 @@ impl<'a> Resolver<'a> { cstore: Box::new(self.crate_loader.into_cstore()), extern_crate_map, export_map, - trait_map, glob_map, maybe_unused_trait_imports, maybe_unused_extern_crates, @@ -1322,21 +1384,6 @@ impl<'a> Resolver<'a> { cstore: Box::new(self.cstore().clone()), extern_crate_map: self.extern_crate_map.clone(), export_map: self.export_map.clone(), - trait_map: self - .trait_map - .iter() - .map(|(&k, v)| { - ( - self.definitions.node_id_to_hir_id(k), - v.iter() - .cloned() - .map(|tc| { - tc.map_import_ids(|id| self.definitions.node_id_to_hir_id(id)) - }) - .collect(), - ) - }) - .collect(), glob_map: self.glob_map.clone(), maybe_unused_trait_imports: self.maybe_unused_trait_imports.clone(), maybe_unused_extern_crates: self.maybe_unused_extern_crates.clone(), @@ -1481,7 +1528,7 @@ impl<'a> Resolver<'a> { #[inline] fn add_to_glob_map(&mut self, import: &Import<'_>, ident: Ident) { if import.is_glob() { - let def_id = self.definitions.local_def_id(import.id); + let def_id = self.local_def_id(import.id); self.glob_map.entry(def_id).or_default().insert(ident.name); } } @@ -2562,7 +2609,11 @@ impl<'a> Resolver<'a> { for UseError { mut err, candidates, def_id, instead, suggestion } in self.use_injections.drain(..) { - let (span, found_use) = UsePlacementFinder::check(&self.definitions, krate, def_id); + let (span, found_use) = if let Some(def_id) = def_id.as_local() { + UsePlacementFinder::check(krate, self.def_id_to_node_id[def_id]) + } else { + (None, false) + }; if !candidates.is_empty() { diagnostics::show_candidates(&mut err, span, &candidates, instead, found_use); } else if let Some((span, msg, sugg, appl)) = suggestion { @@ -2958,6 +3009,12 @@ impl<'a> Resolver<'a> { pub fn all_macros(&self) -> &FxHashMap { &self.all_macros } + + /// 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 let Some(def_id) = def_id.as_local() { Some(self.def_id_to_span[def_id]) } else { None } + } } fn names_to_string(names: &[Symbol]) -> String { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 1b49722355e54..398b0e92d9d8c 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -7,6 +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_ast::ast::{self, NodeId}; +use rustc_ast_lowering::Resolver as ResolverAstLowering; use rustc_ast_pretty::pprust; use rustc_attr::{self as attr, StabilityLevel}; use rustc_data_structures::fx::FxHashSet; @@ -190,7 +191,7 @@ impl<'a> base::Resolver for Resolver<'a> { ))); let parent_scope = if let Some(module_id) = parent_module_id { - let parent_def_id = self.definitions.local_def_id(module_id); + let parent_def_id = self.local_def_id(module_id); self.definitions.add_parent_module_of_macro_def(expn_id, parent_def_id.to_def_id()); self.module_map[&parent_def_id] } else { @@ -340,7 +341,9 @@ impl<'a> base::Resolver for Resolver<'a> { } fn lint_node_id(&mut self, expn_id: ExpnId) -> NodeId { - self.definitions.lint_node_id(expn_id) + self.invocation_parents + .get(&expn_id) + .map_or(ast::CRATE_NODE_ID, |id| self.def_id_to_node_id[*id]) } fn has_derive_copy(&self, expn_id: ExpnId) -> bool { diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index cae501e942b65..f5c3e84c62426 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -518,24 +518,13 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { } pub fn get_expr_data(&self, expr: &hir::Expr<'_>) -> Option { - let hir_node = self.tcx.hir().expect_expr(expr.hir_id); - let ty = self.tables.expr_ty_adjusted_opt(&hir_node); - if ty.is_none() || matches!(ty.unwrap().kind, ty::Error(_)) { + let ty = self.tables.expr_ty_adjusted_opt(expr)?; + if matches!(ty.kind, ty::Error(_)) { return None; } match expr.kind { hir::ExprKind::Field(ref sub_ex, ident) => { - let hir_node = match self.tcx.hir().find(sub_ex.hir_id) { - Some(Node::Expr(expr)) => expr, - _ => { - debug!( - "Missing or weird node for sub-expression {} in {:?}", - sub_ex.hir_id, expr - ); - return None; - } - }; - match self.tables.expr_ty_adjusted(&hir_node).kind { + match self.tables.expr_ty_adjusted(&sub_ex).kind { ty::Adt(def, _) if !def.is_enum() => { let variant = &def.non_enum_variant(); filter!(self.span_utils, ident.span); @@ -562,8 +551,8 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { hir::QPath::Resolved(_, path) => path.segments.last().unwrap(), hir::QPath::TypeRelative(_, segment) => segment, }; - match self.tables.expr_ty_adjusted(&hir_node).kind { - ty::Adt(def, _) if !def.is_enum() => { + match ty.kind { + ty::Adt(def, _) => { let sub_span = segment.ident.span; filter!(self.span_utils, sub_span); let span = self.span_from_span(sub_span); @@ -574,9 +563,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { })) } _ => { - // FIXME ty could legitimately be an enum, but then we will fail - // later if we try to look up the fields. - debug!("expected struct or union, found {:?}", ty); + debug!("expected adt, found {:?}", ty); None } } diff --git a/src/librustc_session/Cargo.toml b/src/librustc_session/Cargo.toml index 4d57c6384ddbd..abce7359c0ed7 100644 --- a/src/librustc_session/Cargo.toml +++ b/src/librustc_session/Cargo.toml @@ -9,6 +9,7 @@ name = "rustc_session" path = "lib.rs" [dependencies] +bitflags = "1.2.1" getopts = "0.2" log = "0.4" rustc_errors = { path = "../librustc_errors" } diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs index 411a6eecbba15..c5a866817cb4a 100644 --- a/src/librustc_session/config.rs +++ b/src/librustc_session/config.rs @@ -10,6 +10,7 @@ use crate::{early_error, early_warn, Session}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::impl_stable_hash_via_hash; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_target::spec::{Target, TargetTriple}; @@ -37,35 +38,55 @@ pub struct Config { pub ptr_width: u32, } -#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] -pub enum Sanitizer { - Address, - Leak, - Memory, - Thread, +bitflags! { + #[derive(Default, RustcEncodable, RustcDecodable)] + pub struct SanitizerSet: u8 { + const ADDRESS = 1 << 0; + const LEAK = 1 << 1; + const MEMORY = 1 << 2; + const THREAD = 1 << 3; + } } -impl fmt::Display for Sanitizer { +/// Formats a sanitizer set as a comma separated list of sanitizers' names. +impl fmt::Display for SanitizerSet { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - Sanitizer::Address => "address".fmt(f), - Sanitizer::Leak => "leak".fmt(f), - Sanitizer::Memory => "memory".fmt(f), - Sanitizer::Thread => "thread".fmt(f), + let mut first = true; + for s in *self { + let name = match s { + SanitizerSet::ADDRESS => "address", + SanitizerSet::LEAK => "leak", + SanitizerSet::MEMORY => "memory", + SanitizerSet::THREAD => "thread", + _ => panic!("unrecognized sanitizer {:?}", s), + }; + if !first { + f.write_str(",")?; + } + f.write_str(name)?; + first = false; } + Ok(()) } } -impl FromStr for Sanitizer { - type Err = (); - fn from_str(s: &str) -> Result { - match s { - "address" => Ok(Sanitizer::Address), - "leak" => Ok(Sanitizer::Leak), - "memory" => Ok(Sanitizer::Memory), - "thread" => Ok(Sanitizer::Thread), - _ => Err(()), - } +impl IntoIterator for SanitizerSet { + type Item = SanitizerSet; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + [SanitizerSet::ADDRESS, SanitizerSet::LEAK, SanitizerSet::MEMORY, SanitizerSet::THREAD] + .iter() + .copied() + .filter(|&s| self.contains(s)) + .collect::>() + .into_iter() + } +} + +impl HashStable for SanitizerSet { + fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + self.bits().hash_stable(ctx, hasher); } } @@ -82,7 +103,7 @@ pub enum Strip { Symbols, } -/// The different settings that the `-Z control_flow_guard` flag can have. +/// The different settings that the `-Z control-flow-guard` flag can have. #[derive(Clone, Copy, PartialEq, Hash, Debug)] pub enum CFGuard { /// Do not emit Control Flow Guard metadata or checks. @@ -726,10 +747,12 @@ pub fn default_configuration(sess: &Session) -> CrateConfig { } } } - if let Some(s) = &sess.opts.debugging_opts.sanitizer { + + for s in sess.opts.debugging_opts.sanitizer { let symbol = Symbol::intern(&s.to_string()); ret.insert((sym::sanitize, Some(symbol))); } + if sess.opts.debug_assertions { ret.insert((Symbol::intern("debug_assertions"), None)); } @@ -1826,6 +1849,7 @@ fn parse_pretty( } } }; + log::debug!("got unpretty option: {:?}", first); first } } @@ -1954,9 +1978,11 @@ impl PpMode { use PpMode::*; use PpSourceMode::*; match *self { - PpmSource(PpmNormal | PpmEveryBodyLoops | PpmIdentified) => false, + PpmSource(PpmNormal | PpmIdentified) => false, - PpmSource(PpmExpanded | PpmExpandedIdentified | PpmExpandedHygiene) + PpmSource( + PpmExpanded | PpmEveryBodyLoops | PpmExpandedIdentified | PpmExpandedHygiene, + ) | PpmHir(_) | PpmHirTree(_) | PpmMir @@ -1995,7 +2021,7 @@ impl PpMode { crate mod dep_tracking { use super::{ CFGuard, CrateType, DebugInfo, ErrorOutputType, LinkerPluginLto, LtoCli, OptLevel, - OutputTypes, Passes, Sanitizer, SourceFileHashAlgorithm, SwitchWithOptPath, + OutputTypes, Passes, SanitizerSet, SourceFileHashAlgorithm, SwitchWithOptPath, SymbolManglingVersion, }; use crate::lint; @@ -2069,8 +2095,7 @@ crate mod dep_tracking { impl_dep_tracking_hash_via_hash!(UnstableFeatures); impl_dep_tracking_hash_via_hash!(OutputTypes); impl_dep_tracking_hash_via_hash!(NativeLibKind); - impl_dep_tracking_hash_via_hash!(Sanitizer); - impl_dep_tracking_hash_via_hash!(Option); + impl_dep_tracking_hash_via_hash!(SanitizerSet); impl_dep_tracking_hash_via_hash!(CFGuard); impl_dep_tracking_hash_via_hash!(TargetTriple); impl_dep_tracking_hash_via_hash!(Edition); @@ -2085,7 +2110,6 @@ crate mod dep_tracking { impl_dep_tracking_hash_for_sortable_vec_of!((String, lint::Level)); impl_dep_tracking_hash_for_sortable_vec_of!((String, Option, NativeLibKind)); impl_dep_tracking_hash_for_sortable_vec_of!((String, u64)); - impl_dep_tracking_hash_for_sortable_vec_of!(Sanitizer); impl DepTrackingHash for (T1, T2) where diff --git a/src/librustc_session/lib.rs b/src/librustc_session/lib.rs index 80b693fe1ab60..be9d2e7be2777 100644 --- a/src/librustc_session/lib.rs +++ b/src/librustc_session/lib.rs @@ -1,6 +1,9 @@ #![feature(crate_visibility_modifier)] #![feature(or_patterns)] +#[macro_use] +extern crate bitflags; + pub mod cgu_reuse_tracker; pub mod utils; #[macro_use] diff --git a/src/librustc_session/lint.rs b/src/librustc_session/lint.rs index ffb4579309075..0dcbee08abea1 100644 --- a/src/librustc_session/lint.rs +++ b/src/librustc_session/lint.rs @@ -88,6 +88,8 @@ pub struct Lint { /// `Some` if this lint is feature gated, otherwise `None`. pub feature_gate: Option, + + pub crate_level_only: bool, } /// Extra information for a future incompatibility lint. @@ -111,6 +113,7 @@ impl Lint { report_in_external_macro: false, future_incompatible: None, feature_gate: None, + crate_level_only: false, } } @@ -336,6 +339,7 @@ macro_rules! declare_tool_lint { future_incompatible: None, is_plugin: true, feature_gate: None, + crate_level_only: false, }; ); } diff --git a/src/librustc_session/lint/builtin.rs b/src/librustc_session/lint/builtin.rs index 5a8f5c1b9fbca..5deee6eb48e6a 100644 --- a/src/librustc_session/lint/builtin.rs +++ b/src/librustc_session/lint/builtin.rs @@ -17,6 +17,7 @@ declare_lint! { reference: "issue #57571 ", edition: None, }; + crate_level_only } declare_lint! { @@ -75,7 +76,8 @@ declare_lint! { declare_lint! { pub UNUSED_CRATE_DEPENDENCIES, Allow, - "crate dependencies that are never used" + "crate dependencies that are never used", + crate_level_only } declare_lint! { @@ -166,7 +168,8 @@ declare_lint! { declare_lint! { pub UNKNOWN_CRATE_TYPES, Deny, - "unknown crate type found in `#[crate_type]` directive" + "unknown crate type found in `#[crate_type]` directive", + crate_level_only } declare_lint! { @@ -339,7 +342,8 @@ declare_lint! { declare_lint! { pub ELIDED_LIFETIMES_IN_PATHS, Allow, - "hidden lifetime parameters in types are deprecated" + "hidden lifetime parameters in types are deprecated", + crate_level_only } declare_lint! { @@ -459,6 +463,7 @@ declare_lint! { reference: "issue #52234 ", edition: None, }; + crate_level_only } declare_lint! { diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs index 2d231359057fd..973891eb84eda 100644 --- a/src/librustc_session/options.rs +++ b/src/librustc_session/options.rs @@ -248,10 +248,10 @@ macro_rules! options { pub const parse_passes: &str = "a space-separated list of passes, or `all`"; pub const parse_panic_strategy: &str = "either `unwind` or `abort`"; pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`"; - pub const parse_sanitizer: &str = "one of: `address`, `leak`, `memory` or `thread`"; - pub const parse_sanitizer_list: &str = "comma separated list of sanitizers"; + pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `leak`, `memory` or `thread`"; pub const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2"; - pub const parse_cfguard: &str = "either `disabled`, `nochecks`, or `checks`"; + pub const parse_cfguard: &str = + "either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`"; pub const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`"; pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavor::one_of(); pub const parse_optimization_fuel: &str = "crate=integer"; @@ -459,24 +459,15 @@ macro_rules! options { true } - fn parse_sanitizer(slot: &mut Option, v: Option<&str>) -> bool { - if let Some(Ok(s)) = v.map(str::parse) { - *slot = Some(s); - true - } else { - false - } - } - - fn parse_sanitizer_list(slot: &mut Vec, v: Option<&str>) -> bool { + fn parse_sanitizers(slot: &mut SanitizerSet, v: Option<&str>) -> bool { if let Some(v) = v { - for s in v.split(',').map(str::parse) { - if let Ok(s) = s { - if !slot.contains(&s) { - slot.push(s); - } - } else { - return false; + for s in v.split(',') { + *slot |= match s { + "address" => SanitizerSet::ADDRESS, + "leak" => SanitizerSet::LEAK, + "memory" => SanitizerSet::MEMORY, + "thread" => SanitizerSet::THREAD, + _ => return false, } } true @@ -505,12 +496,24 @@ macro_rules! options { } fn parse_cfguard(slot: &mut CFGuard, v: Option<&str>) -> bool { - match v { - Some("disabled") => *slot = CFGuard::Disabled, - Some("nochecks") => *slot = CFGuard::NoChecks, - Some("checks") => *slot = CFGuard::Checks, - _ => return false, + if v.is_some() { + let mut bool_arg = None; + if parse_opt_bool(&mut bool_arg, v) { + *slot = if bool_arg.unwrap() { + CFGuard::Checks + } else { + CFGuard::Disabled + }; + return true + } } + + *slot = match v { + None => CFGuard::Checks, + Some("checks") => CFGuard::Checks, + Some("nochecks") => CFGuard::NoChecks, + Some(_) => return false, + }; true } @@ -806,8 +809,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "enable the experimental Chalk-based trait solving engine"), codegen_backend: Option = (None, parse_opt_string, [TRACKED], "the backend to use"), - control_flow_guard: CFGuard = (CFGuard::Disabled, parse_cfguard, [UNTRACKED], - "use Windows Control Flow Guard (`disabled`, `nochecks` or `checks`)"), + control_flow_guard: CFGuard = (CFGuard::Disabled, parse_cfguard, [TRACKED], + "use Windows Control Flow Guard (default: no)"), crate_attr: Vec = (Vec::new(), parse_string_push, [TRACKED], "inject the given attribute in the crate"), debug_macros: bool = (false, parse_bool, [TRACKED], @@ -877,8 +880,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, (such as entering an empty infinite loop) by inserting llvm.sideeffect \ (default: no)"), instrument_coverage: bool = (false, parse_bool, [TRACKED], - "instrument the generated code with LLVM code region counters to \ - (in the future) generate coverage reports (experimental; default: no)"), + "instrument the generated code with LLVM code region counters to (in the \ + future) generate coverage reports (default: no; note, the compiler build \ + config must include `profiler = true`)"), instrument_mcount: bool = (false, parse_bool, [TRACKED], "insert function instrument code for mcount-based tracing (default: no)"), keep_hygiene_data: bool = (false, parse_bool, [UNTRACKED], @@ -974,11 +978,11 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, // soon. run_dsymutil: bool = (true, parse_bool, [TRACKED], "if on Mac, run `dsymutil` and delete intermediate object files (default: yes)"), - sanitizer: Option = (None, parse_sanitizer, [TRACKED], + sanitizer: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED], "use a sanitizer"), sanitizer_memory_track_origins: usize = (0, parse_sanitizer_memory_track_origins, [TRACKED], "enable origins tracking in MemorySanitizer"), - sanitizer_recover: Vec = (vec![], parse_sanitizer_list, [TRACKED], + sanitizer_recover: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED], "enable recovery for selected sanitizers"), saturating_float_casts: Option = (None, parse_opt_bool, [TRACKED], "make float->int casts UB-free: numbers outside the integer type's range are clipped to \ diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs index 06d7d4f14d8f4..2ea312c42dc64 100644 --- a/src/librustc_session/session.rs +++ b/src/librustc_session/session.rs @@ -1,7 +1,7 @@ use crate::cgu_reuse_tracker::CguReuseTracker; use crate::code_stats::CodeStats; pub use crate::code_stats::{DataTypeKind, FieldInfo, SizeKind, VariantInfo}; -use crate::config::{self, CrateType, OutputType, PrintRequest, Sanitizer, SwitchWithOptPath}; +use crate::config::{self, CrateType, OutputType, PrintRequest, SanitizerSet, SwitchWithOptPath}; use crate::filesearch; use crate::lint; use crate::parse::ParseSess; @@ -650,14 +650,9 @@ impl Session { } pub fn fewer_names(&self) -> bool { let more_names = self.opts.output_types.contains_key(&OutputType::LlvmAssembly) - || self.opts.output_types.contains_key(&OutputType::Bitcode); - - // Address sanitizer and memory sanitizer use alloca name when reporting an issue. - let more_names = match self.opts.debugging_opts.sanitizer { - Some(Sanitizer::Address) => true, - Some(Sanitizer::Memory) => true, - _ => more_names, - }; + || self.opts.output_types.contains_key(&OutputType::Bitcode) + // AddressSanitizer and MemorySanitizer use alloca name when reporting an issue. + || self.opts.debugging_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::MEMORY); self.opts.debugging_opts.fewer_names || !more_names } @@ -1020,12 +1015,10 @@ impl Session { /// Checks if LLVM lifetime markers should be emitted. pub fn emit_lifetime_markers(&self) -> bool { - match self.opts.debugging_opts.sanitizer { - // AddressSanitizer uses lifetimes to detect use after scope bugs. - // MemorySanitizer uses lifetimes to detect use of uninitialized stack variables. - Some(Sanitizer::Address | Sanitizer::Memory) => true, - _ => self.opts.optimize != config::OptLevel::No, - } + self.opts.optimize != config::OptLevel::No + // AddressSanitizer uses lifetimes to detect use after scope bugs. + // MemorySanitizer uses lifetimes to detect use of uninitialized stack variables. + || self.opts.debugging_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::MEMORY) } } @@ -1356,33 +1349,44 @@ fn validate_commandline_args_with_session_available(sess: &Session) { ); } + const ASAN_SUPPORTED_TARGETS: &[&str] = &[ + "aarch64-fuchsia", + "aarch64-unknown-linux-gnu", + "x86_64-apple-darwin", + "x86_64-fuchsia", + "x86_64-unknown-linux-gnu", + ]; + const LSAN_SUPPORTED_TARGETS: &[&str] = + &["aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"]; + const MSAN_SUPPORTED_TARGETS: &[&str] = + &["aarch64-unknown-linux-gnu", "x86_64-unknown-linux-gnu"]; + const TSAN_SUPPORTED_TARGETS: &[&str] = + &["aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"]; + // Sanitizers can only be used on some tested platforms. - if let Some(ref sanitizer) = sess.opts.debugging_opts.sanitizer { - const ASAN_SUPPORTED_TARGETS: &[&str] = &[ - "x86_64-unknown-linux-gnu", - "x86_64-apple-darwin", - "x86_64-fuchsia", - "aarch64-fuchsia", - ]; - const TSAN_SUPPORTED_TARGETS: &[&str] = - &["x86_64-unknown-linux-gnu", "x86_64-apple-darwin"]; - const LSAN_SUPPORTED_TARGETS: &[&str] = - &["x86_64-unknown-linux-gnu", "x86_64-apple-darwin"]; - const MSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"]; - - let supported_targets = match *sanitizer { - Sanitizer::Address => ASAN_SUPPORTED_TARGETS, - Sanitizer::Thread => TSAN_SUPPORTED_TARGETS, - Sanitizer::Leak => LSAN_SUPPORTED_TARGETS, - Sanitizer::Memory => MSAN_SUPPORTED_TARGETS, + for s in sess.opts.debugging_opts.sanitizer { + let supported_targets = match s { + SanitizerSet::ADDRESS => ASAN_SUPPORTED_TARGETS, + SanitizerSet::LEAK => LSAN_SUPPORTED_TARGETS, + SanitizerSet::MEMORY => MSAN_SUPPORTED_TARGETS, + SanitizerSet::THREAD => TSAN_SUPPORTED_TARGETS, + _ => panic!("unrecognized sanitizer {}", s), }; - if !supported_targets.contains(&&*sess.opts.target_triple.triple()) { sess.err(&format!( - "{:?}Sanitizer only works with the `{}` target", - sanitizer, - supported_targets.join("` or `") + "`-Zsanitizer={}` only works with targets: {}", + s, + supported_targets.join(", ") + )); + } + let conflicting = sess.opts.debugging_opts.sanitizer - s; + if !conflicting.is_empty() { + sess.err(&format!( + "`-Zsanitizer={}` is incompatible with `-Zsanitizer={}`", + s, conflicting, )); + // Don't report additional errors. + break; } } } diff --git a/src/librustc_span/hygiene.rs b/src/librustc_span/hygiene.rs index f2c9f8055b975..c0fb84e741f4a 100644 --- a/src/librustc_span/hygiene.rs +++ b/src/librustc_span/hygiene.rs @@ -822,15 +822,7 @@ pub enum DesugaringKind { OpaqueTy, Async, Await, - ForLoop(ForLoopLoc), - Operator, -} - -/// A location in the desugaring of a `for` loop -#[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable_Generic)] -pub enum ForLoopLoc { - Head, - IntoIter, + ForLoop, } impl DesugaringKind { @@ -843,8 +835,7 @@ impl DesugaringKind { DesugaringKind::QuestionMark => "operator `?`", DesugaringKind::TryBlock => "`try` block", DesugaringKind::OpaqueTy => "`impl Trait`", - DesugaringKind::ForLoop(_) => "`for` loop", - DesugaringKind::Operator => "operator", + DesugaringKind::ForLoop => "`for` loop", } } } diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs index af9b5a264e313..9624006683467 100644 --- a/src/librustc_span/lib.rs +++ b/src/librustc_span/lib.rs @@ -31,9 +31,7 @@ pub mod edition; use edition::Edition; pub mod hygiene; use hygiene::Transparency; -pub use hygiene::{ - DesugaringKind, ExpnData, ExpnId, ExpnKind, ForLoopLoc, MacroKind, SyntaxContext, -}; +pub use hygiene::{DesugaringKind, ExpnData, ExpnId, ExpnKind, MacroKind, SyntaxContext}; pub mod def_id; use def_id::{CrateNum, DefId, LOCAL_CRATE}; mod span_encoding; diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index 970a26325926c..fa1368b104c7e 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -159,6 +159,7 @@ symbols! { assume_init, async_await, async_closure, + atomics, attr, attributes, attr_literals, @@ -587,7 +588,10 @@ symbols! { proc_macro_mod, proc_macro_non_items, proc_macro_path_invoc, + profiler_builtins, profiler_runtime, + ptr_guaranteed_eq, + ptr_guaranteed_ne, ptr_offset_from, pub_restricted, pure, diff --git a/src/librustc_target/asm/hexagon.rs b/src/librustc_target/asm/hexagon.rs new file mode 100644 index 0000000000000..d41941d0b4cd7 --- /dev/null +++ b/src/librustc_target/asm/hexagon.rs @@ -0,0 +1,93 @@ +use super::{InlineAsmArch, InlineAsmType}; +use rustc_macros::HashStable_Generic; +use std::fmt; + +def_reg_class! { + Hexagon HexagonInlineAsmRegClass { + reg, + } +} + +impl HexagonInlineAsmRegClass { + pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] { + &[] + } + + pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option { + None + } + + pub fn suggest_modifier( + self, + _arch: InlineAsmArch, + _ty: InlineAsmType, + ) -> Option<(char, &'static str)> { + None + } + + pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> { + None + } + + pub fn supported_types( + self, + _arch: InlineAsmArch, + ) -> &'static [(InlineAsmType, Option<&'static str>)] { + match self { + Self::reg => types! { _: I8, I16, I32, F32; }, + } + } +} + +def_regs! { + Hexagon HexagonInlineAsmReg HexagonInlineAsmRegClass { + r0: reg = ["r0"], + r1: reg = ["r1"], + r2: reg = ["r2"], + r3: reg = ["r3"], + r4: reg = ["r4"], + r5: reg = ["r5"], + r6: reg = ["r6"], + r7: reg = ["r7"], + r8: reg = ["r8"], + r9: reg = ["r9"], + r10: reg = ["r10"], + r11: reg = ["r11"], + r12: reg = ["r12"], + r13: reg = ["r13"], + r14: reg = ["r14"], + r15: reg = ["r15"], + r16: reg = ["r16"], + r17: reg = ["r17"], + r18: reg = ["r18"], + r19: reg = ["r19"], + r20: reg = ["r20"], + r21: reg = ["r21"], + r22: reg = ["r22"], + r23: reg = ["r23"], + r24: reg = ["r24"], + r25: reg = ["r25"], + r26: reg = ["r26"], + r27: reg = ["r27"], + r28: reg = ["r28"], + #error = ["r29", "sp"] => + "the stack pointer cannot be used as an operand for inline asm", + #error = ["r30", "fr"] => + "the frame register cannot be used as an operand for inline asm", + #error = ["r31", "lr"] => + "the link register cannot be used as an operand for inline asm", + } +} + +impl HexagonInlineAsmReg { + pub fn emit( + self, + out: &mut dyn fmt::Write, + _arch: InlineAsmArch, + _modifier: Option, + ) -> fmt::Result { + out.write_str(self.name()) + } + + pub fn overlapping_regs(self, mut _cb: impl FnMut(HexagonInlineAsmReg)) {} +} diff --git a/src/librustc_target/asm/mod.rs b/src/librustc_target/asm/mod.rs index a18a4dbd3e214..834d7c6d381a3 100644 --- a/src/librustc_target/asm/mod.rs +++ b/src/librustc_target/asm/mod.rs @@ -148,12 +148,14 @@ macro_rules! types { mod aarch64; mod arm; +mod hexagon; mod nvptx; mod riscv; mod x86; pub use aarch64::{AArch64InlineAsmReg, AArch64InlineAsmRegClass}; pub use arm::{ArmInlineAsmReg, ArmInlineAsmRegClass}; +pub use hexagon::{HexagonInlineAsmReg, HexagonInlineAsmRegClass}; pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass}; pub use riscv::{RiscVInlineAsmReg, RiscVInlineAsmRegClass}; pub use x86::{X86InlineAsmReg, X86InlineAsmRegClass}; @@ -167,6 +169,7 @@ pub enum InlineAsmArch { RiscV32, RiscV64, Nvptx64, + Hexagon, } impl FromStr for InlineAsmArch { @@ -181,6 +184,7 @@ impl FromStr for InlineAsmArch { "riscv32" => Ok(Self::RiscV32), "riscv64" => Ok(Self::RiscV64), "nvptx64" => Ok(Self::Nvptx64), + "hexagon" => Ok(Self::Hexagon), _ => Err(()), } } @@ -203,6 +207,7 @@ pub enum InlineAsmReg { AArch64(AArch64InlineAsmReg), RiscV(RiscVInlineAsmReg), Nvptx(NvptxInlineAsmReg), + Hexagon(HexagonInlineAsmReg), } impl InlineAsmReg { @@ -212,6 +217,7 @@ impl InlineAsmReg { Self::Arm(r) => r.name(), Self::AArch64(r) => r.name(), Self::RiscV(r) => r.name(), + Self::Hexagon(r) => r.name(), } } @@ -221,6 +227,7 @@ impl InlineAsmReg { Self::Arm(r) => InlineAsmRegClass::Arm(r.reg_class()), Self::AArch64(r) => InlineAsmRegClass::AArch64(r.reg_class()), Self::RiscV(r) => InlineAsmRegClass::RiscV(r.reg_class()), + Self::Hexagon(r) => InlineAsmRegClass::Hexagon(r.reg_class()), } } @@ -246,6 +253,9 @@ impl InlineAsmReg { InlineAsmArch::Nvptx64 => { Self::Nvptx(NvptxInlineAsmReg::parse(arch, has_feature, &name)?) } + InlineAsmArch::Hexagon => { + Self::Hexagon(HexagonInlineAsmReg::parse(arch, has_feature, &name)?) + } }) } @@ -262,6 +272,7 @@ impl InlineAsmReg { Self::Arm(r) => r.emit(out, arch, modifier), Self::AArch64(r) => r.emit(out, arch, modifier), Self::RiscV(r) => r.emit(out, arch, modifier), + Self::Hexagon(r) => r.emit(out, arch, modifier), } } @@ -271,6 +282,7 @@ impl InlineAsmReg { Self::Arm(r) => r.overlapping_regs(|r| cb(Self::Arm(r))), Self::AArch64(_) => cb(self), Self::RiscV(_) => cb(self), + Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))), } } } @@ -292,6 +304,7 @@ pub enum InlineAsmRegClass { AArch64(AArch64InlineAsmRegClass), RiscV(RiscVInlineAsmRegClass), Nvptx(NvptxInlineAsmRegClass), + Hexagon(HexagonInlineAsmRegClass), } impl InlineAsmRegClass { @@ -302,6 +315,7 @@ impl InlineAsmRegClass { Self::AArch64(r) => r.name(), Self::RiscV(r) => r.name(), Self::Nvptx(r) => r.name(), + Self::Hexagon(r) => r.name(), } } @@ -315,6 +329,7 @@ impl InlineAsmRegClass { Self::AArch64(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::AArch64), Self::RiscV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::RiscV), Self::Nvptx(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Nvptx), + Self::Hexagon(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Hexagon), } } @@ -335,6 +350,7 @@ impl InlineAsmRegClass { Self::AArch64(r) => r.suggest_modifier(arch, ty), Self::RiscV(r) => r.suggest_modifier(arch, ty), Self::Nvptx(r) => r.suggest_modifier(arch, ty), + Self::Hexagon(r) => r.suggest_modifier(arch, ty), } } @@ -351,6 +367,7 @@ impl InlineAsmRegClass { Self::AArch64(r) => r.default_modifier(arch), Self::RiscV(r) => r.default_modifier(arch), Self::Nvptx(r) => r.default_modifier(arch), + Self::Hexagon(r) => r.default_modifier(arch), } } @@ -366,6 +383,7 @@ impl InlineAsmRegClass { Self::AArch64(r) => r.supported_types(arch), Self::RiscV(r) => r.supported_types(arch), Self::Nvptx(r) => r.supported_types(arch), + Self::Hexagon(r) => r.supported_types(arch), } } @@ -384,6 +402,9 @@ impl InlineAsmRegClass { Self::RiscV(RiscVInlineAsmRegClass::parse(arch, name)?) } InlineAsmArch::Nvptx64 => Self::Nvptx(NvptxInlineAsmRegClass::parse(arch, name)?), + InlineAsmArch::Hexagon => { + Self::Hexagon(HexagonInlineAsmRegClass::parse(arch, name)?) + } }) }) } @@ -397,6 +418,7 @@ impl InlineAsmRegClass { Self::AArch64(r) => r.valid_modifiers(arch), Self::RiscV(r) => r.valid_modifiers(arch), Self::Nvptx(r) => r.valid_modifiers(arch), + Self::Hexagon(r) => r.valid_modifiers(arch), } } } @@ -541,5 +563,10 @@ pub fn allocatable_registers( nvptx::fill_reg_map(arch, has_feature, &mut map); map } + InlineAsmArch::Hexagon => { + let mut map = hexagon::regclass_map(); + hexagon::fill_reg_map(arch, has_feature, &mut map); + map + } } } diff --git a/src/librustc_trait_selection/autoderef.rs b/src/librustc_trait_selection/autoderef.rs new file mode 100644 index 0000000000000..d542e16d83f10 --- /dev/null +++ b/src/librustc_trait_selection/autoderef.rs @@ -0,0 +1,229 @@ +use crate::traits::query::evaluate_obligation::InferCtxtExt; +use crate::traits::{self, TraitEngine}; +use rustc_errors::struct_span_err; +use rustc_hir as hir; +use rustc_infer::infer::InferCtxt; +use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, WithConstness}; +use rustc_middle::ty::{ToPredicate, TypeFoldable}; +use rustc_session::DiagnosticMessageId; +use rustc_span::symbol::Ident; +use rustc_span::Span; + +#[derive(Copy, Clone, Debug)] +pub enum AutoderefKind { + Builtin, + Overloaded, +} + +struct AutoderefSnapshot<'tcx> { + at_start: bool, + reached_recursion_limit: bool, + steps: Vec<(Ty<'tcx>, AutoderefKind)>, + cur_ty: Ty<'tcx>, + obligations: Vec>, +} + +pub struct Autoderef<'a, 'tcx> { + // Meta infos: + infcx: &'a InferCtxt<'a, 'tcx>, + span: Span, + body_id: hir::HirId, + param_env: ty::ParamEnv<'tcx>, + + // Current state: + state: AutoderefSnapshot<'tcx>, + + // Configurations: + include_raw_pointers: bool, + silence_errors: bool, +} + +impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> { + type Item = (Ty<'tcx>, usize); + + fn next(&mut self) -> Option { + let tcx = self.infcx.tcx; + + debug!("autoderef: steps={:?}, cur_ty={:?}", self.state.steps, self.state.cur_ty); + if self.state.at_start { + self.state.at_start = false; + debug!("autoderef stage #0 is {:?}", self.state.cur_ty); + return Some((self.state.cur_ty, 0)); + } + + // If we have reached the recursion limit, error gracefully. + if !tcx.sess.recursion_limit().value_within_limit(self.state.steps.len()) { + if !self.silence_errors { + report_autoderef_recursion_limit_error(tcx, self.span, self.state.cur_ty); + } + self.state.reached_recursion_limit = true; + return None; + } + + if self.state.cur_ty.is_ty_var() { + return None; + } + + // Otherwise, deref if type is derefable: + let (kind, new_ty) = + if let Some(mt) = self.state.cur_ty.builtin_deref(self.include_raw_pointers) { + (AutoderefKind::Builtin, mt.ty) + } else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) { + (AutoderefKind::Overloaded, ty) + } else { + return None; + }; + + if new_ty.references_error() { + return None; + } + + self.state.steps.push((self.state.cur_ty, kind)); + debug!( + "autoderef stage #{:?} is {:?} from {:?}", + self.step_count(), + new_ty, + (self.state.cur_ty, kind) + ); + self.state.cur_ty = new_ty; + + Some((self.state.cur_ty, self.step_count())) + } +} + +impl<'a, 'tcx> Autoderef<'a, 'tcx> { + pub fn new( + infcx: &'a InferCtxt<'a, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + body_id: hir::HirId, + span: Span, + base_ty: Ty<'tcx>, + ) -> Autoderef<'a, 'tcx> { + Autoderef { + infcx, + span, + body_id, + param_env, + state: AutoderefSnapshot { + steps: vec![], + cur_ty: infcx.resolve_vars_if_possible(&base_ty), + obligations: vec![], + at_start: true, + reached_recursion_limit: false, + }, + include_raw_pointers: false, + silence_errors: false, + } + } + + fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option> { + debug!("overloaded_deref_ty({:?})", ty); + + let tcx = self.infcx.tcx; + + // + let trait_ref = TraitRef { + def_id: tcx.lang_items().deref_trait()?, + substs: tcx.mk_substs_trait(ty, &[]), + }; + + let cause = traits::ObligationCause::misc(self.span, self.body_id); + + let obligation = traits::Obligation::new( + cause.clone(), + self.param_env, + trait_ref.without_const().to_predicate(tcx), + ); + if !self.infcx.predicate_may_hold(&obligation) { + debug!("overloaded_deref_ty: cannot match obligation"); + return None; + } + + let mut fulfillcx = traits::FulfillmentContext::new_in_snapshot(); + let normalized_ty = fulfillcx.normalize_projection_type( + &self.infcx, + self.param_env, + ty::ProjectionTy::from_ref_and_name(tcx, trait_ref, Ident::from_str("Target")), + cause, + ); + if let Err(e) = fulfillcx.select_where_possible(&self.infcx) { + // This shouldn't happen, except for evaluate/fulfill mismatches, + // but that's not a reason for an ICE (`predicate_may_hold` is conservative + // by design). + debug!("overloaded_deref_ty: encountered errors {:?} while fulfilling", e); + return None; + } + let obligations = fulfillcx.pending_obligations(); + debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations); + self.state.obligations.extend(obligations); + + Some(self.infcx.resolve_vars_if_possible(&normalized_ty)) + } + + /// Returns the final type we ended up with, which may be an inference + /// variable (we will resolve it first, if we want). + pub fn final_ty(&self, resolve: bool) -> Ty<'tcx> { + if resolve { + self.infcx.resolve_vars_if_possible(&self.state.cur_ty) + } else { + self.state.cur_ty + } + } + + pub fn step_count(&self) -> usize { + self.state.steps.len() + } + + pub fn into_obligations(self) -> Vec> { + self.state.obligations + } + + pub fn steps(&self) -> &[(Ty<'tcx>, AutoderefKind)] { + &self.state.steps + } + + pub fn span(&self) -> Span { + self.span.clone() + } + + pub fn reached_recursion_limit(&self) -> bool { + self.state.reached_recursion_limit + } + + /// also dereference through raw pointer types + /// e.g., assuming ptr_to_Foo is the type `*const Foo` + /// fcx.autoderef(span, ptr_to_Foo) => [*const Foo] + /// fcx.autoderef(span, ptr_to_Foo).include_raw_ptrs() => [*const Foo, Foo] + pub fn include_raw_pointers(mut self) -> Self { + self.include_raw_pointers = true; + self + } + + pub fn silence_errors(mut self) -> Self { + self.silence_errors = true; + self + } +} + +pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) { + // We've reached the recursion limit, error gracefully. + let suggested_limit = tcx.sess.recursion_limit() * 2; + let msg = format!("reached the recursion limit while auto-dereferencing `{:?}`", ty); + let error_id = (DiagnosticMessageId::ErrorId(55), Some(span), msg); + let fresh = tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id); + if fresh { + struct_span_err!( + tcx.sess, + span, + E0055, + "reached the recursion limit while auto-dereferencing `{:?}`", + ty + ) + .span_label(span, "deref recursion limit reached") + .help(&format!( + "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)", + suggested_limit, tcx.crate_name, + )) + .emit(); + } +} diff --git a/src/librustc_trait_selection/infer.rs b/src/librustc_trait_selection/infer.rs index f244785b49d2f..dc895ad34a932 100644 --- a/src/librustc_trait_selection/infer.rs +++ b/src/librustc_trait_selection/infer.rs @@ -44,7 +44,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { let ty = self.resolve_vars_if_possible(&ty); if !(param_env, ty).needs_infer() { - return ty.is_copy_modulo_regions(self.tcx, param_env, span); + return ty.is_copy_modulo_regions(self.tcx.at(span), param_env); } let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem, None); diff --git a/src/librustc_trait_selection/lib.rs b/src/librustc_trait_selection/lib.rs index ea886cd1f9e9b..4692fa04ed587 100644 --- a/src/librustc_trait_selection/lib.rs +++ b/src/librustc_trait_selection/lib.rs @@ -28,6 +28,7 @@ extern crate log; #[macro_use] extern crate rustc_middle; +pub mod autoderef; pub mod infer; pub mod opaque_types; pub mod traits; diff --git a/src/librustc_trait_selection/traits/chalk_fulfill.rs b/src/librustc_trait_selection/traits/chalk_fulfill.rs index 2d4d582c939b6..cbbff82d35f73 100644 --- a/src/librustc_trait_selection/traits/chalk_fulfill.rs +++ b/src/librustc_trait_selection/traits/chalk_fulfill.rs @@ -87,7 +87,9 @@ fn environment<'tcx>( NodeKind::TraitImpl => { let trait_ref = tcx.impl_trait_ref(def_id).expect("not an impl"); - inputs.extend(trait_ref.substs.iter().flat_map(|arg| arg.walk())); + // FIXME(chalk): this has problems because of late-bound regions + //inputs.extend(trait_ref.substs.iter().flat_map(|arg| arg.walk())); + inputs.extend(trait_ref.substs.iter()); } // In an inherent impl, we assume that the receiver type and all its @@ -136,6 +138,8 @@ fn in_environment( let environment = match obligation.param_env.def_id { Some(def_id) => environment(infcx.tcx, def_id), None if obligation.param_env.caller_bounds.is_empty() => ty::List::empty(), + // FIXME(chalk): this is hit in ui/where-clauses/where-clause-constraints-are-local-for-trait-impl + // and ui/generics/generic-static-methods _ => bug!("non-empty `ParamEnv` with no def-id"), }; diff --git a/src/librustc_trait_selection/traits/coherence.rs b/src/librustc_trait_selection/traits/coherence.rs index 706cbf058b713..3ec7fe2bf25c6 100644 --- a/src/librustc_trait_selection/traits/coherence.rs +++ b/src/librustc_trait_selection/traits/coherence.rs @@ -120,12 +120,13 @@ fn overlap<'cx, 'tcx>( debug!("overlap(a_def_id={:?}, b_def_id={:?})", a_def_id, b_def_id); selcx.infcx().probe_maybe_skip_leak_check(skip_leak_check.is_yes(), |snapshot| { - overlap_within_probe(selcx, a_def_id, b_def_id, snapshot) + overlap_within_probe(selcx, skip_leak_check, a_def_id, b_def_id, snapshot) }) } fn overlap_within_probe( selcx: &mut SelectionContext<'cx, 'tcx>, + skip_leak_check: SkipLeakCheck, a_def_id: DefId, b_def_id: DefId, snapshot: &CombinedSnapshot<'_, 'tcx>, @@ -180,6 +181,13 @@ fn overlap_within_probe( return None; } + if !skip_leak_check.is_yes() { + if let Err(_) = infcx.leak_check(true, snapshot) { + debug!("overlap: leak check failed"); + return None; + } + } + let impl_header = selcx.infcx().resolve_vars_if_possible(&a_impl_header); let intercrate_ambiguity_causes = selcx.take_intercrate_ambiguity_causes(); debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes); diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs index e5a6c9a2e391a..fd0c1a54d27ad 100644 --- a/src/librustc_trait_selection/traits/error_reporting/mod.rs +++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs @@ -15,6 +15,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorReported}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_hir::intravisit::Visitor; use rustc_hir::Node; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::error::ExpectedFound; @@ -25,7 +26,7 @@ use rustc_middle::ty::{ TypeFoldable, WithConstness, }; use rustc_session::DiagnosticMessageId; -use rustc_span::{ExpnKind, Span, DUMMY_SP}; +use rustc_span::{ExpnKind, MultiSpan, Span, DUMMY_SP}; use std::fmt; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; @@ -401,6 +402,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { err.span_label(enclosing_scope_span, s.as_str()); } + self.suggest_dereferences(&obligation, &mut err, &trait_ref, points_at_arg); 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); @@ -1695,36 +1697,95 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { err: &mut DiagnosticBuilder<'tcx>, obligation: &PredicateObligation<'tcx>, ) { - if let ( - ty::PredicateKind::Trait(pred, _), - ObligationCauseCode::BindingObligation(item_def_id, span), - ) = (obligation.predicate.kind(), &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_ref().and_then(|trait_ref| trait_ref.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, + let (pred, item_def_id, span) = + match (obligation.predicate.kind(), &obligation.cause.code.peel_derives()) { + ( + ty::PredicateKind::Trait(pred, _), + ObligationCauseCode::BindingObligation(item_def_id, span), + ) => (pred, item_def_id, span), + _ => return, + }; + + let node = match ( + self.tcx.hir().get_if_local(*item_def_id), + Some(pred.def_id()) == self.tcx.lang_items().sized_trait(), + ) { + (Some(node), true) => node, + _ => return, + }; + let generics = match node.generics() { + Some(generics) => generics, + None => return, + }; + for param in generics.params { + if param.span != *span + || param.bounds.iter().any(|bound| { + bound.trait_ref().and_then(|trait_ref| trait_ref.trait_def_id()) + == self.tcx.lang_items().sized_trait() + }) + { + continue; + } + match node { + hir::Node::Item( + item + @ + hir::Item { + kind: + hir::ItemKind::Enum(..) + | hir::ItemKind::Struct(..) + | hir::ItemKind::Union(..), + .. + }, + ) => { + // Suggesting `T: ?Sized` is only valid in an ADT if `T` is only used in a + // borrow. `struct S<'a, T: ?Sized>(&'a T);` is valid, `struct S(T);` + // is not. + let mut visitor = FindTypeParam { + param: param.name.ident().name, + invalid_spans: vec![], + nested: false, + }; + visitor.visit_item(item); + if !visitor.invalid_spans.is_empty() { + let mut multispan: MultiSpan = param.span.into(); + multispan.push_span_label( + param.span, + format!("this could be changed to `{}: ?Sized`...", param.name.ident()), + ); + for sp in visitor.invalid_spans { + multispan.push_span_label( + sp, + format!( + "...if indirection was used here: `Box<{}>`", + param.name.ident(), + ), + ); + } + err.span_help( + multispan, + &format!( + "you could relax the implicit `Sized` bound on `{T}` if it were \ + used through indirection like `&{T}` or `Box<{T}>`", + T = param.name.ident(), + ), ); return; } } + _ => {} } + 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; } } @@ -1744,6 +1805,50 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { } } +/// Look for type `param` in an ADT being used only through a reference to confirm that suggesting +/// `param: ?Sized` would be a valid constraint. +struct FindTypeParam { + param: rustc_span::Symbol, + invalid_spans: Vec, + nested: bool, +} + +impl<'v> Visitor<'v> for FindTypeParam { + type Map = rustc_hir::intravisit::ErasedMap<'v>; + + fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap { + hir::intravisit::NestedVisitorMap::None + } + + fn visit_ty(&mut self, ty: &hir::Ty<'_>) { + // We collect the spans of all uses of the "bare" type param, like in `field: T` or + // `field: (T, T)` where we could make `T: ?Sized` while skipping cases that are known to be + // valid like `field: &'a T` or `field: *mut T` and cases that *might* have further `Sized` + // obligations like `Box` and `Vec`, but we perform no extra analysis for those cases + // and suggest `T: ?Sized` regardless of their obligations. This is fine because the errors + // in that case should make what happened clear enough. + match ty.kind { + hir::TyKind::Ptr(_) | hir::TyKind::Rptr(..) | hir::TyKind::TraitObject(..) => {} + hir::TyKind::Path(hir::QPath::Resolved(None, path)) + if path.segments.len() == 1 && path.segments[0].ident.name == self.param => + { + if !self.nested { + self.invalid_spans.push(ty.span); + } + } + hir::TyKind::Path(_) => { + let prev = self.nested; + self.nested = true; + hir::intravisit::walk_ty(self, ty); + self.nested = prev; + } + _ => { + hir::intravisit::walk_ty(self, ty); + } + } + } +} + pub fn recursive_type_with_infinite_size_error( tcx: TyCtxt<'tcx>, type_def_id: DefId, diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index dfd7dac72d8e1..176bd90303ddd 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -3,6 +3,7 @@ use super::{ SelectionContext, }; +use crate::autoderef::Autoderef; use crate::infer::InferCtxt; use crate::traits::normalize_projection_type; @@ -13,11 +14,11 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items; use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node}; -use rustc_middle::ty::TypeckTables; use rustc_middle::ty::{ self, suggest_constraining_type_param, AdtKind, DefIdTree, Infer, InferTy, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, }; +use rustc_middle::ty::{TypeAndMut, TypeckTables}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{MultiSpan, Span, DUMMY_SP}; use std::fmt; @@ -48,6 +49,14 @@ pub trait InferCtxtExt<'tcx> { err: &mut DiagnosticBuilder<'_>, ); + fn suggest_dereferences( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut DiagnosticBuilder<'tcx>, + trait_ref: &ty::PolyTraitRef<'tcx>, + points_at_arg: bool, + ); + fn get_closure_name( &self, def_id: DefId, @@ -450,6 +459,62 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } } + /// When after several dereferencing, the reference satisfies the trait + /// binding. This function provides dereference suggestion for this + /// specific situation. + fn suggest_dereferences( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut DiagnosticBuilder<'tcx>, + trait_ref: &ty::PolyTraitRef<'tcx>, + points_at_arg: bool, + ) { + // It only make sense when suggesting dereferences for arguments + if !points_at_arg { + return; + } + let param_env = obligation.param_env; + let body_id = obligation.cause.body_id; + let span = obligation.cause.span; + let real_trait_ref = match &obligation.cause.code { + ObligationCauseCode::ImplDerivedObligation(cause) + | ObligationCauseCode::DerivedObligation(cause) + | ObligationCauseCode::BuiltinDerivedObligation(cause) => &cause.parent_trait_ref, + _ => trait_ref, + }; + let real_ty = match real_trait_ref.self_ty().no_bound_vars() { + Some(ty) => ty, + None => return, + }; + + if let ty::Ref(region, base_ty, mutbl) = real_ty.kind { + let mut autoderef = Autoderef::new(self, param_env, body_id, span, base_ty); + if let Some(steps) = autoderef.find_map(|(ty, steps)| { + // Re-add the `&` + let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl }); + let obligation = + self.mk_trait_obligation_with_new_self_ty(param_env, real_trait_ref, ty); + Some(steps).filter(|_| self.predicate_may_hold(&obligation)) + }) { + if steps > 0 { + if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(span) { + // Don't care about `&mut` because `DerefMut` is used less + // often and user will not expect autoderef happens. + if src.starts_with("&") && !src.starts_with("&mut ") { + let derefs = "*".repeat(steps); + err.span_suggestion( + span, + "consider adding dereference here", + format!("&{}{}", derefs, &src[1..]), + Applicability::MachineApplicable, + ); + } + } + } + } + } + } + /// 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. fn suggest_borrow_on_unsized_slice( diff --git a/src/librustc_trait_selection/traits/fulfill.rs b/src/librustc_trait_selection/traits/fulfill.rs index 106753ed809a5..32ab63458e752 100644 --- a/src/librustc_trait_selection/traits/fulfill.rs +++ b/src/librustc_trait_selection/traits/fulfill.rs @@ -321,7 +321,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { ty::PredicateKind::Trait(ref data, _) => { let trait_obligation = obligation.with(*data); - if data.is_global() { + if obligation.predicate.is_global() { // no type variables present, can use evaluation for better caching. // FIXME: consider caching errors too. if infcx.predicate_must_hold_considering_regions(&obligation) { diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs index ed108613bfa23..bc696214cbc66 100644 --- a/src/librustc_trait_selection/traits/project.rs +++ b/src/librustc_trait_selection/traits/project.rs @@ -24,6 +24,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::ErrorReported; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::{FnOnceTraitLangItem, GeneratorTraitLangItem}; +use rustc_infer::infer::resolve::OpportunisticRegionResolver; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::util::IntTypeExt; @@ -148,15 +149,12 @@ pub fn poly_project_and_unify_type<'cx, 'tcx>( debug!("poly_project_and_unify_type(obligation={:?})", obligation); let infcx = selcx.infcx(); - infcx.commit_if_ok(|snapshot| { - let (placeholder_predicate, placeholder_map) = + infcx.commit_if_ok(|_snapshot| { + let (placeholder_predicate, _) = 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) }) } @@ -360,7 +358,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { // 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 + // obligation like `for<'a> T::B: Fn(&'a i32)`), 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 @@ -895,9 +893,12 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( 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), + // If so, extract what we know from the trait and try to come up with a good answer. + let bounds = match obligation_trait_ref.self_ty().kind { + ty::Projection(ref data) => { + tcx.projection_predicates(data.item_def_id).subst(tcx, data.substs) + } + ty::Opaque(def_id, substs) => tcx.projection_predicates(def_id).subst(tcx, 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. @@ -907,17 +908,13 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( _ => 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.into_iter()).map(|o| o.predicate); assemble_candidates_from_predicates( selcx, obligation, obligation_trait_ref, candidate_set, ProjectionTyCandidate::TraitDef, - bounds, + bounds.iter(), ) } @@ -1146,7 +1143,7 @@ fn confirm_candidate<'cx, 'tcx>( ) -> Progress<'tcx> { debug!("confirm_candidate(candidate={:?}, obligation={:?})", candidate, obligation); - match candidate { + let mut progress = match candidate { ProjectionTyCandidate::ParamEnv(poly_projection) | ProjectionTyCandidate::TraitDef(poly_projection) => { confirm_param_env_candidate(selcx, obligation, poly_projection) @@ -1155,7 +1152,16 @@ fn confirm_candidate<'cx, 'tcx>( ProjectionTyCandidate::Select(impl_source) => { confirm_select_candidate(selcx, obligation, obligation_trait_ref, impl_source) } + }; + // When checking for cycle during evaluation, we compare predicates with + // "syntactic" equality. Since normalization generally introduces a type + // with new region variables, we need to resolve them to existing variables + // when possible for this to work. See `auto-trait-projection-recursion.rs` + // for a case where this matters. + if progress.ty.has_infer_regions() { + progress.ty = OpportunisticRegionResolver::new(selcx.infcx()).fold_ty(progress.ty); } + progress } fn confirm_select_candidate<'cx, 'tcx>( @@ -1474,6 +1480,12 @@ fn confirm_impl_candidate<'cx, 'tcx>( ); return Progress { ty: tcx.ty_error(), obligations: nested }; } + // If we're trying to normalize ` as X>::A` using + //`impl X for Vec { type A = Box; }`, then: + // + // * `obligation.predicate.substs` is `[Vec, S]` + // * `substs` is `[u32]` + // * `substs` ends up as `[u32, S]` 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.defining_node); diff --git a/src/librustc_trait_selection/traits/query/normalize.rs b/src/librustc_trait_selection/traits/query/normalize.rs index 3e7749356d212..ca49ff5884f98 100644 --- a/src/librustc_trait_selection/traits/query/normalize.rs +++ b/src/librustc_trait_selection/traits/query/normalize.rs @@ -145,7 +145,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { // 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 + // obligation like `for<'a> T::B: Fn(&'a i32)`), 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 diff --git a/src/librustc_trait_selection/traits/select/candidate_assembly.rs b/src/librustc_trait_selection/traits/select/candidate_assembly.rs index 9045451056b19..4dab5814f7b7e 100644 --- a/src/librustc_trait_selection/traits/select/candidate_assembly.rs +++ b/src/librustc_trait_selection/traits/select/candidate_assembly.rs @@ -163,9 +163,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => return, } - let result = self.infcx.probe(|snapshot| { - self.match_projection_obligation_against_definition_bounds(obligation, snapshot) - }); + let result = self + .infcx + .probe(|_| self.match_projection_obligation_against_definition_bounds(obligation)); if result { candidates.vec.push(ProjectionCandidate); @@ -345,8 +345,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.predicate.def_id(), obligation.predicate.skip_binder().trait_ref.self_ty(), |impl_def_id| { - self.infcx.probe(|snapshot| { - if let Ok(_substs) = self.match_impl(impl_def_id, obligation, snapshot) { + self.infcx.probe(|_| { + if let Ok(_substs) = self.match_impl(impl_def_id, obligation) { candidates.vec.push(ImplCandidate(impl_def_id)); } }); diff --git a/src/librustc_trait_selection/traits/select/confirmation.rs b/src/librustc_trait_selection/traits/select/confirmation.rs index f8d26c06a219d..834bf17227d2e 100644 --- a/src/librustc_trait_selection/traits/select/confirmation.rs +++ b/src/librustc_trait_selection/traits/select/confirmation.rs @@ -121,9 +121,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) { - self.infcx.commit_unconditionally(|snapshot| { - let result = - self.match_projection_obligation_against_definition_bounds(obligation, snapshot); + self.infcx.commit_unconditionally(|_| { + let result = self.match_projection_obligation_against_definition_bounds(obligation); assert!(result); }) } @@ -265,8 +264,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // First, create the substitutions by matching the impl again, // this time not in a probe. - self.infcx.commit_unconditionally(|snapshot| { - let substs = self.rematch_impl(impl_def_id, obligation, snapshot); + self.infcx.commit_unconditionally(|_| { + let substs = self.rematch_impl(impl_def_id, obligation); debug!("confirm_impl_candidate: substs={:?}", substs); let cause = obligation.derived_cause(ImplDerivedObligation); ensure_sufficient_stack(|| { @@ -553,14 +552,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// /// Here is an example. Imagine we have a closure expression /// and we desugared it so that the type of the expression is - /// `Closure`, and `Closure` expects an int as argument. Then it + /// `Closure`, and `Closure` expects `i32` as argument. Then it /// is "as if" the compiler generated this impl: /// - /// impl Fn(int) for Closure { ... } + /// impl Fn(i32) for Closure { ... } /// - /// Now imagine our obligation is `Fn(usize) for Closure`. So far + /// Now imagine our obligation is `Closure: Fn(usize)`. So far /// we have matched the self type `Closure`. At this point we'll - /// compare the `int` to `usize` and generate an error. + /// compare the `i32` to `usize` and generate an error. /// /// Note that this checking occurs *after* the impl has selected, /// because these output type parameters should not affect the @@ -612,24 +611,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Require that the traits involved in this upcast are **equal**; // only the **lifetime bound** is changed. - // - // FIXME: This condition is arguably too strong -- it would - // suffice for the source trait to be a *subtype* of the target - // trait. In particular, changing from something like - // `for<'a, 'b> Foo<'a, 'b>` to `for<'a> Foo<'a, 'a>` should be - // permitted. And, indeed, in the in commit - // 904a0bde93f0348f69914ee90b1f8b6e4e0d7cbc, this - // condition was loosened. However, when the leak check was - // added back, using subtype here actually guides the coercion - // code in such a way that it accepts `old-lub-glb-object.rs`. - // This is probably a good thing, but I've modified this to `.eq` - // because I want to continue rejecting that test (as we have - // done for quite some time) before we are firmly comfortable - // with what our behavior should be there. -nikomatsakis let InferOk { obligations, .. } = self .infcx .at(&obligation.cause, obligation.param_env) - .eq(target, source_trait) // FIXME -- see below + .sup(target, source_trait) .map_err(|_| Unimplemented)?; nested.extend(obligations); diff --git a/src/librustc_trait_selection/traits/select/mod.rs b/src/librustc_trait_selection/traits/select/mod.rs index 3fd566eab437e..cff5efbfd0fd1 100644 --- a/src/librustc_trait_selection/traits/select/mod.rs +++ b/src/librustc_trait_selection/traits/select/mod.rs @@ -21,7 +21,7 @@ use super::{Normalized, ProjectionCacheKey}; use super::{ObligationCause, PredicateObligation, TraitObligation}; use super::{Overflow, SelectionError, Unimplemented}; -use crate::infer::{CombinedSnapshot, InferCtxt, InferOk, PlaceholderMap, TypeFreshener}; +use crate::infer::{InferCtxt, InferOk, TypeFreshener}; use crate::traits::error_reporting::InferCtxtExt; use crate::traits::project::ProjectionCacheKeyExt; use rustc_ast::attr; @@ -347,6 +347,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Result { self.infcx.probe(|snapshot| -> Result { let result = op(self)?; + + match self.infcx.leak_check(true, snapshot) { + Ok(()) => {} + Err(_) => return Ok(EvaluatedToErr), + } + match self.infcx.region_constraints_added_in_snapshot(snapshot) { None => Ok(result), Some(_) => Ok(result.max(EvaluatedToOkModuloRegions)), @@ -1262,10 +1268,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn match_projection_obligation_against_definition_bounds( &mut self, obligation: &TraitObligation<'tcx>, - snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> bool { let poly_trait_predicate = self.infcx().resolve_vars_if_possible(&obligation.predicate); - let (placeholder_trait_predicate, placeholder_map) = + let (placeholder_trait_predicate, _) = self.infcx().replace_bound_vars_with_placeholders(&poly_trait_predicate); debug!( "match_projection_obligation_against_definition_bounds: \ @@ -1273,9 +1278,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { placeholder_trait_predicate, ); - let (def_id, substs) = match placeholder_trait_predicate.trait_ref.self_ty().kind { - ty::Projection(ref data) => (data.trait_ref(self.tcx()).def_id, data.substs), - ty::Opaque(def_id, substs) => (def_id, substs), + let tcx = self.infcx.tcx; + let predicates = match placeholder_trait_predicate.trait_ref.self_ty().kind { + ty::Projection(ref data) => { + tcx.projection_predicates(data.item_def_id).subst(tcx, data.substs) + } + ty::Opaque(def_id, substs) => tcx.projection_predicates(def_id).subst(tcx, substs), _ => { span_bug!( obligation.cause.span, @@ -1285,32 +1293,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); } }; - debug!( - "match_projection_obligation_against_definition_bounds: \ - def_id={:?}, substs={:?}", - def_id, substs - ); - - let predicates_of = self.tcx().predicates_of(def_id); - let bounds = predicates_of.instantiate(self.tcx(), substs); - debug!( - "match_projection_obligation_against_definition_bounds: \ - bounds={:?}", - bounds - ); - let elaborated_predicates = - util::elaborate_predicates(self.tcx(), bounds.predicates.into_iter()); - let matching_bound = elaborated_predicates.filter_to_traits().find(|bound| { - self.infcx.probe(|_| { - self.match_projection( - obligation, - *bound, - placeholder_trait_predicate.trait_ref, - &placeholder_map, - snapshot, - ) - }) + let matching_bound = predicates.iter().find_map(|bound| { + if let ty::PredicateKind::Trait(bound, _) = bound.kind() { + let bound = bound.to_poly_trait_ref(); + if self.infcx.probe(|_| { + self.match_projection(obligation, bound, placeholder_trait_predicate.trait_ref) + }) { + return Some(bound); + } + } + None }); debug!( @@ -1322,13 +1315,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { None => false, Some(bound) => { // Repeat the successful match, if any, this time outside of a probe. - let result = self.match_projection( - obligation, - bound, - placeholder_trait_predicate.trait_ref, - &placeholder_map, - snapshot, - ); + let result = + self.match_projection(obligation, bound, placeholder_trait_predicate.trait_ref); assert!(result); true @@ -1341,15 +1329,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, trait_bound: ty::PolyTraitRef<'tcx>, placeholder_trait_ref: ty::TraitRef<'tcx>, - placeholder_map: &PlaceholderMap<'tcx>, - snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> bool { debug_assert!(!placeholder_trait_ref.has_escaping_bound_vars()); self.infcx .at(&obligation.cause, obligation.param_env) .sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound) .is_ok() - && self.infcx.leak_check(false, placeholder_map, snapshot).is_ok() } fn evaluate_where_clause<'o>( @@ -1754,27 +1739,26 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Vec> { // Because the types were potentially derived from // higher-ranked obligations they may reference late-bound - // regions. For example, `for<'a> Foo<&'a int> : Copy` would - // yield a type like `for<'a> &'a int`. In general, we + // regions. For example, `for<'a> Foo<&'a i32> : Copy` would + // yield a type like `for<'a> &'a i32`. In general, we // maintain the invariant that we never manipulate bound // regions, so we have to process these bound regions somehow. // // The strategy is to: // // 1. Instantiate those regions to placeholder regions (e.g., - // `for<'a> &'a int` becomes `&0 int`. - // 2. Produce something like `&'0 int : Copy` - // 3. Re-bind the regions back to `for<'a> &'a int : Copy` + // `for<'a> &'a i32` becomes `&0 i32`. + // 2. Produce something like `&'0 i32 : Copy` + // 3. Re-bind the regions back to `for<'a> &'a i32 : Copy` types - .skip_binder() + .skip_binder() // binder moved -\ .iter() .flat_map(|ty| { - // binder moved -\ let ty: ty::Binder> = ty::Binder::bind(ty); // <----/ self.infcx.commit_unconditionally(|_| { - let (skol_ty, _) = self.infcx.replace_bound_vars_with_placeholders(&ty); + let (placeholder_ty, _) = self.infcx.replace_bound_vars_with_placeholders(&ty); let Normalized { value: normalized_ty, mut obligations } = ensure_sufficient_stack(|| { project::normalize_with_depth( @@ -1782,10 +1766,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { param_env, cause.clone(), recursion_depth, - &skol_ty, + &placeholder_ty, ) }); - let skol_obligation = predicate_for_trait_def( + let placeholder_obligation = predicate_for_trait_def( self.tcx(), param_env, cause.clone(), @@ -1794,7 +1778,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { normalized_ty, &[], ); - obligations.push(skol_obligation); + obligations.push(placeholder_obligation); obligations }) }) @@ -1815,9 +1799,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, impl_def_id: DefId, obligation: &TraitObligation<'tcx>, - snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> Normalized<'tcx, SubstsRef<'tcx>> { - match self.match_impl(impl_def_id, obligation, snapshot) { + match self.match_impl(impl_def_id, obligation) { Ok(substs) => substs, Err(()) => { bug!( @@ -1833,7 +1816,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, impl_def_id: DefId, obligation: &TraitObligation<'tcx>, - snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> Result>, ()> { let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap(); @@ -1844,9 +1826,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return Err(()); } - let (skol_obligation, placeholder_map) = + let (placeholder_obligation, _) = self.infcx().replace_bound_vars_with_placeholders(&obligation.predicate); - let skol_obligation_trait_ref = skol_obligation.trait_ref; + let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref; let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id); @@ -1865,22 +1847,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!( "match_impl(impl_def_id={:?}, obligation={:?}, \ - impl_trait_ref={:?}, skol_obligation_trait_ref={:?})", - impl_def_id, obligation, impl_trait_ref, skol_obligation_trait_ref + impl_trait_ref={:?}, placeholder_obligation_trait_ref={:?})", + impl_def_id, obligation, impl_trait_ref, placeholder_obligation_trait_ref ); let InferOk { obligations, .. } = self .infcx .at(&obligation.cause, obligation.param_env) - .eq(skol_obligation_trait_ref, impl_trait_ref) + .eq(placeholder_obligation_trait_ref, impl_trait_ref) .map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{}`", e))?; nested_obligations.extend(obligations); - if let Err(e) = self.infcx.leak_check(false, &placeholder_map, snapshot) { - debug!("match_impl: failed leak check due to `{}`", e); - return Err(()); - } - if !self.intercrate && self.tcx().impl_polarity(impl_def_id) == ty::ImplPolarity::Reservation { diff --git a/src/librustc_trait_selection/traits/specialize/mod.rs b/src/librustc_trait_selection/traits/specialize/mod.rs index 2b596be954267..42901102c1076 100644 --- a/src/librustc_trait_selection/traits/specialize/mod.rs +++ b/src/librustc_trait_selection/traits/specialize/mod.rs @@ -130,7 +130,7 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, // We determine whether there's a subset relationship by: // - // - skolemizing impl1, + // - replacing bound vars with placeholders in impl1, // - assuming the where clauses for impl1, // - instantiating impl2 with fresh inference variables, // - unifying, diff --git a/src/librustc_trait_selection/traits/util.rs b/src/librustc_trait_selection/traits/util.rs index 8b5b4128e6672..d3484b8af89fd 100644 --- a/src/librustc_trait_selection/traits/util.rs +++ b/src/librustc_trait_selection/traits/util.rs @@ -302,7 +302,7 @@ pub fn get_vtable_index_of_object_method( ) -> usize { // Count number of methods preceding the one we are selecting and // add them to the total offset. - // Skip over associated types and constants. + // Skip over associated types and constants, as those aren't stored in the vtable. 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 { diff --git a/src/librustc_traits/Cargo.toml b/src/librustc_traits/Cargo.toml index e485bc2929bdb..8def98a9603d8 100644 --- a/src/librustc_traits/Cargo.toml +++ b/src/librustc_traits/Cargo.toml @@ -16,9 +16,8 @@ rustc_hir = { path = "../librustc_hir" } rustc_index = { path = "../librustc_index" } rustc_ast = { path = "../librustc_ast" } rustc_span = { path = "../librustc_span" } -chalk-ir = "0.10.0" -chalk-rust-ir = "0.10.0" -chalk-solve = "0.10.0" +chalk-ir = "0.11.0" +chalk-solve = "0.11.0" 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/chalk/db.rs b/src/librustc_traits/chalk/db.rs index a2aee9b6ef74d..235497d374098 100644 --- a/src/librustc_traits/chalk/db.rs +++ b/src/librustc_traits/chalk/db.rs @@ -6,9 +6,9 @@ //! either the `TyCtxt` (for information about types) or //! `crate::chalk::lowering` (to lower rustc types into Chalk types). -use rustc_middle::traits::{ChalkRustDefId as RustDefId, ChalkRustInterner as RustInterner}; +use rustc_middle::traits::ChalkRustInterner as RustInterner; use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; -use rustc_middle::ty::{self, AssocItemContainer, AssocKind, TyCtxt}; +use rustc_middle::ty::{self, AssocItemContainer, AssocKind, Binder, TyCtxt}; use rustc_hir::def_id::DefId; @@ -38,11 +38,8 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t fn associated_ty_data( &self, assoc_type_id: chalk_ir::AssocTypeId>, - ) -> Arc>> { - let def_id = match assoc_type_id.0 { - RustDefId::AssocTy(def_id) => def_id, - _ => bug!("Did not use `AssocTy` variant when expecting associated type."), - }; + ) -> Arc>> { + let def_id = assoc_type_id.0; let assoc_item = self.tcx.associated_item(def_id); let trait_def_id = match assoc_item.container { AssocItemContainer::TraitContainer(def_id) => def_id, @@ -63,13 +60,13 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t .map(|(wc, _)| wc.subst(self.tcx, &bound_vars)) .filter_map(|wc| LowerInto::>>>::lower_into(wc, &self.interner)).collect(); - Arc::new(chalk_rust_ir::AssociatedTyDatum { - trait_id: chalk_ir::TraitId(RustDefId::Trait(trait_def_id)), + Arc::new(chalk_solve::rust_ir::AssociatedTyDatum { + trait_id: chalk_ir::TraitId(trait_def_id), id: assoc_type_id, name: (), binders: chalk_ir::Binders::new( binders, - chalk_rust_ir::AssociatedTyDatumBound { bounds: vec![], where_clauses }, + chalk_solve::rust_ir::AssociatedTyDatumBound { bounds: vec![], where_clauses }, ), }) } @@ -77,11 +74,8 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t fn trait_datum( &self, trait_id: chalk_ir::TraitId>, - ) -> Arc>> { - let def_id = match trait_id.0 { - RustDefId::Trait(def_id) => def_id, - _ => bug!("Did not use `Trait` variant when expecting trait."), - }; + ) -> Arc>> { + let def_id = trait_id.0; let trait_def = self.tcx.trait_def(def_id); let bound_vars = bound_vars_for_item(self.tcx, def_id); @@ -94,21 +88,21 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let well_known = if self.tcx.lang_items().sized_trait().map(|t| def_id == t).unwrap_or(false) { - Some(chalk_rust_ir::WellKnownTrait::SizedTrait) + Some(chalk_solve::rust_ir::WellKnownTrait::SizedTrait) } else if self.tcx.lang_items().copy_trait().map(|t| def_id == t).unwrap_or(false) { - Some(chalk_rust_ir::WellKnownTrait::CopyTrait) + Some(chalk_solve::rust_ir::WellKnownTrait::CopyTrait) } else if self.tcx.lang_items().clone_trait().map(|t| def_id == t).unwrap_or(false) { - Some(chalk_rust_ir::WellKnownTrait::CloneTrait) + Some(chalk_solve::rust_ir::WellKnownTrait::CloneTrait) } else { None }; - Arc::new(chalk_rust_ir::TraitDatum { + Arc::new(chalk_solve::rust_ir::TraitDatum { id: trait_id, binders: chalk_ir::Binders::new( binders, - chalk_rust_ir::TraitDatumBound { where_clauses }, + chalk_solve::rust_ir::TraitDatumBound { where_clauses }, ), - flags: chalk_rust_ir::TraitFlags { + flags: chalk_solve::rust_ir::TraitFlags { auto: trait_def.has_auto_impl, marker: trait_def.is_marker, upstream: !def_id.is_local(), @@ -121,101 +115,98 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t }) } - fn struct_datum( + fn adt_datum( &self, - struct_id: chalk_ir::StructId>, - ) -> Arc>> { - match struct_id.0 { - RustDefId::Adt(adt_def_id) => { - let adt_def = self.tcx.adt_def(adt_def_id); + adt_id: chalk_ir::AdtId>, + ) -> Arc>> { + let adt_def = adt_id.0; - let bound_vars = bound_vars_for_item(self.tcx, adt_def_id); - let binders = binders_for(&self.interner, bound_vars); + let bound_vars = bound_vars_for_item(self.tcx, adt_def.did); + let binders = binders_for(&self.interner, bound_vars); - let predicates = self.tcx.predicates_of(adt_def_id).predicates; - let where_clauses: Vec<_> = predicates + let predicates = self.tcx.predicates_of(adt_def.did).predicates; + let where_clauses: Vec<_> = predicates + .into_iter() + .map(|(wc, _)| wc.subst(self.tcx, bound_vars)) + .filter_map(|wc| LowerInto::>>>::lower_into(wc, &self.interner)) + .collect(); + let fields = match adt_def.adt_kind() { + ty::AdtKind::Struct | ty::AdtKind::Union => { + let variant = adt_def.non_enum_variant(); + variant + .fields .iter() - .map(|(wc, _)| wc.subst(self.tcx, bound_vars)) - .filter_map(|wc| LowerInto::>>>::lower_into(wc, &self.interner)) - .collect(); - let fields = match adt_def.adt_kind() { - ty::AdtKind::Struct | ty::AdtKind::Union => { - let variant = adt_def.non_enum_variant(); - variant - .fields - .iter() - .map(|field| { - self.tcx - .type_of(field.did) - .subst(self.tcx, bound_vars) - .lower_into(&self.interner) - }) - .collect() - } - // FIXME(chalk): handle enums; force_impl_for requires this - ty::AdtKind::Enum => vec![], - }; - let struct_datum = Arc::new(chalk_rust_ir::StructDatum { - id: struct_id, - binders: chalk_ir::Binders::new( - binders, - chalk_rust_ir::StructDatumBound { fields, where_clauses }, - ), - flags: chalk_rust_ir::StructFlags { - upstream: !adt_def_id.is_local(), - fundamental: adt_def.is_fundamental(), - }, - }); - struct_datum - } - RustDefId::Ref(_) => Arc::new(chalk_rust_ir::StructDatum { - id: struct_id, - binders: chalk_ir::Binders::new( - chalk_ir::ParameterKinds::from( - &self.interner, - vec![ - chalk_ir::ParameterKind::Lifetime(()), - chalk_ir::ParameterKind::Ty(()), - ], - ), - chalk_rust_ir::StructDatumBound { fields: vec![], where_clauses: vec![] }, - ), - flags: chalk_rust_ir::StructFlags { upstream: false, fundamental: false }, - }), - RustDefId::Array | RustDefId::Slice => Arc::new(chalk_rust_ir::StructDatum { - id: struct_id, - binders: chalk_ir::Binders::new( - chalk_ir::ParameterKinds::from( - &self.interner, - Some(chalk_ir::ParameterKind::Ty(())), - ), - chalk_rust_ir::StructDatumBound { fields: vec![], where_clauses: vec![] }, - ), - flags: chalk_rust_ir::StructFlags { upstream: false, fundamental: false }, - }), - RustDefId::Str | RustDefId::Never | RustDefId::FnDef(_) => { - Arc::new(chalk_rust_ir::StructDatum { - id: struct_id, - binders: chalk_ir::Binders::new( - chalk_ir::ParameterKinds::new(&self.interner), - chalk_rust_ir::StructDatumBound { fields: vec![], where_clauses: vec![] }, - ), - flags: chalk_rust_ir::StructFlags { upstream: false, fundamental: false }, - }) + .map(|field| { + self.tcx + .type_of(field.did) + .subst(self.tcx, bound_vars) + .lower_into(&self.interner) + }) + .collect() } + // FIXME(chalk): handle enums; force_impl_for requires this + ty::AdtKind::Enum => vec![], + }; + let struct_datum = Arc::new(chalk_solve::rust_ir::AdtDatum { + id: adt_id, + binders: chalk_ir::Binders::new( + binders, + chalk_solve::rust_ir::AdtDatumBound { fields, where_clauses }, + ), + flags: chalk_solve::rust_ir::AdtFlags { + upstream: !adt_def.did.is_local(), + fundamental: adt_def.is_fundamental(), + }, + }); + return struct_datum; + } - _ => bug!("Used not struct variant when expecting struct variant."), - } + fn fn_def_datum( + &self, + fn_def_id: chalk_ir::FnDefId>, + ) -> Arc>> { + let def_id = fn_def_id.0; + let bound_vars = bound_vars_for_item(self.tcx, def_id); + let binders = binders_for(&self.interner, bound_vars); + + let predicates = self.tcx.predicates_defined_on(def_id).predicates; + let where_clauses: Vec<_> = predicates + .into_iter() + .map(|(wc, _)| wc.subst(self.tcx, &bound_vars)) + .filter_map(|wc| LowerInto::>>>::lower_into(wc, &self.interner)).collect(); + + let sig = self.tcx.fn_sig(def_id); + // FIXME(chalk): collect into an intermediate SmallVec here since + // we need `TypeFoldable` for `no_bound_vars` + let argument_types: Binder> = + sig.map_bound(|i| i.inputs().iter().copied().collect()); + let argument_types = argument_types + .no_bound_vars() + .expect("FIXME(chalk): late-bound fn parameters not supported in chalk") + .iter() + .map(|t| t.subst(self.tcx, &bound_vars).lower_into(&self.interner)) + .collect(); + + let return_type = sig + .output() + .no_bound_vars() + .expect("FIXME(chalk): late-bound fn parameters not supported in chalk") + .subst(self.tcx, &bound_vars) + .lower_into(&self.interner); + + let bound = + chalk_solve::rust_ir::FnDefDatumBound { argument_types, where_clauses, return_type }; + Arc::new(chalk_solve::rust_ir::FnDefDatum { + id: fn_def_id, + binders: chalk_ir::Binders::new(binders, bound), + }) } fn impl_datum( &self, impl_id: chalk_ir::ImplId>, - ) -> Arc>> { - let def_id = match impl_id.0 { - RustDefId::Impl(def_id) => def_id, - _ => bug!("Did not use `Impl` variant when expecting impl."), - }; + ) -> Arc>> { + let def_id = impl_id.0; let bound_vars = bound_vars_for_item(self.tcx, def_id); let binders = binders_for(&self.interner, bound_vars); @@ -228,15 +219,15 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t .map(|(wc, _)| wc.subst(self.tcx, bound_vars)) .filter_map(|wc| LowerInto::>>>::lower_into(wc, &self.interner)).collect(); - let value = chalk_rust_ir::ImplDatumBound { + let value = chalk_solve::rust_ir::ImplDatumBound { trait_ref: trait_ref.lower_into(&self.interner), where_clauses, }; - Arc::new(chalk_rust_ir::ImplDatum { - polarity: chalk_rust_ir::Polarity::Positive, + Arc::new(chalk_solve::rust_ir::ImplDatum { + polarity: chalk_solve::rust_ir::Polarity::Positive, binders: chalk_ir::Binders::new(binders, value), - impl_type: chalk_rust_ir::ImplType::Local, + impl_type: chalk_solve::rust_ir::ImplType::Local, associated_ty_value_ids: vec![], }) } @@ -244,12 +235,9 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t fn impls_for_trait( &self, trait_id: chalk_ir::TraitId>, - parameters: &[chalk_ir::Parameter>], + parameters: &[chalk_ir::GenericArg>], ) -> Vec>> { - let def_id: DefId = match trait_id.0 { - RustDefId::Trait(def_id) => def_id, - _ => bug!("Did not use `Trait` variant when expecting trait."), - }; + let def_id = trait_id.0; // FIXME(chalk): use TraitDef::for_each_relevant_impl, but that will // require us to be able to interconvert `Ty<'tcx>`, and we're @@ -268,32 +256,24 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t parameters[0].assert_ty_ref(&self.interner).could_match(&self.interner, &lowered_ty) }); - let impls = matched_impls - .map(|matched_impl| chalk_ir::ImplId(RustDefId::Impl(matched_impl))) - .collect(); + let impls = matched_impls.map(|matched_impl| chalk_ir::ImplId(matched_impl)).collect(); impls } fn impl_provided_for( &self, auto_trait_id: chalk_ir::TraitId>, - struct_id: chalk_ir::StructId>, + adt_id: chalk_ir::AdtId>, ) -> bool { - let trait_def_id: DefId = match auto_trait_id.0 { - RustDefId::Trait(def_id) => def_id, - _ => bug!("Did not use `Trait` variant when expecting trait."), - }; - let adt_def_id: DefId = match struct_id.0 { - RustDefId::Adt(def_id) => def_id, - _ => bug!("Did not use `Adt` variant when expecting adt."), - }; + let trait_def_id = auto_trait_id.0; + let adt_def = adt_id.0; let all_impls = self.tcx.all_impls(trait_def_id); for impl_def_id in all_impls { let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap(); let self_ty = trait_ref.self_ty(); match self_ty.kind { - ty::Adt(adt_def, _) => { - if adt_def.did == adt_def_id { + ty::Adt(impl_adt_def, _) => { + if impl_adt_def == adt_def { return true; } } @@ -305,12 +285,9 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t fn associated_ty_value( &self, - associated_ty_id: chalk_rust_ir::AssociatedTyValueId>, - ) -> Arc>> { - let def_id = match associated_ty_id.0 { - RustDefId::AssocTy(def_id) => def_id, - _ => bug!("Did not use `AssocTy` variant when expecting associated type."), - }; + associated_ty_id: chalk_solve::rust_ir::AssociatedTyValueId>, + ) -> Arc>> { + let def_id = associated_ty_id.0; let assoc_item = self.tcx.associated_item(def_id); let impl_id = match assoc_item.container { AssocItemContainer::TraitContainer(def_id) => def_id, @@ -324,12 +301,12 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let binders = binders_for(&self.interner, bound_vars); let ty = self.tcx.type_of(def_id); - Arc::new(chalk_rust_ir::AssociatedTyValue { - impl_id: chalk_ir::ImplId(RustDefId::Impl(impl_id)), - associated_ty_id: chalk_ir::AssocTypeId(RustDefId::AssocTy(def_id)), + Arc::new(chalk_solve::rust_ir::AssociatedTyValue { + impl_id: chalk_ir::ImplId(impl_id), + associated_ty_id: chalk_ir::AssocTypeId(def_id), value: chalk_ir::Binders::new( binders, - chalk_rust_ir::AssociatedTyValueBound { ty: ty.lower_into(&self.interner) }, + chalk_solve::rust_ir::AssociatedTyValueBound { ty: ty.lower_into(&self.interner) }, ), }) } @@ -347,9 +324,16 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t fn opaque_ty_data( &self, - _id: chalk_ir::OpaqueTyId>, - ) -> Arc>> { - unimplemented!() + opaque_ty_id: chalk_ir::OpaqueTyId>, + ) -> Arc>> { + // FIXME(chalk): actually lower opaque ty + let value = chalk_solve::rust_ir::OpaqueTyDatumBound { + bounds: chalk_ir::Binders::new(chalk_ir::VariableKinds::new(&self.interner), vec![]), + }; + Arc::new(chalk_solve::rust_ir::OpaqueTyDatum { + opaque_ty_id, + bound: chalk_ir::Binders::new(chalk_ir::VariableKinds::new(&self.interner), value), + }) } /// Since Chalk can't handle all Rust types currently, we have to handle @@ -357,74 +341,49 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t /// `None` and eventually this function will be removed. fn force_impl_for( &self, - well_known: chalk_rust_ir::WellKnownTrait, + well_known: chalk_solve::rust_ir::WellKnownTrait, ty: &chalk_ir::TyData>, ) -> Option { use chalk_ir::TyData::*; match well_known { - chalk_rust_ir::WellKnownTrait::SizedTrait => match ty { + chalk_solve::rust_ir::WellKnownTrait::SizedTrait => match ty { Apply(apply) => match apply.name { - chalk_ir::TypeName::Struct(chalk_ir::StructId(rust_def_id)) => { - use rustc_middle::traits::ChalkRustDefId::*; - match rust_def_id { - Never | Array | RawPtr | FnDef(_) | Ref(_) => Some(true), - - Adt(adt_def_id) => { - let adt_def = self.tcx.adt_def(adt_def_id); - match adt_def.adt_kind() { - ty::AdtKind::Struct | ty::AdtKind::Union => None, - ty::AdtKind::Enum => { - let constraint = self.tcx.adt_sized_constraint(adt_def_id); - if !constraint.0.is_empty() { - unimplemented!() - } else { - Some(true) - } - } - } - } - - Str | Slice => Some(false), - - Trait(_) | Impl(_) | AssocTy(_) => panic!(), + chalk_ir::TypeName::Adt(chalk_ir::AdtId(adt_def)) => match adt_def.adt_kind() { + ty::AdtKind::Struct | ty::AdtKind::Union => None, + ty::AdtKind::Enum => { + let constraint = self.tcx.adt_sized_constraint(adt_def.did); + if constraint.0.len() > 0 { unimplemented!() } else { Some(true) } } - } + }, _ => None, }, - Dyn(_) | Alias(_) | Placeholder(_) | Function(_) | InferenceVar(_) + Dyn(_) + | Alias(_) + | Placeholder(_) + | Function(_) + | InferenceVar(_, _) | BoundVar(_) => None, }, - chalk_rust_ir::WellKnownTrait::CopyTrait - | chalk_rust_ir::WellKnownTrait::CloneTrait => match ty { + chalk_solve::rust_ir::WellKnownTrait::CopyTrait + | chalk_solve::rust_ir::WellKnownTrait::CloneTrait => match ty { Apply(apply) => match apply.name { - chalk_ir::TypeName::Struct(chalk_ir::StructId(rust_def_id)) => { - use rustc_middle::traits::ChalkRustDefId::*; - match rust_def_id { - Never | RawPtr | Ref(_) | Str | Slice => Some(false), - FnDef(_) | Array => Some(true), - Adt(adt_def_id) => { - let adt_def = self.tcx.adt_def(adt_def_id); - match adt_def.adt_kind() { - ty::AdtKind::Struct | ty::AdtKind::Union => None, - ty::AdtKind::Enum => { - let constraint = self.tcx.adt_sized_constraint(adt_def_id); - if !constraint.0.is_empty() { - unimplemented!() - } else { - Some(true) - } - } - } - } - Trait(_) | Impl(_) | AssocTy(_) => panic!(), + chalk_ir::TypeName::Adt(chalk_ir::AdtId(adt_def)) => match adt_def.adt_kind() { + ty::AdtKind::Struct | ty::AdtKind::Union => None, + ty::AdtKind::Enum => { + let constraint = self.tcx.adt_sized_constraint(adt_def.did); + if constraint.0.len() > 0 { unimplemented!() } else { Some(true) } } - } + }, _ => None, }, - Dyn(_) | Alias(_) | Placeholder(_) | Function(_) | InferenceVar(_) + Dyn(_) + | Alias(_) + | Placeholder(_) + | Function(_) + | InferenceVar(_, _) | BoundVar(_) => None, }, - chalk_rust_ir::WellKnownTrait::DropTrait => None, + chalk_solve::rust_ir::WellKnownTrait::DropTrait => None, } } @@ -437,37 +396,33 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t fn well_known_trait_id( &self, - well_known_trait: chalk_rust_ir::WellKnownTrait, + well_known_trait: chalk_solve::rust_ir::WellKnownTrait, ) -> Option>> { - use chalk_rust_ir::WellKnownTrait::*; + use chalk_solve::rust_ir::WellKnownTrait::*; let t = match well_known_trait { - SizedTrait => self - .tcx - .lang_items() - .sized_trait() - .map(|t| chalk_ir::TraitId(RustDefId::Trait(t))) - .unwrap(), - CopyTrait => self - .tcx - .lang_items() - .copy_trait() - .map(|t| chalk_ir::TraitId(RustDefId::Trait(t))) - .unwrap(), - CloneTrait => self - .tcx - .lang_items() - .clone_trait() - .map(|t| chalk_ir::TraitId(RustDefId::Trait(t))) - .unwrap(), - DropTrait => self - .tcx - .lang_items() - .drop_trait() - .map(|t| chalk_ir::TraitId(RustDefId::Trait(t))) - .unwrap(), + SizedTrait => { + self.tcx.lang_items().sized_trait().map(|t| chalk_ir::TraitId(t)).unwrap() + } + CopyTrait => self.tcx.lang_items().copy_trait().map(|t| chalk_ir::TraitId(t)).unwrap(), + CloneTrait => { + self.tcx.lang_items().clone_trait().map(|t| chalk_ir::TraitId(t)).unwrap() + } + DropTrait => self.tcx.lang_items().drop_trait().map(|t| chalk_ir::TraitId(t)).unwrap(), }; Some(t) } + + fn is_object_safe(&self, trait_id: chalk_ir::TraitId>) -> bool { + self.tcx.is_object_safe(trait_id.0) + } + + fn hidden_opaque_type( + &self, + _id: chalk_ir::OpaqueTyId>, + ) -> chalk_ir::Ty> { + // FIXME(chalk): actually get hidden ty + self.tcx.mk_ty(ty::Tuple(self.tcx.intern_substs(&[]))).lower_into(&self.interner) + } } /// Creates a `InternalSubsts` that maps each generic parameter to a higher-ranked @@ -505,13 +460,17 @@ fn bound_vars_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> { fn binders_for<'tcx>( interner: &RustInterner<'tcx>, bound_vars: SubstsRef<'tcx>, -) -> chalk_ir::ParameterKinds> { - chalk_ir::ParameterKinds::from( +) -> chalk_ir::VariableKinds> { + chalk_ir::VariableKinds::from( interner, bound_vars.iter().map(|arg| match arg.unpack() { - ty::subst::GenericArgKind::Lifetime(_re) => chalk_ir::ParameterKind::Lifetime(()), - ty::subst::GenericArgKind::Type(_ty) => chalk_ir::ParameterKind::Ty(()), - ty::subst::GenericArgKind::Const(_const) => chalk_ir::ParameterKind::Ty(()), + ty::subst::GenericArgKind::Lifetime(_re) => chalk_ir::VariableKind::Lifetime, + ty::subst::GenericArgKind::Type(_ty) => { + chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General) + } + ty::subst::GenericArgKind::Const(c) => { + chalk_ir::VariableKind::Const(c.ty.lower_into(interner)) + } }), ) } diff --git a/src/librustc_traits/chalk/lowering.rs b/src/librustc_traits/chalk/lowering.rs index c9dd06e9f1ba2..5546a8db53395 100644 --- a/src/librustc_traits/chalk/lowering.rs +++ b/src/librustc_traits/chalk/lowering.rs @@ -32,8 +32,7 @@ //! variables from the current `Binder`. use rustc_middle::traits::{ - ChalkEnvironmentAndGoal, ChalkEnvironmentClause, ChalkRustDefId as RustDefId, - ChalkRustInterner as RustInterner, + ChalkEnvironmentAndGoal, ChalkEnvironmentClause, ChalkRustInterner as RustInterner, }; use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; @@ -62,7 +61,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Substitution>> for Subst impl<'tcx> LowerInto<'tcx, chalk_ir::AliasTy>> for ty::ProjectionTy<'tcx> { fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::AliasTy> { chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy { - associated_ty_id: chalk_ir::AssocTypeId(RustDefId::AssocTy(self.item_def_id)), + associated_ty_id: chalk_ir::AssocTypeId(self.item_def_id), substitution: self.substs.lower_into(interner), }) } @@ -98,8 +97,30 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment None, + ty::PredicateKind::RegionOutlives(predicate) => { + let (predicate, binders, _named_regions) = + collect_bound_vars(interner, interner.tcx, predicate); + + Some( + chalk_ir::ProgramClauseData::ForAll(chalk_ir::Binders::new( + binders, + chalk_ir::ProgramClauseImplication { + consequence: chalk_ir::DomainGoal::Holds( + chalk_ir::WhereClause::LifetimeOutlives( + chalk_ir::LifetimeOutlives { + a: predicate.0.lower_into(interner), + b: predicate.1.lower_into(interner), + }, + ), + ), + conditions: chalk_ir::Goals::new(interner), + priority: chalk_ir::ClausePriority::High, + }, + )) + .intern(interner), + ) + } + // FIXME(chalk): need to add TypeOutlives ty::PredicateKind::TypeOutlives(_) => None, ty::PredicateKind::Projection(predicate) => { let (predicate, binders, _named_regions) = @@ -157,30 +178,36 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData>> for ty::Predi fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::GoalData> { match self.kind() { ty::PredicateKind::Trait(predicate, _) => predicate.lower_into(interner), - // FIXME(chalk): we need to register constraints. - ty::PredicateKind::RegionOutlives(_predicate) => { - chalk_ir::GoalData::All(chalk_ir::Goals::new(interner)) + ty::PredicateKind::RegionOutlives(predicate) => { + let (predicate, binders, _named_regions) = + collect_bound_vars(interner, interner.tcx, predicate); + + chalk_ir::GoalData::Quantified( + chalk_ir::QuantifierKind::ForAll, + chalk_ir::Binders::new( + binders, + chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds( + chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives { + a: predicate.0.lower_into(interner), + b: predicate.1.lower_into(interner), + }), + )) + .intern(interner), + ), + ) } + // FIXME(chalk): TypeOutlives ty::PredicateKind::TypeOutlives(_predicate) => { chalk_ir::GoalData::All(chalk_ir::Goals::new(interner)) } ty::PredicateKind::Projection(predicate) => predicate.lower_into(interner), ty::PredicateKind::WellFormed(arg) => match arg.unpack() { GenericArgKind::Type(ty) => match ty.kind { - // These types are always WF. - ty::Str | ty::Placeholder(..) | ty::Error(_) | ty::Never => { - chalk_ir::GoalData::All(chalk_ir::Goals::new(interner)) - } + // FIXME(chalk): In Chalk, a placeholder is WellFormed if it + // `FromEnv`. However, when we "lower" Params, we don't update + // the environment. + ty::Placeholder(..) => chalk_ir::GoalData::All(chalk_ir::Goals::new(interner)), - // FIXME(chalk): Well-formed only if ref lifetime outlives type - ty::Ref(..) => chalk_ir::GoalData::All(chalk_ir::Goals::new(interner)), - - ty::Param(..) => panic!("No Params expected."), - - // FIXME(chalk) -- ultimately I think this is what we - // want to do, and we just have rules for how to prove - // `WellFormed` for everything above, instead of - // inlining a bit the rules of the proof here. _ => chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::WellFormed( chalk_ir::WellFormed::Ty(ty.lower_into(interner)), )), @@ -192,12 +219,15 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData>> for ty::Predi GenericArgKind::Lifetime(lt) => bug!("unexpect well formed predicate: {:?}", lt), }, + ty::PredicateKind::ObjectSafe(t) => chalk_ir::GoalData::DomainGoal( + chalk_ir::DomainGoal::ObjectSafe(chalk_ir::TraitId(*t)), + ), + // FIXME(chalk): other predicates // // We can defer this, but ultimately we'll want to express // some of these in terms of chalk operations. - ty::PredicateKind::ObjectSafe(..) - | ty::PredicateKind::ClosureKind(..) + ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Subtype(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) => { @@ -212,7 +242,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::TraitRef>> { fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::TraitRef> { chalk_ir::TraitRef { - trait_id: chalk_ir::TraitId(RustDefId::Trait(self.def_id)), + trait_id: chalk_ir::TraitId(self.def_id), substitution: self.substs.lower_into(interner), } } @@ -274,7 +304,8 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { use TyKind::*; let empty = || chalk_ir::Substitution::empty(interner); - let struct_ty = |def_id| chalk_ir::TypeName::Struct(chalk_ir::StructId(def_id)); + let struct_ty = + |def_id| chalk_ir::TypeName::Adt(chalk_ir::AdtId(interner.tcx.adt_def(def_id))); let apply = |name, substitution| { TyData::Apply(chalk_ir::ApplicationTy { name, substitution }).intern(interner) }; @@ -305,39 +336,72 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { ast::FloatTy::F32 => float(chalk_ir::FloatTy::F32), ast::FloatTy::F64 => float(chalk_ir::FloatTy::F64), }, - Adt(def, substs) => { - apply(struct_ty(RustDefId::Adt(def.did)), substs.lower_into(interner)) - } + Adt(def, substs) => apply(struct_ty(def.did), substs.lower_into(interner)), Foreign(_def_id) => unimplemented!(), - Str => apply(struct_ty(RustDefId::Str), empty()), - Array(ty, _) => apply( - struct_ty(RustDefId::Array), - chalk_ir::Substitution::from1( - interner, - chalk_ir::ParameterKind::Ty(ty.lower_into(interner)).intern(interner), - ), - ), + Str => apply(chalk_ir::TypeName::Str, empty()), + Array(ty, len) => { + let value = match len.val { + ty::ConstKind::Value(val) => { + chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { interned: val }) + } + ty::ConstKind::Bound(db, bound) => { + chalk_ir::ConstValue::BoundVar(chalk_ir::BoundVar::new( + chalk_ir::DebruijnIndex::new(db.as_u32()), + bound.index(), + )) + } + _ => unimplemented!("Const not implemented. {:?}", len.val), + }; + apply( + chalk_ir::TypeName::Array, + chalk_ir::Substitution::from( + interner, + &[ + chalk_ir::GenericArgData::Ty(ty.lower_into(interner)).intern(interner), + chalk_ir::GenericArgData::Const( + chalk_ir::ConstData { ty: len.ty.lower_into(interner), value } + .intern(interner), + ) + .intern(interner), + ], + ), + ) + } Slice(ty) => apply( - struct_ty(RustDefId::Slice), + chalk_ir::TypeName::Slice, chalk_ir::Substitution::from1( interner, - chalk_ir::ParameterKind::Ty(ty.lower_into(interner)).intern(interner), + chalk_ir::GenericArgData::Ty(ty.lower_into(interner)).intern(interner), ), ), - RawPtr(_) => apply(struct_ty(RustDefId::RawPtr), empty()), - Ref(region, ty, mutability) => apply( - struct_ty(RustDefId::Ref(mutability)), - chalk_ir::Substitution::from( - interner, - [ - chalk_ir::ParameterKind::Lifetime(region.lower_into(interner)) - .intern(interner), - chalk_ir::ParameterKind::Ty(ty.lower_into(interner)).intern(interner), - ] - .iter(), - ), + RawPtr(ptr) => { + let name = match ptr.mutbl { + ast::Mutability::Mut => chalk_ir::TypeName::Raw(chalk_ir::Mutability::Mut), + ast::Mutability::Not => chalk_ir::TypeName::Raw(chalk_ir::Mutability::Not), + }; + apply(name, chalk_ir::Substitution::from1(interner, ptr.ty.lower_into(interner))) + } + Ref(region, ty, mutability) => { + let name = match mutability { + ast::Mutability::Mut => chalk_ir::TypeName::Ref(chalk_ir::Mutability::Mut), + ast::Mutability::Not => chalk_ir::TypeName::Ref(chalk_ir::Mutability::Not), + }; + apply( + name, + chalk_ir::Substitution::from( + interner, + &[ + chalk_ir::GenericArgData::Lifetime(region.lower_into(interner)) + .intern(interner), + chalk_ir::GenericArgData::Ty(ty.lower_into(interner)).intern(interner), + ], + ), + ) + } + FnDef(def_id, substs) => apply( + chalk_ir::TypeName::FnDef(chalk_ir::FnDefId(def_id)), + substs.lower_into(interner), ), - FnDef(def_id, _) => apply(struct_ty(RustDefId::FnDef(def_id)), empty()), FnPtr(sig) => { let (inputs_and_outputs, binders, _named_regions) = collect_bound_vars(interner, interner.tcx, &sig.inputs_and_output()); @@ -346,22 +410,32 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { substitution: chalk_ir::Substitution::from( interner, inputs_and_outputs.iter().map(|ty| { - chalk_ir::ParameterKind::Ty(ty.lower_into(interner)).intern(interner) + chalk_ir::GenericArgData::Ty(ty.lower_into(interner)).intern(interner) }), ), }) .intern(interner) } - Dynamic(_, _) => unimplemented!(), + // FIXME(chalk): add region + Dynamic(predicates, _region) => { + TyData::Dyn(chalk_ir::DynTy { bounds: predicates.lower_into(interner) }) + .intern(interner) + } Closure(_def_id, _) => unimplemented!(), Generator(_def_id, _substs, _) => unimplemented!(), GeneratorWitness(_) => unimplemented!(), - Never => apply(struct_ty(RustDefId::Never), empty()), + Never => apply(chalk_ir::TypeName::Never, empty()), Tuple(substs) => { apply(chalk_ir::TypeName::Tuple(substs.len()), substs.lower_into(interner)) } Projection(proj) => TyData::Alias(proj.lower_into(interner)).intern(interner), - Opaque(_def_id, _substs) => unimplemented!(), + Opaque(def_id, substs) => { + TyData::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy { + opaque_ty_id: chalk_ir::OpaqueTyId(def_id), + substitution: substs.lower_into(interner), + })) + .intern(interner) + } // This should have been done eagerly prior to this, and all Params // should have been substituted to placeholders Param(_) => panic!("Lowering Param when not expected."), @@ -376,7 +450,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { }) .intern(interner), Infer(_infer) => unimplemented!(), - Error(_) => unimplemented!(), + Error(_) => apply(chalk_ir::TypeName::Error, empty()), } } } @@ -401,6 +475,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Lifetime>> for Region<'t ty::BrEnv => unimplemented!(), }, ReFree(_) => unimplemented!(), + // FIXME(chalk): need to handle ReStatic ReStatic => unimplemented!(), ReVar(_) => unimplemented!(), RePlaceholder(placeholder_region) => { @@ -411,21 +486,22 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Lifetime>> for Region<'t .intern(interner) } ReEmpty(_) => unimplemented!(), + // FIXME(chalk): need to handle ReErased ReErased => unimplemented!(), } } } -impl<'tcx> LowerInto<'tcx, chalk_ir::Parameter>> for GenericArg<'tcx> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::Parameter> { +impl<'tcx> LowerInto<'tcx, chalk_ir::GenericArg>> for GenericArg<'tcx> { + fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::GenericArg> { match self.unpack() { ty::subst::GenericArgKind::Type(ty) => { - chalk_ir::ParameterKind::Ty(ty.lower_into(interner)) + chalk_ir::GenericArgData::Ty(ty.lower_into(interner)) } ty::subst::GenericArgKind::Lifetime(lifetime) => { - chalk_ir::ParameterKind::Lifetime(lifetime.lower_into(interner)) + chalk_ir::GenericArgData::Lifetime(lifetime.lower_into(interner)) } - ty::subst::GenericArgKind::Const(_) => chalk_ir::ParameterKind::Ty( + ty::subst::GenericArgKind::Const(_) => chalk_ir::GenericArgData::Ty( chalk_ir::TyData::Apply(chalk_ir::ApplicationTy { name: chalk_ir::TypeName::Tuple(0), substitution: chalk_ir::Substitution::empty(interner), @@ -458,7 +534,18 @@ impl<'tcx> LowerInto<'tcx, Option None, + ty::PredicateKind::RegionOutlives(predicate) => { + let (predicate, binders, _named_regions) = + collect_bound_vars(interner, interner.tcx, predicate); + + Some(chalk_ir::Binders::new( + binders, + chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives { + a: predicate.0.lower_into(interner), + b: predicate.1.lower_into(interner), + }), + )) + } ty::PredicateKind::TypeOutlives(_predicate) => None, ty::PredicateKind::Projection(_predicate) => None, ty::PredicateKind::WellFormed(_ty) => None, @@ -472,6 +559,39 @@ impl<'tcx> LowerInto<'tcx, Option LowerInto<'tcx, chalk_ir::Binders>>> + for Binder<&'tcx ty::List>> +{ + fn lower_into( + self, + interner: &RustInterner<'tcx>, + ) -> chalk_ir::Binders>> { + let (predicates, binders, _named_regions) = + collect_bound_vars(interner, interner.tcx, &self); + let where_clauses = predicates.into_iter().map(|predicate| match predicate { + ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef { def_id, substs }) => { + chalk_ir::Binders::new( + chalk_ir::VariableKinds::new(interner), + chalk_ir::WhereClause::Implemented(chalk_ir::TraitRef { + trait_id: chalk_ir::TraitId(def_id), + substitution: substs.lower_into(interner), + }), + ) + } + ty::ExistentialPredicate::Projection(_predicate) => unimplemented!(), + ty::ExistentialPredicate::AutoTrait(def_id) => chalk_ir::Binders::new( + chalk_ir::VariableKinds::new(interner), + chalk_ir::WhereClause::Implemented(chalk_ir::TraitRef { + trait_id: chalk_ir::TraitId(def_id), + substitution: chalk_ir::Substitution::empty(interner), + }), + ), + }); + let value = chalk_ir::QuantifiedWhereClauses::from(interner, where_clauses); + chalk_ir::Binders::new(binders, value) + } +} + /// To collect bound vars, we have to do two passes. In the first pass, we /// collect all `BoundRegion`s and `ty::Bound`s. In the second pass, we then /// replace `BrNamed` into `BrAnon`. The two separate passes are important, @@ -485,7 +605,7 @@ crate fn collect_bound_vars<'a, 'tcx, T: TypeFoldable<'tcx>>( interner: &RustInterner<'tcx>, tcx: TyCtxt<'tcx>, ty: &'a Binder, -) -> (T, chalk_ir::ParameterKinds>, BTreeMap) { +) -> (T, chalk_ir::VariableKinds>, BTreeMap) { let mut bound_vars_collector = BoundVarsCollector::new(); ty.skip_binder().visit_with(&mut bound_vars_collector); let mut parameters = bound_vars_collector.parameters; @@ -500,25 +620,25 @@ crate fn collect_bound_vars<'a, 'tcx, T: TypeFoldable<'tcx>>( let new_ty = ty.skip_binder().fold_with(&mut bound_var_substitutor); for var in named_parameters.values() { - parameters.insert(*var, chalk_ir::ParameterKind::Lifetime(())); + parameters.insert(*var, chalk_ir::VariableKind::Lifetime); } (0..parameters.len()).for_each(|i| { parameters.get(&(i as u32)).expect("Skipped bound var index."); }); - let binders = chalk_ir::ParameterKinds::from(interner, parameters.into_iter().map(|(_, v)| v)); + let binders = chalk_ir::VariableKinds::from(interner, parameters.into_iter().map(|(_, v)| v)); (new_ty, binders, named_parameters) } -crate struct BoundVarsCollector { +crate struct BoundVarsCollector<'tcx> { binder_index: ty::DebruijnIndex, - crate parameters: BTreeMap>, + crate parameters: BTreeMap>>, crate named_parameters: Vec, } -impl BoundVarsCollector { +impl<'tcx> BoundVarsCollector<'tcx> { crate fn new() -> Self { BoundVarsCollector { binder_index: ty::INNERMOST, @@ -528,7 +648,7 @@ impl BoundVarsCollector { } } -impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector { +impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { fn visit_binder>(&mut self, t: &Binder) -> bool { self.binder_index.shift_in(1); let result = t.super_visit_with(self); @@ -541,11 +661,12 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector { ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => { match self.parameters.entry(bound_ty.var.as_u32()) { Entry::Vacant(entry) => { - entry.insert(chalk_ir::ParameterKind::Ty(())); - } - Entry::Occupied(entry) => { - entry.get().assert_ty_ref(); + entry.insert(chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General)); } + Entry::Occupied(entry) => match entry.get() { + chalk_ir::VariableKind::Ty(_) => {} + _ => panic!(), + }, } } @@ -566,11 +687,12 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector { ty::BoundRegion::BrAnon(var) => match self.parameters.entry(*var) { Entry::Vacant(entry) => { - entry.insert(chalk_ir::ParameterKind::Lifetime(())); - } - Entry::Occupied(entry) => { - entry.get().assert_lifetime_ref(); + entry.insert(chalk_ir::VariableKind::Lifetime); } + Entry::Occupied(entry) => match entry.get() { + chalk_ir::VariableKind::Lifetime => {} + _ => panic!(), + }, }, ty::BrEnv => unimplemented!(), diff --git a/src/librustc_traits/chalk/mod.rs b/src/librustc_traits/chalk/mod.rs index 4e635b9db0901..6f657be0908b4 100644 --- a/src/librustc_traits/chalk/mod.rs +++ b/src/librustc_traits/chalk/mod.rs @@ -22,7 +22,7 @@ use rustc_middle::ty::{ use rustc_infer::infer::canonical::{ Canonical, CanonicalVarValues, Certainty, QueryRegionConstraints, QueryResponse, }; -use rustc_infer::traits::{self, ChalkCanonicalGoal, ChalkRustDefId as RustDefId}; +use rustc_infer::traits::{self, ChalkCanonicalGoal}; use crate::chalk::db::RustIrDatabase as ChalkRustIrDatabase; use crate::chalk::lowering::{LowerInto, ParamsSubstitutor}; @@ -55,25 +55,23 @@ crate fn evaluate_goal<'tcx>( CanonicalVarKind::PlaceholderTy(_ty) => unimplemented!(), CanonicalVarKind::PlaceholderRegion(_ui) => unimplemented!(), CanonicalVarKind::Ty(ty) => match ty { - CanonicalTyVarKind::General(ui) => { - chalk_ir::ParameterKind::Ty(chalk_ir::UniverseIndex { - counter: ui.index(), - }) - } - CanonicalTyVarKind::Int | CanonicalTyVarKind::Float => { - // FIXME(chalk) - this is actually really important - // These variable kinds put some limits on the - // types that can be substituted (floats or ints). - // While it's unclear exactly the design here, we - // probably want some way to "register" these. - chalk_ir::ParameterKind::Ty(chalk_ir::UniverseIndex::root()) - } + CanonicalTyVarKind::General(ui) => chalk_ir::WithKind::new( + chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General), + chalk_ir::UniverseIndex { counter: ui.index() }, + ), + CanonicalTyVarKind::Int => chalk_ir::WithKind::new( + chalk_ir::VariableKind::Ty(chalk_ir::TyKind::Integer), + chalk_ir::UniverseIndex::root(), + ), + CanonicalTyVarKind::Float => chalk_ir::WithKind::new( + chalk_ir::VariableKind::Ty(chalk_ir::TyKind::Float), + chalk_ir::UniverseIndex::root(), + ), }, - CanonicalVarKind::Region(ui) => { - chalk_ir::ParameterKind::Lifetime(chalk_ir::UniverseIndex { - counter: ui.index(), - }) - } + CanonicalVarKind::Region(ui) => chalk_ir::WithKind::new( + chalk_ir::VariableKind::Lifetime, + chalk_ir::UniverseIndex { counter: ui.index() }, + ), CanonicalVarKind::Const(_ui) => unimplemented!(), CanonicalVarKind::PlaceholderConst(_pc) => unimplemented!(), }), @@ -101,18 +99,14 @@ crate fn evaluate_goal<'tcx>( // essentially inverse of lowering a `GenericArg`. let _data = p.data(&interner); match _data { - chalk_ir::ParameterKind::Ty(_t) => { + chalk_ir::GenericArgData::Ty(_t) => { use chalk_ir::TyData; use rustc_ast::ast; let _data = _t.data(&interner); let kind = match _data { TyData::Apply(_application_ty) => match _application_ty.name { - chalk_ir::TypeName::Struct(_struct_id) => match _struct_id.0 { - RustDefId::Array => unimplemented!(), - RustDefId::Slice => unimplemented!(), - _ => unimplemented!(), - }, + chalk_ir::TypeName::Adt(_struct_id) => unimplemented!(), chalk_ir::TypeName::Scalar(scalar) => match scalar { chalk_ir::Scalar::Bool => ty::Bool, chalk_ir::Scalar::Char => ty::Char, @@ -137,7 +131,14 @@ crate fn evaluate_goal<'tcx>( chalk_ir::FloatTy::F64 => ty::Float(ast::FloatTy::F64), }, }, + chalk_ir::TypeName::Array => unimplemented!(), + chalk_ir::TypeName::FnDef(_) => unimplemented!(), + chalk_ir::TypeName::Never => unimplemented!(), chalk_ir::TypeName::Tuple(_size) => unimplemented!(), + chalk_ir::TypeName::Slice => unimplemented!(), + chalk_ir::TypeName::Raw(_) => unimplemented!(), + chalk_ir::TypeName::Ref(_) => unimplemented!(), + chalk_ir::TypeName::Str => unimplemented!(), chalk_ir::TypeName::OpaqueType(_ty) => unimplemented!(), chalk_ir::TypeName::AssociatedType(_assoc_ty) => unimplemented!(), chalk_ir::TypeName::Error => unimplemented!(), @@ -154,14 +155,14 @@ crate fn evaluate_goal<'tcx>( kind: ty::BoundTyKind::Anon, }, ), - TyData::InferenceVar(_) => unimplemented!(), + TyData::InferenceVar(_, _) => unimplemented!(), TyData::Dyn(_) => unimplemented!(), }; let _ty: Ty<'_> = tcx.mk_ty(kind); let _arg: GenericArg<'_> = _ty.into(); var_values.push(_arg); } - chalk_ir::ParameterKind::Lifetime(_l) => { + chalk_ir::GenericArgData::Lifetime(_l) => { let _data = _l.data(&interner); let _lifetime: Region<'_> = match _data { chalk_ir::LifetimeData::BoundVar(_var) => { @@ -179,6 +180,7 @@ crate fn evaluate_goal<'tcx>( let _arg: GenericArg<'_> = _lifetime.into(); var_values.push(_arg); } + chalk_ir::GenericArgData::Const(_) => unimplemented!(), } }); let sol = Canonical { @@ -197,7 +199,6 @@ crate fn evaluate_goal<'tcx>( .map(|s| match s { Solution::Unique(_subst) => { // FIXME(chalk): handle constraints - assert!(_subst.value.constraints.is_empty()); make_solution(_subst.value.subst) } Solution::Ambig(_guidance) => { diff --git a/src/librustc_ty/needs_drop.rs b/src/librustc_ty/needs_drop.rs index 439bec1702eae..7880c09c2ad81 100644 --- a/src/librustc_ty/needs_drop.rs +++ b/src/librustc_ty/needs_drop.rs @@ -91,7 +91,7 @@ where for component in components { match component.kind { - _ if component.is_copy_modulo_regions(tcx, self.param_env, DUMMY_SP) => (), + _ if component.is_copy_modulo_regions(tcx.at(DUMMY_SP), self.param_env) => (), ty::Closure(_, substs) => { for upvar_ty in substs.as_closure().upvar_tys() { diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs index cf70a845af0aa..595992d01dd2d 100644 --- a/src/librustc_ty/ty.rs +++ b/src/librustc_ty/ty.rs @@ -1,8 +1,10 @@ use rustc_data_structures::svh::Svh; use rustc_hir as hir; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; +use rustc_infer::traits::util; use rustc_middle::hir::map as hir_map; -use rustc_middle::ty::subst::Subst; +use rustc_middle::ty::subst::{InternalSubsts, Subst}; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness}; use rustc_session::CrateDisambiguator; use rustc_span::symbol::Symbol; @@ -365,6 +367,133 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync { fn_like.asyncness() } +/// For associated types we allow bounds written on the associated type +/// (`type X: Trait`) to be used as candidates. We also allow the same bounds +/// when desugared as bounds on the trait `where Self::X: Trait`. +/// +/// Note that this filtering is done with the items identity substs to +/// simplify checking that these bounds are met in impls. This means that +/// a bound such as `for<'b> >::U: Clone` can't be used, as in +/// `hr-associated-type-bound-1.rs`. +fn associated_type_projection_predicates( + tcx: TyCtxt<'_>, + assoc_item_def_id: DefId, +) -> &'_ ty::List> { + let generic_trait_bounds = tcx.predicates_of(assoc_item_def_id); + // We include predicates from the trait as well to handle + // `where Self::X: Trait`. + let item_bounds = generic_trait_bounds.instantiate_identity(tcx); + let item_predicates = util::elaborate_predicates(tcx, item_bounds.predicates.into_iter()); + + let assoc_item_ty = ty::ProjectionTy { + item_def_id: assoc_item_def_id, + substs: InternalSubsts::identity_for_item(tcx, assoc_item_def_id), + }; + + let predicates = item_predicates.filter_map(|obligation| { + let pred = obligation.predicate; + match pred.kind() { + ty::PredicateKind::Trait(tr, _) => { + if let ty::Projection(p) = tr.skip_binder().self_ty().kind { + if p == assoc_item_ty { + return Some(pred); + } + } + } + ty::PredicateKind::Projection(proj) => { + if let ty::Projection(p) = proj.skip_binder().projection_ty.self_ty().kind { + if p == assoc_item_ty { + return Some(pred); + } + } + } + ty::PredicateKind::TypeOutlives(outlives) => { + if let ty::Projection(p) = outlives.skip_binder().0.kind { + if p == assoc_item_ty { + return Some(pred); + } + } + } + _ => {} + } + None + }); + + let result = tcx.mk_predicates(predicates); + debug!( + "associated_type_projection_predicates({}) = {:?}", + tcx.def_path_str(assoc_item_def_id), + result + ); + result +} + +/// Opaque types don't have the same issues as associated types: the only +/// predicates on an opaque type (excluding those it inherits from its parent +/// item) should be of the form we're expecting. +fn opaque_type_projection_predicates( + tcx: TyCtxt<'_>, + def_id: DefId, +) -> &'_ ty::List> { + let substs = InternalSubsts::identity_for_item(tcx, def_id); + + let bounds = tcx.predicates_of(def_id); + let predicates = + util::elaborate_predicates(tcx, bounds.predicates.into_iter().map(|&(pred, _)| pred)); + + let filtered_predicates = predicates.filter_map(|obligation| { + let pred = obligation.predicate; + match pred.kind() { + ty::PredicateKind::Trait(tr, _) => { + if let ty::Opaque(opaque_def_id, opaque_substs) = tr.skip_binder().self_ty().kind { + if opaque_def_id == def_id && opaque_substs == substs { + return Some(pred); + } + } + } + ty::PredicateKind::Projection(proj) => { + if let ty::Opaque(opaque_def_id, opaque_substs) = + proj.skip_binder().projection_ty.self_ty().kind + { + if opaque_def_id == def_id && opaque_substs == substs { + return Some(pred); + } + } + } + ty::PredicateKind::TypeOutlives(outlives) => { + if let ty::Opaque(opaque_def_id, opaque_substs) = outlives.skip_binder().0.kind { + if opaque_def_id == def_id && opaque_substs == substs { + return Some(pred); + } + } else { + // These can come from elaborating other predicates + return None; + } + } + // These can come from elaborating other predicates + ty::PredicateKind::RegionOutlives(_) => return None, + _ => {} + } + tcx.sess.delay_span_bug( + obligation.cause.span(tcx), + &format!("unexpected predicate {:?} on opaque type", pred), + ); + None + }); + + let result = tcx.mk_predicates(filtered_predicates); + debug!("opaque_type_projection_predicates({}) = {:?}", tcx.def_path_str(def_id), result); + result +} + +fn projection_predicates(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List> { + match tcx.def_kind(def_id) { + DefKind::AssocTy => associated_type_projection_predicates(tcx, def_id), + DefKind::OpaqueTy => opaque_type_projection_predicates(tcx, def_id), + k => bug!("projection_predicates called on {}", k.descr(def_id)), + } +} + pub fn provide(providers: &mut ty::query::Providers<'_>) { *providers = ty::query::Providers { asyncness, @@ -381,6 +510,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { instance_def_size_estimate, issue33140_self_ty, impl_defaultness, + projection_predicates, ..*providers }; } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 7cdcb2face823..1b08bf2fc7710 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -8,8 +8,7 @@ use crate::collect::PlaceholderHirTyCollector; use crate::middle::resolve_lifetime as rl; use crate::require_c_abi_if_c_variadic; -use rustc_ast::ast::ParamKindOrd; -use rustc_ast::util::lev_distance::find_best_match_for_name; +use rustc_ast::{ast::ParamKindOrd, util::lev_distance::find_best_match_for_name}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::ErrorReported; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, FatalError}; @@ -27,7 +26,7 @@ use rustc_middle::ty::{GenericParamDef, GenericParamDefKind}; 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, Ident, Symbol}; +use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{MultiSpan, Span, DUMMY_SP}; use rustc_target::spec::abi; use rustc_trait_selection::traits; @@ -475,7 +474,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// Report an error that a generic argument did not match the generic parameter that was /// expected. - fn generic_arg_mismatch_err(sess: &Session, arg: &GenericArg<'_>, kind: &'static str) { + fn generic_arg_mismatch_err( + sess: &Session, + arg: &GenericArg<'_>, + kind: &'static str, + help: Option<&str>, + ) { let mut err = struct_span_err!( sess, arg.span(), @@ -503,6 +507,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let (first, last) = if kind_ord < arg_ord { (kind, arg.descr()) } else { (arg.descr(), kind) }; err.note(&format!("{} arguments must be provided before {} arguments", first, last)); + + if let Some(help) = help { + err.help(help); + } err.emit(); } @@ -648,7 +656,60 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if arg_count.correct.is_ok() && arg_count.explicit_late_bound == ExplicitLateBound::No { - Self::generic_arg_mismatch_err(tcx.sess, arg, kind.descr()); + // We're going to iterate over the parameters to sort them out, and + // show that order to the user as a possible order for the parameters + let mut param_types_present = defs + .params + .clone() + .into_iter() + .map(|param| { + ( + match param.kind { + GenericParamDefKind::Lifetime => { + ParamKindOrd::Lifetime + } + GenericParamDefKind::Type { .. } => { + ParamKindOrd::Type + } + GenericParamDefKind::Const => { + ParamKindOrd::Const + } + }, + param, + ) + }) + .collect::>(); + param_types_present.sort_by_key(|(ord, _)| *ord); + let (mut param_types_present, ordered_params): ( + Vec, + Vec, + ) = param_types_present.into_iter().unzip(); + param_types_present.dedup(); + + Self::generic_arg_mismatch_err( + tcx.sess, + arg, + kind.descr(), + Some(&format!( + "reorder the arguments: {}: `<{}>`", + param_types_present + .into_iter() + .map(|ord| format!("{}s", ord.to_string())) + .collect::>() + .join(", then "), + ordered_params + .into_iter() + .filter_map(|param| { + if param.name == kw::SelfUpper { + None + } else { + Some(param.name.to_string()) + } + }) + .collect::>() + .join(", ") + )), + ); } // We've reported the error, but we want to make sure that this @@ -680,7 +741,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { assert_eq!(kind, "lifetime"); let provided = force_infer_lt.expect("lifetimes ought to have been inferred"); - Self::generic_arg_mismatch_err(tcx.sess, provided, kind); + Self::generic_arg_mismatch_err(tcx.sess, provided, kind, None); } break; @@ -1394,13 +1455,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // That is, consider this case: // // ``` - // trait SubTrait: SuperTrait { } + // trait SubTrait: SuperTrait { } // trait SuperTrait { type T; } // // ... B: SubTrait ... // ``` // - // We want to produce `>::T == foo`. + // We want to produce `>::T == foo`. // Find any late-bound regions declared in `ty` that are not // declared in the trait-ref. These are not well-formed. @@ -2787,7 +2848,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { hir::PrimTy::Int(it) => tcx.mk_mach_int(it), hir::PrimTy::Uint(uit) => tcx.mk_mach_uint(uit), hir::PrimTy::Float(ft) => tcx.mk_mach_float(ft), - hir::PrimTy::Str => tcx.mk_str(), + hir::PrimTy::Str => tcx.types.str_, } } Res::Err => { diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index 2570025959cb4..97d2b3e5a8e45 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -1,191 +1,46 @@ +//! Some helper functions for `AutoDeref` use super::method::MethodCallee; use super::{FnCtxt, PlaceOp}; -use rustc_errors::struct_span_err; -use rustc_hir as hir; -use rustc_infer::infer::{InferCtxt, InferOk}; +use rustc_infer::infer::InferOk; use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; -use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, WithConstness}; -use rustc_middle::ty::{ToPredicate, TypeFoldable}; -use rustc_session::DiagnosticMessageId; -use rustc_span::symbol::Ident; +use rustc_middle::ty::{self, Ty}; use rustc_span::Span; -use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; -use rustc_trait_selection::traits::{self, TraitEngine}; +use rustc_trait_selection::autoderef::{Autoderef, AutoderefKind}; use std::iter; -#[derive(Copy, Clone, Debug)] -enum AutoderefKind { - Builtin, - Overloaded, -} - -pub struct Autoderef<'a, 'tcx> { - infcx: &'a InferCtxt<'a, 'tcx>, - body_id: hir::HirId, - param_env: ty::ParamEnv<'tcx>, - steps: Vec<(Ty<'tcx>, AutoderefKind)>, - cur_ty: Ty<'tcx>, - obligations: Vec>, - at_start: bool, - include_raw_pointers: bool, - span: Span, - silence_errors: bool, - reached_recursion_limit: bool, -} - -impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> { - type Item = (Ty<'tcx>, usize); - - fn next(&mut self) -> Option { - let tcx = self.infcx.tcx; - - debug!("autoderef: steps={:?}, cur_ty={:?}", self.steps, self.cur_ty); - if self.at_start { - self.at_start = false; - debug!("autoderef stage #0 is {:?}", self.cur_ty); - return Some((self.cur_ty, 0)); - } - - if !tcx.sess.recursion_limit().value_within_limit(self.steps.len()) { - if !self.silence_errors { - report_autoderef_recursion_limit_error(tcx, self.span, self.cur_ty); - } - self.reached_recursion_limit = true; - return None; - } - - if self.cur_ty.is_ty_var() { - return None; - } - - // Otherwise, deref if type is derefable: - let (kind, new_ty) = if let Some(mt) = self.cur_ty.builtin_deref(self.include_raw_pointers) - { - (AutoderefKind::Builtin, mt.ty) - } else { - let ty = self.overloaded_deref_ty(self.cur_ty)?; - (AutoderefKind::Overloaded, ty) - }; - - if new_ty.references_error() { - return None; - } - - self.steps.push((self.cur_ty, kind)); - debug!( - "autoderef stage #{:?} is {:?} from {:?}", - self.steps.len(), - new_ty, - (self.cur_ty, kind) - ); - self.cur_ty = new_ty; - - Some((self.cur_ty, self.steps.len())) +impl<'a, 'tcx> FnCtxt<'a, 'tcx> { + pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'tcx> { + Autoderef::new(self, self.param_env, self.body_id, span, base_ty) } -} -impl<'a, 'tcx> Autoderef<'a, 'tcx> { - pub fn new( - infcx: &'a InferCtxt<'a, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - body_id: hir::HirId, + pub fn try_overloaded_deref( + &self, span: Span, base_ty: Ty<'tcx>, - ) -> Autoderef<'a, 'tcx> { - Autoderef { - infcx, - body_id, - param_env, - steps: vec![], - cur_ty: infcx.resolve_vars_if_possible(&base_ty), - obligations: vec![], - at_start: true, - include_raw_pointers: false, - silence_errors: false, - reached_recursion_limit: false, - span, - } - } - - fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option> { - debug!("overloaded_deref_ty({:?})", ty); - - let tcx = self.infcx.tcx; - - // - let trait_ref = TraitRef { - def_id: tcx.lang_items().deref_trait()?, - substs: tcx.mk_substs_trait(ty, &[]), - }; - - let cause = traits::ObligationCause::misc(self.span, self.body_id); - - let obligation = traits::Obligation::new( - cause.clone(), - self.param_env, - trait_ref.without_const().to_predicate(tcx), - ); - if !self.infcx.predicate_may_hold(&obligation) { - debug!("overloaded_deref_ty: cannot match obligation"); - return None; - } - - let mut fulfillcx = traits::FulfillmentContext::new_in_snapshot(); - let normalized_ty = fulfillcx.normalize_projection_type( - &self.infcx, - self.param_env, - ty::ProjectionTy::from_ref_and_name(tcx, trait_ref, Ident::from_str("Target")), - cause, - ); - if let Err(e) = fulfillcx.select_where_possible(&self.infcx) { - // This shouldn't happen, except for evaluate/fulfill mismatches, - // but that's not a reason for an ICE (`predicate_may_hold` is conservative - // by design). - debug!("overloaded_deref_ty: encountered errors {:?} while fulfilling", e); - return None; - } - let obligations = fulfillcx.pending_obligations(); - debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations); - self.obligations.extend(obligations); - - Some(self.infcx.resolve_vars_if_possible(&normalized_ty)) - } - - /// Returns the final type, generating an error if it is an - /// unresolved inference variable. - pub fn unambiguous_final_ty(&self, fcx: &FnCtxt<'a, 'tcx>) -> Ty<'tcx> { - fcx.structurally_resolved_type(self.span, self.cur_ty) - } - - /// Returns the final type we ended up with, which may well be an - /// inference variable (we will resolve it first, if possible). - pub fn maybe_ambiguous_final_ty(&self) -> Ty<'tcx> { - self.infcx.resolve_vars_if_possible(&self.cur_ty) - } - - pub fn step_count(&self) -> usize { - self.steps.len() + ) -> Option>> { + self.try_overloaded_place_op(span, base_ty, &[], PlaceOp::Deref) } /// Returns the adjustment steps. - pub fn adjust_steps(&self, fcx: &FnCtxt<'a, 'tcx>) -> Vec> { - fcx.register_infer_ok_obligations(self.adjust_steps_as_infer_ok(fcx)) + pub fn adjust_steps(&self, autoderef: &Autoderef<'a, 'tcx>) -> Vec> { + self.register_infer_ok_obligations(self.adjust_steps_as_infer_ok(autoderef)) } pub fn adjust_steps_as_infer_ok( &self, - fcx: &FnCtxt<'a, 'tcx>, + autoderef: &Autoderef<'a, 'tcx>, ) -> InferOk<'tcx, Vec>> { let mut obligations = vec![]; - let targets = self.steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(self.cur_ty)); - let steps: Vec<_> = self - .steps + let steps = autoderef.steps(); + let targets = + steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty(false))); + let steps: Vec<_> = steps .iter() .map(|&(source, kind)| { if let AutoderefKind::Overloaded = kind { - fcx.try_overloaded_deref(self.span, source).and_then( + self.try_overloaded_deref(autoderef.span(), source).and_then( |InferOk { value: method, obligations: o }| { obligations.extend(o); if let ty::Ref(region, _, mutbl) = method.sig.output().kind { @@ -205,67 +60,4 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { InferOk { obligations, value: steps } } - - /// also dereference through raw pointer types - /// e.g., assuming ptr_to_Foo is the type `*const Foo` - /// fcx.autoderef(span, ptr_to_Foo) => [*const Foo] - /// fcx.autoderef(span, ptr_to_Foo).include_raw_ptrs() => [*const Foo, Foo] - pub fn include_raw_pointers(mut self) -> Self { - self.include_raw_pointers = true; - self - } - - pub fn silence_errors(mut self) -> Self { - self.silence_errors = true; - self - } - - pub fn reached_recursion_limit(&self) -> bool { - self.reached_recursion_limit - } - - pub fn finalize(self, fcx: &FnCtxt<'a, 'tcx>) { - fcx.register_predicates(self.into_obligations()); - } - - pub fn into_obligations(self) -> Vec> { - self.obligations - } -} - -pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) { - // We've reached the recursion limit, error gracefully. - let suggested_limit = tcx.sess.recursion_limit() * 2; - let msg = format!("reached the recursion limit while auto-dereferencing `{:?}`", ty); - let error_id = (DiagnosticMessageId::ErrorId(55), Some(span), msg); - let fresh = tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id); - if fresh { - struct_span_err!( - tcx.sess, - span, - E0055, - "reached the recursion limit while auto-dereferencing `{:?}`", - ty - ) - .span_label(span, "deref recursion limit reached") - .help(&format!( - "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)", - suggested_limit, tcx.crate_name, - )) - .emit(); - } -} - -impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'tcx> { - Autoderef::new(self, self.param_env, self.body_id, span, base_ty) - } - - pub fn try_overloaded_deref( - &self, - span: Span, - base_ty: Ty<'tcx>, - ) -> Option>> { - self.try_overloaded_place_op(span, base_ty, &[], PlaceOp::Deref) - } } diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index fe200a0ad2a1c..308ed5d840202 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -1,4 +1,3 @@ -use super::autoderef::Autoderef; use super::method::MethodCallee; use super::{Expectation, FnCtxt, TupleArgumentsFlag}; use crate::type_error_struct; @@ -17,6 +16,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_span::symbol::Ident; use rustc_span::Span; use rustc_target::spec::abi; +use rustc_trait_selection::autoderef::Autoderef; /// Checks that it is legal to call methods of the trait corresponding /// to `trait_id` (this only cares about the trait, not the specific @@ -72,7 +72,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { while result.is_none() && autoderef.next().is_some() { result = self.try_overloaded_call_step(call_expr, callee_expr, arg_exprs, &autoderef); } - autoderef.finalize(self); + self.register_predicates(autoderef.into_obligations()); let output = match result { None => { @@ -106,7 +106,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { arg_exprs: &'tcx [hir::Expr<'tcx>], autoderef: &Autoderef<'a, 'tcx>, ) -> Option> { - let adjusted_ty = autoderef.unambiguous_final_ty(self); + let adjusted_ty = + self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false)); debug!( "try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?})", call_expr, adjusted_ty @@ -115,7 +116,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the callee is a bare function or a closure, then we're all set. match adjusted_ty.kind { ty::FnDef(..) | ty::FnPtr(_) => { - let adjustments = autoderef.adjust_steps(self); + let adjustments = self.adjust_steps(autoderef); self.apply_adjustments(callee_expr, adjustments); return Some(CallStep::Builtin(adjusted_ty)); } @@ -135,7 +136,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &closure_sig, ) .0; - let adjustments = autoderef.adjust_steps(self); + let adjustments = self.adjust_steps(autoderef); self.record_deferred_call_resolution( def_id, DeferredCallResolution { @@ -176,7 +177,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.try_overloaded_call_traits(call_expr, adjusted_ty, Some(arg_exprs)) .or_else(|| self.try_overloaded_call_traits(call_expr, adjusted_ty, None)) .map(|(autoref, method)| { - let mut adjustments = autoderef.adjust_steps(self); + let mut adjustments = self.adjust_steps(autoderef); adjustments.extend(autoref); self.apply_adjustments(callee_expr, adjustments); CallStep::Overloaded(method) diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 1c34d71ee3184..b6cd8da236260 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -10,45 +10,30 @@ //! //! Note that if we are expecting a reference, we will *reborrow* //! even if the argument provided was already a reference. This is -//! useful for freezing mut/const things (that is, when the expected is &T -//! but you have &const T or &mut T) and also for avoiding the linearity +//! useful for freezing mut things (that is, when the expected type is &T +//! but you have &mut T) and also for avoiding the linearity //! of mut things (when the expected is &mut T and you have &mut T). See -//! the various `src/test/ui/coerce-reborrow-*.rs` tests for +//! the various `src/test/ui/coerce/*.rs` tests for //! examples of where this is useful. //! //! ## Subtle note //! -//! When deciding what type coercions to consider, we do not attempt to -//! resolve any type variables we may encounter. This is because `b` -//! represents the expected type "as the user wrote it", meaning that if -//! the user defined a generic function like +//! When infering the generic arguments of functions, the argument +//! order is relevant, which can lead to the following edge case: //! -//! fn foo(a: A, b: A) { ... } +//! ```rust +//! fn foo(a: T, b: T) { +//! // ... +//! } //! -//! and then we wrote `foo(&1, @2)`, we will not auto-borrow -//! either argument. In older code we went to some lengths to -//! resolve the `b` variable, which could mean that we'd -//! auto-borrow later arguments but not earlier ones, which -//! seems very confusing. +//! foo(&7i32, &mut 7i32); +//! // This compiles, as we first infer `T` to be `&i32`, +//! // and then coerce `&mut 7i32` to `&7i32`. //! -//! ## Subtler note -//! -//! However, right now, if the user manually specifies the -//! values for the type variables, as so: -//! -//! foo::<&int>(@1, @2) -//! -//! then we *will* auto-borrow, because we can't distinguish this from a -//! function that declared `&int`. This is inconsistent but it's easiest -//! at the moment. The right thing to do, I think, is to consider the -//! *unsubstituted* type when deciding whether to auto-borrow, but the -//! *substituted* type when considering the bounds and so forth. But most -//! of our methods don't give access to the unsubstituted type, and -//! rightly so because they'd be error-prone. So maybe the thing to do is -//! to actually determine the kind of coercions that should occur -//! separately and pass them in. Or maybe it's ok as is. Anyway, it's -//! sort of a minor point so I've opted to leave it for later -- after all, -//! we may want to adjust precisely when coercions occur. +//! foo(&mut 7i32, &7i32); +//! // This does not compile, as we first infer `T` to be `&mut i32` +//! // and are then unable to coerce `&7i32` to `&mut i32`. +//! ``` use crate::astconv::AstConv; use crate::check::FnCtxt; @@ -96,6 +81,8 @@ impl<'a, 'tcx> Deref for Coerce<'a, 'tcx> { type CoerceResult<'tcx> = InferResult<'tcx, (Vec>, Ty<'tcx>)>; +/// Coercing a mutable reference to an immutable works, while +/// coercing `&T` to `&mut T` should be forbidden. fn coerce_mutbls<'tcx>( from_mutbl: hir::Mutability, to_mutbl: hir::Mutability, @@ -422,7 +409,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } let InferOk { value: mut adjustments, obligations: o } = - autoderef.adjust_steps_as_infer_ok(self); + self.adjust_steps_as_infer_ok(&autoderef); obligations.extend(o); obligations.extend(autoderef.into_obligations()); @@ -908,7 +895,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { let prev_ty = self.resolve_vars_with_obligations(prev_ty); let new_ty = self.resolve_vars_with_obligations(new_ty); - debug!("coercion::try_find_coercion_lub({:?}, {:?})", prev_ty, new_ty); + debug!( + "coercion::try_find_coercion_lub({:?}, {:?}, exprs={:?} exprs)", + prev_ty, + new_ty, + exprs.len() + ); // Special-case that coercion alone cannot handle: // Function items or non-capturing closures of differing IDs or InternalSubsts. @@ -1014,6 +1006,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok(ok) => { let (adjustments, target) = self.register_infer_ok_obligations(ok); self.apply_adjustments(new, adjustments); + debug!( + "coercion::try_find_coercion_lub: was able to coerce from previous type {:?} to new type {:?}", + prev_ty, new_ty, + ); return Ok(target); } Err(e) => first_error = Some(e), @@ -1044,6 +1040,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if !noop { + debug!( + "coercion::try_find_coercion_lub: older expression {:?} had adjustments, requiring LUB", + expr, + ); + return self .commit_if_ok(|_| self.at(cause, self.param_env).lub(prev_ty, new_ty)) .map(|ok| self.register_infer_ok_obligations(ok)); @@ -1061,6 +1062,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } Ok(ok) => { + debug!( + "coercion::try_find_coercion_lub: was able to coerce previous type {:?} to new type {:?}", + prev_ty, new_ty, + ); let (adjustments, target) = self.register_infer_ok_obligations(ok); for expr in exprs { let expr = expr.as_coercion_site(); diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index b39cfcb377595..4e97ba41dcbb3 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -4,15 +4,17 @@ 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_middle::ty; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::subst::{InternalSubsts, Subst}; +use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc_middle::ty::util::ExplicitSelf; -use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt}; +use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt, WithConstness}; 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}; +use std::iter; /// Checks that a method from an impl conforms to the signature of /// the same method as declared in the trait. @@ -91,14 +93,14 @@ fn compare_predicate_entailment<'tcx>( // This code is best explained by example. Consider a trait: // - // trait Trait<'t,T> { - // fn method<'a,M>(t: &'t T, m: &'a M) -> Self; + // trait Trait<'t, T> { + // fn method<'a, M>(t: &'t T, m: &'a M) -> Self; // } // // And an impl: // // impl<'i, 'j, U> Trait<'j, &'i U> for Foo { - // fn method<'b,N>(t: &'j &'i U, m: &'b N) -> Foo; + // fn method<'b, N>(t: &'j &'i U, m: &'b N) -> Foo; // } // // We wish to decide if those two method types are compatible. @@ -116,9 +118,9 @@ fn compare_predicate_entailment<'tcx>( // regions (Note: but only early-bound regions, i.e., those // declared on the impl or used in type parameter bounds). // - // impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 } + // impl_to_placeholder_substs = {'i => 'i0, U => U0, N => N0 } // - // Now we can apply skol_substs to the type of the impl method + // Now we can apply placeholder_substs to the type of the impl method // to yield a new function type in terms of our fresh, placeholder // types: // @@ -127,11 +129,11 @@ fn compare_predicate_entailment<'tcx>( // We now want to extract and substitute the type of the *trait* // method and compare it. To do so, we must create a compound // substitution by combining trait_to_impl_substs and - // impl_to_skol_substs, and also adding a mapping for the method + // impl_to_placeholder_substs, and also adding a mapping for the method // type parameters. We extend the mapping to also include // the method parameters. // - // trait_to_skol_substs = { T => &'i0 U0, Self => Foo, M => N0 } + // trait_to_placeholder_substs = { T => &'i0 U0, Self => Foo, M => N0 } // // Applying this to the trait method type yields: // @@ -145,20 +147,20 @@ fn compare_predicate_entailment<'tcx>( // satisfied by the implementation's method. // // We do this by creating a parameter environment which contains a - // substitution corresponding to impl_to_skol_substs. We then build - // trait_to_skol_substs and use it to convert the predicates contained + // substitution corresponding to impl_to_placeholder_substs. We then build + // trait_to_placeholder_substs and use it to convert the predicates contained // in the trait_m.generics to the placeholder form. // // Finally we register each of these predicates as an obligation in // a fresh FulfillmentCtxt, and invoke select_all_or_error. // Create mapping from impl to placeholder. - let impl_to_skol_substs = InternalSubsts::identity_for_item(tcx, impl_m.def_id); + let impl_to_placeholder_substs = InternalSubsts::identity_for_item(tcx, impl_m.def_id); // Create mapping from trait to placeholder. - let trait_to_skol_substs = - impl_to_skol_substs.rebase_onto(tcx, impl_m.container.id(), trait_to_impl_substs); - debug!("compare_impl_method: trait_to_skol_substs={:?}", trait_to_skol_substs); + let trait_to_placeholder_substs = + impl_to_placeholder_substs.rebase_onto(tcx, impl_m.container.id(), trait_to_impl_substs); + debug!("compare_impl_method: trait_to_placeholder_substs={:?}", trait_to_placeholder_substs); let impl_m_generics = tcx.generics_of(impl_m.def_id); let trait_m_generics = tcx.generics_of(trait_m.def_id); @@ -194,7 +196,7 @@ fn compare_predicate_entailment<'tcx>( // if all constraints hold. hybrid_preds .predicates - .extend(trait_m_predicates.instantiate_own(tcx, trait_to_skol_substs).predicates); + .extend(trait_m_predicates.instantiate_own(tcx, trait_to_placeholder_substs).predicates); // Construct trait parameter environment and then shift it into the placeholder viewpoint. // The key step here is to update the caller_bounds's predicates to be @@ -220,7 +222,7 @@ fn compare_predicate_entailment<'tcx>( let mut selcx = traits::SelectionContext::new(&infcx); - let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_skol_substs); + let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_substs); let (impl_m_own_bounds, _) = infcx.replace_bound_vars_with_fresh_vars( impl_m_span, infer::HigherRankedType, @@ -261,7 +263,7 @@ fn compare_predicate_entailment<'tcx>( debug!("compare_impl_method: impl_fty={:?}", impl_fty); let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, &tcx.fn_sig(trait_m.def_id)); - let trait_sig = trait_sig.subst(tcx, trait_to_skol_substs); + let trait_sig = trait_sig.subst(tcx, trait_to_placeholder_substs); let trait_sig = inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, &trait_sig); let trait_fty = tcx.mk_fn_ptr(ty::Binder::bind(trait_sig)); @@ -1057,13 +1059,15 @@ crate fn compare_ty_impl<'tcx>( let _: Result<(), ErrorReported> = (|| { compare_number_of_generics(tcx, impl_ty, impl_ty_span, trait_ty, trait_item_span)?; - compare_type_predicate_entailment(tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref) + compare_type_predicate_entailment(tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref)?; + + compare_projection_bounds(tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref) })(); } /// The equivalent of [compare_predicate_entailment], but for associated types /// instead of associated functions. -fn compare_type_predicate_entailment( +fn compare_type_predicate_entailment<'tcx>( tcx: TyCtxt<'tcx>, impl_ty: &ty::AssocItem, impl_ty_span: Span, @@ -1165,6 +1169,145 @@ fn compare_type_predicate_entailment( }) } +/// Validate that `ProjectionCandidate`s created for this associated type will +/// be valid. +/// +/// Usually given +/// +/// trait X { type Y: Copy } impl X for T { type Y = S; } +/// +/// We are able to normalize `::U` to `S`, and so when we check the +/// impl is well-formed we have to prove `S: Copy`. +/// +/// For default associated types the normalization is not possible (the value +/// from the impl could be overridden). We also can't normalize generic +/// associated types (yet) because they contain bound parameters. +fn compare_projection_bounds<'tcx>( + tcx: TyCtxt<'tcx>, + trait_ty: &ty::AssocItem, + impl_ty: &ty::AssocItem, + impl_ty_span: Span, + impl_trait_ref: ty::TraitRef<'tcx>, +) -> Result<(), ErrorReported> { + let have_gats = tcx.features().generic_associated_types; + if impl_ty.defaultness.is_final() && !have_gats { + // For "final", non-generic associate type implementations, we + // don't need this as described above. + return Ok(()); + } + + let param_env = tcx.param_env(impl_ty.def_id); + + // Given + // + // impl Foo for (A, B) { + // type Bar =... + // } + // + // - `impl_substs` would be `[A, B, C]` + // - `rebased_substs` would be `[(A, B), u32, C]`, combining the substs from + // the *trait* with the generic associated type parameters. + let impl_ty_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id); + let rebased_substs = + impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs); + let impl_ty_value = tcx.type_of(impl_ty.def_id); + + // Map the predicate from the trait to the corresponding one for the impl. + // For example: + // + // trait X { type Y<'a>: PartialEq } impl X for T { type Y<'a> = &'a S; } + // impl<'x> X<&'x u32> for () { type Y<'c> = &'c u32; } + // + // For the `for<'a> <>::Y<'a>: PartialEq` bound, this + // function would translate and partially normalize + // `[>::Y<'a>, A]` to `[&'a u32, &'x u32]`. + let translate_predicate_substs = move |predicate_substs: SubstsRef<'tcx>| { + tcx.mk_substs( + iter::once(impl_ty_value.into()) + .chain(predicate_substs[1..].iter().map(|s| s.subst(tcx, rebased_substs))), + ) + }; + + tcx.infer_ctxt().enter(move |infcx| { + let inh = Inherited::new(infcx, impl_ty.def_id.expect_local()); + let infcx = &inh.infcx; + let mut selcx = traits::SelectionContext::new(&infcx); + + let impl_ty_hir_id = tcx.hir().as_local_hir_id(impl_ty.def_id.expect_local()); + let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id); + let cause = ObligationCause::new( + impl_ty_span, + impl_ty_hir_id, + ObligationCauseCode::ItemObligation(trait_ty.def_id), + ); + + let predicates = tcx.projection_predicates(trait_ty.def_id); + + debug!("compare_projection_bounds: projection_predicates={:?}", predicates); + + for predicate in predicates { + let concrete_ty_predicate = match predicate.kind() { + ty::PredicateKind::Trait(poly_tr, c) => poly_tr + .map_bound(|tr| { + let trait_substs = translate_predicate_substs(tr.trait_ref.substs); + ty::TraitRef { def_id: tr.def_id(), substs: trait_substs } + }) + .with_constness(*c) + .to_predicate(tcx), + ty::PredicateKind::Projection(poly_projection) => poly_projection + .map_bound(|projection| { + let projection_substs = + translate_predicate_substs(projection.projection_ty.substs); + ty::ProjectionPredicate { + projection_ty: ty::ProjectionTy { + substs: projection_substs, + item_def_id: projection.projection_ty.item_def_id, + }, + ty: projection.ty.subst(tcx, rebased_substs), + } + }) + .to_predicate(tcx), + ty::PredicateKind::TypeOutlives(poly_outlives) => poly_outlives + .map_bound(|outlives| { + ty::OutlivesPredicate(impl_ty_value, outlives.1.subst(tcx, rebased_substs)) + }) + .to_predicate(tcx), + _ => bug!("unexepected projection predicate kind: `{:?}`", predicate), + }; + + let traits::Normalized { value: normalized_predicate, obligations } = traits::normalize( + &mut selcx, + param_env, + normalize_cause.clone(), + &concrete_ty_predicate, + ); + + debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate); + + inh.register_predicates(obligations); + inh.register_predicate(traits::Obligation::new( + cause.clone(), + param_env, + normalized_predicate, + )); + } + + // Check that all obligations are satisfied by the implementation's + // version. + if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) { + infcx.report_fulfillment_errors(errors, None, false); + return Err(ErrorReported); + } + + // Finally, resolve all regions. This catches wily misuses of + // lifetime parameters. + let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id); + fcx.regionck_item(impl_ty_hir_id, impl_ty_span, &[]); + + Ok(()) + }) +} + fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str { match impl_item.kind { ty::AssocKind::Const => "const", diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 019b4ca66060c..85c073ca30034 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -34,6 +34,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty); self.suggest_missing_await(err, expr, expected, expr_ty); + self.note_need_for_fn_pointer(err, expected, expr_ty); } // Requires that the two types unify, and prints an error message if @@ -783,6 +784,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let literal_is_ty_suffixed = |expr: &hir::Expr<'_>| { if let hir::ExprKind::Lit(lit) = &expr.kind { lit.node.is_suffixed() } else { false } }; + let is_negative_int = + |expr: &hir::Expr<'_>| matches!(expr.kind, hir::ExprKind::Unary(hir::UnOp::UnNeg, ..)); + let is_uint = |ty: Ty<'_>| matches!(ty.kind, ty::Uint(..)); let in_const_context = self.tcx.hir().is_inside_const_context(expr.hir_id); @@ -807,7 +811,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "you can convert `{}` from `{}` to `{}`, matching the type of `{}`", lhs_src, expected_ty, checked_ty, src ); - let suggestion = format!("{}::from({})", checked_ty, lhs_src,); + let suggestion = format!("{}::from({})", checked_ty, lhs_src); (lhs_expr.span, msg, suggestion) } else { let msg = format!("{} and panic if the converted value wouldn't fit", msg); @@ -822,8 +826,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { |err: &mut DiagnosticBuilder<'_>, found_to_exp_is_fallible: bool, exp_to_found_is_fallible: bool| { + let always_fallible = found_to_exp_is_fallible + && (exp_to_found_is_fallible || expected_ty_expr.is_none()); let msg = if literal_is_ty_suffixed(expr) { &lit_msg + } else if always_fallible && (is_negative_int(expr) && is_uint(expected_ty)) { + // We now know that converting either the lhs or rhs is fallible. Before we + // suggest a fallible conversion, check if the value can never fit in the + // expected type. + let msg = format!("`{}` cannot fit into type `{}`", src, expected_ty); + err.note(&msg); + return; } else if in_const_context { // Do not recommend `into` or `try_into` in const contexts. return; diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 188f4a9401422..1eaa5a6c31e20 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -888,10 +888,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcvr, probe::ProbeScope::AllTraits, ) { - err.span_label( - pick.item.ident.span, - &format!("the method is available for `{}` here", new_rcvr_t), - ); + debug!("try_alt_rcvr: pick candidate {:?}", pick); + // Make sure the method is defined for the *actual* receiver: + // we don't want to treat `Box` as a receiver if + // it only works because of an autoderef to `&self` + if pick.autoderefs == 0 { + err.span_label( + pick.item.ident.span, + &format!("the method is available for `{}` here", new_rcvr_t), + ); + } } } }; @@ -1441,9 +1447,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // of error recovery. self.write_field_index(expr.hir_id, index); if field.vis.is_accessible_from(def_scope, self.tcx) { - let adjustments = autoderef.adjust_steps(self); + let adjustments = self.adjust_steps(&autoderef); self.apply_adjustments(base, adjustments); - autoderef.finalize(self); + self.register_predicates(autoderef.into_obligations()); self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span); return field_ty; @@ -1456,9 +1462,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Ok(index) = fstr.parse::() { if fstr == index.to_string() { if let Some(field_ty) = tys.get(index) { - let adjustments = autoderef.adjust_steps(self); + let adjustments = self.adjust_steps(&autoderef); self.apply_adjustments(base, adjustments); - autoderef.finalize(self); + self.register_predicates(autoderef.into_obligations()); self.write_field_index(expr.hir_id, index); return field_ty.expect_ty(); @@ -1469,7 +1475,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => {} } } - autoderef.unambiguous_final_ty(self); + self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false)); if let Some((did, field_ty)) = private_candidate { self.ban_private_field_access(expr, expr_t, field, did); diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 3ec6973a17d56..ef6c7c14404a7 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -74,9 +74,8 @@ pub fn intrinsic_operation_unsafety(intrinsic: &str) -> hir::Unsafety { | "wrapping_add" | "wrapping_sub" | "wrapping_mul" | "saturating_add" | "saturating_sub" | "rotate_left" | "rotate_right" | "ctpop" | "ctlz" | "cttz" | "bswap" | "bitreverse" | "discriminant_value" | "type_id" | "likely" | "unlikely" - | "minnumf32" | "minnumf64" | "maxnumf32" | "maxnumf64" | "type_name" => { - hir::Unsafety::Normal - } + | "ptr_guaranteed_eq" | "ptr_guaranteed_ne" | "minnumf32" | "minnumf64" | "maxnumf32" + | "maxnumf64" | "type_name" => hir::Unsafety::Normal, _ => hir::Unsafety::Unsafe, } } @@ -258,6 +257,10 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { (1, vec![param(0), param(0)], tcx.intern_tup(&[param(0), tcx.types.bool])) } + "ptr_guaranteed_eq" | "ptr_guaranteed_ne" => { + (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.bool) + } + "ptr_offset_from" => { (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.isize) } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 6844c9416af8a..1c3d23a3a241f 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -144,9 +144,10 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { }; assert_eq!(n, pick.autoderefs); - let mut adjustments = autoderef.adjust_steps(self); + let mut adjustments = self.adjust_steps(&autoderef); - let mut target = autoderef.unambiguous_final_ty(self); + let mut target = + self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false)); if let Some(mutbl) = pick.autoref { let region = self.next_region_var(infer::Autoref(self.span)); @@ -176,7 +177,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { assert!(pick.unsize.is_none()); } - autoderef.finalize(self); + self.register_predicates(autoderef.into_obligations()); // Write out the final adjustments. self.apply_adjustments(self.self_expr, adjustments); diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index ac3fa15417e9c..259c4a8664f1b 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -194,11 +194,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.lookup_probe(span, segment.ident, self_ty, call_expr, ProbeScope::TraitsInScope)?; for import_id in &pick.import_ids { - let import_def_id = self.tcx.hir().local_def_id(*import_id); - debug!("used_trait_import: {:?}", import_def_id); + debug!("used_trait_import: {:?}", import_id); Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports) .unwrap() - .insert(import_def_id.to_def_id()); + .insert(*import_id); } self.tcx.check_stability(pick.item.def_id, Some(call_expr.hir_id), span); @@ -461,9 +460,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut tables = self.tables.borrow_mut(); let used_trait_imports = Lrc::get_mut(&mut tables.used_trait_imports).unwrap(); for import_id in pick.import_ids { - let import_def_id = tcx.hir().local_def_id(import_id); - debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id); - used_trait_imports.insert(import_def_id.to_def_id()); + debug!("resolve_ufcs: used_trait_import: {:?}", import_id); + used_trait_imports.insert(import_id); } } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 93bcd5cf29149..a3e34815d3182 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -3,7 +3,6 @@ use super::MethodError; use super::NoMatchData; use super::{CandidateSource, ImplSource, TraitSource}; -use crate::check::autoderef::{self, Autoderef}; use crate::check::FnCtxt; use crate::hir::def::DefKind; use crate::hir::def_id::DefId; @@ -28,7 +27,9 @@ use rustc_middle::ty::{ }; use rustc_session::config::nightly_options; use rustc_session::lint; +use rustc_span::def_id::LocalDefId; use rustc_span::{symbol::Ident, Span, Symbol, DUMMY_SP}; +use rustc_trait_selection::autoderef::{self, Autoderef}; 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::{ @@ -129,7 +130,7 @@ struct Candidate<'tcx> { xform_ret_ty: Option>, item: ty::AssocItem, kind: CandidateKind<'tcx>, - import_ids: SmallVec<[hir::HirId; 1]>, + import_ids: SmallVec<[LocalDefId; 1]>, } #[derive(Debug)] @@ -158,7 +159,7 @@ enum ProbeResult { pub struct Pick<'tcx> { pub item: ty::AssocItem, pub kind: PickKind<'tcx>, - pub import_ids: SmallVec<[hir::HirId; 1]>, + pub import_ids: SmallVec<[LocalDefId; 1]>, // Indicates that the source expression should be autoderef'd N times // @@ -476,7 +477,7 @@ fn method_autoderef_steps<'tcx>( }) .collect(); - let final_ty = autoderef.maybe_ambiguous_final_ty(); + let final_ty = autoderef.final_ty(true); let opt_bad_ty = match final_ty.kind { ty::Infer(ty::TyVar(_)) | ty::Error(_) => Some(MethodAutoderefBadTy { reached_raw_pointer, @@ -930,7 +931,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn assemble_extension_candidates_for_trait( &mut self, - import_ids: &SmallVec<[hir::HirId; 1]>, + import_ids: &SmallVec<[LocalDefId; 1]>, trait_def_id: DefId, ) -> Result<(), MethodError<'tcx>> { debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})", trait_def_id); @@ -1467,7 +1468,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { /// /// ``` /// trait Foo { ... } - /// impl Foo for Vec { ... } + /// impl Foo for Vec { ... } /// impl Foo for Vec { ... } /// ``` /// diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2ece8e8c28423..0325782e69d51 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -97,7 +97,7 @@ use rustc_errors::ErrorReported; 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, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::lang_items::{ @@ -840,7 +840,7 @@ fn has_typeck_tables(tcx: TyCtxt<'_>, def_id: DefId) -> bool { } } -fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &DefIdSet { +fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &FxHashSet { &*tcx.typeck_tables_of(def_id).used_trait_imports } @@ -2281,7 +2281,7 @@ fn check_impl_items_against_trait<'tcx>( &ty_trait_item, impl_trait_ref, opt_trait_span, - ) + ); } else { let mut err = struct_span_err!( tcx.sess, @@ -5362,6 +5362,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + fn note_need_for_fn_pointer( + &self, + err: &mut DiagnosticBuilder<'_>, + expected: Ty<'tcx>, + found: Ty<'tcx>, + ) { + let (sig, did, substs) = match (&expected.kind, &found.kind) { + (ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => { + let sig1 = self.tcx.fn_sig(*did1).subst(self.tcx, substs1); + let sig2 = self.tcx.fn_sig(*did2).subst(self.tcx, substs2); + if sig1 != sig2 { + return; + } + err.note( + "different `fn` items always have unique types, even if their signatures are \ + the same", + ); + (sig1, *did1, substs1) + } + (ty::FnDef(did, substs), ty::FnPtr(sig2)) => { + let sig1 = self.tcx.fn_sig(*did).subst(self.tcx, substs); + if sig1 != *sig2 { + return; + } + (sig1, *did, substs) + } + _ => return, + }; + err.help(&format!("change the expected type to be function pointer `{}`", sig)); + err.help(&format!( + "if the expected type is due to type inference, cast the expected `fn` to a function \ + pointer: `{} as {}`", + self.tcx.def_path_str_with_substs(did, substs), + sig + )); + } + /// A common error is to add an extra semicolon: /// /// ``` diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 7965c9c9ce12a..ea47ae68ce7d3 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -212,7 +212,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // errors in some cases, such as this one: // // ``` - // fn foo<'x>(x: &'x int) { + // fn foo<'x>(x: &'x i32) { // let a = 1; // let mut z = x; // z = &a; @@ -220,7 +220,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // ``` // // The reason we might get an error is that `z` might be - // assigned a type like `&'x int`, and then we would have + // assigned a type like `&'x i32`, and then we would have // a problem when we try to assign `&a` to `z`, because // the lifetime of `&a` (i.e., the enclosing block) is // shorter than `'x`. @@ -229,11 +229,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // expected type here is whatever type the user wrote, not // the initializer's type. In this case the user wrote // nothing, so we are going to create a type variable `Z`. - // Then we will assign the type of the initializer (`&'x - // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we - // will instantiate `Z` as a type `&'0 int` where `'0` is - // a fresh region variable, with the constraint that `'x : - // '0`. So basically we're all set. + // Then we will assign the type of the initializer (`&'x i32`) + // as a subtype of `Z`: `&'x i32 <: Z`. And hence we + // will instantiate `Z` as a type `&'0 i32` where `'0` is + // a fresh region variable, with the constraint that `'x : '0`. + // So basically we're all set. // // Note that there are two tests to check that this remains true // (`regions-reassign-{match,let}-bound-pointer.rs`). diff --git a/src/librustc_typeck/check/place_op.rs b/src/librustc_typeck/check/place_op.rs index d1c22cd1ac03e..b7c8f310a1414 100644 --- a/src/librustc_typeck/check/place_op.rs +++ b/src/librustc_typeck/check/place_op.rs @@ -1,4 +1,3 @@ -use crate::check::autoderef::Autoderef; use crate::check::method::MethodCallee; use crate::check::{FnCtxt, PlaceOp}; use rustc_hir as hir; @@ -9,6 +8,7 @@ use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutabili use rustc_middle::ty::{self, Ty}; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; +use rustc_trait_selection::autoderef::Autoderef; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Type-check `*oprnd_expr` with `oprnd_expr` type-checked already. @@ -57,7 +57,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { while result.is_none() && autoderef.next().is_some() { result = self.try_index_step(expr, base_expr, &autoderef, idx_ty); } - autoderef.finalize(self); + self.register_predicates(autoderef.into_obligations()); result } @@ -73,7 +73,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { autoderef: &Autoderef<'a, 'tcx>, index_ty: Ty<'tcx>, ) -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)> { - let adjusted_ty = autoderef.unambiguous_final_ty(self); + let adjusted_ty = + self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false)); debug!( "try_index_step(expr={:?}, base_expr={:?}, adjusted_ty={:?}, \ index_ty={:?})", @@ -105,7 +106,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("try_index_step: success, using overloaded indexing"); let method = self.register_infer_ok_obligations(ok); - let mut adjustments = autoderef.adjust_steps(self); + let mut adjustments = self.adjust_steps(autoderef); if let ty::Ref(region, _, hir::Mutability::Not) = method.sig.inputs()[0].kind { adjustments.push(Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(region, AutoBorrowMutability::Not)), diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 90ba15aa08988..d3bccaaa3e4b9 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -439,7 +439,10 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { /// Invoked on any adjustments that occur. Checks that if this is a region pointer being /// dereferenced, the lifetime of the pointer includes the deref expr. - fn constrain_adjustments(&mut self, expr: &hir::Expr<'_>) -> mc::McResult> { + fn constrain_adjustments( + &mut self, + expr: &hir::Expr<'_>, + ) -> mc::McResult> { debug!("constrain_adjustments(expr={:?})", expr); let mut place = self.with_mc(|mc| mc.cat_expr_unadjusted(expr))?; @@ -480,12 +483,12 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { fn check_safety_of_rvalue_destructor_if_necessary( &mut self, - place: &mc::Place<'tcx>, + place_with_id: &mc::PlaceWithHirId<'tcx>, span: Span, ) { - if let mc::PlaceBase::Rvalue = place.base { - if place.projections.is_empty() { - let typ = self.resolve_type(place.ty); + if let mc::PlaceBase::Rvalue = place_with_id.place.base { + if place_with_id.place.projections.is_empty() { + let typ = self.resolve_type(place_with_id.place.ty); let body_id = self.body_id; let _ = dropck::check_drop_obligations(self, typ, span, body_id); } @@ -570,7 +573,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { /// Link lifetimes of any ref bindings in `root_pat` to the pointers found /// in the discriminant, if needed. - fn link_pattern(&self, discr_cmt: mc::Place<'tcx>, root_pat: &hir::Pat<'_>) { + fn link_pattern(&self, discr_cmt: mc::PlaceWithHirId<'tcx>, root_pat: &hir::Pat<'_>) { debug!("link_pattern(discr_cmt={:?}, root_pat={:?})", discr_cmt, root_pat); ignore_err!(self.with_mc(|mc| { mc.cat_pattern(discr_cmt, root_pat, |sub_cmt, hir::Pat { kind, span, hir_id }| { @@ -591,7 +594,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { fn link_autoref( &self, expr: &hir::Expr<'_>, - expr_cmt: &mc::Place<'tcx>, + expr_cmt: &mc::PlaceWithHirId<'tcx>, autoref: &adjustment::AutoBorrow<'tcx>, ) { debug!("link_autoref(autoref={:?}, expr_cmt={:?})", autoref, expr_cmt); @@ -612,7 +615,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { span: Span, id: hir::HirId, mutbl: hir::Mutability, - cmt_borrowed: &mc::Place<'tcx>, + cmt_borrowed: &mc::PlaceWithHirId<'tcx>, ) { debug!( "link_region_from_node_type(id={:?}, mutbl={:?}, cmt_borrowed={:?})", @@ -635,12 +638,12 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { span: Span, borrow_region: ty::Region<'tcx>, borrow_kind: ty::BorrowKind, - borrow_place: &mc::Place<'tcx>, + borrow_place: &mc::PlaceWithHirId<'tcx>, ) { - let origin = infer::DataBorrowed(borrow_place.ty, span); - self.type_must_outlive(origin, borrow_place.ty, borrow_region); + let origin = infer::DataBorrowed(borrow_place.place.ty, span); + self.type_must_outlive(origin, borrow_place.place.ty, borrow_region); - for pointer_ty in borrow_place.deref_tys() { + for pointer_ty in borrow_place.place.deref_tys() { debug!( "link_region(borrow_region={:?}, borrow_kind={:?}, pointer_ty={:?})", borrow_region, borrow_kind, borrow_place @@ -656,7 +659,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { _ => assert!(pointer_ty.is_box(), "unexpected built-in deref type {}", pointer_ty), } } - if let mc::PlaceBase::Upvar(upvar_id) = borrow_place.base { + if let mc::PlaceBase::Upvar(upvar_id) = borrow_place.place.base { self.link_upvar_region(span, borrow_region, upvar_id); } } diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 8403c99f01bb5..0f3133e0695f1 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -270,10 +270,13 @@ struct InferBorrowKind<'a, 'tcx> { impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { fn adjust_upvar_borrow_kind_for_consume( &mut self, - place: &mc::Place<'tcx>, + place_with_id: &mc::PlaceWithHirId<'tcx>, mode: euv::ConsumeMode, ) { - debug!("adjust_upvar_borrow_kind_for_consume(place={:?}, mode={:?})", place, mode); + debug!( + "adjust_upvar_borrow_kind_for_consume(place_with_id={:?}, mode={:?})", + place_with_id, mode + ); // we only care about moves match mode { @@ -284,7 +287,7 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { } let tcx = self.fcx.tcx; - let upvar_id = if let PlaceBase::Upvar(upvar_id) = place.base { + let upvar_id = if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base { upvar_id } else { return; @@ -296,22 +299,22 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { self.adjust_closure_kind( upvar_id.closure_expr_id, ty::ClosureKind::FnOnce, - place.span, + tcx.hir().span(place_with_id.hir_id), var_name(tcx, upvar_id.var_path.hir_id), ); self.adjust_upvar_captures.insert(upvar_id, ty::UpvarCapture::ByValue); } - /// Indicates that `place` is being directly mutated (e.g., assigned + /// Indicates that `place_with_id` is being directly mutated (e.g., assigned /// to). If the place is based on a by-ref upvar, this implies that /// the upvar must be borrowed using an `&mut` borrow. - fn adjust_upvar_borrow_kind_for_mut(&mut self, place: &mc::Place<'tcx>) { - debug!("adjust_upvar_borrow_kind_for_mut(place={:?})", place); + fn adjust_upvar_borrow_kind_for_mut(&mut self, place_with_id: &mc::PlaceWithHirId<'tcx>) { + debug!("adjust_upvar_borrow_kind_for_mut(place_with_id={:?})", place_with_id); - if let PlaceBase::Upvar(upvar_id) = place.base { + if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base { let mut borrow_kind = ty::MutBorrow; - for pointer_ty in place.deref_tys() { + for pointer_ty in place_with_id.place.deref_tys() { match pointer_ty.kind { // Raw pointers don't inherit mutability. ty::RawPtr(_) => return, @@ -323,20 +326,28 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { _ => (), } } - self.adjust_upvar_deref(upvar_id, place.span, borrow_kind); + self.adjust_upvar_deref( + upvar_id, + self.fcx.tcx.hir().span(place_with_id.hir_id), + borrow_kind, + ); } } - fn adjust_upvar_borrow_kind_for_unique(&mut self, place: &mc::Place<'tcx>) { - debug!("adjust_upvar_borrow_kind_for_unique(place={:?})", place); + fn adjust_upvar_borrow_kind_for_unique(&mut self, place_with_id: &mc::PlaceWithHirId<'tcx>) { + debug!("adjust_upvar_borrow_kind_for_unique(place_with_id={:?})", place_with_id); - if let PlaceBase::Upvar(upvar_id) = place.base { - if place.deref_tys().any(ty::TyS::is_unsafe_ptr) { + if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base { + if place_with_id.place.deref_tys().any(ty::TyS::is_unsafe_ptr) { // Raw pointers don't inherit mutability. return; } // for a borrowed pointer to be unique, its base must be unique - self.adjust_upvar_deref(upvar_id, place.span, ty::UniqueImmBorrow); + self.adjust_upvar_deref( + upvar_id, + self.fcx.tcx.hir().span(place_with_id.hir_id), + ty::UniqueImmBorrow, + ); } } @@ -453,26 +464,26 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { } impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> { - fn consume(&mut self, place: &mc::Place<'tcx>, mode: euv::ConsumeMode) { - debug!("consume(place={:?},mode={:?})", place, mode); - self.adjust_upvar_borrow_kind_for_consume(place, mode); + fn consume(&mut self, place_with_id: &mc::PlaceWithHirId<'tcx>, mode: euv::ConsumeMode) { + debug!("consume(place_with_id={:?},mode={:?})", place_with_id, mode); + self.adjust_upvar_borrow_kind_for_consume(place_with_id, mode); } - fn borrow(&mut self, place: &mc::Place<'tcx>, bk: ty::BorrowKind) { - debug!("borrow(place={:?}, bk={:?})", place, bk); + fn borrow(&mut self, place_with_id: &mc::PlaceWithHirId<'tcx>, bk: ty::BorrowKind) { + debug!("borrow(place_with_id={:?}, bk={:?})", place_with_id, bk); match bk { ty::ImmBorrow => {} ty::UniqueImmBorrow => { - self.adjust_upvar_borrow_kind_for_unique(place); + self.adjust_upvar_borrow_kind_for_unique(place_with_id); } ty::MutBorrow => { - self.adjust_upvar_borrow_kind_for_mut(place); + self.adjust_upvar_borrow_kind_for_mut(place_with_id); } } } - fn mutate(&mut self, assignee_place: &mc::Place<'tcx>) { + fn mutate(&mut self, assignee_place: &mc::PlaceWithHirId<'tcx>) { debug!("mutate(assignee_place={:?})", assignee_place); self.adjust_upvar_borrow_kind_for_mut(assignee_place); diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index f3297ed674347..d1a86a7ee89a8 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -1118,7 +1118,7 @@ fn receiver_is_valid<'fcx, 'tcx>( ); if can_eq_self(potential_self_ty) { - autoderef.finalize(fcx); + fcx.register_predicates(autoderef.into_obligations()); if let Some(mut err) = fcx.demand_eqtype_with_origin(&cause, self_ty, potential_self_ty) diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index ba806430f17fd..4704d8fc7666f 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -4,10 +4,8 @@ use crate::check::FnCtxt; -use rustc_data_structures::sync::Lrc; use rustc_errors::ErrorReported; use rustc_hir as hir; -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; @@ -67,10 +65,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { wbcx.visit_user_provided_sigs(); wbcx.visit_generator_interior_types(); - let used_trait_imports = mem::replace( - &mut self.tables.borrow_mut().used_trait_imports, - Lrc::new(DefIdSet::default()), - ); + let used_trait_imports = mem::take(&mut self.tables.borrow_mut().used_trait_imports); debug!("used_trait_imports({:?}) = {:?}", item_def_id, used_trait_imports); wbcx.tables.used_trait_imports = used_trait_imports; diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index eaaff70472bfb..81daf064bb368 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -1,14 +1,14 @@ -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, DefIdSet, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_middle::ty::TyCtxt; use rustc_session::lint; use rustc_span::{Span, Symbol}; pub fn check_crate(tcx: TyCtxt<'_>) { - let mut used_trait_imports = DefIdSet::default(); + let mut used_trait_imports = FxHashSet::default(); for &body_id in tcx.hir().krate().bodies.keys() { let item_def_id = tcx.hir().body_owner_def_id(body_id); let imports = tcx.used_trait_imports(item_def_id); @@ -39,7 +39,7 @@ impl ItemLikeVisitor<'v> for CheckVisitor<'tcx> { struct CheckVisitor<'tcx> { tcx: TyCtxt<'tcx>, - used_trait_imports: DefIdSet, + used_trait_imports: FxHashSet, } impl CheckVisitor<'tcx> { @@ -49,7 +49,7 @@ impl CheckVisitor<'tcx> { return; } - if self.used_trait_imports.contains(&def_id.to_def_id()) { + if self.used_trait_imports.contains(&def_id) { return; } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 3bd75095bb602..054165f2b0977 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -35,11 +35,12 @@ use rustc_middle::hir::map::Map; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mir::mono::Linkage; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::subst::{InternalSubsts, Subst}; +use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::util::Discr; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, AdtKind, Const, ToPolyTraitRef, Ty, TyCtxt}; use rustc_middle::ty::{ReprOptions, ToPredicate, WithConstness}; +use rustc_session::config::SanitizerSet; use rustc_session::lint; use rustc_session::parse::feature_err; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -1691,6 +1692,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat let mut is_trait = None; let mut is_default_impl_trait = None; + let mut is_trait_associated_type = None; let icx = ItemCtxt::new(tcx, def_id); let constness = icx.default_constness_for_trait_bounds(); @@ -1700,7 +1702,12 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat let mut predicates = UniquePredicates::new(); let ast_generics = match node { - Node::TraitItem(item) => &item.generics, + Node::TraitItem(item) => { + if let hir::TraitItemKind::Type(bounds, _) = item.kind { + is_trait_associated_type = Some((bounds, item.span)); + } + &item.generics + } Node::ImplItem(item) => &item.generics, @@ -1924,10 +1931,21 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat } } - // Add predicates from associated type bounds. - if let Some((self_trait_ref, trait_items)) = is_trait { + // Add predicates from associated type bounds (`type X: Bound`) + if tcx.features().generic_associated_types { + // New behavior: bounds declared on associate type are predicates of that + // associated type. Not the default because it needs more testing. + if let Some((bounds, span)) = is_trait_associated_type { + let projection_ty = + tcx.mk_projection(def_id, InternalSubsts::identity_for_item(tcx, def_id)); + + predicates.extend(associated_item_bounds(tcx, def_id, bounds, projection_ty, span)) + } + } else if let Some((self_trait_ref, trait_items)) = is_trait { + // Current behavior: bounds declared on associate type are predicates + // of its parent trait. predicates.extend(trait_items.iter().flat_map(|trait_item_ref| { - associated_item_predicates(tcx, def_id, self_trait_ref, trait_item_ref) + trait_associated_item_predicates(tcx, def_id, self_trait_ref, trait_item_ref) })) } @@ -1957,7 +1975,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat result } -fn associated_item_predicates( +fn trait_associated_item_predicates( tcx: TyCtxt<'tcx>, def_id: DefId, self_trait_ref: ty::TraitRef<'tcx>, @@ -1970,92 +1988,40 @@ fn associated_item_predicates( _ => return Vec::new(), }; - let is_gat = !tcx.generics_of(item_def_id).params.is_empty(); - - let mut had_error = false; - - let mut unimplemented_error = |arg_kind: &str| { - if !had_error { - tcx.sess - .struct_span_err( - trait_item.span, - &format!("{}-generic associated types are not yet implemented", arg_kind), - ) - .note( - "for more information, see issue #44265 \ - for more information", - ) - .emit(); - had_error = true; - } - }; - - let mk_bound_param = |param: &ty::GenericParamDef, _: &_| { - match param.kind { - ty::GenericParamDefKind::Lifetime => tcx - .mk_region(ty::RegionKind::ReLateBound( - ty::INNERMOST, - ty::BoundRegion::BrNamed(param.def_id, param.name), - )) - .into(), - // FIXME(generic_associated_types): Use bound types and constants - // once they are handled by the trait system. - ty::GenericParamDefKind::Type { .. } => { - unimplemented_error("type"); - tcx.ty_error().into() - } - ty::GenericParamDefKind::Const => { - unimplemented_error("const"); - tcx.const_error(tcx.type_of(param.def_id)).into() - } - } - }; + if !tcx.generics_of(item_def_id).params.is_empty() { + // For GATs the substs provided to the mk_projection call below are + // wrong. We should emit a feature gate error if we get here so skip + // this type. + tcx.sess.delay_span_bug(trait_item.span, "gats used without feature gate"); + return Vec::new(); + } - let bound_substs = if is_gat { - // Given: - // - // trait X<'a, B, const C: usize> { - // type T<'d, E, const F: usize>: Default; - // } - // - // We need to create predicates on the trait: - // - // for<'d, E, const F: usize> - // >::T<'d, E, const F: usize>: Sized + Default - // - // We substitute escaping bound parameters for the generic - // arguments to the associated type which are then bound by - // the `Binder` around the the predicate. - // - // FIXME(generic_associated_types): Currently only lifetimes are handled. - self_trait_ref.substs.extend_to(tcx, item_def_id.to_def_id(), mk_bound_param) - } else { - self_trait_ref.substs - }; + let assoc_ty = tcx.mk_projection( + tcx.hir().local_def_id(trait_item.hir_id).to_def_id(), + self_trait_ref.substs, + ); - let assoc_ty = - tcx.mk_projection(tcx.hir().local_def_id(trait_item.hir_id).to_def_id(), bound_substs); + associated_item_bounds(tcx, def_id, bounds, assoc_ty, trait_item.span) +} +fn associated_item_bounds( + tcx: TyCtxt<'tcx>, + def_id: DefId, + bounds: &'tcx [hir::GenericBound<'tcx>], + projection_ty: Ty<'tcx>, + span: Span, +) -> Vec<(ty::Predicate<'tcx>, Span)> { let bounds = AstConv::compute_bounds( &ItemCtxt::new(tcx, def_id), - assoc_ty, + projection_ty, bounds, SizedByDefault::Yes, - trait_item.span, + span, ); - let predicates = bounds.predicates(tcx, assoc_ty); + let predicates = bounds.predicates(tcx, projection_ty); - if is_gat { - // We use shifts to get the regions that we're substituting to - // be bound by the binders in the `Predicate`s rather that - // escaping. - let shifted_in = ty::fold::shift_vars(tcx, &predicates, 1); - let substituted = shifted_in.subst(tcx, bound_substs); - ty::fold::shift_out_vars(tcx, &substituted, 1) - } else { - predicates - } + predicates } /// Converts a specific `GenericBound` from the AST into a set of @@ -2450,11 +2416,11 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { if let Some(list) = attr.meta_item_list() { for item in list.iter() { if item.check_name(sym::address) { - codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_SANITIZE_ADDRESS; + codegen_fn_attrs.no_sanitize |= SanitizerSet::ADDRESS; } else if item.check_name(sym::memory) { - codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_SANITIZE_MEMORY; + codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY; } else if item.check_name(sym::thread) { - codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_SANITIZE_THREAD; + codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD; } else { tcx.sess .struct_span_err(item.span(), "invalid argument for `no_sanitize`") @@ -2554,7 +2520,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { } } - if codegen_fn_attrs.flags.intersects(CodegenFnAttrFlags::NO_SANITIZE_ANY) { + if !codegen_fn_attrs.no_sanitize.is_empty() { if codegen_fn_attrs.inline == InlineAttr::Always { if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) { let hir_id = tcx.hir().as_local_hir_id(id.expect_local()); diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs index cf5f2ec69d8d8..3dd9c9c5c39db 100644 --- a/src/librustc_typeck/collect/type_of.rs +++ b/src/librustc_typeck/collect/type_of.rs @@ -10,8 +10,7 @@ use rustc_middle::hir::map::Map; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; -use rustc_session::parse::feature_err; -use rustc_span::symbol::{sym, Ident}; +use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; use rustc_trait_selection::traits; @@ -303,25 +302,22 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { GenericParamKind::Type { default: Some(ref ty), .. } => icx.to_ty(ty), GenericParamKind::Const { ty: ref hir_ty, .. } => { let ty = icx.to_ty(hir_ty); - if !tcx.features().const_compare_raw_pointers { - let err = match ty.peel_refs().kind { - ty::FnPtr(_) => Some("function pointers"), - ty::RawPtr(_) => Some("raw pointers"), - _ => None, - }; - if let Some(unsupported_type) = err { - feature_err( - &tcx.sess.parse_sess, - sym::const_compare_raw_pointers, + let err = match ty.peel_refs().kind { + ty::FnPtr(_) => Some("function pointers"), + ty::RawPtr(_) => Some("raw pointers"), + _ => None, + }; + if let Some(unsupported_type) = err { + tcx.sess + .struct_span_err( hir_ty.span, &format!( - "using {} as const generic parameters is unstable", + "using {} as const generic parameters is forbidden", unsupported_type ), ) .emit(); - }; - } + }; if traits::search_for_structural_match_violation(param.hir_id, param.span, tcx, ty) .is_some() { diff --git a/src/librustc_typeck/expr_use_visitor.rs b/src/librustc_typeck/expr_use_visitor.rs index 6baadb8febd36..b72fae96e4ca0 100644 --- a/src/librustc_typeck/expr_use_visitor.rs +++ b/src/librustc_typeck/expr_use_visitor.rs @@ -5,7 +5,7 @@ pub use self::ConsumeMode::*; // Export these here so that Clippy can use them. -pub use mc::{Place, PlaceBase, Projection}; +pub use mc::{PlaceBase, PlaceWithHirId, Projection}; use rustc_hir as hir; use rustc_hir::def::Res; @@ -25,13 +25,13 @@ use rustc_span::Span; pub trait Delegate<'tcx> { // The value found at `place` is either copied or moved, depending // on mode. - fn consume(&mut self, place: &mc::Place<'tcx>, mode: ConsumeMode); + fn consume(&mut self, place_with_id: &mc::PlaceWithHirId<'tcx>, mode: ConsumeMode); // The value found at `place` is being borrowed with kind `bk`. - fn borrow(&mut self, place: &mc::Place<'tcx>, bk: ty::BorrowKind); + fn borrow(&mut self, place_with_id: &mc::PlaceWithHirId<'tcx>, bk: ty::BorrowKind); - // The path at `place` is being assigned to. - fn mutate(&mut self, assignee_place: &mc::Place<'tcx>); + // The path at `place_with_id` is being assigned to. + fn mutate(&mut self, assignee_place: &mc::PlaceWithHirId<'tcx>); } #[derive(Copy, Clone, PartialEq, Debug)] @@ -113,11 +113,11 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { self.mc.tcx() } - fn delegate_consume(&mut self, place: &Place<'tcx>) { - debug!("delegate_consume(place={:?})", place); + fn delegate_consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>) { + debug!("delegate_consume(place_with_id={:?})", place_with_id); - let mode = copy_or_move(&self.mc, place); - self.delegate.consume(place, mode); + let mode = copy_or_move(&self.mc, place_with_id); + self.delegate.consume(place_with_id, mode); } fn consume_exprs(&mut self, exprs: &[hir::Expr<'_>]) { @@ -129,22 +129,22 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { pub fn consume_expr(&mut self, expr: &hir::Expr<'_>) { debug!("consume_expr(expr={:?})", expr); - let place = return_if_err!(self.mc.cat_expr(expr)); - self.delegate_consume(&place); + let place_with_id = return_if_err!(self.mc.cat_expr(expr)); + self.delegate_consume(&place_with_id); self.walk_expr(expr); } fn mutate_expr(&mut self, expr: &hir::Expr<'_>) { - let place = return_if_err!(self.mc.cat_expr(expr)); - self.delegate.mutate(&place); + let place_with_id = return_if_err!(self.mc.cat_expr(expr)); + self.delegate.mutate(&place_with_id); self.walk_expr(expr); } fn borrow_expr(&mut self, expr: &hir::Expr<'_>, bk: ty::BorrowKind) { debug!("borrow_expr(expr={:?}, bk={:?})", expr, bk); - let place = return_if_err!(self.mc.cat_expr(expr)); - self.delegate.borrow(&place, bk); + let place_with_id = return_if_err!(self.mc.cat_expr(expr)); + self.delegate.borrow(&place_with_id, bk); self.walk_expr(expr) } @@ -384,7 +384,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // Select just those fields of the `with` // expression that will actually be used - match with_place.ty.kind { + match with_place.place.ty.kind { ty::Adt(adt, substs) if adt.is_struct() => { // Consume those fields of the with expression that are needed. for (f_index, with_field) in adt.non_enum_variant().fields.iter().enumerate() { @@ -422,14 +422,14 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // process. fn walk_adjustment(&mut self, expr: &hir::Expr<'_>) { let adjustments = self.mc.tables.expr_adjustments(expr); - let mut place = return_if_err!(self.mc.cat_expr_unadjusted(expr)); + let mut place_with_id = return_if_err!(self.mc.cat_expr_unadjusted(expr)); for adjustment in adjustments { debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment); match adjustment.kind { adjustment::Adjust::NeverToAny | adjustment::Adjust::Pointer(_) => { // Creating a closure/fn-pointer or unsizing consumes // the input and stores it into the resulting rvalue. - self.delegate_consume(&place); + self.delegate_consume(&place_with_id); } adjustment::Adjust::Deref(None) => {} @@ -441,14 +441,15 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // this is an autoref of `x`. adjustment::Adjust::Deref(Some(ref deref)) => { let bk = ty::BorrowKind::from_mutbl(deref.mutbl); - self.delegate.borrow(&place, bk); + self.delegate.borrow(&place_with_id, bk); } adjustment::Adjust::Borrow(ref autoref) => { - self.walk_autoref(expr, &place, autoref); + self.walk_autoref(expr, &place_with_id, autoref); } } - place = return_if_err!(self.mc.cat_expr_adjusted(expr, place, &adjustment)); + place_with_id = + return_if_err!(self.mc.cat_expr_adjusted(expr, place_with_id, &adjustment)); } } @@ -458,7 +459,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { fn walk_autoref( &mut self, expr: &hir::Expr<'_>, - base_place: &mc::Place<'tcx>, + base_place: &mc::PlaceWithHirId<'tcx>, autoref: &adjustment::AutoBorrow<'tcx>, ) { debug!( @@ -479,7 +480,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } } - fn walk_arm(&mut self, discr_place: &Place<'tcx>, arm: &hir::Arm<'_>) { + fn walk_arm(&mut self, discr_place: &PlaceWithHirId<'tcx>, arm: &hir::Arm<'_>) { self.walk_pat(discr_place, &arm.pat); if let Some(hir::Guard::If(ref e)) = arm.guard { @@ -491,12 +492,12 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { /// Walks a pat that occurs in isolation (i.e., top-level of fn argument or /// let binding, and *not* a match arm or nested pat.) - fn walk_irrefutable_pat(&mut self, discr_place: &Place<'tcx>, pat: &hir::Pat<'_>) { + fn walk_irrefutable_pat(&mut self, discr_place: &PlaceWithHirId<'tcx>, pat: &hir::Pat<'_>) { self.walk_pat(discr_place, pat); } /// The core driver for walking a pattern - fn walk_pat(&mut self, discr_place: &Place<'tcx>, pat: &hir::Pat<'_>) { + fn walk_pat(&mut self, discr_place: &PlaceWithHirId<'tcx>, pat: &hir::Pat<'_>) { debug!("walk_pat(discr_place={:?}, pat={:?})", discr_place, pat); let tcx = self.tcx(); @@ -569,7 +570,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { closure_hir_id: hir::HirId, closure_span: Span, var_id: hir::HirId, - ) -> mc::McResult> { + ) -> mc::McResult> { // Create the place for the variable being borrowed, from the // perspective of the creator (parent) of the closure. let var_ty = self.mc.node_ty(var_id)?; @@ -579,7 +580,14 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { fn copy_or_move<'a, 'tcx>( mc: &mc::MemCategorizationContext<'a, 'tcx>, - place: &Place<'tcx>, + place_with_id: &PlaceWithHirId<'tcx>, ) -> ConsumeMode { - if !mc.type_is_copy_modulo_regions(place.ty, place.span) { Move } else { Copy } + if !mc.type_is_copy_modulo_regions( + place_with_id.place.ty, + mc.tcx().hir().span(place_with_id.hir_id), + ) { + Move + } else { + Copy + } } diff --git a/src/librustc_typeck/mem_categorization.rs b/src/librustc_typeck/mem_categorization.rs index 93d01ccd66f1e..d619d37be2d7b 100644 --- a/src/librustc_typeck/mem_categorization.rs +++ b/src/librustc_typeck/mem_categorization.rs @@ -74,22 +74,24 @@ pub enum PlaceBase { } #[derive(Clone, Debug)] -pub enum Projection<'tcx> { +pub enum ProjectionKind<'tcx> { /// A dereference of a pointer, reference or `Box` of the given type Deref(Ty<'tcx>), /// An index or a field Other, } +#[derive(Clone, Debug)] +pub struct Projection<'tcx> { + /// Defines the type of access + kind: ProjectionKind<'tcx>, +} + /// A `Place` represents how a value is located in memory. /// /// This is an HIR version of `mir::Place` #[derive(Clone, Debug)] pub struct Place<'tcx> { - /// `HirId` of the expression or pattern producing this value. - pub hir_id: hir::HirId, - /// The `Span` of the expression or pattern producing this value. - pub span: Span, /// The type of the `Place` pub ty: Ty<'tcx>, /// The "outermost" place that holds this value. @@ -98,6 +100,32 @@ pub struct Place<'tcx> { pub projections: Vec>, } +/// A `PlaceWithHirId` represents how a value is located in memory. +/// +/// This is an HIR version of `mir::Place` +#[derive(Clone, Debug)] +pub struct PlaceWithHirId<'tcx> { + /// `HirId` of the expression or pattern producing this value. + pub hir_id: hir::HirId, + + /// Information about the `Place` + pub place: Place<'tcx>, +} + +impl<'tcx> PlaceWithHirId<'tcx> { + crate fn new( + hir_id: hir::HirId, + ty: Ty<'tcx>, + base: PlaceBase, + projections: Vec>, + ) -> PlaceWithHirId<'tcx> { + PlaceWithHirId { + hir_id: hir_id, + place: Place { ty: ty, base: base, projections: projections }, + } + } +} + impl<'tcx> Place<'tcx> { /// Returns an iterator of the types that have to be dereferenced to access /// the `Place`. @@ -107,7 +135,7 @@ impl<'tcx> Place<'tcx> { ///`*const u32` then `&*const u32`. crate fn deref_tys(&self) -> impl Iterator> + '_ { self.projections.iter().rev().filter_map(|proj| { - if let Projection::Deref(deref_ty) = *proj { Some(deref_ty) } else { None } + if let ProjectionKind::Deref(deref_ty) = proj.kind { Some(deref_ty) } else { None } }) } } @@ -280,14 +308,14 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { Ok(ret_ty) } - crate fn cat_expr(&self, expr: &hir::Expr<'_>) -> McResult> { + crate fn cat_expr(&self, expr: &hir::Expr<'_>) -> McResult> { // This recursion helper avoids going through *too many* // adjustments, since *only* non-overloaded deref recurses. fn helper<'a, 'tcx>( mc: &MemCategorizationContext<'a, 'tcx>, expr: &hir::Expr<'_>, adjustments: &[adjustment::Adjustment<'tcx>], - ) -> McResult> { + ) -> McResult> { match adjustments.split_last() { None => mc.cat_expr_unadjusted(expr), Some((adjustment, previous)) => { @@ -302,9 +330,9 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { crate fn cat_expr_adjusted( &self, expr: &hir::Expr<'_>, - previous: Place<'tcx>, + previous: PlaceWithHirId<'tcx>, adjustment: &adjustment::Adjustment<'tcx>, - ) -> McResult> { + ) -> McResult> { self.cat_expr_adjusted_with(expr, || Ok(previous), adjustment) } @@ -313,9 +341,9 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { expr: &hir::Expr<'_>, previous: F, adjustment: &adjustment::Adjustment<'tcx>, - ) -> McResult> + ) -> McResult> where - F: FnOnce() -> McResult>, + F: FnOnce() -> McResult>, { debug!("cat_expr_adjusted_with({:?}): {:?}", adjustment, expr); let target = self.resolve_vars_if_possible(&adjustment.target); @@ -342,7 +370,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { } } - crate fn cat_expr_unadjusted(&self, expr: &hir::Expr<'_>) -> McResult> { + crate fn cat_expr_unadjusted(&self, expr: &hir::Expr<'_>) -> McResult> { debug!("cat_expr: id={} expr={:?}", expr.hir_id, expr); let expr_ty = self.expr_ty(expr)?; @@ -418,7 +446,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { span: Span, expr_ty: Ty<'tcx>, res: Res, - ) -> McResult> { + ) -> McResult> { debug!("cat_res: id={:?} expr={:?} def={:?}", hir_id, expr_ty, res); match res { @@ -433,25 +461,15 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { ) | Res::SelfCtor(..) => Ok(self.cat_rvalue(hir_id, span, expr_ty)), - Res::Def(DefKind::Static, _) => Ok(Place { - hir_id, - span, - ty: expr_ty, - base: PlaceBase::StaticItem, - projections: Vec::new(), - }), + Res::Def(DefKind::Static, _) => { + Ok(PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::StaticItem, Vec::new())) + } Res::Local(var_id) => { if self.upvars.map_or(false, |upvars| upvars.contains_key(&var_id)) { - self.cat_upvar(hir_id, span, var_id) + self.cat_upvar(hir_id, var_id) } else { - Ok(Place { - hir_id, - span, - ty: expr_ty, - base: PlaceBase::Local(var_id), - projections: Vec::new(), - }) + Ok(PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Local(var_id), Vec::new())) } } @@ -464,12 +482,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { /// Note: the actual upvar access contains invisible derefs of closure /// environment and upvar reference as appropriate. Only regionck cares /// about these dereferences, so we let it compute them as needed. - fn cat_upvar( - &self, - hir_id: hir::HirId, - span: Span, - var_id: hir::HirId, - ) -> McResult> { + fn cat_upvar(&self, hir_id: hir::HirId, var_id: hir::HirId) -> McResult> { let closure_expr_def_id = self.body_owner; let upvar_id = ty::UpvarId { @@ -478,22 +491,20 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { }; let var_ty = self.node_ty(var_id)?; - let ret = Place { - hir_id, - span, - ty: var_ty, - base: PlaceBase::Upvar(upvar_id), - projections: Vec::new(), - }; + let ret = PlaceWithHirId::new(hir_id, var_ty, PlaceBase::Upvar(upvar_id), Vec::new()); debug!("cat_upvar ret={:?}", ret); Ok(ret) } - crate fn cat_rvalue(&self, hir_id: hir::HirId, span: Span, expr_ty: Ty<'tcx>) -> Place<'tcx> { + crate fn cat_rvalue( + &self, + hir_id: hir::HirId, + span: Span, + expr_ty: Ty<'tcx>, + ) -> PlaceWithHirId<'tcx> { debug!("cat_rvalue hir_id={:?}, expr_ty={:?}, span={:?}", hir_id, expr_ty, span); - let ret = - Place { hir_id, span, base: PlaceBase::Rvalue, projections: Vec::new(), ty: expr_ty }; + let ret = PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Rvalue, Vec::new()); debug!("cat_rvalue ret={:?}", ret); ret } @@ -501,18 +512,12 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { crate fn cat_projection( &self, node: &N, - base_place: Place<'tcx>, + base_place: PlaceWithHirId<'tcx>, ty: Ty<'tcx>, - ) -> Place<'tcx> { - let mut projections = base_place.projections; - projections.push(Projection::Other); - let ret = Place { - hir_id: node.hir_id(), - span: node.span(), - ty, - base: base_place.base, - projections, - }; + ) -> PlaceWithHirId<'tcx> { + let mut projections = base_place.place.projections; + projections.push(Projection { kind: ProjectionKind::Other }); + let ret = PlaceWithHirId::new(node.hir_id(), ty, base_place.place.base, projections); debug!("cat_field ret {:?}", ret); ret } @@ -521,7 +526,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { &self, expr: &hir::Expr<'_>, base: &hir::Expr<'_>, - ) -> McResult> { + ) -> McResult> { debug!("cat_overloaded_place(expr={:?}, base={:?})", expr, base); // Reconstruct the output assuming it's a reference with the @@ -540,10 +545,14 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { self.cat_deref(expr, base) } - fn cat_deref(&self, node: &impl HirNode, base_place: Place<'tcx>) -> McResult> { + fn cat_deref( + &self, + node: &impl HirNode, + base_place: PlaceWithHirId<'tcx>, + ) -> McResult> { debug!("cat_deref: base_place={:?}", base_place); - let base_ty = base_place.ty; + let base_ty = base_place.place.ty; let deref_ty = match base_ty.builtin_deref(true) { Some(mt) => mt.ty, None => { @@ -551,28 +560,22 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { return Err(()); } }; - let mut projections = base_place.projections; - projections.push(Projection::Deref(base_ty)); - - let ret = Place { - hir_id: node.hir_id(), - span: node.span(), - ty: deref_ty, - base: base_place.base, - projections, - }; + let mut projections = base_place.place.projections; + projections.push(Projection { kind: ProjectionKind::Deref(base_ty) }); + + let ret = PlaceWithHirId::new(node.hir_id(), deref_ty, base_place.place.base, projections); debug!("cat_deref ret {:?}", ret); Ok(ret) } crate fn cat_pattern( &self, - place: Place<'tcx>, + place: PlaceWithHirId<'tcx>, pat: &hir::Pat<'_>, mut op: F, ) -> McResult<()> where - F: FnMut(&Place<'tcx>, &hir::Pat<'_>), + F: FnMut(&PlaceWithHirId<'tcx>, &hir::Pat<'_>), { self.cat_pattern_(place, pat, &mut op) } @@ -580,24 +583,24 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { // FIXME(#19596) This is a workaround, but there should be a better way to do this fn cat_pattern_( &self, - mut place: Place<'tcx>, + mut place_with_id: PlaceWithHirId<'tcx>, pat: &hir::Pat<'_>, op: &mut F, ) -> McResult<()> where - F: FnMut(&Place<'tcx>, &hir::Pat<'_>), + F: FnMut(&PlaceWithHirId<'tcx>, &hir::Pat<'_>), { - // Here, `place` is the `Place` being matched and pat is the pattern it + // Here, `place` is the `PlaceWithHirId` being matched and pat is the pattern it // is being matched against. // // In general, the way that this works is that we walk down the pattern, - // constructing a `Place` that represents the path that will be taken + // constructing a `PlaceWithHirId` that represents the path that will be taken // to reach the value being matched. - debug!("cat_pattern(pat={:?}, place={:?})", pat, place); + debug!("cat_pattern(pat={:?}, place_with_id={:?})", pat, place_with_id); - // If (pattern) adjustments are active for this pattern, adjust the `Place` correspondingly. - // `Place`s are constructed differently from patterns. For example, in + // If (pattern) adjustments are active for this pattern, adjust the `PlaceWithHirId` correspondingly. + // `PlaceWithHirId`s are constructed differently from patterns. For example, in // // ``` // match foo { @@ -607,7 +610,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { // ``` // // the pattern `&&Some(x,)` is represented as `Ref { Ref { TupleStruct }}`. To build the - // corresponding `Place` we start with the `Place` for `foo`, and then, by traversing the + // corresponding `PlaceWithHirId` we start with the `PlaceWithHirId` for `foo`, and then, by traversing the // pattern, try to answer the question: given the address of `foo`, how is `x` reached? // // `&&Some(x,)` `place_foo` @@ -629,29 +632,29 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { // `deref { deref { place_foo }}` instead of `place_foo` since the pattern is now `Some(x,)` // and not `&&Some(x,)`, even though its assigned type is that of `&&Some(x,)`. for _ in 0..self.tables.pat_adjustments().get(pat.hir_id).map(|v| v.len()).unwrap_or(0) { - debug!("cat_pattern: applying adjustment to place={:?}", place); - place = self.cat_deref(pat, place)?; + debug!("cat_pattern: applying adjustment to place_with_id={:?}", place_with_id); + place_with_id = self.cat_deref(pat, place_with_id)?; } - let place = place; // lose mutability - debug!("cat_pattern: applied adjustment derefs to get place={:?}", place); + let place_with_id = place_with_id; // lose mutability + debug!("cat_pattern: applied adjustment derefs to get place_with_id={:?}", place_with_id); - // Invoke the callback, but only now, after the `place` has adjusted. + // Invoke the callback, but only now, after the `place_with_id` has adjusted. // // To see that this makes sense, consider `match &Some(3) { Some(x) => { ... }}`. In that - // case, the initial `place` will be that for `&Some(3)` and the pattern is `Some(x)`. We + // case, the initial `place_with_id` will be that for `&Some(3)` and the pattern is `Some(x)`. We // don't want to call `op` with these incompatible values. As written, what happens instead // is that `op` is called with the adjusted place (that for `*&Some(3)`) and the pattern // `Some(x)` (which matches). Recursing once more, `*&Some(3)` and the pattern `Some(x)` // result in the place `Downcast(*&Some(3)).0` associated to `x` and invoke `op` with // that (where the `ref` on `x` is implied). - op(&place, pat); + op(&place_with_id, pat); match pat.kind { PatKind::TupleStruct(_, ref subpats, _) | PatKind::Tuple(ref subpats, _) => { // S(p1, ..., pN) or (p1, ..., pN) for subpat in subpats.iter() { let subpat_ty = self.pat_ty_adjusted(&subpat)?; - let sub_place = self.cat_projection(pat, place.clone(), subpat_ty); + let sub_place = self.cat_projection(pat, place_with_id.clone(), subpat_ty); self.cat_pattern_(sub_place, &subpat, op)?; } } @@ -660,44 +663,44 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { // S { f1: p1, ..., fN: pN } for fp in field_pats { let field_ty = self.pat_ty_adjusted(&fp.pat)?; - let field_place = self.cat_projection(pat, place.clone(), field_ty); + let field_place = self.cat_projection(pat, place_with_id.clone(), field_ty); self.cat_pattern_(field_place, &fp.pat, op)?; } } PatKind::Or(pats) => { for pat in pats { - self.cat_pattern_(place.clone(), &pat, op)?; + self.cat_pattern_(place_with_id.clone(), &pat, op)?; } } PatKind::Binding(.., Some(ref subpat)) => { - self.cat_pattern_(place, &subpat, op)?; + self.cat_pattern_(place_with_id, &subpat, op)?; } PatKind::Box(ref subpat) | PatKind::Ref(ref subpat, _) => { // box p1, &p1, &mut p1. we can ignore the mutability of // PatKind::Ref since that information is already contained // in the type. - let subplace = self.cat_deref(pat, place)?; + let subplace = self.cat_deref(pat, place_with_id)?; self.cat_pattern_(subplace, &subpat, op)?; } PatKind::Slice(before, ref slice, after) => { - let element_ty = match place.ty.builtin_index() { + let element_ty = match place_with_id.place.ty.builtin_index() { Some(ty) => ty, None => { - debug!("explicit index of non-indexable type {:?}", place); + debug!("explicit index of non-indexable type {:?}", place_with_id); return Err(()); } }; - let elt_place = self.cat_projection(pat, place.clone(), element_ty); + let elt_place = self.cat_projection(pat, place_with_id.clone(), element_ty); for before_pat in before { self.cat_pattern_(elt_place.clone(), &before_pat, op)?; } if let Some(ref slice_pat) = *slice { let slice_pat_ty = self.pat_ty_adjusted(&slice_pat)?; - let slice_place = self.cat_projection(pat, place, slice_pat_ty); + let slice_place = self.cat_projection(pat, place_with_id, slice_pat_ty); self.cat_pattern_(slice_place, &slice_pat, op)?; } for after_pat in after { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 5c76c840b1ddd..6dec016cc2ee3 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -486,6 +486,33 @@ impl Attributes { }) } + /// Enforce the format of attributes inside `#[doc(...)]`. + pub fn check_doc_attributes( + diagnostic: &::rustc_errors::Handler, + mi: &ast::MetaItem, + ) -> Option<(String, String)> { + mi.meta_item_list().and_then(|list| { + for meta in list { + if meta.check_name(sym::alias) { + if !meta.is_value_str() + || meta + .value_str() + .map(|s| s.to_string()) + .unwrap_or_else(String::new) + .is_empty() + { + diagnostic.span_err( + meta.span(), + "doc alias attribute expects a string: #[doc(alias = \"0\")]", + ); + } + } + } + + None + }) + } + pub fn has_doc_flag(&self, flag: Symbol) -> bool { for attr in &self.other_attrs { if !attr.check_name(sym::doc) { @@ -529,6 +556,7 @@ impl Attributes { } else { if attr.check_name(sym::doc) { if let Some(mi) = attr.meta() { + Attributes::check_doc_attributes(&diagnostic, &mi); if let Some(cfg_mi) = Attributes::extract_cfg(&mi) { // Extracted #[doc(cfg(...))] match Cfg::parse(cfg_mi) { diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 8d53b05795374..59bb206678f51 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -1015,12 +1015,13 @@ function defocusSearchBar() { var aliases = []; var crateAliases = []; var i; - if (filterCrates !== undefined && - ALIASES[filterCrates] && - ALIASES[filterCrates][query.search]) { - for (i = 0; i < ALIASES[crate][query.search].length; ++i) { - aliases.push( - createAliasFromItem(searchIndex[ALIASES[filterCrates][query.search]])); + if (filterCrates !== undefined) { + if (ALIASES[filterCrates] && ALIASES[filterCrates][query.search]) { + for (i = 0; i < ALIASES[filterCrates][query.search].length; ++i) { + aliases.push( + createAliasFromItem( + searchIndex[ALIASES[filterCrates][query.search][i]])); + } } } else { Object.keys(ALIASES).forEach(function(crate) { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 95d113166e001..de6fa3dbd4a89 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -9,7 +9,6 @@ #![feature(nll)] #![feature(or_patterns)] #![feature(test)] -#![feature(vec_remove_item)] #![feature(ptr_offset_from)] #![feature(crate_visibility_modifier)] #![feature(never_type)] diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs index d80a38819ead0..f7248e7547e27 100644 --- a/src/libstd/io/error.rs +++ b/src/libstd/io/error.rs @@ -160,6 +160,11 @@ pub enum ErrorKind { #[stable(feature = "rust1", since = "1.0.0")] Interrupted, /// Any I/O error not part of this list. + /// + /// Errors that are `Other` now may move to a different or a new + /// [`ErrorKind`] variant in the future. It is not recommended to match + /// an error against `Other` and to expect any additional characteristics, + /// e.g., a specific [`Error::raw_os_error`] return value. #[stable(feature = "rust1", since = "1.0.0")] Other, diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index b8fa1a7f744d3..8c8d1aadf48e2 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -964,6 +964,14 @@ impl ToSocketAddrs for (&str, u16) { } } +#[stable(feature = "string_u16_to_socket_addrs", since = "1.46.0")] +impl ToSocketAddrs for (String, u16) { + type Iter = vec::IntoIter; + fn to_socket_addrs(&self) -> io::Result> { + (&*self.0, self.1).to_socket_addrs() + } +} + // accepts strings like 'localhost:12345' #[stable(feature = "rust1", since = "1.0.0")] impl ToSocketAddrs for str { diff --git a/src/libstd/prelude/mod.rs b/src/libstd/prelude/mod.rs index 3085c3d829653..48f7cf169885f 100644 --- a/src/libstd/prelude/mod.rs +++ b/src/libstd/prelude/mod.rs @@ -10,22 +10,6 @@ //! things, particularly traits, which are used in almost every single Rust //! program. //! -//! On a technical level, Rust inserts -//! -//! ``` -//! # #[allow(unused_extern_crates)] -//! extern crate std; -//! ``` -//! -//! into the crate root of every crate, and -//! -//! ``` -//! # #[allow(unused_imports)] -//! use std::prelude::v1::*; -//! ``` -//! -//! into every module. -//! //! # Other preludes //! //! Preludes can be seen as a pattern to make using multiple types more diff --git a/src/libstd/sys/hermit/stdio.rs b/src/libstd/sys/hermit/stdio.rs index 208265de465ad..f3654ee38716c 100644 --- a/src/libstd/sys/hermit/stdio.rs +++ b/src/libstd/sys/hermit/stdio.rs @@ -10,19 +10,19 @@ impl Stdin { pub fn new() -> io::Result { Ok(Stdin) } +} - pub fn read(&self, data: &mut [u8]) -> io::Result { +impl io::Read for Stdin { + fn read(&mut self, data: &mut [u8]) -> io::Result { self.read_vectored(&mut [IoSliceMut::new(data)]) } - pub fn read_vectored(&self, _data: &mut [IoSliceMut<'_>]) -> io::Result { - //ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDIN_FILENO as u32) }) - // .read(data) + fn read_vectored(&mut self, _data: &mut [IoSliceMut<'_>]) -> io::Result { Ok(0) } #[inline] - pub fn is_read_vectored(&self) -> bool { + fn is_read_vectored(&self) -> bool { true } } @@ -31,8 +31,10 @@ impl Stdout { pub fn new() -> io::Result { Ok(Stdout) } +} - pub fn write(&self, data: &[u8]) -> io::Result { +impl io::Write for Stdout { + fn write(&mut self, data: &[u8]) -> io::Result { let len; unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) } @@ -44,7 +46,7 @@ impl Stdout { } } - pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result { + fn write_vectored(&mut self, data: &[IoSlice<'_>]) -> io::Result { let len; unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) } @@ -57,11 +59,11 @@ impl Stdout { } #[inline] - pub fn is_write_vectored(&self) -> bool { + fn is_write_vectored(&self) -> bool { true } - pub fn flush(&self) -> io::Result<()> { + fn flush(&mut self) -> io::Result<()> { Ok(()) } } @@ -70,8 +72,10 @@ impl Stderr { pub fn new() -> io::Result { Ok(Stderr) } +} - pub fn write(&self, data: &[u8]) -> io::Result { +impl io::Write for Stderr { + fn write(&mut self, data: &[u8]) -> io::Result { let len; unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) } @@ -83,7 +87,7 @@ impl Stderr { } } - pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result { + fn write_vectored(&mut self, data: &[IoSlice<'_>]) -> io::Result { let len; unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) } @@ -96,21 +100,12 @@ impl Stderr { } #[inline] - pub fn is_write_vectored(&self) -> bool { + fn is_write_vectored(&self) -> bool { true } - pub fn flush(&self) -> io::Result<()> { - Ok(()) - } -} - -impl io::Write for Stderr { - fn write(&mut self, data: &[u8]) -> io::Result { - (&*self).write(data) - } fn flush(&mut self) -> io::Result<()> { - (&*self).flush() + Ok(()) } } diff --git a/src/libstd/sys/sgx/abi/entry.S b/src/libstd/sys/sgx/abi/entry.S index 2badfc973c972..fc6ce5770338e 100644 --- a/src/libstd/sys/sgx/abi/entry.S +++ b/src/libstd/sys/sgx/abi/entry.S @@ -26,18 +26,10 @@ IMAGE_BASE: .Lxsave_clear: .org .+24 .Lxsave_mxcsr: - .int 0 + .short 0x1f80 /* We can store a bunch of data in the gap between MXCSR and the XSAVE header */ -/* MXCSR initialization value for ABI */ -.Lmxcsr_init: - .int 0x1f80 - -/* x87 FPU control word initialization value for ABI */ -.Lfpucw_init: - .int 0x037f - /* The following symbols point at read-only data that will be filled in by the */ /* post-linker. */ @@ -177,13 +169,17 @@ sgx_entry: jz .Lskip_debug_init mov %r10,%gs:tcsls_debug_panic_buf_ptr .Lskip_debug_init: +/* reset cpu state */ + mov %rdx, %r10 + mov $-1, %rax + mov $-1, %rdx + xrstor .Lxsave_clear(%rip) + mov %r10, %rdx + /* check if returning from usercall */ mov %gs:tcsls_last_rsp,%r11 test %r11,%r11 jnz .Lusercall_ret -/* reset user state */ - ldmxcsr .Lmxcsr_init(%rip) - fldcw .Lfpucw_init(%rip) /* setup stack */ mov %gs:tcsls_tos,%rsp /* initially, RSP is not set to the correct value */ /* here. This is fixed below under "adjust stack". */ diff --git a/src/libstd/sys/unix/args.rs b/src/libstd/sys/unix/args.rs index 4c3e8542d576d..1d1cdda1257aa 100644 --- a/src/libstd/sys/unix/args.rs +++ b/src/libstd/sys/unix/args.rs @@ -205,6 +205,7 @@ mod imp { #[cfg(target_arch = "aarch64")] extern "C" { fn objc_msgSend(obj: NsId, sel: Sel) -> NsId; + #[cfg_attr(not(bootstrap), allow(clashing_extern_decl))] #[link_name = "objc_msgSend"] fn objc_msgSend_ul(obj: NsId, sel: Sel, i: libc::c_ulong) -> NsId; } @@ -212,6 +213,7 @@ mod imp { #[cfg(not(target_arch = "aarch64"))] extern "C" { fn objc_msgSend(obj: NsId, sel: Sel, ...) -> NsId; + #[cfg_attr(not(bootstrap), allow(clashing_extern_decl))] #[link_name = "objc_msgSend"] fn objc_msgSend_ul(obj: NsId, sel: Sel, ...) -> NsId; } diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index 2d7267263dedf..6e33cdd3c4826 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -428,6 +428,7 @@ mod tests { // ignored there. #[cfg_attr(target_arch = "arm", ignore)] #[cfg_attr(target_arch = "aarch64", ignore)] + #[cfg_attr(target_arch = "riscv64", ignore)] fn test_process_mask() { unsafe { // Test to make sure that a signal mask does not get inherited. diff --git a/src/libstd/sys/wasi/stdio.rs b/src/libstd/sys/wasi/stdio.rs index 9f9e35566ecf5..78e3911dc4efe 100644 --- a/src/libstd/sys/wasi/stdio.rs +++ b/src/libstd/sys/wasi/stdio.rs @@ -11,22 +11,25 @@ impl Stdin { Ok(Stdin) } - pub fn read(&self, data: &mut [u8]) -> io::Result { + #[inline] + pub fn as_raw_fd(&self) -> u32 { + 0 + } +} + +impl io::Read for Stdin { + fn read(&mut self, data: &mut [u8]) -> io::Result { self.read_vectored(&mut [IoSliceMut::new(data)]) } - pub fn read_vectored(&self, data: &mut [IoSliceMut<'_>]) -> io::Result { + fn read_vectored(&mut self, data: &mut [IoSliceMut<'_>]) -> io::Result { ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).read(data) } #[inline] - pub fn is_read_vectored(&self) -> bool { + fn is_read_vectored(&self) -> bool { true } - - pub fn as_raw_fd(&self) -> u32 { - 0 - } } impl Stdout { @@ -34,26 +37,28 @@ impl Stdout { Ok(Stdout) } - pub fn write(&self, data: &[u8]) -> io::Result { + #[inline] + pub fn as_raw_fd(&self) -> u32 { + 1 + } +} + +impl io::Write for Stdout { + fn write(&mut self, data: &[u8]) -> io::Result { self.write_vectored(&[IoSlice::new(data)]) } - pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result { + fn write_vectored(&mut self, data: &[IoSlice<'_>]) -> io::Result { ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).write(data) } #[inline] - pub fn is_write_vectored(&self) -> bool { + fn is_write_vectored(&self) -> bool { true } - - pub fn flush(&self) -> io::Result<()> { + fn flush(&mut self) -> io::Result<()> { Ok(()) } - - pub fn as_raw_fd(&self) -> u32 { - 1 - } } impl Stderr { @@ -61,23 +66,7 @@ impl Stderr { Ok(Stderr) } - pub fn write(&self, data: &[u8]) -> io::Result { - self.write_vectored(&[IoSlice::new(data)]) - } - - pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result { - ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).write(data) - } - #[inline] - pub fn is_write_vectored(&self) -> bool { - true - } - - pub fn flush(&self) -> io::Result<()> { - Ok(()) - } - pub fn as_raw_fd(&self) -> u32 { 2 } @@ -85,11 +74,20 @@ impl Stderr { impl io::Write for Stderr { fn write(&mut self, data: &[u8]) -> io::Result { - (&*self).write(data) + self.write_vectored(&[IoSlice::new(data)]) + } + + fn write_vectored(&mut self, data: &[IoSlice<'_>]) -> io::Result { + ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).write(data) + } + + #[inline] + fn is_write_vectored(&self) -> bool { + true } fn flush(&mut self) -> io::Result<()> { - (&*self).flush() + Ok(()) } } diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 6115d652b0cea..f440442ca3062 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -161,6 +161,8 @@ pub const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD; pub const PROGRESS_CONTINUE: DWORD = 0; +// List of Windows system error codes with descriptions: +// https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes#system-error-codes pub const ERROR_FILE_NOT_FOUND: DWORD = 2; pub const ERROR_PATH_NOT_FOUND: DWORD = 3; pub const ERROR_ACCESS_DENIED: DWORD = 5; @@ -171,13 +173,26 @@ pub const ERROR_FILE_EXISTS: DWORD = 80; pub const ERROR_INVALID_PARAMETER: DWORD = 87; pub const ERROR_BROKEN_PIPE: DWORD = 109; pub const ERROR_CALL_NOT_IMPLEMENTED: DWORD = 120; +pub const ERROR_SEM_TIMEOUT: DWORD = 121; pub const ERROR_INSUFFICIENT_BUFFER: DWORD = 122; pub const ERROR_ALREADY_EXISTS: DWORD = 183; -pub const ERROR_NO_DATA: DWORD = 232; pub const ERROR_ENVVAR_NOT_FOUND: DWORD = 203; +pub const ERROR_NO_DATA: DWORD = 232; +pub const ERROR_DRIVER_CANCEL_TIMEOUT: DWORD = 594; pub const ERROR_OPERATION_ABORTED: DWORD = 995; pub const ERROR_IO_PENDING: DWORD = 997; -pub const ERROR_TIMEOUT: DWORD = 0x5B4; +pub const ERROR_SERVICE_REQUEST_TIMEOUT: DWORD = 1053; +pub const ERROR_COUNTER_TIMEOUT: DWORD = 1121; +pub const ERROR_TIMEOUT: DWORD = 1460; +pub const ERROR_RESOURCE_CALL_TIMED_OUT: DWORD = 5910; +pub const ERROR_CTX_MODEM_RESPONSE_TIMEOUT: DWORD = 7012; +pub const ERROR_CTX_CLIENT_QUERY_TIMEOUT: DWORD = 7040; +pub const FRS_ERR_SYSVOL_POPULATE_TIMEOUT: DWORD = 8014; +pub const ERROR_DS_TIMELIMIT_EXCEEDED: DWORD = 8226; +pub const DNS_ERROR_RECORD_TIMED_OUT: DWORD = 9705; +pub const ERROR_IPSEC_IKE_TIMED_OUT: DWORD = 13805; +pub const ERROR_RUNLEVEL_SWITCH_TIMEOUT: DWORD = 15402; +pub const ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT: DWORD = 15403; pub const E_NOTIMPL: HRESULT = 0x80004001u32 as HRESULT; diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index d63139d8052c2..640c9f3636d4b 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -61,7 +61,22 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { c::ERROR_FILE_NOT_FOUND => return ErrorKind::NotFound, c::ERROR_PATH_NOT_FOUND => return ErrorKind::NotFound, c::ERROR_NO_DATA => return ErrorKind::BrokenPipe, - c::ERROR_OPERATION_ABORTED => return ErrorKind::TimedOut, + c::ERROR_SEM_TIMEOUT + | c::WAIT_TIMEOUT + | c::ERROR_DRIVER_CANCEL_TIMEOUT + | c::ERROR_OPERATION_ABORTED + | c::ERROR_SERVICE_REQUEST_TIMEOUT + | c::ERROR_COUNTER_TIMEOUT + | c::ERROR_TIMEOUT + | c::ERROR_RESOURCE_CALL_TIMED_OUT + | c::ERROR_CTX_MODEM_RESPONSE_TIMEOUT + | c::ERROR_CTX_CLIENT_QUERY_TIMEOUT + | c::FRS_ERR_SYSVOL_POPULATE_TIMEOUT + | c::ERROR_DS_TIMELIMIT_EXCEEDED + | c::DNS_ERROR_RECORD_TIMED_OUT + | c::ERROR_IPSEC_IKE_TIMED_OUT + | c::ERROR_RUNLEVEL_SWITCH_TIMEOUT + | c::ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT => return ErrorKind::TimedOut, _ => {} } diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 295ebcbb72939..84fa35e01bb09 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -811,11 +811,11 @@ mod tests { // Right now for CI this test is run in an emulator, and apparently the // aarch64 emulator's sense of time is that we're still living in the - // 70s. + // 70s. This is also true for riscv (also qemu) // // Otherwise let's assume that we're all running computers later than // 2000. - if !cfg!(target_arch = "aarch64") { + if !cfg!(target_arch = "aarch64") && !cfg!(target_arch = "riscv64") { assert!(a > thirty_years); } diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 323bd26c698a3..9bc111c26ba6b 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -717,11 +717,12 @@ enum class LLVMRustOptStage { }; struct LLVMRustSanitizerOptions { + bool SanitizeAddress; + bool SanitizeAddressRecover; bool SanitizeMemory; + bool SanitizeMemoryRecover; + int SanitizeMemoryTrackOrigins; bool SanitizeThread; - bool SanitizeAddress; - bool SanitizeRecover; - int SanitizeMemoryTrackOrigins; }; extern "C" void @@ -808,7 +809,7 @@ LLVMRustOptimizeWithNewPassManager( if (SanitizerOptions->SanitizeMemory) { MemorySanitizerOptions Options( SanitizerOptions->SanitizeMemoryTrackOrigins, - SanitizerOptions->SanitizeRecover, + SanitizerOptions->SanitizeMemoryRecover, /*CompileKernel=*/false); #if LLVM_VERSION_GE(10, 0) PipelineStartEPCallbacks.push_back([Options](ModulePassManager &MPM) { @@ -842,14 +843,14 @@ LLVMRustOptimizeWithNewPassManager( OptimizerLastEPCallbacks.push_back( [SanitizerOptions](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) { FPM.addPass(AddressSanitizerPass( - /*CompileKernel=*/false, SanitizerOptions->SanitizeRecover, + /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover, /*UseAfterScope=*/true)); } ); PipelineStartEPCallbacks.push_back( [SanitizerOptions](ModulePassManager &MPM) { MPM.addPass(ModuleAddressSanitizerPass( - /*CompileKernel=*/false, SanitizerOptions->SanitizeRecover)); + /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover)); } ); } diff --git a/src/stage0.txt b/src/stage0.txt index 5e840b9db1994..769ec669bdc8d 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+1).0` for Cargo where they were released on `date`. -date: 2020-06-03 +date: 2020-06-16 rustc: beta cargo: beta diff --git a/src/test/assembly/asm/hexagon-types.rs b/src/test/assembly/asm/hexagon-types.rs new file mode 100644 index 0000000000000..ba2d8a363cd4e --- /dev/null +++ b/src/test/assembly/asm/hexagon-types.rs @@ -0,0 +1,130 @@ +// no-system-llvm +// assembly-output: emit-asm +// compile-flags: --target hexagon-unknown-linux-musl + +#![feature(no_core, lang_items, rustc_attrs, repr_simd)] +#![crate_type = "rlib"] +#![no_core] +#![allow(asm_sub_register, non_camel_case_types)] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! stringify { + () => {}; +} + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +type ptr = *const i32; + +impl Copy for i8 {} +impl Copy for i16 {} +impl Copy for i32 {} +impl Copy for f32 {} +impl Copy for ptr {} +extern "C" { + fn extern_func(); + static extern_static: u8; +} + +macro_rules! check { + ($func:ident $ty:ident $class:ident) => { + #[no_mangle] + pub unsafe fn $func(x: $ty) -> $ty { + // Hack to avoid function merging + extern "Rust" { + fn dont_merge(s: &str); + } + dont_merge(stringify!($func)); + + let y; + asm!("{} = {}", out($class) y, in($class) x); + y + } + }; +} + +// CHECK-LABEL: sym_static: +// CHECK: InlineAsm Start +// CHECK: r0 = #extern_static +// CHECK: InlineAsm End +#[no_mangle] +pub unsafe fn sym_static() { + // Hack to avoid function merging + extern "Rust" { + fn dont_merge(s: &str); + } + dont_merge(stringify!($func)); + + asm!("r0 = #{}", sym extern_static); +} + +// CHECK-LABEL: sym_fn: +// CHECK: InlineAsm Start +// CHECK: r0 = #extern_func +// CHECK: InlineAsm End +#[no_mangle] +pub unsafe fn sym_fn() { + // Hack to avoid function merging + extern "Rust" { + fn dont_merge(s: &str); + } + dont_merge(stringify!($func)); + + asm!("r0 = #{}", sym extern_func); +} + +// This is a test for multi-instruction packets, +// which require the escaped braces. +// +// CHECK-LABEL: packet: +// CHECK: InlineAsm Start +// CHECK: { +// CHECK: r{{[0-9]+}} = r0 +// CHECK: memw(r1) = r{{[0-9]+}} +// CHECK: } +// CHECK: InlineAsm End +#[no_mangle] +pub unsafe fn packet() { + let val = 1024; + asm!("{{ + {} = r0 + memw(r1) = {} + }}", out(reg) _, in(reg) &val); +} + +// CHECK-LABEL: ptr: +// CHECK: InlineAsm Start +// CHECK: r{{[0-9]+}} = r{{[0-9]+}} +// CHECK: InlineAsm End +check!(reg_ptr ptr reg); + +// CHECK-LABEL: reg_f32: +// CHECK: InlineAsm Start +// CHECK: r{{[0-9]+}} = r{{[0-9]+}} +// CHECK: InlineAsm End +check!(reg_f32 f32 reg); + +// CHECK-LABEL: reg_i32: +// CHECK: InlineAsm Start +// CHECK: r{{[0-9]+}} = r{{[0-9]+}} +// CHECK: InlineAsm End +check!(reg_i32 i32 reg); + +// CHECK-LABEL: reg_i8: +// CHECK: InlineAsm Start +// CHECK: r{{[0-9]+}} = r{{[0-9]+}} +// CHECK: InlineAsm End +check!(reg_i8 i8 reg); + +// CHECK-LABEL: reg_i16: +// CHECK: InlineAsm Start +// CHECK: r{{[0-9]+}} = r{{[0-9]+}} +// CHECK: InlineAsm End +check!(reg_i16 i16 reg); diff --git a/src/test/codegen/asm-multiple-options.rs b/src/test/codegen/asm-multiple-options.rs new file mode 100644 index 0000000000000..c702742bf1a63 --- /dev/null +++ b/src/test/codegen/asm-multiple-options.rs @@ -0,0 +1,53 @@ +// compile-flags: -O +// only-x86_64 + +#![crate_type = "rlib"] +#![feature(asm)] + +// CHECK-LABEL: @pure +// CHECK-NOT: asm +// CHECK: ret void +#[no_mangle] +pub unsafe fn pure(x: i32) { + let y: i32; + asm!("", out("ax") y, in("bx") x, options(pure), options(nomem)); +} + +pub static mut VAR: i32 = 0; +pub static mut DUMMY_OUTPUT: i32 = 0; + +// CHECK-LABEL: @readonly +// CHECK: call i32 asm +// CHECK: ret i32 1 +#[no_mangle] +pub unsafe fn readonly() -> i32 { + VAR = 1; + asm!("", out("ax") DUMMY_OUTPUT, options(pure), options(readonly)); + VAR +} + +// CHECK-LABEL: @nomem +// CHECK-NOT: store +// CHECK: call i32 asm +// CHECK: store +// CHECK: ret i32 2 +#[no_mangle] +pub unsafe fn nomem() -> i32 { + VAR = 1; + asm!("", out("ax") DUMMY_OUTPUT, options(pure), options(nomem)); + VAR = 2; + VAR +} + +// CHECK-LABEL: @not_nomem +// CHECK: store +// CHECK: call i32 asm +// CHECK: store +// CHECK: ret i32 2 +#[no_mangle] +pub unsafe fn not_nomem() -> i32 { + VAR = 1; + asm!("", out("ax") DUMMY_OUTPUT, options(pure), options(readonly)); + VAR = 2; + VAR +} diff --git a/src/test/codegen/cfguard_checks.rs b/src/test/codegen/cfguard_checks.rs index 40a7353eac045..96f9158f9d394 100644 --- a/src/test/codegen/cfguard_checks.rs +++ b/src/test/codegen/cfguard_checks.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z control_flow_guard=checks +// compile-flags: -Z control-flow-guard=checks #![crate_type = "lib"] diff --git a/src/test/codegen/cfguard_disabled.rs b/src/test/codegen/cfguard_disabled.rs index d1747931e15c8..1325ffc0f2595 100644 --- a/src/test/codegen/cfguard_disabled.rs +++ b/src/test/codegen/cfguard_disabled.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z control_flow_guard=disabled +// compile-flags: -Z control-flow-guard=no #![crate_type = "lib"] diff --git a/src/test/codegen/cfguard_nochecks.rs b/src/test/codegen/cfguard_nochecks.rs index c5d7afbae257b..ae1de4c4d26d5 100644 --- a/src/test/codegen/cfguard_nochecks.rs +++ b/src/test/codegen/cfguard_nochecks.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z control_flow_guard=nochecks +// compile-flags: -Z control-flow-guard=nochecks #![crate_type = "lib"] diff --git a/src/test/compile-fail/issue-52443.rs b/src/test/compile-fail/issue-52443.rs index 9761959335273..00aca1d14baa7 100644 --- a/src/test/compile-fail/issue-52443.rs +++ b/src/test/compile-fail/issue-52443.rs @@ -9,7 +9,7 @@ fn main() { [(); { for _ in 0usize.. {}; 0}]; //~^ ERROR `for` is not allowed in a `const` //~| ERROR calls in constants are limited to constant functions - //~| ERROR references in constants may only refer to immutable values + //~| ERROR mutable references are not allowed in constants //~| ERROR calls in constants are limited to constant functions //~| ERROR evaluation of constant value failed } diff --git a/src/test/compile-fail/specialization/issue-50452.rs b/src/test/compile-fail/specialization/issue-50452.rs index d9e5280c7e11d..958f0eb266801 100644 --- a/src/test/compile-fail/specialization/issue-50452.rs +++ b/src/test/compile-fail/specialization/issue-50452.rs @@ -1,6 +1,6 @@ // compile-fail - #![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete pub trait Foo { fn foo(); diff --git a/src/test/mir-opt/address-of/rustc.address_of_reborrow.SimplifyCfg-initial.after.mir b/src/test/mir-opt/address-of/rustc.address_of_reborrow.SimplifyCfg-initial.after.mir index 9742530bd812f..aeb38f3f91068 100644 --- a/src/test/mir-opt/address-of/rustc.address_of_reborrow.SimplifyCfg-initial.after.mir +++ b/src/test/mir-opt/address-of/rustc.address_of_reborrow.SimplifyCfg-initial.after.mir @@ -12,7 +12,7 @@ | 8: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) } at $DIR/address-of.rs:16:12: 16:24 | 9: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) } at $DIR/address-of.rs:16:12: 16:24 | 10: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) } at $DIR/address-of.rs:18:5: 18:18 -| 11: Canonical { max_universe: U3, variables: [CanonicalVarInfo { kind: Region(U3) }], value: Ty(*const dyn std::marker::Send) } at $DIR/address-of.rs:20:5: 20:25 +| 11: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*const dyn std::marker::Send) } at $DIR/address-of.rs:20:5: 20:25 | 12: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) } at $DIR/address-of.rs:23:12: 23:20 | 13: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) } at $DIR/address-of.rs:23:12: 23:20 | 14: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32; 10]) } at $DIR/address-of.rs:24:12: 24:28 @@ -22,7 +22,7 @@ | 18: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) } at $DIR/address-of.rs:26:12: 26:24 | 19: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) } at $DIR/address-of.rs:26:12: 26:24 | 20: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*mut ^0) } at $DIR/address-of.rs:28:5: 28:16 -| 21: Canonical { max_universe: U6, variables: [CanonicalVarInfo { kind: Region(U6) }], value: Ty(*mut dyn std::marker::Send) } at $DIR/address-of.rs:30:5: 30:23 +| 21: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*mut dyn std::marker::Send) } at $DIR/address-of.rs:30:5: 30:23 | 22: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*mut ^0) } at $DIR/address-of.rs:33:12: 33:18 | 23: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*mut ^0) } at $DIR/address-of.rs:33:12: 33:18 | 24: Canonical { max_universe: U0, variables: [], value: Ty(*mut [i32; 10]) } at $DIR/address-of.rs:34:12: 34:26 diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/32bit/rustc.main.ConstProp.diff index 7071f31dbf104..7ceec94d81e76 100644 --- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/32bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/32bit/rustc.main.ConstProp.diff @@ -46,22 +46,8 @@ // mir::Constant // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:7:23: 7:24 // + literal: Const { ty: usize, val: Value(Scalar(0x00000003)) } -- _7 = Len((*_1)); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 -- _8 = Lt(_6, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 -+ _7 = const 3usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 -+ // ty::Const -+ // + ty: usize -+ // + val: Value(Scalar(0x00000003)) -+ // mir::Constant -+ // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 -+ // + literal: Const { ty: usize, val: Value(Scalar(0x00000003)) } -+ _8 = const false; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 -+ // ty::Const -+ // + ty: bool -+ // + val: Value(Scalar(0x00)) -+ // mir::Constant -+ // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 -+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) } + _7 = Len((*_1)); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 + _8 = Lt(_6, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 } diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/64bit/rustc.main.ConstProp.diff index 15995ab070019..483a6f232ef79 100644 --- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/64bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/64bit/rustc.main.ConstProp.diff @@ -46,22 +46,8 @@ // mir::Constant // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:7:23: 7:24 // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000003)) } -- _7 = Len((*_1)); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 -- _8 = Lt(_6, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 -+ _7 = const 3usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 -+ // ty::Const -+ // + ty: usize -+ // + val: Value(Scalar(0x0000000000000003)) -+ // mir::Constant -+ // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 -+ // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000003)) } -+ _8 = const false; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 -+ // ty::Const -+ // + ty: bool -+ // + val: Value(Scalar(0x00)) -+ // mir::Constant -+ // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 -+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) } + _7 = Len((*_1)); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 + _8 = Lt(_6, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 } diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref/rustc.main.ConstProp.diff index 44203ac327ab1..0d703068d41f4 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref/rustc.main.ConstProp.diff @@ -23,13 +23,15 @@ // + ty: i32 // + val: Value(Scalar(0x0000002a)) // mir::Constant - // + span: $DIR/mutable_variable_aggregate_mut_ref.rs:5:18: 5:20 +- // + span: $DIR/mutable_variable_aggregate_mut_ref.rs:5:18: 5:20 ++ // + span: $DIR/mutable_variable_aggregate_mut_ref.rs:5:17: 5:25 // + literal: Const { ty: i32, val: Value(Scalar(0x0000002a)) } // ty::Const // + ty: i32 // + val: Value(Scalar(0x0000002b)) // mir::Constant - // + span: $DIR/mutable_variable_aggregate_mut_ref.rs:5:22: 5:24 +- // + span: $DIR/mutable_variable_aggregate_mut_ref.rs:5:22: 5:24 ++ // + span: $DIR/mutable_variable_aggregate_mut_ref.rs:5:17: 5:25 // + literal: Const { ty: i32, val: Value(Scalar(0x0000002b)) } StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:6:9: 6:10 _2 = &mut _1; // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:6:13: 6:19 diff --git a/src/test/mir-opt/const_prop_miscompile.rs b/src/test/mir-opt/const_prop_miscompile.rs new file mode 100644 index 0000000000000..043b22870f49e --- /dev/null +++ b/src/test/mir-opt/const_prop_miscompile.rs @@ -0,0 +1,22 @@ +#![feature(raw_ref_op)] + +// EMIT_MIR rustc.foo.ConstProp.diff +fn foo() { + let mut u = (1,); + *&mut u.0 = 5; + let y = { u.0 } == 5; +} + +// EMIT_MIR rustc.bar.ConstProp.diff +fn bar() { + let mut v = (1,); + unsafe { + *&raw mut v.0 = 5; + } + let y = { v.0 } == 5; +} + +fn main() { + foo(); + bar(); +} diff --git a/src/test/mir-opt/const_prop_miscompile/rustc.bar.ConstProp.diff b/src/test/mir-opt/const_prop_miscompile/rustc.bar.ConstProp.diff new file mode 100644 index 0000000000000..c87f67bf9f587 --- /dev/null +++ b/src/test/mir-opt/const_prop_miscompile/rustc.bar.ConstProp.diff @@ -0,0 +1,75 @@ +- // MIR for `bar` before ConstProp ++ // MIR for `bar` after ConstProp + + fn bar() -> () { + let mut _0: (); // return place in scope 0 at $DIR/const_prop_miscompile.rs:11:10: 11:10 + let mut _1: (i32,); // in scope 0 at $DIR/const_prop_miscompile.rs:12:9: 12:14 + let _2: (); // in scope 0 at $DIR/const_prop_miscompile.rs:13:5: 15:6 + let mut _3: *mut i32; // in scope 0 at $DIR/const_prop_miscompile.rs:14:10: 14:22 + let mut _5: i32; // in scope 0 at $DIR/const_prop_miscompile.rs:16:13: 16:20 + scope 1 { + debug v => _1; // in scope 1 at $DIR/const_prop_miscompile.rs:12:9: 12:14 + let _4: bool; // in scope 1 at $DIR/const_prop_miscompile.rs:16:9: 16:10 + scope 2 { + } + scope 3 { + debug y => _4; // in scope 3 at $DIR/const_prop_miscompile.rs:16:9: 16:10 + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/const_prop_miscompile.rs:12:9: 12:14 +- _1 = (const 1i32,); // scope 0 at $DIR/const_prop_miscompile.rs:12:17: 12:21 ++ _1 = const (1i32,); // scope 0 at $DIR/const_prop_miscompile.rs:12:17: 12:21 + // ty::Const +- // + ty: i32 ++ // + ty: (i32,) + // + val: Value(Scalar(0x00000001)) + // mir::Constant +- // + span: $DIR/const_prop_miscompile.rs:12:18: 12:19 +- // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) } ++ // + span: $DIR/const_prop_miscompile.rs:12:17: 12:21 ++ // + literal: Const { ty: (i32,), val: Value(Scalar(0x00000001)) } + StorageLive(_2); // scope 1 at $DIR/const_prop_miscompile.rs:13:5: 15:6 + StorageLive(_3); // scope 2 at $DIR/const_prop_miscompile.rs:14:10: 14:22 + _3 = &raw mut (_1.0: i32); // scope 2 at $DIR/const_prop_miscompile.rs:14:10: 14:22 + (*_3) = const 5i32; // scope 2 at $DIR/const_prop_miscompile.rs:14:9: 14:26 + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000005)) + // mir::Constant + // + span: $DIR/const_prop_miscompile.rs:14:25: 14:26 + // + literal: Const { ty: i32, val: Value(Scalar(0x00000005)) } + StorageDead(_3); // scope 2 at $DIR/const_prop_miscompile.rs:14:26: 14:27 + _2 = const (); // scope 2 at $DIR/const_prop_miscompile.rs:13:5: 15:6 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/const_prop_miscompile.rs:13:5: 15:6 + // + literal: Const { ty: (), val: Value(Scalar()) } + StorageDead(_2); // scope 1 at $DIR/const_prop_miscompile.rs:15:5: 15:6 + StorageLive(_4); // scope 1 at $DIR/const_prop_miscompile.rs:16:9: 16:10 + StorageLive(_5); // scope 1 at $DIR/const_prop_miscompile.rs:16:13: 16:20 + _5 = (_1.0: i32); // scope 1 at $DIR/const_prop_miscompile.rs:16:15: 16:18 + _4 = Eq(move _5, const 5i32); // scope 1 at $DIR/const_prop_miscompile.rs:16:13: 16:25 + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000005)) + // mir::Constant + // + span: $DIR/const_prop_miscompile.rs:16:24: 16:25 + // + literal: Const { ty: i32, val: Value(Scalar(0x00000005)) } + StorageDead(_5); // scope 1 at $DIR/const_prop_miscompile.rs:16:24: 16:25 + _0 = const (); // scope 0 at $DIR/const_prop_miscompile.rs:11:10: 17:2 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/const_prop_miscompile.rs:11:10: 17:2 + // + literal: Const { ty: (), val: Value(Scalar()) } + StorageDead(_4); // scope 1 at $DIR/const_prop_miscompile.rs:17:1: 17:2 + StorageDead(_1); // scope 0 at $DIR/const_prop_miscompile.rs:17:1: 17:2 + return; // scope 0 at $DIR/const_prop_miscompile.rs:17:2: 17:2 + } + } + diff --git a/src/test/mir-opt/const_prop_miscompile/rustc.foo.ConstProp.diff b/src/test/mir-opt/const_prop_miscompile/rustc.foo.ConstProp.diff new file mode 100644 index 0000000000000..8a6850d2fe3ad --- /dev/null +++ b/src/test/mir-opt/const_prop_miscompile/rustc.foo.ConstProp.diff @@ -0,0 +1,63 @@ +- // MIR for `foo` before ConstProp ++ // MIR for `foo` after ConstProp + + fn foo() -> () { + let mut _0: (); // return place in scope 0 at $DIR/const_prop_miscompile.rs:4:10: 4:10 + let mut _1: (i32,); // in scope 0 at $DIR/const_prop_miscompile.rs:5:9: 5:14 + let mut _2: &mut i32; // in scope 0 at $DIR/const_prop_miscompile.rs:6:6: 6:14 + let mut _4: i32; // in scope 0 at $DIR/const_prop_miscompile.rs:7:13: 7:20 + scope 1 { + debug u => _1; // in scope 1 at $DIR/const_prop_miscompile.rs:5:9: 5:14 + let _3: bool; // in scope 1 at $DIR/const_prop_miscompile.rs:7:9: 7:10 + scope 2 { + debug y => _3; // in scope 2 at $DIR/const_prop_miscompile.rs:7:9: 7:10 + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/const_prop_miscompile.rs:5:9: 5:14 +- _1 = (const 1i32,); // scope 0 at $DIR/const_prop_miscompile.rs:5:17: 5:21 ++ _1 = const (1i32,); // scope 0 at $DIR/const_prop_miscompile.rs:5:17: 5:21 + // ty::Const +- // + ty: i32 ++ // + ty: (i32,) + // + val: Value(Scalar(0x00000001)) + // mir::Constant +- // + span: $DIR/const_prop_miscompile.rs:5:18: 5:19 +- // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) } ++ // + span: $DIR/const_prop_miscompile.rs:5:17: 5:21 ++ // + literal: Const { ty: (i32,), val: Value(Scalar(0x00000001)) } + StorageLive(_2); // scope 1 at $DIR/const_prop_miscompile.rs:6:6: 6:14 + _2 = &mut (_1.0: i32); // scope 1 at $DIR/const_prop_miscompile.rs:6:6: 6:14 + (*_2) = const 5i32; // scope 1 at $DIR/const_prop_miscompile.rs:6:5: 6:18 + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000005)) + // mir::Constant + // + span: $DIR/const_prop_miscompile.rs:6:17: 6:18 + // + literal: Const { ty: i32, val: Value(Scalar(0x00000005)) } + StorageDead(_2); // scope 1 at $DIR/const_prop_miscompile.rs:6:18: 6:19 + StorageLive(_3); // scope 1 at $DIR/const_prop_miscompile.rs:7:9: 7:10 + StorageLive(_4); // scope 1 at $DIR/const_prop_miscompile.rs:7:13: 7:20 + _4 = (_1.0: i32); // scope 1 at $DIR/const_prop_miscompile.rs:7:15: 7:18 + _3 = Eq(move _4, const 5i32); // scope 1 at $DIR/const_prop_miscompile.rs:7:13: 7:25 + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000005)) + // mir::Constant + // + span: $DIR/const_prop_miscompile.rs:7:24: 7:25 + // + literal: Const { ty: i32, val: Value(Scalar(0x00000005)) } + StorageDead(_4); // scope 1 at $DIR/const_prop_miscompile.rs:7:24: 7:25 + _0 = const (); // scope 0 at $DIR/const_prop_miscompile.rs:4:10: 8:2 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/const_prop_miscompile.rs:4:10: 8:2 + // + literal: Const { ty: (), val: Value(Scalar()) } + StorageDead(_3); // scope 1 at $DIR/const_prop_miscompile.rs:8:1: 8:2 + StorageDead(_1); // scope 0 at $DIR/const_prop_miscompile.rs:8:1: 8:2 + return; // scope 0 at $DIR/const_prop_miscompile.rs:8:2: 8:2 + } + } + diff --git a/src/test/mir-opt/fn-ptr-shim.rs b/src/test/mir-opt/fn-ptr-shim.rs new file mode 100644 index 0000000000000..08413c9f6fceb --- /dev/null +++ b/src/test/mir-opt/fn-ptr-shim.rs @@ -0,0 +1,15 @@ +// compile-flags: -Zmir-opt-level=0 -Zvalidate-mir + +// Tests that the `` shim does not create a `Call` terminator with a `Self` callee +// (as only `FnDef` and `FnPtr` callees are allowed in MIR). + +// EMIT_MIR rustc.ops-function-Fn-call.AddMovesForPackedDrops.before.mir +fn main() { + call(noop as fn()); +} + +fn noop() {} + +fn call(f: F) { + f(); +} diff --git a/src/test/mir-opt/fn-ptr-shim/rustc.ops-function-Fn-call.AddMovesForPackedDrops.before.mir b/src/test/mir-opt/fn-ptr-shim/rustc.ops-function-Fn-call.AddMovesForPackedDrops.before.mir new file mode 100644 index 0000000000000..4ecc331afaeb9 --- /dev/null +++ b/src/test/mir-opt/fn-ptr-shim/rustc.ops-function-Fn-call.AddMovesForPackedDrops.before.mir @@ -0,0 +1,13 @@ +// MIR for `std::ops::Fn::call` before AddMovesForPackedDrops + +fn std::ops::Fn::call(_1: *const fn(), _2: Args) -> >::Output { + let mut _0: >::Output; // return place in scope 0 at $SRC_DIR/libcore/ops/function.rs:LL:COL + + bb0: { + _0 = move (*_1)() -> bb1; // scope 0 at $SRC_DIR/libcore/ops/function.rs:LL:COL + } + + bb1: { + return; // scope 0 at $SRC_DIR/libcore/ops/function.rs:LL:COL + } +} diff --git a/src/test/mir-opt/issue-72181-1.rs b/src/test/mir-opt/issue-72181-1.rs new file mode 100644 index 0000000000000..6d65f847a2c63 --- /dev/null +++ b/src/test/mir-opt/issue-72181-1.rs @@ -0,0 +1,21 @@ +// compile-flags: -Z mir-opt-level=1 +// Regression test for #72181, this ICE requires `-Z mir-opt-level=1` flags. + +#![feature(never_type)] +#![allow(unused, invalid_value)] + +enum Void {} + +// EMIT_MIR rustc.f.mir_map.0.mir +fn f(v: Void) -> ! { + match v {} +} + +// EMIT_MIR rustc.main.mir_map.0.mir +fn main() { + let v: Void = unsafe { + std::mem::transmute::<(), Void>(()) + }; + + f(v); +} diff --git a/src/test/mir-opt/issue-72181-1/rustc.f.mir_map.0.mir b/src/test/mir-opt/issue-72181-1/rustc.f.mir_map.0.mir new file mode 100644 index 0000000000000..1821365898e53 --- /dev/null +++ b/src/test/mir-opt/issue-72181-1/rustc.f.mir_map.0.mir @@ -0,0 +1,37 @@ +// MIR for `f` 0 mir_map + +fn f(_1: Void) -> ! { + debug v => _1; // in scope 0 at $DIR/issue-72181-1.rs:10:6: 10:7 + let mut _0: !; // return place in scope 0 at $DIR/issue-72181-1.rs:10:18: 10:19 + let mut _2: !; // in scope 0 at $DIR/issue-72181-1.rs:10:20: 12:2 + let mut _3: !; // in scope 0 at $DIR/issue-72181-1.rs:11:5: 11:15 + + bb0: { + StorageLive(_2); // scope 0 at $DIR/issue-72181-1.rs:10:20: 12:2 + StorageLive(_3); // scope 0 at $DIR/issue-72181-1.rs:11:5: 11:15 + FakeRead(ForMatchedPlace, _1); // scope 0 at $DIR/issue-72181-1.rs:11:11: 11:12 + unreachable; // scope 0 at $DIR/issue-72181-1.rs:11:11: 11:12 + } + + bb1 (cleanup): { + resume; // scope 0 at $DIR/issue-72181-1.rs:10:1: 12:2 + } + + bb2: { + unreachable; // scope 0 at $DIR/issue-72181-1.rs:11:5: 11:15 + } + + bb3: { + StorageDead(_3); // scope 0 at $DIR/issue-72181-1.rs:11:14: 11:15 + unreachable; // scope 0 at $DIR/issue-72181-1.rs:10:20: 12:2 + } + + bb4: { + StorageDead(_2); // scope 0 at $DIR/issue-72181-1.rs:12:1: 12:2 + goto -> bb5; // scope 0 at $DIR/issue-72181-1.rs:12:2: 12:2 + } + + bb5: { + return; // scope 0 at $DIR/issue-72181-1.rs:12:2: 12:2 + } +} diff --git a/src/test/mir-opt/issue-72181-1/rustc.main.mir_map.0.mir b/src/test/mir-opt/issue-72181-1/rustc.main.mir_map.0.mir new file mode 100644 index 0000000000000..b87d0294fb87b --- /dev/null +++ b/src/test/mir-opt/issue-72181-1/rustc.main.mir_map.0.mir @@ -0,0 +1,67 @@ +// MIR for `main` 0 mir_map + +| User Type Annotations +| 0: Canonical { max_universe: U0, variables: [], value: Ty(Void) } at $DIR/issue-72181-1.rs:16:12: 16:16 +| 1: Canonical { max_universe: U0, variables: [], value: Ty(Void) } at $DIR/issue-72181-1.rs:16:12: 16:16 +| +fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/issue-72181-1.rs:15:11: 15:11 + let mut _1: !; // in scope 0 at $DIR/issue-72181-1.rs:15:11: 21:2 + let _2: Void as UserTypeProjection { base: UserType(0), projs: [] }; // in scope 0 at $DIR/issue-72181-1.rs:16:9: 16:10 + let mut _3: (); // in scope 0 at $DIR/issue-72181-1.rs:17:41: 17:43 + let _4: !; // in scope 0 at $DIR/issue-72181-1.rs:20:5: 20:9 + let mut _5: Void; // in scope 0 at $DIR/issue-72181-1.rs:20:7: 20:8 + scope 1 { + debug v => _2; // in scope 1 at $DIR/issue-72181-1.rs:16:9: 16:10 + } + scope 2 { + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/issue-72181-1.rs:16:9: 16:10 + StorageLive(_3); // scope 2 at $DIR/issue-72181-1.rs:17:41: 17:43 + _3 = (); // scope 2 at $DIR/issue-72181-1.rs:17:41: 17:43 + _2 = const std::intrinsics::transmute::<(), Void>(move _3) -> [return: bb2, unwind: bb1]; // scope 2 at $DIR/issue-72181-1.rs:17:9: 17:44 + // ty::Const + // + ty: unsafe extern "rust-intrinsic" fn(()) -> Void {std::intrinsics::transmute::<(), Void>} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/issue-72181-1.rs:17:9: 17:40 + // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(()) -> Void {std::intrinsics::transmute::<(), Void>}, val: Value(Scalar()) } + } + + bb1 (cleanup): { + resume; // scope 0 at $DIR/issue-72181-1.rs:15:1: 21:2 + } + + bb2: { + StorageDead(_3); // scope 2 at $DIR/issue-72181-1.rs:17:43: 17:44 + FakeRead(ForLet, _2); // scope 0 at $DIR/issue-72181-1.rs:16:9: 16:10 + AscribeUserType(_2, o, UserTypeProjection { base: UserType(1), projs: [] }); // scope 0 at $DIR/issue-72181-1.rs:16:12: 16:16 + StorageLive(_4); // scope 1 at $DIR/issue-72181-1.rs:20:5: 20:9 + StorageLive(_5); // scope 1 at $DIR/issue-72181-1.rs:20:7: 20:8 + _5 = move _2; // scope 1 at $DIR/issue-72181-1.rs:20:7: 20:8 + const f(move _5) -> bb1; // scope 1 at $DIR/issue-72181-1.rs:20:5: 20:9 + // ty::Const + // + ty: fn(Void) -> ! {f} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/issue-72181-1.rs:20:5: 20:6 + // + literal: Const { ty: fn(Void) -> ! {f}, val: Value(Scalar()) } + } + + bb3: { + StorageDead(_5); // scope 1 at $DIR/issue-72181-1.rs:20:8: 20:9 + StorageDead(_4); // scope 1 at $DIR/issue-72181-1.rs:20:9: 20:10 + StorageDead(_2); // scope 0 at $DIR/issue-72181-1.rs:21:1: 21:2 + unreachable; // scope 0 at $DIR/issue-72181-1.rs:15:11: 21:2 + } + + bb4: { + goto -> bb5; // scope 0 at $DIR/issue-72181-1.rs:21:2: 21:2 + } + + bb5: { + return; // scope 0 at $DIR/issue-72181-1.rs:21:2: 21:2 + } +} diff --git a/src/test/mir-opt/issue-72181.rs b/src/test/mir-opt/issue-72181.rs new file mode 100644 index 0000000000000..9373ce12032b9 --- /dev/null +++ b/src/test/mir-opt/issue-72181.rs @@ -0,0 +1,28 @@ +// compile-flags: -Z mir-opt-level=1 +// Regression test for #72181, this ICE requires `-Z mir-opt-level=1` flags. + +use std::mem; + +#[derive(Copy, Clone)] +enum Never {} + +union Foo { + a: u64, + b: Never +} + +// EMIT_MIR_FOR_EACH_BIT_WIDTH +// EMIT_MIR rustc.foo.mir_map.0.mir +fn foo(xs: [(Never, u32); 1]) -> u32 { xs[0].1 } + +// EMIT_MIR rustc.bar.mir_map.0.mir +fn bar([(_, x)]: [(Never, u32); 1]) -> u32 { x } + +// EMIT_MIR_FOR_EACH_BIT_WIDTH +// EMIT_MIR rustc.main.mir_map.0.mir +fn main() { + let _ = mem::size_of::(); + + let f = [Foo { a: 42 }, Foo { a: 10 }]; + let _ = unsafe { f[0].a }; +} diff --git a/src/test/mir-opt/issue-72181/32bit/rustc.bar.mir_map.0.mir b/src/test/mir-opt/issue-72181/32bit/rustc.bar.mir_map.0.mir new file mode 100644 index 0000000000000..29654c2b1f83b --- /dev/null +++ b/src/test/mir-opt/issue-72181/32bit/rustc.bar.mir_map.0.mir @@ -0,0 +1,25 @@ +// MIR for `bar` 0 mir_map + +fn bar(_1: [(Never, u32); 1]) -> u32 { + let mut _0: u32; // return place in scope 0 at $DIR/issue-72181.rs:19:40: 19:43 + let _2: u32; // in scope 0 at $DIR/issue-72181.rs:19:13: 19:14 + scope 1 { + debug x => _2; // in scope 1 at $DIR/issue-72181.rs:19:13: 19:14 + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/issue-72181.rs:19:13: 19:14 + _2 = (_1[0 of 1].1: u32); // scope 0 at $DIR/issue-72181.rs:19:13: 19:14 + _0 = _2; // scope 1 at $DIR/issue-72181.rs:19:46: 19:47 + StorageDead(_2); // scope 0 at $DIR/issue-72181.rs:19:48: 19:49 + goto -> bb2; // scope 0 at $DIR/issue-72181.rs:19:49: 19:49 + } + + bb1 (cleanup): { + resume; // scope 0 at $DIR/issue-72181.rs:19:1: 19:49 + } + + bb2: { + return; // scope 0 at $DIR/issue-72181.rs:19:49: 19:49 + } +} diff --git a/src/test/mir-opt/issue-72181/32bit/rustc.foo.mir_map.0.mir b/src/test/mir-opt/issue-72181/32bit/rustc.foo.mir_map.0.mir new file mode 100644 index 0000000000000..776eb61a5264f --- /dev/null +++ b/src/test/mir-opt/issue-72181/32bit/rustc.foo.mir_map.0.mir @@ -0,0 +1,37 @@ +// MIR for `foo` 0 mir_map + +fn foo(_1: [(Never, u32); 1]) -> u32 { + debug xs => _1; // in scope 0 at $DIR/issue-72181.rs:16:8: 16:10 + let mut _0: u32; // return place in scope 0 at $DIR/issue-72181.rs:16:34: 16:37 + let _2: usize; // in scope 0 at $DIR/issue-72181.rs:16:43: 16:44 + let mut _3: usize; // in scope 0 at $DIR/issue-72181.rs:16:40: 16:45 + let mut _4: bool; // in scope 0 at $DIR/issue-72181.rs:16:40: 16:45 + + bb0: { + StorageLive(_2); // scope 0 at $DIR/issue-72181.rs:16:43: 16:44 + _2 = const 0usize; // scope 0 at $DIR/issue-72181.rs:16:43: 16:44 + // ty::Const + // + ty: usize + // + val: Value(Scalar(0x00000000)) + // mir::Constant + // + span: $DIR/issue-72181.rs:16:43: 16:44 + // + literal: Const { ty: usize, val: Value(Scalar(0x00000000)) } + _3 = Len(_1); // scope 0 at $DIR/issue-72181.rs:16:40: 16:45 + _4 = Lt(_2, _3); // scope 0 at $DIR/issue-72181.rs:16:40: 16:45 + assert(move _4, "index out of bounds: the len is {} but the index is {}", move _3, _2) -> [success: bb2, unwind: bb1]; // scope 0 at $DIR/issue-72181.rs:16:40: 16:45 + } + + bb1 (cleanup): { + resume; // scope 0 at $DIR/issue-72181.rs:16:1: 16:49 + } + + bb2: { + _0 = (_1[_2].1: u32); // scope 0 at $DIR/issue-72181.rs:16:40: 16:47 + StorageDead(_2); // scope 0 at $DIR/issue-72181.rs:16:48: 16:49 + goto -> bb3; // scope 0 at $DIR/issue-72181.rs:16:49: 16:49 + } + + bb3: { + return; // scope 0 at $DIR/issue-72181.rs:16:49: 16:49 + } +} diff --git a/src/test/mir-opt/issue-72181/32bit/rustc.main.mir_map.0.mir b/src/test/mir-opt/issue-72181/32bit/rustc.main.mir_map.0.mir new file mode 100644 index 0000000000000..aa44dcd8eaee3 --- /dev/null +++ b/src/test/mir-opt/issue-72181/32bit/rustc.main.mir_map.0.mir @@ -0,0 +1,93 @@ +// MIR for `main` 0 mir_map + +fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/issue-72181.rs:23:11: 23:11 + let mut _1: usize; // in scope 0 at $DIR/issue-72181.rs:24:13: 24:34 + let mut _3: Foo; // in scope 0 at $DIR/issue-72181.rs:26:14: 26:27 + let mut _4: Foo; // in scope 0 at $DIR/issue-72181.rs:26:29: 26:42 + let mut _5: u64; // in scope 0 at $DIR/issue-72181.rs:27:13: 27:30 + let _6: usize; // in scope 0 at $DIR/issue-72181.rs:27:24: 27:25 + let mut _7: usize; // in scope 0 at $DIR/issue-72181.rs:27:22: 27:26 + let mut _8: bool; // in scope 0 at $DIR/issue-72181.rs:27:22: 27:26 + scope 1 { + let _2: [Foo; 2]; // in scope 1 at $DIR/issue-72181.rs:26:9: 26:10 + scope 2 { + debug f => _2; // in scope 2 at $DIR/issue-72181.rs:26:9: 26:10 + scope 3 { + } + scope 4 { + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/issue-72181.rs:24:13: 24:34 + _1 = const std::mem::size_of::() -> [return: bb2, unwind: bb1]; // scope 0 at $DIR/issue-72181.rs:24:13: 24:34 + // ty::Const + // + ty: fn() -> usize {std::mem::size_of::} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/issue-72181.rs:24:13: 24:32 + // + literal: Const { ty: fn() -> usize {std::mem::size_of::}, val: Value(Scalar()) } + } + + bb1 (cleanup): { + resume; // scope 0 at $DIR/issue-72181.rs:23:1: 28:2 + } + + bb2: { + StorageDead(_1); // scope 0 at $DIR/issue-72181.rs:24:34: 24:35 + StorageLive(_2); // scope 1 at $DIR/issue-72181.rs:26:9: 26:10 + StorageLive(_3); // scope 1 at $DIR/issue-72181.rs:26:14: 26:27 + _3 = Foo { a: const 42u64 }; // scope 1 at $DIR/issue-72181.rs:26:14: 26:27 + // ty::Const + // + ty: u64 + // + val: Value(Scalar(0x000000000000002a)) + // mir::Constant + // + span: $DIR/issue-72181.rs:26:23: 26:25 + // + literal: Const { ty: u64, val: Value(Scalar(0x000000000000002a)) } + StorageLive(_4); // scope 1 at $DIR/issue-72181.rs:26:29: 26:42 + _4 = Foo { a: const 10u64 }; // scope 1 at $DIR/issue-72181.rs:26:29: 26:42 + // ty::Const + // + ty: u64 + // + val: Value(Scalar(0x000000000000000a)) + // mir::Constant + // + span: $DIR/issue-72181.rs:26:38: 26:40 + // + literal: Const { ty: u64, val: Value(Scalar(0x000000000000000a)) } + _2 = [move _3, move _4]; // scope 1 at $DIR/issue-72181.rs:26:13: 26:43 + StorageDead(_4); // scope 1 at $DIR/issue-72181.rs:26:42: 26:43 + StorageDead(_3); // scope 1 at $DIR/issue-72181.rs:26:42: 26:43 + FakeRead(ForLet, _2); // scope 1 at $DIR/issue-72181.rs:26:9: 26:10 + StorageLive(_5); // scope 2 at $DIR/issue-72181.rs:27:13: 27:30 + StorageLive(_6); // scope 4 at $DIR/issue-72181.rs:27:24: 27:25 + _6 = const 0usize; // scope 4 at $DIR/issue-72181.rs:27:24: 27:25 + // ty::Const + // + ty: usize + // + val: Value(Scalar(0x00000000)) + // mir::Constant + // + span: $DIR/issue-72181.rs:27:24: 27:25 + // + literal: Const { ty: usize, val: Value(Scalar(0x00000000)) } + _7 = Len(_2); // scope 4 at $DIR/issue-72181.rs:27:22: 27:26 + _8 = Lt(_6, _7); // scope 4 at $DIR/issue-72181.rs:27:22: 27:26 + assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> [success: bb3, unwind: bb1]; // scope 4 at $DIR/issue-72181.rs:27:22: 27:26 + } + + bb3: { + _5 = (_2[_6].0: u64); // scope 4 at $DIR/issue-72181.rs:27:22: 27:28 + StorageDead(_6); // scope 2 at $DIR/issue-72181.rs:27:30: 27:31 + StorageDead(_5); // scope 2 at $DIR/issue-72181.rs:27:30: 27:31 + _0 = const (); // scope 0 at $DIR/issue-72181.rs:23:11: 28:2 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/issue-72181.rs:23:11: 28:2 + // + literal: Const { ty: (), val: Value(Scalar()) } + StorageDead(_2); // scope 1 at $DIR/issue-72181.rs:28:1: 28:2 + goto -> bb4; // scope 0 at $DIR/issue-72181.rs:28:2: 28:2 + } + + bb4: { + return; // scope 0 at $DIR/issue-72181.rs:28:2: 28:2 + } +} diff --git a/src/test/mir-opt/issue-72181/64bit/rustc.bar.mir_map.0.mir b/src/test/mir-opt/issue-72181/64bit/rustc.bar.mir_map.0.mir new file mode 100644 index 0000000000000..29654c2b1f83b --- /dev/null +++ b/src/test/mir-opt/issue-72181/64bit/rustc.bar.mir_map.0.mir @@ -0,0 +1,25 @@ +// MIR for `bar` 0 mir_map + +fn bar(_1: [(Never, u32); 1]) -> u32 { + let mut _0: u32; // return place in scope 0 at $DIR/issue-72181.rs:19:40: 19:43 + let _2: u32; // in scope 0 at $DIR/issue-72181.rs:19:13: 19:14 + scope 1 { + debug x => _2; // in scope 1 at $DIR/issue-72181.rs:19:13: 19:14 + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/issue-72181.rs:19:13: 19:14 + _2 = (_1[0 of 1].1: u32); // scope 0 at $DIR/issue-72181.rs:19:13: 19:14 + _0 = _2; // scope 1 at $DIR/issue-72181.rs:19:46: 19:47 + StorageDead(_2); // scope 0 at $DIR/issue-72181.rs:19:48: 19:49 + goto -> bb2; // scope 0 at $DIR/issue-72181.rs:19:49: 19:49 + } + + bb1 (cleanup): { + resume; // scope 0 at $DIR/issue-72181.rs:19:1: 19:49 + } + + bb2: { + return; // scope 0 at $DIR/issue-72181.rs:19:49: 19:49 + } +} diff --git a/src/test/mir-opt/issue-72181/64bit/rustc.foo.mir_map.0.mir b/src/test/mir-opt/issue-72181/64bit/rustc.foo.mir_map.0.mir new file mode 100644 index 0000000000000..639019eaf9ccc --- /dev/null +++ b/src/test/mir-opt/issue-72181/64bit/rustc.foo.mir_map.0.mir @@ -0,0 +1,37 @@ +// MIR for `foo` 0 mir_map + +fn foo(_1: [(Never, u32); 1]) -> u32 { + debug xs => _1; // in scope 0 at $DIR/issue-72181.rs:16:8: 16:10 + let mut _0: u32; // return place in scope 0 at $DIR/issue-72181.rs:16:34: 16:37 + let _2: usize; // in scope 0 at $DIR/issue-72181.rs:16:43: 16:44 + let mut _3: usize; // in scope 0 at $DIR/issue-72181.rs:16:40: 16:45 + let mut _4: bool; // in scope 0 at $DIR/issue-72181.rs:16:40: 16:45 + + bb0: { + StorageLive(_2); // scope 0 at $DIR/issue-72181.rs:16:43: 16:44 + _2 = const 0usize; // scope 0 at $DIR/issue-72181.rs:16:43: 16:44 + // ty::Const + // + ty: usize + // + val: Value(Scalar(0x0000000000000000)) + // mir::Constant + // + span: $DIR/issue-72181.rs:16:43: 16:44 + // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000000)) } + _3 = Len(_1); // scope 0 at $DIR/issue-72181.rs:16:40: 16:45 + _4 = Lt(_2, _3); // scope 0 at $DIR/issue-72181.rs:16:40: 16:45 + assert(move _4, "index out of bounds: the len is {} but the index is {}", move _3, _2) -> [success: bb2, unwind: bb1]; // scope 0 at $DIR/issue-72181.rs:16:40: 16:45 + } + + bb1 (cleanup): { + resume; // scope 0 at $DIR/issue-72181.rs:16:1: 16:49 + } + + bb2: { + _0 = (_1[_2].1: u32); // scope 0 at $DIR/issue-72181.rs:16:40: 16:47 + StorageDead(_2); // scope 0 at $DIR/issue-72181.rs:16:48: 16:49 + goto -> bb3; // scope 0 at $DIR/issue-72181.rs:16:49: 16:49 + } + + bb3: { + return; // scope 0 at $DIR/issue-72181.rs:16:49: 16:49 + } +} diff --git a/src/test/mir-opt/issue-72181/64bit/rustc.main.mir_map.0.mir b/src/test/mir-opt/issue-72181/64bit/rustc.main.mir_map.0.mir new file mode 100644 index 0000000000000..4098e0e295c5d --- /dev/null +++ b/src/test/mir-opt/issue-72181/64bit/rustc.main.mir_map.0.mir @@ -0,0 +1,93 @@ +// MIR for `main` 0 mir_map + +fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/issue-72181.rs:23:11: 23:11 + let mut _1: usize; // in scope 0 at $DIR/issue-72181.rs:24:13: 24:34 + let mut _3: Foo; // in scope 0 at $DIR/issue-72181.rs:26:14: 26:27 + let mut _4: Foo; // in scope 0 at $DIR/issue-72181.rs:26:29: 26:42 + let mut _5: u64; // in scope 0 at $DIR/issue-72181.rs:27:13: 27:30 + let _6: usize; // in scope 0 at $DIR/issue-72181.rs:27:24: 27:25 + let mut _7: usize; // in scope 0 at $DIR/issue-72181.rs:27:22: 27:26 + let mut _8: bool; // in scope 0 at $DIR/issue-72181.rs:27:22: 27:26 + scope 1 { + let _2: [Foo; 2]; // in scope 1 at $DIR/issue-72181.rs:26:9: 26:10 + scope 2 { + debug f => _2; // in scope 2 at $DIR/issue-72181.rs:26:9: 26:10 + scope 3 { + } + scope 4 { + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/issue-72181.rs:24:13: 24:34 + _1 = const std::mem::size_of::() -> [return: bb2, unwind: bb1]; // scope 0 at $DIR/issue-72181.rs:24:13: 24:34 + // ty::Const + // + ty: fn() -> usize {std::mem::size_of::} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/issue-72181.rs:24:13: 24:32 + // + literal: Const { ty: fn() -> usize {std::mem::size_of::}, val: Value(Scalar()) } + } + + bb1 (cleanup): { + resume; // scope 0 at $DIR/issue-72181.rs:23:1: 28:2 + } + + bb2: { + StorageDead(_1); // scope 0 at $DIR/issue-72181.rs:24:34: 24:35 + StorageLive(_2); // scope 1 at $DIR/issue-72181.rs:26:9: 26:10 + StorageLive(_3); // scope 1 at $DIR/issue-72181.rs:26:14: 26:27 + _3 = Foo { a: const 42u64 }; // scope 1 at $DIR/issue-72181.rs:26:14: 26:27 + // ty::Const + // + ty: u64 + // + val: Value(Scalar(0x000000000000002a)) + // mir::Constant + // + span: $DIR/issue-72181.rs:26:23: 26:25 + // + literal: Const { ty: u64, val: Value(Scalar(0x000000000000002a)) } + StorageLive(_4); // scope 1 at $DIR/issue-72181.rs:26:29: 26:42 + _4 = Foo { a: const 10u64 }; // scope 1 at $DIR/issue-72181.rs:26:29: 26:42 + // ty::Const + // + ty: u64 + // + val: Value(Scalar(0x000000000000000a)) + // mir::Constant + // + span: $DIR/issue-72181.rs:26:38: 26:40 + // + literal: Const { ty: u64, val: Value(Scalar(0x000000000000000a)) } + _2 = [move _3, move _4]; // scope 1 at $DIR/issue-72181.rs:26:13: 26:43 + StorageDead(_4); // scope 1 at $DIR/issue-72181.rs:26:42: 26:43 + StorageDead(_3); // scope 1 at $DIR/issue-72181.rs:26:42: 26:43 + FakeRead(ForLet, _2); // scope 1 at $DIR/issue-72181.rs:26:9: 26:10 + StorageLive(_5); // scope 2 at $DIR/issue-72181.rs:27:13: 27:30 + StorageLive(_6); // scope 4 at $DIR/issue-72181.rs:27:24: 27:25 + _6 = const 0usize; // scope 4 at $DIR/issue-72181.rs:27:24: 27:25 + // ty::Const + // + ty: usize + // + val: Value(Scalar(0x0000000000000000)) + // mir::Constant + // + span: $DIR/issue-72181.rs:27:24: 27:25 + // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000000)) } + _7 = Len(_2); // scope 4 at $DIR/issue-72181.rs:27:22: 27:26 + _8 = Lt(_6, _7); // scope 4 at $DIR/issue-72181.rs:27:22: 27:26 + assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> [success: bb3, unwind: bb1]; // scope 4 at $DIR/issue-72181.rs:27:22: 27:26 + } + + bb3: { + _5 = (_2[_6].0: u64); // scope 4 at $DIR/issue-72181.rs:27:22: 27:28 + StorageDead(_6); // scope 2 at $DIR/issue-72181.rs:27:30: 27:31 + StorageDead(_5); // scope 2 at $DIR/issue-72181.rs:27:30: 27:31 + _0 = const (); // scope 0 at $DIR/issue-72181.rs:23:11: 28:2 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/issue-72181.rs:23:11: 28:2 + // + literal: Const { ty: (), val: Value(Scalar()) } + StorageDead(_2); // scope 1 at $DIR/issue-72181.rs:28:1: 28:2 + goto -> bb4; // scope 0 at $DIR/issue-72181.rs:28:2: 28:2 + } + + bb4: { + return; // scope 0 at $DIR/issue-72181.rs:28:2: 28:2 + } +} diff --git a/src/test/mir-opt/issue-72181/rustc.bar.mir_map.0.mir b/src/test/mir-opt/issue-72181/rustc.bar.mir_map.0.mir new file mode 100644 index 0000000000000..3b6dc46d055cd --- /dev/null +++ b/src/test/mir-opt/issue-72181/rustc.bar.mir_map.0.mir @@ -0,0 +1,25 @@ +// MIR for `bar` 0 mir_map + +fn bar(_1: [(Never, u32); 1]) -> u32 { + let mut _0: u32; // return place in scope 0 at $DIR/issue-72181.rs:18:40: 18:43 + let _2: u32; // in scope 0 at $DIR/issue-72181.rs:18:13: 18:14 + scope 1 { + debug x => _2; // in scope 1 at $DIR/issue-72181.rs:18:13: 18:14 + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/issue-72181.rs:18:13: 18:14 + _2 = (_1[0 of 1].1: u32); // scope 0 at $DIR/issue-72181.rs:18:13: 18:14 + _0 = _2; // scope 1 at $DIR/issue-72181.rs:18:46: 18:47 + StorageDead(_2); // scope 0 at $DIR/issue-72181.rs:18:48: 18:49 + goto -> bb2; // scope 0 at $DIR/issue-72181.rs:18:49: 18:49 + } + + bb1 (cleanup): { + resume; // scope 0 at $DIR/issue-72181.rs:18:1: 18:49 + } + + bb2: { + return; // scope 0 at $DIR/issue-72181.rs:18:49: 18:49 + } +} diff --git a/src/test/mir-opt/issue-72181/rustc.foo.mir_map.0.mir b/src/test/mir-opt/issue-72181/rustc.foo.mir_map.0.mir new file mode 100644 index 0000000000000..2941e282cf42b --- /dev/null +++ b/src/test/mir-opt/issue-72181/rustc.foo.mir_map.0.mir @@ -0,0 +1,37 @@ +// MIR for `foo` 0 mir_map + +fn foo(_1: [(Never, u32); 1]) -> u32 { + debug xs => _1; // in scope 0 at $DIR/issue-72181.rs:15:8: 15:10 + let mut _0: u32; // return place in scope 0 at $DIR/issue-72181.rs:15:34: 15:37 + let _2: usize; // in scope 0 at $DIR/issue-72181.rs:15:43: 15:44 + let mut _3: usize; // in scope 0 at $DIR/issue-72181.rs:15:40: 15:45 + let mut _4: bool; // in scope 0 at $DIR/issue-72181.rs:15:40: 15:45 + + bb0: { + StorageLive(_2); // scope 0 at $DIR/issue-72181.rs:15:43: 15:44 + _2 = const 0usize; // scope 0 at $DIR/issue-72181.rs:15:43: 15:44 + // ty::Const + // + ty: usize + // + val: Value(Scalar(0x0000000000000000)) + // mir::Constant + // + span: $DIR/issue-72181.rs:15:43: 15:44 + // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000000)) } + _3 = Len(_1); // scope 0 at $DIR/issue-72181.rs:15:40: 15:45 + _4 = Lt(_2, _3); // scope 0 at $DIR/issue-72181.rs:15:40: 15:45 + assert(move _4, "index out of bounds: the len is {} but the index is {}", move _3, _2) -> [success: bb2, unwind: bb1]; // scope 0 at $DIR/issue-72181.rs:15:40: 15:45 + } + + bb1 (cleanup): { + resume; // scope 0 at $DIR/issue-72181.rs:15:1: 15:49 + } + + bb2: { + _0 = (_1[_2].1: u32); // scope 0 at $DIR/issue-72181.rs:15:40: 15:47 + StorageDead(_2); // scope 0 at $DIR/issue-72181.rs:15:48: 15:49 + goto -> bb3; // scope 0 at $DIR/issue-72181.rs:15:49: 15:49 + } + + bb3: { + return; // scope 0 at $DIR/issue-72181.rs:15:49: 15:49 + } +} diff --git a/src/test/mir-opt/issue-72181/rustc.main.mir_map.0.mir b/src/test/mir-opt/issue-72181/rustc.main.mir_map.0.mir new file mode 100644 index 0000000000000..65f4de0e23545 --- /dev/null +++ b/src/test/mir-opt/issue-72181/rustc.main.mir_map.0.mir @@ -0,0 +1,93 @@ +// MIR for `main` 0 mir_map + +fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/issue-72181.rs:21:11: 21:11 + let mut _1: usize; // in scope 0 at $DIR/issue-72181.rs:22:13: 22:34 + let mut _3: Foo; // in scope 0 at $DIR/issue-72181.rs:24:14: 24:27 + let mut _4: Foo; // in scope 0 at $DIR/issue-72181.rs:24:29: 24:42 + let mut _5: u64; // in scope 0 at $DIR/issue-72181.rs:25:13: 25:30 + let _6: usize; // in scope 0 at $DIR/issue-72181.rs:25:24: 25:25 + let mut _7: usize; // in scope 0 at $DIR/issue-72181.rs:25:22: 25:26 + let mut _8: bool; // in scope 0 at $DIR/issue-72181.rs:25:22: 25:26 + scope 1 { + let _2: [Foo; 2]; // in scope 1 at $DIR/issue-72181.rs:24:9: 24:10 + scope 2 { + debug f => _2; // in scope 2 at $DIR/issue-72181.rs:24:9: 24:10 + scope 3 { + } + scope 4 { + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/issue-72181.rs:22:13: 22:34 + _1 = const std::mem::size_of::() -> [return: bb2, unwind: bb1]; // scope 0 at $DIR/issue-72181.rs:22:13: 22:34 + // ty::Const + // + ty: fn() -> usize {std::mem::size_of::} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/issue-72181.rs:22:13: 22:32 + // + literal: Const { ty: fn() -> usize {std::mem::size_of::}, val: Value(Scalar()) } + } + + bb1 (cleanup): { + resume; // scope 0 at $DIR/issue-72181.rs:21:1: 26:2 + } + + bb2: { + StorageDead(_1); // scope 0 at $DIR/issue-72181.rs:22:34: 22:35 + StorageLive(_2); // scope 1 at $DIR/issue-72181.rs:24:9: 24:10 + StorageLive(_3); // scope 1 at $DIR/issue-72181.rs:24:14: 24:27 + _3 = Foo { a: const 42u64 }; // scope 1 at $DIR/issue-72181.rs:24:14: 24:27 + // ty::Const + // + ty: u64 + // + val: Value(Scalar(0x000000000000002a)) + // mir::Constant + // + span: $DIR/issue-72181.rs:24:23: 24:25 + // + literal: Const { ty: u64, val: Value(Scalar(0x000000000000002a)) } + StorageLive(_4); // scope 1 at $DIR/issue-72181.rs:24:29: 24:42 + _4 = Foo { a: const 10u64 }; // scope 1 at $DIR/issue-72181.rs:24:29: 24:42 + // ty::Const + // + ty: u64 + // + val: Value(Scalar(0x000000000000000a)) + // mir::Constant + // + span: $DIR/issue-72181.rs:24:38: 24:40 + // + literal: Const { ty: u64, val: Value(Scalar(0x000000000000000a)) } + _2 = [move _3, move _4]; // scope 1 at $DIR/issue-72181.rs:24:13: 24:43 + StorageDead(_4); // scope 1 at $DIR/issue-72181.rs:24:42: 24:43 + StorageDead(_3); // scope 1 at $DIR/issue-72181.rs:24:42: 24:43 + FakeRead(ForLet, _2); // scope 1 at $DIR/issue-72181.rs:24:9: 24:10 + StorageLive(_5); // scope 2 at $DIR/issue-72181.rs:25:13: 25:30 + StorageLive(_6); // scope 4 at $DIR/issue-72181.rs:25:24: 25:25 + _6 = const 0usize; // scope 4 at $DIR/issue-72181.rs:25:24: 25:25 + // ty::Const + // + ty: usize + // + val: Value(Scalar(0x0000000000000000)) + // mir::Constant + // + span: $DIR/issue-72181.rs:25:24: 25:25 + // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000000)) } + _7 = Len(_2); // scope 4 at $DIR/issue-72181.rs:25:22: 25:26 + _8 = Lt(_6, _7); // scope 4 at $DIR/issue-72181.rs:25:22: 25:26 + assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> [success: bb3, unwind: bb1]; // scope 4 at $DIR/issue-72181.rs:25:22: 25:26 + } + + bb3: { + _5 = (_2[_6].0: u64); // scope 4 at $DIR/issue-72181.rs:25:22: 25:28 + StorageDead(_6); // scope 2 at $DIR/issue-72181.rs:25:30: 25:31 + StorageDead(_5); // scope 2 at $DIR/issue-72181.rs:25:30: 25:31 + _0 = const (); // scope 0 at $DIR/issue-72181.rs:21:11: 26:2 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/issue-72181.rs:21:11: 26:2 + // + literal: Const { ty: (), val: Value(Scalar()) } + StorageDead(_2); // scope 1 at $DIR/issue-72181.rs:26:1: 26:2 + goto -> bb4; // scope 0 at $DIR/issue-72181.rs:26:2: 26:2 + } + + bb4: { + return; // scope 0 at $DIR/issue-72181.rs:26:2: 26:2 + } +} diff --git a/src/test/mir-opt/simplify-arm-identity/32bit/rustc.main.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify-arm-identity/32bit/rustc.main.SimplifyArmIdentity.diff index dfd6d6f0f2ecd..94759dca038b1 100644 --- a/src/test/mir-opt/simplify-arm-identity/32bit/rustc.main.SimplifyArmIdentity.diff +++ b/src/test/mir-opt/simplify-arm-identity/32bit/rustc.main.SimplifyArmIdentity.diff @@ -39,14 +39,13 @@ } bb1: { - ((_2 as Foo).0: u8) = const 0u8; // scope 1 at $DIR/simplify-arm-identity.rs:21:21: 21:32 + _2 = const Dst::Foo(0u8); // scope 1 at $DIR/simplify-arm-identity.rs:21:21: 21:32 // ty::Const - // + ty: u8 + // + ty: Dst // + val: Value(Scalar(0x00)) // mir::Constant - // + span: $DIR/simplify-arm-identity.rs:21:30: 21:31 - // + literal: Const { ty: u8, val: Value(Scalar(0x00)) } - discriminant(_2) = 0; // scope 1 at $DIR/simplify-arm-identity.rs:21:21: 21:32 + // + span: $DIR/simplify-arm-identity.rs:21:21: 21:32 + // + literal: Const { ty: Dst, val: Value(Scalar(0x00)) } goto -> bb4; // scope 1 at $DIR/simplify-arm-identity.rs:19:18: 22:6 } diff --git a/src/test/mir-opt/simplify-arm-identity/64bit/rustc.main.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify-arm-identity/64bit/rustc.main.SimplifyArmIdentity.diff index f2bbd19586993..ba21f16b685d4 100644 --- a/src/test/mir-opt/simplify-arm-identity/64bit/rustc.main.SimplifyArmIdentity.diff +++ b/src/test/mir-opt/simplify-arm-identity/64bit/rustc.main.SimplifyArmIdentity.diff @@ -39,14 +39,13 @@ } bb1: { - ((_2 as Foo).0: u8) = const 0u8; // scope 1 at $DIR/simplify-arm-identity.rs:21:21: 21:32 + _2 = const Dst::Foo(0u8); // scope 1 at $DIR/simplify-arm-identity.rs:21:21: 21:32 // ty::Const - // + ty: u8 + // + ty: Dst // + val: Value(Scalar(0x00)) // mir::Constant - // + span: $DIR/simplify-arm-identity.rs:21:30: 21:31 - // + literal: Const { ty: u8, val: Value(Scalar(0x00)) } - discriminant(_2) = 0; // scope 1 at $DIR/simplify-arm-identity.rs:21:21: 21:32 + // + span: $DIR/simplify-arm-identity.rs:21:21: 21:32 + // + literal: Const { ty: Dst, val: Value(Scalar(0x00)) } goto -> bb4; // scope 1 at $DIR/simplify-arm-identity.rs:19:18: 22:6 } diff --git a/src/test/mir-opt/simplify-arm-identity/rustc.main.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify-arm-identity/rustc.main.SimplifyArmIdentity.diff index b2517cb7012b4..e7373391b79c7 100644 --- a/src/test/mir-opt/simplify-arm-identity/rustc.main.SimplifyArmIdentity.diff +++ b/src/test/mir-opt/simplify-arm-identity/rustc.main.SimplifyArmIdentity.diff @@ -33,15 +33,14 @@ } bb1: { - ((_2 as Foo).0: u8) = const 0u8; // scope 1 at $DIR/simplify-arm-identity.rs:20:21: 20:32 + _2 = const Dst::Foo(0u8); // bb1[0]: scope 1 at $DIR/simplify-arm-identity.rs:20:21: 20:32 // ty::Const - // + ty: u8 + // + ty: Dst // + val: Value(Scalar(0x00)) // mir::Constant - // + span: $DIR/simplify-arm-identity.rs:20:30: 20:31 - // + literal: Const { ty: u8, val: Value(Scalar(0x00)) } - discriminant(_2) = 0; // scope 1 at $DIR/simplify-arm-identity.rs:20:21: 20:32 - goto -> bb4; // scope 1 at $DIR/simplify-arm-identity.rs:18:18: 21:6 + // + span: $DIR/simplify-arm-identity.rs:20:21: 20:32 + // + literal: Const { ty: Dst, val: Value(Scalar(0x00)) } + goto -> bb4; // bb1[1]: scope 1 at $DIR/simplify-arm-identity.rs:18:18: 21:6 } bb2: { diff --git a/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs b/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs index 067fa879b4038..7047b542aa607 100644 --- a/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs +++ b/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs @@ -9,4 +9,5 @@ fn main() { map(None); } +// EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR rustc.map.SimplifyLocals.diff diff --git a/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/rustc.map.SimplifyLocals.diff b/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/32bit/rustc.map.SimplifyLocals.diff similarity index 76% rename from src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/rustc.map.SimplifyLocals.diff rename to src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/32bit/rustc.map.SimplifyLocals.diff index 0ca54af85e3b6..2f78671763d51 100644 --- a/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/rustc.map.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/32bit/rustc.map.SimplifyLocals.diff @@ -24,7 +24,13 @@ } bb2: { - discriminant(_0) = 0; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:17: 3:21 + _0 = const std::option::Option::>::None; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:17: 3:21 + // ty::Const + // + ty: std::option::Option> + // + val: Value(Scalar(0x00000000)) + // mir::Constant + // + span: $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:17: 3:21 + // + literal: Const { ty: std::option::Option>, val: Value(Scalar(0x00000000)) } goto -> bb3; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:2:5: 5:6 } diff --git a/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/64bit/rustc.map.SimplifyLocals.diff b/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/64bit/rustc.map.SimplifyLocals.diff new file mode 100644 index 0000000000000..a97fa98a7b09e --- /dev/null +++ b/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/64bit/rustc.map.SimplifyLocals.diff @@ -0,0 +1,42 @@ +- // MIR for `map` before SimplifyLocals ++ // MIR for `map` after SimplifyLocals + + fn map(_1: std::option::Option>) -> std::option::Option> { + debug x => _1; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:1:8: 1:9 + let mut _0: std::option::Option>; // return place in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:1:31: 1:46 + let mut _2: isize; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13 + let _3: std::boxed::Box<()>; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:14: 4:15 +- let mut _4: std::boxed::Box<()>; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:25: 4:26 +- let mut _5: isize; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2 +- let mut _6: isize; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2 + scope 1 { + debug x => _3; // in scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:14: 4:15 + } + + bb0: { + _2 = discriminant(_1); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13 + switchInt(move _2) -> [0isize: bb2, otherwise: bb1]; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13 + } + + bb1: { + _0 = move _1; // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:20: 4:27 + goto -> bb3; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:2:5: 5:6 + } + + bb2: { + _0 = const std::option::Option::>::None; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:17: 3:21 + // ty::Const + // + ty: std::option::Option> + // + val: Value(Scalar(0x0000000000000000)) + // mir::Constant + // + span: $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:17: 3:21 + // + literal: Const { ty: std::option::Option>, val: Value(Scalar(0x0000000000000000)) } + goto -> bb3; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:2:5: 5:6 + } + + bb3: { +- _5 = discriminant(_1); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2 + return; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:2: 6:2 + } + } + diff --git a/src/test/pretty/asm.pp b/src/test/pretty/asm.pp index 4903050e08ed2..b3d188dd70881 100644 --- a/src/test/pretty/asm.pp +++ b/src/test/pretty/asm.pp @@ -22,5 +22,13 @@ asm!("{0}", inout(reg) b); asm!("{0} {1}", out(reg) _, inlateout(reg) b => _); asm!("", out("al") _, lateout("rbx") _); + asm!("inst1\ninst2"); + asm!("inst1 {0}, 42\ninst2 {1}, 24", in(reg) a, out(reg) b); + asm!("inst2 {1}, 24\ninst1 {0}, 42", in(reg) a, out(reg) b); + asm!("inst1 {0}, 42\ninst2 {1}, 24", in(reg) a, out(reg) b); + asm!("inst1\ninst2"); + asm!("inst1\ninst2"); + asm!("inst1\n\tinst2"); + asm!("inst1\ninst2\ninst3\ninst4"); } } diff --git a/src/test/pretty/asm.rs b/src/test/pretty/asm.rs index 12c32e6721b33..33f25e5216b4e 100644 --- a/src/test/pretty/asm.rs +++ b/src/test/pretty/asm.rs @@ -16,5 +16,14 @@ pub fn main() { asm!("{name}", name = inout(reg) b); asm!("{} {}", out(reg) _, inlateout(reg) b => _); asm!("", out("al") _, lateout("rbx") _); + asm!("inst1", "inst2"); + asm!("inst1 {}, 42", "inst2 {}, 24", in(reg) a, out(reg) b); + asm!("inst2 {1}, 24", "inst1 {0}, 42", in(reg) a, out(reg) b); + asm!("inst1 {}, 42", "inst2 {name}, 24", in(reg) a, name = out(reg) b); + asm!("inst1 +inst2"); + asm!("inst1\ninst2"); + asm!("inst1\n\tinst2"); + asm!("inst1\ninst2", "inst3\ninst4"); } } diff --git a/src/test/rustdoc-js/doc-alias-filter-out.js b/src/test/rustdoc-js/doc-alias-filter-out.js new file mode 100644 index 0000000000000..46a089d06ebef --- /dev/null +++ b/src/test/rustdoc-js/doc-alias-filter-out.js @@ -0,0 +1,9 @@ +// exact-check + +const QUERY = 'true'; + +const FILTER_CRATE = 'some_other_crate'; + +const EXPECTED = { + 'others': [], +}; diff --git a/src/test/rustdoc-js/doc-alias-filter-out.rs b/src/test/rustdoc-js/doc-alias-filter-out.rs new file mode 100644 index 0000000000000..815e8cedd16da --- /dev/null +++ b/src/test/rustdoc-js/doc-alias-filter-out.rs @@ -0,0 +1,4 @@ +#![feature(doc_alias)] + +#[doc(alias = "true")] +pub struct Foo; diff --git a/src/test/rustdoc-js/doc-alias-filter.js b/src/test/rustdoc-js/doc-alias-filter.js new file mode 100644 index 0000000000000..4b1e2e2970479 --- /dev/null +++ b/src/test/rustdoc-js/doc-alias-filter.js @@ -0,0 +1,17 @@ +// exact-check + +const QUERY = 'true'; + +const FILTER_CRATE = 'doc_alias_filter'; + +const EXPECTED = { + 'others': [ + { + 'path': 'doc_alias_filter', + 'name': 'Foo', + 'alias': 'true', + 'href': '../doc_alias_filter/struct.Foo.html', + 'is_alias': true + }, + ], +}; diff --git a/src/test/rustdoc-js/doc-alias-filter.rs b/src/test/rustdoc-js/doc-alias-filter.rs new file mode 100644 index 0000000000000..8887f8c2b0149 --- /dev/null +++ b/src/test/rustdoc-js/doc-alias-filter.rs @@ -0,0 +1,7 @@ +#![feature(doc_alias)] + +#[doc(alias = "true")] +pub struct Foo; + +#[doc(alias = "false")] +pub struct Bar; diff --git a/src/test/rustdoc-ui/check-doc-alias-attr.rs b/src/test/rustdoc-ui/check-doc-alias-attr.rs new file mode 100644 index 0000000000000..2f01099107d9e --- /dev/null +++ b/src/test/rustdoc-ui/check-doc-alias-attr.rs @@ -0,0 +1,9 @@ +#![feature(doc_alias)] + +#[doc(alias = "foo")] // ok! +pub struct Bar; + +#[doc(alias)] //~ ERROR +#[doc(alias = 0)] //~ ERROR +#[doc(alias("bar"))] //~ ERROR +pub struct Foo; diff --git a/src/test/rustdoc-ui/check-doc-alias-attr.stderr b/src/test/rustdoc-ui/check-doc-alias-attr.stderr new file mode 100644 index 0000000000000..480acc821aaa8 --- /dev/null +++ b/src/test/rustdoc-ui/check-doc-alias-attr.stderr @@ -0,0 +1,20 @@ +error: doc alias attribute expects a string: #[doc(alias = "0")] + --> $DIR/check-doc-alias-attr.rs:6:7 + | +LL | #[doc(alias)] + | ^^^^^ + +error: doc alias attribute expects a string: #[doc(alias = "0")] + --> $DIR/check-doc-alias-attr.rs:7:7 + | +LL | #[doc(alias = 0)] + | ^^^^^^^^^ + +error: doc alias attribute expects a string: #[doc(alias = "0")] + --> $DIR/check-doc-alias-attr.rs:8:7 + | +LL | #[doc(alias("bar"))] + | ^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/rustdoc-ui/test-compile-fail3.stderr b/src/test/rustdoc-ui/test-compile-fail3.stderr index 7a2f1815ed8e5..fab801b3beaea 100644 --- a/src/test/rustdoc-ui/test-compile-fail3.stderr +++ b/src/test/rustdoc-ui/test-compile-fail3.stderr @@ -1,4 +1,4 @@ -error: unterminated double quote string +error[E0765]: unterminated double quote string --> $DIR/test-compile-fail3.rs:3:1 | 3 | "fail @@ -6,3 +6,4 @@ error: unterminated double quote string error: aborting due to previous error +For more information about this error, try `rustc --explain E0765`. diff --git a/src/test/rustdoc-ui/unparseable-doc-test.stdout b/src/test/rustdoc-ui/unparseable-doc-test.stdout index 4ea6455d3aa4c..29cb22e2e4b09 100644 --- a/src/test/rustdoc-ui/unparseable-doc-test.stdout +++ b/src/test/rustdoc-ui/unparseable-doc-test.stdout @@ -5,7 +5,7 @@ test $DIR/unparseable-doc-test.rs - foo (line 6) ... FAILED failures: ---- $DIR/unparseable-doc-test.rs - foo (line 6) stdout ---- -error: unterminated double quote string +error[E0765]: unterminated double quote string --> $DIR/unparseable-doc-test.rs:8:1 | LL | "unterminated @@ -13,6 +13,7 @@ LL | "unterminated error: aborting due to previous error +For more information about this error, try `rustc --explain E0765`. Couldn't compile the test. failures: diff --git a/src/test/rustdoc/synthetic_auto/overflow.rs b/src/test/rustdoc/synthetic_auto/overflow.rs new file mode 100644 index 0000000000000..546b3e07793e1 --- /dev/null +++ b/src/test/rustdoc/synthetic_auto/overflow.rs @@ -0,0 +1,35 @@ +// Tests that we don't fail with an overflow error for certain +// strange types +// See https://github.com/rust-lang/rust/pull/72936#issuecomment-643676915 + +pub trait Interner { + type InternedType; +} + +struct RustInterner<'tcx> { + foo: &'tcx () +} + +impl<'tcx> Interner for RustInterner<'tcx> { + type InternedType = Box>; +} + +enum TyData { + FnDef(I::InternedType) +} + +struct VariableKind(I::InternedType); + +// @has overflow/struct.BoundVarsCollector.html +// @has - '//code' "impl<'tcx> Send for BoundVarsCollector<'tcx>" +pub struct BoundVarsCollector<'tcx> { + val: VariableKind> +} + +fn is_send() {} + +struct MyInterner<'tcx> { + val: &'tcx () +} + +fn main() {} diff --git a/src/test/ui/asm/duplicate-options.fixed b/src/test/ui/asm/duplicate-options.fixed new file mode 100644 index 0000000000000..f4672a50fd0f4 --- /dev/null +++ b/src/test/ui/asm/duplicate-options.fixed @@ -0,0 +1,26 @@ +// only-x86_64 +// run-rustfix + +#![feature(asm)] + +fn main() { + unsafe { + asm!("", options(nomem, )); + //~^ ERROR the `nomem` option was already provided + asm!("", options(att_syntax, )); + //~^ ERROR the `att_syntax` option was already provided + asm!("", options(nostack, att_syntax), options()); + //~^ ERROR the `nostack` option was already provided + asm!("", options(nostack, ), options(), options()); + //~^ ERROR the `nostack` option was already provided + //~| ERROR the `nostack` option was already provided + //~| ERROR the `nostack` option was already provided + asm!( + "", + options(nomem, noreturn), + options(att_syntax, ), //~ ERROR the `noreturn` option was already provided + options( nostack), //~ ERROR the `nomem` option was already provided + options(), //~ ERROR the `noreturn` option was already provided + ); + } +} diff --git a/src/test/ui/asm/duplicate-options.rs b/src/test/ui/asm/duplicate-options.rs new file mode 100644 index 0000000000000..80292d7521a9a --- /dev/null +++ b/src/test/ui/asm/duplicate-options.rs @@ -0,0 +1,26 @@ +// only-x86_64 +// run-rustfix + +#![feature(asm)] + +fn main() { + unsafe { + asm!("", options(nomem, nomem)); + //~^ ERROR the `nomem` option was already provided + asm!("", options(att_syntax, att_syntax)); + //~^ ERROR the `att_syntax` option was already provided + asm!("", options(nostack, att_syntax), options(nostack)); + //~^ ERROR the `nostack` option was already provided + asm!("", options(nostack, nostack), options(nostack), options(nostack)); + //~^ ERROR the `nostack` option was already provided + //~| ERROR the `nostack` option was already provided + //~| ERROR the `nostack` option was already provided + asm!( + "", + options(nomem, noreturn), + options(att_syntax, noreturn), //~ ERROR the `noreturn` option was already provided + options(nomem, nostack), //~ ERROR the `nomem` option was already provided + options(noreturn), //~ ERROR the `noreturn` option was already provided + ); + } +} diff --git a/src/test/ui/asm/duplicate-options.stderr b/src/test/ui/asm/duplicate-options.stderr new file mode 100644 index 0000000000000..cd8d743e031a5 --- /dev/null +++ b/src/test/ui/asm/duplicate-options.stderr @@ -0,0 +1,56 @@ +error: the `nomem` option was already provided + --> $DIR/duplicate-options.rs:8:33 + | +LL | asm!("", options(nomem, nomem)); + | ^^^^^ this option was already provided + +error: the `att_syntax` option was already provided + --> $DIR/duplicate-options.rs:10:38 + | +LL | asm!("", options(att_syntax, att_syntax)); + | ^^^^^^^^^^ this option was already provided + +error: the `nostack` option was already provided + --> $DIR/duplicate-options.rs:12:56 + | +LL | asm!("", options(nostack, att_syntax), options(nostack)); + | ^^^^^^^ this option was already provided + +error: the `nostack` option was already provided + --> $DIR/duplicate-options.rs:14:35 + | +LL | asm!("", options(nostack, nostack), options(nostack), options(nostack)); + | ^^^^^^^ this option was already provided + +error: the `nostack` option was already provided + --> $DIR/duplicate-options.rs:14:53 + | +LL | asm!("", options(nostack, nostack), options(nostack), options(nostack)); + | ^^^^^^^ this option was already provided + +error: the `nostack` option was already provided + --> $DIR/duplicate-options.rs:14:71 + | +LL | asm!("", options(nostack, nostack), options(nostack), options(nostack)); + | ^^^^^^^ this option was already provided + +error: the `noreturn` option was already provided + --> $DIR/duplicate-options.rs:21:33 + | +LL | options(att_syntax, noreturn), + | ^^^^^^^^ this option was already provided + +error: the `nomem` option was already provided + --> $DIR/duplicate-options.rs:22:21 + | +LL | options(nomem, nostack), + | ^^^^^ this option was already provided + +error: the `noreturn` option was already provided + --> $DIR/duplicate-options.rs:23:21 + | +LL | options(noreturn), + | ^^^^^^^^ this option was already provided + +error: aborting due to 9 previous errors + diff --git a/src/test/ui/asm/parse-error.rs b/src/test/ui/asm/parse-error.rs index 2b1f018f3642e..538a3fde8fdeb 100644 --- a/src/test/ui/asm/parse-error.rs +++ b/src/test/ui/asm/parse-error.rs @@ -13,7 +13,7 @@ fn main() { asm!("{}" foo); //~^ ERROR expected token: `,` asm!("{}", foo); - //~^ ERROR expected one of + //~^ ERROR expected operand, options, or additional template string asm!("{}", in foo); //~^ ERROR expected `(`, found `foo` asm!("{}", in(reg foo)); @@ -34,11 +34,6 @@ fn main() { //~^ ERROR expected one of asm!("", options(nomem, foo)); //~^ ERROR expected one of - asm!("", options(), options()); - //~^ ERROR asm options cannot be specified multiple times - asm!("", options(), options(), options()); - //~^ ERROR asm options cannot be specified multiple times - //~^^ ERROR asm options cannot be specified multiple times asm!("{}", options(), const foo); //~^ ERROR arguments are not allowed after options asm!("{a}", a = const foo, a = const bar); @@ -52,5 +47,13 @@ fn main() { //~^ ERROR named arguments cannot follow explicit register arguments asm!("{1}", in("eax") foo, const bar); //~^ ERROR positional arguments cannot follow named arguments or explicit register arguments + asm!("", options(), ""); + //~^ ERROR expected one of + asm!("{}", in(reg) foo, "{}", out(reg) foo); + //~^ ERROR expected one of + asm!(format!("{{{}}}", 0), in(reg) foo); + //~^ ERROR asm template must be a string literal + asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar); + //~^ ERROR asm template must be a string literal } } diff --git a/src/test/ui/asm/parse-error.stderr b/src/test/ui/asm/parse-error.stderr index 583a10570360b..dfbfc0abe3472 100644 --- a/src/test/ui/asm/parse-error.stderr +++ b/src/test/ui/asm/parse-error.stderr @@ -16,11 +16,11 @@ error: expected token: `,` LL | asm!("{}" foo); | ^^^ expected `,` -error: expected one of `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `foo` +error: expected operand, options, or additional template string --> $DIR/parse-error.rs:15:20 | LL | asm!("{}", foo); - | ^^^ expected one of 8 possible tokens + | ^^^ expected operand, options, or additional template string error: expected `(`, found `foo` --> $DIR/parse-error.rs:17:23 @@ -82,32 +82,8 @@ error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `prese LL | asm!("", options(nomem, foo)); | ^^^ expected one of 8 possible tokens -error: asm options cannot be specified multiple times - --> $DIR/parse-error.rs:37:29 - | -LL | asm!("", options(), options()); - | --------- ^^^^^^^^^ duplicate options - | | - | previously here - -error: asm options cannot be specified multiple times - --> $DIR/parse-error.rs:39:29 - | -LL | asm!("", options(), options(), options()); - | --------- ^^^^^^^^^ duplicate options - | | - | previously here - -error: asm options cannot be specified multiple times - --> $DIR/parse-error.rs:39:40 - | -LL | asm!("", options(), options(), options()); - | --------- ^^^^^^^^^ duplicate options - | | - | previously here - error: arguments are not allowed after options - --> $DIR/parse-error.rs:42:31 + --> $DIR/parse-error.rs:37:31 | LL | asm!("{}", options(), const foo); | --------- ^^^^^^^^^ argument @@ -115,7 +91,7 @@ LL | asm!("{}", options(), const foo); | previous options error: duplicate argument named `a` - --> $DIR/parse-error.rs:44:36 + --> $DIR/parse-error.rs:39:36 | LL | asm!("{a}", a = const foo, a = const bar); | ------------- ^^^^^^^^^^^^^ duplicate argument @@ -123,7 +99,7 @@ LL | asm!("{a}", a = const foo, a = const bar); | previously here error: argument never used - --> $DIR/parse-error.rs:44:36 + --> $DIR/parse-error.rs:39:36 | LL | asm!("{a}", a = const foo, a = const bar); | ^^^^^^^^^^^^^ argument never used @@ -131,13 +107,13 @@ LL | asm!("{a}", a = const foo, a = const bar); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"` error: explicit register arguments cannot have names - --> $DIR/parse-error.rs:47:18 + --> $DIR/parse-error.rs:42:18 | LL | asm!("", a = in("eax") foo); | ^^^^^^^^^^^^^^^^^ error: named arguments cannot follow explicit register arguments - --> $DIR/parse-error.rs:49:36 + --> $DIR/parse-error.rs:44:36 | LL | asm!("{a}", in("eax") foo, a = const bar); | ------------- ^^^^^^^^^^^^^ named argument @@ -145,7 +121,7 @@ LL | asm!("{a}", in("eax") foo, a = const bar); | explicit register argument error: named arguments cannot follow explicit register arguments - --> $DIR/parse-error.rs:51:36 + --> $DIR/parse-error.rs:46:36 | LL | asm!("{a}", in("eax") foo, a = const bar); | ------------- ^^^^^^^^^^^^^ named argument @@ -153,12 +129,40 @@ LL | asm!("{a}", in("eax") foo, a = const bar); | explicit register argument error: positional arguments cannot follow named arguments or explicit register arguments - --> $DIR/parse-error.rs:53:36 + --> $DIR/parse-error.rs:48:36 | LL | asm!("{1}", in("eax") foo, const bar); | ------------- ^^^^^^^^^ positional argument | | | explicit register argument -error: aborting due to 24 previous errors +error: expected one of `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `""` + --> $DIR/parse-error.rs:50:29 + | +LL | asm!("", options(), ""); + | ^^ expected one of 8 possible tokens + +error: expected one of `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `"{}"` + --> $DIR/parse-error.rs:52:33 + | +LL | asm!("{}", in(reg) foo, "{}", out(reg) foo); + | ^^^^ expected one of 8 possible tokens + +error: asm template must be a string literal + --> $DIR/parse-error.rs:54:14 + | +LL | asm!(format!("{{{}}}", 0), in(reg) foo); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: asm template must be a string literal + --> $DIR/parse-error.rs:56:21 + | +LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 25 previous errors diff --git a/src/test/ui/asm/srcloc.rs b/src/test/ui/asm/srcloc.rs index 402adc50d5b44..1477e3dd5665c 100644 --- a/src/test/ui/asm/srcloc.rs +++ b/src/test/ui/asm/srcloc.rs @@ -40,5 +40,85 @@ fn main() { asm!("movaps %xmm3, (%esi, 2)", options(att_syntax)); //~^ WARN: scale factor without index register is ignored + + asm!( + "invalid_instruction", + ); + //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction' + + asm!( + "mov eax, eax", + "invalid_instruction", + "mov eax, eax", + ); + //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction' + + asm!( + "mov eax, eax\n", + "invalid_instruction", + "mov eax, eax", + ); + //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction' + + asm!( + "mov eax, eax", + concat!("invalid", "_", "instruction"), + "mov eax, eax", + ); + //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction' + + asm!( + concat!("mov eax", ", ", "eax"), + concat!("invalid", "_", "instruction"), + concat!("mov eax", ", ", "eax"), + ); + //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction' + + // Make sure template strings get separated + asm!( + "invalid_instruction1", + "invalid_instruction2", + ); + //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1' + //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2' + + asm!( + concat!( + "invalid", "_", "instruction1", "\n", + "invalid", "_", "instruction2", + ), + ); + //~^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1' + //~^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2' + + asm!( + concat!( + "invalid", "_", "instruction1", "\n", + "invalid", "_", "instruction2", + ), + concat!( + "invalid", "_", "instruction3", "\n", + "invalid", "_", "instruction4", + ), + ); + //~^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1' + //~^^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2' + //~^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction3' + //~^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction4' + + asm!( + concat!( + "invalid", "_", "instruction1", "\n", + "invalid", "_", "instruction2", "\n", + ), + concat!( + "invalid", "_", "instruction3", "\n", + "invalid", "_", "instruction4", "\n", + ), + ); + //~^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1' + //~^^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2' + //~^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction3' + //~^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction4' } } diff --git a/src/test/ui/asm/srcloc.stderr b/src/test/ui/asm/srcloc.stderr index d5d12b004816f..b62c8948289dd 100644 --- a/src/test/ui/asm/srcloc.stderr +++ b/src/test/ui/asm/srcloc.stderr @@ -82,5 +82,209 @@ note: instantiated into assembly here LL | movaps %xmm3, (%esi, 2) | ^ -error: aborting due to 6 previous errors; 1 warning emitted +error: invalid instruction mnemonic 'invalid_instruction' + --> $DIR/srcloc.rs:45:14 + | +LL | "invalid_instruction", + | ^ + | +note: instantiated into assembly here + --> :2:2 + | +LL | invalid_instruction + | ^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction' + --> $DIR/srcloc.rs:51:14 + | +LL | "invalid_instruction", + | ^ + | +note: instantiated into assembly here + --> :3:1 + | +LL | invalid_instruction + | ^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction' + --> $DIR/srcloc.rs:58:14 + | +LL | "invalid_instruction", + | ^ + | +note: instantiated into assembly here + --> :4:1 + | +LL | invalid_instruction + | ^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction' + --> $DIR/srcloc.rs:65:13 + | +LL | concat!("invalid", "_", "instruction"), + | ^ + | +note: instantiated into assembly here + --> :3:1 + | +LL | invalid_instruction + | ^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction' + --> $DIR/srcloc.rs:72:13 + | +LL | concat!("invalid", "_", "instruction"), + | ^ + | +note: instantiated into assembly here + --> :3:1 + | +LL | invalid_instruction + | ^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction1' + --> $DIR/srcloc.rs:79:14 + | +LL | "invalid_instruction1", + | ^ + | +note: instantiated into assembly here + --> :2:2 + | +LL | invalid_instruction1 + | ^^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction2' + --> $DIR/srcloc.rs:80:14 + | +LL | "invalid_instruction2", + | ^ + | +note: instantiated into assembly here + --> :3:1 + | +LL | invalid_instruction2 + | ^^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction1' + --> $DIR/srcloc.rs:86:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :2:2 + | +LL | invalid_instruction1 + | ^^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction2' + --> $DIR/srcloc.rs:86:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :3:1 + | +LL | invalid_instruction2 + | ^^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction1' + --> $DIR/srcloc.rs:95:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :2:2 + | +LL | invalid_instruction1 + | ^^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction2' + --> $DIR/srcloc.rs:95:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :3:1 + | +LL | invalid_instruction2 + | ^^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction3' + --> $DIR/srcloc.rs:99:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :4:1 + | +LL | invalid_instruction3 + | ^^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction4' + --> $DIR/srcloc.rs:99:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :5:1 + | +LL | invalid_instruction4 + | ^^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction1' + --> $DIR/srcloc.rs:110:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :2:2 + | +LL | invalid_instruction1 + | ^^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction2' + --> $DIR/srcloc.rs:110:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :3:1 + | +LL | invalid_instruction2 + | ^^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction3' + --> $DIR/srcloc.rs:114:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :5:1 + | +LL | invalid_instruction3 + | ^^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction4' + --> $DIR/srcloc.rs:114:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :6:1 + | +LL | invalid_instruction4 + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 23 previous errors; 1 warning emitted diff --git a/src/test/ui/associated-types/associated-types-eq-hr.nll.stderr b/src/test/ui/associated-types/associated-types-eq-hr.nll.stderr new file mode 100644 index 0000000000000..25e9f726ba53a --- /dev/null +++ b/src/test/ui/associated-types/associated-types-eq-hr.nll.stderr @@ -0,0 +1,33 @@ +error[E0271]: type mismatch resolving `for<'x> >::A == &'x isize` + --> $DIR/associated-types-eq-hr.rs:87:5 + | +LL | fn foo() + | --- required by a bound in this +LL | where +LL | T: for<'x> TheTrait<&'x isize, A = &'x isize>, + | ------------- required by this bound in `foo` +... +LL | foo::(); + | ^^^^^^^^^^^^^^^^^ expected `isize`, found `usize` + | + = note: expected reference `&isize` + found reference `&usize` + +error[E0271]: type mismatch resolving `for<'x> >::A == &'x usize` + --> $DIR/associated-types-eq-hr.rs:91:5 + | +LL | fn bar() + | --- required by a bound in this +LL | where +LL | T: for<'x> TheTrait<&'x isize, A = &'x usize>, + | ------------- required by this bound in `bar` +... +LL | bar::(); + | ^^^^^^^^^^^^^^^^ expected `usize`, found `isize` + | + = note: expected reference `&usize` + found reference `&isize` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/associated-types/associated-types-eq-hr.rs b/src/test/ui/associated-types/associated-types-eq-hr.rs index e6afa3f71c2f0..fb391913c321e 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.rs +++ b/src/test/ui/associated-types/associated-types-eq-hr.rs @@ -7,7 +7,7 @@ pub trait TheTrait { } struct IntStruct { - x: isize + x: isize, } impl<'a> TheTrait<&'a isize> for IntStruct { @@ -19,7 +19,7 @@ impl<'a> TheTrait<&'a isize> for IntStruct { } struct UintStruct { - x: isize + x: isize, } impl<'a> TheTrait<&'a isize> for UintStruct { @@ -30,8 +30,7 @@ impl<'a> TheTrait<&'a isize> for UintStruct { } } -struct Tuple { -} +struct Tuple {} impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { type A = &'a isize; @@ -42,37 +41,43 @@ impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { } fn foo() - where T : for<'x> TheTrait<&'x isize, A = &'x isize> +where + T: for<'x> TheTrait<&'x isize, A = &'x isize>, { // ok for IntStruct, but not UintStruct } fn bar() - where T : for<'x> TheTrait<&'x isize, A = &'x usize> +where + T: for<'x> TheTrait<&'x isize, A = &'x usize>, { // ok for UintStruct, but not IntStruct } fn tuple_one() - where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize> +where + T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, { // not ok for tuple, two lifetimes and we pick first } fn tuple_two() - where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize> +where + T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, { // not ok for tuple, two lifetimes and we pick second } fn tuple_three() - where T : for<'x> TheTrait<(&'x isize, &'x isize), A = &'x isize> +where + T: for<'x> TheTrait<(&'x isize, &'x isize), A = &'x isize>, { // ok for tuple } fn tuple_four() - where T : for<'x,'y> TheTrait<(&'x isize, &'y isize)> +where + T: for<'x, 'y> TheTrait<(&'x isize, &'y isize)>, { // not ok for tuple, two lifetimes, and lifetime matching is invariant } @@ -89,14 +94,14 @@ pub fn call_bar() { pub fn call_tuple_one() { tuple_one::(); - //~^ ERROR not satisfied - //~| ERROR type mismatch + //~^ ERROR implementation of `TheTrait` is not general enough + //~| ERROR implementation of `TheTrait` is not general enough } pub fn call_tuple_two() { tuple_two::(); - //~^ ERROR not satisfied - //~| ERROR type mismatch + //~^ ERROR implementation of `TheTrait` is not general enough + //~| ERROR implementation of `TheTrait` is not general enough } pub fn call_tuple_three() { @@ -105,7 +110,7 @@ pub fn call_tuple_three() { pub fn call_tuple_four() { tuple_four::(); - //~^ ERROR not satisfied + //~^ ERROR implementation of `TheTrait` is not general enough } -fn main() { } +fn main() {} diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr index 58d72746e76aa..127ab8673556d 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.stderr +++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr @@ -1,10 +1,11 @@ error[E0271]: type mismatch resolving `for<'x> >::A == &'x isize` - --> $DIR/associated-types-eq-hr.rs:82:5 + --> $DIR/associated-types-eq-hr.rs:87:5 | LL | fn foo() | --- required by a bound in this -LL | where T : for<'x> TheTrait<&'x isize, A = &'x isize> - | ------------- required by this bound in `foo` +LL | where +LL | T: for<'x> TheTrait<&'x isize, A = &'x isize>, + | ------------- required by this bound in `foo` ... LL | foo::(); | ^^^^^^^^^^^^^^^^^ expected `isize`, found `usize` @@ -13,12 +14,13 @@ LL | foo::(); found reference `&usize` error[E0271]: type mismatch resolving `for<'x> >::A == &'x usize` - --> $DIR/associated-types-eq-hr.rs:86:5 + --> $DIR/associated-types-eq-hr.rs:91:5 | LL | fn bar() | --- required by a bound in this -LL | where T : for<'x> TheTrait<&'x isize, A = &'x usize> - | ------------- required by this bound in `bar` +LL | where +LL | T: for<'x> TheTrait<&'x isize, A = &'x usize>, + | ------------- required by this bound in `bar` ... LL | bar::(); | ^^^^^^^^^^^^^^^^ expected `usize`, found `isize` @@ -26,71 +28,86 @@ LL | bar::(); = note: expected reference `&usize` found reference `&isize` -error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied - --> $DIR/associated-types-eq-hr.rs:91:17 +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:96:5 | -LL | fn tuple_one() - | --------- required by a bound in this -LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize> - | ---------------------------------------------------------- required by this bound in `tuple_one` +LL | / pub trait TheTrait { +LL | | type A; +LL | | +LL | | fn get(&self, t: T) -> Self::A; +LL | | } + | |_- trait `TheTrait` defined here ... -LL | tuple_one::(); - | ^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` +LL | tuple_one::(); + | ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough | - = help: the following implementations were found: - > + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` -error[E0271]: type mismatch resolving `for<'x, 'y> >::A == &'x isize` - --> $DIR/associated-types-eq-hr.rs:91:5 +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:96:5 | -LL | fn tuple_one() - | --------- required by a bound in this -LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize> - | ------------- required by this bound in `tuple_one` +LL | / pub trait TheTrait { +LL | | type A; +LL | | +LL | | fn get(&self, t: T) -> Self::A; +LL | | } + | |_- trait `TheTrait` defined here ... -LL | tuple_one::(); - | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime +LL | tuple_one::(); + | ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` -error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied - --> $DIR/associated-types-eq-hr.rs:97:17 +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:102:5 | -LL | fn tuple_two() - | --------- required by a bound in this -LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize> - | ---------------------------------------------------------- required by this bound in `tuple_two` +LL | / pub trait TheTrait { +LL | | type A; +LL | | +LL | | fn get(&self, t: T) -> Self::A; +LL | | } + | |_- trait `TheTrait` defined here ... -LL | tuple_two::(); - | ^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` +LL | tuple_two::(); + | ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough | - = help: the following implementations were found: - > + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` -error[E0271]: type mismatch resolving `for<'x, 'y> >::A == &'y isize` - --> $DIR/associated-types-eq-hr.rs:97:5 +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:102:5 | -LL | fn tuple_two() - | --------- required by a bound in this -LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize> - | ------------- required by this bound in `tuple_two` +LL | / pub trait TheTrait { +LL | | type A; +LL | | +LL | | fn get(&self, t: T) -> Self::A; +LL | | } + | |_- trait `TheTrait` defined here ... -LL | tuple_two::(); - | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime +LL | tuple_two::(); + | ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` -error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied - --> $DIR/associated-types-eq-hr.rs:107:18 +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:112:5 | -LL | fn tuple_four() - | ---------- required by a bound in this -LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize)> - | ------------------------------------------- required by this bound in `tuple_four` +LL | / pub trait TheTrait { +LL | | type A; +LL | | +LL | | fn get(&self, t: T) -> Self::A; +LL | | } + | |_- trait `TheTrait` defined here ... -LL | tuple_four::(); - | ^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` +LL | tuple_four::(); + | ^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough | - = help: the following implementations were found: - > + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` error: aborting due to 7 previous errors -Some errors have detailed explanations: E0271, E0277. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr index 71a533a36f418..4fc336122fa9d 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr @@ -1,26 +1,26 @@ error: lifetime may not live long enough - --> $DIR/project-fn-ret-invariant.rs:55:4 + --> $DIR/project-fn-ret-invariant.rs:56:5 | -LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - | -- -- lifetime `'b` defined here +LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here ... -LL | (a, b) - | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` +LL | (a, b) + | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` error: lifetime may not live long enough - --> $DIR/project-fn-ret-invariant.rs:55:4 + --> $DIR/project-fn-ret-invariant.rs:56:5 | -LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - | -- -- lifetime `'b` defined here +LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here ... -LL | (a, b) - | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` +LL | (a, b) + | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` | = help: consider adding the following bound: `'b: 'a` diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr index 5009e0868a7d4..9462121bdf203 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr @@ -1,23 +1,23 @@ error[E0623]: lifetime mismatch - --> $DIR/project-fn-ret-invariant.rs:53:21 + --> $DIR/project-fn-ret-invariant.rs:54:22 | -LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - | -------- -------------------- - | | - | this parameter and the return type are declared with different lifetimes... -LL | let a = bar(foo, y); - | ^ ...but data from `x` is returned here +LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | -------- -------------------- + | | + | this parameter and the return type are declared with different lifetimes... +LL | let a = bar(foo, y); + | ^ ...but data from `x` is returned here error[E0623]: lifetime mismatch - --> $DIR/project-fn-ret-invariant.rs:54:21 + --> $DIR/project-fn-ret-invariant.rs:56:9 | -LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - | -------- -------------------- - | | - | this parameter and the return type are declared with different lifetimes... -LL | let a = bar(foo, y); -LL | let b = bar(foo, x); - | ^ ...but data from `y` is returned here +LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | -------- -------------------- + | | + | this parameter and the return type are declared with different lifetimes... +... +LL | (a, b) + | ^ ...but data from `x` is returned here error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr index 8f445acf2b98c..2156ecb17393f 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr @@ -1,8 +1,8 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/project-fn-ret-invariant.rs:59:1 + --> $DIR/project-fn-ret-invariant.rs:60:1 | -LL | fn main() { } - | ^^^^^^^^^^^^^ +LL | fn main() {} + | ^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr index c39030fbed1e1..44850df7b2f42 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr @@ -1,26 +1,26 @@ error: lifetime may not live long enough - --> $DIR/project-fn-ret-invariant.rs:38:12 + --> $DIR/project-fn-ret-invariant.rs:39:13 | -LL | fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - | -- -- lifetime `'b` defined here +LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here -LL | let f = foo; // <-- No consistent type can be inferred for `f` here. -LL | let a = bar(f, x); - | ^^^^^^^^^ argument requires that `'a` must outlive `'b` +LL | let f = foo; // <-- No consistent type can be inferred for `f` here. +LL | let a = bar(f, x); + | ^^^^^^^^^ argument requires that `'a` must outlive `'b` | = help: consider adding the following bound: `'a: 'b` error: lifetime may not live long enough - --> $DIR/project-fn-ret-invariant.rs:39:12 + --> $DIR/project-fn-ret-invariant.rs:40:13 | -LL | fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - | -- -- lifetime `'b` defined here +LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here ... -LL | let b = bar(f, y); - | ^^^^^^^^^ argument requires that `'b` must outlive `'a` +LL | let b = bar(f, y); + | ^^^^^^^^^ argument requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr index 65d16440ac9b0..64b5722390858 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr @@ -1,13 +1,13 @@ error[E0623]: lifetime mismatch - --> $DIR/project-fn-ret-invariant.rs:39:19 + --> $DIR/project-fn-ret-invariant.rs:40:20 | -LL | fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - | -------- -------------------- - | | - | this parameter and the return type are declared with different lifetimes... +LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | -------- -------------------- + | | + | this parameter and the return type are declared with different lifetimes... ... -LL | let b = bar(f, y); - | ^ ...but data from `x` is returned here +LL | let b = bar(f, y); + | ^ ...but data from `x` is returned here error: aborting due to previous error diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs index 23d873212ed1e..0034d796826de 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs @@ -1,60 +1,61 @@ #![feature(unboxed_closures)] #![feature(rustc_attrs)] - // Test for projection cache. We should be able to project distinct // lifetimes from `foo` as we reinstantiate it multiple times, but not // if we do it just once. In this variant, the region `'a` is used in // an invariant position, which affects the results. // revisions: ok oneuse transmute krisskross - #![allow(dead_code, unused_variables)] use std::marker::PhantomData; struct Type<'a> { // Invariant - data: PhantomData &'a u32> + data: PhantomData &'a u32>, } -fn foo<'a>() -> Type<'a> { loop { } } +fn foo<'a>() -> Type<'a> { + loop {} +} fn bar(t: T, x: T::Output) -> T::Output - where T: FnOnce<()> +where + T: FnOnce<()>, { t() } #[cfg(ok)] // two instantiations: OK -fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { +fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { let a = bar(foo, x); let b = bar(foo, y); (a, b) } #[cfg(oneuse)] // one instantiation: BAD -fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - let f = foo; // <-- No consistent type can be inferred for `f` here. - let a = bar(f, x); - let b = bar(f, y); //[oneuse]~ ERROR lifetime mismatch [E0623] - (a, b) +fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + let f = foo; // <-- No consistent type can be inferred for `f` here. + let a = bar(f, x); + let b = bar(f, y); //[oneuse]~ ERROR lifetime mismatch [E0623] + (a, b) } #[cfg(transmute)] // one instantiations: BAD -fn baz<'a,'b>(x: Type<'a>) -> Type<'static> { - // Cannot instantiate `foo` with any lifetime other than `'a`, - // since it is provided as input. +fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> { + // Cannot instantiate `foo` with any lifetime other than `'a`, + // since it is provided as input. - bar(foo, x) //[transmute]~ ERROR E0495 + bar(foo, x) //[transmute]~ ERROR E0495 } #[cfg(krisskross)] // two instantiations, mixing and matching: BAD -fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - let a = bar(foo, y); //[krisskross]~ ERROR E0623 - let b = bar(foo, x); //[krisskross]~ ERROR E0623 - (a, b) +fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + let a = bar(foo, y); //[krisskross]~ ERROR E0623 + let b = bar(foo, x); + (a, b) //[krisskross]~ ERROR E0623 } #[rustc_error] -fn main() { } +fn main() {} //[ok]~^ ERROR fatal error triggered by #[rustc_error] diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr index f74d4ba73bf4e..db82c9fd43794 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr @@ -1,11 +1,11 @@ error: lifetime may not live long enough - --> $DIR/project-fn-ret-invariant.rs:48:4 + --> $DIR/project-fn-ret-invariant.rs:49:5 | -LL | fn baz<'a,'b>(x: Type<'a>) -> Type<'static> { +LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> { | -- lifetime `'a` defined here ... -LL | bar(foo, x) - | ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` +LL | bar(foo, x) + | ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` | = help: consider replacing `'a` with `'static` diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr index 137cb83ccd327..ef57f9e0bc480 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr @@ -1,27 +1,27 @@ -error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements - --> $DIR/project-fn-ret-invariant.rs:48:8 +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements + --> $DIR/project-fn-ret-invariant.rs:49:9 | -LL | bar(foo, x) - | ^^^ +LL | bar(foo, x) + | ^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 44:8... - --> $DIR/project-fn-ret-invariant.rs:44:8 +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 45:8... + --> $DIR/project-fn-ret-invariant.rs:45:8 | -LL | fn baz<'a,'b>(x: Type<'a>) -> Type<'static> { +LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> { | ^^ note: ...so that the expression is assignable - --> $DIR/project-fn-ret-invariant.rs:48:13 + --> $DIR/project-fn-ret-invariant.rs:49:14 | -LL | bar(foo, x) - | ^ +LL | bar(foo, x) + | ^ = note: expected `Type<'_>` found `Type<'a>` = note: but, the lifetime must be valid for the static lifetime... note: ...so that the expression is assignable - --> $DIR/project-fn-ret-invariant.rs:48:4 + --> $DIR/project-fn-ret-invariant.rs:49:5 | -LL | bar(foo, x) - | ^^^^^^^^^^^ +LL | bar(foo, x) + | ^^^^^^^^^^^ = note: expected `Type<'static>` found `Type<'_>` diff --git a/src/test/ui/associated-types/defaults-specialization.rs b/src/test/ui/associated-types/defaults-specialization.rs index d0ed718b83923..553705b2a4fab 100644 --- a/src/test/ui/associated-types/defaults-specialization.rs +++ b/src/test/ui/associated-types/defaults-specialization.rs @@ -1,6 +1,7 @@ //! Tests the interaction of associated type defaults and specialization. #![feature(associated_type_defaults, specialization)] +//~^ WARN the feature `specialization` is incomplete trait Tr { type Ty = u8; diff --git a/src/test/ui/associated-types/defaults-specialization.stderr b/src/test/ui/associated-types/defaults-specialization.stderr index 37a4d9b60fdfd..09a8c8f8a88a2 100644 --- a/src/test/ui/associated-types/defaults-specialization.stderr +++ b/src/test/ui/associated-types/defaults-specialization.stderr @@ -1,5 +1,14 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/defaults-specialization.rs:3:38 + | +LL | #![feature(associated_type_defaults, specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + error[E0053]: method `make` has an incompatible type for trait - --> $DIR/defaults-specialization.rs:18:18 + --> $DIR/defaults-specialization.rs:19:18 | LL | fn make() -> Self::Ty { | -------- type in trait @@ -11,7 +20,7 @@ LL | fn make() -> u8 { 0 } found fn pointer `fn() -> u8` error[E0053]: method `make` has an incompatible type for trait - --> $DIR/defaults-specialization.rs:34:18 + --> $DIR/defaults-specialization.rs:35:18 | LL | fn make() -> Self::Ty { | -------- type in trait @@ -26,7 +35,7 @@ LL | fn make() -> bool { true } found fn pointer `fn() -> bool` error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:9:9 + --> $DIR/defaults-specialization.rs:10:9 | LL | type Ty = u8; | ------------- associated type defaults can't be assumed inside the trait defining them @@ -40,7 +49,7 @@ LL | 0u8 found type `u8` error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:25:29 + --> $DIR/defaults-specialization.rs:26:29 | LL | fn make() -> Self::Ty { 0u8 } | -------- ^^^ expected associated type, found `u8` @@ -53,7 +62,7 @@ LL | fn make() -> Self::Ty { 0u8 } = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:43:29 + --> $DIR/defaults-specialization.rs:44:29 | LL | default type Ty = bool; | ----------------------- expected this associated type @@ -67,7 +76,7 @@ LL | fn make() -> Self::Ty { true } found type `bool` error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:86:32 + --> $DIR/defaults-specialization.rs:87:32 | LL | let _: as Tr>::Ty = 0u8; | ----------------- ^^^ expected associated type, found `u8` @@ -77,13 +86,13 @@ LL | let _: as Tr>::Ty = 0u8; = note: expected associated type ` as Tr>::Ty` found type `u8` help: a method is available that returns ` as Tr>::Ty` - --> $DIR/defaults-specialization.rs:8:5 + --> $DIR/defaults-specialization.rs:9:5 | LL | fn make() -> Self::Ty { | ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make` error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:87:32 + --> $DIR/defaults-specialization.rs:88:32 | LL | let _: as Tr>::Ty = true; | ----------------- ^^^^ expected associated type, found `bool` @@ -93,13 +102,13 @@ LL | let _: as Tr>::Ty = true; = note: expected associated type ` as Tr>::Ty` found type `bool` help: a method is available that returns ` as Tr>::Ty` - --> $DIR/defaults-specialization.rs:8:5 + --> $DIR/defaults-specialization.rs:9:5 | LL | fn make() -> Self::Ty { | ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make` error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:88:33 + --> $DIR/defaults-specialization.rs:89:33 | LL | let _: as Tr>::Ty = 0u8; | ------------------ ^^^ expected associated type, found `u8` @@ -109,13 +118,13 @@ LL | let _: as Tr>::Ty = 0u8; = note: expected associated type ` as Tr>::Ty` found type `u8` help: a method is available that returns ` as Tr>::Ty` - --> $DIR/defaults-specialization.rs:8:5 + --> $DIR/defaults-specialization.rs:9:5 | LL | fn make() -> Self::Ty { | ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make` error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:89:33 + --> $DIR/defaults-specialization.rs:90:33 | LL | let _: as Tr>::Ty = true; | ------------------ ^^^^ expected associated type, found `bool` @@ -125,12 +134,12 @@ LL | let _: as Tr>::Ty = true; = note: expected associated type ` as Tr>::Ty` found type `bool` help: a method is available that returns ` as Tr>::Ty` - --> $DIR/defaults-specialization.rs:8:5 + --> $DIR/defaults-specialization.rs:9:5 | LL | fn make() -> Self::Ty { | ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make` -error: aborting due to 9 previous errors +error: aborting due to 9 previous errors; 1 warning emitted Some errors have detailed explanations: E0053, E0308. For more information about an error, try `rustc --explain E0053`. diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr new file mode 100644 index 0000000000000..2e03986a9ed8f --- /dev/null +++ b/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/higher-ranked-projection.rs:25:5 + | +LL | foo(()); + | ^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr index 3b3e4c3ea117a..811c9a8f5e12b 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr @@ -1,14 +1,12 @@ -error[E0271]: type mismatch resolving `for<'a> <&'a _ as Mirror>::Image == _` +error[E0308]: mismatched types --> $DIR/higher-ranked-projection.rs:25:5 | -LL | fn foo(_t: T) - | --- required by a bound in this -LL | where for<'a> &'a T: Mirror - | ------- required by this bound in `foo` -... LL | foo(()); - | ^^^ expected bound lifetime parameter 'a, found concrete lifetime + | ^^^ one type is more general than the other + | + = note: expected type `&'a ()` + found type `&()` error: aborting due to previous error -For more information about this error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/associated-types/higher-ranked-projection.rs b/src/test/ui/associated-types/higher-ranked-projection.rs index 5315e21b0f5a9..1b5476d4c364f 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.rs +++ b/src/test/ui/associated-types/higher-ranked-projection.rs @@ -23,5 +23,5 @@ fn foo(_t: T) #[rustc_error] fn main() { //[good]~ ERROR fatal error triggered by #[rustc_error] foo(()); - //[bad]~^ ERROR type mismatch + //[bad]~^ ERROR mismatched types } diff --git a/src/test/ui/associated-types/hr-associated-type-bound-1.rs b/src/test/ui/associated-types/hr-associated-type-bound-1.rs new file mode 100644 index 0000000000000..497b86eeab88d --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-1.rs @@ -0,0 +1,18 @@ +trait X<'a> +where + for<'b> >::U: Clone, +{ + type U: ?Sized; + fn f(&self, x: &Self::U) { + ::clone(x); + } +} + +impl X<'_> for i32 { + type U = str; + //~^ ERROR the trait bound `for<'b> >::U: std::clone::Clone` +} + +fn main() { + 1i32.f("abc"); +} diff --git a/src/test/ui/associated-types/hr-associated-type-bound-1.stderr b/src/test/ui/associated-types/hr-associated-type-bound-1.stderr new file mode 100644 index 0000000000000..7ef2faef9c6e7 --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-1.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `for<'b> >::U: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-1.rs:12:14 + | +LL | trait X<'a> + | - required by a bound in this +LL | where +LL | for<'b> >::U: Clone, + | ----- required by this bound in `X` +... +LL | type U = str; + | ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `>::U` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/hr-associated-type-bound-2.rs b/src/test/ui/associated-types/hr-associated-type-bound-2.rs new file mode 100644 index 0000000000000..7ff0fede28cfe --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-2.rs @@ -0,0 +1,21 @@ +trait X<'a> +where + for<'b> >::U: Clone, +{ + type U: ?Sized; + fn f(&self, x: &Self::U) { + ::clone(x); + } +} + +impl X<'_> for u32 +where + for<'b> >::U: Clone, +{ + type U = str; +} + +fn main() { + 1u32.f("abc"); + //~^ ERROR no method named `f` found for type `u32` in the current scope +} diff --git a/src/test/ui/associated-types/hr-associated-type-bound-2.stderr b/src/test/ui/associated-types/hr-associated-type-bound-2.stderr new file mode 100644 index 0000000000000..2a364d349d77e --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-2.stderr @@ -0,0 +1,13 @@ +error[E0599]: no method named `f` found for type `u32` in the current scope + --> $DIR/hr-associated-type-bound-2.rs:19:10 + | +LL | 1u32.f("abc"); + | ^ method not found in `u32` + | + = note: the method `f` exists but the following trait bounds were not satisfied: + `>::U: std::clone::Clone` + which is required by `u32: X` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/associated-types/hr-associated-type-bound-object.rs b/src/test/ui/associated-types/hr-associated-type-bound-object.rs new file mode 100644 index 0000000000000..7c64ae38caf60 --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-object.rs @@ -0,0 +1,14 @@ +trait X<'a> +where + for<'b> >::U: Clone, +{ + type U: ?Sized; +} +fn f<'a, T: X<'a> + ?Sized>(x: &>::U) { + //~^ ERROR the trait bound `for<'b> >::U: std::clone::Clone` is not satisfied + <>::U>::clone(x); +} + +pub fn main() { + f::>("abc"); +} diff --git a/src/test/ui/associated-types/hr-associated-type-bound-object.stderr b/src/test/ui/associated-types/hr-associated-type-bound-object.stderr new file mode 100644 index 0000000000000..db966875c708f --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-object.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `for<'b> >::U: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-object.rs:7:13 + | +LL | trait X<'a> + | - required by a bound in this +LL | where +LL | for<'b> >::U: Clone, + | ----- required by this bound in `X` +... +LL | fn f<'a, T: X<'a> + ?Sized>(x: &>::U) { + | ^^^^^ the trait `for<'b> std::clone::Clone` is not implemented for `>::U` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-1.rs b/src/test/ui/associated-types/hr-associated-type-bound-param-1.rs new file mode 100644 index 0000000000000..a65f8a8c498b7 --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-1.rs @@ -0,0 +1,20 @@ +trait Y<'a, T: ?Sized> +where + T: Y<'a, Self>, + for<'b> >::V: Clone, + for<'b> >::V: Clone, +{ + type V: ?Sized; + fn g(&self, x: &Self::V) { + ::clone(x); + } +} + +impl<'a> Y<'a, u8> for u8 { + type V = str; + //~^ ERROR the trait bound `for<'b> >::V: std::clone::Clone` is not satisfied +} + +fn main() { + 1u8.g("abc"); +} diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-1.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-1.stderr new file mode 100644 index 0000000000000..347a5818dce31 --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-1.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `for<'b> >::V: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-1.rs:14:14 + | +LL | trait Y<'a, T: ?Sized> + | - required by a bound in this +... +LL | for<'b> >::V: Clone, + | ----- required by this bound in `Y` +... +LL | type V = str; + | ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `>::V` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-2.rs b/src/test/ui/associated-types/hr-associated-type-bound-param-2.rs new file mode 100644 index 0000000000000..9f849b0327669 --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-2.rs @@ -0,0 +1,21 @@ +trait Z<'a, T: ?Sized> +where + T: Z<'a, u16>, + //~^ the trait bound `for<'b> >::W: std::clone::Clone` is not satisfied + //~| the trait bound `for<'b> >::W: std::clone::Clone` is not satisfied + for<'b> >::W: Clone, +{ + type W: ?Sized; + fn h(&self, x: &T::W) { + ::clone(x); + } +} + +impl<'a> Z<'a, u16> for u16 { + type W = str; + //~^ ERROR the trait bound `for<'b> >::W: std::clone::Clone +} + +fn main() { + 1u16.h("abc"); +} diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr new file mode 100644 index 0000000000000..e06777e36a8c5 --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr @@ -0,0 +1,51 @@ +error[E0277]: the trait bound `for<'b> >::W: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-2.rs:3:8 + | +LL | trait Z<'a, T: ?Sized> + | - required by a bound in this +LL | where +LL | T: Z<'a, u16>, + | ^^^^^^^^^^ the trait `for<'b> std::clone::Clone` is not implemented for `>::W` +... +LL | for<'b> >::W: Clone, + | ----- required by this bound in `Z` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +error[E0277]: the trait bound `for<'b> >::W: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-2.rs:15:14 + | +LL | trait Z<'a, T: ?Sized> + | - required by a bound in this +... +LL | for<'b> >::W: Clone, + | ----- required by this bound in `Z` +... +LL | type W = str; + | ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `>::W` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +error[E0277]: the trait bound `for<'b> >::W: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-2.rs:3:8 + | +LL | trait Z<'a, T: ?Sized> + | - required by a bound in this +LL | where +LL | T: Z<'a, u16>, + | ^^^^^^^^^^ the trait `for<'b> std::clone::Clone` is not implemented for `>::W` +... +LL | for<'b> >::W: Clone, + | ----- required by this bound in `Z` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-3.rs b/src/test/ui/associated-types/hr-associated-type-bound-param-3.rs new file mode 100644 index 0000000000000..9aca59f8ce6d7 --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-3.rs @@ -0,0 +1,21 @@ +// ignore-tidy-linelength + +trait X<'a, T> +where + for<'b> T: X<'b, T>, + for<'b> >::U: Clone, +{ + type U: ?Sized; + fn f(x: &>::U) { + <>::U>::clone(x); + } +} + +impl X<'_, (T,)> for (S,) { + type U = str; + //~^ ERROR the trait bound `for<'b> <(T,) as X<'b, (T,)>>::U: std::clone::Clone` is not satisfied +} + +pub fn main() { + <(i32,) as X<(i32,)>>::f("abc"); +} diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-3.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-3.stderr new file mode 100644 index 0000000000000..ff56f60e4c9e5 --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-3.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `for<'b> <(T,) as X<'b, (T,)>>::U: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-3.rs:15:14 + | +LL | trait X<'a, T> + | - required by a bound in this +... +LL | for<'b> >::U: Clone, + | ----- required by this bound in `X` +... +LL | type U = str; + | ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<(T,) as X<'b, (T,)>>::U` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-4.rs b/src/test/ui/associated-types/hr-associated-type-bound-param-4.rs new file mode 100644 index 0000000000000..ffe43c674c3dc --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-4.rs @@ -0,0 +1,19 @@ +trait X<'a, T> +where + for<'b> (T,): X<'b, T>, + for<'b> <(T,) as X<'b, T>>::U: Clone, +{ + type U: ?Sized; + fn f(x: &<(T,) as X<'_, T>>::U) { + <<(T,) as X<'_, T>>::U>::clone(x); + } +} + +impl X<'_, T> for (S,) { + type U = str; + //~^ ERROR the trait bound `for<'b> <(T,) as X<'b, T>>::U: std::clone::Clone` is not satisfied +} + +pub fn main() { + <(i32,) as X>::f("abc"); +} diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-4.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-4.stderr new file mode 100644 index 0000000000000..c41efb8b6e1a2 --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-4.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `for<'b> <(T,) as X<'b, T>>::U: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-4.rs:13:14 + | +LL | trait X<'a, T> + | - required by a bound in this +... +LL | for<'b> <(T,) as X<'b, T>>::U: Clone, + | ----- required by this bound in `X` +... +LL | type U = str; + | ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<(T,) as X<'b, T>>::U` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-5.rs b/src/test/ui/associated-types/hr-associated-type-bound-param-5.rs new file mode 100644 index 0000000000000..dcca0b3ce92aa --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-5.rs @@ -0,0 +1,41 @@ +// ignore-tidy-linelength + +trait Cycle: Sized { + type Next: Cycle; +} + +impl Cycle for Box { + type Next = Vec; +} + +impl Cycle for Vec { + type Next = Box; +} + +trait X<'a, T: Cycle + for<'b> X<'b, T>> +where + for<'b> >::U: Clone, + for<'b> T::Next: X<'b, T::Next>, + for<'b> >::U: Clone, +{ + type U: ?Sized; + fn f(x: &>::U) { + <>::U>::clone(x); + } +} + +impl X<'_, Vec> for S { + type U = str; + //~^ ERROR the trait bound `for<'b> as X<'b, std::boxed::Box>>::U: std::clone::Clone` is not satisfied + //~| ERROR the trait bound `for<'b> as X<'b, std::vec::Vec>>::U: std::clone::Clone` is not satisfied +} + +impl X<'_, Box> for S { + type U = str; + //~^ ERROR the trait bound `for<'b> as X<'b, std::boxed::Box>>::U: std::clone::Clone` is not satisfied + //~| ERROR the trait bound `for<'b> as X<'b, std::vec::Vec>>::U: std::clone::Clone` is not satisfied +} + +pub fn main() { + >>::f("abc"); +} diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-5.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-5.stderr new file mode 100644 index 0000000000000..39c191e974777 --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-5.stderr @@ -0,0 +1,67 @@ +error[E0277]: the trait bound `for<'b> as X<'b, std::boxed::Box>>::U: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-5.rs:28:14 + | +LL | trait X<'a, T: Cycle + for<'b> X<'b, T>> + | - required by a bound in this +... +LL | for<'b> >::U: Clone, + | ----- required by this bound in `X` +... +LL | type U = str; + | ^^^ the trait `for<'b> std::clone::Clone` is not implemented for ` as X<'b, std::boxed::Box>>::U` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +error[E0277]: the trait bound `for<'b> as X<'b, std::vec::Vec>>::U: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-5.rs:28:14 + | +LL | trait X<'a, T: Cycle + for<'b> X<'b, T>> + | - required by a bound in this +LL | where +LL | for<'b> >::U: Clone, + | ----- required by this bound in `X` +... +LL | type U = str; + | ^^^ the trait `for<'b> std::clone::Clone` is not implemented for ` as X<'b, std::vec::Vec>>::U` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +error[E0277]: the trait bound `for<'b> as X<'b, std::vec::Vec>>::U: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-5.rs:34:14 + | +LL | trait X<'a, T: Cycle + for<'b> X<'b, T>> + | - required by a bound in this +... +LL | for<'b> >::U: Clone, + | ----- required by this bound in `X` +... +LL | type U = str; + | ^^^ the trait `for<'b> std::clone::Clone` is not implemented for ` as X<'b, std::vec::Vec>>::U` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +error[E0277]: the trait bound `for<'b> as X<'b, std::boxed::Box>>::U: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-5.rs:34:14 + | +LL | trait X<'a, T: Cycle + for<'b> X<'b, T>> + | - required by a bound in this +LL | where +LL | for<'b> >::U: Clone, + | ----- required by this bound in `X` +... +LL | type U = str; + | ^^^ the trait `for<'b> std::clone::Clone` is not implemented for ` as X<'b, std::boxed::Box>>::U` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-6.rs b/src/test/ui/associated-types/hr-associated-type-bound-param-6.rs new file mode 100644 index 0000000000000..4b8018cb43024 --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-6.rs @@ -0,0 +1,20 @@ +trait X<'a, T> +where + for<'b> T: X<'b, T>, + for<'b> >::U: Clone, +{ + type U: ?Sized; + fn f(x: &>::U) { + <>::U>::clone(x); + } +} + +impl X<'_, T> for (S,) { + //~^ ERROR the trait bound `for<'b> T: X<'b, T>` is not satisfied + type U = str; + //~^ ERROR the trait bound `for<'b> >::U: std::clone::Clone` is not satisfied +} + +pub fn main() { + <(i32,) as X>::f("abc"); +} diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-6.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-6.stderr new file mode 100644 index 0000000000000..83845d3a9410e --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-6.stderr @@ -0,0 +1,36 @@ +error[E0277]: the trait bound `for<'b> >::U: std::clone::Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-6.rs:14:14 + | +LL | trait X<'a, T> + | - required by a bound in this +... +LL | for<'b> >::U: Clone, + | ----- required by this bound in `X` +... +LL | type U = str; + | ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `>::U` + | + = help: the following implementations were found: + <&T as std::clone::Clone> + <&mut T as std::clone::Clone> + +error[E0277]: the trait bound `for<'b> T: X<'b, T>` is not satisfied + --> $DIR/hr-associated-type-bound-param-6.rs:12:12 + | +LL | trait X<'a, T> + | - required by a bound in this +LL | where +LL | for<'b> T: X<'b, T>, + | -------- required by this bound in `X` +... +LL | impl X<'_, T> for (S,) { + | ^^^^^^^^ the trait `for<'b> X<'b, T>` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | impl X<'b, T>> X<'_, T> for (S,) { + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/hr-associated-type-projection-1.rs b/src/test/ui/associated-types/hr-associated-type-projection-1.rs new file mode 100644 index 0000000000000..0d4567a55fc99 --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-projection-1.rs @@ -0,0 +1,21 @@ +trait UnsafeCopy<'a, T: Copy> +where + for<'b> >::Item: std::ops::Deref, +{ + type Item; + + fn bug(item: &Self::Item) -> () { + let x: T = **item; + &x as *const _; + } +} + +impl UnsafeCopy<'_, T> for T { + //~^ ERROR the trait bound `>::Item: std::ops::Deref` is not satisfied + type Item = T; + //~^ ERROR the trait bound `for<'b> >::Item: std::ops::Deref +} + +pub fn main() { + <&'static str>::bug(&""); +} diff --git a/src/test/ui/associated-types/hr-associated-type-projection-1.stderr b/src/test/ui/associated-types/hr-associated-type-projection-1.stderr new file mode 100644 index 0000000000000..5ab57410c441b --- /dev/null +++ b/src/test/ui/associated-types/hr-associated-type-projection-1.stderr @@ -0,0 +1,30 @@ +error[E0277]: the trait bound `for<'b> >::Item: std::ops::Deref` is not satisfied + --> $DIR/hr-associated-type-projection-1.rs:15:17 + | +LL | trait UnsafeCopy<'a, T: Copy> + | ---------- required by a bound in this +LL | where +LL | for<'b> >::Item: std::ops::Deref, + | --------------------------- required by this bound in `UnsafeCopy` +... +LL | type Item = T; + | ^ the trait `for<'b> std::ops::Deref` is not implemented for `>::Item` + | + = help: the following implementations were found: + <&T as std::ops::Deref> + <&mut T as std::ops::Deref> + +error[E0277]: the trait bound `>::Item: std::ops::Deref` is not satisfied + --> $DIR/hr-associated-type-projection-1.rs:13:33 + | +LL | impl UnsafeCopy<'_, T> for T { + | ^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `>::Item` + | +help: consider further restricting the associated type + | +LL | impl UnsafeCopy<'_, T> for T where >::Item: std::ops::Deref { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/auto-is-contextual.rs b/src/test/ui/auto-traits/auto-is-contextual.rs similarity index 100% rename from src/test/ui/auto-is-contextual.rs rename to src/test/ui/auto-traits/auto-is-contextual.rs diff --git a/src/test/ui/auto-traits/auto-trait-projection-recursion.rs b/src/test/ui/auto-traits/auto-trait-projection-recursion.rs new file mode 100644 index 0000000000000..a36f26f02e9f4 --- /dev/null +++ b/src/test/ui/auto-traits/auto-trait-projection-recursion.rs @@ -0,0 +1,34 @@ +// Checking the `Send` bound in `main` requires: +// +// checking as Y>::P: Send +// which normalizes to Box>>: Send +// which needs X>: Send +// which needs as Y>::P: Send +// +// At this point we used to normalize the predicate to `Box>>: Send` +// and continue in a loop where we created new region variables to the +// recursion limit. To avoid this we now "canonicalize" region variables to +// lowest unified region vid. This means we instead have to prove +// `Box>>: Send`, which we can because auto traits are coinductive. + +// check-pass + +// Avoid a really long error message if this regresses. +#![recursion_limit="20"] + +trait Y { + type P; +} + +impl<'a> Y for C<'a> { + type P = Box>>; +} + +struct C<'a>(&'a ()); +struct X(T::P); + +fn is_send() {} + +fn main() { + is_send::>>(); +} diff --git a/src/test/ui/auto-trait-validation.rs b/src/test/ui/auto-traits/auto-trait-validation.rs similarity index 100% rename from src/test/ui/auto-trait-validation.rs rename to src/test/ui/auto-traits/auto-trait-validation.rs diff --git a/src/test/ui/auto-trait-validation.stderr b/src/test/ui/auto-traits/auto-trait-validation.stderr similarity index 100% rename from src/test/ui/auto-trait-validation.stderr rename to src/test/ui/auto-traits/auto-trait-validation.stderr diff --git a/src/test/ui/traits/auto-traits.rs b/src/test/ui/auto-traits/auto-traits.rs similarity index 100% rename from src/test/ui/traits/auto-traits.rs rename to src/test/ui/auto-traits/auto-traits.rs diff --git a/src/test/ui/issues/issue-23080-2.rs b/src/test/ui/auto-traits/issue-23080-2.rs similarity index 100% rename from src/test/ui/issues/issue-23080-2.rs rename to src/test/ui/auto-traits/issue-23080-2.rs diff --git a/src/test/ui/issues/issue-23080-2.stderr b/src/test/ui/auto-traits/issue-23080-2.stderr similarity index 100% rename from src/test/ui/issues/issue-23080-2.stderr rename to src/test/ui/auto-traits/issue-23080-2.stderr diff --git a/src/test/ui/issues/issue-23080.rs b/src/test/ui/auto-traits/issue-23080.rs similarity index 100% rename from src/test/ui/issues/issue-23080.rs rename to src/test/ui/auto-traits/issue-23080.rs diff --git a/src/test/ui/issues/issue-23080.stderr b/src/test/ui/auto-traits/issue-23080.stderr similarity index 100% rename from src/test/ui/issues/issue-23080.stderr rename to src/test/ui/auto-traits/issue-23080.stderr diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.rs b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs similarity index 100% rename from src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.rs rename to src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr similarity index 100% rename from src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr rename to src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.rs b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits.rs similarity index 100% rename from src/test/ui/typeck/typeck-auto-trait-no-supertraits.rs rename to src/test/ui/auto-traits/typeck-auto-trait-no-supertraits.rs diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr similarity index 100% rename from src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr rename to src/test/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.rs b/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.rs similarity index 100% rename from src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.rs rename to src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.rs diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr b/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr similarity index 100% rename from src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr rename to src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.rs b/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types.rs similarity index 100% rename from src/test/ui/typeck/typeck-default-trait-impl-constituent-types.rs rename to src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types.rs diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr b/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types.stderr similarity index 100% rename from src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr rename to src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types.stderr diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation.rs b/src/test/ui/auto-traits/typeck-default-trait-impl-negation.rs similarity index 100% rename from src/test/ui/typeck/typeck-default-trait-impl-negation.rs rename to src/test/ui/auto-traits/typeck-default-trait-impl-negation.rs diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr b/src/test/ui/auto-traits/typeck-default-trait-impl-negation.stderr similarity index 100% rename from src/test/ui/typeck/typeck-default-trait-impl-negation.stderr rename to src/test/ui/auto-traits/typeck-default-trait-impl-negation.stderr diff --git a/src/test/ui/typeck/typeck-default-trait-impl-precedence.rs b/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.rs similarity index 100% rename from src/test/ui/typeck/typeck-default-trait-impl-precedence.rs rename to src/test/ui/auto-traits/typeck-default-trait-impl-precedence.rs diff --git a/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr b/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr similarity index 100% rename from src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr rename to src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr diff --git a/src/test/ui/binop/binop-consume-args.stderr b/src/test/ui/binop/binop-consume-args.stderr index addc8a0efe1aa..acdc03e372638 100644 --- a/src/test/ui/binop/binop-consume-args.stderr +++ b/src/test/ui/binop/binop-consume-args.stderr @@ -4,15 +4,10 @@ error[E0382]: use of moved value: `lhs` LL | fn add, B>(lhs: A, rhs: B) { | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait LL | lhs + rhs; - | --------- `lhs` moved due to usage in operator + | --- value moved here LL | drop(lhs); | ^^^ value used here after move | -note: calling this operator moves the left-hand side - --> $SRC_DIR/libcore/ops/arith.rs:LL:COL - | -LL | fn add(self, rhs: Rhs) -> Self::Output; - | ^^^^ help: consider further restricting this bound | LL | fn add + Copy, B>(lhs: A, rhs: B) { @@ -40,15 +35,10 @@ error[E0382]: use of moved value: `lhs` LL | fn sub, B>(lhs: A, rhs: B) { | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait LL | lhs - rhs; - | --------- `lhs` moved due to usage in operator + | --- value moved here LL | drop(lhs); | ^^^ value used here after move | -note: calling this operator moves the left-hand side - --> $SRC_DIR/libcore/ops/arith.rs:LL:COL - | -LL | fn sub(self, rhs: Rhs) -> Self::Output; - | ^^^^ help: consider further restricting this bound | LL | fn sub + Copy, B>(lhs: A, rhs: B) { @@ -76,15 +66,10 @@ error[E0382]: use of moved value: `lhs` LL | fn mul, B>(lhs: A, rhs: B) { | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait LL | lhs * rhs; - | --------- `lhs` moved due to usage in operator + | --- value moved here LL | drop(lhs); | ^^^ value used here after move | -note: calling this operator moves the left-hand side - --> $SRC_DIR/libcore/ops/arith.rs:LL:COL - | -LL | fn mul(self, rhs: Rhs) -> Self::Output; - | ^^^^ help: consider further restricting this bound | LL | fn mul + Copy, B>(lhs: A, rhs: B) { @@ -112,15 +97,10 @@ error[E0382]: use of moved value: `lhs` LL | fn div, B>(lhs: A, rhs: B) { | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait LL | lhs / rhs; - | --------- `lhs` moved due to usage in operator + | --- value moved here LL | drop(lhs); | ^^^ value used here after move | -note: calling this operator moves the left-hand side - --> $SRC_DIR/libcore/ops/arith.rs:LL:COL - | -LL | fn div(self, rhs: Rhs) -> Self::Output; - | ^^^^ help: consider further restricting this bound | LL | fn div + Copy, B>(lhs: A, rhs: B) { @@ -148,15 +128,10 @@ error[E0382]: use of moved value: `lhs` LL | fn rem, B>(lhs: A, rhs: B) { | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait LL | lhs % rhs; - | --------- `lhs` moved due to usage in operator + | --- value moved here LL | drop(lhs); | ^^^ value used here after move | -note: calling this operator moves the left-hand side - --> $SRC_DIR/libcore/ops/arith.rs:LL:COL - | -LL | fn rem(self, rhs: Rhs) -> Self::Output; - | ^^^^ help: consider further restricting this bound | LL | fn rem + Copy, B>(lhs: A, rhs: B) { @@ -184,15 +159,10 @@ error[E0382]: use of moved value: `lhs` LL | fn bitand, B>(lhs: A, rhs: B) { | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait LL | lhs & rhs; - | --------- `lhs` moved due to usage in operator + | --- value moved here LL | drop(lhs); | ^^^ value used here after move | -note: calling this operator moves the left-hand side - --> $SRC_DIR/libcore/ops/bit.rs:LL:COL - | -LL | fn bitand(self, rhs: Rhs) -> Self::Output; - | ^^^^ help: consider further restricting this bound | LL | fn bitand + Copy, B>(lhs: A, rhs: B) { @@ -220,15 +190,10 @@ error[E0382]: use of moved value: `lhs` LL | fn bitor, B>(lhs: A, rhs: B) { | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait LL | lhs | rhs; - | --------- `lhs` moved due to usage in operator + | --- value moved here LL | drop(lhs); | ^^^ value used here after move | -note: calling this operator moves the left-hand side - --> $SRC_DIR/libcore/ops/bit.rs:LL:COL - | -LL | fn bitor(self, rhs: Rhs) -> Self::Output; - | ^^^^ help: consider further restricting this bound | LL | fn bitor + Copy, B>(lhs: A, rhs: B) { @@ -256,15 +221,10 @@ error[E0382]: use of moved value: `lhs` LL | fn bitxor, B>(lhs: A, rhs: B) { | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait LL | lhs ^ rhs; - | --------- `lhs` moved due to usage in operator + | --- value moved here LL | drop(lhs); | ^^^ value used here after move | -note: calling this operator moves the left-hand side - --> $SRC_DIR/libcore/ops/bit.rs:LL:COL - | -LL | fn bitxor(self, rhs: Rhs) -> Self::Output; - | ^^^^ help: consider further restricting this bound | LL | fn bitxor + Copy, B>(lhs: A, rhs: B) { @@ -292,15 +252,10 @@ error[E0382]: use of moved value: `lhs` LL | fn shl, B>(lhs: A, rhs: B) { | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait LL | lhs << rhs; - | ---------- `lhs` moved due to usage in operator + | --- value moved here LL | drop(lhs); | ^^^ value used here after move | -note: calling this operator moves the left-hand side - --> $SRC_DIR/libcore/ops/bit.rs:LL:COL - | -LL | fn shl(self, rhs: Rhs) -> Self::Output; - | ^^^^ help: consider further restricting this bound | LL | fn shl + Copy, B>(lhs: A, rhs: B) { @@ -328,15 +283,10 @@ error[E0382]: use of moved value: `lhs` LL | fn shr, B>(lhs: A, rhs: B) { | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait LL | lhs >> rhs; - | ---------- `lhs` moved due to usage in operator + | --- value moved here LL | drop(lhs); | ^^^ value used here after move | -note: calling this operator moves the left-hand side - --> $SRC_DIR/libcore/ops/bit.rs:LL:COL - | -LL | fn shr(self, rhs: Rhs) -> Self::Output; - | ^^^^ help: consider further restricting this bound | LL | fn shr + Copy, B>(lhs: A, rhs: B) { diff --git a/src/test/ui/binop/binop-move-semantics.stderr b/src/test/ui/binop/binop-move-semantics.stderr index 97b70efe20e79..6d5ac9cab30c0 100644 --- a/src/test/ui/binop/binop-move-semantics.stderr +++ b/src/test/ui/binop/binop-move-semantics.stderr @@ -1,21 +1,14 @@ error[E0382]: use of moved value: `x` --> $DIR/binop-move-semantics.rs:8:5 | -LL | fn double_move>(x: T) { - | - move occurs because `x` has type `T`, which does not implement the `Copy` trait -LL | / x -LL | | + -LL | | x; - | | ^ - | | | - | |_____value used here after move - | `x` moved due to usage in operator - | -note: calling this operator moves the left-hand side - --> $SRC_DIR/libcore/ops/arith.rs:LL:COL +LL | fn double_move>(x: T) { + | - move occurs because `x` has type `T`, which does not implement the `Copy` trait +LL | x + | - value moved here +LL | + +LL | x; + | ^ value used here after move | -LL | fn add(self, rhs: Rhs) -> Self::Output; - | ^^^^ help: consider further restricting this bound | LL | fn double_move + Copy>(x: T) { diff --git a/src/test/ui/borrowck/borrowck-unboxed-closures.stderr b/src/test/ui/borrowck/borrowck-unboxed-closures.stderr index bc1721944fbbb..a51cda548efd7 100644 --- a/src/test/ui/borrowck/borrowck-unboxed-closures.stderr +++ b/src/test/ui/borrowck/borrowck-unboxed-closures.stderr @@ -22,15 +22,10 @@ error[E0382]: use of moved value: `f` LL | fn c isize>(f: F) { | - move occurs because `f` has type `F`, which does not implement the `Copy` trait LL | f(1, 2); - | ------- `f` moved due to this call + | - value moved here LL | f(1, 2); | ^ value used here after move | -note: this value implements `FnOnce`, which causes it to be moved when called - --> $DIR/borrowck-unboxed-closures.rs:11:5 - | -LL | f(1, 2); - | ^ help: consider further restricting this bound | LL | fn c isize + Copy>(f: F) { diff --git a/src/test/ui/chalkify/impl_wf.rs b/src/test/ui/chalkify/impl_wf.rs index 8aa876422924d..fdc94f69bf21a 100644 --- a/src/test/ui/chalkify/impl_wf.rs +++ b/src/test/ui/chalkify/impl_wf.rs @@ -8,12 +8,9 @@ trait Bar { impl Foo for i32 { } -// FIXME(chalk): blocked on better handling of builtin traits for non-struct -// application types (or a workaround) -/* impl Foo for str { } -//^ ERROR the size for values of type `str` cannot be known at compilation time -*/ +//~^ ERROR the size for values of type `str` cannot be known at compilation time + // Implicit `T: Sized` bound. impl Foo for Option { } diff --git a/src/test/ui/chalkify/impl_wf.stderr b/src/test/ui/chalkify/impl_wf.stderr index befd688741c80..5293bbaecd389 100644 --- a/src/test/ui/chalkify/impl_wf.stderr +++ b/src/test/ui/chalkify/impl_wf.stderr @@ -1,5 +1,17 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/impl_wf.rs:11:6 + | +LL | trait Foo: Sized { } + | ----- required by this bound in `Foo` +... +LL | impl Foo for str { } + | ^^^ 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 + error[E0277]: the trait bound `f32: Foo` is not satisfied - --> $DIR/impl_wf.rs:43:6 + --> $DIR/impl_wf.rs:40:6 | LL | trait Baz where U: Foo { } | --- required by this bound in `Baz` @@ -7,6 +19,6 @@ LL | trait Baz where U: Foo { } LL | impl Baz for f32 { } | ^^^^^^^^ the trait `Foo` is not implemented for `f32` -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/chalkify/inherent_impl.rs b/src/test/ui/chalkify/inherent_impl.rs index 44e120c1eebba..9dd9eb320ddd3 100644 --- a/src/test/ui/chalkify/inherent_impl.rs +++ b/src/test/ui/chalkify/inherent_impl.rs @@ -1,5 +1,7 @@ // run-pass // compile-flags: -Z chalk +// FIXME(chalk): remove when uncommented +#![allow(dead_code, unused_variables)] trait Foo { } @@ -9,6 +11,8 @@ struct S { x: T, } +// FIXME(chalk): need late-bound regions on FnDefs +/* fn only_foo(_x: &T) { } impl S { @@ -17,6 +21,7 @@ impl S { only_foo(&self.x) } } +*/ trait Bar { } impl Bar for u32 { } @@ -26,10 +31,16 @@ fn only_bar() { } impl S { // Test that the environment of `dummy_bar` adds up with the environment // of the inherent impl. + // FIXME(chalk): need late-bound regions on FnDefs + /* fn dummy_bar(&self) { only_foo(&self.x); only_bar::(); } + */ + fn dummy_bar() { + only_bar::(); + } } fn main() { @@ -37,6 +48,10 @@ fn main() { x: 5, }; + // FIXME(chalk): need late-bound regions on FnDefs + /* s.dummy_foo(); s.dummy_bar::(); + */ + S::::dummy_bar::(); } diff --git a/src/test/ui/chalkify/type_inference.rs b/src/test/ui/chalkify/type_inference.rs index 5175c5d062a6e..2b62bf18a71ce 100644 --- a/src/test/ui/chalkify/type_inference.rs +++ b/src/test/ui/chalkify/type_inference.rs @@ -18,11 +18,11 @@ fn main() { // is expecting a variable of type `i32`. This behavior differs from the // old-style trait solver. I guess this will change, that's why I'm // adding that test. - // FIXME(chalk): partially blocked on float/int special casing - only_foo(x); //~ ERROR the trait bound `f64: Foo` is not satisfied + // FIXME(chalk): order of these two errors is non-deterministic, + // so let's just hide one for now + //only_foo(x); // ERROR the trait bound `f64: Foo` is not satisfied // Here we have two solutions so we get back the behavior of the old-style // trait solver. - // FIXME(chalk): blocked on float/int special casing - //only_bar(x); // ERROR the trait bound `{float}: Bar` is not satisfied + only_bar(x); //~ ERROR the trait bound `f64: Bar` is not satisfied } diff --git a/src/test/ui/chalkify/type_inference.stderr b/src/test/ui/chalkify/type_inference.stderr index ee9e67c6c7884..5cfb968404df6 100644 --- a/src/test/ui/chalkify/type_inference.stderr +++ b/src/test/ui/chalkify/type_inference.stderr @@ -1,11 +1,11 @@ -error[E0277]: the trait bound `f64: Foo` is not satisfied - --> $DIR/type_inference.rs:22:5 +error[E0277]: the trait bound `f64: Bar` is not satisfied + --> $DIR/type_inference.rs:27:5 | -LL | fn only_foo(_x: T) { } - | --- required by this bound in `only_foo` +LL | fn only_bar(_x: T) { } + | --- required by this bound in `only_bar` ... -LL | only_foo(x); - | ^^^^^^^^ the trait `Foo` is not implemented for `f64` +LL | only_bar(x); + | ^^^^^^^^ the trait `Bar` is not implemented for `f64` error: aborting due to previous error diff --git a/src/test/ui/chalkify/type_wf.rs b/src/test/ui/chalkify/type_wf.rs index 396baf814a0b0..7c469d99c5799 100644 --- a/src/test/ui/chalkify/type_wf.rs +++ b/src/test/ui/chalkify/type_wf.rs @@ -1,5 +1,4 @@ -// FIXME(chalk): should have an error, see below -// check-pass +// check-fail // compile-flags: -Z chalk trait Foo { } @@ -16,17 +15,11 @@ fn main() { x: 5, }; - // FIXME(chalk): blocked on float/int special handling. Needs to know that {float}: !i32 - /* - let s = S { // ERROR the trait bound `{float}: Foo` is not satisfied + let s = S { //~ ERROR the trait bound `f64: Foo` is not satisfied x: 5.0, }; - */ - // FIXME(chalk): blocked on float/int special handling. Needs to know that {float}: Sized - /* let s = S { x: Some(5.0), }; - */ } diff --git a/src/test/ui/chalkify/type_wf.stderr b/src/test/ui/chalkify/type_wf.stderr new file mode 100644 index 0000000000000..ab585a6ed2140 --- /dev/null +++ b/src/test/ui/chalkify/type_wf.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `f64: Foo` is not satisfied + --> $DIR/type_wf.rs:18:13 + | +LL | struct S { + | ---------------- required by `S` +... +LL | let s = S { + | ^ the trait `Foo` is not implemented for `f64` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/check-static-immutable-mut-slices.rs b/src/test/ui/check-static-immutable-mut-slices.rs index d5e9fb2dede93..3be02f6a0f674 100644 --- a/src/test/ui/check-static-immutable-mut-slices.rs +++ b/src/test/ui/check-static-immutable-mut-slices.rs @@ -1,6 +1,6 @@ // Checks that immutable static items can't have mutable slices static TEST: &'static mut [isize] = &mut []; -//~^ ERROR references in statics may only refer to immutable values +//~^ ERROR mutable references are not allowed in statics pub fn main() { } diff --git a/src/test/ui/check-static-immutable-mut-slices.stderr b/src/test/ui/check-static-immutable-mut-slices.stderr index 66fe8646e1016..9ffbb483d139d 100644 --- a/src/test/ui/check-static-immutable-mut-slices.stderr +++ b/src/test/ui/check-static-immutable-mut-slices.stderr @@ -1,12 +1,9 @@ -error[E0658]: references in statics may only refer to immutable values +error[E0764]: mutable references are not allowed in statics --> $DIR/check-static-immutable-mut-slices.rs:3:37 | LL | static TEST: &'static mut [isize] = &mut []; - | ^^^^^^^ statics require immutable values - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + | ^^^^^^^ `&mut` is only allowed in `const fn` error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. +For more information about this error, try `rustc --explain E0764`. diff --git a/src/test/ui/check-static-values-constraints.stderr b/src/test/ui/check-static-values-constraints.stderr index 6b5a739899cac..b00affdca850a 100644 --- a/src/test/ui/check-static-values-constraints.stderr +++ b/src/test/ui/check-static-values-constraints.stderr @@ -5,7 +5,9 @@ LL | ..SafeStruct{field1: SafeEnum::Va | ___________________________________________^ LL | | LL | | field2: SafeEnum::Variant1}}; - | |________________________________________________________________________________^ statics cannot evaluate destructors + | | ^- value is dropped here + | |________________________________________________________________________________| + | statics cannot evaluate destructors error[E0010]: allocations are not allowed in statics --> $DIR/check-static-values-constraints.rs:79:33 diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr index 97fdb76dd11c7..64a0b52a1fac5 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr @@ -1,42 +1,43 @@ -error[E0631]: type mismatch in closure arguments - --> $DIR/expect-fn-supply-fn.rs:30:5 +error: lifetime may not live long enough + --> $DIR/expect-fn-supply-fn.rs:16:49 | -LL | fn with_closure_expecting_fn_with_free_region(_: F) - | ------------------------------------------ required by a bound in this -LL | where F: for<'a> FnOnce(fn(&'a u32), &i32) - | ------------------------- required by this bound in `with_closure_expecting_fn_with_free_region` +LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { + | -- lifetime `'x` defined here ... -LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _` - | | - | expected signature of `fn(fn(&'a u32), &i32) -> _` +LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); + | ^ + | | + | has type `fn(&'1 u32)` + | requires that `'1` must outlive `'x` -error[E0631]: type mismatch in closure arguments - --> $DIR/expect-fn-supply-fn.rs:37:5 +error: lifetime may not live long enough + --> $DIR/expect-fn-supply-fn.rs:16:49 | -LL | fn with_closure_expecting_fn_with_bound_region(_: F) - | ------------------------------------------- required by a bound in this -LL | where F: FnOnce(fn(&u32), &i32) - | ---------------------- required by this bound in `with_closure_expecting_fn_with_bound_region` +LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { + | -- lifetime `'x` defined here ... +LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); + | ^ requires that `'x` must outlive `'static` + | + = help: consider replacing `'x` with `'static` + +error: higher-ranked subtype error + --> $DIR/expect-fn-supply-fn.rs:32:49 + | +LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); + | ^ + +error: higher-ranked subtype error + --> $DIR/expect-fn-supply-fn.rs:39:50 + | LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _` - | | - | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` + | ^ -error[E0631]: type mismatch in closure arguments - --> $DIR/expect-fn-supply-fn.rs:46:5 +error: higher-ranked subtype error + --> $DIR/expect-fn-supply-fn.rs:48:50 | -LL | fn with_closure_expecting_fn_with_bound_region(_: F) - | ------------------------------------------- required by a bound in this -LL | where F: FnOnce(fn(&u32), &i32) - | ---------------------- required by this bound in `with_closure_expecting_fn_with_bound_region` -... LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- found signature of `for<'r> fn(fn(&'r u32), _) -> _` - | | - | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` + | ^ -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs index a4e43da91baf8..c81c40c18b45b 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs @@ -1,10 +1,12 @@ fn with_closure_expecting_fn_with_free_region(_: F) - where F: for<'a> FnOnce(fn(&'a u32), &i32) +where + F: for<'a> FnOnce(fn(&'a u32), &i32), { } fn with_closure_expecting_fn_with_bound_region(_: F) - where F: FnOnce(fn(&u32), &i32) +where + F: FnOnce(fn(&u32), &i32), { } @@ -28,14 +30,14 @@ fn expect_free_supply_bound() { // Here, we are given a function whose region is bound at closure level, // but we expect one bound in the argument. Error results. with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); - //~^ ERROR type mismatch + //~^ ERROR mismatched types } fn expect_bound_supply_free_from_fn<'x>(x: &'x u32) { // Here, we are given a `fn(&u32)` but we expect a `fn(&'x // u32)`. In principle, this could be ok, but we demand equality. with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); - //~^ ERROR type mismatch + //~^ ERROR mismatched types } fn expect_bound_supply_free_from_closure() { @@ -44,7 +46,7 @@ fn expect_bound_supply_free_from_closure() { // the argument level. type Foo<'a> = fn(&'a u32); with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { - //~^ ERROR type mismatch + //~^ ERROR mismatched types }); } @@ -52,8 +54,7 @@ fn expect_bound_supply_bound<'x>(x: &'x u32) { // No error in this case. The supplied type supplies the bound // regions, and hence we are able to figure out the type of `y` // from the expected type - with_closure_expecting_fn_with_bound_region(|x: for<'z> fn(&'z u32), y| { - }); + with_closure_expecting_fn_with_bound_region(|x: for<'z> fn(&'z u32), y| {}); } -fn main() { } +fn main() {} diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr index fae41c4114abc..0de15dfa7357d 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr @@ -1,81 +1,68 @@ error[E0308]: mismatched types - --> $DIR/expect-fn-supply-fn.rs:14:52 + --> $DIR/expect-fn-supply-fn.rs:16:52 | LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); | ^^^^^^^^^^^ lifetime mismatch | = note: expected fn pointer `fn(&u32)` found fn pointer `fn(&'x u32)` -note: the anonymous lifetime #2 defined on the body at 14:48... - --> $DIR/expect-fn-supply-fn.rs:14:48 +note: the anonymous lifetime #2 defined on the body at 16:48... + --> $DIR/expect-fn-supply-fn.rs:16:48 | LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); | ^^^^^^^^^^^^^^^^^^^^^^ -note: ...does not necessarily outlive the lifetime `'x` as defined on the function body at 11:36 - --> $DIR/expect-fn-supply-fn.rs:11:36 +note: ...does not necessarily outlive the lifetime `'x` as defined on the function body at 13:36 + --> $DIR/expect-fn-supply-fn.rs:13:36 | LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { | ^^ error[E0308]: mismatched types - --> $DIR/expect-fn-supply-fn.rs:14:52 + --> $DIR/expect-fn-supply-fn.rs:16:52 | LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); | ^^^^^^^^^^^ lifetime mismatch | = note: expected fn pointer `fn(&u32)` found fn pointer `fn(&'x u32)` -note: the lifetime `'x` as defined on the function body at 11:36... - --> $DIR/expect-fn-supply-fn.rs:11:36 +note: the lifetime `'x` as defined on the function body at 13:36... + --> $DIR/expect-fn-supply-fn.rs:13:36 | LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { | ^^ -note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 14:48 - --> $DIR/expect-fn-supply-fn.rs:14:48 +note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 16:48 + --> $DIR/expect-fn-supply-fn.rs:16:48 | LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); | ^^^^^^^^^^^^^^^^^^^^^^ -error[E0631]: type mismatch in closure arguments - --> $DIR/expect-fn-supply-fn.rs:30:5 +error[E0308]: mismatched types + --> $DIR/expect-fn-supply-fn.rs:32:52 | -LL | fn with_closure_expecting_fn_with_free_region(_: F) - | ------------------------------------------ required by a bound in this -LL | where F: for<'a> FnOnce(fn(&'a u32), &i32) - | ------------------------- required by this bound in `with_closure_expecting_fn_with_free_region` -... LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _` - | | - | expected signature of `fn(fn(&'a u32), &i32) -> _` + | ^^^^^^^^ one type is more general than the other + | + = note: expected fn pointer `fn(&u32)` + found fn pointer `for<'r> fn(&'r u32)` -error[E0631]: type mismatch in closure arguments - --> $DIR/expect-fn-supply-fn.rs:37:5 +error[E0308]: mismatched types + --> $DIR/expect-fn-supply-fn.rs:39:53 | -LL | fn with_closure_expecting_fn_with_bound_region(_: F) - | ------------------------------------------- required by a bound in this -LL | where F: FnOnce(fn(&u32), &i32) - | ---------------------- required by this bound in `with_closure_expecting_fn_with_bound_region` -... LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _` - | | - | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` + | ^^^^^^^^^^^ one type is more general than the other + | + = note: expected fn pointer `for<'r> fn(&'r u32)` + found fn pointer `fn(&'x u32)` -error[E0631]: type mismatch in closure arguments - --> $DIR/expect-fn-supply-fn.rs:46:5 +error[E0308]: mismatched types + --> $DIR/expect-fn-supply-fn.rs:48:53 | -LL | fn with_closure_expecting_fn_with_bound_region(_: F) - | ------------------------------------------- required by a bound in this -LL | where F: FnOnce(fn(&u32), &i32) - | ---------------------- required by this bound in `with_closure_expecting_fn_with_bound_region` -... LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- found signature of `for<'r> fn(fn(&'r u32), _) -> _` - | | - | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` + | ^^^^^^^ one type is more general than the other + | + = note: expected fn pointer `for<'r> fn(&'r u32)` + found fn pointer `fn(&u32)` error: aborting due to 5 previous errors -Some errors have detailed explanations: E0308, E0631. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr b/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr index 2005bd4dd5ca7..0c6d11cd3211d 100644 --- a/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr +++ b/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr @@ -1,8 +1,8 @@ error[E0282]: type annotations needed - --> $DIR/expect-two-infer-vars-supply-ty-with-bound-region.rs:8:27 + --> $DIR/expect-two-infer-vars-supply-ty-with-bound-region.rs:8:5 | LL | with_closure(|x: u32, y| {}); - | ^ consider giving this closure parameter a type + | ^^^^^^^^^^^^ cannot infer type for type parameter `B` declared on the function `with_closure` error: aborting due to previous error diff --git a/src/test/ui/closure_context/issue-42065.stderr b/src/test/ui/closure_context/issue-42065.stderr index 896bb6dc6bee8..69d98654048cb 100644 --- a/src/test/ui/closure_context/issue-42065.stderr +++ b/src/test/ui/closure_context/issue-42065.stderr @@ -2,7 +2,7 @@ error[E0382]: use of moved value: `debug_dump_dict` --> $DIR/issue-42065.rs:11:5 | LL | debug_dump_dict(); - | ----------------- `debug_dump_dict` moved due to this call + | --------------- value moved here LL | debug_dump_dict(); | ^^^^^^^^^^^^^^^ value used here after move | @@ -11,11 +11,6 @@ note: closure cannot be invoked more than once because it moves the variable `di | LL | for (key, value) in dict { | ^^^^ -note: this value implements `FnOnce`, which causes it to be moved when called - --> $DIR/issue-42065.rs:10:5 - | -LL | debug_dump_dict(); - | ^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/closures/issue-41366.rs b/src/test/ui/closures/issue-41366.rs index 5cae0e76d1acb..af1e37ba867de 100644 --- a/src/test/ui/closures/issue-41366.rs +++ b/src/test/ui/closures/issue-41366.rs @@ -7,7 +7,6 @@ impl<'g> T<'g> for u32 { } fn main() { - (&|_|()) as &dyn for<'x> Fn(>::V); + (&|_| ()) as &dyn for<'x> Fn(>::V); //~^ ERROR: type mismatch in closure arguments - //~| ERROR: type mismatch resolving } diff --git a/src/test/ui/closures/issue-41366.stderr b/src/test/ui/closures/issue-41366.stderr index 2f2871e9f0e90..9c4b7d529ef4d 100644 --- a/src/test/ui/closures/issue-41366.stderr +++ b/src/test/ui/closures/issue-41366.stderr @@ -1,23 +1,14 @@ error[E0631]: type mismatch in closure arguments --> $DIR/issue-41366.rs:10:5 | -LL | (&|_|()) as &dyn for<'x> Fn(>::V); - | ^^-----^ +LL | (&|_| ()) as &dyn for<'x> Fn(>::V); + | ^^------^ | | | - | | found signature of `fn(_) -> _` - | expected signature of `for<'x> fn(>::V) -> _` + | | found signature of `fn(u16) -> _` + | expected signature of `fn(>::V) -> _` | = note: required for the cast to the object type `dyn for<'x> std::ops::Fn(>::V)` -error[E0271]: type mismatch resolving `for<'x> <[closure@$DIR/issue-41366.rs:10:7: 10:12] as std::ops::FnOnce<(>::V,)>>::Output == ()` - --> $DIR/issue-41366.rs:10:5 - | -LL | (&|_|()) as &dyn for<'x> Fn(>::V); - | ^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime - | - = note: required for the cast to the object type `dyn for<'x> std::ops::Fn(>::V)` - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0271, E0631. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/codemap_tests/tab_2.stderr b/src/test/ui/codemap_tests/tab_2.stderr index 70414bbd953d6..0bfdc3ac2651d 100644 --- a/src/test/ui/codemap_tests/tab_2.stderr +++ b/src/test/ui/codemap_tests/tab_2.stderr @@ -1,4 +1,4 @@ -error: unterminated double quote string +error[E0765]: unterminated double quote string --> $DIR/tab_2.rs:4:7 | LL | """; @@ -8,3 +8,4 @@ LL | | } error: aborting due to previous error +For more information about this error, try `rustc --explain E0765`. diff --git a/src/test/ui/codemap_tests/tab_3.stderr b/src/test/ui/codemap_tests/tab_3.stderr index 614e69e89f6ec..97816a76004d0 100644 --- a/src/test/ui/codemap_tests/tab_3.stderr +++ b/src/test/ui/codemap_tests/tab_3.stderr @@ -4,16 +4,10 @@ error[E0382]: borrow of moved value: `some_vec` LL | let some_vec = vec!["hi"]; | -------- move occurs because `some_vec` has type `std::vec::Vec<&str>`, which does not implement the `Copy` trait LL | some_vec.into_iter(); - | ----------- `some_vec` moved due to this method call + | -------- value moved here LL | { LL | println!("{:?}", some_vec); | ^^^^^^^^ value borrowed here after move - | -note: this function consumes the receiver `self` by taking ownership of it, which moves `some_vec` - --> $SRC_DIR/libcore/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/coerce/coerce-overloaded-autoderef.rs b/src/test/ui/coerce/coerce-overloaded-autoderef.rs deleted file mode 100644 index d5484607c8b52..0000000000000 --- a/src/test/ui/coerce/coerce-overloaded-autoderef.rs +++ /dev/null @@ -1,68 +0,0 @@ -// run-pass -#![allow(unused_braces)] -#![allow(dead_code)] -// pretty-expanded FIXME #23616 - -use std::rc::Rc; - -// Examples from the "deref coercions" RFC, at rust-lang/rfcs#241. - -fn use_ref(_: &T) {} -fn use_mut(_: &mut T) {} - -fn use_rc(t: Rc) { - use_ref(&*t); // what you have to write today - use_ref(&t); // what you'd be able to write - use_ref(&&&&&&t); - use_ref(&mut &&&&&t); - use_ref(&&&mut &&&t); -} - -fn use_mut_box(mut t: &mut Box) { - use_mut(&mut *t); // what you have to write today - use_mut(t); // what you'd be able to write - use_mut(&mut &mut &mut t); - - use_ref(&*t); // what you have to write today - use_ref(t); // what you'd be able to write - use_ref(&&&&&&t); - use_ref(&mut &&&&&t); - use_ref(&&&mut &&&t); -} - -fn use_nested(t: &Box) { - use_ref(&**t); // what you have to write today - use_ref(t); // what you'd be able to write (note: recursive deref) - use_ref(&&&&&&t); - use_ref(&mut &&&&&t); - use_ref(&&&mut &&&t); -} - -fn use_slice(_: &[u8]) {} -fn use_slice_mut(_: &mut [u8]) {} - -fn use_vec(mut v: Vec) { - use_slice_mut(&mut v[..]); // what you have to write today - use_slice_mut(&mut v); // what you'd be able to write - use_slice_mut(&mut &mut &mut v); - - use_slice(&v[..]); // what you have to write today - use_slice(&v); // what you'd be able to write - use_slice(&&&&&&v); - use_slice(&mut &&&&&v); - use_slice(&&&mut &&&v); -} - -fn use_vec_ref(v: &Vec) { - use_slice(&v[..]); // what you have to write today - use_slice(v); // what you'd be able to write - use_slice(&&&&&&v); - use_slice(&mut &&&&&v); - use_slice(&&&mut &&&v); -} - -fn use_op_rhs(s: &mut String) { - *s += {&String::from(" ")}; -} - -pub fn main() {} diff --git a/src/test/ui/coerce/coerce-expect-unsized.rs b/src/test/ui/coercion/coerce-expect-unsized.rs similarity index 100% rename from src/test/ui/coerce/coerce-expect-unsized.rs rename to src/test/ui/coercion/coerce-expect-unsized.rs diff --git a/src/test/ui/coercion/coerce-overloaded-autoderef-fail.rs b/src/test/ui/coercion/coerce-overloaded-autoderef-fail.rs new file mode 100644 index 0000000000000..01d9c1e486a42 --- /dev/null +++ b/src/test/ui/coercion/coerce-overloaded-autoderef-fail.rs @@ -0,0 +1,32 @@ +fn borrow_mut(x: &mut T) -> &mut T { x } +fn borrow(x: &T) -> &T { x } + +fn borrow_mut2(_: &mut T, _: &mut T) {} +fn borrow2(_: &mut T, _: &T) {} + +fn double_mut_borrow(x: &mut Box) { + let y = borrow_mut(x); + let z = borrow_mut(x); + //~^ ERROR cannot borrow `*x` as mutable more than once at a time + drop((y, z)); +} + +fn double_imm_borrow(x: &mut Box) { + let y = borrow(x); + let z = borrow(x); + **x += 1; + //~^ ERROR cannot assign to `**x` because it is borrowed + drop((y, z)); +} + +fn double_mut_borrow2(x: &mut Box) { + borrow_mut2(x, x); + //~^ ERROR cannot borrow `*x` as mutable more than once at a time +} + +fn double_borrow2(x: &mut Box) { + borrow2(x, x); + //~^ ERROR cannot borrow `*x` as mutable because it is also borrowed as immutable +} + +pub fn main() {} diff --git a/src/test/ui/coercion/coerce-overloaded-autoderef.stderr b/src/test/ui/coercion/coerce-overloaded-autoderef-fail.stderr similarity index 87% rename from src/test/ui/coercion/coerce-overloaded-autoderef.stderr rename to src/test/ui/coercion/coerce-overloaded-autoderef-fail.stderr index 7cdfcb5f4fc63..d067c3b3a1805 100644 --- a/src/test/ui/coercion/coerce-overloaded-autoderef.stderr +++ b/src/test/ui/coercion/coerce-overloaded-autoderef-fail.stderr @@ -1,5 +1,5 @@ error[E0499]: cannot borrow `*x` as mutable more than once at a time - --> $DIR/coerce-overloaded-autoderef.rs:9:24 + --> $DIR/coerce-overloaded-autoderef-fail.rs:9:24 | LL | let y = borrow_mut(x); | - first mutable borrow occurs here @@ -10,7 +10,7 @@ LL | drop((y, z)); | - first borrow later used here error[E0506]: cannot assign to `**x` because it is borrowed - --> $DIR/coerce-overloaded-autoderef.rs:17:5 + --> $DIR/coerce-overloaded-autoderef-fail.rs:17:5 | LL | let y = borrow(x); | - borrow of `**x` occurs here @@ -22,7 +22,7 @@ LL | drop((y, z)); | - borrow later used here error[E0499]: cannot borrow `*x` as mutable more than once at a time - --> $DIR/coerce-overloaded-autoderef.rs:23:20 + --> $DIR/coerce-overloaded-autoderef-fail.rs:23:20 | LL | borrow_mut2(x, x); | ----------- - ^ second mutable borrow occurs here @@ -31,7 +31,7 @@ LL | borrow_mut2(x, x); | first borrow later used by call error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable - --> $DIR/coerce-overloaded-autoderef.rs:28:5 + --> $DIR/coerce-overloaded-autoderef-fail.rs:28:5 | LL | borrow2(x, x); | -------^^^^-^ diff --git a/src/test/ui/coercion/coerce-overloaded-autoderef.rs b/src/test/ui/coercion/coerce-overloaded-autoderef.rs index 01d9c1e486a42..d5484607c8b52 100644 --- a/src/test/ui/coercion/coerce-overloaded-autoderef.rs +++ b/src/test/ui/coercion/coerce-overloaded-autoderef.rs @@ -1,32 +1,68 @@ -fn borrow_mut(x: &mut T) -> &mut T { x } -fn borrow(x: &T) -> &T { x } +// run-pass +#![allow(unused_braces)] +#![allow(dead_code)] +// pretty-expanded FIXME #23616 -fn borrow_mut2(_: &mut T, _: &mut T) {} -fn borrow2(_: &mut T, _: &T) {} +use std::rc::Rc; -fn double_mut_borrow(x: &mut Box) { - let y = borrow_mut(x); - let z = borrow_mut(x); - //~^ ERROR cannot borrow `*x` as mutable more than once at a time - drop((y, z)); +// Examples from the "deref coercions" RFC, at rust-lang/rfcs#241. + +fn use_ref(_: &T) {} +fn use_mut(_: &mut T) {} + +fn use_rc(t: Rc) { + use_ref(&*t); // what you have to write today + use_ref(&t); // what you'd be able to write + use_ref(&&&&&&t); + use_ref(&mut &&&&&t); + use_ref(&&&mut &&&t); +} + +fn use_mut_box(mut t: &mut Box) { + use_mut(&mut *t); // what you have to write today + use_mut(t); // what you'd be able to write + use_mut(&mut &mut &mut t); + + use_ref(&*t); // what you have to write today + use_ref(t); // what you'd be able to write + use_ref(&&&&&&t); + use_ref(&mut &&&&&t); + use_ref(&&&mut &&&t); } -fn double_imm_borrow(x: &mut Box) { - let y = borrow(x); - let z = borrow(x); - **x += 1; - //~^ ERROR cannot assign to `**x` because it is borrowed - drop((y, z)); +fn use_nested(t: &Box) { + use_ref(&**t); // what you have to write today + use_ref(t); // what you'd be able to write (note: recursive deref) + use_ref(&&&&&&t); + use_ref(&mut &&&&&t); + use_ref(&&&mut &&&t); +} + +fn use_slice(_: &[u8]) {} +fn use_slice_mut(_: &mut [u8]) {} + +fn use_vec(mut v: Vec) { + use_slice_mut(&mut v[..]); // what you have to write today + use_slice_mut(&mut v); // what you'd be able to write + use_slice_mut(&mut &mut &mut v); + + use_slice(&v[..]); // what you have to write today + use_slice(&v); // what you'd be able to write + use_slice(&&&&&&v); + use_slice(&mut &&&&&v); + use_slice(&&&mut &&&v); } -fn double_mut_borrow2(x: &mut Box) { - borrow_mut2(x, x); - //~^ ERROR cannot borrow `*x` as mutable more than once at a time +fn use_vec_ref(v: &Vec) { + use_slice(&v[..]); // what you have to write today + use_slice(v); // what you'd be able to write + use_slice(&&&&&&v); + use_slice(&mut &&&&&v); + use_slice(&&&mut &&&v); } -fn double_borrow2(x: &mut Box) { - borrow2(x, x); - //~^ ERROR cannot borrow `*x` as mutable because it is also borrowed as immutable +fn use_op_rhs(s: &mut String) { + *s += {&String::from(" ")}; } pub fn main() {} diff --git a/src/test/ui/coerce/coerce-reborrow-imm-ptr-arg.rs b/src/test/ui/coercion/coerce-reborrow-imm-ptr-arg.rs similarity index 100% rename from src/test/ui/coerce/coerce-reborrow-imm-ptr-arg.rs rename to src/test/ui/coercion/coerce-reborrow-imm-ptr-arg.rs diff --git a/src/test/ui/coerce/coerce-reborrow-imm-ptr-rcvr.rs b/src/test/ui/coercion/coerce-reborrow-imm-ptr-rcvr.rs similarity index 100% rename from src/test/ui/coerce/coerce-reborrow-imm-ptr-rcvr.rs rename to src/test/ui/coercion/coerce-reborrow-imm-ptr-rcvr.rs diff --git a/src/test/ui/coerce/coerce-reborrow-imm-vec-arg.rs b/src/test/ui/coercion/coerce-reborrow-imm-vec-arg.rs similarity index 100% rename from src/test/ui/coerce/coerce-reborrow-imm-vec-arg.rs rename to src/test/ui/coercion/coerce-reborrow-imm-vec-arg.rs diff --git a/src/test/ui/coerce/coerce-reborrow-imm-vec-rcvr.rs b/src/test/ui/coercion/coerce-reborrow-imm-vec-rcvr.rs similarity index 100% rename from src/test/ui/coerce/coerce-reborrow-imm-vec-rcvr.rs rename to src/test/ui/coercion/coerce-reborrow-imm-vec-rcvr.rs diff --git a/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.rs b/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.rs new file mode 100644 index 0000000000000..48be2d3146b81 --- /dev/null +++ b/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.rs @@ -0,0 +1,6 @@ +fn test(_a: T, _b: T) {} + +fn main() { + test(&mut 7, &7); + //~^ mismatched types +} diff --git a/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.stderr b/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.stderr new file mode 100644 index 0000000000000..59b0ec496f16f --- /dev/null +++ b/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/coerce-reborrow-multi-arg-fail.rs:4:18 + | +LL | test(&mut 7, &7); + | ^^ types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&{integer}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/coercion/coerce-reborrow-multi-arg.rs b/src/test/ui/coercion/coerce-reborrow-multi-arg.rs new file mode 100644 index 0000000000000..93cd0bb3e27f6 --- /dev/null +++ b/src/test/ui/coercion/coerce-reborrow-multi-arg.rs @@ -0,0 +1,9 @@ +// build-pass +fn test(_a: T, _b: T) {} + +fn main() { + test(&7, &7); + test(&7, &mut 7); + test::<&i32>(&mut 7, &7); + test::<&i32>(&mut 7, &mut 7); +} diff --git a/src/test/ui/coerce/coerce-reborrow-mut-ptr-arg.rs b/src/test/ui/coercion/coerce-reborrow-mut-ptr-arg.rs similarity index 100% rename from src/test/ui/coerce/coerce-reborrow-mut-ptr-arg.rs rename to src/test/ui/coercion/coerce-reborrow-mut-ptr-arg.rs diff --git a/src/test/ui/coerce/coerce-reborrow-mut-ptr-rcvr.rs b/src/test/ui/coercion/coerce-reborrow-mut-ptr-rcvr.rs similarity index 100% rename from src/test/ui/coerce/coerce-reborrow-mut-ptr-rcvr.rs rename to src/test/ui/coercion/coerce-reborrow-mut-ptr-rcvr.rs diff --git a/src/test/ui/coerce/coerce-reborrow-mut-vec-arg.rs b/src/test/ui/coercion/coerce-reborrow-mut-vec-arg.rs similarity index 100% rename from src/test/ui/coerce/coerce-reborrow-mut-vec-arg.rs rename to src/test/ui/coercion/coerce-reborrow-mut-vec-arg.rs diff --git a/src/test/ui/coerce/coerce-reborrow-mut-vec-rcvr.rs b/src/test/ui/coercion/coerce-reborrow-mut-vec-rcvr.rs similarity index 100% rename from src/test/ui/coerce/coerce-reborrow-mut-vec-rcvr.rs rename to src/test/ui/coercion/coerce-reborrow-mut-vec-rcvr.rs diff --git a/src/test/ui/coercion/coerce-to-bang-cast.rs b/src/test/ui/coercion/coerce-to-bang-cast.rs index 8ef1948084654..85598a42eccd9 100644 --- a/src/test/ui/coercion/coerce-to-bang-cast.rs +++ b/src/test/ui/coercion/coerce-to-bang-cast.rs @@ -1,7 +1,5 @@ #![feature(never_type)] -fn foo(x: usize, y: !, z: usize) { } - fn cast_a() { let y = {return; 22} as !; //~^ ERROR non-primitive cast diff --git a/src/test/ui/coercion/coerce-to-bang-cast.stderr b/src/test/ui/coercion/coerce-to-bang-cast.stderr index d3adbd5158dbb..50e009aa25bb1 100644 --- a/src/test/ui/coercion/coerce-to-bang-cast.stderr +++ b/src/test/ui/coercion/coerce-to-bang-cast.stderr @@ -1,11 +1,11 @@ error[E0605]: non-primitive cast: `i32` as `!` - --> $DIR/coerce-to-bang-cast.rs:6:13 + --> $DIR/coerce-to-bang-cast.rs:4:13 | LL | let y = {return; 22} as !; | ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object error[E0605]: non-primitive cast: `i32` as `!` - --> $DIR/coerce-to-bang-cast.rs:11:13 + --> $DIR/coerce-to-bang-cast.rs:9:13 | LL | let y = 22 as !; | ^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object diff --git a/src/test/ui/coerce/coerce-unify-return.rs b/src/test/ui/coercion/coerce-unify-return.rs similarity index 100% rename from src/test/ui/coerce/coerce-unify-return.rs rename to src/test/ui/coercion/coerce-unify-return.rs diff --git a/src/test/ui/coerce/coerce-unify.rs b/src/test/ui/coercion/coerce-unify.rs similarity index 100% rename from src/test/ui/coerce/coerce-unify.rs rename to src/test/ui/coercion/coerce-unify.rs diff --git a/src/test/ui/coerce/coerce-unsize-subtype.rs b/src/test/ui/coercion/coerce-unsize-subtype.rs similarity index 100% rename from src/test/ui/coerce/coerce-unsize-subtype.rs rename to src/test/ui/coercion/coerce-unsize-subtype.rs diff --git a/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.rs b/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.rs new file mode 100644 index 0000000000000..99f805f7f0f63 --- /dev/null +++ b/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.rs @@ -0,0 +1,26 @@ +// Test that impls for these two types are considered ovelapping: +// +// * `for<'r> fn(fn(&'r u32))` +// * `fn(fn(&'a u32)` where `'a` is free +// +// This is because, for `'a = 'static`, the two types overlap. +// Effectively for them to be equal to you get: +// +// * `for<'r> fn(fn(&'r u32)) <: fn(fn(&'static u32))` +// * true if `exists<'r> { 'r: 'static }` (obviously true) +// * `fn(fn(&'static u32)) <: for<'r> fn(fn(&'r u32))` +// * true if `forall<'r> { 'static: 'r }` (also true) + +trait Trait {} + +impl Trait for for<'r> fn(fn(&'r ())) {} +impl<'a> Trait for fn(fn(&'a ())) {} +//~^ ERROR conflicting implementations +// +// Note in particular that we do NOT get a future-compatibility warning +// here. This is because the new leak-check proposed in [MCP 295] does not +// "error" when these two types are equated. +// +// [MCP 295]: https://github.com/rust-lang/compiler-team/issues/295 + +fn main() {} diff --git a/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr b/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr new file mode 100644 index 0000000000000..49271edf8e5e4 --- /dev/null +++ b/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `Trait` for type `for<'r> fn(fn(&'r ()))`: + --> $DIR/coherence-fn-covariant-bound-vs-static.rs:17:1 + | +LL | impl Trait for for<'r> fn(fn(&'r ())) {} + | ------------------------------------- first implementation here +LL | impl<'a> Trait for fn(fn(&'a ())) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'r> fn(fn(&'r ()))` + | + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/coherence/coherence-fn-implied-bounds.rs b/src/test/ui/coherence/coherence-fn-implied-bounds.rs new file mode 100644 index 0000000000000..4539af9a32e38 --- /dev/null +++ b/src/test/ui/coherence/coherence-fn-implied-bounds.rs @@ -0,0 +1,26 @@ +// Test that our leak-check is not smart enough to take implied bounds +// into account (yet). Here we have two types that look like they +// should not be equivalent, but because of the rules on implied +// bounds we ought to know that, in fact, `'a = 'b` must always hold, +// and hence they are. +// +// Rustc can't figure this out and hence it accepts the impls but +// gives a future-compatibility warning (because we'd like to make +// this an error someday). +// +// Note that while we would like to make this a hard error, we also +// give the same warning for `coherence-wasm-bindgen.rs`, which ought +// to be accepted. + +#![deny(coherence_leak_check)] + +trait Trait {} + +impl Trait for for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32 {} + +impl Trait for for<'c> fn(&'c &'c u32, &'c &'c u32) -> &'c u32 { + //~^ ERROR conflicting implementations + //~| WARNING this was previously accepted by the compiler +} + +fn main() {} diff --git a/src/test/ui/coherence/coherence-fn-implied-bounds.stderr b/src/test/ui/coherence/coherence-fn-implied-bounds.stderr new file mode 100644 index 0000000000000..a3e7f0bcde376 --- /dev/null +++ b/src/test/ui/coherence/coherence-fn-implied-bounds.stderr @@ -0,0 +1,20 @@ +error: conflicting implementations of trait `Trait` for type `for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32`: + --> $DIR/coherence-fn-implied-bounds.rs:21:1 + | +LL | impl Trait for for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32 {} + | ------------------------------------------------------------------ first implementation here +LL | +LL | impl Trait for for<'c> fn(&'c &'c u32, &'c &'c u32) -> &'c u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32` + | +note: the lint level is defined here + --> $DIR/coherence-fn-implied-bounds.rs:15:9 + | +LL | #![deny(coherence_leak_check)] + | ^^^^^^^^^^^^^^^^^^^^ + = 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 #56105 + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + +error: aborting due to previous error + diff --git a/src/test/ui/coherence/coherence-fn-inputs.rs b/src/test/ui/coherence/coherence-fn-inputs.rs new file mode 100644 index 0000000000000..3afec5c5459af --- /dev/null +++ b/src/test/ui/coherence/coherence-fn-inputs.rs @@ -0,0 +1,25 @@ +// Test that we consider these two types completely equal: +// +// * `for<'a, 'b> fn(&'a u32, &'b u32)` +// * `for<'c> fn(&'c u32, &'c u32)` +// +// For a long time we considered these to be distinct types. But in fact they +// are equivalent, if you work through the implications of subtyping -- this is +// because: +// +// * `'c` can be the intersection of `'a` and `'b` (and there is always an intersection) +// * `'a` and `'b` can both be equal to `'c` + +trait Trait {} +impl Trait for for<'a, 'b> fn(&'a u32, &'b u32) {} +impl Trait for for<'c> fn(&'c u32, &'c u32) { + //~^ ERROR conflicting implementations + // + // Note in particular that we do NOT get a future-compatibility warning + // here. This is because the new leak-check proposed in [MCP 295] does not + // "error" when these two types are equated. + // + // [MCP 295]: https://github.com/rust-lang/compiler-team/issues/295 +} + +fn main() {} diff --git a/src/test/ui/coherence/coherence-fn-inputs.stderr b/src/test/ui/coherence/coherence-fn-inputs.stderr new file mode 100644 index 0000000000000..56ab873a39320 --- /dev/null +++ b/src/test/ui/coherence/coherence-fn-inputs.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `Trait` for type `for<'a, 'b> fn(&'a u32, &'b u32)`: + --> $DIR/coherence-fn-inputs.rs:15:1 + | +LL | impl Trait for for<'a, 'b> fn(&'a u32, &'b u32) {} + | ----------------------------------------------- first implementation here +LL | impl Trait for for<'c> fn(&'c u32, &'c u32) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u32, &'b u32)` + | + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/coherence/coherence-free-vs-bound-region.rs b/src/test/ui/coherence/coherence-free-vs-bound-region.rs new file mode 100644 index 0000000000000..2f5c49d293d5d --- /dev/null +++ b/src/test/ui/coherence/coherence-free-vs-bound-region.rs @@ -0,0 +1,21 @@ +// Capture a coherence pattern from wasm-bindgen that we discovered as part of +// future-compatibility warning #56105. This pattern currently receives a lint +// warning but we probably want to support it long term. +// +// Key distinction: we are implementing once for `A` (take ownership) and one +// for `&A` (borrow). +// +// c.f. #56105 + +#![deny(coherence_leak_check)] + +trait TheTrait {} + +impl<'a> TheTrait for fn(&'a u8) {} + +impl TheTrait for fn(&u8) { + //~^ ERROR conflicting implementations of trait + //~| WARNING this was previously accepted by the compiler +} + +fn main() {} diff --git a/src/test/ui/coherence/coherence-free-vs-bound-region.stderr b/src/test/ui/coherence/coherence-free-vs-bound-region.stderr new file mode 100644 index 0000000000000..97aa491272143 --- /dev/null +++ b/src/test/ui/coherence/coherence-free-vs-bound-region.stderr @@ -0,0 +1,20 @@ +error: conflicting implementations of trait `TheTrait` for type `fn(&u8)`: + --> $DIR/coherence-free-vs-bound-region.rs:16:1 + | +LL | impl<'a> TheTrait for fn(&'a u8) {} + | -------------------------------- first implementation here +LL | +LL | impl TheTrait for fn(&u8) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `fn(&u8)` + | +note: the lint level is defined here + --> $DIR/coherence-free-vs-bound-region.rs:10:9 + | +LL | #![deny(coherence_leak_check)] + | ^^^^^^^^^^^^^^^^^^^^ + = 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 #56105 + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + +error: aborting due to previous error + diff --git a/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.rs b/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.rs index 7f0e5472c3c2e..d74d3a2a52351 100644 --- a/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.rs +++ b/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.rs @@ -4,6 +4,7 @@ // // No we expect to run into a more user-friendly cycle error instead. #![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete trait Trait { type Assoc; } //~^ ERROR E0391 diff --git a/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr b/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr index 71f997c54c6f2..7e140480b77d4 100644 --- a/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr +++ b/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr @@ -1,16 +1,25 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:6:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + error[E0391]: cycle detected when building specialization graph of trait `Trait` - --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:8:1 + --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:9:1 | LL | trait Trait { type Assoc; } | ^^^^^^^^^^^^^^ | = note: ...which again requires building specialization graph of trait `Trait`, completing the cycle note: cycle used when coherence checking all impls of trait `Trait` - --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:8:1 + --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:9:1 | LL | trait Trait { type Assoc; } | ^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/coherence/coherence-subtyping.old.stderr b/src/test/ui/coherence/coherence-subtyping.old.stderr deleted file mode 100644 index b3c2f4516349e..0000000000000 --- a/src/test/ui/coherence/coherence-subtyping.old.stderr +++ /dev/null @@ -1,16 +0,0 @@ -warning: conflicting implementations of trait `TheTrait` for type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`: - --> $DIR/coherence-subtyping.rs:16:1 - | -LL | impl TheTrait for for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8 {} - | ---------------------------------------------------------- first implementation here -LL | -LL | impl TheTrait for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` - | - = note: `#[warn(coherence_leak_check)]` 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 #56105 - = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details - -warning: 1 warning emitted - diff --git a/src/test/ui/coherence/coherence-subtyping.rs b/src/test/ui/coherence/coherence-subtyping.rs index f5c1d92411baa..b3ed728a81c06 100644 --- a/src/test/ui/coherence/coherence-subtyping.rs +++ b/src/test/ui/coherence/coherence-subtyping.rs @@ -4,7 +4,6 @@ // Note: This scenario is currently accepted, but as part of the // universe transition (#56105) may eventually become an error. -// revisions: old re // check-pass trait TheTrait { @@ -14,10 +13,8 @@ trait TheTrait { impl TheTrait for for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8 {} impl TheTrait for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { - //[re]~^ WARNING conflicting implementation - //[re]~^^ WARNING this was previously accepted by the compiler but is being phased out - //[old]~^^^ WARNING conflicting implementation - //[old]~^^^^ WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING conflicting implementation + //~^^ WARNING this was previously accepted by the compiler but is being phased out } fn main() {} diff --git a/src/test/ui/coherence/coherence-subtyping.re.stderr b/src/test/ui/coherence/coherence-subtyping.stderr similarity index 95% rename from src/test/ui/coherence/coherence-subtyping.re.stderr rename to src/test/ui/coherence/coherence-subtyping.stderr index b3c2f4516349e..7f751a24c75c9 100644 --- a/src/test/ui/coherence/coherence-subtyping.re.stderr +++ b/src/test/ui/coherence/coherence-subtyping.stderr @@ -1,5 +1,5 @@ warning: conflicting implementations of trait `TheTrait` for type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`: - --> $DIR/coherence-subtyping.rs:16:1 + --> $DIR/coherence-subtyping.rs:15:1 | LL | impl TheTrait for for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8 {} | ---------------------------------------------------------- first implementation here diff --git a/src/test/ui/coherence/coherence-wasm-bindgen.rs b/src/test/ui/coherence/coherence-wasm-bindgen.rs new file mode 100644 index 0000000000000..ee09a72449be1 --- /dev/null +++ b/src/test/ui/coherence/coherence-wasm-bindgen.rs @@ -0,0 +1,37 @@ +// Capture a coherence pattern from wasm-bindgen that we discovered as part of +// future-compatibility warning #56105. This pattern currently receives a lint +// warning but we probably want to support it long term. +// +// Key distinction: we are implementing once for `A` (take ownership) and one +// for `&A` (borrow). +// +// c.f. #56105 + +#![deny(coherence_leak_check)] + +trait IntoWasmAbi { + fn some_method(&self) {} +} + +trait FromWasmAbi {} +trait RefFromWasmAbi {} +trait ReturnWasmAbi {} + +impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn Fn(A) -> R + 'b) +where + A: FromWasmAbi, + R: ReturnWasmAbi, +{ +} + +// Explicitly writing the bound lifetime. +impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn for<'x> Fn(&'x A) -> R + 'b) +where + A: RefFromWasmAbi, + R: ReturnWasmAbi, +{ + //~^^^^^ ERROR conflicting implementation + //~| WARNING this was previously accepted +} + +fn main() {} diff --git a/src/test/ui/coherence/coherence-wasm-bindgen.stderr b/src/test/ui/coherence/coherence-wasm-bindgen.stderr new file mode 100644 index 0000000000000..c77483bb847f5 --- /dev/null +++ b/src/test/ui/coherence/coherence-wasm-bindgen.stderr @@ -0,0 +1,32 @@ +error: conflicting implementations of trait `IntoWasmAbi` for type `&dyn std::ops::Fn(&_) -> _`: + --> $DIR/coherence-wasm-bindgen.rs:28:1 + | +LL | / impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn Fn(A) -> R + 'b) +LL | | where +LL | | A: FromWasmAbi, +LL | | R: ReturnWasmAbi, +LL | | { +LL | | } + | |_- first implementation here +... +LL | / impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn for<'x> Fn(&'x A) -> R + 'b) +LL | | where +LL | | A: RefFromWasmAbi, +LL | | R: ReturnWasmAbi, +... | +LL | | +LL | | } + | |_^ conflicting implementation for `&dyn std::ops::Fn(&_) -> _` + | +note: the lint level is defined here + --> $DIR/coherence-wasm-bindgen.rs:10:9 + | +LL | #![deny(coherence_leak_check)] + | ^^^^^^^^^^^^^^^^^^^^ + = 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 #56105 + = note: downstream crates may implement trait `FromWasmAbi` for type `&_` + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/auxiliary/impl-const.rs b/src/test/ui/const-generics/auxiliary/impl-const.rs new file mode 100644 index 0000000000000..fc993d63927c3 --- /dev/null +++ b/src/test/ui/const-generics/auxiliary/impl-const.rs @@ -0,0 +1,9 @@ +#![feature(const_generics)] + +pub struct Num; + +// Braces around const expression causes crash +impl Num<{5}> { + pub fn five(&self) { + } +} diff --git a/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr b/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr index ad38b632b75f0..4a6241de1b453 100644 --- a/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr +++ b/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr @@ -14,6 +14,7 @@ LL | fn foo() -> Array { | ^ | = note: type arguments must be provided before constant arguments + = help: reorder the arguments: types, then consts: `` error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/const-generics/fn-const-param-call.rs b/src/test/ui/const-generics/fn-const-param-call.rs index afa577fa67ff2..90c438b05cb81 100644 --- a/src/test/ui/const-generics/fn-const-param-call.rs +++ b/src/test/ui/const-generics/fn-const-param-call.rs @@ -1,15 +1,14 @@ -// run-pass - -#![feature(const_generics, const_compare_raw_pointers)] +#![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete fn function() -> u32 { 17 } -struct Wrapper u32>; +struct Wrapper u32>; //~ ERROR: using function pointers as const generic parameters impl u32> Wrapper { +//~^ ERROR: using function pointers as const generic parameters fn call() -> u32 { F() } diff --git a/src/test/ui/const-generics/fn-const-param-call.stderr b/src/test/ui/const-generics/fn-const-param-call.stderr index 9c0f7e3ab9b87..b5811243caa8a 100644 --- a/src/test/ui/const-generics/fn-const-param-call.stderr +++ b/src/test/ui/const-generics/fn-const-param-call.stderr @@ -1,11 +1,23 @@ warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/fn-const-param-call.rs:3:12 + --> $DIR/fn-const-param-call.rs:1:12 | -LL | #![feature(const_generics, const_compare_raw_pointers)] +LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information -warning: 1 warning emitted +error: using function pointers as const generic parameters is forbidden + --> $DIR/fn-const-param-call.rs:8:25 + | +LL | struct Wrapper u32>; + | ^^^^^^^^^^^ + +error: using function pointers as const generic parameters is forbidden + --> $DIR/fn-const-param-call.rs:10:15 + | +LL | impl u32> Wrapper { + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors; 1 warning emitted diff --git a/src/test/ui/const-generics/fn-const-param-infer.rs b/src/test/ui/const-generics/fn-const-param-infer.rs index 08f6e0db31cae..14fa3b494b3fc 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.rs +++ b/src/test/ui/const-generics/fn-const-param-infer.rs @@ -1,7 +1,8 @@ -#![feature(const_generics, const_compare_raw_pointers)] +#![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete struct Checked bool>; +//~^ ERROR: using function pointers as const generic parameters fn not_one(val: usize) -> bool { val != 1 } fn not_two(val: usize) -> bool { val != 2 } @@ -13,14 +14,14 @@ fn generic(val: usize) -> bool { val != 1 } fn main() { let _: Option> = None; let _: Checked = Checked::; - let _: Checked = Checked::; //~ mismatched types + let _: Checked = Checked::; let _ = Checked::; let _ = Checked::<{generic_arg::}>; - let _ = Checked::<{generic_arg::}>; //~ mismatched types + let _ = Checked::<{generic_arg::}>; - let _ = Checked::; //~ type annotations needed + let _ = Checked::; let _ = Checked::<{generic::}>; let _: Checked<{generic::}> = Checked::<{generic::}>; - let _: Checked<{generic::}> = Checked::<{generic::}>; //~ mismatched types + let _: Checked<{generic::}> = Checked::<{generic::}>; } 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 de41d2984a655..7aaa41eb7d7b1 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.stderr +++ b/src/test/ui/const-generics/fn-const-param-infer.stderr @@ -1,46 +1,17 @@ warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/fn-const-param-infer.rs:1:12 | -LL | #![feature(const_generics, const_compare_raw_pointers)] +LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information -error[E0308]: mismatched types - --> $DIR/fn-const-param-infer.rs:16:31 +error: using function pointers as const generic parameters is forbidden + --> $DIR/fn-const-param-infer.rs:4:25 | -LL | let _: Checked = Checked::; - | ^^^^^^^^^^^^^^^^^^ expected `{not_one as fn(usize) -> bool}`, found `{not_two as fn(usize) -> bool}` - | - = note: expected type `{not_one as fn(usize) -> bool}` - found type `{not_two as fn(usize) -> bool}` - -error[E0308]: mismatched types - --> $DIR/fn-const-param-infer.rs:20:24 - | -LL | let _ = Checked::<{generic_arg::}>; - | ^^^^^^^^^^^^^^^^^^ expected `usize`, found `u32` - | - = note: expected fn pointer `fn(usize) -> _` - found fn item `fn(u32) -> _ {generic_arg::}` - -error[E0282]: type annotations needed - --> $DIR/fn-const-param-infer.rs:22:23 - | -LL | let _ = Checked::; - | ^^^^^^^ cannot infer type for type parameter `T` declared on the function `generic` - -error[E0308]: mismatched types - --> $DIR/fn-const-param-infer.rs:25:40 - | -LL | let _: Checked<{generic::}> = Checked::<{generic::}>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{generic:: as fn(usize) -> bool}`, found `{generic:: as fn(usize) -> bool}` - | - = note: expected type `{generic:: as fn(usize) -> bool}` - found type `{generic:: as fn(usize) -> bool}` +LL | struct Checked bool>; + | ^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors; 1 warning emitted +error: aborting due to previous error; 1 warning emitted -Some errors have detailed explanations: E0282, E0308. -For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/const-generics/issue-68104-print-stack-overflow.rs b/src/test/ui/const-generics/issue-68104-print-stack-overflow.rs new file mode 100644 index 0000000000000..bda9ce8767d08 --- /dev/null +++ b/src/test/ui/const-generics/issue-68104-print-stack-overflow.rs @@ -0,0 +1,14 @@ +// aux-build:impl-const.rs +// run-pass + +#![feature(const_generics)] +#![allow(incomplete_features)] + +extern crate impl_const; + +use impl_const::*; + +pub fn main() { + let n = Num::<5>; + n.five(); +} diff --git a/src/test/ui/const-generics/raw-ptr-const-param-deref.rs b/src/test/ui/const-generics/raw-ptr-const-param-deref.rs index c498bfe2e9781..97ca9d6a44c9e 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param-deref.rs +++ b/src/test/ui/const-generics/raw-ptr-const-param-deref.rs @@ -1,12 +1,11 @@ -// run-pass -#![feature(const_generics, const_compare_raw_pointers)] +#![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete const A: u32 = 3; -struct Const; +struct Const; //~ ERROR: using raw pointers as const generic parameters -impl Const

{ +impl Const

{ //~ ERROR: using raw pointers as const generic parameters fn get() -> u32 { unsafe { *P diff --git a/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr b/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr index 1ffc63ffdac03..1ce8bb9c05423 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr +++ b/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr @@ -1,11 +1,23 @@ warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/raw-ptr-const-param-deref.rs:2:12 + --> $DIR/raw-ptr-const-param-deref.rs:1:12 | -LL | #![feature(const_generics, const_compare_raw_pointers)] +LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information -warning: 1 warning emitted +error: using raw pointers as const generic parameters is forbidden + --> $DIR/raw-ptr-const-param-deref.rs:6:23 + | +LL | struct Const; + | ^^^^^^^^^^ + +error: using raw pointers as const generic parameters is forbidden + --> $DIR/raw-ptr-const-param-deref.rs:8:15 + | +LL | impl Const

{ + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors; 1 warning emitted 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 d7d970e952b65..237b410e073d6 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.rs +++ b/src/test/ui/const-generics/raw-ptr-const-param.rs @@ -1,9 +1,9 @@ -#![feature(const_generics, const_compare_raw_pointers)] +#![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete -struct Const; +struct Const; //~ ERROR: using raw pointers as const generic parameters fn main() { - let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>; //~ mismatched types + let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>; 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 7a665397c1207..6e64f8a327fd5 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.stderr +++ b/src/test/ui/const-generics/raw-ptr-const-param.stderr @@ -1,21 +1,17 @@ warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/raw-ptr-const-param.rs:1:12 | -LL | #![feature(const_generics, const_compare_raw_pointers)] +LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information -error[E0308]: mismatched types - --> $DIR/raw-ptr-const-param.rs:7:40 +error: using raw pointers as const generic parameters is forbidden + --> $DIR/raw-ptr-const-param.rs:4:23 | -LL | let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{0xf as *const u32}`, found `{0xa as *const u32}` - | - = note: expected type `{0xf as *const u32}` - found type `{0xa as *const u32}` +LL | struct Const; + | ^^^^^^^^^^ error: aborting due to previous error; 1 warning emitted -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/consts/const-eval/const_let.stderr b/src/test/ui/consts/const-eval/const_let.stderr index 4753222a7c07d..47f39b703e460 100644 --- a/src/test/ui/consts/const-eval/const_let.stderr +++ b/src/test/ui/consts/const-eval/const_let.stderr @@ -2,25 +2,33 @@ error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/const_let.rs:16:32 | LL | const Y: FakeNeedsDrop = { let mut x = FakeNeedsDrop; x = FakeNeedsDrop; x }; - | ^^^^^ constants cannot evaluate destructors + | ^^^^^ - value is dropped here + | | + | constants cannot evaluate destructors error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/const_let.rs:20:33 | LL | const Y2: FakeNeedsDrop = { let mut x; x = FakeNeedsDrop; x = FakeNeedsDrop; x }; - | ^^^^^ constants cannot evaluate destructors + | ^^^^^ - value is dropped here + | | + | constants cannot evaluate destructors error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/const_let.rs:24:21 | LL | const Z: () = { let mut x = None; x = Some(FakeNeedsDrop); }; - | ^^^^^ constants cannot evaluate destructors + | ^^^^^ - value is dropped here + | | + | constants cannot evaluate destructors error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/const_let.rs:28:22 | LL | const Z2: () = { let mut x; x = None; x = Some(FakeNeedsDrop); }; - | ^^^^^ constants cannot evaluate destructors + | ^^^^^ - value is dropped here + | | + | constants cannot evaluate destructors error: aborting due to 4 previous errors diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs b/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs index 9be1374f85d99..e238e13b8e2da 100644 --- a/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs @@ -1,17 +1,6 @@ -#![feature(const_raw_ptr_to_usize_cast, const_compare_raw_pointers, const_raw_ptr_deref)] - fn main() {} // unconst and bad, will thus error in miri -const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR any use of this -// unconst and bad, will thus error in miri -const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; //~ ERROR any use of this -// unconst and fine -const Y: usize = unsafe { 42usize as *const i32 as usize + 1 }; -// unconst and bad, will thus error in miri -const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; //~ ERROR any use of this -// unconst and fine -const Z: i32 = unsafe { *(&1 as *const i32) }; +const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR cannot be reliably // unconst and bad, will thus error in miri -const Z2: i32 = unsafe { *(42 as *const i32) }; //~ ERROR any use of this value will cause -const Z3: i32 = unsafe { *(44 as *const i32) }; //~ ERROR any use of this value will cause +const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; //~ ERROR cannot be reliably 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 cc40728e6b574..21d3f5e7e8536 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 @@ -1,44 +1,18 @@ -error: any use of this value will cause an error - --> $DIR/const_raw_ptr_ops.rs:6:26 +error: pointers cannot be reliably compared during const eval. + --> $DIR/const_raw_ptr_ops.rs:4:26 | LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; - | -------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | "pointer arithmetic or comparison" needs an rfc before being allowed inside constants + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `#[deny(const_err)]` on by default + = note: see issue #53020 for more information -error: any use of this value will cause an error - --> $DIR/const_raw_ptr_ops.rs:8:27 +error: pointers cannot be reliably compared during const eval. + --> $DIR/const_raw_ptr_ops.rs:6:27 | LL | const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; - | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | "pointer arithmetic or comparison" needs an rfc before being allowed inside constants - -error: any use of this value will cause an error - --> $DIR/const_raw_ptr_ops.rs:12:28 - | -LL | const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; - | ---------------------------^^^^^^^^^^^^^^^^^^^^^^^^^------- - | | - | "pointer-to-integer cast" needs an rfc before being allowed inside constants - -error: any use of this value will cause an error - --> $DIR/const_raw_ptr_ops.rs:16:26 - | -LL | const Z2: i32 = unsafe { *(42 as *const i32) }; - | -------------------------^^^^^^^^^^^^^^^^^^^--- - | | - | 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 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -LL | const Z3: i32 = unsafe { *(44 as *const i32) }; - | -------------------------^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn bytes into a pointer + = note: see issue #53020 for more information -error: aborting due to 5 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs b/src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs new file mode 100644 index 0000000000000..d2a7623837a23 --- /dev/null +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs @@ -0,0 +1,13 @@ +#![feature(const_raw_ptr_to_usize_cast, const_raw_ptr_deref)] + +fn main() {} + +// unconst and fine +const Y: usize = unsafe { 42usize as *const i32 as usize + 1 }; +// unconst and bad, will thus error in miri +const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; //~ ERROR any use of this +// unconst and fine +const Z: i32 = unsafe { *(&1 as *const i32) }; +// unconst and bad, will thus error in miri +const Z2: i32 = unsafe { *(42 as *const i32) }; //~ ERROR any use of this value will cause +const Z3: i32 = unsafe { *(44 as *const i32) }; //~ ERROR any use of this value will cause diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr b/src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr new file mode 100644 index 0000000000000..93f2261745d6f --- /dev/null +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr @@ -0,0 +1,28 @@ +error: any use of this value will cause an error + --> $DIR/const_raw_ptr_ops2.rs:8:28 + | +LL | const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; + | ---------------------------^^^^^^^^^^^^^^^^^^^^^^^^^------- + | | + | "pointer-to-integer cast" needs an rfc before being allowed inside constants + | + = note: `#[deny(const_err)]` on by default + +error: any use of this value will cause an error + --> $DIR/const_raw_ptr_ops2.rs:12:26 + | +LL | const Z2: i32 = unsafe { *(42 as *const i32) }; + | -------------------------^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn bytes into a pointer + +error: any use of this value will cause an error + --> $DIR/const_raw_ptr_ops2.rs:13:26 + | +LL | const Z3: i32 = unsafe { *(44 as *const i32) }; + | -------------------------^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn bytes into a pointer + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/consts/const-eval/issue-65394.rs b/src/test/ui/consts/const-eval/issue-65394.rs index b1c058eac9e4b..2518e4ed40b30 100644 --- a/src/test/ui/consts/const-eval/issue-65394.rs +++ b/src/test/ui/consts/const-eval/issue-65394.rs @@ -5,7 +5,7 @@ const _: Vec = { let mut x = Vec::::new(); //~ ERROR destructors cannot be evaluated at compile-time - let r = &mut x; //~ ERROR references in constants may only refer to immutable values + let r = &mut x; //~ ERROR mutable references are not allowed in constants let y = x; y }; diff --git a/src/test/ui/consts/const-eval/issue-65394.stderr b/src/test/ui/consts/const-eval/issue-65394.stderr index d85a1a1a3c32b..771d368d78391 100644 --- a/src/test/ui/consts/const-eval/issue-65394.stderr +++ b/src/test/ui/consts/const-eval/issue-65394.stderr @@ -1,19 +1,19 @@ -error[E0658]: references in constants may only refer to immutable values +error[E0764]: mutable references are not allowed in constants --> $DIR/issue-65394.rs:8:13 | LL | let r = &mut x; - | ^^^^^^ constants require immutable values - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + | ^^^^^^ `&mut` is only allowed in `const fn` error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/issue-65394.rs:7:9 | LL | let mut x = Vec::::new(); | ^^^^^ constants cannot evaluate destructors +... +LL | }; + | - value is dropped here error: aborting due to 2 previous errors -Some errors have detailed explanations: E0493, E0658. +Some errors have detailed explanations: E0493, E0764. For more information about an error, try `rustc --explain E0493`. diff --git a/src/test/ui/consts/const-eval/livedrop.rs b/src/test/ui/consts/const-eval/livedrop.rs new file mode 100644 index 0000000000000..f00d1c70659fd --- /dev/null +++ b/src/test/ui/consts/const-eval/livedrop.rs @@ -0,0 +1,20 @@ +#![feature(const_if_match)] +#![feature(const_loop)] + +const _: Option> = { + let mut never_returned = Some(Vec::new()); + let mut always_returned = None; //~ ERROR destructors cannot be evaluated at compile-time + + let mut i = 0; + loop { + always_returned = never_returned; + never_returned = None; + + i += 1; + if i == 10 { + break always_returned; + } + } +}; + +fn main() {} diff --git a/src/test/ui/consts/const-eval/livedrop.stderr b/src/test/ui/consts/const-eval/livedrop.stderr new file mode 100644 index 0000000000000..b802d23d9a89c --- /dev/null +++ b/src/test/ui/consts/const-eval/livedrop.stderr @@ -0,0 +1,12 @@ +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/livedrop.rs:6:9 + | +LL | let mut always_returned = None; + | ^^^^^^^^^^^^^^^^^^^ constants cannot evaluate destructors +... +LL | always_returned = never_returned; + | --------------- value is dropped here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0493`. diff --git a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs index c6fb5eeab5aec..d724fe3060b21 100644 --- a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs +++ b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs @@ -1,4 +1,4 @@ -#![feature(const_raw_ptr_to_usize_cast, const_compare_raw_pointers, const_raw_ptr_deref)] +#![feature(const_raw_ptr_to_usize_cast, const_raw_ptr_deref)] fn main() { let x: &'static bool = &(42 as *const i32 == 43 as *const i32); diff --git a/src/test/ui/consts/const-multi-ref.rs b/src/test/ui/consts/const-multi-ref.rs index 5e2be0d4f3f02..18645efc88715 100644 --- a/src/test/ui/consts/const-multi-ref.rs +++ b/src/test/ui/consts/const-multi-ref.rs @@ -3,7 +3,7 @@ const _: i32 = { let mut a = 5; - let p = &mut a; //~ ERROR references in constants may only refer to immutable values + let p = &mut a; //~ ERROR mutable references are not allowed in constants let reborrow = {p}; let pp = &reborrow; diff --git a/src/test/ui/consts/const-multi-ref.stderr b/src/test/ui/consts/const-multi-ref.stderr index e01dd4e574738..9a7914b458874 100644 --- a/src/test/ui/consts/const-multi-ref.stderr +++ b/src/test/ui/consts/const-multi-ref.stderr @@ -1,11 +1,8 @@ -error[E0658]: references in constants may only refer to immutable values +error[E0764]: mutable references are not allowed in constants --> $DIR/const-multi-ref.rs:6:13 | LL | let p = &mut a; - | ^^^^^^ constants require immutable values - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + | ^^^^^^ `&mut` is only allowed in `const fn` error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead --> $DIR/const-multi-ref.rs:16:13 @@ -15,5 +12,5 @@ LL | let p = &a; error: aborting due to 2 previous errors -Some errors have detailed explanations: E0492, E0658. +Some errors have detailed explanations: E0492, E0764. For more information about an error, try `rustc --explain E0492`. diff --git a/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs b/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs index 130ba9283b1d9..5819daa817af0 100644 --- a/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs +++ b/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs @@ -1,5 +1,3 @@ -// check-pass - #![feature(const_mut_refs)] #![feature(const_fn)] #![feature(raw_ref_op)] @@ -24,7 +22,9 @@ const fn baz(foo: &mut Foo)-> *mut usize { const _: () = { foo().bar(); + //~^ ERROR mutable references are not allowed in constants baz(&mut foo()); + //~^ ERROR mutable references are not allowed in constants }; fn main() {} diff --git a/src/test/ui/consts/const-mut-refs/const_mut_address_of.stderr b/src/test/ui/consts/const-mut-refs/const_mut_address_of.stderr new file mode 100644 index 0000000000000..2214ce6ee1c87 --- /dev/null +++ b/src/test/ui/consts/const-mut-refs/const_mut_address_of.stderr @@ -0,0 +1,15 @@ +error[E0764]: mutable references are not allowed in constants + --> $DIR/const_mut_address_of.rs:24:5 + | +LL | foo().bar(); + | ^^^^^ `&mut` is only allowed in `const fn` + +error[E0764]: mutable references are not allowed in constants + --> $DIR/const_mut_address_of.rs:26:9 + | +LL | baz(&mut foo()); + | ^^^^^^^^^^ `&mut` is only allowed in `const fn` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0764`. diff --git a/src/test/ui/consts/const-mut-refs/const_mut_refs.rs b/src/test/ui/consts/const-mut-refs/const_mut_refs.rs index 99006a20b1bcb..9099d5a1b8ea6 100644 --- a/src/test/ui/consts/const-mut-refs/const_mut_refs.rs +++ b/src/test/ui/consts/const-mut-refs/const_mut_refs.rs @@ -1,5 +1,3 @@ -// run-pass - #![feature(const_mut_refs)] struct Foo { @@ -31,6 +29,9 @@ const fn bazz(foo: &mut Foo) -> usize { fn main() { let _: [(); foo().bar()] = [(); 1]; + //~^ ERROR mutable references are not allowed in constants let _: [(); baz(&mut foo())] = [(); 2]; + //~^ ERROR mutable references are not allowed in constants let _: [(); bazz(&mut foo())] = [(); 3]; + //~^ ERROR mutable references are not allowed in constants } diff --git a/src/test/ui/consts/const-mut-refs/const_mut_refs.stderr b/src/test/ui/consts/const-mut-refs/const_mut_refs.stderr new file mode 100644 index 0000000000000..4ca7b128b7c4b --- /dev/null +++ b/src/test/ui/consts/const-mut-refs/const_mut_refs.stderr @@ -0,0 +1,21 @@ +error[E0764]: mutable references are not allowed in constants + --> $DIR/const_mut_refs.rs:31:17 + | +LL | let _: [(); foo().bar()] = [(); 1]; + | ^^^^^ `&mut` is only allowed in `const fn` + +error[E0764]: mutable references are not allowed in constants + --> $DIR/const_mut_refs.rs:33:21 + | +LL | let _: [(); baz(&mut foo())] = [(); 2]; + | ^^^^^^^^^^ `&mut` is only allowed in `const fn` + +error[E0764]: mutable references are not allowed in constants + --> $DIR/const_mut_refs.rs:35:22 + | +LL | let _: [(); bazz(&mut foo())] = [(); 3]; + | ^^^^^^^^^^ `&mut` is only allowed in `const fn` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0764`. diff --git a/src/test/ui/consts/const_let_assign3.rs b/src/test/ui/consts/const_let_assign3.rs index cbe73923e9c42..f993a427b4899 100644 --- a/src/test/ui/consts/const_let_assign3.rs +++ b/src/test/ui/consts/const_let_assign3.rs @@ -13,14 +13,14 @@ impl S { const FOO: S = { let mut s = S { state: 42 }; - s.foo(3); //~ ERROR references in constants may only refer to immutable values + s.foo(3); //~ ERROR mutable references are not allowed in constants s }; type Array = [u32; { let mut x = 2; let y = &mut x; -//~^ ERROR references in constants may only refer to immutable values +//~^ ERROR mutable references are not allowed in constants *y = 42; //~^ ERROR constant contains unimplemented expression type *y diff --git a/src/test/ui/consts/const_let_assign3.stderr b/src/test/ui/consts/const_let_assign3.stderr index 62fd04ea522c3..dd05a4c0bb069 100644 --- a/src/test/ui/consts/const_let_assign3.stderr +++ b/src/test/ui/consts/const_let_assign3.stderr @@ -6,23 +6,17 @@ LL | self.state = x; | = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error[E0658]: references in constants may only refer to immutable values +error[E0764]: mutable references are not allowed in constants --> $DIR/const_let_assign3.rs:16:5 | LL | s.foo(3); - | ^ constants require immutable values - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + | ^ `&mut` is only allowed in `const fn` -error[E0658]: references in constants may only refer to immutable values +error[E0764]: mutable references are not allowed in constants --> $DIR/const_let_assign3.rs:22:13 | LL | let y = &mut x; - | ^^^^^^ constants require immutable values - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + | ^^^^^^ `&mut` is only allowed in `const fn` error[E0019]: constant contains unimplemented expression type --> $DIR/const_let_assign3.rs:24:5 @@ -34,5 +28,5 @@ LL | *y = 42; error: aborting due to 4 previous errors -Some errors have detailed explanations: E0019, E0658. +Some errors have detailed explanations: E0019, E0764. For more information about an error, try `rustc --explain E0019`. diff --git a/src/test/ui/consts/control-flow/drop-fail.stock.stderr b/src/test/ui/consts/control-flow/drop-fail.stock.stderr index 77cded5c438b5..6a9ea91d20e1f 100644 --- a/src/test/ui/consts/control-flow/drop-fail.stock.stderr +++ b/src/test/ui/consts/control-flow/drop-fail.stock.stderr @@ -3,24 +3,36 @@ error[E0493]: destructors cannot be evaluated at compile-time | LL | let x = Some(Vec::new()); | ^ constants cannot evaluate destructors +... +LL | }; + | - value is dropped here error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/drop-fail.rs:23:9 | LL | let vec_tuple = (Vec::new(),); | ^^^^^^^^^ constants cannot evaluate destructors +... +LL | }; + | - value is dropped here error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/drop-fail.rs:31:9 | LL | let x: Result<_, Vec> = Ok(Vec::new()); | ^ constants cannot evaluate destructors +... +LL | }; + | - value is dropped here error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/drop-fail.rs:41:9 | LL | let mut tmp = None; | ^^^^^^^ constants cannot evaluate destructors +... +LL | }; + | - value is dropped here error: aborting due to 4 previous errors diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr index 512b343011b40..4b0401ebf9dba 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr @@ -2,7 +2,9 @@ error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:37:25 | LL | const fn into_inner(self) -> T { self.0 } - | ^^^^ constant functions cannot evaluate destructors + | ^^^^ - value is dropped here + | | + | constant functions cannot evaluate destructors error[E0723]: mutable references in const fn are unstable --> $DIR/min_const_fn.rs:39:36 @@ -17,7 +19,9 @@ error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:44:28 | LL | const fn into_inner_lt(self) -> T { self.0 } - | ^^^^ constant functions cannot evaluate destructors + | ^^^^ - value is dropped here + | | + | constant functions cannot evaluate destructors error[E0723]: mutable references in const fn are unstable --> $DIR/min_const_fn.rs:46:42 @@ -32,7 +36,9 @@ error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:51:27 | LL | const fn into_inner_s(self) -> T { self.0 } - | ^^^^ constant functions cannot evaluate destructors + | ^^^^ - value is dropped here + | | + | constant functions cannot evaluate destructors error[E0723]: mutable references in const fn are unstable --> $DIR/min_const_fn.rs:53:38 diff --git a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr index 37016664ac58f..0b6cb2fab46f1 100644 --- a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr +++ b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr @@ -2,7 +2,9 @@ error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/feature-gate-unleash_the_miri_inside_of_you.rs:11:20 | LL | const F: u32 = (U::X, 42).1; - | ^^^^^^^^^^ constants cannot evaluate destructors + | ^^^^^^^^^^ - value is dropped here + | | + | constants cannot evaluate destructors error: aborting due to previous error diff --git a/src/test/ui/consts/miri_unleashed/ptr_arith.rs b/src/test/ui/consts/miri_unleashed/ptr_arith.rs index 064dc6c262c88..65fc49c0b27a6 100644 --- a/src/test/ui/consts/miri_unleashed/ptr_arith.rs +++ b/src/test/ui/consts/miri_unleashed/ptr_arith.rs @@ -6,15 +6,14 @@ static CMP: () = { let x = &0 as *const _; - let _v = x == x; //~ NOTE in this + let _v = x == x; //~^ ERROR could not evaluate static initializer //~| NOTE pointer arithmetic or comparison - //~| NOTE in this }; static INT_PTR_ARITH: () = unsafe { let x: usize = std::mem::transmute(&0); - let _v = x + 0; //~ NOTE in this + let _v = x + 0; //~^ ERROR could not evaluate static initializer //~| NOTE pointer-to-integer cast }; diff --git a/src/test/ui/consts/miri_unleashed/ptr_arith.stderr b/src/test/ui/consts/miri_unleashed/ptr_arith.stderr index 4b3fe9957002e..21f11dda5a667 100644 --- a/src/test/ui/consts/miri_unleashed/ptr_arith.stderr +++ b/src/test/ui/consts/miri_unleashed/ptr_arith.stderr @@ -5,20 +5,20 @@ LL | let _v = x == x; | ^^^^^^ "pointer arithmetic or comparison" needs an rfc before being allowed inside constants error[E0080]: could not evaluate static initializer - --> $DIR/ptr_arith.rs:17:14 + --> $DIR/ptr_arith.rs:16:14 | LL | let _v = x + 0; | ^^^^^ "pointer-to-integer cast" needs an rfc before being allowed inside constants warning: skipping const checks | -help: skipping check for `const_compare_raw_pointers` feature +help: skipping check that does not even have a feature gate --> $DIR/ptr_arith.rs:9:14 | LL | let _v = x == x; | ^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/ptr_arith.rs:16:20 + --> $DIR/ptr_arith.rs:15:20 | LL | let x: usize = std::mem::transmute(&0); | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/consts/miri_unleashed/slice_eq.rs b/src/test/ui/consts/miri_unleashed/slice_eq.rs new file mode 100644 index 0000000000000..fd843105daf2a --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/slice_eq.rs @@ -0,0 +1,17 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you +// run-pass + +#![feature(const_raw_ptr_comparison)] + +const EMPTY_SLICE: &[i32] = &[]; +const EMPTY_EQ: bool = EMPTY_SLICE.as_ptr().guaranteed_eq(&[] as *const _); +const EMPTY_EQ2: bool = EMPTY_SLICE.as_ptr().guaranteed_ne(&[] as *const _); +const EMPTY_NE: bool = EMPTY_SLICE.as_ptr().guaranteed_ne(&[1] as *const _); +const EMPTY_NE2: bool = EMPTY_SLICE.as_ptr().guaranteed_eq(&[1] as *const _); + +fn main() { + assert!(!EMPTY_EQ); + assert!(!EMPTY_EQ2); + assert!(!EMPTY_NE); + assert!(!EMPTY_NE2); +} diff --git a/src/test/ui/consts/projection_qualif.mut_refs.stderr b/src/test/ui/consts/projection_qualif.mut_refs.stderr index 0945a23f3b123..fad8f011f75f5 100644 --- a/src/test/ui/consts/projection_qualif.mut_refs.stderr +++ b/src/test/ui/consts/projection_qualif.mut_refs.stderr @@ -1,3 +1,9 @@ +error[E0764]: mutable references are not allowed in constants + --> $DIR/projection_qualif.rs:10:27 + | +LL | let b: *mut u32 = &mut a; + | ^^^^^^ `&mut` is only allowed in `const fn` + error[E0658]: dereferencing raw pointers in constants is unstable --> $DIR/projection_qualif.rs:11:18 | @@ -7,6 +13,7 @@ LL | unsafe { *b = 5; } = note: see issue #51911 for more information = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0658, E0764. +For more information about an error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/projection_qualif.rs b/src/test/ui/consts/projection_qualif.rs index cfe8e7f03d5e4..7db970cf1379f 100644 --- a/src/test/ui/consts/projection_qualif.rs +++ b/src/test/ui/consts/projection_qualif.rs @@ -7,7 +7,7 @@ use std::cell::Cell; const FOO: &u32 = { let mut a = 42; { - let b: *mut u32 = &mut a; //[stock]~ ERROR may only refer to immutable values + let b: *mut u32 = &mut a; //~ ERROR mutable references are not allowed in constants unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants //[stock]~^ contains unimplemented expression } diff --git a/src/test/ui/consts/projection_qualif.stock.stderr b/src/test/ui/consts/projection_qualif.stock.stderr index cfa48d947c992..212f12286455f 100644 --- a/src/test/ui/consts/projection_qualif.stock.stderr +++ b/src/test/ui/consts/projection_qualif.stock.stderr @@ -1,11 +1,8 @@ -error[E0658]: references in constants may only refer to immutable values +error[E0764]: mutable references are not allowed in constants --> $DIR/projection_qualif.rs:10:27 | LL | let b: *mut u32 = &mut a; - | ^^^^^^ constants require immutable values - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + | ^^^^^^ `&mut` is only allowed in `const fn` error[E0658]: dereferencing raw pointers in constants is unstable --> $DIR/projection_qualif.rs:11:18 @@ -26,5 +23,5 @@ LL | unsafe { *b = 5; } error: aborting due to 3 previous errors -Some errors have detailed explanations: E0019, E0658. +Some errors have detailed explanations: E0019, E0658, E0764. For more information about an error, try `rustc --explain E0019`. diff --git a/src/test/ui/consts/read_from_static_mut_ref.rs b/src/test/ui/consts/read_from_static_mut_ref.rs index c18227e0f5515..5faa983ab09f7 100644 --- a/src/test/ui/consts/read_from_static_mut_ref.rs +++ b/src/test/ui/consts/read_from_static_mut_ref.rs @@ -1,10 +1,9 @@ -// run-pass +// We are keeping this test in case we decide to allow mutable references in statics again #![feature(const_mut_refs)] #![allow(const_err)] -static OH_YES: &mut i32 = &mut 42; - +static OH_NO: &mut i32 = &mut 42; +//~^ ERROR mutable references are not allowed in statics fn main() { - // Make sure `OH_YES` can be read. - assert_eq!(*OH_YES, 42); + assert_eq!(*OH_NO, 42); } diff --git a/src/test/ui/consts/read_from_static_mut_ref.stderr b/src/test/ui/consts/read_from_static_mut_ref.stderr new file mode 100644 index 0000000000000..c936ac0b7d585 --- /dev/null +++ b/src/test/ui/consts/read_from_static_mut_ref.stderr @@ -0,0 +1,9 @@ +error[E0764]: mutable references are not allowed in statics + --> $DIR/read_from_static_mut_ref.rs:5:26 + | +LL | static OH_NO: &mut i32 = &mut 42; + | ^^^^^^^ `&mut` is only allowed in `const fn` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0764`. 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 8db75dd63cf2a..36c280ca5c607 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 @@ -1,9 +1,9 @@ -error[E0080]: could not evaluate static initializer - --> $DIR/static_mut_containing_mut_ref2.rs:7:45 +error[E0764]: mutable references are not allowed in statics + --> $DIR/static_mut_containing_mut_ref2.rs:7:46 | LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ modifying a static's initial value from another static's initializer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `&mut` is only allowed in `const fn` error: aborting due to previous error -For more information about this error, try `rustc --explain E0080`. +For more information about this error, try `rustc --explain E0764`. diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.rs b/src/test/ui/consts/static_mut_containing_mut_ref2.rs index 74162fbd54b04..a6bbe8d6ec24c 100644 --- a/src/test/ui/consts/static_mut_containing_mut_ref2.rs +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.rs @@ -5,8 +5,7 @@ static mut STDERR_BUFFER_SPACE: u8 = 0; pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; -//[mut_refs]~^ ERROR could not evaluate static initializer -//[stock]~^^ ERROR references in statics may only refer to immutable values +//~^ ERROR mutable references are not allowed in statics //[stock]~| ERROR static contains unimplemented expression type fn main() {} diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr index cc169351bf268..57fb27e642e6f 100644 --- a/src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr @@ -1,11 +1,8 @@ -error[E0658]: references in statics may only refer to immutable values +error[E0764]: mutable references are not allowed in statics --> $DIR/static_mut_containing_mut_ref2.rs:7:46 | LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ statics require immutable values - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `&mut` is only allowed in `const fn` error[E0019]: static contains unimplemented expression type --> $DIR/static_mut_containing_mut_ref2.rs:7:45 @@ -17,5 +14,5 @@ LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 4 error: aborting due to 2 previous errors -Some errors have detailed explanations: E0019, E0658. +Some errors have detailed explanations: E0019, E0764. For more information about an error, try `rustc --explain E0019`. diff --git a/src/test/ui/consts/trait_specialization.rs b/src/test/ui/consts/trait_specialization.rs index 8010d2fe1aee9..3adbbb5304634 100644 --- a/src/test/ui/consts/trait_specialization.rs +++ b/src/test/ui/consts/trait_specialization.rs @@ -5,7 +5,7 @@ // Tests that specialization does not cause optimizations running on polymorphic MIR to resolve // to a `default` implementation. -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait Marker {} diff --git a/src/test/ui/consts/trait_specialization.stderr b/src/test/ui/consts/trait_specialization.stderr new file mode 100644 index 0000000000000..03da7d512e592 --- /dev/null +++ b/src/test/ui/consts/trait_specialization.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/trait_specialization.rs:8:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/consts/unstable-const-fn-in-libcore.stderr b/src/test/ui/consts/unstable-const-fn-in-libcore.stderr index a8455cefd01cf..928605356a16e 100644 --- a/src/test/ui/consts/unstable-const-fn-in-libcore.stderr +++ b/src/test/ui/consts/unstable-const-fn-in-libcore.stderr @@ -9,12 +9,18 @@ error[E0493]: destructors cannot be evaluated at compile-time | LL | const fn unwrap_or_else T>(self, f: F) -> T { | ^ constant functions cannot evaluate destructors +... +LL | } + | - value is dropped here error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/unstable-const-fn-in-libcore.rs:19:47 | LL | const fn unwrap_or_else T>(self, f: F) -> T { | ^^^^ constant functions cannot evaluate destructors +... +LL | } + | - value is dropped here error: aborting due to 3 previous errors diff --git a/src/test/ui/dst/dst-sized-trait-param.stderr b/src/test/ui/dst/dst-sized-trait-param.stderr index 749d569b9aedc..006a334021b14 100644 --- a/src/test/ui/dst/dst-sized-trait-param.stderr +++ b/src/test/ui/dst/dst-sized-trait-param.stderr @@ -9,6 +9,10 @@ LL | impl Foo<[isize]> for usize { } | = help: the trait `std::marker::Sized` is not implemented for `[isize]` = note: to learn more, visit +help: consider relaxing the implicit `Sized` restriction + | +LL | trait Foo : Sized { fn take(self, x: &T) { } } // Note: T is sized + | ^^^^^^^^ error[E0277]: the size for values of type `[usize]` cannot be known at compilation time --> $DIR/dst-sized-trait-param.rs:10:6 diff --git a/src/test/ui/error-codes/E0017.rs b/src/test/ui/error-codes/E0017.rs index 64be41170d0c8..818dec1207b96 100644 --- a/src/test/ui/error-codes/E0017.rs +++ b/src/test/ui/error-codes/E0017.rs @@ -2,10 +2,10 @@ static X: i32 = 1; const C: i32 = 2; static mut M: i32 = 3; -const CR: &'static mut i32 = &mut C; //~ ERROR E0658 -static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0658 +const CR: &'static mut i32 = &mut C; //~ ERROR E0764 +static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0764 //~| ERROR E0019 //~| ERROR cannot borrow -static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0658 -static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; //~ ERROR E0658 +static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0764 +static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; //~ ERROR E0764 fn main() {} diff --git a/src/test/ui/error-codes/E0017.stderr b/src/test/ui/error-codes/E0017.stderr index f959ad0d00887..c1d96de1dca7c 100644 --- a/src/test/ui/error-codes/E0017.stderr +++ b/src/test/ui/error-codes/E0017.stderr @@ -1,11 +1,8 @@ -error[E0658]: references in constants may only refer to immutable values +error[E0764]: mutable references are not allowed in constants --> $DIR/E0017.rs:5:30 | LL | const CR: &'static mut i32 = &mut C; - | ^^^^^^ constants require immutable values - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + | ^^^^^^ `&mut` is only allowed in `const fn` error[E0019]: static contains unimplemented expression type --> $DIR/E0017.rs:6:39 @@ -15,14 +12,11 @@ LL | static STATIC_REF: &'static mut i32 = &mut X; | = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error[E0658]: references in statics may only refer to immutable values +error[E0764]: mutable references are not allowed in statics --> $DIR/E0017.rs:6:39 | LL | static STATIC_REF: &'static mut i32 = &mut X; - | ^^^^^^ statics require immutable values - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + | ^^^^^^ `&mut` is only allowed in `const fn` error[E0596]: cannot borrow immutable static item `X` as mutable --> $DIR/E0017.rs:6:39 @@ -30,25 +24,19 @@ error[E0596]: cannot borrow immutable static item `X` as mutable LL | static STATIC_REF: &'static mut i32 = &mut X; | ^^^^^^ cannot borrow as mutable -error[E0658]: references in statics may only refer to immutable values +error[E0764]: mutable references are not allowed in statics --> $DIR/E0017.rs:9:38 | LL | static CONST_REF: &'static mut i32 = &mut C; - | ^^^^^^ statics require immutable values - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + | ^^^^^^ `&mut` is only allowed in `const fn` -error[E0658]: references in statics may only refer to immutable values +error[E0764]: mutable references are not allowed in statics --> $DIR/E0017.rs:10:52 | LL | static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; - | ^^^^^^ statics require immutable values - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + | ^^^^^^ `&mut` is only allowed in `const fn` error: aborting due to 6 previous errors -Some errors have detailed explanations: E0019, E0596, E0658. +Some errors have detailed explanations: E0019, E0596, E0764. For more information about an error, try `rustc --explain E0019`. diff --git a/src/test/ui/error-codes/E0388.rs b/src/test/ui/error-codes/E0388.rs index 5954e3490b06c..13131017c2e07 100644 --- a/src/test/ui/error-codes/E0388.rs +++ b/src/test/ui/error-codes/E0388.rs @@ -1,10 +1,10 @@ static X: i32 = 1; const C: i32 = 2; -const CR: &'static mut i32 = &mut C; //~ ERROR E0658 -static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0658 +const CR: &'static mut i32 = &mut C; //~ ERROR E0764 +static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0019 //~| ERROR cannot borrow - //~| ERROR E0019 -static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0658 + //~| ERROR E0764 +static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0764 fn main() {} diff --git a/src/test/ui/error-codes/E0388.stderr b/src/test/ui/error-codes/E0388.stderr index 8bdfbac36816b..f09100bac43ce 100644 --- a/src/test/ui/error-codes/E0388.stderr +++ b/src/test/ui/error-codes/E0388.stderr @@ -1,11 +1,8 @@ -error[E0658]: references in constants may only refer to immutable values +error[E0764]: mutable references are not allowed in constants --> $DIR/E0388.rs:4:30 | LL | const CR: &'static mut i32 = &mut C; - | ^^^^^^ constants require immutable values - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + | ^^^^^^ `&mut` is only allowed in `const fn` error[E0019]: static contains unimplemented expression type --> $DIR/E0388.rs:5:39 @@ -15,14 +12,11 @@ LL | static STATIC_REF: &'static mut i32 = &mut X; | = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error[E0658]: references in statics may only refer to immutable values +error[E0764]: mutable references are not allowed in statics --> $DIR/E0388.rs:5:39 | LL | static STATIC_REF: &'static mut i32 = &mut X; - | ^^^^^^ statics require immutable values - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + | ^^^^^^ `&mut` is only allowed in `const fn` error[E0596]: cannot borrow immutable static item `X` as mutable --> $DIR/E0388.rs:5:39 @@ -30,16 +24,13 @@ error[E0596]: cannot borrow immutable static item `X` as mutable LL | static STATIC_REF: &'static mut i32 = &mut X; | ^^^^^^ cannot borrow as mutable -error[E0658]: references in statics may only refer to immutable values +error[E0764]: mutable references are not allowed in statics --> $DIR/E0388.rs:8:38 | LL | static CONST_REF: &'static mut i32 = &mut C; - | ^^^^^^ statics require immutable values - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + | ^^^^^^ `&mut` is only allowed in `const fn` error: aborting due to 5 previous errors -Some errors have detailed explanations: E0019, E0596, E0658. +Some errors have detailed explanations: E0019, E0596, E0764. For more information about an error, try `rustc --explain E0019`. diff --git a/src/test/ui/error-codes/E0395.rs b/src/test/ui/error-codes/E0395.rs index bbefff27d7f68..d2edd97efb232 100644 --- a/src/test/ui/error-codes/E0395.rs +++ b/src/test/ui/error-codes/E0395.rs @@ -1,10 +1,8 @@ -// gate-test-const_compare_raw_pointers - static FOO: i32 = 42; static BAR: i32 = 42; static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) }; -//~^ ERROR comparing raw pointers inside static +//~^ ERROR pointers cannot be reliably compared during const eval fn main() { } diff --git a/src/test/ui/error-codes/E0395.stderr b/src/test/ui/error-codes/E0395.stderr index 20c8622f33726..674cc69645029 100644 --- a/src/test/ui/error-codes/E0395.stderr +++ b/src/test/ui/error-codes/E0395.stderr @@ -1,12 +1,10 @@ -error[E0658]: comparing raw pointers inside static - --> $DIR/E0395.rs:6:29 +error: pointers cannot be reliably compared during const eval. + --> $DIR/E0395.rs:4:29 | LL | static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #53020 for more information - = help: add `#![feature(const_compare_raw_pointers)]` 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/error-codes/E0520.rs b/src/test/ui/error-codes/E0520.rs index b746ca63590ec..ead78b7ffa2c4 100644 --- a/src/test/ui/error-codes/E0520.rs +++ b/src/test/ui/error-codes/E0520.rs @@ -1,4 +1,5 @@ #![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete trait SpaceLlama { fn fly(&self); diff --git a/src/test/ui/error-codes/E0520.stderr b/src/test/ui/error-codes/E0520.stderr index 72fc85ab1e74b..1041ccee93704 100644 --- a/src/test/ui/error-codes/E0520.stderr +++ b/src/test/ui/error-codes/E0520.stderr @@ -1,5 +1,14 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/E0520.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + error[E0520]: `fly` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/E0520.rs:16:5 + --> $DIR/E0520.rs:17:5 | LL | / impl SpaceLlama for T { LL | | fn fly(&self) {} @@ -11,6 +20,6 @@ LL | default fn fly(&self) {} | = note: to specialize, `fly` in the parent `impl` must be marked `default` -error: aborting due to previous error +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0520`. diff --git a/src/test/ui/extern/extern-types-unsized.stderr b/src/test/ui/extern/extern-types-unsized.stderr index 9ed52511fa399..0c7995fde3273 100644 --- a/src/test/ui/extern/extern-types-unsized.stderr +++ b/src/test/ui/extern/extern-types-unsized.stderr @@ -26,6 +26,10 @@ LL | assert_sized::(); = help: within `Foo`, the trait `std::marker::Sized` is not implemented for `A` = note: to learn more, visit = note: required because it appears within the type `Foo` +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:28:5 @@ -39,6 +43,10 @@ LL | assert_sized::>(); = help: within `Bar`, the trait `std::marker::Sized` is not implemented for `A` = note: to learn more, visit = note: required because it appears within the type `Bar` +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:31:5 @@ -53,6 +61,10 @@ LL | assert_sized::>>(); = note: to learn more, visit = note: required because it appears within the type `Bar` = note: required because it appears within the type `Bar>` +help: consider relaxing the implicit `Sized` restriction + | +LL | fn assert_sized() { } + | ^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs index 1ab11ce3b4423..dc602ba7e6f21 100644 --- a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs +++ b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs @@ -1,9 +1,9 @@ struct ConstFn; //~^ ERROR const generics are unstable -//~^^ ERROR using function pointers as const generic parameters is unstable +//~^^ ERROR using function pointers as const generic parameters is forbidden struct ConstPtr; //~^ ERROR const generics are unstable -//~^^ ERROR using raw pointers as const generic parameters is unstable +//~^^ ERROR using raw pointers as const generic parameters is forbidden fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr index dc7ef55e7ab99..b2c96d3810f98 100644 --- a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr +++ b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr @@ -16,23 +16,17 @@ LL | struct ConstPtr; = note: see issue #44580 for more information = help: add `#![feature(const_generics)]` to the crate attributes to enable -error[E0658]: using function pointers as const generic parameters is unstable +error: using function pointers as const generic parameters is forbidden --> $DIR/feature-gate-const_generics-ptr.rs:1:25 | LL | struct ConstFn; | ^^^^ - | - = note: see issue #53020 for more information - = help: add `#![feature(const_compare_raw_pointers)]` to the crate attributes to enable -error[E0658]: using raw pointers as const generic parameters is unstable +error: using raw pointers as const generic parameters is forbidden --> $DIR/feature-gate-const_generics-ptr.rs:5:26 | LL | struct ConstPtr; | ^^^^^^^^^^ - | - = note: see issue #53020 for more information - = help: add `#![feature(const_compare_raw_pointers)]` to the crate attributes to enable error: aborting due to 4 previous errors diff --git a/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs b/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs index 7ff348aca7cc1..17548d7b9e88c 100644 --- a/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs +++ b/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs @@ -3,11 +3,9 @@ use std::ops::Deref; trait PointerFamily { type Pointer: Deref; //~^ ERROR generic associated types are unstable - //~| ERROR type-generic associated types are not yet implemented type Pointer2: Deref where T: Clone, U: Clone; //~^ ERROR generic associated types are unstable //~| ERROR where clauses on associated types are unstable - //~| ERROR type-generic associated types are not yet implemented } struct Foo; diff --git a/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr b/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr index a0e06cb2b6795..8499b1ab70f5d 100644 --- a/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr +++ b/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr @@ -8,7 +8,7 @@ LL | type Pointer: Deref; = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable error[E0658]: generic associated types are unstable - --> $DIR/feature-gate-generic_associated_types.rs:7:5 + --> $DIR/feature-gate-generic_associated_types.rs:6:5 | LL | type Pointer2: Deref where T: Clone, U: Clone; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | type Pointer2: Deref where T: Clone, U: Clone; = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable error[E0658]: where clauses on associated types are unstable - --> $DIR/feature-gate-generic_associated_types.rs:7:5 + --> $DIR/feature-gate-generic_associated_types.rs:6:5 | LL | type Pointer2: Deref where T: Clone, U: Clone; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | type Pointer2: Deref where T: Clone, U: Clone; = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable error[E0658]: generic associated types are unstable - --> $DIR/feature-gate-generic_associated_types.rs:16:5 + --> $DIR/feature-gate-generic_associated_types.rs:14:5 | LL | type Pointer = Box; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -35,7 +35,7 @@ LL | type Pointer = Box; = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable error[E0658]: generic associated types are unstable - --> $DIR/feature-gate-generic_associated_types.rs:18:5 + --> $DIR/feature-gate-generic_associated_types.rs:16:5 | LL | type Pointer2 = Box; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | type Pointer2 = Box; = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable error[E0658]: where clauses on associated types are unstable - --> $DIR/feature-gate-generic_associated_types.rs:23:5 + --> $DIR/feature-gate-generic_associated_types.rs:21:5 | LL | type Assoc where Self: Sized; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -53,7 +53,7 @@ LL | type Assoc where Self: Sized; = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable error[E0658]: where clauses on associated types are unstable - --> $DIR/feature-gate-generic_associated_types.rs:28:5 + --> $DIR/feature-gate-generic_associated_types.rs:26:5 | LL | type Assoc where Self: Sized = Foo; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,22 +61,6 @@ LL | type Assoc where Self: Sized = Foo; = note: see issue #44265 for more information = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable -error: type-generic associated types are not yet implemented - --> $DIR/feature-gate-generic_associated_types.rs:4:5 - | -LL | type Pointer: Deref; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: type-generic associated types are not yet implemented - --> $DIR/feature-gate-generic_associated_types.rs:7:5 - | -LL | type Pointer2: Deref where T: Clone, U: Clone; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: aborting due to 9 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/fn/fn-item-type.rs b/src/test/ui/fn/fn-item-type.rs index 68b75c18a43dc..abae40162a0fc 100644 --- a/src/test/ui/fn/fn-item-type.rs +++ b/src/test/ui/fn/fn-item-type.rs @@ -12,22 +12,44 @@ impl Foo for T { /* `foo` is still default here */ } fn main() { eq(foo::, bar::); //~^ ERROR mismatched types - //~| expected fn item `fn(_) -> _ {foo::}` - //~| found fn item `fn(_) -> _ {bar::}` - //~| expected fn item, found a different fn item + //~| expected fn item `fn(_) -> _ {foo::}` + //~| found fn item `fn(_) -> _ {bar::}` + //~| expected fn item, found a different fn item + //~| different `fn` items always have unique types, even if their signatures are the same + //~| change the expected type to be function pointer + //~| if the expected type is due to type inference, cast the expected `fn` to a function pointer eq(foo::, foo::); //~^ ERROR mismatched types //~| expected `u8`, found `i8` + //~| different `fn` items always have unique types, even if their signatures are the same + //~| change the expected type to be function pointer + //~| if the expected type is due to type inference, cast the expected `fn` to a function pointer eq(bar::, bar::>); //~^ ERROR mismatched types - //~| expected fn item `fn(_) -> _ {bar::}` - //~| found fn item `fn(_) -> _ {bar::>}` - //~| expected struct `std::string::String`, found struct `std::vec::Vec` + //~| expected fn item `fn(_) -> _ {bar::}` + //~| found fn item `fn(_) -> _ {bar::>}` + //~| expected struct `std::string::String`, found struct `std::vec::Vec` + //~| different `fn` items always have unique types, even if their signatures are the same + //~| change the expected type to be function pointer + //~| if the expected type is due to type inference, cast the expected `fn` to a function pointer // Make sure we distinguish between trait methods correctly. eq(::foo, ::foo); //~^ ERROR mismatched types //~| expected `u8`, found `u16` + //~| different `fn` items always have unique types, even if their signatures are the same + //~| change the expected type to be function pointer + //~| if the expected type is due to type inference, cast the expected `fn` to a function pointer + + eq(foo::, bar:: as fn(isize) -> isize); + //~^ ERROR mismatched types + //~| expected fn item `fn(_) -> _ {foo::}` + //~| found fn pointer `fn(_) -> _` + //~| expected fn item, found fn pointer + //~| change the expected type to be function pointer + //~| if the expected type is due to type inference, cast the expected `fn` to a function pointer + + eq(foo:: as fn(isize) -> isize, bar::); // ok! } diff --git a/src/test/ui/fn/fn-item-type.stderr b/src/test/ui/fn/fn-item-type.stderr index 4cce25c43c485..bfa9efa219f4c 100644 --- a/src/test/ui/fn/fn-item-type.stderr +++ b/src/test/ui/fn/fn-item-type.stderr @@ -6,34 +6,57 @@ LL | eq(foo::, bar::); | = note: expected fn item `fn(_) -> _ {foo::}` found fn item `fn(_) -> _ {bar::}` + = note: different `fn` items always have unique types, even if their signatures are the same + = help: change the expected type to be function pointer `fn(isize) -> isize` + = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `foo:: as fn(isize) -> isize` error[E0308]: mismatched types - --> $DIR/fn-item-type.rs:19:19 + --> $DIR/fn-item-type.rs:22:19 | LL | eq(foo::, foo::); | ^^^^^^^^^ expected `u8`, found `i8` | = note: expected fn item `fn(_) -> _ {foo::}` found fn item `fn(_) -> _ {foo::}` + = note: different `fn` items always have unique types, even if their signatures are the same + = help: change the expected type to be function pointer `fn(isize) -> isize` + = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `foo:: as fn(isize) -> isize` error[E0308]: mismatched types - --> $DIR/fn-item-type.rs:23:23 + --> $DIR/fn-item-type.rs:29:23 | LL | eq(bar::, bar::>); | ^^^^^^^^^^^^^^ expected struct `std::string::String`, found struct `std::vec::Vec` | = note: expected fn item `fn(_) -> _ {bar::}` found fn item `fn(_) -> _ {bar::>}` + = note: different `fn` items always have unique types, even if their signatures are the same + = help: change the expected type to be function pointer `fn(isize) -> isize` + = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `bar:: as fn(isize) -> isize` error[E0308]: mismatched types - --> $DIR/fn-item-type.rs:30:26 + --> $DIR/fn-item-type.rs:39:26 | LL | eq(::foo, ::foo); | ^^^^^^^^^^^^^^^^^ expected `u8`, found `u16` | = note: expected fn item `fn() {::foo}` found fn item `fn() {::foo}` + = note: different `fn` items always have unique types, even if their signatures are the same + = help: change the expected type to be function pointer `fn()` + = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `::foo as fn()` -error: aborting due to 4 previous errors +error[E0308]: mismatched types + --> $DIR/fn-item-type.rs:46:19 + | +LL | eq(foo::, bar:: as fn(isize) -> isize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn item, found fn pointer + | + = note: expected fn item `fn(_) -> _ {foo::}` + found fn pointer `fn(_) -> _` + = help: change the expected type to be function pointer `fn(isize) -> isize` + = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `foo:: as fn(isize) -> isize` + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/generator/resume-arg-late-bound.nll.stderr b/src/test/ui/generator/resume-arg-late-bound.nll.stderr new file mode 100644 index 0000000000000..7d71219192407 --- /dev/null +++ b/src/test/ui/generator/resume-arg-late-bound.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/resume-arg-late-bound.rs:15:5 + | +LL | test(gen); + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/generator/resume-arg-late-bound.rs b/src/test/ui/generator/resume-arg-late-bound.rs index 87b1f1a065bc8..a8f657eaabe47 100644 --- a/src/test/ui/generator/resume-arg-late-bound.rs +++ b/src/test/ui/generator/resume-arg-late-bound.rs @@ -13,5 +13,6 @@ fn main() { *arg = true; }; test(gen); - //~^ ERROR type mismatch in function arguments + //~^ ERROR mismatched types + //~| ERROR mismatched types } diff --git a/src/test/ui/generator/resume-arg-late-bound.stderr b/src/test/ui/generator/resume-arg-late-bound.stderr index ffa440daed8c4..c379d9eae8ecd 100644 --- a/src/test/ui/generator/resume-arg-late-bound.stderr +++ b/src/test/ui/generator/resume-arg-late-bound.stderr @@ -1,15 +1,21 @@ -error[E0631]: type mismatch in function arguments - --> $DIR/resume-arg-late-bound.rs:15:10 +error[E0308]: mismatched types + --> $DIR/resume-arg-late-bound.rs:15:5 | -LL | fn test(a: impl for<'a> Generator<&'a mut bool>) {} - | ------------------------------- required by this bound in `test` -... LL | test(gen); - | ^^^ - | | - | expected signature of `for<'a> fn(&'a mut bool) -> _` - | found signature of `fn(&mut bool) -> _` + | ^^^^ one type is more general than the other + | + = note: expected type `for<'a> std::ops::Generator<&'a mut bool>` + found type `std::ops::Generator<&mut bool>` + +error[E0308]: mismatched types + --> $DIR/resume-arg-late-bound.rs:15:5 + | +LL | test(gen); + | ^^^^ one type is more general than the other + | + = note: expected type `for<'a> std::ops::Generator<&'a mut bool>` + found type `std::ops::Generator<&mut bool>` -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0631`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/generic-associated-types/collections-project-default.rs b/src/test/ui/generic-associated-types/collections-project-default.rs new file mode 100644 index 0000000000000..5fbae02573c62 --- /dev/null +++ b/src/test/ui/generic-associated-types/collections-project-default.rs @@ -0,0 +1,72 @@ +#![allow(incomplete_features)] +#![feature(generic_associated_types)] +#![feature(associated_type_defaults)] + +// A Collection trait and collection families. Based on +// http://smallcultfollowing.com/babysteps/blog/2016/11/03/ +// associated-type-constructors-part-2-family-traits/ + +// check that we don't normalize with trait defaults. + +trait Collection { + type Iter<'iter>: Iterator where T: 'iter; + type Family: CollectionFamily; + // Test associated type defaults with parameters + type Sibling: Collection = + <>::Family as CollectionFamily>::Member; + + fn empty() -> Self; + + fn add(&mut self, value: T); + + fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>; +} + +trait CollectionFamily { + type Member: Collection; +} + +struct VecFamily; + +impl CollectionFamily for VecFamily { + type Member = Vec; +} + +impl Collection for Vec { + type Iter<'iter> where T: 'iter = std::slice::Iter<'iter, T>; + type Family = VecFamily; + + fn empty() -> Self { + Vec::new() + } + + fn add(&mut self, value: T) { + self.push(value) + } + + fn iterate<'iter>(&'iter self) -> Self::Iter<'iter> { + self.iter() + } +} + +fn floatify_sibling(ints: &C) -> >::Sibling +where + C: Collection, +{ + let mut res = ::Member::::empty(); + for &v in ints.iterate() { + res.add(v as f32); + } + res + //~^ ERROR mismatched types +} + +fn use_floatify() { + let a = vec![1i32, 2, 3]; + let c = floatify_sibling(&a); + assert_eq!(Some(&1.0), c.iterate().next()); +} + +fn main() { + use_floatify(); +} diff --git a/src/test/ui/generic-associated-types/collections-project-default.stderr b/src/test/ui/generic-associated-types/collections-project-default.stderr new file mode 100644 index 0000000000000..ca02b2603ba64 --- /dev/null +++ b/src/test/ui/generic-associated-types/collections-project-default.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/collections-project-default.rs:60:5 + | +LL | fn floatify_sibling(ints: &C) -> >::Sibling + | ------------------------------------ expected `>::Sibling` because of return type +... +LL | res + | ^^^ expected Collection::Sibling, found CollectionFamily::Member + | + = note: expected associated type `>::Sibling` + found associated type `<>::Family as CollectionFamily>::Member` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/generic-associated-types/collections.rs b/src/test/ui/generic-associated-types/collections.rs index 6f018f0401863..1b5b9c181fb61 100644 --- a/src/test/ui/generic-associated-types/collections.rs +++ b/src/test/ui/generic-associated-types/collections.rs @@ -6,13 +6,14 @@ // http://smallcultfollowing.com/babysteps/blog/2016/11/03/ // associated-type-constructors-part-2-family-traits/ +// run-pass + trait Collection { - type Iter<'iter>: Iterator; + type Iter<'iter>: Iterator where T: 'iter; type Family: CollectionFamily; // Test associated type defaults with parameters type Sibling: Collection = <>::Family as CollectionFamily>::Member; - //~^^ ERROR type-generic associated types are not yet implemented fn empty() -> Self; @@ -23,7 +24,6 @@ trait Collection { trait CollectionFamily { type Member: Collection; - //~^ ERROR type-generic associated types are not yet implemented } struct VecFamily; @@ -33,7 +33,7 @@ impl CollectionFamily for VecFamily { } impl Collection for Vec { - type Iter<'iter> = std::slice::Iter<'iter, T>; + type Iter<'iter> where T: 'iter = std::slice::Iter<'iter, T>; type Family = VecFamily; fn empty() -> Self { @@ -53,18 +53,7 @@ fn floatify(ints: &C) -> <>::Family as CollectionFamily> where C: Collection, { - let mut res = C::Family::Member::::empty(); - for &v in ints.iterate() { - res.add(v as f32); - } - res -} - -fn floatify_sibling(ints: &C) -> >::Sibling -where - C: Collection, -{ - let mut res = C::Family::Member::::empty(); + let mut res = ::Member::::empty(); for &v in ints.iterate() { res.add(v as f32); } @@ -72,11 +61,11 @@ where } fn use_floatify() { - let a = vec![1i32, 2, 3]; - let b = floatify(a); - println!("{}", b.iterate().next()); - let c = floatify_sibling(a); - println!("{}", c.iterate().next()); + let a = vec![1, 2, 3]; + let b = floatify(&a); + assert_eq!(Some(&1.0), b.iterate().next()); } -fn main() {} +fn main() { + use_floatify(); +} diff --git a/src/test/ui/generic-associated-types/collections.stderr b/src/test/ui/generic-associated-types/collections.stderr deleted file mode 100644 index fb06d5e49a391..0000000000000 --- a/src/test/ui/generic-associated-types/collections.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error: type-generic associated types are not yet implemented - --> $DIR/collections.rs:13:5 - | -LL | / type Sibling: Collection = -LL | | <>::Family as CollectionFamily>::Member; - | |_________________________________________________________________________^ - | - = note: for more information, see issue #44265 for more information - -error: type-generic associated types are not yet implemented - --> $DIR/collections.rs:25:5 - | -LL | type Member: Collection; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/generic-associated-types/construct_with_other_type.rs b/src/test/ui/generic-associated-types/construct_with_other_type.rs index 2198b99db25c1..ff9d61658f4eb 100644 --- a/src/test/ui/generic-associated-types/construct_with_other_type.rs +++ b/src/test/ui/generic-associated-types/construct_with_other_type.rs @@ -1,7 +1,7 @@ #![allow(incomplete_features)] #![feature(generic_associated_types)] -// FIXME(#30472) normalize enough to handle this. +// check-pass use std::ops::Deref; @@ -17,7 +17,6 @@ trait Baz { } impl Baz for T where T: Foo { -//~^ ERROR type mismatch resolving type Quux<'a> where T: 'a = T; type Baa<'a> where T: 'a = &'a ::Bar<'a, 'static>; diff --git a/src/test/ui/generic-associated-types/construct_with_other_type.stderr b/src/test/ui/generic-associated-types/construct_with_other_type.stderr deleted file mode 100644 index b9468b3330b44..0000000000000 --- a/src/test/ui/generic-associated-types/construct_with_other_type.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0271]: type mismatch resolving `for<'a> <::Baa<'a> as std::ops::Deref>::Target == <::Quux<'a> as Foo>::Bar<'a, 'static>` - --> $DIR/construct_with_other_type.rs:19:9 - | -LL | impl Baz for T where T: Foo { - | - ^^^ expected type parameter `T`, found associated type - | | - | this type parameter - | - = note: expected associated type `::Bar<'_, 'static>` - found associated type `<::Quux<'_> as Foo>::Bar<'_, 'static>` -help: consider further restricting this bound - | -LL | impl Baz for T where T: Foo + Baz { - | ^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.rs b/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.rs index f88df6a608aa3..c1d68812e9356 100644 --- a/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.rs +++ b/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.rs @@ -6,7 +6,6 @@ struct Foo; trait MyTrait { type Item; //~^ ERROR generic associated types are unstable [E0658] - //~| ERROR type-generic associated types are not yet implemented } impl MyTrait for Foo { diff --git a/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.stderr b/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.stderr index f3da27775adcf..34f536dbe8f64 100644 --- a/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.stderr +++ b/src/test/ui/generic-associated-types/gat-dont-ice-on-absent-feature-2.stderr @@ -8,7 +8,7 @@ LL | type Item; = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable error[E0658]: generic associated types are unstable - --> $DIR/gat-dont-ice-on-absent-feature-2.rs:13:5 + --> $DIR/gat-dont-ice-on-absent-feature-2.rs:12:5 | LL | type Item = T; | ^^^^^^^^^^^^^^^^^ @@ -16,14 +16,6 @@ LL | type Item = T; = note: see issue #44265 for more information = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable -error: type-generic associated types are not yet implemented - --> $DIR/gat-dont-ice-on-absent-feature-2.rs:7:5 - | -LL | type Item; - | ^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/generic-associated-types/generic-associated-types-where.rs b/src/test/ui/generic-associated-types/generic-associated-types-where.rs index 589024e162166..1a94796535c14 100644 --- a/src/test/ui/generic-associated-types/generic-associated-types-where.rs +++ b/src/test/ui/generic-associated-types/generic-associated-types-where.rs @@ -9,11 +9,8 @@ use std::fmt::{Display, Debug}; trait Foo { type Assoc where Self: Sized; type Assoc2 where T: Display; - //~^ ERROR type-generic associated types are not yet implemented type Assoc3; - //~^ ERROR type-generic associated types are not yet implemented - type WithDefault<'a, T: Debug + 'a> = dyn Iterator; - //~^ ERROR type-generic associated types are not yet implemented + type WithDefault<'a, T: Debug + 'a>: ?Sized = dyn Iterator; type NoGenerics; } @@ -23,6 +20,7 @@ impl Foo for Bar { type Assoc = usize; type Assoc2 = Vec; type Assoc3 where T: Iterator = Vec; + //~^ impl has stricter requirements than trait type WithDefault<'a, T: Debug + 'a> = &'a dyn Iterator; type NoGenerics = ::std::cell::Cell; } diff --git a/src/test/ui/generic-associated-types/generic-associated-types-where.stderr b/src/test/ui/generic-associated-types/generic-associated-types-where.stderr index fb29b377a16e3..4d02f2c46a6d0 100644 --- a/src/test/ui/generic-associated-types/generic-associated-types-where.stderr +++ b/src/test/ui/generic-associated-types/generic-associated-types-where.stderr @@ -1,26 +1,12 @@ -error: type-generic associated types are not yet implemented - --> $DIR/generic-associated-types-where.rs:11:5 - | -LL | type Assoc2 where T: Display; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: type-generic associated types are not yet implemented - --> $DIR/generic-associated-types-where.rs:13:5 +error[E0276]: impl has stricter requirements than trait + --> $DIR/generic-associated-types-where.rs:22:5 | LL | type Assoc3; - | ^^^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: type-generic associated types are not yet implemented - --> $DIR/generic-associated-types-where.rs:15:5 - | -LL | type WithDefault<'a, T: Debug + 'a> = dyn Iterator; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information + | --------------- definition of `Assoc3` from trait +... +LL | type Assoc3 where T: Iterator = Vec; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: std::iter::Iterator` -error: aborting due to 3 previous errors +error: aborting due to previous error +For more information about this error, try `rustc --explain E0276`. diff --git a/src/test/ui/generic-associated-types/issue-47206-where-clause.rs b/src/test/ui/generic-associated-types/issue-47206-where-clause.rs index 53e350aacf88e..de2b978460f7f 100644 --- a/src/test/ui/generic-associated-types/issue-47206-where-clause.rs +++ b/src/test/ui/generic-associated-types/issue-47206-where-clause.rs @@ -5,13 +5,13 @@ trait Foo { type Assoc3; - //~^ type-generic associated types are not yet implemented } struct Bar; impl Foo for Bar { type Assoc3 where T: Iterator = Vec; + //~^ ERROR impl has stricter requirements than trait } fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr b/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr index c9c1a4753b0dd..bc5c40ff029f9 100644 --- a/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr +++ b/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr @@ -1,10 +1,12 @@ -error: type-generic associated types are not yet implemented - --> $DIR/issue-47206-where-clause.rs:7:5 +error[E0276]: impl has stricter requirements than trait + --> $DIR/issue-47206-where-clause.rs:13:5 | LL | type Assoc3; - | ^^^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information + | --------------- definition of `Assoc3` from trait +... +LL | type Assoc3 where T: Iterator = Vec; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: std::iter::Iterator` error: aborting due to previous error +For more information about this error, try `rustc --explain E0276`. diff --git a/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs b/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs index 1a79dbf2279a0..404be59a36d92 100644 --- a/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs +++ b/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs @@ -1,11 +1,14 @@ #![allow(incomplete_features)] #![feature(generic_associated_types)] -// FIXME(generic-associated-types) Investigate why this doesn't compile. +// check-pass trait Iterator { type Item<'a>: 'a; - //~^ ERROR the requirement `for<'a> ::Item<'a>: 'a` is not satisfied +} + +impl Iterator for () { + type Item<'a> = &'a (); } fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.stderr b/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.stderr deleted file mode 100644 index 4b06baa09ffbf..0000000000000 --- a/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error[E0280]: the requirement `for<'a> ::Item<'a>: 'a` is not satisfied - --> $DIR/issue-62326-parameter-out-of-range.rs:7:20 - | -LL | trait Iterator { - | -------- required by a bound in this -LL | type Item<'a>: 'a; - | ^^ required by this bound in `Iterator` - -error: aborting due to previous error - diff --git a/src/test/ui/generic-associated-types/issue-67424.rs b/src/test/ui/generic-associated-types/issue-67424.rs index 9b616b8abc2ee..fa35a3e8b04d1 100644 --- a/src/test/ui/generic-associated-types/issue-67424.rs +++ b/src/test/ui/generic-associated-types/issue-67424.rs @@ -7,7 +7,6 @@ trait Trait1 { trait Trait2 { type Type1: Trait1; //~^ ERROR: generic associated types are unstable - //~| ERROR: type-generic associated types are not yet implemented } fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-67424.stderr b/src/test/ui/generic-associated-types/issue-67424.stderr index 8b08c71759bb9..bbb7d56f5928e 100644 --- a/src/test/ui/generic-associated-types/issue-67424.stderr +++ b/src/test/ui/generic-associated-types/issue-67424.stderr @@ -7,14 +7,6 @@ LL | type Type1: Trait1; = note: see issue #44265 for more information = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable -error: type-generic associated types are not yet implemented - --> $DIR/issue-67424.rs:8:5 - | -LL | type Type1: Trait1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.rs b/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.rs new file mode 100644 index 0000000000000..71f9b2967dc58 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.rs @@ -0,0 +1,32 @@ +// Regression test for #68641 + +#![feature(generic_associated_types)] +//~^ WARNING the feature `generic_associated_types` is incomplete and may not + +trait UnsafeCopy { + type Item<'a>: Copy; + + fn copy<'a>(item: &Self::Item<'a>) -> Self::Item<'a> { + *item + } +} + +impl UnsafeCopy for T { + type Item<'a> = T; + //~^ ERROR the trait bound `T: std::marker::Copy` is not satisfied +} + +fn main() { + let mut s = String::from("Hello world!"); + + let copy = String::copy(&s); + + // Do we indeed point to the samme memory? + assert!(s.as_ptr() == copy.as_ptr()); + + // Any use of `copy` is certeinly UB after this + drop(s); + + // UB UB UB UB UB!! + println!("{}", copy); +} diff --git a/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr b/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr new file mode 100644 index 0000000000000..834bc3b7878f2 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr @@ -0,0 +1,26 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-68641-check-gat-bounds.rs:3:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 for more information + +error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied + --> $DIR/issue-68641-check-gat-bounds.rs:15:5 + | +LL | type Item<'a>: Copy; + | -------------------- required by `UnsafeCopy::Item` +... +LL | type Item<'a> = T; + | ^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | impl UnsafeCopy for T { + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs b/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs new file mode 100644 index 0000000000000..c99073c13284d --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs @@ -0,0 +1,21 @@ +// Regression test for #68642 + +#![feature(generic_associated_types)] +//~^ WARNING the feature `generic_associated_types` is incomplete and may not + +trait Fun { + type F<'a>: Fn() -> u32; + + fn callme<'a>(f: Self::F<'a>) -> u32 { + f() + } +} + +impl Fun for T { + type F<'a> = Self; + //~^ ERROR expected a `std::ops::Fn<()>` closure, found `T` +} + +fn main() { + usize>::callme(|| 1); +} diff --git a/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr b/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr new file mode 100644 index 0000000000000..89cc5dfd06018 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr @@ -0,0 +1,28 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-68642-broken-llvm-ir.rs:3:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 for more information + +error[E0277]: expected a `std::ops::Fn<()>` closure, found `T` + --> $DIR/issue-68642-broken-llvm-ir.rs:15:5 + | +LL | type F<'a>: Fn() -> u32; + | ------------------------ required by `Fun::F` +... +LL | type F<'a> = Self; + | ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T` + | + = help: the trait `std::ops::Fn<()>` is not implemented for `T` + = note: wrap the `T` in a closure with no arguments: `|| { /* code */ } +help: consider restricting type parameter `T` + | +LL | impl> Fun for T { + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic-associated-types/issue-68643-broken-mir.rs b/src/test/ui/generic-associated-types/issue-68643-broken-mir.rs new file mode 100644 index 0000000000000..24133e75cccee --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68643-broken-mir.rs @@ -0,0 +1,21 @@ +// Regression test for #68643 + +#![feature(generic_associated_types)] +//~^ WARNING the feature `generic_associated_types` is incomplete and may not + +trait Fun { + type F<'a>: Fn() -> u32; + + fn callme<'a>(f: Self::F<'a>) -> u32 { + f() + } +} + +impl Fun for T { + type F<'a> = Self; + //~^ ERROR expected a `std::ops::Fn<()>` closure, found `T` +} + +pub fn main() { + ::callme(|| {}); +} diff --git a/src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr b/src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr new file mode 100644 index 0000000000000..efd3287853f03 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr @@ -0,0 +1,28 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-68643-broken-mir.rs:3:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 for more information + +error[E0277]: expected a `std::ops::Fn<()>` closure, found `T` + --> $DIR/issue-68643-broken-mir.rs:15:5 + | +LL | type F<'a>: Fn() -> u32; + | ------------------------ required by `Fun::F` +... +LL | type F<'a> = Self; + | ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T` + | + = help: the trait `std::ops::Fn<()>` is not implemented for `T` + = note: wrap the `T` in a closure with no arguments: `|| { /* code */ } +help: consider restricting type parameter `T` + | +LL | impl> Fun for T { + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic-associated-types/issue-68644-codegen-selection.rs b/src/test/ui/generic-associated-types/issue-68644-codegen-selection.rs new file mode 100644 index 0000000000000..22620c61b8390 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68644-codegen-selection.rs @@ -0,0 +1,21 @@ +// Regression test for #68644 + +#![feature(generic_associated_types)] +//~^ WARNING the feature `generic_associated_types` is incomplete and may not + +trait Fun { + type F<'a>: Fn() -> u32; + + fn callme<'a>(f: Self::F<'a>) -> u32 { + f() + } +} + +impl Fun for T { + type F<'a> = Self; + //~^ ERROR expected a `std::ops::Fn<()>` closure, found `T` +} + +fn main() { + ::callme(0); +} diff --git a/src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr b/src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr new file mode 100644 index 0000000000000..5da924a512f00 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr @@ -0,0 +1,28 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-68644-codegen-selection.rs:3:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 for more information + +error[E0277]: expected a `std::ops::Fn<()>` closure, found `T` + --> $DIR/issue-68644-codegen-selection.rs:15:5 + | +LL | type F<'a>: Fn() -> u32; + | ------------------------ required by `Fun::F` +... +LL | type F<'a> = Self; + | ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T` + | + = help: the trait `std::ops::Fn<()>` is not implemented for `T` + = note: wrap the `T` in a closure with no arguments: `|| { /* code */ } +help: consider restricting type parameter `T` + | +LL | impl> Fun for T { + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs b/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs new file mode 100644 index 0000000000000..423b80e8476f4 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs @@ -0,0 +1,21 @@ +// Regression test for #68645 + +#![feature(generic_associated_types)] +//~^ WARNING the feature `generic_associated_types` is incomplete and may not + +trait Fun { + type F<'a>: Fn() -> u32; + + fn callme<'a>(f: Self::F<'a>) -> u32 { + f() + } +} + +impl Fun for T { + type F<'a> = Self; + //~^ ERROR expected a `std::ops::Fn<()>` closure, found `T` +} + +fn main() { + <&dyn Iterator>::callme(&std::iter::once(1)); +} diff --git a/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr b/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr new file mode 100644 index 0000000000000..12d84ab6a369b --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr @@ -0,0 +1,28 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-68645-codegen-fulfillment.rs:3:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 for more information + +error[E0277]: expected a `std::ops::Fn<()>` closure, found `T` + --> $DIR/issue-68645-codegen-fulfillment.rs:15:5 + | +LL | type F<'a>: Fn() -> u32; + | ------------------------ required by `Fun::F` +... +LL | type F<'a> = Self; + | ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T` + | + = help: the trait `std::ops::Fn<()>` is not implemented for `T` + = note: wrap the `T` in a closure with no arguments: `|| { /* code */ } +help: consider restricting type parameter `T` + | +LL | impl> Fun for T { + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic-associated-types/issue-68656-unsized-values.rs b/src/test/ui/generic-associated-types/issue-68656-unsized-values.rs new file mode 100644 index 0000000000000..4ccd42ba6432d --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68656-unsized-values.rs @@ -0,0 +1,22 @@ +// Regression test for #68656 + +#![feature(generic_associated_types)] +//~^ WARNING the feature `generic_associated_types` is incomplete and may not + +trait UnsafeCopy { + type Item<'a>: std::ops::Deref; + + fn bug<'a>(item: &Self::Item<'a>) -> () { + let x: T = **item; + &x as *const _; + } +} + +impl UnsafeCopy for T { + type Item<'a> = T; + //~^ ERROR type mismatch resolving `::Target == T` +} + +fn main() { + <&'static str>::bug(&""); +} diff --git a/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr b/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr new file mode 100644 index 0000000000000..e1ceeac3196a8 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr @@ -0,0 +1,30 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-68656-unsized-values.rs:3:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 for more information + +error[E0271]: type mismatch resolving `::Target == T` + --> $DIR/issue-68656-unsized-values.rs:16:5 + | +LL | type Item<'a>: std::ops::Deref; + | ------------------------------------------- required by `UnsafeCopy::Item` +... +LL | impl UnsafeCopy for T { + | - this type parameter +LL | type Item<'a> = T; + | ^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found associated type + | + = note: expected type parameter `T` + found associated type `::Target` +help: consider further restricting this bound + | +LL | impl> UnsafeCopy for T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/generic-associated-types/iterable.rs b/src/test/ui/generic-associated-types/iterable.rs index 105ab4a8adc38..600a69006c1ea 100644 --- a/src/test/ui/generic-associated-types/iterable.rs +++ b/src/test/ui/generic-associated-types/iterable.rs @@ -1,7 +1,7 @@ #![allow(incomplete_features)] #![feature(generic_associated_types)] -// FIXME(#30472) normalize enough to handle this. +// run-pass trait Iterable { type Item<'a> where Self: 'a; @@ -13,39 +13,35 @@ trait Iterable { // Impl for struct type impl Iterable for Vec { type Item<'a> where T: 'a = as Iterator>::Item; - //~^ ERROR type mismatch resolving type Iter<'a> where T: 'a = std::slice::Iter<'a, T>; fn iter<'a>(&'a self) -> Self::Iter<'a> { - //~^ ERROR type mismatch resolving - self.iter() + self[..].iter() } } // Impl for a primitive type impl Iterable for [T] { type Item<'a> where T: 'a = as Iterator>::Item; - //~^ ERROR type mismatch resolving type Iter<'a> where T: 'a = std::slice::Iter<'a, T>; fn iter<'a>(&'a self) -> Self::Iter<'a> { - //~^ ERROR type mismatch resolving self.iter() } } -fn make_iter<'a, I: Iterable>(it: &'a I) -> I::Iter<'a> { +fn make_iter<'a, I: Iterable + ?Sized>(it: &'a I) -> I::Iter<'a> { it.iter() } -fn get_first<'a, I: Iterable>(it: &'a I) -> Option> { +fn get_first<'a, I: Iterable + ?Sized>(it: &'a I) -> Option> { it.iter().next() } fn main() { let v = vec![1, 2, 3]; - assert_eq!(v, make_iter(&v).copied().collect()); - assert_eq!(v, make_iter(&*v).copied().collect()); - assert_eq!(1, get_first(&v)); - assert_eq!(1, get_first(&*v)); + assert_eq!(v, make_iter(&v).copied().collect::>()); + assert_eq!(v, make_iter(&*v).copied().collect::>()); + assert_eq!(Some(&1), get_first(&v)); + assert_eq!(Some(&1), get_first(&*v)); } diff --git a/src/test/ui/generic-associated-types/iterable.stderr b/src/test/ui/generic-associated-types/iterable.stderr deleted file mode 100644 index 6e75462122513..0000000000000 --- a/src/test/ui/generic-associated-types/iterable.stderr +++ /dev/null @@ -1,59 +0,0 @@ -error[E0271]: type mismatch resolving `for<'a> < as Iterable>::Iter<'a> as std::iter::Iterator>::Item == as Iterable>::Item<'a>` - --> $DIR/iterable.rs:15:33 - | -LL | type Item<'a> where T: 'a = as Iterator>::Item; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found associated type - | - = note: expected reference `&T` - found associated type ` as Iterable>::Item<'_>` - = help: consider constraining the associated type ` as Iterable>::Item<'_>` to `&_` - = 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:33 - | -LL | type Item<'a> where T: 'a = as Iterator>::Item; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found associated type - | - = note: expected reference `&T` - found associated type `<[T] as Iterable>::Item<'_>` - = help: consider constraining the associated type `<[T] as Iterable>::Item<'_>` to `&_` - = 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 - | -LL | trait Iterable { - | -------- required by a bound in this -LL | type Item<'a> where Self: 'a; -LL | type Iter<'a>: Iterator> where Self: 'a; - | --------------------- required by this bound in `Iterable` -... -LL | fn iter<'a>(&'a self) -> Self::Iter<'a> { - | ^^^^^^^^^^^^^^ expected associated type, found reference - | - = note: expected associated type ` as Iterable>::Item<'_>` - found reference `&T` - = help: consider constraining the associated type ` as Iterable>::Item<'_>` to `&_` or calling a method that returns ` as Iterable>::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:31:30 - | -LL | trait Iterable { - | -------- required by a bound in this -LL | type Item<'a> where Self: 'a; -LL | type Iter<'a>: Iterator> where Self: 'a; - | --------------------- required by this bound in `Iterable` -... -LL | fn iter<'a>(&'a self) -> Self::Iter<'a> { - | ^^^^^^^^^^^^^^ expected associated type, found reference - | - = note: expected associated type `<[T] as Iterable>::Item<'_>` - found reference `&T` - = help: consider constraining the associated type `<[T] as Iterable>::Item<'_>` to `&_` or calling a method that returns `<[T] as Iterable>::Item<'_>` - = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/generic-associated-types/missing-bounds.fixed b/src/test/ui/generic-associated-types/missing-bounds.fixed index 364d2388741b0..3ba7d043d0759 100644 --- a/src/test/ui/generic-associated-types/missing-bounds.fixed +++ b/src/test/ui/generic-associated-types/missing-bounds.fixed @@ -34,12 +34,11 @@ impl> Add for D { struct E(B); -impl Add for E where B: Add, B: std::ops::Add { - //~^ ERROR equality constraints are not yet supported in `where` clauses +impl Add for E where B: Add { type Output = Self; fn add(self, rhs: Self) -> Self { - Self(self.0 + rhs.0) //~ ERROR mismatched types + Self(self.0 + rhs.0) } } diff --git a/src/test/ui/generic-associated-types/missing-bounds.rs b/src/test/ui/generic-associated-types/missing-bounds.rs index ffafff5e9f586..962d2db9476bd 100644 --- a/src/test/ui/generic-associated-types/missing-bounds.rs +++ b/src/test/ui/generic-associated-types/missing-bounds.rs @@ -34,12 +34,11 @@ impl Add for D { struct E(B); -impl Add for E where ::Output = B { - //~^ ERROR equality constraints are not yet supported in `where` clauses +impl Add for E where B: Add { type Output = Self; fn add(self, rhs: Self) -> Self { - Self(self.0 + rhs.0) //~ ERROR mismatched types + Self(self.0 + rhs.0) } } diff --git a/src/test/ui/generic-associated-types/missing-bounds.stderr b/src/test/ui/generic-associated-types/missing-bounds.stderr index 50536fdaca96e..630ceac093ef2 100644 --- a/src/test/ui/generic-associated-types/missing-bounds.stderr +++ b/src/test/ui/generic-associated-types/missing-bounds.stderr @@ -1,15 +1,3 @@ -error: equality constraints are not yet supported in `where` clauses - --> $DIR/missing-bounds.rs:37:33 - | -LL | impl Add for E where ::Output = B { - | ^^^^^^^^^^^^^^^^^^^^^^ not supported - | - = note: see issue #20041 for more information -help: if `Output` is an associated type you're trying to set, use the associated type binding syntax - | -LL | impl Add for E where B: Add { - | ^^^^^^^^^^^^^^^^^^ - error[E0308]: mismatched types --> $DIR/missing-bounds.rs:11:11 | @@ -55,23 +43,7 @@ help: consider restricting type parameter `B` LL | impl> Add for D { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0308]: mismatched types - --> $DIR/missing-bounds.rs:42:14 - | -LL | impl Add for E where ::Output = B { - | - this type parameter -... -LL | Self(self.0 + rhs.0) - | ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type - | - = note: expected type parameter `B` - found associated type `::Output` -help: consider further restricting type parameter `B` - | -LL | impl Add for E where ::Output = B, B: std::ops::Add { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0308, E0369. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/generic-associated-types/parameter_number_and_kind.rs b/src/test/ui/generic-associated-types/parameter_number_and_kind.rs index 0edc5c48c01af..f4d09fc1539da 100644 --- a/src/test/ui/generic-associated-types/parameter_number_and_kind.rs +++ b/src/test/ui/generic-associated-types/parameter_number_and_kind.rs @@ -7,18 +7,14 @@ trait Foo { type B<'a, 'b>; type C; type D; - //~^ ERROR type-generic associated types are not yet implemented type E<'a, T>; - //~^ ERROR type-generic associated types are not yet implemented // Test parameters in default values type FOk = Self::E<'static, T>; - //~^ ERROR type-generic associated types are not yet implemented type FErr1 = Self::E<'static, 'static>; //~^ ERROR wrong number of lifetime arguments: expected 1, found 2 //~| ERROR wrong number of type arguments: expected 1, found 0 type FErr2 = Self::E<'static, T, u32>; - //~^ ERROR type-generic associated types are not yet implemented - //~| ERROR wrong number of type arguments: expected 1, found 2 + //~^ ERROR wrong number of type arguments: expected 1, found 2 } fn main() {} diff --git a/src/test/ui/generic-associated-types/parameter_number_and_kind.stderr b/src/test/ui/generic-associated-types/parameter_number_and_kind.stderr index 028ab72f48812..ed090e302cefa 100644 --- a/src/test/ui/generic-associated-types/parameter_number_and_kind.stderr +++ b/src/test/ui/generic-associated-types/parameter_number_and_kind.stderr @@ -1,53 +1,21 @@ -error: type-generic associated types are not yet implemented - --> $DIR/parameter_number_and_kind.rs:9:5 - | -LL | type D; - | ^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: type-generic associated types are not yet implemented - --> $DIR/parameter_number_and_kind.rs:11:5 - | -LL | type E<'a, T>; - | ^^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: type-generic associated types are not yet implemented - --> $DIR/parameter_number_and_kind.rs:14:5 - | -LL | type FOk = Self::E<'static, T>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: type-generic associated types are not yet implemented - --> $DIR/parameter_number_and_kind.rs:19:5 - | -LL | type FErr2 = Self::E<'static, T, u32>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - error[E0107]: wrong number of lifetime arguments: expected 1, found 2 - --> $DIR/parameter_number_and_kind.rs:16:35 + --> $DIR/parameter_number_and_kind.rs:13:35 | LL | type FErr1 = Self::E<'static, 'static>; | ^^^^^^^ unexpected lifetime argument error[E0107]: wrong number of type arguments: expected 1, found 0 - --> $DIR/parameter_number_and_kind.rs:16:18 + --> $DIR/parameter_number_and_kind.rs:13:18 | LL | type FErr1 = Self::E<'static, 'static>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 type argument error[E0107]: wrong number of type arguments: expected 1, found 2 - --> $DIR/parameter_number_and_kind.rs:19:41 + --> $DIR/parameter_number_and_kind.rs:16:41 | LL | type FErr2 = Self::E<'static, T, u32>; | ^^^ unexpected type argument -error: aborting due to 7 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/generic-associated-types/pointer_family.rs b/src/test/ui/generic-associated-types/pointer_family.rs index 1668759b4e39c..b322b752a1567 100644 --- a/src/test/ui/generic-associated-types/pointer_family.rs +++ b/src/test/ui/generic-associated-types/pointer_family.rs @@ -1,7 +1,7 @@ #![allow(incomplete_features)] #![feature(generic_associated_types)] -// FIXME(#44265): allow type-generic associated types. +// check-pass use std::rc::Rc; use std::sync::Arc; @@ -9,7 +9,6 @@ use std::ops::Deref; trait PointerFamily { type Pointer: Deref; - //~^ ERROR type-generic associated types are not yet implemented fn new(value: T) -> Self::Pointer; } diff --git a/src/test/ui/generic-associated-types/pointer_family.stderr b/src/test/ui/generic-associated-types/pointer_family.stderr deleted file mode 100644 index 83fe992fcb571..0000000000000 --- a/src/test/ui/generic-associated-types/pointer_family.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: type-generic associated types are not yet implemented - --> $DIR/pointer_family.rs:11:5 - | -LL | type Pointer: Deref; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: aborting due to previous error - diff --git a/src/test/ui/generic-associated-types/shadowing.rs b/src/test/ui/generic-associated-types/shadowing.rs index 5c308948bd3f8..44528ca1da36e 100644 --- a/src/test/ui/generic-associated-types/shadowing.rs +++ b/src/test/ui/generic-associated-types/shadowing.rs @@ -18,12 +18,10 @@ impl<'a> NoShadow<'a> for &'a u32 { trait ShadowT { type Bar; //~^ ERROR the name `T` is already used - //~| ERROR type-generic associated types are not yet implemented } trait NoShadowT { type Bar; // OK - //~^ ERROR type-generic associated types are not yet implemented } impl NoShadowT for Option { diff --git a/src/test/ui/generic-associated-types/shadowing.stderr b/src/test/ui/generic-associated-types/shadowing.stderr index 2d9a0d6fceb2d..d51c29080a0c9 100644 --- a/src/test/ui/generic-associated-types/shadowing.stderr +++ b/src/test/ui/generic-associated-types/shadowing.stderr @@ -7,7 +7,7 @@ LL | type Bar; | ^ already used error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters - --> $DIR/shadowing.rs:30:14 + --> $DIR/shadowing.rs:28:14 | LL | impl NoShadowT for Option { | - first use of `T` @@ -30,23 +30,7 @@ LL | impl<'a> NoShadow<'a> for &'a u32 { LL | type Bar<'a> = i32; | ^^ lifetime 'a already in scope -error: type-generic associated types are not yet implemented - --> $DIR/shadowing.rs:19:5 - | -LL | type Bar; - | ^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: type-generic associated types are not yet implemented - --> $DIR/shadowing.rs:25:5 - | -LL | type Bar; // OK - | ^^^^^^^^^^^^ - | - = note: for more information, see issue #44265 for more information - -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0403, E0496. For more information about an error, try `rustc --explain E0403`. diff --git a/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs new file mode 100644 index 0000000000000..7510c58d57489 --- /dev/null +++ b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs @@ -0,0 +1,22 @@ +#![allow(incomplete_features)] +#![feature(generic_associated_types)] + +trait ATy { + type Item<'a>: 'a; +} + +impl<'b> ATy for &'b () { + type Item<'a> = &'b (); + //~^ ERROR does not fulfill the required lifetime +} + +trait StaticTy { + type Item<'a>: 'static; +} + +impl StaticTy for () { + type Item<'a> = &'a (); + //~^ ERROR does not fulfill the required lifetime +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr new file mode 100644 index 0000000000000..5d612284a2187 --- /dev/null +++ b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr @@ -0,0 +1,23 @@ +error[E0477]: the type `&'b ()` does not fulfill the required lifetime + --> $DIR/unsatisfied-outlives-bound.rs:9:5 + | +LL | type Item<'a> = &'b (); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: type must outlive the lifetime `'a` as defined on the associated item at 9:15 + --> $DIR/unsatisfied-outlives-bound.rs:9:15 + | +LL | type Item<'a> = &'b (); + | ^^ + +error[E0477]: the type `&'a ()` does not fulfill the required lifetime + --> $DIR/unsatisfied-outlives-bound.rs:18:5 + | +LL | type Item<'a> = &'a (); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: type must satisfy the static lifetime + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0477`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr new file mode 100644 index 0000000000000..d5343566633d5 --- /dev/null +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr @@ -0,0 +1,14 @@ +error: higher-ranked subtype error + --> $DIR/hr-subtype.rs:45:13 + | +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | / check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32, +LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) } + | |_____________________________________________- 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 previous error + diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr index b91798fa12379..92a85825030c2 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr @@ -1,12 +1,12 @@ error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 + --> $DIR/hr-subtype.rs:45:26 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a + | ^^^^^^^^^^^ one type is more general than the other ... LL | / check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32, -LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) } - | |_________________________________________________________________________________________- in this macro invocation +LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) } + | |_____________________________________________- in this macro invocation | = note: expected enum `std::option::Option fn(&'a u32, &'b u32) -> &'a u32>` found enum `std::option::Option fn(&'a u32, &'a u32) -> &'a u32>` diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr index 45f53d4fe99db..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr @@ -1,17 +1,14 @@ -error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 +error: fatal error triggered by #[rustc_error] + --> $DIR/hr-subtype.rs:102:1 | -LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a -... -LL | / check! { bound_a_b_vs_bound_a: (for<'a,'b> fn(&'a u32, &'b u32), -LL | | for<'a> fn(&'a u32, &'a u32)) } - | |__________________________________________________________________- in this macro invocation - | - = note: expected enum `std::option::Option fn(&'a u32, &'b u32)>` - found enum `std::option::Option fn(&'a u32, &'a u32)>` - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) +LL | / fn main() { +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | |_^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr index 6aba6466fada5..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr @@ -1,11 +1,11 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/hr-subtype.rs:100:1 + --> $DIR/hr-subtype.rs:102:1 | LL | / fn main() { LL | | LL | | LL | | -LL | | +... | LL | | LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr index 6aba6466fada5..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr @@ -1,11 +1,11 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/hr-subtype.rs:100:1 + --> $DIR/hr-subtype.rs:102:1 | LL | / fn main() { LL | | LL | | LL | | -LL | | +... | LL | | LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.nll.stderr new file mode 100644 index 0000000000000..f115609396756 --- /dev/null +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.nll.stderr @@ -0,0 +1,14 @@ +error: higher-ranked subtype error + --> $DIR/hr-subtype.rs:45:13 + | +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32), +LL | | fn(&'x u32)) } + | |______________- 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 previous error + diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr index c3e4f6d2ed0c1..98f5bff732762 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr @@ -1,12 +1,12 @@ error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 + --> $DIR/hr-subtype.rs:45:26 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a + | ^^^^^^^^^^^ one type is more general than the other ... LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32), -LL | | fn(&'x u32)) } - | |___________________________________________- in this macro invocation +LL | | fn(&'x u32)) } + | |______________- in this macro invocation | = note: expected enum `std::option::Option fn(&'a u32)>` found enum `std::option::Option` diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr index 4d7b86027f564..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr @@ -1,17 +1,14 @@ -error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 +error: fatal error triggered by #[rustc_error] + --> $DIR/hr-subtype.rs:102:1 | -LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a -... -LL | / check! { bound_co_a_b_vs_bound_co_a: (for<'a,'b> fn(Co<'a>, Co<'b>), -LL | | for<'a> fn(Co<'a>, Co<'a>)) } - | |______________________________________________________________________- in this macro invocation - | - = note: expected enum `std::option::Option fn(Co<'a>, Co<'b>)>` - found enum `std::option::Option fn(Co<'a>, Co<'a>)>` - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) +LL | / fn main() { +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | |_^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr index 7f0a4197dd7fe..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr @@ -1,17 +1,14 @@ -error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 +error: fatal error triggered by #[rustc_error] + --> $DIR/hr-subtype.rs:102:1 | -LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a -... -LL | / check! { bound_co_a_co_b_ret_contra_a: (for<'a,'b> fn(Co<'a>, Co<'b>) -> Contra<'a>, -LL | | for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>) } - | |______________________________________________________________________________________- in this macro invocation - | - = note: expected enum `std::option::Option fn(Co<'a>, Co<'b>) -> Contra<'a>>` - found enum `std::option::Option fn(Co<'a>, Co<'a>) -> Contra<'a>>` - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) +LL | / fn main() { +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | |_^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr index 6aba6466fada5..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr @@ -1,11 +1,11 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/hr-subtype.rs:100:1 + --> $DIR/hr-subtype.rs:102:1 | LL | / fn main() { LL | | LL | | LL | | -LL | | +... | LL | | LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr index c12e543a44e79..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr @@ -1,17 +1,14 @@ -error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 +error: fatal error triggered by #[rustc_error] + --> $DIR/hr-subtype.rs:102:1 | -LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a -... -LL | / check! { bound_contra_a_contra_b_ret_co_a: (for<'a,'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>, -LL | | for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>) } - | |______________________________________________________________________________________________- in this macro invocation - | - = note: expected enum `std::option::Option fn(Contra<'a>, Contra<'b>) -> Co<'a>>` - found enum `std::option::Option fn(Contra<'a>, Contra<'a>) -> Co<'a>>` - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) +LL | / fn main() { +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | |_^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.nll.stderr new file mode 100644 index 0000000000000..4541c462ee056 --- /dev/null +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.nll.stderr @@ -0,0 +1,26 @@ +error: higher-ranked subtype error + --> $DIR/hr-subtype.rs:45:13 + | +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>), +LL | | for<'a> fn(Inv<'a>, Inv<'a>)) } + | |__________________________________- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: higher-ranked subtype error + --> $DIR/hr-subtype.rs:45:13 + | +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>), +LL | | for<'a> fn(Inv<'a>, Inv<'a>)) } + | |__________________________________- 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 2 previous errors + diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr index 460356856bd56..100ba6ac27e25 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr @@ -1,12 +1,12 @@ error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 + --> $DIR/hr-subtype.rs:45:26 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a + | ^^^^^^^^^^^ one type is more general than the other ... LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>), -LL | | for<'a> fn(Inv<'a>, Inv<'a>)) } - | |__________________________________________________________________________- in this macro invocation +LL | | for<'a> fn(Inv<'a>, Inv<'a>)) } + | |__________________________________- in this macro invocation | = note: expected enum `std::option::Option fn(Inv<'a>, Inv<'b>)>` found enum `std::option::Option fn(Inv<'a>, Inv<'a>)>` diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr index 6aba6466fada5..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr @@ -1,11 +1,11 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/hr-subtype.rs:100:1 + --> $DIR/hr-subtype.rs:102:1 | LL | / fn main() { LL | | LL | | LL | | -LL | | +... | LL | | LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr index 6b5e7a5a6345a..af5cf41be0a48 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr @@ -1,33 +1,33 @@ error: lifetime may not live long enough - --> $DIR/hr-subtype.rs:33:13 + --> $DIR/hr-subtype.rs:39:13 | -LL | fn subtype<'x,'y:'x,'z:'y>() { - | -- -- lifetime `'y` defined here +LL | fn subtype<'x, 'y: 'x, 'z: 'y>() { + | -- -- lifetime `'y` defined here | | | lifetime `'x` defined here LL | gimme::<$t2>(None::<$t1>); | ^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'x` must outlive `'y` ... LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), -LL | | fn(Inv<'y>)) } - | |__________________________________________________- in this macro invocation +LL | | fn(Inv<'y>)) } + | |______________- in this macro invocation | = help: consider adding the following bound: `'x: 'y` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: lifetime may not live long enough - --> $DIR/hr-subtype.rs:39:13 + --> $DIR/hr-subtype.rs:45:13 | -LL | fn supertype<'x,'y:'x,'z:'y>() { - | -- -- lifetime `'y` defined here +LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { + | -- -- lifetime `'y` defined here | | | lifetime `'x` defined here LL | gimme::<$t1>(None::<$t2>); | ^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'x` must outlive `'y` ... LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), -LL | | fn(Inv<'y>)) } - | |__________________________________________________- in this macro invocation +LL | | fn(Inv<'y>)) } + | |______________- in this macro invocation | = help: consider adding the following bound: `'x: 'y` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr index fc3643306e628..3c8af20e50cef 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr @@ -1,65 +1,65 @@ error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:33:26 + --> $DIR/hr-subtype.rs:39:26 | LL | gimme::<$t2>(None::<$t1>); | ^^^^^^^^^^^ lifetime mismatch ... LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), -LL | | fn(Inv<'y>)) } - | |__________________________________________________- in this macro invocation +LL | | fn(Inv<'y>)) } + | |______________- in this macro invocation | = note: expected enum `std::option::Option)>` found enum `std::option::Option)>` -note: the lifetime `'x` as defined on the function body at 32:20... - --> $DIR/hr-subtype.rs:32:20 +note: the lifetime `'x` as defined on the function body at 38:20... + --> $DIR/hr-subtype.rs:38:20 | -LL | fn subtype<'x,'y:'x,'z:'y>() { +LL | fn subtype<'x, 'y: 'x, 'z: 'y>() { | ^^ ... LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), -LL | | fn(Inv<'y>)) } - | |__________________________________________________- in this macro invocation -note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 32:23 - --> $DIR/hr-subtype.rs:32:23 +LL | | fn(Inv<'y>)) } + | |______________- in this macro invocation +note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 38:24 + --> $DIR/hr-subtype.rs:38:24 | -LL | fn subtype<'x,'y:'x,'z:'y>() { - | ^^ +LL | fn subtype<'x, 'y: 'x, 'z: 'y>() { + | ^^ ... LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), -LL | | fn(Inv<'y>)) } - | |__________________________________________________- in this macro invocation +LL | | fn(Inv<'y>)) } + | |______________- in this macro invocation = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 + --> $DIR/hr-subtype.rs:45:26 | LL | gimme::<$t1>(None::<$t2>); | ^^^^^^^^^^^ lifetime mismatch ... LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), -LL | | fn(Inv<'y>)) } - | |__________________________________________________- in this macro invocation +LL | | fn(Inv<'y>)) } + | |______________- in this macro invocation | = note: expected enum `std::option::Option)>` found enum `std::option::Option)>` -note: the lifetime `'x` as defined on the function body at 38:22... - --> $DIR/hr-subtype.rs:38:22 +note: the lifetime `'x` as defined on the function body at 44:22... + --> $DIR/hr-subtype.rs:44:22 | -LL | fn supertype<'x,'y:'x,'z:'y>() { +LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { | ^^ ... LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), -LL | | fn(Inv<'y>)) } - | |__________________________________________________- in this macro invocation -note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 38:25 - --> $DIR/hr-subtype.rs:38:25 +LL | | fn(Inv<'y>)) } + | |______________- in this macro invocation +note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 44:26 + --> $DIR/hr-subtype.rs:44:26 | -LL | fn supertype<'x,'y:'x,'z:'y>() { - | ^^ +LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { + | ^^ ... LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), -LL | | fn(Inv<'y>)) } - | |__________________________________________________- in this macro invocation +LL | | fn(Inv<'y>)) } + | |______________- 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 2 previous errors diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr index 6aba6466fada5..948375566104b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr @@ -1,11 +1,11 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/hr-subtype.rs:100:1 + --> $DIR/hr-subtype.rs:102:1 | LL | / fn main() { LL | | LL | | LL | | -LL | | +... | LL | | LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.nll.stderr index 7c0770924daaa..75d7e0e46b72a 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.nll.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.nll.stderr @@ -1,16 +1,16 @@ error: lifetime may not live long enough - --> $DIR/hr-subtype.rs:39:13 + --> $DIR/hr-subtype.rs:45:13 | -LL | fn supertype<'x,'y:'x,'z:'y>() { - | -- -- lifetime `'y` defined here +LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { + | -- -- lifetime `'y` defined here | | | lifetime `'x` defined here LL | gimme::<$t1>(None::<$t2>); | ^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'x` must outlive `'y` ... LL | / check! { free_x_vs_free_y: (fn(&'x u32), -LL | | fn(&'y u32)) } - | |__________________________________________- in this macro invocation +LL | | fn(&'y u32)) } + | |______________- in this macro invocation | = help: consider adding the following bound: `'x: 'y` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr index 0dde27788f629..7b4cdd4a419b4 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr @@ -1,33 +1,33 @@ error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 + --> $DIR/hr-subtype.rs:45:26 | LL | gimme::<$t1>(None::<$t2>); | ^^^^^^^^^^^ lifetime mismatch ... LL | / check! { free_x_vs_free_y: (fn(&'x u32), -LL | | fn(&'y u32)) } - | |__________________________________________- in this macro invocation +LL | | fn(&'y u32)) } + | |______________- in this macro invocation | = note: expected enum `std::option::Option` found enum `std::option::Option` -note: the lifetime `'x` as defined on the function body at 38:22... - --> $DIR/hr-subtype.rs:38:22 +note: the lifetime `'x` as defined on the function body at 44:22... + --> $DIR/hr-subtype.rs:44:22 | -LL | fn supertype<'x,'y:'x,'z:'y>() { +LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { | ^^ ... LL | / check! { free_x_vs_free_y: (fn(&'x u32), -LL | | fn(&'y u32)) } - | |__________________________________________- in this macro invocation -note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 38:25 - --> $DIR/hr-subtype.rs:38:25 +LL | | fn(&'y u32)) } + | |______________- in this macro invocation +note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 44:26 + --> $DIR/hr-subtype.rs:44:26 | -LL | fn supertype<'x,'y:'x,'z:'y>() { - | ^^ +LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { + | ^^ ... LL | / check! { free_x_vs_free_y: (fn(&'x u32), -LL | | fn(&'y u32)) } - | |__________________________________________- in this macro invocation +LL | | fn(&'y u32)) } + | |______________- 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 previous error diff --git a/src/test/ui/hr-subtype/hr-subtype.rs b/src/test/ui/hr-subtype/hr-subtype.rs index b31f198bd97bf..ad9500eedca93 100644 --- a/src/test/ui/hr-subtype/hr-subtype.rs +++ b/src/test/ui/hr-subtype/hr-subtype.rs @@ -18,60 +18,62 @@ // revisions: bound_inv_a_b_vs_bound_inv_a // revisions: bound_a_b_ret_a_vs_bound_a_ret_a -fn gimme(_: Option) { } +fn gimme(_: Option) {} -struct Inv<'a> { x: *mut &'a u32 } +struct Inv<'a> { + x: *mut &'a u32, +} -struct Co<'a> { x: fn(&'a u32) } +struct Co<'a> { + x: fn(&'a u32), +} -struct Contra<'a> { x: &'a u32 } +struct Contra<'a> { + x: &'a u32, +} macro_rules! check { ($rev:ident: ($t1:ty, $t2:ty)) => { #[cfg($rev)] - fn subtype<'x,'y:'x,'z:'y>() { + fn subtype<'x, 'y: 'x, 'z: 'y>() { gimme::<$t2>(None::<$t1>); //[free_inv_x_vs_free_inv_y]~^ ERROR } #[cfg($rev)] - fn supertype<'x,'y:'x,'z:'y>() { + fn supertype<'x, 'y: 'x, 'z: 'y>() { gimme::<$t1>(None::<$t2>); //[bound_a_vs_free_x]~^ ERROR //[free_x_vs_free_y]~^^ ERROR //[bound_inv_a_b_vs_bound_inv_a]~^^^ ERROR //[bound_a_b_ret_a_vs_bound_a_ret_a]~^^^^ ERROR //[free_inv_x_vs_free_inv_y]~^^^^^ ERROR - //[bound_a_b_vs_bound_a]~^^^^^^ ERROR mismatched types - //[bound_co_a_co_b_ret_contra_a]~^^^^^^^ ERROR - //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^ ERROR - //[bound_co_a_b_vs_bound_co_a]~^^^^^^^^^ ERROR } - } + }; } // If both have bound regions, they are equivalent, regardless of // variant. check! { bound_a_vs_bound_a: (for<'a> fn(&'a u32), - for<'a> fn(&'a u32)) } +for<'a> fn(&'a u32)) } check! { bound_a_vs_bound_b: (for<'a> fn(&'a u32), - for<'b> fn(&'b u32)) } +for<'b> fn(&'b u32)) } check! { bound_inv_a_vs_bound_inv_b: (for<'a> fn(Inv<'a>), - for<'b> fn(Inv<'b>)) } +for<'b> fn(Inv<'b>)) } check! { bound_co_a_vs_bound_co_b: (for<'a> fn(Co<'a>), - for<'b> fn(Co<'b>)) } +for<'b> fn(Co<'b>)) } // Bound is a subtype of free. check! { bound_a_vs_free_x: (for<'a> fn(&'a u32), - fn(&'x u32)) } +fn(&'x u32)) } // Two free regions are relatable if subtyping holds. check! { free_x_vs_free_x: (fn(&'x u32), - fn(&'x u32)) } +fn(&'x u32)) } check! { free_x_vs_free_y: (fn(&'x u32), - fn(&'y u32)) } +fn(&'y u32)) } check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), - fn(Inv<'y>)) } +fn(Inv<'y>)) } // Somewhat surprisingly, a fn taking two distinct bound lifetimes and // a fn taking one bound lifetime can be interchangeable, but only if @@ -82,25 +84,29 @@ check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), // intersection; // - if we are contravariant, then 'a can be inferred to 'static. check! { bound_a_b_vs_bound_a: (for<'a,'b> fn(&'a u32, &'b u32), - for<'a> fn(&'a u32, &'a u32)) } +for<'a> fn(&'a u32, &'a u32)) } check! { bound_co_a_b_vs_bound_co_a: (for<'a,'b> fn(Co<'a>, Co<'b>), - for<'a> fn(Co<'a>, Co<'a>)) } +for<'a> fn(Co<'a>, Co<'a>)) } check! { bound_contra_a_contra_b_ret_co_a: (for<'a,'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>, - for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>) } +for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>) } check! { bound_co_a_co_b_ret_contra_a: (for<'a,'b> fn(Co<'a>, Co<'b>) -> Contra<'a>, - for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>) } +for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>) } // If we make those lifetimes invariant, then the two types are not interchangeable. check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>), - for<'a> fn(Inv<'a>, Inv<'a>)) } +for<'a> fn(Inv<'a>, Inv<'a>)) } check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32, - for<'a> fn(&'a u32, &'a u32) -> &'a u32) } +for<'a> fn(&'a u32, &'a u32) -> &'a u32) } #[rustc_error] fn main() { -//[bound_a_vs_bound_a]~^ ERROR fatal error triggered by #[rustc_error] -//[bound_a_vs_bound_b]~^^ ERROR fatal error triggered by #[rustc_error] -//[bound_inv_a_vs_bound_inv_b]~^^^ ERROR fatal error triggered by #[rustc_error] -//[bound_co_a_vs_bound_co_b]~^^^^ ERROR fatal error triggered by #[rustc_error] -//[free_x_vs_free_x]~^^^^^ ERROR fatal error triggered by #[rustc_error] + //[bound_a_vs_bound_a]~^ ERROR fatal error triggered by #[rustc_error] + //[bound_a_vs_bound_b]~^^ ERROR fatal error triggered by #[rustc_error] + //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR fatal error triggered by #[rustc_error] + //[bound_co_a_vs_bound_co_b]~^^^^ ERROR fatal error triggered by #[rustc_error] + //[free_x_vs_free_x]~^^^^^ ERROR fatal error triggered by #[rustc_error] + //[bound_co_a_b_vs_bound_co_a]~^^^^^^ ERROR + //[bound_co_a_co_b_ret_contra_a]~^^^^^^^ ERROR + //[bound_a_b_vs_bound_a]~^^^^^^^^ ERROR + //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR } diff --git a/src/test/ui/hr-subtype/return-static.rs b/src/test/ui/hr-subtype/return-static.rs new file mode 100644 index 0000000000000..6455854f34db8 --- /dev/null +++ b/src/test/ui/hr-subtype/return-static.rs @@ -0,0 +1,13 @@ +// check-pass + +fn make() -> T { + panic!() +} + +fn take(x: T) {} + +fn main() { + let x: for<'a> fn(&'a u32) -> _ = make(); + let y: &'static u32 = x(&22); + take:: fn(&'b u32) -> &'b u32>(x); +} diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.nll.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.nll.stderr new file mode 100644 index 0000000000000..f290a93326f37 --- /dev/null +++ b/src/test/ui/hrtb/hrtb-conflate-regions.nll.stderr @@ -0,0 +1,14 @@ +error: higher-ranked subtype error + --> $DIR/hrtb-conflate-regions.rs:27:10 + | +LL | fn b() { want_foo2::(); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/hrtb-conflate-regions.rs:27:10 + | +LL | fn b() { want_foo2::(); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.stderr index 7250935ea296b..45573814d13c0 100644 --- a/src/test/ui/hrtb/hrtb-conflate-regions.stderr +++ b/src/test/ui/hrtb/hrtb-conflate-regions.stderr @@ -1,17 +1,16 @@ -error[E0277]: the trait bound `for<'a, 'b> SomeStruct: Foo<(&'a isize, &'b isize)>` is not satisfied - --> $DIR/hrtb-conflate-regions.rs:27:22 +error: implementation of `Foo` is not general enough + --> $DIR/hrtb-conflate-regions.rs:27:10 | -LL | fn want_foo2() - | --------- required by a bound in this -LL | where T : for<'a,'b> Foo<(&'a isize, &'b isize)> - | -------------------------------------- required by this bound in `want_foo2` +LL | / trait Foo { +LL | | fn foo(&self, x: X) { } +LL | | } + | |_- trait `Foo` defined here ... -LL | fn b() { want_foo2::(); } - | ^^^^^^^^^^ the trait `for<'a, 'b> Foo<(&'a isize, &'b isize)>` is not implemented for `SomeStruct` +LL | fn b() { want_foo2::(); } + | ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | - = help: the following implementations were found: - > + = note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but `SomeStruct` actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.nll.stderr b/src/test/ui/hrtb/hrtb-exists-forall-fn.nll.stderr new file mode 100644 index 0000000000000..11390d9e2d265 --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/hrtb-exists-forall-fn.rs:17:12 + | +LL | let _: for<'b> fn(&'b u32) = foo(); + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr index 328e98657effb..9914783d9767d 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr @@ -2,9 +2,7 @@ error[E0308]: mismatched types --> $DIR/hrtb-exists-forall-fn.rs:17:34 | LL | let _: for<'b> fn(&'b u32) = foo(); - | ------------------- ^^^^^ expected concrete lifetime, found bound lifetime parameter 'b - | | - | expected due to this + | ^^^^^ one type is more general than the other | = note: expected fn pointer `for<'b> fn(&'b u32)` found fn pointer `fn(&u32)` diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.nll.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.nll.stderr new file mode 100644 index 0000000000000..a4c3ffd1f6c08 --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5 + | +LL | foo::<()>(); + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs index 4c1d4d28a09b0..921061916fc95 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs @@ -32,5 +32,5 @@ fn main() { // NB. *However*, the reinstated leak-check gives an error here. foo::<()>(); - //~^ ERROR not satisfied + //~^ ERROR implementation of `Trait` is not general enough } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr index 7a7285d3d76e0..fe8209d054c8a 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr @@ -1,18 +1,14 @@ -error[E0277]: the trait bound `(): Trait fn(&'b u32)>` is not satisfied - --> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:11 +error: implementation of `Trait` is not general enough + --> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5 | -LL | fn foo() - | --- required by a bound in this -LL | where -LL | T: Trait fn(&'b u32)>, - | -------------------------- required by this bound in `foo` +LL | trait Trait {} + | ----------------- trait `Trait` defined here ... LL | foo::<()>(); - | ^^ the trait `Trait fn(&'b u32)>` is not implemented for `()` + | ^^^^^^^^^ implementation of `Trait` is not general enough | - = help: the following implementations were found: - <() as Trait> + = note: `()` must implement `Trait fn(&'b u32)>` + = note: ...but `()` actually implements `Trait`, for some specific lifetime `'0` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs index 95b57d6c5bb5e..f95496a6c3cc0 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs @@ -2,6 +2,8 @@ // // In particular, we test this pattern in trait solving, where it is not connected // to any part of the source code. +// +// check-pass trait Trait {} @@ -30,9 +32,6 @@ fn main() { // - `?b: ?a` -- solveable if `?b` is inferred to `'static` // - So the subtyping check succeeds, somewhat surprisingly. // This is because we can use `'static`. - // - // NB. *However*, the reinstated leak-check gives an error here. foo::<()>(); - //~^ ERROR not satisfied } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr deleted file mode 100644 index 1e335f9ee9610..0000000000000 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0277]: the trait bound `(): Trait fn(fn(&'b u32))>` is not satisfied - --> $DIR/hrtb-exists-forall-trait-covariant.rs:36:11 - | -LL | fn foo() - | --- required by a bound in this -LL | where -LL | T: Trait fn(fn(&'b u32))>, - | ------------------------------ required by this bound in `foo` -... -LL | foo::<()>(); - | ^^ the trait `Trait fn(fn(&'b u32))>` is not implemented for `()` - | - = help: the following implementations were found: - <() as Trait> - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.nll.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.nll.stderr new file mode 100644 index 0000000000000..e2a399b2faa9d --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5 + | +LL | foo::<()>(); + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs index 827a68beee8bd..b1b7ec6bcf1a5 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs @@ -25,5 +25,5 @@ fn main() { // yielding `fn(&!b u32)`, in a fresh universe U1 // - So we get `?a = !b` but the universe U0 assigned to `?a` cannot name `!b`. - foo::<()>(); //~ ERROR not satisfied + foo::<()>(); //~ ERROR implementation of `Trait` is not general enough } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr index 9174ea4d8419d..720e2276d5343 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr @@ -1,18 +1,14 @@ -error[E0277]: the trait bound `(): Trait fn(std::cell::Cell<&'b u32>)>` is not satisfied - --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:11 +error: implementation of `Trait` is not general enough + --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5 | -LL | fn foo() - | --- required by a bound in this -LL | where -LL | T: Trait fn(Cell<&'b u32>)>, - | -------------------------------- required by this bound in `foo` +LL | trait Trait {} + | ----------------- trait `Trait` defined here ... LL | foo::<()>(); - | ^^ the trait `Trait fn(std::cell::Cell<&'b u32>)>` is not implemented for `()` + | ^^^^^^^^^ implementation of `Trait` is not general enough | - = help: the following implementations were found: - <() as Trait)>> + = note: `()` must implement `Trait fn(std::cell::Cell<&'b u32>)>` + = note: ...but `()` actually implements `Trait)>`, for some specific lifetime `'0` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-just-for-static.nll.stderr b/src/test/ui/hrtb/hrtb-just-for-static.nll.stderr new file mode 100644 index 0000000000000..8901a1b46817d --- /dev/null +++ b/src/test/ui/hrtb/hrtb-just-for-static.nll.stderr @@ -0,0 +1,24 @@ +error: higher-ranked subtype error + --> $DIR/hrtb-just-for-static.rs:24:5 + | +LL | want_hrtb::() + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: lifetime may not live long enough + --> $DIR/hrtb-just-for-static.rs:30:5 + | +LL | fn give_some<'a>() { + | -- lifetime `'a` defined here +LL | want_hrtb::<&'a u32>() + | ^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + | + = help: consider replacing `'a` with `'static` + +error: higher-ranked subtype error + --> $DIR/hrtb-just-for-static.rs:30:5 + | +LL | want_hrtb::<&'a u32>() + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/hrtb/hrtb-just-for-static.stderr b/src/test/ui/hrtb/hrtb-just-for-static.stderr index 4fa404624775b..5e3014317f5bc 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.stderr +++ b/src/test/ui/hrtb/hrtb-just-for-static.stderr @@ -1,31 +1,30 @@ -error[E0277]: the trait bound `for<'a> StaticInt: Foo<&'a isize>` is not satisfied - --> $DIR/hrtb-just-for-static.rs:24:17 +error: implementation of `Foo` is not general enough + --> $DIR/hrtb-just-for-static.rs:24:5 | -LL | fn want_hrtb() - | --------- required by a bound in this -LL | where T : for<'a> Foo<&'a isize> - | ---------------------- required by this bound in `want_hrtb` +LL | / trait Foo { +LL | | fn foo(&self, x: X) { } +LL | | } + | |_- trait `Foo` defined here ... -LL | want_hrtb::() - | ^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `StaticInt` +LL | want_hrtb::() + | ^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | - = help: the following implementations were found: - > + = note: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`... + = note: ...but `StaticInt` actually implements `Foo<&'1 isize>`, for some specific lifetime `'1` -error[E0277]: the trait bound `for<'a> &'a u32: Foo<&'a isize>` is not satisfied - --> $DIR/hrtb-just-for-static.rs:30:17 +error: implementation of `Foo` is not general enough + --> $DIR/hrtb-just-for-static.rs:30:5 | -LL | fn want_hrtb() - | --------- required by a bound in this -LL | where T : for<'a> Foo<&'a isize> - | ---------------------- required by this bound in `want_hrtb` +LL | / trait Foo { +LL | | fn foo(&self, x: X) { } +LL | | } + | |_- trait `Foo` defined here ... -LL | want_hrtb::<&'a u32>() - | ^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `&'a u32` +LL | want_hrtb::<&'a u32>() + | ^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | - = help: the following implementations were found: - <&'a u32 as Foo<&'a isize>> + = note: `Foo<&'0 isize>` would have to be implemented for the type `&'a u32`, for any lifetime `'0`... + = note: ...but `Foo<&'1 isize>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/issue-30786.migrate.stderr b/src/test/ui/hrtb/issue-30786.migrate.stderr index c0e3fd3cf4679..90a7cadca41b7 100644 --- a/src/test/ui/hrtb/issue-30786.migrate.stderr +++ b/src/test/ui/hrtb/issue-30786.migrate.stderr @@ -1,17 +1,43 @@ -error: implementation of `Stream` is not general enough - --> $DIR/issue-30786.rs:108:22 +error[E0599]: no method named `filterx` found for struct `Map` in the current scope + --> $DIR/issue-30786.rs:128:22 | -LL | / pub trait Stream { -LL | | type Item; -LL | | fn next(self) -> Option; -LL | | } - | |_- trait `Stream` defined here +LL | pub struct Map { + | -------------------- + | | + | method `filterx` not found for this + | doesn't satisfy `_: StreamExt` ... -LL | let map = source.map(|x: &_| x); - | ^^^ implementation of `Stream` is not general enough +LL | let filter = map.filterx(|x: &_| true); + | ^^^^^^^ method not found in `Map` | - = note: `Stream` would have to be implemented for the type `&'0 mut Map`, for any lifetime `'0`... - = note: ...but `Stream` is actually implemented for the type `&'1 mut Map`, for some specific lifetime `'1` + = note: the method `filterx` exists but the following trait bounds were not satisfied: + `&'a mut Map: Stream` + which is required by `Map: StreamExt` + `&'a mut &Map: Stream` + which is required by `&Map: StreamExt` + `&'a mut &mut Map: Stream` + which is required by `&mut Map: StreamExt` -error: aborting due to previous error +error[E0599]: no method named `countx` found for struct `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` in the current scope + --> $DIR/issue-30786.rs:141:24 + | +LL | pub struct Filter { + | ----------------------- + | | + | method `countx` not found for this + | doesn't satisfy `_: StreamExt` +... +LL | let count = filter.countx(); + | ^^^^^^ method not found in `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` + | + = note: the method `countx` exists but the following trait bounds were not satisfied: + `&'a mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` + which is required by `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` + `&'a mut &Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` + which is required by `&Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` + `&'a mut &mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` + which is required by `&mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/hrtb/issue-30786.nll.stderr b/src/test/ui/hrtb/issue-30786.nll.stderr index c736c5479f848..90a7cadca41b7 100644 --- a/src/test/ui/hrtb/issue-30786.nll.stderr +++ b/src/test/ui/hrtb/issue-30786.nll.stderr @@ -1,56 +1,43 @@ -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:108:15 - | -LL | let map = source.map(|x: &_| x); - | ^^^^^^^^^^^^^^^^^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:114:18 - | -LL | let filter = map.filter(|x: &_| true); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:114:18 - | -LL | let filter = map.filter(|x: &_| true); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:114:18 - | -LL | let filter = map.filter(|x: &_| true); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:114:18 - | -LL | let filter = map.filter(|x: &_| true); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:119:17 - | -LL | let count = filter.count(); // Assert that we still have a valid stream. - | ^^^^^^^^^^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:119:17 - | -LL | let count = filter.count(); // Assert that we still have a valid stream. - | ^^^^^^^^^^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:119:17 - | -LL | let count = filter.count(); // Assert that we still have a valid stream. - | ^^^^^^^^^^^^^^ - -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:119:17 - | -LL | let count = filter.count(); // Assert that we still have a valid stream. - | ^^^^^^^^^^^^^^ - -error: aborting due to 9 previous errors - +error[E0599]: no method named `filterx` found for struct `Map` in the current scope + --> $DIR/issue-30786.rs:128:22 + | +LL | pub struct Map { + | -------------------- + | | + | method `filterx` not found for this + | doesn't satisfy `_: StreamExt` +... +LL | let filter = map.filterx(|x: &_| true); + | ^^^^^^^ method not found in `Map` + | + = note: the method `filterx` exists but the following trait bounds were not satisfied: + `&'a mut Map: Stream` + which is required by `Map: StreamExt` + `&'a mut &Map: Stream` + which is required by `&Map: StreamExt` + `&'a mut &mut Map: Stream` + which is required by `&mut Map: StreamExt` + +error[E0599]: no method named `countx` found for struct `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` in the current scope + --> $DIR/issue-30786.rs:141:24 + | +LL | pub struct Filter { + | ----------------------- + | | + | method `countx` not found for this + | doesn't satisfy `_: StreamExt` +... +LL | let count = filter.countx(); + | ^^^^^^ method not found in `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` + | + = note: the method `countx` exists but the following trait bounds were not satisfied: + `&'a mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` + which is required by `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` + `&'a mut &Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` + which is required by `&Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` + `&'a mut &mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream` + which is required by `&mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/hrtb/issue-30786.rs b/src/test/ui/hrtb/issue-30786.rs index c656f84306536..8ce5c090b543e 100644 --- a/src/test/ui/hrtb/issue-30786.rs +++ b/src/test/ui/hrtb/issue-30786.rs @@ -16,7 +16,7 @@ //[nll]compile-flags: -Z borrowck=mir -pub trait Stream { //[migrate]~ NOTE trait `Stream` defined here +pub trait Stream { type Item; fn next(self) -> Option; } @@ -37,8 +37,9 @@ pub struct Map { } impl<'a, A, F, T> Stream for &'a mut Map -where &'a mut A: Stream, - F: FnMut(<&'a mut A as Stream>::Item) -> T, +where + &'a mut A: Stream, + F: FnMut(<&'a mut A as Stream>::Item) -> T, { type Item = T; fn next(self) -> Option { @@ -55,8 +56,9 @@ pub struct Filter { } impl<'a, A, F, T> Stream for &'a mut Filter -where for<'b> &'b mut A: Stream, // <---- BAD - F: FnMut(&T) -> bool, +where + for<'b> &'b mut A: Stream, // <---- BAD + F: FnMut(&T) -> bool, { type Item = <&'a mut A as Stream>::Item; fn next(self) -> Option { @@ -69,29 +71,29 @@ where for<'b> &'b mut A: Stream, // <---- BAD } } -pub trait StreamExt where for<'b> &'b mut Self: Stream { - fn map(self, func: F) -> Map - where Self: Sized, - for<'a> &'a mut Map: Stream, +pub trait StreamExt +where + for<'b> &'b mut Self: Stream, +{ + fn mapx(self, func: F) -> Map + where + Self: Sized, + for<'a> &'a mut Map: Stream, { - Map { - func: func, - stream: self, - } + Map { func: func, stream: self } } - fn filter(self, func: F) -> Filter - where Self: Sized, - for<'a> &'a mut Filter: Stream, + fn filterx(self, func: F) -> Filter + where + Self: Sized, + for<'a> &'a mut Filter: Stream, { - Filter { - func: func, - stream: self, - } + Filter { func: func, stream: self } } - fn count(mut self) -> usize - where Self: Sized, + fn countx(mut self) -> usize + where + Self: Sized, { let mut count = 0; while let Some(_) = self.next() { @@ -101,24 +103,44 @@ pub trait StreamExt where for<'b> &'b mut Self: Stream { } } -impl StreamExt for T where for<'a> &'a mut T: Stream { } +impl StreamExt for T where for<'a> &'a mut T: Stream {} -fn main() { +fn identity(x: &T) -> &T { + x +} + +fn variant1() { let source = Repeat(10); - let map = source.map(|x: &_| x); - //[nll]~^ ERROR higher-ranked subtype error - //[migrate]~^^ ERROR implementation of `Stream` is not general enough - //[migrate]~| NOTE `Stream` would have to be implemented for the type `&'0 mut Map - //[migrate]~| NOTE but `Stream` is actually implemented for the type `&'1 - //[migrate]~| NOTE implementation of `Stream` is not general enough - let filter = map.filter(|x: &_| true); - //[nll]~^ ERROR higher-ranked subtype error - //[nll]~| ERROR higher-ranked subtype error - //[nll]~| ERROR higher-ranked subtype error - //[nll]~| ERROR higher-ranked subtype error - let count = filter.count(); // Assert that we still have a valid stream. - //[nll]~^ ERROR higher-ranked subtype error - //[nll]~| ERROR higher-ranked subtype error - //[nll]~| ERROR higher-ranked subtype error - //[nll]~| ERROR higher-ranked subtype error + + // Here, the call to `mapx` returns a type `T` to which `StreamExt` + // is not applicable, because `for<'b> &'b mut T: Stream`) doesn't hold. + // + // More concretely, the type `T` is `Map`, and + // the where clause doesn't hold because the signature of the + // closure gets inferred to a signature like `|&'_ Stream| -> &'_` + // for some specific `'_`, rather than a more generic + // signature. + // + // Why *exactly* we opt for this signature is a bit unclear to me, + // we deduce it somehow from a reuqirement that `Map: Stream` I + // guess. + let map = source.mapx(|x: &_| x); + let filter = map.filterx(|x: &_| true); + //[migrate]~^ ERROR no method named `filterx` + //[nll]~^^ ERROR no method named `filterx` } + +fn variant2() { + let source = Repeat(10); + + // Here, we use a function, which is not subject to the vagaries + // of closure signature inference. In this case, we get the error + // on `countx` as, I think, the test originally expected. + let map = source.mapx(identity); + let filter = map.filterx(|x: &_| true); + let count = filter.countx(); + //[migrate]~^ ERROR no method named `countx` + //[nll]~^^ ERROR no method named `countx` +} + +fn main() {} diff --git a/src/test/ui/hrtb/issue-46989.nll.stderr b/src/test/ui/hrtb/issue-46989.nll.stderr new file mode 100644 index 0000000000000..6c127b92d97d1 --- /dev/null +++ b/src/test/ui/hrtb/issue-46989.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/issue-46989.rs:38:5 + | +LL | assert_foo::(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/hrtb/issue-46989.rs b/src/test/ui/hrtb/issue-46989.rs index 2c85905545807..4a09f4be156e2 100644 --- a/src/test/ui/hrtb/issue-46989.rs +++ b/src/test/ui/hrtb/issue-46989.rs @@ -28,15 +28,13 @@ // // holds because 'a can be instantiated to 'empty. -trait Foo { +trait Foo {} -} - -impl Foo for fn(A) { } +impl Foo for fn(A) {} fn assert_foo() {} fn main() { assert_foo::(); - //~^ ERROR the trait bound `for<'r> fn(&'r i32): Foo` is not satisfied + //~^ ERROR implementation of `Foo` is not general enough } diff --git a/src/test/ui/hrtb/issue-46989.stderr b/src/test/ui/hrtb/issue-46989.stderr index 0a7382c4dd818..c85c37ff9239e 100644 --- a/src/test/ui/hrtb/issue-46989.stderr +++ b/src/test/ui/hrtb/issue-46989.stderr @@ -1,15 +1,14 @@ -error[E0277]: the trait bound `for<'r> fn(&'r i32): Foo` is not satisfied - --> $DIR/issue-46989.rs:40:18 +error: implementation of `Foo` is not general enough + --> $DIR/issue-46989.rs:38:5 | -LL | fn assert_foo() {} - | --- required by this bound in `assert_foo` +LL | trait Foo {} + | ------------ trait `Foo` defined here ... LL | assert_foo::(); - | ^^^^^^^^ the trait `Foo` is not implemented for `for<'r> fn(&'r i32)` + | ^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | - = help: the following implementations were found: - + = note: `Foo` would have to be implemented for the type `for<'r> fn(&'r i32)` + = note: ...but `Foo` is actually implemented for the type `fn(&'0 i32)`, for some specific lifetime `'0` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hygiene/globs.stderr b/src/test/ui/hygiene/globs.stderr index 8f6b7aca8fda8..6dcbf055a8bb7 100644 --- a/src/test/ui/hygiene/globs.stderr +++ b/src/test/ui/hygiene/globs.stderr @@ -23,14 +23,10 @@ LL | | } | |_____- in this macro invocation | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider importing one of these items +help: consider importing this function | LL | use bar::g; | -LL | use foo::test2::test::g; - | -LL | use foo::test::g; - | error[E0425]: cannot find function `f` in this scope --> $DIR/globs.rs:61:12 diff --git a/src/test/ui/hygiene/unpretty-debug.stdout b/src/test/ui/hygiene/unpretty-debug.stdout index fc5ed724e3c67..acd852103cae3 100644 --- a/src/test/ui/hygiene/unpretty-debug.stdout +++ b/src/test/ui/hygiene/unpretty-debug.stdout @@ -18,12 +18,8 @@ fn y /* 0#0 */() { } Expansions: 0: parent: ExpnId(0), call_site_ctxt: #0, kind: Root 1: parent: ExpnId(0), call_site_ctxt: #0, kind: Macro(Bang, "foo") -2: parent: ExpnId(0), call_site_ctxt: #1, kind: Desugaring(Operator) -3: parent: ExpnId(0), call_site_ctxt: #1, kind: Desugaring(Operator) SyntaxContexts: #0: parent: #0, outer_mark: (ExpnId(0), Opaque) #1: parent: #0, outer_mark: (ExpnId(1), SemiTransparent) -#2: parent: #1, outer_mark: (ExpnId(2), Transparent) -#3: parent: #1, outer_mark: (ExpnId(3), Transparent) */ diff --git a/src/test/ui/impl-trait/equality-rpass.rs b/src/test/ui/impl-trait/equality-rpass.rs index 05c9e4173b0e4..607b4a49661cc 100644 --- a/src/test/ui/impl-trait/equality-rpass.rs +++ b/src/test/ui/impl-trait/equality-rpass.rs @@ -1,6 +1,6 @@ // run-pass -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait Foo: std::fmt::Debug + Eq {} diff --git a/src/test/ui/impl-trait/equality-rpass.stderr b/src/test/ui/impl-trait/equality-rpass.stderr new file mode 100644 index 0000000000000..1abf05dca8270 --- /dev/null +++ b/src/test/ui/impl-trait/equality-rpass.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/equality-rpass.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/impl-trait/equality.rs b/src/test/ui/impl-trait/equality.rs index 14b0eeb739ae5..828b5aac896be 100644 --- a/src/test/ui/impl-trait/equality.rs +++ b/src/test/ui/impl-trait/equality.rs @@ -1,4 +1,4 @@ -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait Foo: Copy + ToString {} diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index 9178358b60a9c..628dfb13d4ca8 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -1,3 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/equality.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + error[E0308]: mismatched types --> $DIR/equality.rs:15:5 | @@ -24,7 +33,7 @@ LL | n + sum_to(n - 1) | = help: the trait `std::ops::Add` is not implemented for `u32` -error: aborting due to 2 previous errors +error: aborting due to 2 previous errors; 1 warning emitted Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/equality2.rs b/src/test/ui/impl-trait/equality2.rs index abce8c8c204bd..2e325867da86e 100644 --- a/src/test/ui/impl-trait/equality2.rs +++ b/src/test/ui/impl-trait/equality2.rs @@ -1,4 +1,4 @@ -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait Foo: Copy + ToString {} diff --git a/src/test/ui/impl-trait/equality2.stderr b/src/test/ui/impl-trait/equality2.stderr index 2454c218ffc8b..1780931efc541 100644 --- a/src/test/ui/impl-trait/equality2.stderr +++ b/src/test/ui/impl-trait/equality2.stderr @@ -1,3 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/equality2.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + error[E0308]: mismatched types --> $DIR/equality2.rs:25:18 | @@ -58,6 +67,6 @@ LL | x.0); = note: expected opaque type `impl Foo` (`i32`) found opaque type `impl Foo` (`u32`) -error: aborting due to 4 previous errors +error: aborting due to 4 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr index ca9ca8a9debe2..3b339c5c3d7fc 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr @@ -53,7 +53,15 @@ LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } | help: add explicit lifetime `'a` to the type of `x`: `&'a i32` error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:33:69 + --> $DIR/must_outlive_least_region_or_bound.rs:30:24 + | +LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } + | - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'1` must outlive `'static` + | | + | let's call the lifetime of this reference `'1` + +error: lifetime may not live long enough + --> $DIR/must_outlive_least_region_or_bound.rs:37:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` @@ -62,7 +70,7 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } = help: consider replacing `'a` with `'static` error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:38:61 + --> $DIR/must_outlive_least_region_or_bound.rs:42:61 | LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { | -- -- lifetime `'b` defined here ^^^^^^^^^^^^^^^^ opaque type requires that `'b` must outlive `'a` @@ -72,14 +80,14 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32 = help: consider adding the following bound: `'b: 'a` error[E0310]: the parameter type `T` may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:43:51 + --> $DIR/must_outlive_least_region_or_bound.rs:47:51 | LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { | ^^^^^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `T: 'static`... -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors Some errors have detailed explanations: E0310, E0621. For more information about an error, try `rustc --explain E0310`. diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs index 837244b022721..9bf86fa66cded 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs @@ -27,6 +27,10 @@ fn elided4(x: &i32) -> Box { Box::new(x) } fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } //~^ ERROR cannot infer an appropriate lifetime +fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } +//~^ ERROR cannot infer an appropriate lifetime +//~| ERROR cannot infer an appropriate lifetime + trait LifetimeTrait<'a> {} impl<'a> LifetimeTrait<'a> for &'a i32 {} diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index e1fa4f02b6fcf..ffadcaae08e05 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -87,13 +87,48 @@ LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } | help: add explicit lifetime `'a` to the type of `x`: `&'a i32` error[E0759]: cannot infer an appropriate lifetime - --> $DIR/must_outlive_least_region_or_bound.rs:33:69 + --> $DIR/must_outlive_least_region_or_bound.rs:30:65 + | +LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } + | ---- this data with an anonymous lifetime `'_`... ^ ...is captured here, requiring it to live as long as `'static` + | +help: to declare that the trait object captures data from argument `x`, you can add an explicit `'_` lifetime bound + | +LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } + | ^^^^ +help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'_` lifetime bound + | +LL | fn elided5(x: &i32) -> (Box, impl Debug + '_) { (Box::new(x), x) } + | ^^^^ + +error[E0759]: cannot infer an appropriate lifetime + --> $DIR/must_outlive_least_region_or_bound.rs:30:69 + | +LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } + | ---- this data with an anonymous lifetime `'_`... ^ ...is captured here... + | +note: ...and is required to live as long as `'static` here + --> $DIR/must_outlive_least_region_or_bound.rs:30:41 + | +LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } + | ^^^^^^^^^^ +help: to declare that the trait object captures data from argument `x`, you can add an explicit `'_` lifetime bound + | +LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } + | ^^^^ +help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'_` lifetime bound + | +LL | fn elided5(x: &i32) -> (Box, impl Debug + '_) { (Box::new(x), x) } + | ^^^^ + +error[E0759]: cannot infer an appropriate lifetime + --> $DIR/must_outlive_least_region_or_bound.rs:37:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | ------- this data with lifetime `'a`... ^ ...is captured here... | note: ...and is required to live as long as `'static` here - --> $DIR/must_outlive_least_region_or_bound.rs:33:34 + --> $DIR/must_outlive_least_region_or_bound.rs:37:34 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -107,7 +142,7 @@ LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x | ^^^^^^^^^^^^ error[E0623]: lifetime mismatch - --> $DIR/must_outlive_least_region_or_bound.rs:38:61 + --> $DIR/must_outlive_least_region_or_bound.rs:42:61 | LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { | ------- ^^^^^^^^^^^^^^^^ @@ -116,7 +151,7 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32 | this parameter and the return type are declared with different lifetimes... error[E0310]: the parameter type `T` may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:43:51 + --> $DIR/must_outlive_least_region_or_bound.rs:47:51 | LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { | -- ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds @@ -181,7 +216,7 @@ help: alternatively, add an explicit `'static` bound to this reference LL | fn explicit4<'a>(x: &'static i32) -> Box { Box::new(x) } | ^^^^^^^^^^^^ -error: aborting due to 12 previous errors +error: aborting due to 14 previous errors Some errors have detailed explanations: E0310, E0621, E0623, E0759. For more information about an error, try `rustc --explain E0310`. 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 b5135b53e1890..3cd4d0dd391af 100644 --- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr +++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr @@ -49,14 +49,6 @@ LL | use foo::Bar; error[E0599]: no method named `method` found for struct `std::rc::Rc<&mut std::boxed::Box<&char>>` in the current scope --> $DIR/no-method-suggested-traits.rs:32:43 | -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 -... LL | std::rc::Rc::new(&mut Box::new(&'a')).method(); | ^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&char>>` | @@ -83,16 +75,6 @@ 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/infinite/infinite-instantiation.rs b/src/test/ui/infinite/infinite-instantiation.rs index 6f53680f7c81d..9fee01c1ba623 100644 --- a/src/test/ui/infinite/infinite-instantiation.rs +++ b/src/test/ui/infinite/infinite-instantiation.rs @@ -1,9 +1,3 @@ -// -// We get an error message at the top of file (dummy span). -// This is not helpful, but also kind of annoying to prevent, -// so for now just live with it. -// This test case was originally for issue #2258. - // build-fail trait ToOpt: Sized { @@ -23,11 +17,9 @@ impl ToOpt for Option { } fn function(counter: usize, t: T) { -//~^ ERROR reached the recursion limit while instantiating `function:: 0 { function(counter - 1, t.to_option()); - // FIXME(#4287) Error message should be here. It should be - // a type error to instantiate `test` at a type other than T. + //~^ ERROR reached the recursion limit while instantiating `function::>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` - --> $DIR/infinite-instantiation.rs:25:1 + --> $DIR/infinite-instantiation.rs:21:9 + | +LL | function(counter - 1, t.to_option()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `function` defined here + --> $DIR/infinite-instantiation.rs:19:1 | LL | / fn function(counter: usize, t: T) { -LL | | LL | | if counter > 0 { LL | | function(counter - 1, t.to_option()); -... | +LL | | LL | | } LL | | } | |_^ diff --git a/src/test/ui/issues/issue-10412.stderr b/src/test/ui/issues/issue-10412.stderr index 888576c43365f..d7a4bf4f21f18 100644 --- a/src/test/ui/issues/issue-10412.stderr +++ b/src/test/ui/issues/issue-10412.stderr @@ -57,6 +57,10 @@ LL | impl<'self> Serializable for &'self str { | = help: the trait `std::marker::Sized` is not implemented for `str` = note: to learn more, visit +help: consider relaxing the implicit `Sized` restriction + | +LL | trait Serializable<'self, T: ?Sized> { + | ^^^^^^^^ error: aborting due to 9 previous errors diff --git a/src/test/ui/issues/issue-12127.stderr b/src/test/ui/issues/issue-12127.stderr index b759aa45e3eb7..2283b1275d018 100644 --- a/src/test/ui/issues/issue-12127.stderr +++ b/src/test/ui/issues/issue-12127.stderr @@ -2,15 +2,10 @@ error[E0382]: use of moved value: `f` --> $DIR/issue-12127.rs:11:9 | LL | f(); - | --- `f` moved due to this call + | - value moved here LL | f(); | ^ value used here after move | -note: this value implements `FnOnce`, which causes it to be moved when called - --> $DIR/issue-12127.rs:10:9 - | -LL | f(); - | ^ = note: move occurs because `f` has type `[closure@$DIR/issue-12127.rs:8:24: 8:41 x:std::boxed::Box]`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17718-const-bad-values.rs b/src/test/ui/issues/issue-17718-const-bad-values.rs index 9355c8ab15256..49023f18ddbfb 100644 --- a/src/test/ui/issues/issue-17718-const-bad-values.rs +++ b/src/test/ui/issues/issue-17718-const-bad-values.rs @@ -1,10 +1,10 @@ const C1: &'static mut [usize] = &mut []; -//~^ ERROR: references in constants may only refer to immutable values +//~^ ERROR: mutable references are not allowed in constants static mut S: usize = 3; const C2: &'static mut usize = unsafe { &mut S }; //~^ ERROR: constants cannot refer to statics //~| ERROR: constants cannot refer to statics -//~| ERROR: references in constants may only refer to immutable values +//~| ERROR: mutable references are not allowed in constants fn main() {} diff --git a/src/test/ui/issues/issue-17718-const-bad-values.stderr b/src/test/ui/issues/issue-17718-const-bad-values.stderr index 688efcdd022eb..7c50978d4ebb8 100644 --- a/src/test/ui/issues/issue-17718-const-bad-values.stderr +++ b/src/test/ui/issues/issue-17718-const-bad-values.stderr @@ -1,11 +1,8 @@ -error[E0658]: references in constants may only refer to immutable values +error[E0764]: mutable references are not allowed in constants --> $DIR/issue-17718-const-bad-values.rs:1:34 | LL | const C1: &'static mut [usize] = &mut []; - | ^^^^^^^ constants require immutable values - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + | ^^^^^^^ `&mut` is only allowed in `const fn` error[E0013]: constants cannot refer to statics --> $DIR/issue-17718-const-bad-values.rs:5:46 @@ -23,16 +20,13 @@ LL | const C2: &'static mut usize = unsafe { &mut S }; | = help: consider extracting the value of the `static` to a `const`, and referring to that -error[E0658]: references in constants may only refer to immutable values +error[E0764]: mutable references are not allowed in constants --> $DIR/issue-17718-const-bad-values.rs:5:41 | LL | const C2: &'static mut usize = unsafe { &mut S }; - | ^^^^^^ constants require immutable values - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + | ^^^^^^ `&mut` is only allowed in `const fn` error: aborting due to 4 previous errors -Some errors have detailed explanations: E0013, E0658. +Some errors have detailed explanations: E0013, E0764. For more information about an error, try `rustc --explain E0013`. diff --git a/src/test/ui/issues/issue-1866.rs b/src/test/ui/issues/issue-1866.rs index e4fe26800eff3..668baefa5e4ad 100644 --- a/src/test/ui/issues/issue-1866.rs +++ b/src/test/ui/issues/issue-1866.rs @@ -1,6 +1,7 @@ // build-pass #![allow(dead_code)] #![allow(non_camel_case_types)] +#![warn(clashing_extern_decl)] // pretty-expanded FIXME #23616 @@ -20,6 +21,7 @@ mod b { use super::rust_task; extern { pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool; + //~^ WARN `rust_task_is_unwinding` redeclared with a different signature } } } diff --git a/src/test/ui/issues/issue-1866.stderr b/src/test/ui/issues/issue-1866.stderr new file mode 100644 index 0000000000000..13c08ebd373ed --- /dev/null +++ b/src/test/ui/issues/issue-1866.stderr @@ -0,0 +1,19 @@ +warning: `rust_task_is_unwinding` redeclared with a different signature + --> $DIR/issue-1866.rs:23:13 + | +LL | pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool; + | ------------------------------------------------------------ `rust_task_is_unwinding` previously declared here +... +LL | pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | +note: the lint level is defined here + --> $DIR/issue-1866.rs:4:9 + | +LL | #![warn(clashing_extern_decl)] + | ^^^^^^^^^^^^^^^^^^^^ + = note: expected `unsafe extern "C" fn(*const usize) -> bool` + found `unsafe extern "C" fn(*const bool) -> bool` + +warning: 1 warning emitted + diff --git a/src/test/ui/issues/issue-18919.stderr b/src/test/ui/issues/issue-18919.stderr index 1ea40d0728ed1..383cdd4979ad9 100644 --- a/src/test/ui/issues/issue-18919.stderr +++ b/src/test/ui/issues/issue-18919.stderr @@ -9,6 +9,13 @@ LL | enum Option { | = help: the trait `std::marker::Sized` is not implemented for `dyn for<'r> std::ops::Fn(&'r isize) -> isize` = note: to learn more, visit +help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` + --> $DIR/issue-18919.rs:7:13 + | +LL | enum Option { + | ^ this could be changed to `T: ?Sized`... +LL | Some(T), + | - ...if indirection was used here: `Box` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-23046.rs b/src/test/ui/issues/issue-23046.rs index a68369616d8b6..75be4a11efd22 100644 --- a/src/test/ui/issues/issue-23046.rs +++ b/src/test/ui/issues/issue-23046.rs @@ -14,7 +14,7 @@ pub fn let_<'var, VAR, F: for<'v> Fn(Expr<'v, VAR>) -> Expr<'v, VAR>> } fn main() { - let ex = |x| { //~ ERROR type annotations needed - let_(add(x,x), |y| { + let ex = |x| { + let_(add(x,x), |y| { //~ ERROR type annotations needed let_(add(x, x), |x|x)})}; } diff --git a/src/test/ui/issues/issue-23046.stderr b/src/test/ui/issues/issue-23046.stderr index 12b2eb48e7eaa..77555fce7c460 100644 --- a/src/test/ui/issues/issue-23046.stderr +++ b/src/test/ui/issues/issue-23046.stderr @@ -1,8 +1,13 @@ -error[E0282]: type annotations needed for `Expr<'_, VAR>` - --> $DIR/issue-23046.rs:17:15 +error[E0282]: type annotations needed for the closure `fn(Expr<'_, _>) -> Expr<'_, _>` + --> $DIR/issue-23046.rs:18:9 | -LL | let ex = |x| { - | ^ consider giving this closure parameter the explicit type `Expr<'_, VAR>`, where the type parameter `VAR` is specified +LL | let_(add(x,x), |y| { + | ^^^^ cannot infer type for type parameter `VAR` declared on the function `let_` + | +help: give this closure an explicit return type without `_` placeholders + | +LL | let_(add(x, x), |x|-> Expr<'_, _> { x })})}; + | ^^^^^^^^^^^^^^^^ ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-23281.stderr b/src/test/ui/issues/issue-23281.stderr index 3b4b8997a7009..cffa52361696c 100644 --- a/src/test/ui/issues/issue-23281.stderr +++ b/src/test/ui/issues/issue-23281.stderr @@ -9,6 +9,13 @@ LL | struct Vec { | = help: the trait `std::marker::Sized` is not implemented for `(dyn std::ops::Fn() + 'static)` = note: to learn more, visit +help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` + --> $DIR/issue-23281.rs:8:12 + | +LL | struct Vec { + | ^ this could be changed to `T: ?Sized`... +LL | t: T, + | - ...if indirection was used here: `Box` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-25826.rs b/src/test/ui/issues/issue-25826.rs index 36a69cf4c22ff..d1093c205798a 100644 --- a/src/test/ui/issues/issue-25826.rs +++ b/src/test/ui/issues/issue-25826.rs @@ -1,6 +1,6 @@ fn id(t: T) -> T { t } fn main() { const A: bool = unsafe { id:: as *const () < id:: as *const () }; - //~^ ERROR comparing raw pointers inside constant + //~^ ERROR pointers cannot be reliably compared during const eval println!("{}", A); } diff --git a/src/test/ui/issues/issue-25826.stderr b/src/test/ui/issues/issue-25826.stderr index 3a5a6b509ba9d..67d1b3ab9bed6 100644 --- a/src/test/ui/issues/issue-25826.stderr +++ b/src/test/ui/issues/issue-25826.stderr @@ -1,12 +1,10 @@ -error[E0658]: comparing raw pointers inside constant +error: pointers cannot be reliably compared during const eval. --> $DIR/issue-25826.rs:3:30 | LL | const A: bool = unsafe { id:: as *const () < id:: as *const () }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #53020 for more information - = help: add `#![feature(const_compare_raw_pointers)]` 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/issues/issue-26545.rs b/src/test/ui/issues/issue-26545.rs new file mode 100644 index 0000000000000..5652ee7470605 --- /dev/null +++ b/src/test/ui/issues/issue-26545.rs @@ -0,0 +1,12 @@ +mod foo { + pub struct B(pub ()); +} + +mod baz { + fn foo() { + B(()); + //~^ ERROR cannot find function, tuple struct or tuple variant `B` in this scope [E0425] + } +} + +fn main() {} diff --git a/src/test/ui/issues/issue-26545.stderr b/src/test/ui/issues/issue-26545.stderr new file mode 100644 index 0000000000000..d3c86692501d6 --- /dev/null +++ b/src/test/ui/issues/issue-26545.stderr @@ -0,0 +1,14 @@ +error[E0425]: cannot find function, tuple struct or tuple variant `B` in this scope + --> $DIR/issue-26545.rs:7:9 + | +LL | B(()); + | ^ not found in this scope + | +help: consider importing this tuple struct + | +LL | use foo::B; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/issues/issue-33941.rs b/src/test/ui/issues/issue-33941.rs index 4fb805b37e03f..ccaa6334856b4 100644 --- a/src/test/ui/issues/issue-33941.rs +++ b/src/test/ui/issues/issue-33941.rs @@ -3,5 +3,4 @@ use std::collections::HashMap; fn main() { for _ in HashMap::new().iter().cloned() {} //~ ERROR type mismatch //~^ ERROR type mismatch - //~| ERROR type mismatch } diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr index 20335d2cdd684..734ae78f362db 100644 --- a/src/test/ui/issues/issue-33941.stderr +++ b/src/test/ui/issues/issue-33941.stderr @@ -17,16 +17,6 @@ LL | for _ in HashMap::new().iter().cloned() {} found reference `&_` = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Cloned>` -error[E0271]: type mismatch resolving ` as std::iter::Iterator>::Item == &_` - --> $DIR/issue-33941.rs:4:14 - | -LL | for _ in HashMap::new().iter().cloned() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference - | - = note: expected tuple `(&_, &_)` - found reference `&_` - = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Cloned>` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/issues/issue-34721.stderr b/src/test/ui/issues/issue-34721.stderr index b4cc1a0aa7eb2..6cfed20f43a04 100644 --- a/src/test/ui/issues/issue-34721.stderr +++ b/src/test/ui/issues/issue-34721.stderr @@ -5,19 +5,14 @@ LL | pub fn baz(x: T) -> T { | - move occurs because `x` has type `T`, which does not implement the `Copy` trait LL | if 0 == 1 { LL | bar::bar(x.zero()) - | ------ `x` moved due to this method call + | - value moved here LL | } else { LL | x.zero() - | ------ `x` moved due to this method call + | - value moved here LL | }; LL | x.zero() | ^ value used here after move | -note: this function consumes the receiver `self` by taking ownership of it, which moves `x` - --> $DIR/issue-34721.rs:4:13 - | -LL | fn zero(self) -> Self; - | ^^^^ help: consider further restricting this bound | LL | pub fn baz(x: T) -> T { diff --git a/src/test/ui/issues/issue-35376.rs b/src/test/ui/issues/issue-35376.rs index eb139ec4d7f43..cc35213b93d68 100644 --- a/src/test/ui/issues/issue-35376.rs +++ b/src/test/ui/issues/issue-35376.rs @@ -1,5 +1,6 @@ // check-pass #![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete fn main() {} diff --git a/src/test/ui/issues/issue-35376.stderr b/src/test/ui/issues/issue-35376.stderr new file mode 100644 index 0000000000000..06c31f3bae062 --- /dev/null +++ b/src/test/ui/issues/issue-35376.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-35376.rs:2:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/issues/issue-35675.rs b/src/test/ui/issues/issue-35675.rs index 7876811a9ac39..683761667d40a 100644 --- a/src/test/ui/issues/issue-35675.rs +++ b/src/test/ui/issues/issue-35675.rs @@ -33,7 +33,7 @@ fn qux() -> Some { fn main() {} mod x { - enum Enum { + pub enum Enum { Variant1, Variant2(), Variant3(usize), diff --git a/src/test/ui/issues/issue-38091.rs b/src/test/ui/issues/issue-38091.rs index 00aa810f8308c..a84391b94d1de 100644 --- a/src/test/ui/issues/issue-38091.rs +++ b/src/test/ui/issues/issue-38091.rs @@ -1,5 +1,5 @@ -// run-pass #![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete trait Iterate<'a> { type Ty: Valid; @@ -7,6 +7,7 @@ trait Iterate<'a> { } impl<'a, T> Iterate<'a> for T where T: Check { default type Ty = (); + //~^ ERROR the trait bound `(): Valid` is not satisfied default fn iterate(self) {} } diff --git a/src/test/ui/issues/issue-38091.stderr b/src/test/ui/issues/issue-38091.stderr new file mode 100644 index 0000000000000..81beec8026314 --- /dev/null +++ b/src/test/ui/issues/issue-38091.stderr @@ -0,0 +1,21 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-38091.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +error[E0277]: the trait bound `(): Valid` is not satisfied + --> $DIR/issue-38091.rs:9:5 + | +LL | type Ty: Valid; + | --------------- required by `Iterate::Ty` +... +LL | default type Ty = (); + | ^^^^^^^^^^^^^^^^^^^^^ the trait `Valid` is not implemented for `()` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-40000.nll.stderr b/src/test/ui/issues/issue-40000.nll.stderr new file mode 100644 index 0000000000000..f673fbae8b79c --- /dev/null +++ b/src/test/ui/issues/issue-40000.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/issue-40000.rs:6:9 + | +LL | foo(bar); + | ^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/issues/issue-40000.stderr b/src/test/ui/issues/issue-40000.stderr index 983fdb13083a1..3eb3482ac910e 100644 --- a/src/test/ui/issues/issue-40000.stderr +++ b/src/test/ui/issues/issue-40000.stderr @@ -2,10 +2,10 @@ error[E0308]: mismatched types --> $DIR/issue-40000.rs:6:9 | LL | foo(bar); - | ^^^ expected concrete lifetime, found bound lifetime parameter + | ^^^ one type is more general than the other | - = note: expected struct `std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r i32) + 'static)>` - found struct `std::boxed::Box` + = note: expected trait object `dyn for<'r> std::ops::Fn(&'r i32)` + found trait object `dyn std::ops::Fn(&i32)` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-42944.rs b/src/test/ui/issues/issue-42944.rs index cc365dc4c938e..a088f91554dfb 100644 --- a/src/test/ui/issues/issue-42944.rs +++ b/src/test/ui/issues/issue-42944.rs @@ -1,20 +1,20 @@ mod foo { - pub struct B(()); + pub struct Bx(()); } mod bar { - use foo::B; + use foo::Bx; fn foo() { - B(()); - //~^ ERROR expected function, tuple struct or tuple variant, found struct `B` [E0423] + Bx(()); + //~^ ERROR expected function, tuple struct or tuple variant, found struct `Bx` [E0423] } } mod baz { fn foo() { - B(()); - //~^ ERROR cannot find function, tuple struct or tuple variant `B` in this scope [E0425] + Bx(()); + //~^ ERROR cannot find function, tuple struct or tuple variant `Bx` in this scope [E0425] } } diff --git a/src/test/ui/issues/issue-42944.stderr b/src/test/ui/issues/issue-42944.stderr index e7e251e39c04f..9fad43757ba62 100644 --- a/src/test/ui/issues/issue-42944.stderr +++ b/src/test/ui/issues/issue-42944.stderr @@ -1,18 +1,18 @@ -error[E0423]: expected function, tuple struct or tuple variant, found struct `B` +error[E0423]: expected function, tuple struct or tuple variant, found struct `Bx` --> $DIR/issue-42944.rs:9:9 | -LL | B(()); - | ^ constructor is not visible here due to private fields +LL | Bx(()); + | ^^ constructor is not visible here due to private fields -error[E0425]: cannot find function, tuple struct or tuple variant `B` in this scope +error[E0425]: cannot find function, tuple struct or tuple variant `Bx` in this scope --> $DIR/issue-42944.rs:16:9 | -LL | B(()); - | ^ not found in this scope +LL | Bx(()); + | ^^ not found in this scope | help: consider importing this tuple struct | -LL | use foo::B; +LL | use foo::Bx; | error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-43623.rs b/src/test/ui/issues/issue-43623.rs index b259e9e269d06..99cae46fd9cf2 100644 --- a/src/test/ui/issues/issue-43623.rs +++ b/src/test/ui/issues/issue-43623.rs @@ -9,11 +9,12 @@ impl<'a> Trait<'a> for Type { } pub fn break_me(f: F) -where T: for<'b> Trait<'b>, - F: for<'b> FnMut(>::Assoc) { +where + T: for<'b> Trait<'b>, + F: for<'b> FnMut(>::Assoc), +{ break_me::; //~^ ERROR: type mismatch in function arguments - //~| ERROR: type mismatch resolving } fn main() {} diff --git a/src/test/ui/issues/issue-43623.stderr b/src/test/ui/issues/issue-43623.stderr index 99fb2a1f5d030..80aca482b3d29 100644 --- a/src/test/ui/issues/issue-43623.stderr +++ b/src/test/ui/issues/issue-43623.stderr @@ -1,29 +1,18 @@ error[E0631]: type mismatch in function arguments - --> $DIR/issue-43623.rs:14:5 + --> $DIR/issue-43623.rs:16:5 | LL | pub fn break_me(f: F) | -------- required by a bound in this -LL | where T: for<'b> Trait<'b>, -LL | F: for<'b> FnMut(>::Assoc) { - | -------------------------------------- required by this bound in `break_me` +... +LL | F: for<'b> FnMut(>::Assoc), + | ------------------------------ required by this bound in `break_me` +LL | { LL | break_me::; | ^^^^^^^^^^^^^^^^^^^^^^^ | | - | expected signature of `for<'b> fn(>::Assoc) -> _` - | found signature of `fn(_) -> _` + | expected signature of `fn(>::Assoc) -> _` + | found signature of `fn(()) -> _` -error[E0271]: type mismatch resolving `for<'b> >::Assoc,)>>::Output == ()` - --> $DIR/issue-43623.rs:14:5 - | -LL | pub fn break_me(f: F) - | -------- required by a bound in this -LL | where T: for<'b> Trait<'b>, -LL | F: for<'b> FnMut(>::Assoc) { - | ------------------------------ required by this bound in `break_me` -LL | break_me::; - | ^^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'b, found concrete lifetime - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0271, E0631. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/issues/issue-4366-2.stderr b/src/test/ui/issues/issue-4366-2.stderr index ecee595d4ab6a..a86ec7fabea4b 100644 --- a/src/test/ui/issues/issue-4366-2.stderr +++ b/src/test/ui/issues/issue-4366-2.stderr @@ -15,12 +15,10 @@ error[E0423]: expected function, found module `foo` LL | foo(); | ^^^ not a function | -help: consider importing one of these items instead +help: consider importing this function instead | LL | use foo::foo; | -LL | use m1::foo; - | error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-4366.stderr b/src/test/ui/issues/issue-4366.stderr index a094180572daa..469ea93e90468 100644 --- a/src/test/ui/issues/issue-4366.stderr +++ b/src/test/ui/issues/issue-4366.stderr @@ -4,12 +4,10 @@ error[E0425]: cannot find function `foo` in this scope LL | fn sub() -> isize { foo(); 1 } | ^^^ not found in this scope | -help: consider importing one of these items +help: consider importing this function | LL | use foo::foo; | -LL | use m1::foo; - | error: aborting due to previous error diff --git a/src/test/ui/issues/issue-44078.stderr b/src/test/ui/issues/issue-44078.stderr index 43b49e463128f..daf67219f4d0a 100644 --- a/src/test/ui/issues/issue-44078.stderr +++ b/src/test/ui/issues/issue-44078.stderr @@ -1,4 +1,4 @@ -error: unterminated double quote string +error[E0765]: unterminated double quote string --> $DIR/issue-44078.rs:2:8 | LL | "😊""; @@ -8,3 +8,4 @@ LL | | } error: aborting due to previous error +For more information about this error, try `rustc --explain E0765`. diff --git a/src/test/ui/issues/issue-46604.rs b/src/test/ui/issues/issue-46604.rs index e1967eb765542..273187a5a13be 100644 --- a/src/test/ui/issues/issue-46604.rs +++ b/src/test/ui/issues/issue-46604.rs @@ -1,4 +1,4 @@ -static buf: &mut [u8] = &mut [1u8,2,3,4,5,7]; //~ ERROR E0658 +static buf: &mut [u8] = &mut [1u8,2,3,4,5,7]; //~ ERROR E0764 fn write>(buffer: T) { } fn main() { diff --git a/src/test/ui/issues/issue-46604.stderr b/src/test/ui/issues/issue-46604.stderr index 771e368a35d93..5421721dec2e3 100644 --- a/src/test/ui/issues/issue-46604.stderr +++ b/src/test/ui/issues/issue-46604.stderr @@ -1,11 +1,8 @@ -error[E0658]: references in statics may only refer to immutable values +error[E0764]: mutable references are not allowed in statics --> $DIR/issue-46604.rs:1:25 | LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7]; - | ^^^^^^^^^^^^^^^^^^^^ statics require immutable values - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + | ^^^^^^^^^^^^^^^^^^^^ `&mut` is only allowed in `const fn` error[E0594]: cannot assign to `buf[_]`, as `buf` is an immutable static item --> $DIR/issue-46604.rs:6:5 @@ -15,5 +12,5 @@ LL | buf[0]=2; error: aborting due to 2 previous errors -Some errors have detailed explanations: E0594, E0658. +Some errors have detailed explanations: E0594, E0764. For more information about an error, try `rustc --explain E0594`. diff --git a/src/test/ui/issues/issue-48508.rs b/src/test/ui/issues/issue-48508.rs index 87965c204ada7..8dc9351260ebc 100644 --- a/src/test/ui/issues/issue-48508.rs +++ b/src/test/ui/issues/issue-48508.rs @@ -11,7 +11,7 @@ // ignore-asmjs wasm2js does not support source maps yet #![feature(non_ascii_idents)] -#[allow(uncommon_codepoints)] +#![allow(uncommon_codepoints)] #[path = "issue-48508-aux.rs"] mod other_file; diff --git a/src/test/ui/issues/issue-55380.rs b/src/test/ui/issues/issue-55380.rs index 862218e219279..f7cb296d3b8bb 100644 --- a/src/test/ui/issues/issue-55380.rs +++ b/src/test/ui/issues/issue-55380.rs @@ -1,6 +1,6 @@ // run-pass - #![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete pub trait Foo { fn abc() -> u32; diff --git a/src/test/ui/issues/issue-55380.stderr b/src/test/ui/issues/issue-55380.stderr new file mode 100644 index 0000000000000..451beebd1061e --- /dev/null +++ b/src/test/ui/issues/issue-55380.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-55380.rs:2:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/issues/issue-57362-2.stderr b/src/test/ui/issues/issue-57362-2.stderr index 2edc009746455..47cc64ec470a5 100644 --- a/src/test/ui/issues/issue-57362-2.stderr +++ b/src/test/ui/issues/issue-57362-2.stderr @@ -4,6 +4,8 @@ error[E0599]: no function or associated item named `make_g` found for fn pointer LL | let x = ::make_g(); | ^^^^^^ function or associated item not found in `for<'r> fn(&'r ())` | + = note: the method `make_g` exists but the following trait bounds were not satisfied: + `for<'r> fn(&'r ()): X` = help: items from traits can only be used if the trait is implemented and in scope note: `X` defines an item `make_g`, perhaps you need to implement it --> $DIR/issue-57362-2.rs:8:1 diff --git a/src/test/ui/issues/issue-5791.rs b/src/test/ui/issues/issue-5791.rs index 2f8bf1e936905..fda72a1b20e4a 100644 --- a/src/test/ui/issues/issue-5791.rs +++ b/src/test/ui/issues/issue-5791.rs @@ -1,11 +1,13 @@ // run-pass #![allow(dead_code)] +#![warn(clashing_extern_decl)] // pretty-expanded FIXME #23616 extern { #[link_name = "malloc"] fn malloc1(len: i32) -> *const u8; #[link_name = "malloc"] + //~^ WARN `malloc2` redeclares `malloc` with a different signature fn malloc2(len: i32, foo: i32) -> *const u8; } diff --git a/src/test/ui/issues/issue-5791.stderr b/src/test/ui/issues/issue-5791.stderr new file mode 100644 index 0000000000000..7ae83c43f1339 --- /dev/null +++ b/src/test/ui/issues/issue-5791.stderr @@ -0,0 +1,21 @@ +warning: `malloc2` redeclares `malloc` with a different signature + --> $DIR/issue-5791.rs:9:5 + | +LL | / #[link_name = "malloc"] +LL | | fn malloc1(len: i32) -> *const u8; + | |______________________________________- `malloc` previously declared here +LL | / #[link_name = "malloc"] +LL | | +LL | | fn malloc2(len: i32, foo: i32) -> *const u8; + | |________________________________________________^ this signature doesn't match the previous declaration + | +note: the lint level is defined here + --> $DIR/issue-5791.rs:3:9 + | +LL | #![warn(clashing_extern_decl)] + | ^^^^^^^^^^^^^^^^^^^^ + = note: expected `unsafe extern "C" fn(i32) -> *const u8` + found `unsafe extern "C" fn(i32, i32) -> *const u8` + +warning: 1 warning emitted + diff --git a/src/test/ui/issues/issue-60283.rs b/src/test/ui/issues/issue-60283.rs index e5a9caa32fae7..9c2b2dc9f4dae 100644 --- a/src/test/ui/issues/issue-60283.rs +++ b/src/test/ui/issues/issue-60283.rs @@ -7,11 +7,13 @@ impl<'a> Trait<'a> for () { } pub fn foo(_: T, _: F) -where T: for<'a> Trait<'a>, - F: for<'a> FnMut(>::Item) {} +where + T: for<'a> Trait<'a>, + F: for<'a> FnMut(>::Item), +{ +} fn main() { foo((), drop) //~^ ERROR type mismatch in function arguments - //~| ERROR type mismatch resolving } diff --git a/src/test/ui/issues/issue-60283.stderr b/src/test/ui/issues/issue-60283.stderr index e74a34e247a67..ad679bfa22063 100644 --- a/src/test/ui/issues/issue-60283.stderr +++ b/src/test/ui/issues/issue-60283.stderr @@ -1,31 +1,18 @@ error[E0631]: type mismatch in function arguments - --> $DIR/issue-60283.rs:14:13 + --> $DIR/issue-60283.rs:17:13 | LL | pub fn foo(_: T, _: F) | --- required by a bound in this -LL | where T: for<'a> Trait<'a>, -LL | F: for<'a> FnMut(>::Item) {} - | ------------------------------------- required by this bound in `foo` +... +LL | F: for<'a> FnMut(>::Item), + | ----------------------------- required by this bound in `foo` ... LL | foo((), drop) | ^^^^ | | - | expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _` - | found signature of `fn(_) -> _` - -error[E0271]: type mismatch resolving `for<'a> } as std::ops::FnOnce<(<() as Trait<'a>>::Item,)>>::Output == ()` - --> $DIR/issue-60283.rs:14:5 - | -LL | pub fn foo(_: T, _: F) - | --- required by a bound in this -LL | where T: for<'a> Trait<'a>, -LL | F: for<'a> FnMut(>::Item) {} - | ----------------------------- required by this bound in `foo` -... -LL | foo((), drop) - | ^^^ expected bound lifetime parameter 'a, found concrete lifetime + | expected signature of `fn(<() as Trait<'a>>::Item) -> _` + | found signature of `fn(()) -> _` -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0271, E0631. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/issues/issue-61108.stderr b/src/test/ui/issues/issue-61108.stderr index ba43f2d33ee44..8523a6f6548a6 100644 --- a/src/test/ui/issues/issue-61108.stderr +++ b/src/test/ui/issues/issue-61108.stderr @@ -6,17 +6,11 @@ LL | let mut bad_letters = vec!['e', 't', 'o', 'i']; LL | for l in bad_letters { | ----------- | | - | `bad_letters` moved due to this implicit call to `.into_iter()` + | value moved here | help: consider borrowing to avoid moving into the for loop: `&bad_letters` ... LL | bad_letters.push('s'); | ^^^^^^^^^^^ value borrowed here after move - | -note: this function consumes the receiver `self` by taking ownership of it, which moves `bad_letters` - --> $SRC_DIR/libcore/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-64559.stderr b/src/test/ui/issues/issue-64559.stderr index 2c337bae13017..3c685dc8d089a 100644 --- a/src/test/ui/issues/issue-64559.stderr +++ b/src/test/ui/issues/issue-64559.stderr @@ -6,18 +6,12 @@ LL | let orig = vec![true]; LL | for _val in orig {} | ---- | | - | `orig` moved due to this implicit call to `.into_iter()` + | value moved here | help: consider borrowing to avoid moving into the for loop: `&orig` LL | let _closure = || orig; | ^^ ---- use occurs due to use in closure | | | value used here after move - | -note: this function consumes the receiver `self` by taking ownership of it, which moves `orig` - --> $SRC_DIR/libcore/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-67552.rs b/src/test/ui/issues/issue-67552.rs index 1400c6f97b605..b0fcb74764b98 100644 --- a/src/test/ui/issues/issue-67552.rs +++ b/src/test/ui/issues/issue-67552.rs @@ -18,7 +18,6 @@ fn identity(x: T) -> T { } fn rec(mut it: T) -//~^ ERROR reached the recursion limit while instantiating where T: Iterator, { @@ -26,5 +25,6 @@ where T::count(it); } else { rec(identity(&mut it)) + //~^ ERROR reached the recursion limit while instantiating } } diff --git a/src/test/ui/issues/issue-67552.stderr b/src/test/ui/issues/issue-67552.stderr index 881f9d221d6ae..3bb2016f07d24 100644 --- a/src/test/ui/issues/issue-67552.stderr +++ b/src/test/ui/issues/issue-67552.stderr @@ -1,10 +1,16 @@ error: reached the recursion limit while instantiating `rec::<&mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut Empty>` + --> $DIR/issue-67552.rs:27:9 + | +LL | rec(identity(&mut it)) + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: `rec` defined here --> $DIR/issue-67552.rs:20:1 | LL | / fn rec(mut it: T) -LL | | LL | | where LL | | T: Iterator, +LL | | { ... | LL | | } LL | | } diff --git a/src/test/ui/issues/issue-72690.rs b/src/test/ui/issues/issue-72690.rs new file mode 100644 index 0000000000000..4edbd9ca15de7 --- /dev/null +++ b/src/test/ui/issues/issue-72690.rs @@ -0,0 +1,62 @@ +fn no_err() { + |x: String| x; + let _ = String::from("x"); +} + +fn err() { + String::from("x".as_ref()); //~ ERROR type annotations needed +} + +fn arg_pat_closure_err() { + |x| String::from("x".as_ref()); //~ ERROR type annotations needed +} + +fn local_pat_closure_err() { + let _ = "x".as_ref(); //~ ERROR type annotations needed +} + +fn err_first_arg_pat() { + String::from("x".as_ref()); //~ ERROR type annotations needed + |x: String| x; +} + +fn err_second_arg_pat() { + |x: String| x; + String::from("x".as_ref()); //~ ERROR type annotations needed +} + +fn err_mid_arg_pat() { + |x: String| x; + |x: String| x; + |x: String| x; + |x: String| x; + String::from("x".as_ref()); //~ ERROR type annotations needed + |x: String| x; + |x: String| x; + |x: String| x; + |x: String| x; +} + +fn err_first_local_pat() { + String::from("x".as_ref()); //~ ERROR type annotations needed + let _ = String::from("x"); +} + +fn err_second_local_pat() { + let _ = String::from("x"); + String::from("x".as_ref()); //~ ERROR type annotations needed +} + +fn err_mid_local_pat() { + let _ = String::from("x"); + let _ = String::from("x"); + let _ = String::from("x"); + let _ = String::from("x"); + String::from("x".as_ref()); //~ ERROR type annotations needed + let _ = String::from("x"); + let _ = String::from("x"); + let _ = String::from("x"); + let _ = String::from("x"); +} + +fn main() {} diff --git a/src/test/ui/issues/issue-72690.stderr b/src/test/ui/issues/issue-72690.stderr new file mode 100644 index 0000000000000..64e78ddf60474 --- /dev/null +++ b/src/test/ui/issues/issue-72690.stderr @@ -0,0 +1,88 @@ +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:7:5 + | +LL | String::from("x".as_ref()); + | ^^^^^^^^^^^^ cannot infer type for struct `std::string::String` + | + = note: cannot satisfy `std::string::String: std::convert::From<&_>` + = note: required by `std::convert::From::from` + +error[E0282]: type annotations needed + --> $DIR/issue-72690.rs:11:6 + | +LL | |x| String::from("x".as_ref()); + | ^ consider giving this closure parameter a type + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:15:17 + | +LL | let _ = "x".as_ref(); + | ^^^^^^ cannot infer type for type `str` + | + = note: cannot satisfy `str: std::convert::AsRef<_>` + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:19:5 + | +LL | String::from("x".as_ref()); + | ^^^^^^^^^^^^ cannot infer type for struct `std::string::String` + | + = note: cannot satisfy `std::string::String: std::convert::From<&_>` + = note: required by `std::convert::From::from` + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:25:5 + | +LL | String::from("x".as_ref()); + | ^^^^^^^^^^^^ cannot infer type for struct `std::string::String` + | + = note: cannot satisfy `std::string::String: std::convert::From<&_>` + = note: required by `std::convert::From::from` + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:33:5 + | +LL | String::from("x".as_ref()); + | ^^^^^^^^^^^^ cannot infer type for struct `std::string::String` + | + = note: cannot satisfy `std::string::String: std::convert::From<&_>` + = note: required by `std::convert::From::from` + +error[E0283]: type annotations needed for `std::string::String` + --> $DIR/issue-72690.rs:41:5 + | +LL | String::from("x".as_ref()); + | ^^^^^^^^^^^^ cannot infer type for struct `std::string::String` +LL | let _ = String::from("x"); + | - consider giving this pattern a type + | + = note: cannot satisfy `std::string::String: std::convert::From<&_>` + = note: required by `std::convert::From::from` + +error[E0283]: type annotations needed for `std::string::String` + --> $DIR/issue-72690.rs:47:5 + | +LL | let _ = String::from("x"); + | - consider giving this pattern a type +LL | String::from("x".as_ref()); + | ^^^^^^^^^^^^ cannot infer type for struct `std::string::String` + | + = note: cannot satisfy `std::string::String: std::convert::From<&_>` + = note: required by `std::convert::From::from` + +error[E0283]: type annotations needed for `std::string::String` + --> $DIR/issue-72690.rs:55:5 + | +LL | let _ = String::from("x"); + | - consider giving this pattern a type +... +LL | String::from("x".as_ref()); + | ^^^^^^^^^^^^ cannot infer type for struct `std::string::String` + | + = note: cannot satisfy `std::string::String: std::convert::From<&_>` + = note: required by `std::convert::From::from` + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0282, E0283. +For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/issues/issue-8727.rs b/src/test/ui/issues/issue-8727.rs index 80f360155cb49..14bdd8511119e 100644 --- a/src/test/ui/issues/issue-8727.rs +++ b/src/test/ui/issues/issue-8727.rs @@ -3,12 +3,10 @@ // build-fail -fn generic() { +fn generic() { //~ WARN function cannot return without recursing generic::>(); } -//~^^^ ERROR reached the recursion limit while instantiating `generic::>(); = help: a `loop` may express intention better if this is on purpose error: reached the recursion limit while instantiating `generic::>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + --> $DIR/issue-8727.rs:7:5 + | +LL | generic::>(); + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: `generic` defined here --> $DIR/issue-8727.rs:6:1 | LL | / fn generic() { diff --git a/src/test/ui/lint/auxiliary/external_extern_fn.rs b/src/test/ui/lint/auxiliary/external_extern_fn.rs new file mode 100644 index 0000000000000..b2caebc6fee0e --- /dev/null +++ b/src/test/ui/lint/auxiliary/external_extern_fn.rs @@ -0,0 +1,3 @@ +extern { + pub fn extern_fn(x: u8); +} diff --git a/src/test/ui/lint/clashing-extern-fn.rs b/src/test/ui/lint/clashing-extern-fn.rs new file mode 100644 index 0000000000000..32f3a78f4e980 --- /dev/null +++ b/src/test/ui/lint/clashing-extern-fn.rs @@ -0,0 +1,159 @@ +// check-pass +// aux-build:external_extern_fn.rs +#![crate_type = "lib"] +#![warn(clashing_extern_decl)] + +extern crate external_extern_fn; + +extern { + fn clash(x: u8); + fn no_clash(x: u8); +} + +fn redeclared_different_signature() { + extern { + fn clash(x: u64); //~ WARN `clash` redeclared with a different signature + } + + unsafe { + clash(123); + no_clash(123); + } +} + +fn redeclared_same_signature() { + extern { + fn no_clash(x: u8); + } + unsafe { + no_clash(123); + } +} + +extern { + fn extern_fn(x: u64); +} + +fn extern_clash() { + extern { + fn extern_fn(x: u32); //~ WARN `extern_fn` redeclared with a different signature + } + unsafe { + extern_fn(123); + } +} + +fn extern_no_clash() { + unsafe { + external_extern_fn::extern_fn(123); + crate::extern_fn(123); + } +} +extern { + fn some_other_new_name(x: i16); + + #[link_name = "extern_link_name"] + fn some_new_name(x: i16); + + #[link_name = "link_name_same"] + fn both_names_different(x: i16); +} + +fn link_name_clash() { + extern { + fn extern_link_name(x: u32); + //~^ WARN `extern_link_name` redeclared with a different signature + + #[link_name = "some_other_new_name"] + //~^ WARN `some_other_extern_link_name` redeclares `some_other_new_name` with a different + fn some_other_extern_link_name(x: u32); + + #[link_name = "link_name_same"] + //~^ WARN `other_both_names_different` redeclares `link_name_same` with a different + fn other_both_names_different(x: u32); + } +} + +mod a { + extern { + fn different_mod(x: u8); + } +} +mod b { + extern { + fn different_mod(x: u64); //~ WARN `different_mod` redeclared with a different signature + } +} + +extern { + fn variadic_decl(x: u8, ...); +} + +fn variadic_clash() { + extern { + fn variadic_decl(x: u8); //~ WARN `variadic_decl` redeclared with a different signature + } +} + +#[no_mangle] +fn no_mangle_name(x: u8) { } + +extern { + #[link_name = "unique_link_name"] + fn link_name_specified(x: u8); +} + +fn tricky_no_clash() { + extern { + // Shouldn't warn, because the declaration above actually declares a different symbol (and + // Rust's name resolution rules around shadowing will handle this gracefully). + fn link_name_specified() -> u32; + + // The case of a no_mangle name colliding with an extern decl (see #28179) is related but + // shouldn't be reported by ClashingExternDecl, because this is an example of unmangled + // name clash causing bad behaviour in functions with a defined body. + fn no_mangle_name() -> u32; + } +} + +mod banana { + mod one { + #[repr(C)] struct Banana { weight: u32, length: u16 } + extern "C" { fn weigh_banana(count: *const Banana) -> u64; } + } + + mod two { + #[repr(C)] struct Banana { weight: u32, length: u16 } // note: distinct type + // This should not trigger the lint because two::Banana is structurally equivalent to + // one::Banana. + extern "C" { fn weigh_banana(count: *const Banana) -> u64; } + } + + mod three { + // This _should_ trigger the lint, because repr(packed) should generate a struct that has a + // different layout. + #[repr(packed)] struct Banana { weight: u32, length: u16 } + #[allow(improper_ctypes)] + extern "C" { fn weigh_banana(count: *const Banana) -> u64; } + //~^ WARN `weigh_banana` redeclared with a different signature + } +} + +mod sameish_members { + mod a { + #[repr(C)] + struct Point { x: i16, y: i16 } + + extern "C" { fn draw_point(p: Point); } + } + mod b { + #[repr(C)] + struct Point { coordinates: [i16; 2] } + + // It's possible we are overconservative for this case, as accessing the elements of the + // coordinates array might end up correctly accessing `.x` and `.y`. However, this may not + // always be the case, for every architecture and situation. This is also a really odd + // thing to do anyway. + extern "C" { fn draw_point(p: Point); } //~ WARN `draw_point` redeclared with a different + } +} diff --git a/src/test/ui/lint/clashing-extern-fn.stderr b/src/test/ui/lint/clashing-extern-fn.stderr new file mode 100644 index 0000000000000..fb7bf135f538c --- /dev/null +++ b/src/test/ui/lint/clashing-extern-fn.stderr @@ -0,0 +1,121 @@ +warning: `clash` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:15:9 + | +LL | fn clash(x: u8); + | ---------------- `clash` previously declared here +... +LL | fn clash(x: u64); + | ^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | +note: the lint level is defined here + --> $DIR/clashing-extern-fn.rs:4:9 + | +LL | #![warn(clashing_extern_decl)] + | ^^^^^^^^^^^^^^^^^^^^ + = note: expected `unsafe extern "C" fn(u8)` + found `unsafe extern "C" fn(u64)` + +warning: `extern_fn` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:39:9 + | +LL | fn extern_fn(x: u64); + | --------------------- `extern_fn` previously declared here +... +LL | fn extern_fn(x: u32); + | ^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn(u64)` + found `unsafe extern "C" fn(u32)` + +warning: `extern_link_name` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:64:9 + | +LL | / #[link_name = "extern_link_name"] +LL | | fn some_new_name(x: i16); + | |_____________________________- `extern_link_name` previously declared here +... +LL | fn extern_link_name(x: u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn(i16)` + found `unsafe extern "C" fn(u32)` + +warning: `some_other_extern_link_name` redeclares `some_other_new_name` with a different signature + --> $DIR/clashing-extern-fn.rs:67:9 + | +LL | fn some_other_new_name(x: i16); + | ------------------------------- `some_other_new_name` previously declared here +... +LL | / #[link_name = "some_other_new_name"] +LL | | +LL | | fn some_other_extern_link_name(x: u32); + | |_______________________________________________^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn(i16)` + found `unsafe extern "C" fn(u32)` + +warning: `other_both_names_different` redeclares `link_name_same` with a different signature + --> $DIR/clashing-extern-fn.rs:71:9 + | +LL | / #[link_name = "link_name_same"] +LL | | fn both_names_different(x: i16); + | |____________________________________- `link_name_same` previously declared here +... +LL | / #[link_name = "link_name_same"] +LL | | +LL | | fn other_both_names_different(x: u32); + | |______________________________________________^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn(i16)` + found `unsafe extern "C" fn(u32)` + +warning: `different_mod` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:84:9 + | +LL | fn different_mod(x: u8); + | ------------------------ `different_mod` previously declared here +... +LL | fn different_mod(x: u64); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn(u8)` + found `unsafe extern "C" fn(u64)` + +warning: `variadic_decl` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:94:9 + | +LL | fn variadic_decl(x: u8, ...); + | ----------------------------- `variadic_decl` previously declared here +... +LL | fn variadic_decl(x: u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn(u8, ...)` + found `unsafe extern "C" fn(u8)` + +warning: `weigh_banana` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:137:22 + | +LL | extern "C" { fn weigh_banana(count: *const Banana) -> u64; } + | --------------------------------------------- `weigh_banana` previously declared here +... +LL | extern "C" { fn weigh_banana(count: *const Banana) -> u64; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn(*const banana::one::Banana) -> u64` + found `unsafe extern "C" fn(*const banana::three::Banana) -> u64` + +warning: `draw_point` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:157:22 + | +LL | extern "C" { fn draw_point(p: Point); } + | ------------------------ `draw_point` previously declared here +... +LL | extern "C" { fn draw_point(p: Point); } + | ^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn(sameish_members::a::Point)` + found `unsafe extern "C" fn(sameish_members::b::Point)` + +warning: 9 warnings emitted + diff --git a/src/test/ui/lint/crate_level_only_lint.rs b/src/test/ui/lint/crate_level_only_lint.rs new file mode 100644 index 0000000000000..d9673faa2142e --- /dev/null +++ b/src/test/ui/lint/crate_level_only_lint.rs @@ -0,0 +1,22 @@ +#![deny(uncommon_codepoints, unused_attributes)] + +mod foo { +#![allow(uncommon_codepoints)] +//~^ ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] + +#[allow(uncommon_codepoints)] +//~^ ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +const BAR: f64 = 0.000001; + +} + +#[allow(uncommon_codepoints)] +//~^ ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +fn main() { +} diff --git a/src/test/ui/lint/crate_level_only_lint.stderr b/src/test/ui/lint/crate_level_only_lint.stderr new file mode 100644 index 0000000000000..8fb06df2a481a --- /dev/null +++ b/src/test/ui/lint/crate_level_only_lint.stderr @@ -0,0 +1,62 @@ +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:4:10 + | +LL | #![allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/crate_level_only_lint.rs:1:30 + | +LL | #![deny(uncommon_codepoints, unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:9:9 + | +LL | #[allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:17:9 + | +LL | #[allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:4:10 + | +LL | #![allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:9:9 + | +LL | #[allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:17:9 + | +LL | #[allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:4:10 + | +LL | #![allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:9:9 + | +LL | #[allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:17:9 + | +LL | #[allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 9 previous errors + diff --git a/src/test/ui/lint/dead-code/lint-dead-code-3.rs b/src/test/ui/lint/dead-code/lint-dead-code-3.rs index 6826d2cd67eb9..ff33abfa64586 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-3.rs +++ b/src/test/ui/lint/dead-code/lint-dead-code-3.rs @@ -1,5 +1,6 @@ #![allow(unused_variables)] #![allow(non_camel_case_types)] +#![allow(clashing_extern_decl)] #![deny(dead_code)] #![crate_type="lib"] diff --git a/src/test/ui/lint/dead-code/lint-dead-code-3.stderr b/src/test/ui/lint/dead-code/lint-dead-code-3.stderr index 6d174e8d9bc38..cf8f01ea19f0c 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-3.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-3.stderr @@ -1,35 +1,35 @@ error: struct is never constructed: `Foo` - --> $DIR/lint-dead-code-3.rs:13:8 + --> $DIR/lint-dead-code-3.rs:14:8 | LL | struct Foo; | ^^^ | note: the lint level is defined here - --> $DIR/lint-dead-code-3.rs:3:9 + --> $DIR/lint-dead-code-3.rs:4:9 | LL | #![deny(dead_code)] | ^^^^^^^^^ error: associated function is never used: `foo` - --> $DIR/lint-dead-code-3.rs:15:8 + --> $DIR/lint-dead-code-3.rs:16:8 | LL | fn foo(&self) { | ^^^ error: function is never used: `bar` - --> $DIR/lint-dead-code-3.rs:20:4 + --> $DIR/lint-dead-code-3.rs:21:4 | LL | fn bar() { | ^^^ error: enum is never used: `c_void` - --> $DIR/lint-dead-code-3.rs:59:6 + --> $DIR/lint-dead-code-3.rs:60:6 | LL | enum c_void {} | ^^^^^^ error: function is never used: `free` - --> $DIR/lint-dead-code-3.rs:61:5 + --> $DIR/lint-dead-code-3.rs:62:5 | LL | fn free(p: *const c_void); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/lint/lint-ctypes-73249-1.rs b/src/test/ui/lint/lint-ctypes-73249-1.rs new file mode 100644 index 0000000000000..cf416c3fe8b12 --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-73249-1.rs @@ -0,0 +1,21 @@ +// check-pass +#![deny(improper_ctypes)] + +pub trait Foo { + type Assoc: 'static; +} + +impl Foo for () { + type Assoc = u32; +} + +extern "C" { + pub fn lint_me(x: Bar<()>); +} + +#[repr(transparent)] +pub struct Bar { + value: &'static ::Assoc, +} + +fn main() {} diff --git a/src/test/ui/lint/lint-ctypes-73249-2.rs b/src/test/ui/lint/lint-ctypes-73249-2.rs new file mode 100644 index 0000000000000..86cc5e2c31e81 --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-73249-2.rs @@ -0,0 +1,29 @@ +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +pub trait Baz { } + +impl Baz for () { } + +type Qux = impl Baz; + +fn assign() -> Qux {} + +pub trait Foo { + type Assoc: 'static; +} + +impl Foo for () { + type Assoc = Qux; +} + +#[repr(transparent)] +pub struct A { + x: &'static ::Assoc, +} + +extern "C" { + pub fn lint_me() -> A<()>; //~ ERROR: uses type `impl Baz` +} + +fn main() {} diff --git a/src/test/ui/lint/lint-ctypes-73249-2.stderr b/src/test/ui/lint/lint-ctypes-73249-2.stderr new file mode 100644 index 0000000000000..36dbe3217d75a --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-73249-2.stderr @@ -0,0 +1,15 @@ +error: `extern` block uses type `impl Baz`, which is not FFI-safe + --> $DIR/lint-ctypes-73249-2.rs:26:25 + | +LL | pub fn lint_me() -> A<()>; + | ^^^^^ not FFI-safe + | +note: the lint level is defined here + --> $DIR/lint-ctypes-73249-2.rs:2:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + = note: opaque types have no C equivalent + +error: aborting due to previous error + diff --git a/src/test/ui/lint/lint-ctypes-73249-3.rs b/src/test/ui/lint/lint-ctypes-73249-3.rs new file mode 100644 index 0000000000000..25c4e7c92a854 --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-73249-3.rs @@ -0,0 +1,21 @@ +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +pub trait Baz { } + +impl Baz for u32 { } + +type Qux = impl Baz; + +fn assign() -> Qux { 3 } + +#[repr(C)] +pub struct A { + x: Qux, +} + +extern "C" { + pub fn lint_me() -> A; //~ ERROR: uses type `impl Baz` +} + +fn main() {} diff --git a/src/test/ui/lint/lint-ctypes-73249-3.stderr b/src/test/ui/lint/lint-ctypes-73249-3.stderr new file mode 100644 index 0000000000000..7d133287bd73e --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-73249-3.stderr @@ -0,0 +1,15 @@ +error: `extern` block uses type `impl Baz`, which is not FFI-safe + --> $DIR/lint-ctypes-73249-3.rs:18:25 + | +LL | pub fn lint_me() -> A; + | ^ not FFI-safe + | +note: the lint level is defined here + --> $DIR/lint-ctypes-73249-3.rs:2:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + = note: opaque types have no C equivalent + +error: aborting due to previous error + diff --git a/src/test/ui/lint/lint-ctypes-73249-4.rs b/src/test/ui/lint/lint-ctypes-73249-4.rs new file mode 100644 index 0000000000000..6c72bd691b17c --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-73249-4.rs @@ -0,0 +1,24 @@ +// check-pass +#![deny(improper_ctypes)] + +use std::marker::PhantomData; + +trait Foo { + type Assoc; +} + +impl Foo for () { + type Assoc = PhantomData<()>; +} + +#[repr(transparent)] +struct Wow where T: Foo> { + x: ::Assoc, + v: u32, +} + +extern "C" { + fn test(v: Wow<()>); +} + +fn main() {} diff --git a/src/test/ui/lint/lint-ctypes-73249-5.rs b/src/test/ui/lint/lint-ctypes-73249-5.rs new file mode 100644 index 0000000000000..61e46983ede65 --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-73249-5.rs @@ -0,0 +1,21 @@ +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +pub trait Baz { } + +impl Baz for u32 { } + +type Qux = impl Baz; + +fn assign() -> Qux { 3 } + +#[repr(transparent)] +pub struct A { + x: Qux, +} + +extern "C" { + pub fn lint_me() -> A; //~ ERROR: uses type `impl Baz` +} + +fn main() {} diff --git a/src/test/ui/lint/lint-ctypes-73249-5.stderr b/src/test/ui/lint/lint-ctypes-73249-5.stderr new file mode 100644 index 0000000000000..d2780cb60e7dd --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-73249-5.stderr @@ -0,0 +1,15 @@ +error: `extern` block uses type `impl Baz`, which is not FFI-safe + --> $DIR/lint-ctypes-73249-5.rs:18:25 + | +LL | pub fn lint_me() -> A; + | ^ not FFI-safe + | +note: the lint level is defined here + --> $DIR/lint-ctypes-73249-5.rs:2:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + = note: opaque types have no C equivalent + +error: aborting due to previous error + diff --git a/src/test/ui/lint/lint-ctypes-73249.rs b/src/test/ui/lint/lint-ctypes-73249.rs new file mode 100644 index 0000000000000..5b48fa9b7376f --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-73249.rs @@ -0,0 +1,21 @@ +// check-pass +#![deny(improper_ctypes)] + +pub trait Foo { + type Assoc; +} + +impl Foo for () { + type Assoc = u32; +} + +extern "C" { + pub fn lint_me(x: Bar<()>); +} + +#[repr(transparent)] +pub struct Bar { + value: ::Assoc, +} + +fn main() {} diff --git a/src/test/ui/lint/lint-ctypes-73251-1.rs b/src/test/ui/lint/lint-ctypes-73251-1.rs new file mode 100644 index 0000000000000..2ce80982f5ca1 --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-73251-1.rs @@ -0,0 +1,24 @@ +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +pub trait Baz { } + +impl Baz for u32 { } + +type Qux = impl Baz; + +pub trait Foo { + type Assoc; +} + +impl Foo for u32 { + type Assoc = Qux; +} + +fn assign() -> Qux { 1 } + +extern "C" { + pub fn lint_me() -> ::Assoc; //~ ERROR: uses type `impl Baz` +} + +fn main() {} diff --git a/src/test/ui/lint/lint-ctypes-73251-1.stderr b/src/test/ui/lint/lint-ctypes-73251-1.stderr new file mode 100644 index 0000000000000..0b4237bb96fb7 --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-73251-1.stderr @@ -0,0 +1,15 @@ +error: `extern` block uses type `impl Baz`, which is not FFI-safe + --> $DIR/lint-ctypes-73251-1.rs:21:25 + | +LL | pub fn lint_me() -> ::Assoc; + | ^^^^^^^^^^^^^^^^^^^ not FFI-safe + | +note: the lint level is defined here + --> $DIR/lint-ctypes-73251-1.rs:2:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + = note: opaque types have no C equivalent + +error: aborting due to previous error + diff --git a/src/test/ui/lint/lint-ctypes-73251-2.rs b/src/test/ui/lint/lint-ctypes-73251-2.rs new file mode 100644 index 0000000000000..3427c657b42ac --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-73251-2.rs @@ -0,0 +1,32 @@ +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +pub trait TraitA { + type Assoc; +} + +impl TraitA for u32 { + type Assoc = u32; +} + +pub trait TraitB { + type Assoc; +} + +impl TraitB for T where T: TraitA { + type Assoc = ::Assoc; +} + +type AliasA = impl TraitA; + +type AliasB = impl TraitB; + +fn use_of_a() -> AliasA { 3 } + +fn use_of_b() -> AliasB { 3 } + +extern "C" { + pub fn lint_me() -> ::Assoc; //~ ERROR: uses type `impl TraitA` +} + +fn main() {} diff --git a/src/test/ui/lint/lint-ctypes-73251-2.stderr b/src/test/ui/lint/lint-ctypes-73251-2.stderr new file mode 100644 index 0000000000000..43f7629b043a9 --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-73251-2.stderr @@ -0,0 +1,15 @@ +error: `extern` block uses type `impl TraitA`, which is not FFI-safe + --> $DIR/lint-ctypes-73251-2.rs:29:25 + | +LL | pub fn lint_me() -> ::Assoc; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | +note: the lint level is defined here + --> $DIR/lint-ctypes-73251-2.rs:2:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + = note: opaque types have no C equivalent + +error: aborting due to previous error + diff --git a/src/test/ui/lint/lint-ctypes-73251.rs b/src/test/ui/lint/lint-ctypes-73251.rs new file mode 100644 index 0000000000000..ebc2ca77b67a1 --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-73251.rs @@ -0,0 +1,22 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +pub trait Foo { + type Assoc; +} + +impl Foo for () { + type Assoc = u32; +} + +type Bar = impl Foo; + +fn assign() -> Bar {} + +extern "C" { + pub fn lint_me() -> ::Assoc; +} + +fn main() {} diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.rs b/src/test/ui/lub-glb/old-lub-glb-hr-eq.rs similarity index 57% rename from src/test/ui/lub-glb/old-lub-glb-hr.rs rename to src/test/ui/lub-glb/old-lub-glb-hr-eq.rs index bc7b787cd65ac..fbf4aee02045d 100644 --- a/src/test/ui/lub-glb/old-lub-glb-hr.rs +++ b/src/test/ui/lub-glb/old-lub-glb-hr-eq.rs @@ -4,23 +4,19 @@ // longer get an error, because we recognize these two types as // equivalent! // -// Whoops -- now that we reinstituted the leak-check, we get an error -// again. +// check-pass -fn foo( - x: fn(&u8, &u8), - y: for<'a> fn(&'a u8, &'a u8), -) { +fn foo(x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8)) { + // The two types above are actually equivalent. With the older + // leak check, though, we didn't consider them as equivalent, and + // hence we gave errors. But now we've fixed that. let z = match 22 { 0 => x, - _ => y, //~ ERROR `match` arms have incompatible types + _ => y, }; } -fn bar( - x: fn(&u8, &u8), - y: for<'a> fn(&'a u8, &'a u8), -) { +fn foo_cast(x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8)) { let z = match 22 { // No error with an explicit cast: 0 => x as for<'a> fn(&'a u8, &'a u8), @@ -28,5 +24,4 @@ fn bar( }; } -fn main() { -} +fn main() {} diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr new file mode 100644 index 0000000000000..b95e247d2a8cf --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/old-lub-glb-hr-noteq1.rs:11:14 + | +LL | _ => y, + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.rs b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.rs new file mode 100644 index 0000000000000..918542d471b58 --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.rs @@ -0,0 +1,24 @@ +// Test taking the LUB of two function types that are not equatable but where one is more +// general than the other. Test the case where the more general type (`x`) is the first +// match arm specifically. + +fn foo(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) { + // The two types above are not equivalent. With the older LUB/GLB + // algorithm, this may have worked (I don't remember), but now it + // doesn't because we require equality. + let z = match 22 { + 0 => x, + _ => y, //~ ERROR `match` arms have incompatible types + }; +} + +fn foo_cast(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) { + // But we can *upcast* explicitly the type of `x` and figure + // things out: + let z = match 22 { + 0 => x as for<'a> fn(&'a u8, &'a u8) -> &'a u8, + _ => y, + }; +} + +fn main() {} diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.stderr b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.stderr new file mode 100644 index 0000000000000..305e952d6046b --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.stderr @@ -0,0 +1,18 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/old-lub-glb-hr-noteq1.rs:11:14 + | +LL | let z = match 22 { + | _____________- +LL | | 0 => x, + | | - this is found to be of type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` +LL | | _ => y, + | | ^ one type is more general than the other +LL | | }; + | |_____- `match` arms have incompatible types + | + = note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` + found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs b/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs new file mode 100644 index 0000000000000..4bdd05b4f92fa --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs @@ -0,0 +1,33 @@ +// Test taking the LUB of two function types that are not equatable but where +// one is more general than the other. Test the case where the more general type +// (`x`) is the second match arm specifically. +// +// FIXME(#73154) Skip for compare-mode because the pure NLL checker accepts this +// test. (Note that it still errors in old-lub-glb-hr-noteq1.rs). What happens +// is that, due to the ordering of the match arms, we pick the correct "more +// general" fn type, and we ignore the errors from the non-NLL type checker that +// requires equality. The NLL type checker only requires a subtyping +// relationship, and that holds. +// +// ignore-compare-mode-nll + +fn foo(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) { + // The two types above are not equivalent. With the older LUB/GLB + // algorithm, this may have worked (I don't remember), but now it + // doesn't because we require equality. + let z = match 22 { + 0 => y, + _ => x, //~ ERROR `match` arms have incompatible types + }; +} + +fn foo_cast(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) { + // But we can *upcast* explicitly the type of `x` and figure + // things out: + let z = match 22 { + 0 => x as for<'a> fn(&'a u8, &'a u8) -> &'a u8, + _ => y, + }; +} + +fn main() {} diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.stderr b/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.stderr new file mode 100644 index 0000000000000..252e13aada054 --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.stderr @@ -0,0 +1,18 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/old-lub-glb-hr-noteq2.rs:20:14 + | +LL | let z = match 22 { + | _____________- +LL | | 0 => y, + | | - this is found to be of type `for<'a> fn(&'a u8, &'a u8) -> &'a u8` +LL | | _ => x, + | | ^ one type is more general than the other +LL | | }; + | |_____- `match` arms have incompatible types + | + = note: expected fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8` + found fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.stderr b/src/test/ui/lub-glb/old-lub-glb-hr.stderr deleted file mode 100644 index 6d5d51174699f..0000000000000 --- a/src/test/ui/lub-glb/old-lub-glb-hr.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0308]: `match` arms have incompatible types - --> $DIR/old-lub-glb-hr.rs:16:14 - | -LL | let z = match 22 { - | _____________- -LL | | 0 => x, - | | - this is found to be of type `for<'r, 's> fn(&'r u8, &'s u8)` -LL | | _ => y, - | | ^ expected bound lifetime parameter, found concrete lifetime -LL | | }; - | |_____- `match` arms have incompatible types - | - = note: expected type `for<'r, 's> fn(&'r u8, &'s u8)` - found fn pointer `for<'a> fn(&'a u8, &'a u8)` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/lub-glb/old-lub-glb-object.nll.stderr b/src/test/ui/lub-glb/old-lub-glb-object.nll.stderr new file mode 100644 index 0000000000000..51bf96f32335b --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-object.nll.stderr @@ -0,0 +1,14 @@ +error: higher-ranked subtype error + --> $DIR/old-lub-glb-object.rs:10:14 + | +LL | _ => y, + | ^ + +error: higher-ranked subtype error + --> $DIR/old-lub-glb-object.rs:10:14 + | +LL | _ => y, + | ^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/lub-glb/old-lub-glb-object.rs b/src/test/ui/lub-glb/old-lub-glb-object.rs index 63bbae59991bc..39d351c235574 100644 --- a/src/test/ui/lub-glb/old-lub-glb-object.rs +++ b/src/test/ui/lub-glb/old-lub-glb-object.rs @@ -1,22 +1,17 @@ // Test that we give a note when the old LUB/GLB algorithm would have // succeeded but the new code (which is stricter) gives an error. -trait Foo { } +trait Foo {} -fn foo( - x: &dyn for<'a, 'b> Foo<&'a u8, &'b u8>, - y: &dyn for<'a> Foo<&'a u8, &'a u8>, -) { +fn foo(x: &dyn for<'a, 'b> Foo<&'a u8, &'b u8>, y: &dyn for<'a> Foo<&'a u8, &'a u8>) { let z = match 22 { + //~^ ERROR mismatched types 0 => x, - _ => y, //~ ERROR `match` arms have incompatible types + _ => y, }; } -fn bar( - x: &dyn for<'a, 'b> Foo<&'a u8, &'b u8>, - y: &dyn for<'a> Foo<&'a u8, &'a u8>, -) { +fn bar(x: &dyn for<'a, 'b> Foo<&'a u8, &'b u8>, y: &dyn for<'a> Foo<&'a u8, &'a u8>) { // Accepted with explicit case: let z = match 22 { 0 => x as &dyn for<'a> Foo<&'a u8, &'a u8>, @@ -24,5 +19,4 @@ fn bar( }; } -fn main() { -} +fn main() {} diff --git a/src/test/ui/lub-glb/old-lub-glb-object.stderr b/src/test/ui/lub-glb/old-lub-glb-object.stderr index 65c797f6b19d7..6eabe5eaeeeeb 100644 --- a/src/test/ui/lub-glb/old-lub-glb-object.stderr +++ b/src/test/ui/lub-glb/old-lub-glb-object.stderr @@ -1,17 +1,16 @@ -error[E0308]: `match` arms have incompatible types - --> $DIR/old-lub-glb-object.rs:12:14 +error[E0308]: mismatched types + --> $DIR/old-lub-glb-object.rs:7:13 | LL | let z = match 22 { - | _____________- + | _____________^ +LL | | LL | | 0 => x, - | | - this is found to be of type `&dyn for<'a, 'b> Foo<&'a u8, &'b u8>` LL | | _ => y, - | | ^ expected bound lifetime parameter 'a, found concrete lifetime LL | | }; - | |_____- `match` arms have incompatible types + | |_____^ one type is more general than the other | - = note: expected type `&dyn for<'a, 'b> Foo<&'a u8, &'b u8>` - found reference `&dyn for<'a> Foo<&'a u8, &'a u8>` + = note: expected trait object `dyn for<'a, 'b> Foo<&'a u8, &'b u8>` + found trait object `dyn for<'a> Foo<&'a u8, &'a u8>` error: aborting due to previous error diff --git a/src/test/ui/mir/mir_detects_invalid_ops.rs b/src/test/ui/mir/mir_detects_invalid_ops.rs index 0940dbe6a5e87..136c03cd9f1bc 100644 --- a/src/test/ui/mir/mir_detects_invalid_ops.rs +++ b/src/test/ui/mir/mir_detects_invalid_ops.rs @@ -19,6 +19,6 @@ fn mod_by_zero() { fn oob_error_for_slices() { let a: *const [_] = &[1, 2, 3]; unsafe { - let _b = (*a)[3]; //~ ERROR this operation will panic at runtime [unconditional_panic] + let _b = (*a)[3]; } } diff --git a/src/test/ui/mir/mir_detects_invalid_ops.stderr b/src/test/ui/mir/mir_detects_invalid_ops.stderr index 41f03789f237f..0b6dbfd7c3d85 100644 --- a/src/test/ui/mir/mir_detects_invalid_ops.stderr +++ b/src/test/ui/mir/mir_detects_invalid_ops.stderr @@ -12,11 +12,5 @@ error: this operation will panic at runtime LL | let _z = 1 % y; | ^^^^^ attempt to calculate the remainder with a divisor of zero -error: this operation will panic at runtime - --> $DIR/mir_detects_invalid_ops.rs:22:18 - | -LL | let _b = (*a)[3]; - | ^^^^^^^ index out of bounds: the len is 3 but the index is 3 - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.nll.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.nll.stderr new file mode 100644 index 0000000000000..6ed91b20ab8a6 --- /dev/null +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.nll.stderr @@ -0,0 +1,27 @@ +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:3:14 + | +LL | a.iter().map(|_: (u32, u32)| 45); + | ^^^ ------------------ found signature of `fn((u32, u32)) -> _` + | | + | expected signature of `fn(&(u32, u32)) -> _` + +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:4:14 + | +LL | a.iter().map(|_: &(u16, u16)| 45); + | ^^^ ------------------- found signature of `for<'r> fn(&'r (u16, u16)) -> _` + | | + | expected signature of `fn(&(u32, u32)) -> _` + +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:5:14 + | +LL | a.iter().map(|_: (u16, u16)| 45); + | ^^^ ------------------ found signature of `fn((u16, u16)) -> _` + | | + | expected signature of `fn(&(u32, u32)) -> _` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs index 521bd3695dfe5..e278049c8cc42 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs @@ -7,6 +7,9 @@ fn main() { fn baz(_: F) {} fn _test<'a>(f: fn(*mut &'a u32)) { - baz(f); //~ ERROR type mismatch - //~| ERROR type mismatch + baz(f); + //~^ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types } diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr index 69a4b458ebf50..664fa4bcaf328 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -22,28 +22,43 @@ LL | a.iter().map(|_: (u16, u16)| 45); | | | expected signature of `fn(&(u32, u32)) -> _` -error[E0631]: type mismatch in function arguments - --> $DIR/closure-arg-type-mismatch.rs:10:9 +error[E0308]: mismatched types + --> $DIR/closure-arg-type-mismatch.rs:10:5 | -LL | fn baz(_: F) {} - | ------------- required by this bound in `baz` -LL | fn _test<'a>(f: fn(*mut &'a u32)) { LL | baz(f); - | ^ - | | - | expected signature of `for<'r> fn(*mut &'r u32) -> _` - | found signature of `fn(*mut &'a u32) -> _` + | ^^^ one type is more general than the other + | + = note: expected type `for<'r> std::ops::Fn<(*mut &'r u32,)>` + found type `std::ops::Fn<(*mut &'a u32,)>` + +error[E0308]: mismatched types + --> $DIR/closure-arg-type-mismatch.rs:10:5 + | +LL | baz(f); + | ^^^ one type is more general than the other + | + = note: expected type `std::ops::FnOnce<(*mut &u32,)>` + found type `std::ops::FnOnce<(*mut &'a u32,)>` -error[E0271]: type mismatch resolving `for<'r> >::Output == ()` +error[E0308]: mismatched types --> $DIR/closure-arg-type-mismatch.rs:10:5 | -LL | fn baz(_: F) {} - | ------------- required by this bound in `baz` -LL | fn _test<'a>(f: fn(*mut &'a u32)) { LL | baz(f); - | ^^^ expected bound lifetime parameter, found concrete lifetime + | ^^^ one type is more general than the other + | + = note: expected type `for<'r> std::ops::Fn<(*mut &'r u32,)>` + found type `std::ops::Fn<(*mut &'a u32,)>` + +error[E0308]: mismatched types + --> $DIR/closure-arg-type-mismatch.rs:10:5 + | +LL | baz(f); + | ^^^ one type is more general than the other + | + = note: expected type `std::ops::FnOnce<(*mut &u32,)>` + found type `std::ops::FnOnce<(*mut &'a u32,)>` -error: aborting due to 5 previous errors +error: aborting due to 7 previous errors -Some errors have detailed explanations: E0271, E0631. -For more information about an error, try `rustc --explain E0271`. +Some errors have detailed explanations: E0308, E0631. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/closure-mismatch.nll.stderr b/src/test/ui/mismatched_types/closure-mismatch.nll.stderr new file mode 100644 index 0000000000000..745a61b866ed2 --- /dev/null +++ b/src/test/ui/mismatched_types/closure-mismatch.nll.stderr @@ -0,0 +1,14 @@ +error: higher-ranked subtype error + --> $DIR/closure-mismatch.rs:8:5 + | +LL | baz(|_| ()); + | ^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/closure-mismatch.rs:8:5 + | +LL | baz(|_| ()); + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/mismatched_types/closure-mismatch.rs b/src/test/ui/mismatched_types/closure-mismatch.rs index 40a4641fe7196..d2b78b4b7dba5 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.rs +++ b/src/test/ui/mismatched_types/closure-mismatch.rs @@ -5,6 +5,5 @@ impl Foo for T {} fn baz(_: T) {} fn main() { - baz(|_| ()); //~ ERROR type mismatch - //~^ ERROR type mismatch + baz(|_| ()); //~ ERROR mismatched types } diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr index 389b21574465a..d6c17d125cf1e 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-mismatch.stderr @@ -1,28 +1,12 @@ -error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/closure-mismatch.rs:8:9: 8:15] as std::ops::FnOnce<(&'r (),)>>::Output == ()` +error[E0308]: mismatched types --> $DIR/closure-mismatch.rs:8:5 | -LL | fn baz(_: T) {} - | --- required by this bound in `baz` -... LL | baz(|_| ()); - | ^^^ expected bound lifetime parameter, found concrete lifetime + | ^^^ one type is more general than the other | - = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:8:9: 8:15]` + = note: expected type `for<'r> std::ops::Fn<(&'r (),)>` + found type `std::ops::Fn<(&(),)>` -error[E0631]: type mismatch in closure arguments - --> $DIR/closure-mismatch.rs:8:5 - | -LL | fn baz(_: T) {} - | --- required by this bound in `baz` -... -LL | baz(|_| ()); - | ^^^ ------ found signature of `fn(_) -> _` - | | - | expected signature of `for<'r> fn(&'r ()) -> _` - | - = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:8:9: 8:15]` - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0271, E0631. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/moves/issue-46099-move-in-macro.rs b/src/test/ui/moves/issue-46099-move-in-macro.rs new file mode 100644 index 0000000000000..576fe1f4c8905 --- /dev/null +++ b/src/test/ui/moves/issue-46099-move-in-macro.rs @@ -0,0 +1,15 @@ +// Regression test for issue #46099 +// Tests that we don't emit spurious +// 'value moved in previous iteration of loop' message + +macro_rules! test { + ($v:expr) => {{ + drop(&$v); + $v + }} +} + +fn main() { + let b = Box::new(true); + test!({b}); //~ ERROR use of moved value +} diff --git a/src/test/ui/moves/issue-46099-move-in-macro.stderr b/src/test/ui/moves/issue-46099-move-in-macro.stderr new file mode 100644 index 0000000000000..83c99db870951 --- /dev/null +++ b/src/test/ui/moves/issue-46099-move-in-macro.stderr @@ -0,0 +1,14 @@ +error[E0382]: use of moved value: `b` + --> $DIR/issue-46099-move-in-macro.rs:14:12 + | +LL | let b = Box::new(true); + | - move occurs because `b` has type `std::boxed::Box`, which does not implement the `Copy` trait +LL | test!({b}); + | ^ + | | + | value moved here + | value used here after move + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/moves/move-fn-self-receiver.rs b/src/test/ui/moves/move-fn-self-receiver.rs deleted file mode 100644 index 6107f53fa1960..0000000000000 --- a/src/test/ui/moves/move-fn-self-receiver.rs +++ /dev/null @@ -1,74 +0,0 @@ -use std::pin::Pin; -use std::rc::Rc; -use std::ops::Add; - -struct Foo; - -impl Add for Foo { - type Output = (); - fn add(self, _rhs: Self) -> () {} -} - -impl Foo { - fn use_self(self) {} - fn use_box_self(self: Box) {} - fn use_pin_box_self(self: Pin>) {} - fn use_rc_self(self: Rc) {} - fn use_mut_self(&mut self) -> &mut Self { self } -} - -struct Container(Vec); - -impl Container { - fn custom_into_iter(self) -> impl Iterator { - self.0.into_iter() - } -} - -fn move_out(val: Container) { - val.0.into_iter().next(); - val.0; //~ ERROR use of moved - - let foo = Foo; - foo.use_self(); - foo; //~ ERROR use of moved - - let second_foo = Foo; - second_foo.use_self(); - second_foo; //~ ERROR use of moved - - let boxed_foo = Box::new(Foo); - boxed_foo.use_box_self(); - boxed_foo; //~ ERROR use of moved - - let pin_box_foo = Box::pin(Foo); - pin_box_foo.use_pin_box_self(); - pin_box_foo; //~ ERROR use of moved - - let mut mut_foo = Foo; - let ret = mut_foo.use_mut_self(); - mut_foo; //~ ERROR cannot move out - ret; - - let rc_foo = Rc::new(Foo); - rc_foo.use_rc_self(); - rc_foo; //~ ERROR use of moved - - let foo_add = Foo; - foo_add + Foo; - foo_add; //~ ERROR use of moved - - let implicit_into_iter = vec![true]; - for _val in implicit_into_iter {} - implicit_into_iter; //~ ERROR use of moved - - let explicit_into_iter = vec![true]; - for _val in explicit_into_iter.into_iter() {} - explicit_into_iter; //~ ERROR use of moved - - let container = Container(vec![]); - for _val in container.custom_into_iter() {} - container; //~ ERROR use of moved -} - -fn main() {} diff --git a/src/test/ui/moves/move-fn-self-receiver.stderr b/src/test/ui/moves/move-fn-self-receiver.stderr deleted file mode 100644 index 4333e8a23e866..0000000000000 --- a/src/test/ui/moves/move-fn-self-receiver.stderr +++ /dev/null @@ -1,158 +0,0 @@ -error[E0382]: use of moved value: `val.0` - --> $DIR/move-fn-self-receiver.rs:30:5 - | -LL | val.0.into_iter().next(); - | ----------- `val.0` moved due to this method call -LL | val.0; - | ^^^^^ value used here after move - | -note: this function consumes the receiver `self` by taking ownership of it, which moves `val.0` - --> $SRC_DIR/libcore/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^ - = note: move occurs because `val.0` has type `std::vec::Vec`, which does not implement the `Copy` trait - -error[E0382]: use of moved value: `foo` - --> $DIR/move-fn-self-receiver.rs:34:5 - | -LL | let foo = Foo; - | --- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait -LL | foo.use_self(); - | ---------- `foo` moved due to this method call -LL | foo; - | ^^^ value used here after move - | -note: this function consumes the receiver `self` by taking ownership of it, which moves `foo` - --> $DIR/move-fn-self-receiver.rs:13:17 - | -LL | fn use_self(self) {} - | ^^^^ - -error[E0382]: use of moved value: `second_foo` - --> $DIR/move-fn-self-receiver.rs:38:5 - | -LL | let second_foo = Foo; - | ---------- move occurs because `second_foo` has type `Foo`, which does not implement the `Copy` trait -LL | second_foo.use_self(); - | ---------- `second_foo` moved due to this method call -LL | second_foo; - | ^^^^^^^^^^ value used here after move - -error[E0382]: use of moved value: `boxed_foo` - --> $DIR/move-fn-self-receiver.rs:42:5 - | -LL | let boxed_foo = Box::new(Foo); - | --------- move occurs because `boxed_foo` has type `std::boxed::Box`, which does not implement the `Copy` trait -LL | boxed_foo.use_box_self(); - | -------------- `boxed_foo` moved due to this method call -LL | boxed_foo; - | ^^^^^^^^^ value used here after move - | -note: this function consumes the receiver `self` by taking ownership of it, which moves `boxed_foo` - --> $DIR/move-fn-self-receiver.rs:14:21 - | -LL | fn use_box_self(self: Box) {} - | ^^^^ - -error[E0382]: use of moved value: `pin_box_foo` - --> $DIR/move-fn-self-receiver.rs:46:5 - | -LL | let pin_box_foo = Box::pin(Foo); - | ----------- move occurs because `pin_box_foo` has type `std::pin::Pin>`, which does not implement the `Copy` trait -LL | pin_box_foo.use_pin_box_self(); - | ------------------ `pin_box_foo` moved due to this method call -LL | pin_box_foo; - | ^^^^^^^^^^^ value used here after move - | -note: this function consumes the receiver `self` by taking ownership of it, which moves `pin_box_foo` - --> $DIR/move-fn-self-receiver.rs:15:25 - | -LL | fn use_pin_box_self(self: Pin>) {} - | ^^^^ - -error[E0505]: cannot move out of `mut_foo` because it is borrowed - --> $DIR/move-fn-self-receiver.rs:50:5 - | -LL | let ret = mut_foo.use_mut_self(); - | ------- borrow of `mut_foo` occurs here -LL | mut_foo; - | ^^^^^^^ move out of `mut_foo` occurs here -LL | ret; - | --- borrow later used here - -error[E0382]: use of moved value: `rc_foo` - --> $DIR/move-fn-self-receiver.rs:55:5 - | -LL | let rc_foo = Rc::new(Foo); - | ------ move occurs because `rc_foo` has type `std::rc::Rc`, which does not implement the `Copy` trait -LL | rc_foo.use_rc_self(); - | ------------- `rc_foo` moved due to this method call -LL | rc_foo; - | ^^^^^^ value used here after move - | -note: this function consumes the receiver `self` by taking ownership of it, which moves `rc_foo` - --> $DIR/move-fn-self-receiver.rs:16:20 - | -LL | fn use_rc_self(self: Rc) {} - | ^^^^ - -error[E0382]: use of moved value: `foo_add` - --> $DIR/move-fn-self-receiver.rs:59:5 - | -LL | let foo_add = Foo; - | ------- move occurs because `foo_add` has type `Foo`, which does not implement the `Copy` trait -LL | foo_add + Foo; - | ------------- `foo_add` moved due to usage in operator -LL | foo_add; - | ^^^^^^^ value used here after move - | -note: calling this operator moves the left-hand side - --> $SRC_DIR/libcore/ops/arith.rs:LL:COL - | -LL | fn add(self, rhs: Rhs) -> Self::Output; - | ^^^^ - -error[E0382]: use of moved value: `implicit_into_iter` - --> $DIR/move-fn-self-receiver.rs:63:5 - | -LL | let implicit_into_iter = vec![true]; - | ------------------ move occurs because `implicit_into_iter` has type `std::vec::Vec`, which does not implement the `Copy` trait -LL | for _val in implicit_into_iter {} - | ------------------ - | | - | `implicit_into_iter` moved due to this implicit call to `.into_iter()` - | help: consider borrowing to avoid moving into the for loop: `&implicit_into_iter` -LL | implicit_into_iter; - | ^^^^^^^^^^^^^^^^^^ value used here after move - -error[E0382]: use of moved value: `explicit_into_iter` - --> $DIR/move-fn-self-receiver.rs:67:5 - | -LL | let explicit_into_iter = vec![true]; - | ------------------ move occurs because `explicit_into_iter` has type `std::vec::Vec`, which does not implement the `Copy` trait -LL | for _val in explicit_into_iter.into_iter() {} - | ----------- `explicit_into_iter` moved due to this method call -LL | explicit_into_iter; - | ^^^^^^^^^^^^^^^^^^ value used here after move - -error[E0382]: use of moved value: `container` - --> $DIR/move-fn-self-receiver.rs:71:5 - | -LL | let container = Container(vec![]); - | --------- move occurs because `container` has type `Container`, which does not implement the `Copy` trait -LL | for _val in container.custom_into_iter() {} - | ------------------ `container` moved due to this method call -LL | container; - | ^^^^^^^^^ value used here after move - | -note: this function consumes the receiver `self` by taking ownership of it, which moves `container` - --> $DIR/move-fn-self-receiver.rs:23:25 - | -LL | fn custom_into_iter(self) -> impl Iterator { - | ^^^^ - -error: aborting due to 11 previous errors - -Some errors have detailed explanations: E0382, E0505. -For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/moves/move-in-guard-2.stderr b/src/test/ui/moves/move-in-guard-2.stderr index 8bd405279c526..00d89f550714c 100644 --- a/src/test/ui/moves/move-in-guard-2.stderr +++ b/src/test/ui/moves/move-in-guard-2.stderr @@ -5,7 +5,10 @@ LL | let x: Box<_> = box 1; | - move occurs because `x` has type `std::boxed::Box`, which does not implement the `Copy` trait ... LL | (_, 2) if take(x) => (), - | ^ value moved here, in previous iteration of loop + | ^ + | | + | value moved here + | value used here after move error: aborting due to previous error diff --git a/src/test/ui/moves/moves-based-on-type-access-to-field.stderr b/src/test/ui/moves/moves-based-on-type-access-to-field.stderr index 142feb280d153..71a3c4506eaf2 100644 --- a/src/test/ui/moves/moves-based-on-type-access-to-field.stderr +++ b/src/test/ui/moves/moves-based-on-type-access-to-field.stderr @@ -4,15 +4,9 @@ error[E0382]: borrow of moved value: `x` LL | let x = vec!["hi".to_string()]; | - move occurs because `x` has type `std::vec::Vec`, which does not implement the `Copy` trait LL | consume(x.into_iter().next().unwrap()); - | ----------- `x` moved due to this method call + | - value moved here LL | touch(&x[0]); | ^ value borrowed here after move - | -note: this function consumes the receiver `self` by taking ownership of it, which moves `x` - --> $SRC_DIR/libcore/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/moves/moves-based-on-type-exprs.stderr b/src/test/ui/moves/moves-based-on-type-exprs.stderr index ff98aab50c9f8..67fae606c4e43 100644 --- a/src/test/ui/moves/moves-based-on-type-exprs.stderr +++ b/src/test/ui/moves/moves-based-on-type-exprs.stderr @@ -104,15 +104,9 @@ error[E0382]: borrow of moved value: `x` LL | let x = vec!["hi".to_string()]; | - move occurs because `x` has type `std::vec::Vec`, which does not implement the `Copy` trait LL | let _y = x.into_iter().next().unwrap(); - | ----------- `x` moved due to this method call + | - value moved here LL | touch(&x); | ^^ value borrowed here after move - | -note: this function consumes the receiver `self` by taking ownership of it, which moves `x` - --> $SRC_DIR/libcore/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^ error[E0382]: borrow of moved value: `x` --> $DIR/moves-based-on-type-exprs.rs:83:11 @@ -120,15 +114,9 @@ error[E0382]: borrow of moved value: `x` LL | let x = vec!["hi".to_string()]; | - move occurs because `x` has type `std::vec::Vec`, which does not implement the `Copy` trait LL | let _y = [x.into_iter().next().unwrap(); 1]; - | ----------- `x` moved due to this method call + | - value moved here LL | touch(&x); | ^^ value borrowed here after move - | -note: this function consumes the receiver `self` by taking ownership of it, which moves `x` - --> $SRC_DIR/libcore/iter/traits/collect.rs:LL:COL - | -LL | fn into_iter(self) -> Self::IntoIter; - | ^^^^ error: aborting due to 11 previous errors diff --git a/src/test/ui/numeric/numeric-cast-no-fix.rs b/src/test/ui/numeric/numeric-cast-no-fix.rs new file mode 100644 index 0000000000000..63e5f098a25d3 --- /dev/null +++ b/src/test/ui/numeric/numeric-cast-no-fix.rs @@ -0,0 +1,87 @@ +#[allow(unused_must_use)] +fn main() { + let x_usize: usize = 1; + let x_u128: u128 = 2; + let x_u64: u64 = 3; + let x_u32: u32 = 4; + let x_u16: u16 = 5; + let x_u8: u8 = 6; + + x_usize > -1_isize; + //~^ ERROR mismatched types + x_u128 > -1_isize; + //~^ ERROR mismatched types + x_u64 > -1_isize; + //~^ ERROR mismatched types + x_u32 > -1_isize; + //~^ ERROR mismatched types + x_u16 > -1_isize; + //~^ ERROR mismatched types + x_u8 > -1_isize; + //~^ ERROR mismatched types + + x_usize > -1_i128; + //~^ ERROR mismatched types + x_u128 > -1_i128; + //~^ ERROR mismatched types + x_u64 > -1_i128; + //~^ ERROR mismatched types + x_u32 > -1_i128; + //~^ ERROR mismatched types + x_u16 > -1_i128; + //~^ ERROR mismatched types + x_u8 > -1_i128; + //~^ ERROR mismatched types + + x_usize > -1_i64; + //~^ ERROR mismatched types + x_u128 > -1_i64; + //~^ ERROR mismatched types + x_u64 > -1_i64; + //~^ ERROR mismatched types + x_u32 > -1_i64; + //~^ ERROR mismatched types + x_u16 > -1_i64; + //~^ ERROR mismatched types + x_u8 > -1_i64; + //~^ ERROR mismatched types + + x_usize > -1_i32; + //~^ ERROR mismatched types + x_u128 > -1_i32; + //~^ ERROR mismatched types + x_u64 > -1_i32; + //~^ ERROR mismatched types + x_u32 > -1_i32; + //~^ ERROR mismatched types + x_u16 > -1_i32; + //~^ ERROR mismatched types + x_u8 > -1_i32; + //~^ ERROR mismatched types + + x_usize > -1_i16; + //~^ ERROR mismatched types + x_u128 > -1_i16; + //~^ ERROR mismatched types + x_u64 > -1_i16; + //~^ ERROR mismatched types + x_u32 > -1_i16; + //~^ ERROR mismatched types + x_u16 > -1_i16; + //~^ ERROR mismatched types + x_u8 > -1_i16; + //~^ ERROR mismatched types + + x_usize > -1_i8; + //~^ ERROR mismatched types + x_u128 > -1_i8; + //~^ ERROR mismatched types + x_u64 > -1_i8; + //~^ ERROR mismatched types + x_u32 > -1_i8; + //~^ ERROR mismatched types + x_u16 > -1_i8; + //~^ ERROR mismatched types + x_u8 > -1_i8; + //~^ ERROR mismatched types +} diff --git a/src/test/ui/numeric/numeric-cast-no-fix.stderr b/src/test/ui/numeric/numeric-cast-no-fix.stderr new file mode 100644 index 0000000000000..4852e7047b47a --- /dev/null +++ b/src/test/ui/numeric/numeric-cast-no-fix.stderr @@ -0,0 +1,324 @@ +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:10:15 + | +LL | x_usize > -1_isize; + | ^^^^^^^^ expected `usize`, found `isize` + | + = note: `-1_isize` cannot fit into type `usize` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:12:14 + | +LL | x_u128 > -1_isize; + | ^^^^^^^^ expected `u128`, found `isize` + | + = note: `-1_isize` cannot fit into type `u128` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:14:13 + | +LL | x_u64 > -1_isize; + | ^^^^^^^^ expected `u64`, found `isize` + | + = note: `-1_isize` cannot fit into type `u64` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:16:13 + | +LL | x_u32 > -1_isize; + | ^^^^^^^^ expected `u32`, found `isize` + | + = note: `-1_isize` cannot fit into type `u32` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:18:13 + | +LL | x_u16 > -1_isize; + | ^^^^^^^^ expected `u16`, found `isize` + | + = note: `-1_isize` cannot fit into type `u16` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:20:12 + | +LL | x_u8 > -1_isize; + | ^^^^^^^^ expected `u8`, found `isize` + | +help: you can convert `x_u8` from `u8` to `isize`, matching the type of `-1_isize` + | +LL | isize::from(x_u8) > -1_isize; + | ^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:23:15 + | +LL | x_usize > -1_i128; + | ^^^^^^^ expected `usize`, found `i128` + | + = note: `-1_i128` cannot fit into type `usize` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:25:14 + | +LL | x_u128 > -1_i128; + | ^^^^^^^ expected `u128`, found `i128` + | + = note: `-1_i128` cannot fit into type `u128` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:27:13 + | +LL | x_u64 > -1_i128; + | ^^^^^^^ expected `u64`, found `i128` + | +help: you can convert `x_u64` from `u64` to `i128`, matching the type of `-1_i128` + | +LL | i128::from(x_u64) > -1_i128; + | ^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:29:13 + | +LL | x_u32 > -1_i128; + | ^^^^^^^ expected `u32`, found `i128` + | +help: you can convert `x_u32` from `u32` to `i128`, matching the type of `-1_i128` + | +LL | i128::from(x_u32) > -1_i128; + | ^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:31:13 + | +LL | x_u16 > -1_i128; + | ^^^^^^^ expected `u16`, found `i128` + | +help: you can convert `x_u16` from `u16` to `i128`, matching the type of `-1_i128` + | +LL | i128::from(x_u16) > -1_i128; + | ^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:33:12 + | +LL | x_u8 > -1_i128; + | ^^^^^^^ expected `u8`, found `i128` + | +help: you can convert `x_u8` from `u8` to `i128`, matching the type of `-1_i128` + | +LL | i128::from(x_u8) > -1_i128; + | ^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:36:15 + | +LL | x_usize > -1_i64; + | ^^^^^^ expected `usize`, found `i64` + | + = note: `-1_i64` cannot fit into type `usize` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:38:14 + | +LL | x_u128 > -1_i64; + | ^^^^^^ expected `u128`, found `i64` + | + = note: `-1_i64` cannot fit into type `u128` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:40:13 + | +LL | x_u64 > -1_i64; + | ^^^^^^ expected `u64`, found `i64` + | + = note: `-1_i64` cannot fit into type `u64` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:42:13 + | +LL | x_u32 > -1_i64; + | ^^^^^^ expected `u32`, found `i64` + | +help: you can convert `x_u32` from `u32` to `i64`, matching the type of `-1_i64` + | +LL | i64::from(x_u32) > -1_i64; + | ^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:44:13 + | +LL | x_u16 > -1_i64; + | ^^^^^^ expected `u16`, found `i64` + | +help: you can convert `x_u16` from `u16` to `i64`, matching the type of `-1_i64` + | +LL | i64::from(x_u16) > -1_i64; + | ^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:46:12 + | +LL | x_u8 > -1_i64; + | ^^^^^^ expected `u8`, found `i64` + | +help: you can convert `x_u8` from `u8` to `i64`, matching the type of `-1_i64` + | +LL | i64::from(x_u8) > -1_i64; + | ^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:49:15 + | +LL | x_usize > -1_i32; + | ^^^^^^ expected `usize`, found `i32` + | + = note: `-1_i32` cannot fit into type `usize` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:51:14 + | +LL | x_u128 > -1_i32; + | ^^^^^^ expected `u128`, found `i32` + | + = note: `-1_i32` cannot fit into type `u128` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:53:13 + | +LL | x_u64 > -1_i32; + | ^^^^^^ expected `u64`, found `i32` + | + = note: `-1_i32` cannot fit into type `u64` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:55:13 + | +LL | x_u32 > -1_i32; + | ^^^^^^ expected `u32`, found `i32` + | + = note: `-1_i32` cannot fit into type `u32` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:57:13 + | +LL | x_u16 > -1_i32; + | ^^^^^^ expected `u16`, found `i32` + | +help: you can convert `x_u16` from `u16` to `i32`, matching the type of `-1_i32` + | +LL | i32::from(x_u16) > -1_i32; + | ^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:59:12 + | +LL | x_u8 > -1_i32; + | ^^^^^^ expected `u8`, found `i32` + | +help: you can convert `x_u8` from `u8` to `i32`, matching the type of `-1_i32` + | +LL | i32::from(x_u8) > -1_i32; + | ^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:62:15 + | +LL | x_usize > -1_i16; + | ^^^^^^ expected `usize`, found `i16` + | + = note: `-1_i16` cannot fit into type `usize` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:64:14 + | +LL | x_u128 > -1_i16; + | ^^^^^^ expected `u128`, found `i16` + | + = note: `-1_i16` cannot fit into type `u128` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:66:13 + | +LL | x_u64 > -1_i16; + | ^^^^^^ expected `u64`, found `i16` + | + = note: `-1_i16` cannot fit into type `u64` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:68:13 + | +LL | x_u32 > -1_i16; + | ^^^^^^ expected `u32`, found `i16` + | + = note: `-1_i16` cannot fit into type `u32` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:70:13 + | +LL | x_u16 > -1_i16; + | ^^^^^^ expected `u16`, found `i16` + | + = note: `-1_i16` cannot fit into type `u16` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:72:12 + | +LL | x_u8 > -1_i16; + | ^^^^^^ expected `u8`, found `i16` + | +help: you can convert `x_u8` from `u8` to `i16`, matching the type of `-1_i16` + | +LL | i16::from(x_u8) > -1_i16; + | ^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:75:15 + | +LL | x_usize > -1_i8; + | ^^^^^ expected `usize`, found `i8` + | + = note: `-1_i8` cannot fit into type `usize` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:77:14 + | +LL | x_u128 > -1_i8; + | ^^^^^ expected `u128`, found `i8` + | + = note: `-1_i8` cannot fit into type `u128` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:79:13 + | +LL | x_u64 > -1_i8; + | ^^^^^ expected `u64`, found `i8` + | + = note: `-1_i8` cannot fit into type `u64` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:81:13 + | +LL | x_u32 > -1_i8; + | ^^^^^ expected `u32`, found `i8` + | + = note: `-1_i8` cannot fit into type `u32` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:83:13 + | +LL | x_u16 > -1_i8; + | ^^^^^ expected `u16`, found `i8` + | + = note: `-1_i8` cannot fit into type `u16` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:85:12 + | +LL | x_u8 > -1_i8; + | ^^^^^ expected `u8`, found `i8` + | + = note: `-1_i8` cannot fit into type `u8` + +error: aborting due to 36 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/once-cant-call-twice-on-heap.stderr b/src/test/ui/once-cant-call-twice-on-heap.stderr index 8761b5261d51b..7133a32431a67 100644 --- a/src/test/ui/once-cant-call-twice-on-heap.stderr +++ b/src/test/ui/once-cant-call-twice-on-heap.stderr @@ -4,15 +4,10 @@ error[E0382]: use of moved value: `blk` LL | fn foo(blk: F) { | --- move occurs because `blk` has type `F`, which does not implement the `Copy` trait LL | blk(); - | ----- `blk` moved due to this call + | --- value moved here LL | blk(); | ^^^ value used here after move | -note: this value implements `FnOnce`, which causes it to be moved when called - --> $DIR/once-cant-call-twice-on-heap.rs:8:5 - | -LL | blk(); - | ^^^ help: consider further restricting this bound | LL | fn foo(blk: F) { diff --git a/src/test/ui/overlap-doesnt-conflict-with-specialization.rs b/src/test/ui/overlap-doesnt-conflict-with-specialization.rs index dd09d68367ec3..1e413120a3717 100644 --- a/src/test/ui/overlap-doesnt-conflict-with-specialization.rs +++ b/src/test/ui/overlap-doesnt-conflict-with-specialization.rs @@ -1,7 +1,7 @@ // run-pass #![feature(marker_trait_attr)] -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete #[marker] trait MyMarker {} diff --git a/src/test/ui/overlap-doesnt-conflict-with-specialization.stderr b/src/test/ui/overlap-doesnt-conflict-with-specialization.stderr new file mode 100644 index 0000000000000..16df31ba2a88b --- /dev/null +++ b/src/test/ui/overlap-doesnt-conflict-with-specialization.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/overlap-doesnt-conflict-with-specialization.rs:4:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/parser/assoc-static-semantic-fail.rs b/src/test/ui/parser/assoc-static-semantic-fail.rs index 215a292131521..a8759d2090d0f 100644 --- a/src/test/ui/parser/assoc-static-semantic-fail.rs +++ b/src/test/ui/parser/assoc-static-semantic-fail.rs @@ -1,6 +1,7 @@ // Semantically, we do not allow e.g., `static X: u8 = 0;` as an associated item. #![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete fn main() {} diff --git a/src/test/ui/parser/assoc-static-semantic-fail.stderr b/src/test/ui/parser/assoc-static-semantic-fail.stderr index 612297c9cd8b1..bc3054c3e3062 100644 --- a/src/test/ui/parser/assoc-static-semantic-fail.stderr +++ b/src/test/ui/parser/assoc-static-semantic-fail.stderr @@ -1,17 +1,17 @@ error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:9:5 + --> $DIR/assoc-static-semantic-fail.rs:10:5 | LL | static IA: u8 = 0; | ^^^^^^^^^^^^^^^^^^ error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:11:5 + --> $DIR/assoc-static-semantic-fail.rs:12:5 | LL | static IB: u8; | ^^^^^^^^^^^^^^ error: a static item cannot be `default` - --> $DIR/assoc-static-semantic-fail.rs:14:5 + --> $DIR/assoc-static-semantic-fail.rs:15:5 | LL | default static IC: u8 = 0; | ^^^^^^^ `default` because of this @@ -19,13 +19,13 @@ LL | default static IC: u8 = 0; = note: only associated `fn`, `const`, and `type` items can be `default` error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:14:5 + --> $DIR/assoc-static-semantic-fail.rs:15:5 | LL | default static IC: u8 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a static item cannot be `default` - --> $DIR/assoc-static-semantic-fail.rs:17:16 + --> $DIR/assoc-static-semantic-fail.rs:18:16 | LL | pub(crate) default static ID: u8; | ^^^^^^^ `default` because of this @@ -33,25 +33,25 @@ LL | pub(crate) default static ID: u8; = note: only associated `fn`, `const`, and `type` items can be `default` error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:17:5 + --> $DIR/assoc-static-semantic-fail.rs:18:5 | LL | pub(crate) default static ID: u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:24:5 + --> $DIR/assoc-static-semantic-fail.rs:25:5 | LL | static TA: u8 = 0; | ^^^^^^^^^^^^^^^^^^ error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:26:5 + --> $DIR/assoc-static-semantic-fail.rs:27:5 | LL | static TB: u8; | ^^^^^^^^^^^^^^ error: a static item cannot be `default` - --> $DIR/assoc-static-semantic-fail.rs:28:5 + --> $DIR/assoc-static-semantic-fail.rs:29:5 | LL | default static TC: u8 = 0; | ^^^^^^^ `default` because of this @@ -59,13 +59,13 @@ LL | default static TC: u8 = 0; = note: only associated `fn`, `const`, and `type` items can be `default` error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:28:5 + --> $DIR/assoc-static-semantic-fail.rs:29:5 | LL | default static TC: u8 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a static item cannot be `default` - --> $DIR/assoc-static-semantic-fail.rs:31:16 + --> $DIR/assoc-static-semantic-fail.rs:32:16 | LL | pub(crate) default static TD: u8; | ^^^^^^^ `default` because of this @@ -73,25 +73,25 @@ LL | pub(crate) default static TD: u8; = note: only associated `fn`, `const`, and `type` items can be `default` error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:31:5 + --> $DIR/assoc-static-semantic-fail.rs:32:5 | LL | pub(crate) default static TD: u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:38:5 + --> $DIR/assoc-static-semantic-fail.rs:39:5 | LL | static TA: u8 = 0; | ^^^^^^^^^^^^^^^^^^ error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:40:5 + --> $DIR/assoc-static-semantic-fail.rs:41:5 | LL | static TB: u8; | ^^^^^^^^^^^^^^ error: a static item cannot be `default` - --> $DIR/assoc-static-semantic-fail.rs:43:5 + --> $DIR/assoc-static-semantic-fail.rs:44:5 | LL | default static TC: u8 = 0; | ^^^^^^^ `default` because of this @@ -99,13 +99,13 @@ LL | default static TC: u8 = 0; = note: only associated `fn`, `const`, and `type` items can be `default` error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:43:5 + --> $DIR/assoc-static-semantic-fail.rs:44:5 | LL | default static TC: u8 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a static item cannot be `default` - --> $DIR/assoc-static-semantic-fail.rs:46:9 + --> $DIR/assoc-static-semantic-fail.rs:47:9 | LL | pub default static TD: u8; | ^^^^^^^ `default` because of this @@ -113,13 +113,13 @@ LL | pub default static TD: u8; = note: only associated `fn`, `const`, and `type` items can be `default` error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:46:5 + --> $DIR/assoc-static-semantic-fail.rs:47:5 | LL | pub default static TD: u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: associated constant in `impl` without body - --> $DIR/assoc-static-semantic-fail.rs:11:5 + --> $DIR/assoc-static-semantic-fail.rs:12:5 | LL | static IB: u8; | ^^^^^^^^^^^^^- @@ -127,7 +127,7 @@ LL | static IB: u8; | help: provide a definition for the constant: `= ;` error: associated constant in `impl` without body - --> $DIR/assoc-static-semantic-fail.rs:17:5 + --> $DIR/assoc-static-semantic-fail.rs:18:5 | LL | pub(crate) default static ID: u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -135,13 +135,13 @@ LL | pub(crate) default static ID: u8; | help: provide a definition for the constant: `= ;` error[E0449]: unnecessary visibility qualifier - --> $DIR/assoc-static-semantic-fail.rs:31:5 + --> $DIR/assoc-static-semantic-fail.rs:32:5 | LL | pub(crate) default static TD: u8; | ^^^^^^^^^^ error: associated constant in `impl` without body - --> $DIR/assoc-static-semantic-fail.rs:40:5 + --> $DIR/assoc-static-semantic-fail.rs:41:5 | LL | static TB: u8; | ^^^^^^^^^^^^^- @@ -149,7 +149,7 @@ LL | static TB: u8; | help: provide a definition for the constant: `= ;` error: associated constant in `impl` without body - --> $DIR/assoc-static-semantic-fail.rs:46:5 + --> $DIR/assoc-static-semantic-fail.rs:47:5 | LL | pub default static TD: u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -157,11 +157,20 @@ LL | pub default static TD: u8; | help: provide a definition for the constant: `= ;` error[E0449]: unnecessary visibility qualifier - --> $DIR/assoc-static-semantic-fail.rs:46:5 + --> $DIR/assoc-static-semantic-fail.rs:47:5 | LL | pub default static TD: u8; | ^^^ `pub` not permitted here because it's implied -error: aborting due to 24 previous errors +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/assoc-static-semantic-fail.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +error: aborting due to 24 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0449`. diff --git a/src/test/ui/parser/default.rs b/src/test/ui/parser/default.rs index 64ba4b5531184..52338c1f13aad 100644 --- a/src/test/ui/parser/default.rs +++ b/src/test/ui/parser/default.rs @@ -1,6 +1,7 @@ // Test successful and unsuccessful parsing of the `default` contextual keyword #![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete trait Foo { fn foo() -> T; diff --git a/src/test/ui/parser/default.stderr b/src/test/ui/parser/default.stderr index 15c49e8b6270b..dea35666f37b5 100644 --- a/src/test/ui/parser/default.stderr +++ b/src/test/ui/parser/default.stderr @@ -1,5 +1,5 @@ error: `default` is not followed by an item - --> $DIR/default.rs:22:5 + --> $DIR/default.rs:23:5 | LL | default pub fn foo() -> T { T::default() } | ^^^^^^^ the `default` qualifier @@ -7,7 +7,7 @@ LL | default pub fn foo() -> T { T::default() } = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default` error: non-item in item list - --> $DIR/default.rs:22:13 + --> $DIR/default.rs:23:13 | LL | impl Foo for u32 { | - item list starts here @@ -18,13 +18,22 @@ LL | } | - item list ends here error[E0449]: unnecessary visibility qualifier - --> $DIR/default.rs:16:5 + --> $DIR/default.rs:17:5 | LL | pub default fn foo() -> T { | ^^^ `pub` not permitted here because it's implied +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/default.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + error[E0046]: not all trait items implemented, missing: `foo` - --> $DIR/default.rs:21:1 + --> $DIR/default.rs:22:1 | LL | fn foo() -> T; | -------------------------- `foo` from trait @@ -32,7 +41,7 @@ LL | fn foo() -> T; LL | impl Foo for u32 { | ^^^^^^^^^^^^^^^^ missing `foo` in implementation -error: aborting due to 4 previous errors +error: aborting due to 4 previous errors; 1 warning emitted Some errors have detailed explanations: E0046, E0449. For more information about an error, try `rustc --explain E0046`. 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 4ecb21d26ab9b..a516aa44c6576 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,3 +1,4 @@ +#![allow(clashing_extern_decl)] // check-pass // In this test we check that the parser accepts an ABI string when it diff --git a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs index 09f967f161ede..34aee7f69359e 100644 --- a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs +++ b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs @@ -1,4 +1,4 @@ -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete fn main() {} diff --git a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr index 6bb946d5b6470..e8ff93f63237d 100644 --- a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr +++ b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr @@ -46,5 +46,14 @@ LL | default fn f2() {} | | | `default` because of this -error: aborting due to 6 previous errors +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +error: aborting due to 6 previous errors; 1 warning emitted diff --git a/src/test/ui/parser/unbalanced-doublequote.stderr b/src/test/ui/parser/unbalanced-doublequote.stderr index 4d98515c224ad..94b300a7bd765 100644 --- a/src/test/ui/parser/unbalanced-doublequote.stderr +++ b/src/test/ui/parser/unbalanced-doublequote.stderr @@ -1,4 +1,4 @@ -error: unterminated double quote string +error[E0765]: unterminated double quote string --> $DIR/unbalanced-doublequote.rs:5:5 | LL | / " @@ -7,3 +7,4 @@ LL | | } error: aborting due to previous error +For more information about this error, try `rustc --explain E0765`. diff --git a/src/test/ui/privacy/privacy-ns1.stderr b/src/test/ui/privacy/privacy-ns1.stderr index 4d2af735fa6b9..eda9d4c128d81 100644 --- a/src/test/ui/privacy/privacy-ns1.stderr +++ b/src/test/ui/privacy/privacy-ns1.stderr @@ -11,14 +11,10 @@ help: a unit struct with a similar name exists | LL | Baz(); | ^^^ -help: consider importing one of these items instead - | -LL | use foo1::Bar; +help: consider importing this function instead | LL | use foo2::Bar; | -LL | use foo3::Bar; - | error[E0425]: cannot find function, tuple struct or tuple variant `Bar` in this scope --> $DIR/privacy-ns1.rs:51:5 @@ -33,14 +29,10 @@ help: a unit struct with a similar name exists | LL | Baz(); | ^^^ -help: consider importing one of these items - | -LL | use foo1::Bar; +help: consider importing this function | LL | use foo2::Bar; | -LL | use foo3::Bar; - | error[E0412]: cannot find type `Bar` in this scope --> $DIR/privacy-ns1.rs:52:17 @@ -55,14 +47,10 @@ help: a struct with a similar name exists | LL | let _x: Box; | ^^^ -help: consider importing one of these items +help: consider importing this trait | LL | use foo1::Bar; | -LL | use foo2::Bar; - | -LL | use foo3::Bar; - | error[E0107]: wrong number of const arguments: expected 0, found 1 --> $DIR/privacy-ns1.rs:35:17 diff --git a/src/test/ui/privacy/privacy-ns2.stderr b/src/test/ui/privacy/privacy-ns2.stderr index f1aa523742ae4..d7d9b83527509 100644 --- a/src/test/ui/privacy/privacy-ns2.stderr +++ b/src/test/ui/privacy/privacy-ns2.stderr @@ -4,14 +4,10 @@ error[E0423]: expected function, tuple struct or tuple variant, found trait `Bar LL | Bar(); | ^^^ not a function, tuple struct or tuple variant | -help: consider importing one of these items instead - | -LL | use foo1::Bar; +help: consider importing this function instead | LL | use foo2::Bar; | -LL | use foo3::Bar; - | error[E0423]: expected function, tuple struct or tuple variant, found trait `Bar` --> $DIR/privacy-ns2.rs:26:5 @@ -26,14 +22,10 @@ help: a unit struct with a similar name exists | LL | Baz(); | ^^^ -help: consider importing one of these items instead - | -LL | use foo1::Bar; +help: consider importing this function instead | LL | use foo2::Bar; | -LL | use foo3::Bar; - | error[E0573]: expected type, found function `Bar` --> $DIR/privacy-ns2.rs:43:14 @@ -45,14 +37,10 @@ help: use `=` if you meant to assign | LL | let _x = Bar(); | ^ -help: consider importing one of these items instead +help: consider importing this trait instead | LL | use foo1::Bar; | -LL | use foo2::Bar; - | -LL | use foo3::Bar; - | error[E0603]: trait `Bar` is private --> $DIR/privacy-ns2.rs:63:15 diff --git a/src/test/ui/proc-macro/auxiliary/first-second.rs b/src/test/ui/proc-macro/auxiliary/first-second.rs new file mode 100644 index 0000000000000..6331608fbe543 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/first-second.rs @@ -0,0 +1,20 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, Group, Delimiter}; + +#[proc_macro_attribute] +pub fn first(_attr: TokenStream, item: TokenStream) -> TokenStream { + let tokens: TokenStream = "#[derive(Second)]".parse().unwrap(); + let wrapped = TokenTree::Group(Group::new(Delimiter::None, item.into_iter().collect())); + tokens.into_iter().chain(std::iter::once(wrapped)).collect() +} + +#[proc_macro_derive(Second)] +pub fn second(item: TokenStream) -> TokenStream { + TokenStream::new() +} diff --git a/src/test/ui/proc-macro/auxiliary/recollect.rs b/src/test/ui/proc-macro/auxiliary/recollect.rs new file mode 100644 index 0000000000000..d4494a5aff2e9 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/recollect.rs @@ -0,0 +1,12 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro] +pub fn recollect(tokens: TokenStream) -> TokenStream { + tokens.into_iter().collect() +} diff --git a/src/test/ui/proc-macro/auxiliary/weird-hygiene.rs b/src/test/ui/proc-macro/auxiliary/weird-hygiene.rs new file mode 100644 index 0000000000000..338e436df500f --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/weird-hygiene.rs @@ -0,0 +1,48 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, Group}; + +fn find_my_ident(tokens: TokenStream) -> Option { + for token in tokens { + if let TokenTree::Ident(ident) = &token { + if ident.to_string() == "hidden_ident" { + return Some(vec![token].into_iter().collect()) + } + } else if let TokenTree::Group(g) = token { + if let Some(stream) = find_my_ident(g.stream()) { + return Some(stream) + } + } + } + return None; +} + + +#[proc_macro_derive(WeirdDerive)] +pub fn weird_derive(item: TokenStream) -> TokenStream { + let my_ident = find_my_ident(item).expect("Missing 'my_ident'!"); + let tokens: TokenStream = "call_it!();".parse().unwrap(); + let final_call = tokens.into_iter().map(|tree| { + if let TokenTree::Group(g) = tree { + return Group::new(g.delimiter(), my_ident.clone()).into() + } else { + return tree + } + }).collect(); + final_call +} + +#[proc_macro] +pub fn recollect(item: TokenStream) -> TokenStream { + item.into_iter().collect() +} + +#[proc_macro_attribute] +pub fn recollect_attr(_attr: TokenStream, mut item: TokenStream) -> TokenStream { + item.into_iter().collect() +} diff --git a/src/test/ui/proc-macro/capture-macro-rules-invoke.rs b/src/test/ui/proc-macro/capture-macro-rules-invoke.rs new file mode 100644 index 0000000000000..a404ddace9bbe --- /dev/null +++ b/src/test/ui/proc-macro/capture-macro-rules-invoke.rs @@ -0,0 +1,22 @@ +// aux-build:test-macros.rs +// check-pass + +extern crate test_macros; +use test_macros::recollect; + +macro_rules! use_expr { + ($expr:expr) => { + recollect!($expr) + } +} + +#[allow(dead_code)] +struct Foo; +impl Foo { + #[allow(dead_code)] + fn use_self(self) { + drop(use_expr!(self)); + } +} + +fn main() {} diff --git a/src/test/ui/proc-macro/macro-rules-derive.rs b/src/test/ui/proc-macro/macro-rules-derive.rs new file mode 100644 index 0000000000000..5b4d577a1acc4 --- /dev/null +++ b/src/test/ui/proc-macro/macro-rules-derive.rs @@ -0,0 +1,20 @@ +// aux-build:first-second.rs +// FIXME: The spans here are bad, see PR #73084 + +extern crate first_second; +use first_second::*; + +macro_rules! produce_it { + ($name:ident) => { + #[first] //~ ERROR cannot find type + struct $name { + field: MissingType + } + } +} + +produce_it!(MyName); + +fn main() { + println!("Hello, world!"); +} diff --git a/src/test/ui/proc-macro/macro-rules-derive.stderr b/src/test/ui/proc-macro/macro-rules-derive.stderr new file mode 100644 index 0000000000000..4b72d29fe8ae0 --- /dev/null +++ b/src/test/ui/proc-macro/macro-rules-derive.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `MissingType` in this scope + --> $DIR/macro-rules-derive.rs:9:9 + | +LL | #[first] + | ^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/proc-macro/weird-hygiene.rs b/src/test/ui/proc-macro/weird-hygiene.rs new file mode 100644 index 0000000000000..3f48191b5b26e --- /dev/null +++ b/src/test/ui/proc-macro/weird-hygiene.rs @@ -0,0 +1,48 @@ +// aux-build:weird-hygiene.rs +// check-pass +// FIXME: This should actually error, see PR #73084 + +#![feature(stmt_expr_attributes)] +#![feature(proc_macro_hygiene)] + +extern crate weird_hygiene; +use weird_hygiene::*; + +macro_rules! other { + ($tokens:expr) => { + macro_rules! call_it { + ($outer_ident:ident) => { + macro_rules! inner { + () => { + $outer_ident; + } + } + } + } + + #[derive(WeirdDerive)] + enum MyEnum { + Value = (stringify!($tokens + hidden_ident), 1).1 + } + + inner!(); + } +} + +macro_rules! invoke_it { + ($token:expr) => { + #[recollect_attr] { + $token; + hidden_ident + } + } +} + +fn main() { + // `other` and `invoke_it` are both macro_rules! macros, + // so it should be impossible for them to ever see `hidden_ident`, + // even if they invoke a proc macro. + let hidden_ident = "Hello1"; + other!(50); + invoke_it!(25); +} diff --git a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr index de6df4cd0268c..0552847c48ca9 100644 --- a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr +++ b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr @@ -1,4 +1,22 @@ error: reached the recursion limit while instantiating `std::intrinsics::drop_in_place::> - shim(Some(S))` + --> $SRC_DIR/libcore/ptr/mod.rs:LL:COL + | +LL | / pub unsafe fn drop_in_place(to_drop: *mut T) { +LL | | // Code here does not matter - this is replaced by the +LL | | // real drop glue by the compiler. +LL | | drop_in_place(to_drop) +LL | | } + | |_^ + | +note: `std::intrinsics::drop_in_place` defined here + --> $SRC_DIR/libcore/ptr/mod.rs:LL:COL + | +LL | / pub unsafe fn drop_in_place(to_drop: *mut T) { +LL | | // Code here does not matter - this is replaced by the +LL | | // real drop glue by the compiler. +LL | | drop_in_place(to_drop) +LL | | } + | |_^ error: aborting due to previous error diff --git a/src/test/ui/recursion/recursion.rs b/src/test/ui/recursion/recursion.rs index bf1eaef367d69..373cc17d0e0fe 100644 --- a/src/test/ui/recursion/recursion.rs +++ b/src/test/ui/recursion/recursion.rs @@ -12,11 +12,10 @@ impl Dot for Cons { self.head * other.head + self.tail.dot(other.tail) } } -fn test (n:isize, i:isize, first:T, second:T) ->isize { //~ ERROR recursion limit +fn test (n:isize, i:isize, first:T, second:T) ->isize { match n { 0 => {first.dot(second)} - // FIXME(#4287) Error message should be here. It should be - // a type error to instantiate `test` at a type other than T. _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})} + //~^ ERROR recursion limit } } pub fn main() { diff --git a/src/test/ui/recursion/recursion.stderr b/src/test/ui/recursion/recursion.stderr index 1a65b0e84f6a3..0c0eba68c83b4 100644 --- a/src/test/ui/recursion/recursion.stderr +++ b/src/test/ui/recursion/recursion.stderr @@ -1,11 +1,16 @@ error: reached the recursion limit while instantiating `test::>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + --> $DIR/recursion.rs:17:11 + | +LL | _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `test` defined here --> $DIR/recursion.rs:15:1 | LL | / fn test (n:isize, i:isize, first:T, second:T) ->isize { LL | | match n { 0 => {first.dot(second)} -LL | | // FIXME(#4287) Error message should be here. It should be -LL | | // a type error to instantiate `test` at a type other than T. LL | | _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})} +LL | | LL | | } LL | | } | |_^ diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.nll.stderr b/src/test/ui/regions-fn-subtyping-return-static-fail.nll.stderr new file mode 100644 index 0000000000000..d762f55f9d5f1 --- /dev/null +++ b/src/test/ui/regions-fn-subtyping-return-static-fail.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/regions-fn-subtyping-return-static-fail.rs:48:5 + | +LL | want_G(baz); + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.rs b/src/test/ui/regions-fn-subtyping-return-static-fail.rs index 2dd0c9796e258..539221b5a046c 100644 --- a/src/test/ui/regions-fn-subtyping-return-static-fail.rs +++ b/src/test/ui/regions-fn-subtyping-return-static-fail.rs @@ -13,11 +13,11 @@ struct S; // Given 'cx, return 'cx type F = for<'cx> fn(&'cx S) -> &'cx S; -fn want_F(f: F) { } +fn want_F(f: F) {} // Given anything, return 'static type G = for<'cx> fn(&'cx S) -> &'static S; -fn want_G(f: G) { } +fn want_G(f: G) {} // Should meet both. fn foo(x: &S) -> &'static S { @@ -25,7 +25,7 @@ fn foo(x: &S) -> &'static S { } // Should meet both. -fn bar<'a,'b>(x: &'a S) -> &'b S { +fn bar<'a, 'b>(x: &'a S) -> &'b S { panic!() } @@ -37,7 +37,7 @@ fn baz(x: &S) -> &S { fn supply_F() { want_F(foo); - want_F(bar); //~ ERROR mismatched types + want_F(bar); want_F(baz); } @@ -48,5 +48,4 @@ fn supply_G() { want_G(baz); //~ ERROR mismatched types } -pub fn main() { -} +pub fn main() {} diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr index 27704b3e0a8c7..c9ce936c7d43f 100644 --- a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr +++ b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr @@ -1,21 +1,12 @@ -error[E0308]: mismatched types - --> $DIR/regions-fn-subtyping-return-static-fail.rs:40:12 - | -LL | want_F(bar); - | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx - | - = note: expected fn pointer `for<'cx> fn(&'cx S) -> &'cx S` - found fn item `for<'a> fn(&'a S) -> &S {bar::<'_>}` - error[E0308]: mismatched types --> $DIR/regions-fn-subtyping-return-static-fail.rs:48:12 | LL | want_G(baz); - | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx + | ^^^ one type is more general than the other | = note: expected fn pointer `for<'cx> fn(&'cx S) -> &'static S` - found fn item `for<'r> fn(&'r S) -> &'r S {baz}` + found fn pointer `for<'r> fn(&'r S) -> &'r S` -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr index c3e8789a903b1..695f5506d5e38 100644 --- a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr +++ b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr @@ -1,14 +1,40 @@ -error[E0308]: mismatched types - --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:43 +error: lifetime may not live long enough + --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:8:5 + | +LL | fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Illegal now because there is no `'b:'a` declaration. +LL | *x = *y; + | ^^^^^^^ assignment requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:14:5 + | +LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | a(x, y); + | ^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: higher-ranked subtype error + --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:12 | LL | let _: fn(&mut &isize, &mut &isize) = a; - | ---------------------------- ^ expected concrete lifetime, found bound lifetime parameter - | | - | expected due to this + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:12 | - = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` - found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` +LL | let _: fn(&mut &isize, &mut &isize) = a; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr index 159d32b50b03c..b83e07663faba 100644 --- a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr +++ b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr @@ -20,12 +20,10 @@ error[E0308]: mismatched types --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:43 | LL | let _: fn(&mut &isize, &mut &isize) = a; - | ---------------------------- ^ expected concrete lifetime, found bound lifetime parameter - | | - | expected due to this + | ^ one type is more general than the other | = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` - found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` + found fn pointer `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)` error: aborting due to 3 previous errors diff --git a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr index 2aadd8f4f8c7e..a28f7aa3e08ca 100644 --- a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr +++ b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr @@ -1,14 +1,46 @@ -error[E0308]: mismatched types - --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:56 +error: lifetime may not live long enough + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:9:5 + | +LL | fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Illegal now because there is no `'b:'a` declaration. +LL | *x = *y; + | ^^^^^^^ assignment requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:16:5 + | +LL | fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | a(x, y, z); + | ^^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: higher-ranked subtype error + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12 | LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; - | ----------------------------------------- ^ expected concrete lifetime, found bound lifetime parameter - | | - | expected due to this + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12 | - = note: expected fn pointer `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)` - found fn item `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize) {a::<'_, '_, '_>}` +LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12 + | +LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr index dda6129e19536..c93f2890f1110 100644 --- a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr +++ b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr @@ -31,12 +31,10 @@ error[E0308]: mismatched types --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:56 | LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; - | ----------------------------------------- ^ expected concrete lifetime, found bound lifetime parameter - | | - | expected due to this + | ^ one type is more general than the other | = note: expected fn pointer `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)` - found fn item `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize) {a::<'_, '_, '_>}` + found fn pointer `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize)` error: aborting due to 4 previous errors diff --git a/src/test/ui/regions/regions-fn-subtyping-return-static.rs b/src/test/ui/regions/regions-fn-subtyping-return-static.rs index fa2cc37d05b2b..de14d5ba82a1b 100644 --- a/src/test/ui/regions/regions-fn-subtyping-return-static.rs +++ b/src/test/ui/regions/regions-fn-subtyping-return-static.rs @@ -5,6 +5,8 @@ // *ANY* lifetime and returns a reference with the 'static lifetime. // This can safely be considered to be an instance of `F` because all // lifetimes are sublifetimes of 'static. +// +// check-pass #![allow(dead_code)] #![allow(unused_variables)] @@ -14,11 +16,11 @@ struct S; // Given 'cx, return 'cx type F = for<'cx> fn(&'cx S) -> &'cx S; -fn want_F(f: F) { } +fn want_F(f: F) {} // Given anything, return 'static type G = for<'cx> fn(&'cx S) -> &'static S; -fn want_G(f: G) { } +fn want_G(f: G) {} // Should meet both. fn foo(x: &S) -> &'static S { @@ -26,7 +28,7 @@ fn foo(x: &S) -> &'static S { } // Should meet both. -fn bar<'a,'b>(x: &'a S) -> &'b S { +fn bar<'a, 'b>(x: &'a S) -> &'b S { panic!() } @@ -38,10 +40,9 @@ fn baz(x: &S) -> &S { fn supply_F() { want_F(foo); - want_F(bar); //~ ERROR mismatched types + want_F(bar); want_F(baz); } -pub fn main() { -} +pub fn main() {} diff --git a/src/test/ui/regions/regions-fn-subtyping-return-static.stderr b/src/test/ui/regions/regions-fn-subtyping-return-static.stderr deleted file mode 100644 index a8a7e97e6acf6..0000000000000 --- a/src/test/ui/regions/regions-fn-subtyping-return-static.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/regions-fn-subtyping-return-static.rs:41:12 - | -LL | want_F(bar); - | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx - | - = note: expected fn pointer `for<'cx> fn(&'cx S) -> &'cx S` - found fn item `for<'a> fn(&'a S) -> &S {bar::<'_>}` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr b/src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr index 434a3e47b492a..37f7fcf2e331a 100644 --- a/src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr +++ b/src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr @@ -1,14 +1,40 @@ -error[E0308]: mismatched types - --> $DIR/regions-lifetime-bounds-on-fns.rs:20:43 +error: lifetime may not live long enough + --> $DIR/regions-lifetime-bounds-on-fns.rs:8:5 + | +LL | fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Illegal now because there is no `'b:'a` declaration. +LL | *x = *y; + | ^^^^^^^ assignment requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/regions-lifetime-bounds-on-fns.rs:14:5 + | +LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | a(x, y); + | ^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: higher-ranked subtype error + --> $DIR/regions-lifetime-bounds-on-fns.rs:20:12 | LL | let _: fn(&mut &isize, &mut &isize) = a; - | ---------------------------- ^ expected concrete lifetime, found bound lifetime parameter - | | - | expected due to this + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/regions-lifetime-bounds-on-fns.rs:20:12 | - = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` - found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` +LL | let _: fn(&mut &isize, &mut &isize) = a; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr index 01f43aeebaf7c..2b2dd0dbbf250 100644 --- a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr +++ b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr @@ -20,12 +20,10 @@ error[E0308]: mismatched types --> $DIR/regions-lifetime-bounds-on-fns.rs:20:43 | LL | let _: fn(&mut &isize, &mut &isize) = a; - | ---------------------------- ^ expected concrete lifetime, found bound lifetime parameter - | | - | expected due to this + | ^ one type is more general than the other | = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` - found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` + found fn pointer `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)` error: aborting due to 3 previous errors diff --git a/src/test/ui/repeat_count.stderr b/src/test/ui/repeat_count.stderr index 6a081e23d9d37..2eab3ebc7687d 100644 --- a/src/test/ui/repeat_count.stderr +++ b/src/test/ui/repeat_count.stderr @@ -39,12 +39,16 @@ error[E0308]: mismatched types | LL | let f = [0; -4_isize]; | ^^^^^^^^ expected `usize`, found `isize` + | + = note: `-4_isize` cannot fit into type `usize` error[E0308]: mismatched types --> $DIR/repeat_count.rs:22:23 | LL | let f = [0_usize; -1_isize]; | ^^^^^^^^ expected `usize`, found `isize` + | + = note: `-1_isize` cannot fit into type `usize` error[E0308]: mismatched types --> $DIR/repeat_count.rs:25:17 diff --git a/src/test/ui/resolve/issue-21221-1.stderr b/src/test/ui/resolve/issue-21221-1.stderr index d3e1953435359..538eeead9fc9d 100644 --- a/src/test/ui/resolve/issue-21221-1.stderr +++ b/src/test/ui/resolve/issue-21221-1.stderr @@ -25,11 +25,8 @@ LL | use mul1::Mul; | LL | use mul2::Mul; | -LL | use mul3::Mul; - | -LL | use mul4::Mul; +LL | use std::ops::Mul; | - and 2 other candidates error[E0405]: cannot find trait `ThisTraitReallyDoesntExistInAnyModuleReally` in this scope --> $DIR/issue-21221-1.rs:63:6 diff --git a/src/test/ui/rfc1623.nll.stderr b/src/test/ui/rfc1623.nll.stderr new file mode 100644 index 0000000000000..848d4fef1abfc --- /dev/null +++ b/src/test/ui/rfc1623.nll.stderr @@ -0,0 +1,68 @@ +error[E0277]: `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` cannot be shared between threads safely + --> $DIR/rfc1623.rs:21:1 + | +LL | / static SOME_STRUCT: &SomeStruct = &SomeStruct { +LL | | foo: &Foo { bools: &[false, true] }, +LL | | bar: &Bar { bools: &[true, true] }, +LL | | f: &id, +LL | | +LL | | }; + | |__^ `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` cannot be shared between threads safely + | + = help: within `&SomeStruct`, the trait `std::marker::Sync` is not implemented for `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` + = note: required because it appears within the type `&dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` + = note: required because it appears within the type `SomeStruct` + = note: required because it appears within the type `&SomeStruct` + = note: shared static variables must have a type that implements `Sync` + +error: higher-ranked subtype error + --> $DIR/rfc1623.rs:21:35 + | +LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { + | ___________________________________^ +LL | | foo: &Foo { bools: &[false, true] }, +LL | | bar: &Bar { bools: &[true, true] }, +LL | | f: &id, +LL | | +LL | | }; + | |_^ + +error: higher-ranked subtype error + --> $DIR/rfc1623.rs:21:35 + | +LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { + | ___________________________________^ +LL | | foo: &Foo { bools: &[false, true] }, +LL | | bar: &Bar { bools: &[true, true] }, +LL | | f: &id, +LL | | +LL | | }; + | |_^ + +error: higher-ranked subtype error + --> $DIR/rfc1623.rs:21:35 + | +LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { + | ___________________________________^ +LL | | foo: &Foo { bools: &[false, true] }, +LL | | bar: &Bar { bools: &[true, true] }, +LL | | f: &id, +LL | | +LL | | }; + | |_^ + +error: higher-ranked subtype error + --> $DIR/rfc1623.rs:21:35 + | +LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { + | ___________________________________^ +LL | | foo: &Foo { bools: &[false, true] }, +LL | | bar: &Bar { bools: &[true, true] }, +LL | | f: &id, +LL | | +LL | | }; + | |_^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc1623.rs b/src/test/ui/rfc1623.rs index 55f5d0b94dcb0..aa6b1c0012c93 100644 --- a/src/test/ui/rfc1623.rs +++ b/src/test/ui/rfc1623.rs @@ -8,23 +8,21 @@ fn non_elidable<'a, 'b>(a: &'a u8, b: &'b u8) -> &'a u8 { static NON_ELIDABLE_FN: &for<'a> fn(&'a u8, &'a u8) -> &'a u8 = &(non_elidable as for<'a> fn(&'a u8, &'a u8) -> &'a u8); - struct SomeStruct<'x, 'y, 'z: 'x> { foo: &'x Foo<'z>, bar: &'x Bar<'z>, - f: &'y dyn for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Bar<'b>, + f: &'y dyn for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Foo<'b>, } fn id(t: T) -> T { t } -static SOME_STRUCT: &SomeStruct = SomeStruct { //~ ERROR mismatched types +static SOME_STRUCT: &SomeStruct = &SomeStruct { foo: &Foo { bools: &[false, true] }, bar: &Bar { bools: &[true, true] }, f: &id, - //~^ ERROR type mismatch in function arguments - //~| ERROR type mismatch resolving + //~^ ERROR mismatched types }; // very simple test for a 'static static with default lifetime diff --git a/src/test/ui/rfc1623.stderr b/src/test/ui/rfc1623.stderr index ca956004ef76f..2efc58ac3819c 100644 --- a/src/test/ui/rfc1623.stderr +++ b/src/test/ui/rfc1623.stderr @@ -1,46 +1,12 @@ error[E0308]: mismatched types - --> $DIR/rfc1623.rs:22:35 - | -LL | static SOME_STRUCT: &SomeStruct = SomeStruct { - | ___________________________________^ -LL | | foo: &Foo { bools: &[false, true] }, -LL | | bar: &Bar { bools: &[true, true] }, -LL | | f: &id, -LL | | -LL | | -LL | | }; - | |_^ expected `&SomeStruct<'static, 'static, 'static>`, found struct `SomeStruct` - | -help: consider borrowing here - | -LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { -LL | foo: &Foo { bools: &[false, true] }, -LL | bar: &Bar { bools: &[true, true] }, -LL | f: &id, -LL | -LL | - ... - -error[E0631]: type mismatch in function arguments - --> $DIR/rfc1623.rs:25:8 - | -LL | fn id(t: T) -> T { - | ------------------- found signature of `fn(_) -> _` -... -LL | f: &id, - | ^^^ expected signature of `for<'a, 'b> fn(&'a Foo<'b>) -> _` - | - = note: required for the cast to the object type `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` - -error[E0271]: type mismatch resolving `for<'a, 'b> _ {id::<_>} as std::ops::FnOnce<(&'a Foo<'b>,)>>::Output == &'a Foo<'b>` - --> $DIR/rfc1623.rs:25:8 + --> $DIR/rfc1623.rs:24:8 | LL | f: &id, - | ^^^ expected bound lifetime parameter 'a, found concrete lifetime + | ^^^ one type is more general than the other | - = note: required for the cast to the object type `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` + = note: expected type `std::ops::FnOnce<(&'a Foo<'b>,)>` + found type `std::ops::FnOnce<(&Foo<'_>,)>` -error: aborting due to 3 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0271, E0308, E0631. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/sanitize/incompatible.rs b/src/test/ui/sanitize/incompatible.rs new file mode 100644 index 0000000000000..4947f3b3d8b13 --- /dev/null +++ b/src/test/ui/sanitize/incompatible.rs @@ -0,0 +1,6 @@ +// compile-flags: -Z sanitizer=address -Z sanitizer=memory --target x86_64-unknown-linux-gnu +// error-pattern: error: `-Zsanitizer=address` is incompatible with `-Zsanitizer=memory` + +#![feature(no_core)] +#![no_core] +#![no_main] diff --git a/src/test/ui/sanitize/incompatible.stderr b/src/test/ui/sanitize/incompatible.stderr new file mode 100644 index 0000000000000..f86db41bac717 --- /dev/null +++ b/src/test/ui/sanitize/incompatible.stderr @@ -0,0 +1,4 @@ +error: `-Zsanitizer=address` is incompatible with `-Zsanitizer=memory` + +error: aborting due to previous error + diff --git a/src/test/ui/sanitize/unsupported-target.rs b/src/test/ui/sanitize/unsupported-target.rs index 444333c3f01e2..6ccc9988cdecc 100644 --- a/src/test/ui/sanitize/unsupported-target.rs +++ b/src/test/ui/sanitize/unsupported-target.rs @@ -1,6 +1,5 @@ -// ignore-tidy-linelength // compile-flags: -Z sanitizer=leak --target i686-unknown-linux-gnu -// error-pattern: error: LeakSanitizer only works with the `x86_64-unknown-linux-gnu` or `x86_64-apple-darwin` target +// error-pattern: error: `-Zsanitizer=leak` only works with targets: #![feature(no_core)] #![no_core] diff --git a/src/test/ui/sanitize/unsupported-target.stderr b/src/test/ui/sanitize/unsupported-target.stderr index 38be58dd4b365..f5961a11b1f1c 100644 --- a/src/test/ui/sanitize/unsupported-target.stderr +++ b/src/test/ui/sanitize/unsupported-target.stderr @@ -1,4 +1,4 @@ -error: LeakSanitizer only works with the `x86_64-unknown-linux-gnu` or `x86_64-apple-darwin` target +error: `-Zsanitizer=leak` only works with targets: aarch64-unknown-linux-gnu, x86_64-apple-darwin, x86_64-unknown-linux-gnu error: aborting due to previous error diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 88bd990b1e81b..f2fbb0ba7d755 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -6,6 +6,11 @@ LL | async fn f(self: Pin<&Self>) -> impl Clone { self } | | | | | this data with an anonymous lifetime `'_`... | ...is captured here... + | +help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound + | +LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self } + | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/span/E0493.stderr b/src/test/ui/span/E0493.stderr index d05e89e257f45..29d1b00094321 100644 --- a/src/test/ui/span/E0493.stderr +++ b/src/test/ui/span/E0493.stderr @@ -2,7 +2,9 @@ error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/E0493.rs:17:17 | LL | const F : Foo = (Foo { a : 0 }, Foo { a : 1 }).1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constants cannot evaluate destructors + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - value is dropped here + | | + | constants cannot evaluate destructors error: aborting due to previous error diff --git a/src/test/ui/specialization/assoc-ty-graph-cycle.rs b/src/test/ui/specialization/assoc-ty-graph-cycle.rs index 54d51492ab349..fc39b553a61ac 100644 --- a/src/test/ui/specialization/assoc-ty-graph-cycle.rs +++ b/src/test/ui/specialization/assoc-ty-graph-cycle.rs @@ -2,7 +2,7 @@ // Make sure we don't crash with a cycle error during coherence. -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait Trait { type Assoc; diff --git a/src/test/ui/specialization/assoc-ty-graph-cycle.stderr b/src/test/ui/specialization/assoc-ty-graph-cycle.stderr new file mode 100644 index 0000000000000..250f48f8e5932 --- /dev/null +++ b/src/test/ui/specialization/assoc-ty-graph-cycle.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/assoc-ty-graph-cycle.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/specialization/cross-crate-defaults.rs b/src/test/ui/specialization/cross-crate-defaults.rs index 79cb659439721..fc28d0c815eb3 100644 --- a/src/test/ui/specialization/cross-crate-defaults.rs +++ b/src/test/ui/specialization/cross-crate-defaults.rs @@ -2,7 +2,7 @@ // aux-build:cross_crates_defaults.rs -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete extern crate cross_crates_defaults; diff --git a/src/test/ui/specialization/cross-crate-defaults.stderr b/src/test/ui/specialization/cross-crate-defaults.stderr new file mode 100644 index 0000000000000..f18bc99d73916 --- /dev/null +++ b/src/test/ui/specialization/cross-crate-defaults.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/cross-crate-defaults.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/specialization/deafult-associated-type-bound-1.rs b/src/test/ui/specialization/deafult-associated-type-bound-1.rs new file mode 100644 index 0000000000000..272a5e3fe10c6 --- /dev/null +++ b/src/test/ui/specialization/deafult-associated-type-bound-1.rs @@ -0,0 +1,24 @@ +// Check that we check that default associated types satisfy the required +// bounds on them. + +#![feature(specialization)] +//~^ WARNING `specialization` is incomplete + +trait X { + type U: Clone; + fn unsafe_clone(&self, x: Option<&Self::U>) { + x.cloned(); + } +} + +// We cannot normalize `::U` to `str` here, because the default could +// be overridden. The error here must therefore be found by a method other than +// normalization. +impl X for T { + default type U = str; + //~^ ERROR the trait bound `str: std::clone::Clone` is not satisfied +} + +pub fn main() { + 1.unsafe_clone(None); +} diff --git a/src/test/ui/specialization/deafult-associated-type-bound-1.stderr b/src/test/ui/specialization/deafult-associated-type-bound-1.stderr new file mode 100644 index 0000000000000..90ad5d4c1559b --- /dev/null +++ b/src/test/ui/specialization/deafult-associated-type-bound-1.stderr @@ -0,0 +1,21 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/deafult-associated-type-bound-1.rs:4:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +error[E0277]: the trait bound `str: std::clone::Clone` is not satisfied + --> $DIR/deafult-associated-type-bound-1.rs:18:5 + | +LL | type U: Clone; + | -------------- required by `X::U` +... +LL | default type U = str; + | ^^^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `str` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/specialization/deafult-associated-type-bound-2.rs b/src/test/ui/specialization/deafult-associated-type-bound-2.rs new file mode 100644 index 0000000000000..0a21b1f09106b --- /dev/null +++ b/src/test/ui/specialization/deafult-associated-type-bound-2.rs @@ -0,0 +1,22 @@ +// Check that generic predicates are also checked for default associated types. +#![feature(specialization)] +//~^ WARNING `specialization` is incomplete + +trait X { + type U: PartialEq; + fn unsafe_compare(x: Option, y: Option) { + match (x, y) { + (Some(a), Some(b)) => a == b, + _ => false, + }; + } +} + +impl X for T { + default type U = &'static B; + //~^ ERROR can't compare `&'static B` with `B` +} + +pub fn main() { + >::unsafe_compare(None, None); +} diff --git a/src/test/ui/specialization/deafult-associated-type-bound-2.stderr b/src/test/ui/specialization/deafult-associated-type-bound-2.stderr new file mode 100644 index 0000000000000..ea40f846e3665 --- /dev/null +++ b/src/test/ui/specialization/deafult-associated-type-bound-2.stderr @@ -0,0 +1,23 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/deafult-associated-type-bound-2.rs:2:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +error[E0277]: can't compare `&'static B` with `B` + --> $DIR/deafult-associated-type-bound-2.rs:16:5 + | +LL | type U: PartialEq; + | --------------------- required by `X::U` +... +LL | default type U = &'static B; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `&'static B == B` + | + = help: the trait `std::cmp::PartialEq` is not implemented for `&'static B` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/specialization/deafult-generic-associated-type-bound.rs b/src/test/ui/specialization/deafult-generic-associated-type-bound.rs new file mode 100644 index 0000000000000..8a94ea658d2d0 --- /dev/null +++ b/src/test/ui/specialization/deafult-generic-associated-type-bound.rs @@ -0,0 +1,27 @@ +// Check that default generics associated types are validated. + +#![feature(specialization)] +#![feature(generic_associated_types)] +//~^^ WARNING `specialization` is incomplete +//~^^ WARNING the feature `generic_associated_types` is incomplete + +trait X { + type U<'a>: PartialEq<&'a Self>; + fn unsafe_compare<'b>(x: Option>, y: Option<&'b Self>) { + match (x, y) { + (Some(a), Some(b)) => a == b, + _ => false, + }; + } +} + +impl X for T { + default type U<'a> = &'a T; + //~^ ERROR can't compare `T` with `T` +} + +struct NotComparable; + +pub fn main() { + ::unsafe_compare(None, None); +} diff --git a/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr b/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr new file mode 100644 index 0000000000000..7f3c49e753fd7 --- /dev/null +++ b/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr @@ -0,0 +1,36 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/deafult-generic-associated-type-bound.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/deafult-generic-associated-type-bound.rs:4:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #44265 for more information + +error[E0277]: can't compare `T` with `T` + --> $DIR/deafult-generic-associated-type-bound.rs:19:5 + | +LL | type U<'a>: PartialEq<&'a Self>; + | -------------------------------- required by `X::U` +... +LL | default type U<'a> = &'a T; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `T == T` + | + = help: the trait `std::cmp::PartialEq` is not implemented for `T` + = note: required because of the requirements on the impl of `std::cmp::PartialEq` for `&'a T` +help: consider further restricting this bound + | +LL | impl X for T { + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 2 warnings emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/specialization/defaultimpl/allowed-cross-crate.rs b/src/test/ui/specialization/defaultimpl/allowed-cross-crate.rs index 15550bcce2a8a..5d67160eb96ad 100644 --- a/src/test/ui/specialization/defaultimpl/allowed-cross-crate.rs +++ b/src/test/ui/specialization/defaultimpl/allowed-cross-crate.rs @@ -5,7 +5,7 @@ // aux-build:go_trait.rs -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete extern crate go_trait; diff --git a/src/test/ui/specialization/defaultimpl/allowed-cross-crate.stderr b/src/test/ui/specialization/defaultimpl/allowed-cross-crate.stderr new file mode 100644 index 0000000000000..1b50329719d01 --- /dev/null +++ b/src/test/ui/specialization/defaultimpl/allowed-cross-crate.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/allowed-cross-crate.rs:8:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/specialization/defaultimpl/out-of-order.rs b/src/test/ui/specialization/defaultimpl/out-of-order.rs index f9c73a19cfa46..13258ac8c9fe6 100644 --- a/src/test/ui/specialization/defaultimpl/out-of-order.rs +++ b/src/test/ui/specialization/defaultimpl/out-of-order.rs @@ -2,7 +2,7 @@ // Test that you can list the more specific impl before the more general one. -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait Foo { type Out; diff --git a/src/test/ui/specialization/defaultimpl/out-of-order.stderr b/src/test/ui/specialization/defaultimpl/out-of-order.stderr new file mode 100644 index 0000000000000..deae021a8914d --- /dev/null +++ b/src/test/ui/specialization/defaultimpl/out-of-order.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/out-of-order.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/specialization/defaultimpl/overlap-projection.rs b/src/test/ui/specialization/defaultimpl/overlap-projection.rs index ed38bb3fc3a12..0add4d5516c7b 100644 --- a/src/test/ui/specialization/defaultimpl/overlap-projection.rs +++ b/src/test/ui/specialization/defaultimpl/overlap-projection.rs @@ -4,7 +4,7 @@ // projections involve specialization, so long as the associated type is // provided by the most specialized impl. -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait Assoc { type Output; diff --git a/src/test/ui/specialization/defaultimpl/overlap-projection.stderr b/src/test/ui/specialization/defaultimpl/overlap-projection.stderr new file mode 100644 index 0000000000000..46899ca995490 --- /dev/null +++ b/src/test/ui/specialization/defaultimpl/overlap-projection.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/overlap-projection.rs:7:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/specialization/defaultimpl/projection.rs b/src/test/ui/specialization/defaultimpl/projection.rs index 897a7aade2fe1..4a9140969324d 100644 --- a/src/test/ui/specialization/defaultimpl/projection.rs +++ b/src/test/ui/specialization/defaultimpl/projection.rs @@ -1,7 +1,7 @@ // run-pass #![allow(dead_code)] -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete // Make sure we *can* project non-defaulted associated types // cf compile-fail/specialization-default-projection.rs diff --git a/src/test/ui/specialization/defaultimpl/projection.stderr b/src/test/ui/specialization/defaultimpl/projection.stderr new file mode 100644 index 0000000000000..8629c6c52d4a7 --- /dev/null +++ b/src/test/ui/specialization/defaultimpl/projection.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/projection.rs:4:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/specialization/defaultimpl/specialization-no-default.rs b/src/test/ui/specialization/defaultimpl/specialization-no-default.rs index 37005f839d488..661724eef8a43 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-no-default.rs +++ b/src/test/ui/specialization/defaultimpl/specialization-no-default.rs @@ -1,4 +1,4 @@ -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete // Check a number of scenarios in which one impl tries to override another, // without correctly using `default`. diff --git a/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr b/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr index 13636b28b126c..7958eddbeba25 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr @@ -1,3 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-no-default.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` --> $DIR/specialization-no-default.rs:20:5 | @@ -65,6 +74,6 @@ LL | fn redundant(&self) {} | = note: to specialize, `redundant` in the parent `impl` must be marked `default` -error: aborting due to 5 previous errors +error: aborting due to 5 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0520`. diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs index 2b8ca6bb1ddbb..89fef5b5ef969 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs @@ -3,7 +3,7 @@ // Tests that we can combine a default impl that supplies one method with a // full impl that supplies the other, and they can invoke one another. -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait Foo { fn foo_one(&self) -> &'static str; diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr new file mode 100644 index 0000000000000..dc377dd10c868 --- /dev/null +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-trait-item-not-implemented-rpass.rs:6:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs index 2a121e61aaa97..3c5414469fac2 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs @@ -1,6 +1,6 @@ // Tests that default impls do not have to supply all items but regular impls do. -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait Foo { fn foo_one(&self) -> &'static str; diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr index b862a937066d4..9d1eca1d6af76 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr @@ -1,3 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-trait-item-not-implemented.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + error[E0046]: not all trait items implemented, missing: `foo_two` --> $DIR/specialization-trait-item-not-implemented.rs:18:1 | @@ -7,6 +16,6 @@ LL | fn foo_two(&self) -> &'static str; LL | impl Foo for MyStruct {} | ^^^^^^^^^^^^^^^^^^^^^ missing `foo_two` in implementation -error: aborting due to previous error +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0046`. diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs index 5c104449fe9c0..35e3b8725a82a 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs @@ -2,7 +2,7 @@ // - default impls do not have to supply all items and // - a default impl does not count as an impl (in this case, an incomplete default impl). -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait Foo { fn foo_one(&self) -> &'static str; diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr index a55d79ee03534..6b8e559bc3634 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -1,3 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-trait-not-implemented.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + error[E0599]: no method named `foo_one` found for struct `MyStruct` in the current scope --> $DIR/specialization-trait-not-implemented.rs:22:29 | @@ -19,6 +28,6 @@ note: `Foo` defines an item `foo_one`, perhaps you need to implement it LL | trait Foo { | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/specialization/defaultimpl/specialization-wfcheck.rs b/src/test/ui/specialization/defaultimpl/specialization-wfcheck.rs index 232338d9d4d99..afd634725e365 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-wfcheck.rs +++ b/src/test/ui/specialization/defaultimpl/specialization-wfcheck.rs @@ -1,6 +1,6 @@ // Tests that a default impl still has to have a WF trait ref. -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait Foo<'a, T: Eq + 'a> { } diff --git a/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr b/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr index f499c1f569859..d45825651a8e2 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr @@ -1,3 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-wfcheck.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + error[E0277]: the trait bound `U: std::cmp::Eq` is not satisfied --> $DIR/specialization-wfcheck.rs:7:17 | @@ -12,6 +21,6 @@ help: consider restricting type parameter `U` LL | default impl Foo<'static, U> for () {} | ^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/specialization/defaultimpl/validation.rs b/src/test/ui/specialization/defaultimpl/validation.rs index 8134333c58f73..8558a1efb82f3 100644 --- a/src/test/ui/specialization/defaultimpl/validation.rs +++ b/src/test/ui/specialization/defaultimpl/validation.rs @@ -1,5 +1,5 @@ #![feature(negative_impls)] -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete struct S; struct Z; diff --git a/src/test/ui/specialization/defaultimpl/validation.stderr b/src/test/ui/specialization/defaultimpl/validation.stderr index 254eaf51a646b..2449849725f38 100644 --- a/src/test/ui/specialization/defaultimpl/validation.stderr +++ b/src/test/ui/specialization/defaultimpl/validation.stderr @@ -8,6 +8,15 @@ LL | default impl S {} | = note: only trait implementations may be annotated with `default` +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/validation.rs:2:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + error: impls of auto traits cannot be default --> $DIR/validation.rs:9:21 | @@ -36,6 +45,6 @@ error[E0750]: negative impls cannot be default impls LL | default impl !Tr for S {} | ^^^^^^^ ^ -error: aborting due to 5 previous errors +error: aborting due to 5 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0750`. diff --git a/src/test/ui/specialization/issue-36804.rs b/src/test/ui/specialization/issue-36804.rs index 9546a5dd5f516..89350602f3652 100644 --- a/src/test/ui/specialization/issue-36804.rs +++ b/src/test/ui/specialization/issue-36804.rs @@ -1,5 +1,5 @@ // check-pass -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete pub struct Cloned(I); diff --git a/src/test/ui/specialization/issue-36804.stderr b/src/test/ui/specialization/issue-36804.stderr new file mode 100644 index 0000000000000..744d88204247b --- /dev/null +++ b/src/test/ui/specialization/issue-36804.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-36804.rs:2:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/specialization/issue-39448.rs b/src/test/ui/specialization/issue-39448.rs index 8ac6d8e9311fc..9dd47a4a17e43 100644 --- a/src/test/ui/specialization/issue-39448.rs +++ b/src/test/ui/specialization/issue-39448.rs @@ -1,4 +1,4 @@ -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete // Regression test for a specialization-related ICE (#39448). diff --git a/src/test/ui/specialization/issue-39448.stderr b/src/test/ui/specialization/issue-39448.stderr index 861a1d9e8fc66..f3bb69b8f712a 100644 --- a/src/test/ui/specialization/issue-39448.stderr +++ b/src/test/ui/specialization/issue-39448.stderr @@ -1,3 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-39448.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + error[E0275]: overflow evaluating the requirement `T: FromA` --> $DIR/issue-39448.rs:45:13 | @@ -7,6 +16,6 @@ LL | x.foo(y.to()).to() = note: required because of the requirements on the impl of `FromA` for `T` = note: required because of the requirements on the impl of `ToA` for `U` -error: aborting due to previous error +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/specialization/issue-39618.rs b/src/test/ui/specialization/issue-39618.rs index 20e81e4359bac..72630ee9c7055 100644 --- a/src/test/ui/specialization/issue-39618.rs +++ b/src/test/ui/specialization/issue-39618.rs @@ -4,7 +4,7 @@ // check-pass -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait Foo { fn foo(&self); diff --git a/src/test/ui/specialization/issue-39618.stderr b/src/test/ui/specialization/issue-39618.stderr new file mode 100644 index 0000000000000..d40d17d8f71ca --- /dev/null +++ b/src/test/ui/specialization/issue-39618.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-39618.rs:7:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/specialization/issue-50452.rs b/src/test/ui/specialization/issue-50452.rs index 93f081d955819..29fc12066e875 100644 --- a/src/test/ui/specialization/issue-50452.rs +++ b/src/test/ui/specialization/issue-50452.rs @@ -1,6 +1,6 @@ // run-pass -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete pub trait Foo { fn foo(); diff --git a/src/test/ui/specialization/issue-50452.stderr b/src/test/ui/specialization/issue-50452.stderr new file mode 100644 index 0000000000000..c01817e0b2793 --- /dev/null +++ b/src/test/ui/specialization/issue-50452.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-50452.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/specialization/issue-52050.rs b/src/test/ui/specialization/issue-52050.rs index 1e1bfe9cf0755..8046587020661 100644 --- a/src/test/ui/specialization/issue-52050.rs +++ b/src/test/ui/specialization/issue-52050.rs @@ -1,4 +1,4 @@ -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete // Regression test for #52050: when inserting the blanket impl `I` // into the tree, we had to replace the child node for `Foo`, which diff --git a/src/test/ui/specialization/issue-52050.stderr b/src/test/ui/specialization/issue-52050.stderr index 36f96b011983f..a7564ced055d5 100644 --- a/src/test/ui/specialization/issue-52050.stderr +++ b/src/test/ui/specialization/issue-52050.stderr @@ -1,3 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-52050.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + error[E0119]: conflicting implementations of trait `IntoPyDictPointer` for type `()`: --> $DIR/issue-52050.rs:28:1 | @@ -13,6 +22,6 @@ LL | impl IntoPyDictPointer for () | = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions -error: aborting due to previous error +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/specialization/issue-63716-parse-async.rs b/src/test/ui/specialization/issue-63716-parse-async.rs index c3764ffaab83f..10f185c335144 100644 --- a/src/test/ui/specialization/issue-63716-parse-async.rs +++ b/src/test/ui/specialization/issue-63716-parse-async.rs @@ -4,7 +4,7 @@ // check-pass // edition:2018 -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete fn main() {} diff --git a/src/test/ui/specialization/issue-63716-parse-async.stderr b/src/test/ui/specialization/issue-63716-parse-async.stderr new file mode 100644 index 0000000000000..43620e1ba51e1 --- /dev/null +++ b/src/test/ui/specialization/issue-63716-parse-async.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-63716-parse-async.rs:7:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/specialization/issue-70442.rs b/src/test/ui/specialization/issue-70442.rs index 4371dd2e16747..d41b5355c2cde 100644 --- a/src/test/ui/specialization/issue-70442.rs +++ b/src/test/ui/specialization/issue-70442.rs @@ -1,4 +1,4 @@ -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete // check-pass diff --git a/src/test/ui/specialization/issue-70442.stderr b/src/test/ui/specialization/issue-70442.stderr new file mode 100644 index 0000000000000..f71e4c7dd1cef --- /dev/null +++ b/src/test/ui/specialization/issue-70442.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-70442.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/specialization/non-defaulted-item-fail.rs b/src/test/ui/specialization/non-defaulted-item-fail.rs index 403f718d7dd9f..b7d6ac829dd14 100644 --- a/src/test/ui/specialization/non-defaulted-item-fail.rs +++ b/src/test/ui/specialization/non-defaulted-item-fail.rs @@ -1,4 +1,5 @@ #![feature(specialization, associated_type_defaults)] +//~^ WARN the feature `specialization` is incomplete // Test that attempting to override a non-default method or one not in the // parent impl causes an error. diff --git a/src/test/ui/specialization/non-defaulted-item-fail.stderr b/src/test/ui/specialization/non-defaulted-item-fail.stderr index e6c5fc1441b2f..eae045b92c04d 100644 --- a/src/test/ui/specialization/non-defaulted-item-fail.stderr +++ b/src/test/ui/specialization/non-defaulted-item-fail.stderr @@ -1,5 +1,14 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/non-defaulted-item-fail.rs:1:12 + | +LL | #![feature(specialization, associated_type_defaults)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/non-defaulted-item-fail.rs:29:5 + --> $DIR/non-defaulted-item-fail.rs:30:5 | LL | / impl Foo for Box { LL | | type Ty = bool; @@ -14,7 +23,7 @@ LL | type Ty = Vec<()>; = note: to specialize, `Ty` in the parent `impl` must be marked `default` error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/non-defaulted-item-fail.rs:31:5 + --> $DIR/non-defaulted-item-fail.rs:32:5 | LL | / impl Foo for Box { LL | | type Ty = bool; @@ -29,7 +38,7 @@ LL | const CONST: u8 = 42; = note: to specialize, `CONST` in the parent `impl` must be marked `default` error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/non-defaulted-item-fail.rs:33:5 + --> $DIR/non-defaulted-item-fail.rs:34:5 | LL | / impl Foo for Box { LL | | type Ty = bool; @@ -44,7 +53,7 @@ LL | fn foo(&self) -> bool { true } = note: to specialize, `foo` in the parent `impl` must be marked `default` error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/non-defaulted-item-fail.rs:45:5 + --> $DIR/non-defaulted-item-fail.rs:46:5 | LL | impl Foo for Vec {} | ------------------------- parent `impl` is here @@ -55,7 +64,7 @@ LL | type Ty = Vec<()>; = note: to specialize, `Ty` in the parent `impl` must be marked `default` error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/non-defaulted-item-fail.rs:47:5 + --> $DIR/non-defaulted-item-fail.rs:48:5 | LL | impl Foo for Vec {} | ------------------------- parent `impl` is here @@ -66,7 +75,7 @@ LL | const CONST: u8 = 42; = note: to specialize, `CONST` in the parent `impl` must be marked `default` error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/non-defaulted-item-fail.rs:49:5 + --> $DIR/non-defaulted-item-fail.rs:50:5 | LL | impl Foo for Vec {} | ------------------------- parent `impl` is here @@ -76,6 +85,6 @@ LL | fn foo(&self) -> bool { true } | = note: to specialize, `foo` in the parent `impl` must be marked `default` -error: aborting due to 6 previous errors +error: aborting due to 6 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0520`. diff --git a/src/test/ui/specialization/specialization-allowed-cross-crate.rs b/src/test/ui/specialization/specialization-allowed-cross-crate.rs index 15550bcce2a8a..5d67160eb96ad 100644 --- a/src/test/ui/specialization/specialization-allowed-cross-crate.rs +++ b/src/test/ui/specialization/specialization-allowed-cross-crate.rs @@ -5,7 +5,7 @@ // aux-build:go_trait.rs -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete extern crate go_trait; diff --git a/src/test/ui/specialization/specialization-allowed-cross-crate.stderr b/src/test/ui/specialization/specialization-allowed-cross-crate.stderr new file mode 100644 index 0000000000000..7d087545725be --- /dev/null +++ b/src/test/ui/specialization/specialization-allowed-cross-crate.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-allowed-cross-crate.rs:8:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/specialization/specialization-assoc-fns.rs b/src/test/ui/specialization/specialization-assoc-fns.rs index b6a7a48972ac2..cbfcb4719f6a4 100644 --- a/src/test/ui/specialization/specialization-assoc-fns.rs +++ b/src/test/ui/specialization/specialization-assoc-fns.rs @@ -2,7 +2,7 @@ // Test that non-method associated functions can be specialized -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait Foo { fn mk() -> Self; diff --git a/src/test/ui/specialization/specialization-assoc-fns.stderr b/src/test/ui/specialization/specialization-assoc-fns.stderr new file mode 100644 index 0000000000000..b12738604ea83 --- /dev/null +++ b/src/test/ui/specialization/specialization-assoc-fns.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-assoc-fns.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/specialization/specialization-basics.rs b/src/test/ui/specialization/specialization-basics.rs index 6c359e51bc2e4..721c934dbfab9 100644 --- a/src/test/ui/specialization/specialization-basics.rs +++ b/src/test/ui/specialization/specialization-basics.rs @@ -1,6 +1,6 @@ // run-pass -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete // Tests a variety of basic specialization scenarios and method // dispatch for them. diff --git a/src/test/ui/specialization/specialization-basics.stderr b/src/test/ui/specialization/specialization-basics.stderr new file mode 100644 index 0000000000000..ad00cd81df13c --- /dev/null +++ b/src/test/ui/specialization/specialization-basics.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-basics.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/specialization/specialization-cross-crate.rs b/src/test/ui/specialization/specialization-cross-crate.rs index fa63c86632985..4171505aa374c 100644 --- a/src/test/ui/specialization/specialization-cross-crate.rs +++ b/src/test/ui/specialization/specialization-cross-crate.rs @@ -2,7 +2,7 @@ // aux-build:specialization_cross_crate.rs -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete extern crate specialization_cross_crate; diff --git a/src/test/ui/specialization/specialization-cross-crate.stderr b/src/test/ui/specialization/specialization-cross-crate.stderr new file mode 100644 index 0000000000000..7481eed796d96 --- /dev/null +++ b/src/test/ui/specialization/specialization-cross-crate.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-cross-crate.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/specialization/specialization-default-methods.rs b/src/test/ui/specialization/specialization-default-methods.rs index 9ae3d1e9f3931..dcf68afa945bf 100644 --- a/src/test/ui/specialization/specialization-default-methods.rs +++ b/src/test/ui/specialization/specialization-default-methods.rs @@ -1,6 +1,6 @@ // run-pass -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete // Test that default methods are cascaded correctly diff --git a/src/test/ui/specialization/specialization-default-methods.stderr b/src/test/ui/specialization/specialization-default-methods.stderr new file mode 100644 index 0000000000000..4fa19adad066e --- /dev/null +++ b/src/test/ui/specialization/specialization-default-methods.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-default-methods.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/specialization/specialization-default-projection.rs b/src/test/ui/specialization/specialization-default-projection.rs index e9343f2360170..7f3ae951287ca 100644 --- a/src/test/ui/specialization/specialization-default-projection.rs +++ b/src/test/ui/specialization/specialization-default-projection.rs @@ -1,4 +1,4 @@ -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete // Make sure we can't project defaulted associated types diff --git a/src/test/ui/specialization/specialization-default-projection.stderr b/src/test/ui/specialization/specialization-default-projection.stderr index ac15ab0681a02..456eb6d5ca553 100644 --- a/src/test/ui/specialization/specialization-default-projection.stderr +++ b/src/test/ui/specialization/specialization-default-projection.stderr @@ -1,3 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-default-projection.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + error[E0308]: mismatched types --> $DIR/specialization-default-projection.rs:21:5 | @@ -28,6 +37,6 @@ LL | generic::<()>() = help: consider constraining the associated type `<() as Foo>::Assoc` to `()` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html -error: aborting due to 2 previous errors +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/specialization/specialization-default-types.rs b/src/test/ui/specialization/specialization-default-types.rs index acb86d889d43c..346471f11e4a8 100644 --- a/src/test/ui/specialization/specialization-default-types.rs +++ b/src/test/ui/specialization/specialization-default-types.rs @@ -2,7 +2,7 @@ // associated type in the impl defining it -- otherwise, what happens // if it's overridden? -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait Example { type Output; diff --git a/src/test/ui/specialization/specialization-default-types.stderr b/src/test/ui/specialization/specialization-default-types.stderr index 7233387eba1fa..5e0221f07882e 100644 --- a/src/test/ui/specialization/specialization-default-types.stderr +++ b/src/test/ui/specialization/specialization-default-types.stderr @@ -1,3 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-default-types.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + error[E0308]: mismatched types --> $DIR/specialization-default-types.rs:15:9 | @@ -24,6 +33,6 @@ LL | Example::generate(t) = help: consider constraining the associated type `::Output` to `std::boxed::Box` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html -error: aborting due to 2 previous errors +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/specialization/specialization-no-default.rs b/src/test/ui/specialization/specialization-no-default.rs index 57346b26d24ec..ae739b2358d58 100644 --- a/src/test/ui/specialization/specialization-no-default.rs +++ b/src/test/ui/specialization/specialization-no-default.rs @@ -1,4 +1,4 @@ -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete // Check a number of scenarios in which one impl tries to override another, // without correctly using `default`. diff --git a/src/test/ui/specialization/specialization-no-default.stderr b/src/test/ui/specialization/specialization-no-default.stderr index 992e9abbd4ce2..bb8b2a6c98e09 100644 --- a/src/test/ui/specialization/specialization-no-default.stderr +++ b/src/test/ui/specialization/specialization-no-default.stderr @@ -1,3 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-no-default.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` --> $DIR/specialization-no-default.rs:20:5 | @@ -65,6 +74,6 @@ LL | default fn redundant(&self) {} | = note: to specialize, `redundant` in the parent `impl` must be marked `default` -error: aborting due to 5 previous errors +error: aborting due to 5 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0520`. diff --git a/src/test/ui/specialization/specialization-on-projection.rs b/src/test/ui/specialization/specialization-on-projection.rs index 5606eaea3073d..be8dcc4232e7b 100644 --- a/src/test/ui/specialization/specialization-on-projection.rs +++ b/src/test/ui/specialization/specialization-on-projection.rs @@ -1,7 +1,7 @@ // run-pass #![allow(dead_code)] -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete // Ensure that specialization works for impls defined directly on a projection diff --git a/src/test/ui/specialization/specialization-on-projection.stderr b/src/test/ui/specialization/specialization-on-projection.stderr new file mode 100644 index 0000000000000..d91668d10c5f3 --- /dev/null +++ b/src/test/ui/specialization/specialization-on-projection.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-on-projection.rs:4:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/specialization/specialization-out-of-order.rs b/src/test/ui/specialization/specialization-out-of-order.rs index 94e764f76366e..cb7563e2760c2 100644 --- a/src/test/ui/specialization/specialization-out-of-order.rs +++ b/src/test/ui/specialization/specialization-out-of-order.rs @@ -2,7 +2,7 @@ // Test that you can list the more specific impl before the more general one. -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait Foo { type Out; diff --git a/src/test/ui/specialization/specialization-out-of-order.stderr b/src/test/ui/specialization/specialization-out-of-order.stderr new file mode 100644 index 0000000000000..a17f9f11a3f31 --- /dev/null +++ b/src/test/ui/specialization/specialization-out-of-order.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-out-of-order.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/specialization/specialization-overlap-negative.rs b/src/test/ui/specialization/specialization-overlap-negative.rs index 90dbef3075b7f..550d370829539 100644 --- a/src/test/ui/specialization/specialization-overlap-negative.rs +++ b/src/test/ui/specialization/specialization-overlap-negative.rs @@ -1,5 +1,5 @@ #![feature(negative_impls)] -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait MyTrait {} diff --git a/src/test/ui/specialization/specialization-overlap-negative.stderr b/src/test/ui/specialization/specialization-overlap-negative.stderr index e2616534d2041..6141174ba8c03 100644 --- a/src/test/ui/specialization/specialization-overlap-negative.stderr +++ b/src/test/ui/specialization/specialization-overlap-negative.stderr @@ -1,3 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-overlap-negative.rs:2:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + error[E0751]: found both positive and negative implementation of trait `std::marker::Send` for type `TestType<_>`: --> $DIR/specialization-overlap-negative.rs:9:1 | @@ -6,6 +15,6 @@ LL | unsafe impl Send for TestType {} LL | impl !Send for TestType {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here -error: aborting due to previous error +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0751`. diff --git a/src/test/ui/specialization/specialization-overlap-projection.rs b/src/test/ui/specialization/specialization-overlap-projection.rs index 00b83c7e7a1b8..b07efb2a5c1cd 100644 --- a/src/test/ui/specialization/specialization-overlap-projection.rs +++ b/src/test/ui/specialization/specialization-overlap-projection.rs @@ -4,7 +4,7 @@ // projections involve specialization, so long as the associated type is // provided by the most specialized impl. -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait Assoc { type Output; diff --git a/src/test/ui/specialization/specialization-overlap-projection.stderr b/src/test/ui/specialization/specialization-overlap-projection.stderr new file mode 100644 index 0000000000000..6f1a594bacb3a --- /dev/null +++ b/src/test/ui/specialization/specialization-overlap-projection.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-overlap-projection.rs:7:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/specialization/specialization-overlap.rs b/src/test/ui/specialization/specialization-overlap.rs index c8ef8d61c1e8f..6bee22ceb8b64 100644 --- a/src/test/ui/specialization/specialization-overlap.rs +++ b/src/test/ui/specialization/specialization-overlap.rs @@ -1,4 +1,4 @@ -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait Foo { fn foo() {} } impl Foo for T {} diff --git a/src/test/ui/specialization/specialization-overlap.stderr b/src/test/ui/specialization/specialization-overlap.stderr index 4275e7bdd85e2..cf0f186a18337 100644 --- a/src/test/ui/specialization/specialization-overlap.stderr +++ b/src/test/ui/specialization/specialization-overlap.stderr @@ -1,3 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-overlap.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + error[E0119]: conflicting implementations of trait `Foo` for type `std::vec::Vec<_>`: --> $DIR/specialization-overlap.rs:5:1 | @@ -30,6 +39,6 @@ LL | impl Qux for T {} LL | impl Qux for T {} | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation -error: aborting due to 4 previous errors +error: aborting due to 4 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/specialization/specialization-polarity.rs b/src/test/ui/specialization/specialization-polarity.rs index e78035f171075..17897d8b803d9 100644 --- a/src/test/ui/specialization/specialization-polarity.rs +++ b/src/test/ui/specialization/specialization-polarity.rs @@ -2,7 +2,7 @@ #![feature(optin_builtin_traits)] #![feature(negative_impls)] -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete auto trait Foo {} diff --git a/src/test/ui/specialization/specialization-polarity.stderr b/src/test/ui/specialization/specialization-polarity.stderr index 44e60cad67aa4..c44af22b8e63b 100644 --- a/src/test/ui/specialization/specialization-polarity.stderr +++ b/src/test/ui/specialization/specialization-polarity.stderr @@ -1,3 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-polarity.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + error[E0751]: found both positive and negative implementation of trait `Foo` for type `u8`: --> $DIR/specialization-polarity.rs:10:1 | @@ -14,6 +23,6 @@ LL | impl !Bar for T {} LL | impl Bar for u8 {} | ^^^^^^^^^^^^^^^ positive implementation here -error: aborting due to 2 previous errors +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0751`. diff --git a/src/test/ui/specialization/specialization-projection-alias.rs b/src/test/ui/specialization/specialization-projection-alias.rs index 0081ed455c960..f1f0b47bb6503 100644 --- a/src/test/ui/specialization/specialization-projection-alias.rs +++ b/src/test/ui/specialization/specialization-projection-alias.rs @@ -2,7 +2,7 @@ #![allow(dead_code)] #![allow(unused_variables)] -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete // Regression test for ICE when combining specialized associated types and type // aliases diff --git a/src/test/ui/specialization/specialization-projection-alias.stderr b/src/test/ui/specialization/specialization-projection-alias.stderr new file mode 100644 index 0000000000000..0c3659a8f7a06 --- /dev/null +++ b/src/test/ui/specialization/specialization-projection-alias.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-projection-alias.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/specialization/specialization-projection.rs b/src/test/ui/specialization/specialization-projection.rs index 86cdccf131e22..700975e3b828f 100644 --- a/src/test/ui/specialization/specialization-projection.rs +++ b/src/test/ui/specialization/specialization-projection.rs @@ -1,7 +1,7 @@ // run-pass #![allow(dead_code)] -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete // Make sure we *can* project non-defaulted associated types // cf compile-fail/specialization-default-projection.rs diff --git a/src/test/ui/specialization/specialization-projection.stderr b/src/test/ui/specialization/specialization-projection.stderr new file mode 100644 index 0000000000000..c5c86f5108e6e --- /dev/null +++ b/src/test/ui/specialization/specialization-projection.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-projection.rs:4:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/specialization/specialization-super-traits.rs b/src/test/ui/specialization/specialization-super-traits.rs index a0f71d876931e..fb85d8019218a 100644 --- a/src/test/ui/specialization/specialization-super-traits.rs +++ b/src/test/ui/specialization/specialization-super-traits.rs @@ -1,6 +1,6 @@ // run-pass -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete // Test that you can specialize via an explicit trait hierarchy diff --git a/src/test/ui/specialization/specialization-super-traits.stderr b/src/test/ui/specialization/specialization-super-traits.stderr new file mode 100644 index 0000000000000..05bdfd40136a4 --- /dev/null +++ b/src/test/ui/specialization/specialization-super-traits.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-super-traits.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.rs b/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.rs index 2e32e3ff02d3e..5c2781a9c63a6 100644 --- a/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.rs +++ b/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.rs @@ -1,6 +1,6 @@ // run-pass -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait Iterator { fn next(&self); diff --git a/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.stderr b/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.stderr new file mode 100644 index 0000000000000..6284dd8f3f7d7 --- /dev/null +++ b/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-translate-projections-with-lifetimes.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/specialization/specialization-translate-projections-with-params.rs b/src/test/ui/specialization/specialization-translate-projections-with-params.rs index bdc6501df44b8..62d63590a6688 100644 --- a/src/test/ui/specialization/specialization-translate-projections-with-params.rs +++ b/src/test/ui/specialization/specialization-translate-projections-with-params.rs @@ -4,7 +4,7 @@ // type parameters *and* rely on projections, and the type parameters are input // types on the trait. -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait Trait { fn convert(&self) -> T; diff --git a/src/test/ui/specialization/specialization-translate-projections-with-params.stderr b/src/test/ui/specialization/specialization-translate-projections-with-params.stderr new file mode 100644 index 0000000000000..b17794173c570 --- /dev/null +++ b/src/test/ui/specialization/specialization-translate-projections-with-params.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-translate-projections-with-params.rs:7:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/specialization/specialization-translate-projections.rs b/src/test/ui/specialization/specialization-translate-projections.rs index fcccb67902e58..92ea9e2b85d32 100644 --- a/src/test/ui/specialization/specialization-translate-projections.rs +++ b/src/test/ui/specialization/specialization-translate-projections.rs @@ -3,7 +3,7 @@ // Ensure that provided items are inherited properly even when impls vary in // type parameters *and* rely on projections. -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete use std::convert::Into; diff --git a/src/test/ui/specialization/specialization-translate-projections.stderr b/src/test/ui/specialization/specialization-translate-projections.stderr new file mode 100644 index 0000000000000..fbb28e6064088 --- /dev/null +++ b/src/test/ui/specialization/specialization-translate-projections.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-translate-projections.rs:6:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/static/static-drop-scope.stderr b/src/test/ui/static/static-drop-scope.stderr index bc08f33f82093..ed81734f6ebd7 100644 --- a/src/test/ui/static/static-drop-scope.stderr +++ b/src/test/ui/static/static-drop-scope.stderr @@ -2,7 +2,9 @@ error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:9:60 | LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor); - | ^^^^^^^^ statics cannot evaluate destructors + | ^^^^^^^^- value is dropped here + | | + | statics cannot evaluate destructors error[E0716]: temporary value dropped while borrowed --> $DIR/static-drop-scope.rs:9:60 @@ -18,7 +20,9 @@ error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:13:59 | LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); - | ^^^^^^^^ constants cannot evaluate destructors + | ^^^^^^^^- value is dropped here + | | + | constants cannot evaluate destructors error[E0716]: temporary value dropped while borrowed --> $DIR/static-drop-scope.rs:13:59 @@ -34,37 +38,50 @@ error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:17:28 | LL | static EARLY_DROP_S: i32 = (WithDtor, 0).1; - | ^^^^^^^^^^^^^ statics cannot evaluate destructors + | ^^^^^^^^^^^^^ - value is dropped here + | | + | statics cannot evaluate destructors error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:20:27 | LL | const EARLY_DROP_C: i32 = (WithDtor, 0).1; - | ^^^^^^^^^^^^^ constants cannot evaluate destructors + | ^^^^^^^^^^^^^ - value is dropped here + | | + | constants cannot evaluate destructors error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:23:24 | LL | const fn const_drop(_: T) {} - | ^ constant functions cannot evaluate destructors + | ^ - value is dropped here + | | + | constant functions cannot evaluate destructors error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:27:5 | LL | (x, ()).1 | ^^^^^^^ constant functions cannot evaluate destructors +LL | +LL | } + | - value is dropped here error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:31:34 | LL | const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1; - | ^^^^^^^^^^^^^^^^^^^ constants cannot evaluate destructors + | ^^^^^^^^^^^^^^^^^^^ - value is dropped here + | | + | constants cannot evaluate destructors error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:36:43 | LL | const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1; - | ^^^^^^^^^^^ constants cannot evaluate destructors + | ^^^^^^^^^^^ - value is dropped here + | | + | constants cannot evaluate destructors error: aborting due to 10 previous errors diff --git a/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.rs b/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.rs new file mode 100644 index 0000000000000..ef64d799b65cf --- /dev/null +++ b/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.rs @@ -0,0 +1,28 @@ +trait Trait { + fn func1() -> Struct1; //~ ERROR E0277 + fn func2<'a>() -> Struct2<'a, Self>; //~ ERROR E0277 + fn func3() -> Struct3; //~ ERROR E0277 + fn func4() -> Struct4; //~ ERROR E0277 +} + +struct Struct1{ + _t: std::marker::PhantomData<*const T>, +} +struct Struct2<'a, T>{ + _t: &'a T, +} +struct Struct3{ + _t: T, +} + +struct X(T); + +struct Struct4{ + _t: X, +} + +struct Struct5{ + _t: X, //~ ERROR E0277 +} + +fn main() {} diff --git a/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.stderr b/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.stderr new file mode 100644 index 0000000000000..ee08f51f80270 --- /dev/null +++ b/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.stderr @@ -0,0 +1,107 @@ +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/adt-param-with-implicit-sized-bound.rs:25:5 + | +LL | struct X(T); + | - required by this bound in `X` +... +LL | struct Struct5{ + | - this type parameter needs to be `std::marker::Sized` +LL | _t: X, + | ^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `T` + = note: to learn more, visit +help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` + --> $DIR/adt-param-with-implicit-sized-bound.rs:18:10 + | +LL | struct X(T); + | ^ - ...if indirection was used here: `Box` + | | + | this could be changed to `T: ?Sized`... + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/adt-param-with-implicit-sized-bound.rs:2:19 + | +LL | fn func1() -> Struct1; + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time +... +LL | struct Struct1{ + | - required by this bound in `Struct1` + | + = help: the trait `std::marker::Sized` is not implemented for `Self` + = note: to learn more, visit +help: consider further restricting `Self` + | +LL | fn func1() -> Struct1 where Self: std::marker::Sized; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider relaxing the implicit `Sized` restriction + | +LL | struct Struct1{ + | ^^^^^^^^ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/adt-param-with-implicit-sized-bound.rs:3:23 + | +LL | fn func2<'a>() -> Struct2<'a, Self>; + | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time +... +LL | struct Struct2<'a, T>{ + | - required by this bound in `Struct2` + | + = help: the trait `std::marker::Sized` is not implemented for `Self` + = note: to learn more, visit +help: consider further restricting `Self` + | +LL | fn func2<'a>() -> Struct2<'a, Self> where Self: std::marker::Sized; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider relaxing the implicit `Sized` restriction + | +LL | struct Struct2<'a, T: ?Sized>{ + | ^^^^^^^^ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/adt-param-with-implicit-sized-bound.rs:4:19 + | +LL | fn func3() -> Struct3; + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time +... +LL | struct Struct3{ + | - required by this bound in `Struct3` + | + = help: the trait `std::marker::Sized` is not implemented for `Self` + = note: to learn more, visit +help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` + --> $DIR/adt-param-with-implicit-sized-bound.rs:14:16 + | +LL | struct Struct3{ + | ^ this could be changed to `T: ?Sized`... +LL | _t: T, + | - ...if indirection was used here: `Box` +help: consider further restricting `Self` + | +LL | fn func3() -> Struct3 where Self: std::marker::Sized; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/adt-param-with-implicit-sized-bound.rs:5:19 + | +LL | fn func4() -> Struct4; + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time +... +LL | struct Struct4{ + | - required by this bound in `Struct4` + | + = help: the trait `std::marker::Sized` is not implemented for `Self` + = note: to learn more, visit +help: consider further restricting `Self` + | +LL | fn func4() -> Struct4 where Self: std::marker::Sized; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider relaxing the implicit `Sized` restriction + | +LL | struct Struct4{ + | ^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.nll.stderr b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.nll.stderr new file mode 100644 index 0000000000000..2407d13714a2a --- /dev/null +++ b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.nll.stderr @@ -0,0 +1,53 @@ +error: lifetime may not live long enough + --> $DIR/trait-object-nested-in-impl-trait.rs:27:23 + | +LL | fn iter(&self) -> impl Iterator> { + | - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'1` must outlive `'static` + | | + | let's call the lifetime of this reference `'1` + | +help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound + | +LL | fn iter(&self) -> impl Iterator> + '_ { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: lifetime may not live long enough + --> $DIR/trait-object-nested-in-impl-trait.rs:39:9 + | +LL | fn iter(&self) -> impl Iterator> + '_ { + | - let's call the lifetime of this reference `'1` +LL | / Iter { +LL | | current: None, +LL | | remaining: self.0.iter(), +LL | | } + | |_________^ returning this value requires that `'1` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/trait-object-nested-in-impl-trait.rs:50:9 + | +LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { + | -- lifetime `'a` defined here +LL | / Iter { +LL | | current: None, +LL | | remaining: self.0.iter(), +LL | | } + | |_________^ returning this value requires that `'a` must outlive `'static` + | + = help: consider replacing `'a` with `'static` + +error: lifetime may not live long enough + --> $DIR/trait-object-nested-in-impl-trait.rs:60:30 + | +LL | fn iter<'a>(&'a self) -> impl Iterator> { + | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'a` must outlive `'static` + | | + | lifetime `'a` defined here + | + = help: consider replacing `'a` with `'static` +help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound + | +LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs new file mode 100644 index 0000000000000..f78edb1c83a4c --- /dev/null +++ b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs @@ -0,0 +1,68 @@ +trait Foo {} +impl<'a, T: Foo> Foo for &'a T {} +impl Foo for Box {} + +struct Iter<'a, T> { + current: Option>, + remaining: T, +} + +impl<'a, T> Iterator for Iter<'a, T> +where + T: Iterator, + T::Item: Foo + 'a, +{ + type Item = Box; + + fn next(&mut self) -> Option { + let result = self.current.take(); + self.current = Box::new(self.remaining.next()).map(|f| Box::new(f) as _); + result + } +} + +struct Bar(Vec>); + +impl Bar { + fn iter(&self) -> impl Iterator> { + Iter { + current: None, + remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime + } + } +} + +struct Baz(Vec>); + +impl Baz { + fn iter(&self) -> impl Iterator> + '_ { + Iter { + current: None, + remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime + } + } +} + +struct Bat(Vec>); + +impl Bat { + fn iter<'a>(&'a self) -> impl Iterator> + 'a { + Iter { + current: None, + remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime + } + } +} + +struct Ban(Vec>); + +impl Ban { + fn iter<'a>(&'a self) -> impl Iterator> { + Iter { + current: None, + remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime + } + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr new file mode 100644 index 0000000000000..1257e9b172cf7 --- /dev/null +++ b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr @@ -0,0 +1,95 @@ +error[E0759]: cannot infer an appropriate lifetime + --> $DIR/trait-object-nested-in-impl-trait.rs:30:31 + | +LL | fn iter(&self) -> impl Iterator> { + | ----- this data with an anonymous lifetime `'_`... +... +LL | remaining: self.0.iter(), + | ------ ^^^^ + | | + | ...is captured here... + | +note: ...and is required to live as long as `'static` here + --> $DIR/trait-object-nested-in-impl-trait.rs:27:23 + | +LL | fn iter(&self) -> impl Iterator> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound + | +LL | fn iter(&self) -> impl Iterator> + '_ { + | ^^^^ +help: to declare that the trait object captures data from argument `self`, you can add an explicit `'_` lifetime bound + | +LL | fn iter(&self) -> impl Iterator> { + | ^^^^ + +error[E0759]: cannot infer an appropriate lifetime + --> $DIR/trait-object-nested-in-impl-trait.rs:41:31 + | +LL | fn iter(&self) -> impl Iterator> + '_ { + | ----- this data with an anonymous lifetime `'_`... +... +LL | remaining: self.0.iter(), + | ------ ^^^^ + | | + | ...is captured here... + | +note: ...and is required to live as long as `'static` here + --> $DIR/trait-object-nested-in-impl-trait.rs:38:23 + | +LL | fn iter(&self) -> impl Iterator> + '_ { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: to declare that the trait object captures data from argument `self`, you can add an explicit `'_` lifetime bound + | +LL | fn iter(&self) -> impl Iterator> + '_ { + | ^^^^ + +error[E0759]: cannot infer an appropriate lifetime + --> $DIR/trait-object-nested-in-impl-trait.rs:52:31 + | +LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { + | -------- this data with lifetime `'a`... +... +LL | remaining: self.0.iter(), + | ------ ^^^^ + | | + | ...is captured here... + | +note: ...and is required to live as long as `'static` here + --> $DIR/trait-object-nested-in-impl-trait.rs:49:30 + | +LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: to declare that the trait object captures data from argument `self`, you can add an explicit `'a` lifetime bound + | +LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { + | ^^^^ + +error[E0759]: cannot infer an appropriate lifetime + --> $DIR/trait-object-nested-in-impl-trait.rs:63:31 + | +LL | fn iter<'a>(&'a self) -> impl Iterator> { + | -------- this data with lifetime `'a`... +... +LL | remaining: self.0.iter(), + | ------ ^^^^ + | | + | ...is captured here... + | +note: ...and is required to live as long as `'static` here + --> $DIR/trait-object-nested-in-impl-trait.rs:60:30 + | +LL | fn iter<'a>(&'a self) -> impl Iterator> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'a` lifetime bound + | +LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { + | ^^^^ +help: to declare that the trait object captures data from argument `self`, you can add an explicit `'a` lifetime bound + | +LL | fn iter<'a>(&'a self) -> impl Iterator> { + | ^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/suggestions/suggest-move-types.stderr b/src/test/ui/suggestions/suggest-move-types.stderr index 96f1656bae4ac..3c2226574ee9e 100644 --- a/src/test/ui/suggestions/suggest-move-types.stderr +++ b/src/test/ui/suggestions/suggest-move-types.stderr @@ -125,6 +125,7 @@ LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime` error[E0747]: lifetime provided when a type was expected --> $DIR/suggest-move-types.rs:82:56 @@ -133,6 +134,7 @@ LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime` error: aborting due to 12 previous errors diff --git a/src/test/ui/traits/negative-impls/negative-default-impls.rs b/src/test/ui/traits/negative-impls/negative-default-impls.rs index 2d50bc83ec304..c68bca432fa86 100644 --- a/src/test/ui/traits/negative-impls/negative-default-impls.rs +++ b/src/test/ui/traits/negative-impls/negative-default-impls.rs @@ -1,5 +1,6 @@ #![feature(negative_impls)] #![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete trait MyTrait { type Foo; diff --git a/src/test/ui/traits/negative-impls/negative-default-impls.stderr b/src/test/ui/traits/negative-impls/negative-default-impls.stderr index a70bbe6b948d1..50e74373b53bb 100644 --- a/src/test/ui/traits/negative-impls/negative-default-impls.stderr +++ b/src/test/ui/traits/negative-impls/negative-default-impls.stderr @@ -1,9 +1,18 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/negative-default-impls.rs:2:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + error[E0750]: negative impls cannot be default impls - --> $DIR/negative-default-impls.rs:8:1 + --> $DIR/negative-default-impls.rs:9:1 | LL | default impl !MyTrait for u32 {} | ^^^^^^^ ^ -error: aborting due to previous error +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0750`. diff --git a/src/test/ui/traits/negative-impls/negative-specializes-negative.rs b/src/test/ui/traits/negative-impls/negative-specializes-negative.rs index 877c3e8af4f1a..35297ab124ed0 100644 --- a/src/test/ui/traits/negative-impls/negative-specializes-negative.rs +++ b/src/test/ui/traits/negative-impls/negative-specializes-negative.rs @@ -1,4 +1,4 @@ -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete #![feature(negative_impls)] // Test a negative impl that "specializes" another negative impl. diff --git a/src/test/ui/traits/negative-impls/negative-specializes-negative.stderr b/src/test/ui/traits/negative-impls/negative-specializes-negative.stderr new file mode 100644 index 0000000000000..8b536de378630 --- /dev/null +++ b/src/test/ui/traits/negative-impls/negative-specializes-negative.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/negative-specializes-negative.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + 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 index da22e43377f52..4281eedaf631c 100644 --- a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs +++ b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs @@ -1,4 +1,4 @@ -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete #![feature(negative_impls)] // Negative impl for u32 cannot "specialize" the base impl. 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 index 079546a7df40b..89ef15e89ac96 100644 --- a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr +++ b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr @@ -1,3 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/negative-specializes-positive-item.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`: --> $DIR/negative-specializes-positive-item.rs:11:1 | @@ -7,6 +16,6 @@ LL | impl MyTrait for T { LL | impl !MyTrait for u32 {} | ^^^^^^^^^^^^^^^^^^^^^ negative implementation here -error: aborting due to previous error +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0751`. diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive.rs b/src/test/ui/traits/negative-impls/negative-specializes-positive.rs index 1939a098b50ee..0e227691e0404 100644 --- a/src/test/ui/traits/negative-impls/negative-specializes-positive.rs +++ b/src/test/ui/traits/negative-impls/negative-specializes-positive.rs @@ -1,4 +1,4 @@ -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete #![feature(negative_impls)] // Negative impl for u32 cannot "specialize" the base impl. diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr b/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr index ea005c1cbe0c6..e45d5a251ab26 100644 --- a/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr +++ b/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr @@ -1,3 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/negative-specializes-positive.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`: --> $DIR/negative-specializes-positive.rs:7:1 | @@ -6,6 +15,6 @@ LL | impl MyTrait for T {} LL | impl !MyTrait for u32 {} | ^^^^^^^^^^^^^^^^^^^^^ negative implementation here -error: aborting due to previous error +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0751`. diff --git a/src/test/ui/traits/negative-impls/positive-specializes-negative.rs b/src/test/ui/traits/negative-impls/positive-specializes-negative.rs index f2c5f507a4ebb..a06b357654068 100644 --- a/src/test/ui/traits/negative-impls/positive-specializes-negative.rs +++ b/src/test/ui/traits/negative-impls/positive-specializes-negative.rs @@ -1,4 +1,4 @@ -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete #![feature(negative_impls)] trait MyTrait {} diff --git a/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr b/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr index a24d7aa442f4a..49c16d474040e 100644 --- a/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr +++ b/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr @@ -1,3 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/positive-specializes-negative.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`: --> $DIR/positive-specializes-negative.rs:7:1 | @@ -6,6 +15,6 @@ LL | impl !MyTrait for T {} LL | impl MyTrait for u32 {} | ^^^^^^^^^^^^^^^^^^^^ positive implementation here -error: aborting due to previous error +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0751`. diff --git a/src/test/ui/traits/trait-item-privacy.stderr b/src/test/ui/traits/trait-item-privacy.stderr index 7fd5c11fcf090..3be4f11097311 100644 --- a/src/test/ui/traits/trait-item-privacy.stderr +++ b/src/test/ui/traits/trait-item-privacy.stderr @@ -20,13 +20,6 @@ error[E0599]: no method named `b` found for struct `S` in the current scope LL | struct S; | --------- method `b` not found for this ... -LL | fn b(&self) { } - | - - | | - | the method is available for `std::boxed::Box` here - | the method is available for `std::sync::Arc` here - | the method is available for `std::rc::Rc` here -... LL | S.b(); | ^ method not found in `S` | diff --git a/src/test/ui/traits/trait-suggest-deferences-issue-39029.fixed b/src/test/ui/traits/trait-suggest-deferences-issue-39029.fixed new file mode 100644 index 0000000000000..2bb34b0ebee6f --- /dev/null +++ b/src/test/ui/traits/trait-suggest-deferences-issue-39029.fixed @@ -0,0 +1,18 @@ +// run-rustfix +use std::net::TcpListener; + +struct NoToSocketAddrs(String); + +impl std::ops::Deref for NoToSocketAddrs { + type Target = String; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +fn main() { + let _works = TcpListener::bind("some string"); + let bad = NoToSocketAddrs("bad".to_owned()); + let _errors = TcpListener::bind(&*bad); + //~^ ERROR the trait bound `NoToSocketAddrs: std::net::ToSocketAddrs` is not satisfied +} diff --git a/src/test/ui/traits/trait-suggest-deferences-issue-39029.rs b/src/test/ui/traits/trait-suggest-deferences-issue-39029.rs new file mode 100644 index 0000000000000..33d524608a058 --- /dev/null +++ b/src/test/ui/traits/trait-suggest-deferences-issue-39029.rs @@ -0,0 +1,18 @@ +// run-rustfix +use std::net::TcpListener; + +struct NoToSocketAddrs(String); + +impl std::ops::Deref for NoToSocketAddrs { + type Target = String; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +fn main() { + let _works = TcpListener::bind("some string"); + let bad = NoToSocketAddrs("bad".to_owned()); + let _errors = TcpListener::bind(&bad); + //~^ ERROR the trait bound `NoToSocketAddrs: std::net::ToSocketAddrs` is not satisfied +} diff --git a/src/test/ui/traits/trait-suggest-deferences-issue-39029.stderr b/src/test/ui/traits/trait-suggest-deferences-issue-39029.stderr new file mode 100644 index 0000000000000..0bf9794a744c9 --- /dev/null +++ b/src/test/ui/traits/trait-suggest-deferences-issue-39029.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `NoToSocketAddrs: std::net::ToSocketAddrs` is not satisfied + --> $DIR/trait-suggest-deferences-issue-39029.rs:16:37 + | +LL | let _errors = TcpListener::bind(&bad); + | ^^^^ + | | + | the trait `std::net::ToSocketAddrs` is not implemented for `NoToSocketAddrs` + | help: consider adding dereference here: `&*bad` + | + ::: $SRC_DIR/libstd/net/tcp.rs:LL:COL + | +LL | pub fn bind(addr: A) -> io::Result { + | ------------- required by this bound in `std::net::TcpListener::bind` + | + = note: required because of the requirements on the impl of `std::net::ToSocketAddrs` for `&NoToSocketAddrs` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/traits/trait-suggest-deferences-issue-62530.fixed b/src/test/ui/traits/trait-suggest-deferences-issue-62530.fixed new file mode 100644 index 0000000000000..fa7b9167d8d7f --- /dev/null +++ b/src/test/ui/traits/trait-suggest-deferences-issue-62530.fixed @@ -0,0 +1,15 @@ +// run-rustfix +fn takes_str(_x: &str) {} + +fn takes_type_parameter(_x: T) where T: SomeTrait {} + +trait SomeTrait {} +impl SomeTrait for &'_ str {} +impl SomeTrait for char {} + +fn main() { + let string = String::new(); + takes_str(&string); // Ok + takes_type_parameter(&*string); // Error + //~^ ERROR the trait bound `&std::string::String: SomeTrait` is not satisfied +} diff --git a/src/test/ui/traits/trait-suggest-deferences-issue-62530.rs b/src/test/ui/traits/trait-suggest-deferences-issue-62530.rs new file mode 100644 index 0000000000000..e785f01217735 --- /dev/null +++ b/src/test/ui/traits/trait-suggest-deferences-issue-62530.rs @@ -0,0 +1,15 @@ +// run-rustfix +fn takes_str(_x: &str) {} + +fn takes_type_parameter(_x: T) where T: SomeTrait {} + +trait SomeTrait {} +impl SomeTrait for &'_ str {} +impl SomeTrait for char {} + +fn main() { + let string = String::new(); + takes_str(&string); // Ok + takes_type_parameter(&string); // Error + //~^ ERROR the trait bound `&std::string::String: SomeTrait` is not satisfied +} diff --git a/src/test/ui/traits/trait-suggest-deferences-issue-62530.stderr b/src/test/ui/traits/trait-suggest-deferences-issue-62530.stderr new file mode 100644 index 0000000000000..9c2a582638ecb --- /dev/null +++ b/src/test/ui/traits/trait-suggest-deferences-issue-62530.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `&std::string::String: SomeTrait` is not satisfied + --> $DIR/trait-suggest-deferences-issue-62530.rs:13:26 + | +LL | fn takes_type_parameter(_x: T) where T: SomeTrait {} + | --------- required by this bound in `takes_type_parameter` +... +LL | takes_type_parameter(&string); // Error + | ^^^^^^^ + | | + | the trait `SomeTrait` is not implemented for `&std::string::String` + | help: consider adding dereference here: `&*string` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/traits/trait-suggest-deferences-multiple-0.fixed b/src/test/ui/traits/trait-suggest-deferences-multiple-0.fixed new file mode 100644 index 0000000000000..b7160b75c605e --- /dev/null +++ b/src/test/ui/traits/trait-suggest-deferences-multiple-0.fixed @@ -0,0 +1,36 @@ +// run-rustfix +use std::ops::Deref; + +trait Happy {} +struct LDM; +impl Happy for &LDM {} + +struct Foo(LDM); +struct Bar(Foo); +struct Baz(Bar); +impl Deref for Foo { + type Target = LDM; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Bar { + type Target = Foo; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Baz { + type Target = Bar; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +fn foo(_: T) where T: Happy {} + +fn main() { + let baz = Baz(Bar(Foo(LDM))); + foo(&***baz); + //~^ ERROR the trait bound `&Baz: Happy` is not satisfied +} diff --git a/src/test/ui/traits/trait-suggest-deferences-multiple-0.rs b/src/test/ui/traits/trait-suggest-deferences-multiple-0.rs new file mode 100644 index 0000000000000..9ac55177ffadd --- /dev/null +++ b/src/test/ui/traits/trait-suggest-deferences-multiple-0.rs @@ -0,0 +1,36 @@ +// run-rustfix +use std::ops::Deref; + +trait Happy {} +struct LDM; +impl Happy for &LDM {} + +struct Foo(LDM); +struct Bar(Foo); +struct Baz(Bar); +impl Deref for Foo { + type Target = LDM; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Bar { + type Target = Foo; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Baz { + type Target = Bar; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +fn foo(_: T) where T: Happy {} + +fn main() { + let baz = Baz(Bar(Foo(LDM))); + foo(&baz); + //~^ ERROR the trait bound `&Baz: Happy` is not satisfied +} diff --git a/src/test/ui/traits/trait-suggest-deferences-multiple-0.stderr b/src/test/ui/traits/trait-suggest-deferences-multiple-0.stderr new file mode 100644 index 0000000000000..add34a553bc9f --- /dev/null +++ b/src/test/ui/traits/trait-suggest-deferences-multiple-0.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `&Baz: Happy` is not satisfied + --> $DIR/trait-suggest-deferences-multiple-0.rs:34:9 + | +LL | fn foo(_: T) where T: Happy {} + | ----- required by this bound in `foo` +... +LL | foo(&baz); + | ^^^^ + | | + | the trait `Happy` is not implemented for `&Baz` + | help: consider adding dereference here: `&***baz` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/traits/trait-suggest-deferences-multiple-1.rs b/src/test/ui/traits/trait-suggest-deferences-multiple-1.rs new file mode 100644 index 0000000000000..91c6c7924a408 --- /dev/null +++ b/src/test/ui/traits/trait-suggest-deferences-multiple-1.rs @@ -0,0 +1,54 @@ +use std::ops::{Deref, DerefMut}; + +trait Happy {} +struct LDM; +impl Happy for &mut LDM {} + +struct Foo(LDM); +struct Bar(Foo); +struct Baz(Bar); +impl Deref for Foo { + type Target = LDM; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Bar { + type Target = Foo; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Baz { + type Target = Bar; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl DerefMut for Foo { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +impl DerefMut for Bar { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +impl DerefMut for Baz { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + + +fn foo(_: T) where T: Happy {} + +fn main() { + // Currently the compiler doesn't try to suggest dereferences for situations + // where DerefMut involves. So this test is meant to ensure compiler doesn't + // generate incorrect help message. + let mut baz = Baz(Bar(Foo(LDM))); + foo(&mut baz); + //~^ ERROR the trait bound `&mut Baz: Happy` is not satisfied +} diff --git a/src/test/ui/traits/trait-suggest-deferences-multiple-1.stderr b/src/test/ui/traits/trait-suggest-deferences-multiple-1.stderr new file mode 100644 index 0000000000000..e90278fa16f0e --- /dev/null +++ b/src/test/ui/traits/trait-suggest-deferences-multiple-1.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `&mut Baz: Happy` is not satisfied + --> $DIR/trait-suggest-deferences-multiple-1.rs:52:9 + | +LL | fn foo(_: T) where T: Happy {} + | ----- required by this bound in `foo` +... +LL | foo(&mut baz); + | ^^^^^^^^ the trait `Happy` is not implemented for `&mut Baz` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/traits/traits-inductive-overflow-lifetime.rs b/src/test/ui/traits/traits-inductive-overflow-lifetime.rs new file mode 100644 index 0000000000000..205d50a2ed9ce --- /dev/null +++ b/src/test/ui/traits/traits-inductive-overflow-lifetime.rs @@ -0,0 +1,30 @@ +// Test that we don't hit the recursion limit for short cycles involving lifetimes. + +// Shouldn't hit this, we should realize that we're in a cycle sooner. +#![recursion_limit="20"] + +trait NotAuto {} +trait Y { + type P; +} + +impl<'a> Y for C<'a> { + type P = Box>>; +} + +struct C<'a>(&'a ()); +struct X(T::P); + +impl NotAuto for Box {} +impl NotAuto for X where T::P: NotAuto {} +impl<'a> NotAuto for C<'a> {} + +fn is_send() {} +//~^ NOTE: required + +fn main() { + // Should only be a few notes. + is_send::>>(); + //~^ ERROR overflow evaluating + //~| NOTE: required +} diff --git a/src/test/ui/traits/traits-inductive-overflow-lifetime.stderr b/src/test/ui/traits/traits-inductive-overflow-lifetime.stderr new file mode 100644 index 0000000000000..9a227229ea4c2 --- /dev/null +++ b/src/test/ui/traits/traits-inductive-overflow-lifetime.stderr @@ -0,0 +1,14 @@ +error[E0275]: overflow evaluating the requirement `std::boxed::Box>>: NotAuto` + --> $DIR/traits-inductive-overflow-lifetime.rs:27:5 + | +LL | fn is_send() {} + | ------- required by this bound in `is_send` +... +LL | is_send::>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: required because of the requirements on the impl of `NotAuto` for `X>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/transmute-specialization.rs b/src/test/ui/transmute-specialization.rs index 002fba9ce8101..499334d983b1f 100644 --- a/src/test/ui/transmute-specialization.rs +++ b/src/test/ui/transmute-specialization.rs @@ -1,6 +1,6 @@ // run-pass -#![feature(specialization)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait Specializable { type Output; } diff --git a/src/test/ui/transmute-specialization.stderr b/src/test/ui/transmute-specialization.stderr new file mode 100644 index 0000000000000..02315051d30ec --- /dev/null +++ b/src/test/ui/transmute-specialization.stderr @@ -0,0 +1,11 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/transmute-specialization.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr new file mode 100644 index 0000000000000..8c9cb742fac91 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr @@ -0,0 +1,14 @@ +error: higher-ranked subtype error + --> $DIR/issue-57611-trait-alias.rs:21:9 + | +LL | |x| x + | ^^^^^ + +error: higher-ranked subtype error + --> $DIR/issue-57611-trait-alias.rs:21:9 + | +LL | |x| x + | ^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs index 1c2051e7eaeeb..41e019247c942 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs @@ -14,8 +14,8 @@ trait Foo { struct X; impl Foo for X { - type Bar = impl Baz; //~ ERROR type mismatch in closure arguments - //~^ ERROR type mismatch resolving + type Bar = impl Baz; + //~^ ERROR mismatched types fn bar(&self) -> Self::Bar { |x| x diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr index cc121ac89fb8d..cd637056c94ad 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr @@ -1,23 +1,12 @@ -error[E0631]: type mismatch in closure arguments +error[E0308]: mismatched types --> $DIR/issue-57611-trait-alias.rs:17:16 | LL | type Bar = impl Baz; - | ^^^^^^^^^^^^^^^^^^^^ expected signature of `for<'r> fn(&'r X) -> _` -... -LL | |x| x - | ----- found signature of `fn(_) -> _` + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | - = note: the return type of a function must have a statically known size + = note: expected type `std::ops::FnOnce<(&X,)>` + found type `std::ops::FnOnce<(&X,)>` -error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/issue-57611-trait-alias.rs:21:9: 21:14] as std::ops::FnOnce<(&'r X,)>>::Output == &'r X` - --> $DIR/issue-57611-trait-alias.rs:17:16 - | -LL | type Bar = impl Baz; - | ^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter, found concrete lifetime - | - = note: the return type of a function must have a statically known size - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0271, E0631. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.stderr index ab6f06518467c..0b9aa61a765fa 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.stderr @@ -2,7 +2,7 @@ error[E0382]: use of moved value: `tick` --> $DIR/unboxed-closures-infer-fnonce-call-twice.rs:10:5 | LL | tick(); - | ------ `tick` moved due to this call + | ---- value moved here LL | tick(); | ^^^^ value used here after move | @@ -11,11 +11,6 @@ note: closure cannot be invoked more than once because it moves the variable `co | LL | let tick = || mem::drop(counter); | ^^^^^^^ -note: this value implements `FnOnce`, which causes it to be moved when called - --> $DIR/unboxed-closures-infer-fnonce-call-twice.rs:9:5 - | -LL | tick(); - | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.stderr index 8d70a2b17602b..20773d561f9f2 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.stderr @@ -2,7 +2,7 @@ error[E0382]: use of moved value: `tick` --> $DIR/unboxed-closures-infer-fnonce-move-call-twice.rs:10:5 | LL | tick(); - | ------ `tick` moved due to this call + | ---- value moved here LL | tick(); | ^^^^ value used here after move | @@ -11,11 +11,6 @@ note: closure cannot be invoked more than once because it moves the variable `co | LL | let tick = move || mem::drop(counter); | ^^^^^^^ -note: this value implements `FnOnce`, which causes it to be moved when called - --> $DIR/unboxed-closures-infer-fnonce-move-call-twice.rs:9:5 - | -LL | tick(); - | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs index a6e26614a6a50..e2082d4f78e70 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs @@ -1,23 +1,29 @@ // Tests that unsafe extern fn pointers do not implement any Fn traits. -use std::ops::{Fn,FnMut,FnOnce}; +use std::ops::{Fn, FnMut, FnOnce}; -unsafe fn square(x: &isize) -> isize { (*x) * (*x) } +unsafe fn square(x: &isize) -> isize { + (*x) * (*x) +} -fn call_itisize>(_: &F, _: isize) -> isize { 0 } -fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } -fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } +fn call_it isize>(_: &F, _: isize) -> isize { + 0 +} +fn call_it_mut isize>(_: &mut F, _: isize) -> isize { + 0 +} +fn call_it_once isize>(_: F, _: isize) -> isize { + 0 +} fn a() { let x = call_it(&square, 22); //~^ ERROR E0277 - //~| ERROR expected } fn b() { let y = call_it_mut(&mut square, 22); //~^ ERROR E0277 - //~| ERROR expected } fn c() { @@ -25,4 +31,4 @@ fn c() { //~^ ERROR E0277 } -fn main() { } +fn main() {} diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr index b9ee9e460201a..b06f745e7c1f1 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr @@ -1,30 +1,19 @@ error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:21 + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:20:21 | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ----------------- required by this bound in `call_it` +LL | fn call_it isize>(_: &F, _: isize) -> isize { + | ------------------- required by this bound in `call_it` ... LL | let x = call_it(&square, 22); | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` | = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` -error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:21 - | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it` -... -LL | let x = call_it(&square, 22); - | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` - error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:18:25 + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:25:25 | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | -------------------- required by this bound in `call_it_mut` +LL | fn call_it_mut isize>(_: &mut F, _: isize) -> isize { + | ---------------------- required by this bound in `call_it_mut` ... LL | let y = call_it_mut(&mut square, 22); | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` @@ -32,27 +21,16 @@ LL | let y = call_it_mut(&mut square, 22); = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:18:25 - | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it_mut` -... -LL | let y = call_it_mut(&mut square, 22); - | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` - -error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:24:26 + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:30:26 | -LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it_once` +LL | fn call_it_once isize>(_: F, _: isize) -> isize { + | ----------------------- required by this bound in `call_it_once` ... LL | let z = call_it_once(square, 22); | ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` + = help: the trait `for<'r> std::ops::FnOnce<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs index dd3b1afc39f31..dd76c597d28ad 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs @@ -1,23 +1,29 @@ // Tests that unsafe extern fn pointers do not implement any Fn traits. -use std::ops::{Fn,FnMut,FnOnce}; +use std::ops::{Fn, FnMut, FnOnce}; -extern "C" fn square(x: &isize) -> isize { (*x) * (*x) } +extern "C" fn square(x: &isize) -> isize { + (*x) * (*x) +} -fn call_itisize>(_: &F, _: isize) -> isize { 0 } -fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } -fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } +fn call_it isize>(_: &F, _: isize) -> isize { + 0 +} +fn call_it_mut isize>(_: &mut F, _: isize) -> isize { + 0 +} +fn call_it_once isize>(_: F, _: isize) -> isize { + 0 +} fn a() { let x = call_it(&square, 22); //~^ ERROR E0277 - //~| ERROR expected } fn b() { let y = call_it_mut(&mut square, 22); //~^ ERROR E0277 - //~| ERROR expected } fn c() { @@ -25,4 +31,4 @@ fn c() { //~^ ERROR E0277 } -fn main() { } +fn main() {} diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr index 654b626cf65cc..8f6945cda806c 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr @@ -1,30 +1,19 @@ error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:12:21 + --> $DIR/unboxed-closures-wrong-abi.rs:20:21 | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ----------------- required by this bound in `call_it` +LL | fn call_it isize>(_: &F, _: isize) -> isize { + | ------------------- required by this bound in `call_it` ... LL | let x = call_it(&square, 22); | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` | = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` -error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:12:21 - | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it` -... -LL | let x = call_it(&square, 22); - | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` - error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:18:25 + --> $DIR/unboxed-closures-wrong-abi.rs:25:25 | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | -------------------- required by this bound in `call_it_mut` +LL | fn call_it_mut isize>(_: &mut F, _: isize) -> isize { + | ---------------------- required by this bound in `call_it_mut` ... LL | let y = call_it_mut(&mut square, 22); | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` @@ -32,27 +21,16 @@ LL | let y = call_it_mut(&mut square, 22); = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:18:25 - | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it_mut` -... -LL | let y = call_it_mut(&mut square, 22); - | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` - -error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:24:26 + --> $DIR/unboxed-closures-wrong-abi.rs:30:26 | -LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it_once` +LL | fn call_it_once isize>(_: F, _: isize) -> isize { + | ----------------------- required by this bound in `call_it_once` ... LL | let z = call_it_once(square, 22); | ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` + = help: the trait `for<'r> std::ops::FnOnce<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs index c689d79266187..02e8b7b47ae19 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs @@ -1,24 +1,30 @@ // Tests that unsafe extern fn pointers do not implement any Fn traits. -use std::ops::{Fn,FnMut,FnOnce}; +use std::ops::{Fn, FnMut, FnOnce}; -unsafe fn square(x: isize) -> isize { x * x } +unsafe fn square(x: isize) -> isize { + x * x +} // note: argument type here is `isize`, not `&isize` -fn call_itisize>(_: &F, _: isize) -> isize { 0 } -fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } -fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } +fn call_it isize>(_: &F, _: isize) -> isize { + 0 +} +fn call_it_mut isize>(_: &mut F, _: isize) -> isize { + 0 +} +fn call_it_once isize>(_: F, _: isize) -> isize { + 0 +} fn a() { let x = call_it(&square, 22); //~^ ERROR E0277 - //~| ERROR expected } fn b() { let y = call_it_mut(&mut square, 22); //~^ ERROR E0277 - //~| ERROR expected } fn c() { @@ -26,4 +32,4 @@ fn c() { //~^ ERROR E0277 } -fn main() { } +fn main() {} diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr index 434c8a579f671..93a645b485ef0 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr @@ -1,30 +1,19 @@ error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:21 + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:21:21 | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ----------------- required by this bound in `call_it` +LL | fn call_it isize>(_: &F, _: isize) -> isize { + | ------------------- required by this bound in `call_it` ... LL | let x = call_it(&square, 22); | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` | = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` -error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:21 - | -LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it` -... -LL | let x = call_it(&square, 22); - | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` - error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:19:25 + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:26:25 | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | -------------------- required by this bound in `call_it_mut` +LL | fn call_it_mut isize>(_: &mut F, _: isize) -> isize { + | ---------------------- required by this bound in `call_it_mut` ... LL | let y = call_it_mut(&mut square, 22); | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` @@ -32,27 +21,16 @@ LL | let y = call_it_mut(&mut square, 22); = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:19:25 - | -LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it_mut` -... -LL | let y = call_it_mut(&mut square, 22); - | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` - -error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:25:26 + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:31:26 | -LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it_once` +LL | fn call_it_once isize>(_: F, _: isize) -> isize { + | ----------------------- required by this bound in `call_it_once` ... LL | let z = call_it_once(square, 22); | ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` + = help: the trait `for<'r> std::ops::FnOnce<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unop-move-semantics.stderr b/src/test/ui/unop-move-semantics.stderr index 7e9c8559a4b39..e0499cfe95ce9 100644 --- a/src/test/ui/unop-move-semantics.stderr +++ b/src/test/ui/unop-move-semantics.stderr @@ -4,16 +4,11 @@ error[E0382]: borrow of moved value: `x` LL | fn move_then_borrow + Clone>(x: T) { | - move occurs because `x` has type `T`, which does not implement the `Copy` trait LL | !x; - | -- `x` moved due to this method call + | - value moved here LL | LL | x.clone(); | ^ value borrowed here after move | -note: this function consumes the receiver `self` by taking ownership of it, which moves `x` - --> $SRC_DIR/libcore/ops/bit.rs:LL:COL - | -LL | fn not(self) -> Self::Output; - | ^^^^ help: consider further restricting this bound | LL | fn move_then_borrow + Clone + Copy>(x: T) { diff --git a/src/test/ui/unsafe/unsafe-unstable-const-fn.rs b/src/test/ui/unsafe/unsafe-unstable-const-fn.rs index d9d85ee913266..963d892931a75 100644 --- a/src/test/ui/unsafe/unsafe-unstable-const-fn.rs +++ b/src/test/ui/unsafe/unsafe-unstable-const-fn.rs @@ -1,13 +1,13 @@ #![stable(feature = "foo", since = "1.33.0")] #![feature(staged_api)] -#![feature(const_compare_raw_pointers)] +#![feature(const_raw_ptr_deref)] #![feature(const_fn)] #[stable(feature = "foo", since = "1.33.0")] #[rustc_const_unstable(feature = "const_foo", issue = "none")] -const fn unstable(a: *const i32, b: *const i32) -> bool { - a == b - //~^ pointer operation is unsafe +const fn unstable(a: *const i32, b: i32) -> bool { + *a == b + //~^ dereference of raw pointer is unsafe } fn main() {} diff --git a/src/test/ui/unsafe/unsafe-unstable-const-fn.stderr b/src/test/ui/unsafe/unsafe-unstable-const-fn.stderr index d8f3737c8f541..4642a7a5fc9f8 100644 --- a/src/test/ui/unsafe/unsafe-unstable-const-fn.stderr +++ b/src/test/ui/unsafe/unsafe-unstable-const-fn.stderr @@ -1,10 +1,10 @@ -error[E0133]: pointer operation is unsafe and requires unsafe function or block +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block --> $DIR/unsafe-unstable-const-fn.rs:9:5 | -LL | a == b - | ^^^^^^ pointer operation +LL | *a == b + | ^^ dereference of raw pointer | - = note: operations on pointers in constants + = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior error: aborting due to previous error diff --git a/src/test/ui/unsized-locals/borrow-after-move.stderr b/src/test/ui/unsized-locals/borrow-after-move.stderr index 906b543e42122..110edab69be87 100644 --- a/src/test/ui/unsized-locals/borrow-after-move.stderr +++ b/src/test/ui/unsized-locals/borrow-after-move.stderr @@ -37,16 +37,10 @@ error[E0382]: borrow of moved value: `y` LL | let y = *x; | - move occurs because `y` has type `str`, which does not implement the `Copy` trait LL | y.foo(); - | ----- `y` moved due to this method call + | - value moved here ... LL | println!("{}", &y); | ^^ value borrowed here after move - | -note: this function consumes the receiver `self` by taking ownership of it, which moves `y` - --> $DIR/borrow-after-move.rs:4:12 - | -LL | fn foo(self) -> String; - | ^^^^ error[E0382]: borrow of moved value: `x` --> $DIR/borrow-after-move.rs:39:24 diff --git a/src/test/ui/unsized-locals/double-move.stderr b/src/test/ui/unsized-locals/double-move.stderr index 49b2031c6b9d9..5b936fb64474f 100644 --- a/src/test/ui/unsized-locals/double-move.stderr +++ b/src/test/ui/unsized-locals/double-move.stderr @@ -34,15 +34,9 @@ error[E0382]: use of moved value: `y` LL | let y = *x; | - move occurs because `y` has type `str`, which does not implement the `Copy` trait LL | y.foo(); - | ----- `y` moved due to this method call + | - value moved here LL | y.foo(); | ^ value used here after move - | -note: this function consumes the receiver `self` by taking ownership of it, which moves `y` - --> $DIR/double-move.rs:4:12 - | -LL | fn foo(self) -> String; - | ^^^^ error[E0382]: use of moved value: `x` --> $DIR/double-move.rs:45:9 diff --git a/src/test/ui/unsized/unsized-enum.stderr b/src/test/ui/unsized/unsized-enum.stderr index f43d00f97398d..1908aee25ea7b 100644 --- a/src/test/ui/unsized/unsized-enum.stderr +++ b/src/test/ui/unsized/unsized-enum.stderr @@ -11,6 +11,13 @@ LL | fn foo2() { not_sized::>() } | = help: the trait `std::marker::Sized` is not implemented for `T` = note: to learn more, visit +help: you could relax the implicit `Sized` bound on `U` if it were used through indirection like `&U` or `Box` + --> $DIR/unsized-enum.rs:4:10 + | +LL | enum Foo { FooSome(U), FooNone } + | ^ - ...if indirection was used here: `Box` + | | + | this could be changed to `U: ?Sized`... error: aborting due to previous error diff --git a/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr b/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr index 808c9c583d458..e0f077d66f99c 100644 --- a/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr +++ b/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr @@ -11,6 +11,13 @@ LL | impl S5 { | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit +help: you could relax the implicit `Sized` bound on `Y` if it were used through indirection like `&Y` or `Box` + --> $DIR/unsized-inherent-impl-self-type.rs:5:11 + | +LL | struct S5(Y); + | ^ - ...if indirection was used here: `Box` + | | + | this could be changed to `Y: ?Sized`... error: aborting due to previous error diff --git a/src/test/ui/unsized/unsized-struct.stderr b/src/test/ui/unsized/unsized-struct.stderr index 42fc5569eceb4..d92d1d9113e5c 100644 --- a/src/test/ui/unsized/unsized-struct.stderr +++ b/src/test/ui/unsized/unsized-struct.stderr @@ -11,6 +11,13 @@ LL | fn foo2() { not_sized::>() } | = help: the trait `std::marker::Sized` is not implemented for `T` = note: to learn more, visit +help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` + --> $DIR/unsized-struct.rs:4:12 + | +LL | struct Foo { data: T } + | ^ - ...if indirection was used here: `Box` + | | + | this could be changed to `T: ?Sized`... error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/unsized-struct.rs:13:24 diff --git a/src/test/ui/unsized/unsized-trait-impl-self-type.stderr b/src/test/ui/unsized/unsized-trait-impl-self-type.stderr index c2b2fe40ce67f..73c5439da53b6 100644 --- a/src/test/ui/unsized/unsized-trait-impl-self-type.stderr +++ b/src/test/ui/unsized/unsized-trait-impl-self-type.stderr @@ -11,6 +11,13 @@ LL | impl T3 for S5 { | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit +help: you could relax the implicit `Sized` bound on `Y` if it were used through indirection like `&Y` or `Box` + --> $DIR/unsized-trait-impl-self-type.rs:8:11 + | +LL | struct S5(Y); + | ^ - ...if indirection was used here: `Box` + | | + | this could be changed to `Y: ?Sized`... error: aborting due to previous error diff --git a/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr b/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr index 4cf054d177f66..e423a9bdeab6f 100644 --- a/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr +++ b/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr @@ -11,6 +11,10 @@ LL | impl T2 for S4 { | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit +help: consider relaxing the implicit `Sized` restriction + | +LL | trait T2 { + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/unsized3.stderr b/src/test/ui/unsized3.stderr index 828e8bc9f4aa1..e0a0389dc4690 100644 --- a/src/test/ui/unsized3.stderr +++ b/src/test/ui/unsized3.stderr @@ -48,6 +48,10 @@ LL | f5(x1); = help: within `S`, the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit = note: required because it appears within the type `S` +help: consider relaxing the implicit `Sized` restriction + | +LL | fn f5(x: &Y) {} + | ^^^^^^^^ error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized3.rs:40:8 @@ -91,6 +95,10 @@ LL | f5(&(32, *x1)); = note: to learn more, visit = note: required because it appears within the type `S` = note: required because it appears within the type `({integer}, S)` +help: consider relaxing the implicit `Sized` restriction + | +LL | fn f5(x: &Y) {} + | ^^^^^^^^ error: aborting due to 6 previous errors diff --git a/src/test/ui/unsized7.stderr b/src/test/ui/unsized7.stderr index d18644f005a88..e616a5cf0f9c2 100644 --- a/src/test/ui/unsized7.stderr +++ b/src/test/ui/unsized7.stderr @@ -11,6 +11,10 @@ LL | impl T1 for S3 { | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit +help: consider relaxing the implicit `Sized` restriction + | +LL | trait T1 { + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/use/use-after-move-self-based-on-type.stderr b/src/test/ui/use/use-after-move-self-based-on-type.stderr index b9440f4de07a9..9bf1175430c84 100644 --- a/src/test/ui/use/use-after-move-self-based-on-type.stderr +++ b/src/test/ui/use/use-after-move-self-based-on-type.stderr @@ -4,15 +4,9 @@ error[E0382]: use of moved value: `self` LL | pub fn foo(self) -> isize { | ---- move occurs because `self` has type `S`, which does not implement the `Copy` trait LL | self.bar(); - | ----- `self` moved due to this method call + | ---- value moved here LL | return self.x; | ^^^^^^ value used here after move - | -note: this function consumes the receiver `self` by taking ownership of it, which moves `self` - --> $DIR/use-after-move-self-based-on-type.rs:15:16 - | -LL | pub fn bar(self) {} - | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/use/use-after-move-self.stderr b/src/test/ui/use/use-after-move-self.stderr index 3da53b024db44..3be0a65550b7f 100644 --- a/src/test/ui/use/use-after-move-self.stderr +++ b/src/test/ui/use/use-after-move-self.stderr @@ -4,15 +4,9 @@ error[E0382]: use of moved value: `self` LL | pub fn foo(self) -> isize { | ---- move occurs because `self` has type `S`, which does not implement the `Copy` trait LL | self.bar(); - | ----- `self` moved due to this method call + | ---- value moved here LL | return *self.x; | ^^^^^^^ value used here after move - | -note: this function consumes the receiver `self` by taking ownership of it, which moves `self` - --> $DIR/use-after-move-self.rs:13:16 - | -LL | pub fn bar(self) {} - | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/walk-struct-literal-with.stderr b/src/test/ui/walk-struct-literal-with.stderr index ece63a2b81947..eeb594a21f38c 100644 --- a/src/test/ui/walk-struct-literal-with.stderr +++ b/src/test/ui/walk-struct-literal-with.stderr @@ -4,15 +4,9 @@ error[E0382]: borrow of moved value: `start` LL | let start = Mine{test:"Foo".to_string(), other_val:0}; | ----- move occurs because `start` has type `Mine`, which does not implement the `Copy` trait LL | let end = Mine{other_val:1, ..start.make_string_bar()}; - | ----------------- `start` moved due to this method call + | ----- value moved here LL | println!("{}", start.test); | ^^^^^^^^^^ value borrowed here after move - | -note: this function consumes the receiver `self` by taking ownership of it, which moves `start` - --> $DIR/walk-struct-literal-with.rs:7:28 - | -LL | fn make_string_bar(mut self) -> Mine{ - | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-fn-where-clause.stderr b/src/test/ui/wf/wf-fn-where-clause.stderr index 59a4f9bad9dfa..731d31ac34f62 100644 --- a/src/test/ui/wf/wf-fn-where-clause.stderr +++ b/src/test/ui/wf/wf-fn-where-clause.stderr @@ -23,6 +23,13 @@ LL | struct Vec { | = help: the trait `std::marker::Sized` is not implemented for `(dyn std::marker::Copy + 'static)` = note: to learn more, visit +help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` + --> $DIR/wf-fn-where-clause.rs:16:12 + | +LL | struct Vec { + | ^ this could be changed to `T: ?Sized`... +LL | t: T, + | - ...if indirection was used here: `Box` error[E0038]: the trait `std::marker::Copy` cannot be made into an object --> $DIR/wf-fn-where-clause.rs:12:16 diff --git a/src/test/ui/where-clauses/where-for-self-2.nll.stderr b/src/test/ui/where-clauses/where-for-self-2.nll.stderr new file mode 100644 index 0000000000000..d0c476dc6ec05 --- /dev/null +++ b/src/test/ui/where-clauses/where-for-self-2.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/where-for-self-2.rs:23:5 + | +LL | foo(&X); + | ^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/where-clauses/where-for-self-2.rs b/src/test/ui/where-clauses/where-for-self-2.rs index 31174fd4cf163..37c6954fd52ee 100644 --- a/src/test/ui/where-clauses/where-for-self-2.rs +++ b/src/test/ui/where-clauses/where-for-self-2.rs @@ -14,9 +14,11 @@ impl Bar for &'static u32 { } fn foo(x: &T) - where for<'a> &'a T: Bar -{} +where + for<'a> &'a T: Bar, +{ +} fn main() { - foo(&X); //~ ERROR trait bound + foo(&X); //~ ERROR implementation of `Bar` is not general enough } diff --git a/src/test/ui/where-clauses/where-for-self-2.stderr b/src/test/ui/where-clauses/where-for-self-2.stderr index 9976243b200dc..30eb78b2da4f7 100644 --- a/src/test/ui/where-clauses/where-for-self-2.stderr +++ b/src/test/ui/where-clauses/where-for-self-2.stderr @@ -1,17 +1,16 @@ -error[E0277]: the trait bound `for<'a> &'a _: Bar` is not satisfied - --> $DIR/where-for-self-2.rs:21:5 +error: implementation of `Bar` is not general enough + --> $DIR/where-for-self-2.rs:23:5 | -LL | fn foo(x: &T) - | --- required by a bound in this -LL | where for<'a> &'a T: Bar - | --- required by this bound in `foo` +LL | / trait Bar { +LL | | fn bar(&self); +LL | | } + | |_- trait `Bar` defined here ... -LL | foo(&X); - | ^^^ the trait `for<'a> Bar` is not implemented for `&'a _` +LL | foo(&X); + | ^^^ implementation of `Bar` is not general enough | - = help: the following implementations were found: - <&'static u32 as Bar> + = note: `Bar` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... + = note: ...but `Bar` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/where-clauses/where-lifetime-resolution.rs b/src/test/ui/where-clauses/where-lifetime-resolution.rs index 0d426386768c8..d8677ee959abd 100644 --- a/src/test/ui/where-clauses/where-lifetime-resolution.rs +++ b/src/test/ui/where-clauses/where-lifetime-resolution.rs @@ -7,7 +7,6 @@ fn f() where //~^ ERROR use of undeclared lifetime name `'a` for<'a> dyn for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>, //~^ ERROR use of undeclared lifetime name `'b` - //~| ERROR nested quantification of lifetimes {} fn main() {} diff --git a/src/test/ui/where-clauses/where-lifetime-resolution.stderr b/src/test/ui/where-clauses/where-lifetime-resolution.stderr index 49799a93017eb..6c52664154bbf 100644 --- a/src/test/ui/where-clauses/where-lifetime-resolution.stderr +++ b/src/test/ui/where-clauses/where-lifetime-resolution.stderr @@ -7,12 +7,6 @@ LL | for<'a> dyn Trait1<'a>: Trait1<'a>, // OK LL | (dyn for<'a> Trait1<'a>): Trait1<'a>, | ^^ undeclared lifetime -error[E0316]: nested quantification of lifetimes - --> $DIR/where-lifetime-resolution.rs:8:17 - | -LL | for<'a> dyn for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>, - | ^^^^^^^^^^^^^^^^^^^^^^ - error[E0261]: use of undeclared lifetime name `'b` --> $DIR/where-lifetime-resolution.rs:8:52 | @@ -22,6 +16,6 @@ LL | fn f() where LL | for<'a> dyn for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>, | ^^ undeclared lifetime -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0261`. diff --git a/src/tools/cargo b/src/tools/cargo index 79c769c3d7b4c..089cbb80b73ba 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 79c769c3d7b4c2cf6a93781575b7f592ef974255 +Subproject commit 089cbb80b73ba242efdcf5430e89f63fa3b5328d diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs index 7227683aa5ac2..59af475af175e 100644 --- a/src/tools/clippy/clippy_lints/src/escape.rs +++ b/src/tools/clippy/clippy_lints/src/escape.rs @@ -6,7 +6,7 @@ use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; use rustc_target::abi::LayoutOf; -use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Place, PlaceBase}; +use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, PlaceWithHirId, PlaceBase}; use crate::utils::span_lint; @@ -112,9 +112,9 @@ fn is_argument(map: rustc_middle::hir::map::Map<'_>, id: HirId) -> bool { } impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { - fn consume(&mut self, cmt: &Place<'tcx>, mode: ConsumeMode) { - if cmt.projections.is_empty() { - if let PlaceBase::Local(lid) = cmt.base { + fn consume(&mut self, cmt: &PlaceWithHirId<'tcx>, mode: ConsumeMode) { + if cmt.place.projections.is_empty() { + if let PlaceBase::Local(lid) = cmt.place.base { if let ConsumeMode::Move = mode { // moved out or in. clearly can't be localized self.set.remove(&lid); @@ -132,16 +132,16 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { } } - fn borrow(&mut self, cmt: &Place<'tcx>, _: ty::BorrowKind) { - if cmt.projections.is_empty() { - if let PlaceBase::Local(lid) = cmt.base { + fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: ty::BorrowKind) { + if cmt.place.projections.is_empty() { + if let PlaceBase::Local(lid) = cmt.place.base { self.set.remove(&lid); } } } - fn mutate(&mut self, cmt: &Place<'tcx>) { - if cmt.projections.is_empty() { + fn mutate(&mut self, cmt: &PlaceWithHirId<'tcx>) { + if cmt.place.projections.is_empty() { let map = &self.cx.tcx.hir(); if is_argument(*map, cmt.hir_id) { // Skip closure arguments @@ -150,7 +150,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { return; } - if is_non_trait_box(cmt.ty) && !self.is_large_box(cmt.ty) { + if is_non_trait_box(cmt.place.ty) && !self.is_large_box(cmt.place.ty) { self.set.insert(cmt.hir_id); } return; diff --git a/src/tools/clippy/clippy_lints/src/functions.rs b/src/tools/clippy/clippy_lints/src/functions.rs index 991d129e8f0d6..1f9bd7a691b52 100644 --- a/src/tools/clippy/clippy_lints/src/functions.rs +++ b/src/tools/clippy/clippy_lints/src/functions.rs @@ -513,7 +513,7 @@ fn is_mutable_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>, span: Span, // primitive types are never mutable ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false, ty::Adt(ref adt, ref substs) => { - tys.insert(adt.did) && !ty.is_freeze(cx.tcx, cx.param_env, span) + tys.insert(adt.did) && !ty.is_freeze(cx.tcx.at(span), cx.param_env) || KNOWN_WRAPPER_TYS.iter().any(|path| match_def_path(cx, adt.did, path)) && substs.types().any(|ty| is_mutable_ty(cx, ty, span, tys)) }, diff --git a/src/tools/clippy/clippy_lints/src/let_if_seq.rs b/src/tools/clippy/clippy_lints/src/let_if_seq.rs index d7bf8a1476817..e097f40f87e47 100644 --- a/src/tools/clippy/clippy_lints/src/let_if_seq.rs +++ b/src/tools/clippy/clippy_lints/src/let_if_seq.rs @@ -74,9 +74,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { let span = stmt.span.to(if_.span); let has_interior_mutability = !cx.tables.node_type(canonical_id).is_freeze( - cx.tcx, + cx.tcx.at(span), cx.param_env, - span ); if has_interior_mutability { return; } diff --git a/src/tools/clippy/clippy_lints/src/loops.rs b/src/tools/clippy/clippy_lints/src/loops.rs index 771bc8d055825..83093ec51bd90 100644 --- a/src/tools/clippy/clippy_lints/src/loops.rs +++ b/src/tools/clippy/clippy_lints/src/loops.rs @@ -28,7 +28,7 @@ use rustc_middle::ty::{self, Ty, TyS}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use rustc_span::symbol::Symbol; -use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Place, PlaceBase}; +use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, PlaceWithHirId, PlaceBase}; use std::iter::{once, Iterator}; use std::mem; @@ -1489,42 +1489,43 @@ fn check_for_loop_over_map_kv<'a, 'tcx>( } } -struct MutatePairDelegate { +struct MutatePairDelegate<'a, 'tcx> { + cx: &'a LateContext<'a, 'tcx>, hir_id_low: Option, hir_id_high: Option, span_low: Option, span_high: Option, } -impl<'tcx> Delegate<'tcx> for MutatePairDelegate { - fn consume(&mut self, _: &Place<'tcx>, _: ConsumeMode) {} +impl<'a, 'tcx> Delegate<'tcx> for MutatePairDelegate<'a, 'tcx> { + fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: ConsumeMode) {} - fn borrow(&mut self, cmt: &Place<'tcx>, bk: ty::BorrowKind) { + fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, bk: ty::BorrowKind) { if let ty::BorrowKind::MutBorrow = bk { - if let PlaceBase::Local(id) = cmt.base { + if let PlaceBase::Local(id) = cmt.place.base { if Some(id) == self.hir_id_low { - self.span_low = Some(cmt.span) + self.span_low = Some(self.cx.tcx.hir().span(cmt.hir_id)) } if Some(id) == self.hir_id_high { - self.span_high = Some(cmt.span) + self.span_high = Some(self.cx.tcx.hir().span(cmt.hir_id)) } } } } - fn mutate(&mut self, cmt: &Place<'tcx>) { - if let PlaceBase::Local(id) = cmt.base { + fn mutate(&mut self, cmt: &PlaceWithHirId<'tcx>) { + if let PlaceBase::Local(id) = cmt.place.base { if Some(id) == self.hir_id_low { - self.span_low = Some(cmt.span) + self.span_low = Some(self.cx.tcx.hir().span(cmt.hir_id)) } if Some(id) == self.hir_id_high { - self.span_high = Some(cmt.span) + self.span_high = Some(self.cx.tcx.hir().span(cmt.hir_id)) } } } } -impl<'tcx> MutatePairDelegate { +impl<'a, 'tcx> MutatePairDelegate<'a, 'tcx> { fn mutation_span(&self) -> (Option, Option) { (self.span_low, self.span_high) } @@ -1579,12 +1580,13 @@ fn check_for_mutability(cx: &LateContext<'_, '_>, bound: &Expr<'_>) -> Option, +fn check_for_mutation<'a, 'tcx> ( + cx: &LateContext<'a, 'tcx>, body: &Expr<'_>, bound_ids: &[Option], ) -> (Option, Option) { let mut delegate = MutatePairDelegate { + cx: cx, hir_id_low: bound_ids[0], hir_id_high: bound_ids[1], span_low: None, diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs index 0b9b7e1b8cc1b..93569a04f7a3a 100644 --- a/src/tools/clippy/clippy_lints/src/mut_key.rs +++ b/src/tools/clippy/clippy_lints/src/mut_key.rs @@ -118,7 +118,7 @@ fn is_mutable_type<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>, span: Spa size.try_eval_usize(cx.tcx, cx.param_env).map_or(true, |u| u != 0) && is_mutable_type(cx, inner_ty, span) }, Tuple(..) => ty.tuple_fields().any(|ty| is_mutable_type(cx, ty, span)), - Adt(..) => cx.tcx.layout_of(cx.param_env.and(ty)).is_ok() && !ty.is_freeze(cx.tcx, cx.param_env, span), + Adt(..) => cx.tcx.layout_of(cx.param_env.and(ty)).is_ok() && !ty.is_freeze(cx.tcx.at(span), cx.param_env), _ => false, } } diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index 218b0d27f7486..ca87deac9891c 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -326,21 +326,21 @@ struct MovedVariablesCtxt { } impl MovedVariablesCtxt { - fn move_common(&mut self, cmt: &euv::Place<'_>) { - if let euv::PlaceBase::Local(vid) = cmt.base { + fn move_common(&mut self, cmt: &euv::PlaceWithHirId<'_>) { + if let euv::PlaceBase::Local(vid) = cmt.place.base { self.moved_vars.insert(vid); } } } impl<'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt { - fn consume(&mut self, cmt: &euv::Place<'tcx>, mode: euv::ConsumeMode) { + fn consume(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, mode: euv::ConsumeMode) { if let euv::ConsumeMode::Move = mode { self.move_common(cmt); } } - fn borrow(&mut self, _: &euv::Place<'tcx>, _: ty::BorrowKind) {} + fn borrow(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: ty::BorrowKind) {} - fn mutate(&mut self, _: &euv::Place<'tcx>) {} + fn mutate(&mut self, _: &euv::PlaceWithHirId<'tcx>) {} } diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index bb257e5a542d9..230dfd2ebf566 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -110,7 +110,7 @@ impl Source { } fn verify_ty_bound<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>, source: Source) { - if ty.is_freeze(cx.tcx, cx.param_env, DUMMY_SP) || is_copy(cx, ty) { + if ty.is_freeze(cx.tcx.at(DUMMY_SP), cx.param_env) || is_copy(cx, ty) { // An `UnsafeCell` is `!Copy`, and an `UnsafeCell` is also the only type which // is `!Freeze`, thus if our type is `Copy` we can be sure it must be `Freeze` // as well. diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index 3591972fe082f..d8a73f8054bca 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -137,7 +137,7 @@ impl QuestionMark { fn moves_by_default(cx: &LateContext<'_, '_>, expression: &Expr<'_>) -> bool { let expr_ty = cx.tables.expr_ty(expression); - !expr_ty.is_copy_modulo_regions(cx.tcx, cx.param_env, expression.span) + !expr_ty.is_copy_modulo_regions(cx.tcx.at(expression.span), cx.param_env) } fn is_option(cx: &LateContext<'_, '_>, expression: &Expr<'_>) -> bool { diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs index 60ab19e71f5e4..6d4c6c6ce1cea 100644 --- a/src/tools/clippy/clippy_lints/src/utils/mod.rs +++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs @@ -891,7 +891,7 @@ pub fn type_is_unsafe_function<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx } pub fn is_copy<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { - ty.is_copy_modulo_regions(cx.tcx, cx.param_env, DUMMY_SP) + ty.is_copy_modulo_regions(cx.tcx.at(DUMMY_SP), cx.param_env) } /// Checks if an expression is constructing a tuple-like enum variant or struct diff --git a/src/tools/clippy/clippy_lints/src/utils/usage.rs b/src/tools/clippy/clippy_lints/src/utils/usage.rs index 904d948ad29ed..6a7a1f1ceaaef 100644 --- a/src/tools/clippy/clippy_lints/src/utils/usage.rs +++ b/src/tools/clippy/clippy_lints/src/utils/usage.rs @@ -8,7 +8,7 @@ use rustc_lint::LateContext; use rustc_middle::hir::map::Map; use rustc_middle::ty; use rustc_span::symbol::{Ident, Symbol}; -use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Place, PlaceBase}; +use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, PlaceWithHirId, PlaceBase}; /// Returns a set of mutated local variable IDs, or `None` if mutations could not be determined. pub fn mutated_variables<'a, 'tcx>(expr: &'tcx Expr<'_>, cx: &'a LateContext<'a, 'tcx>) -> Option> { @@ -46,8 +46,8 @@ struct MutVarsDelegate { impl<'tcx> MutVarsDelegate { #[allow(clippy::similar_names)] - fn update(&mut self, cat: &Place<'tcx>) { - match cat.base { + fn update(&mut self, cat: &PlaceWithHirId<'tcx>) { + match cat.place.base { PlaceBase::Local(id) => { self.used_mutably.insert(id); }, @@ -63,15 +63,15 @@ impl<'tcx> MutVarsDelegate { } impl<'tcx> Delegate<'tcx> for MutVarsDelegate { - fn consume(&mut self, _: &Place<'tcx>, _: ConsumeMode) {} + fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: ConsumeMode) {} - fn borrow(&mut self, cmt: &Place<'tcx>, bk: ty::BorrowKind) { + fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, bk: ty::BorrowKind) { if let ty::BorrowKind::MutBorrow = bk { self.update(&cmt) } } - fn mutate(&mut self, cmt: &Place<'tcx>) { + fn mutate(&mut self, cmt: &PlaceWithHirId<'tcx>) { self.update(&cmt) } } diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs index f28aedbf0ab8b..368fa6a98c5d6 100644 --- a/src/tools/clippy/tests/compile-test.rs +++ b/src/tools/clippy/tests/compile-test.rs @@ -49,7 +49,9 @@ fn third_party_crates() -> String { if let Some(name) = path.file_name().and_then(OsStr::to_str) { for dep in CRATES { if name.starts_with(&format!("lib{}-", dep)) && name.ends_with(".rlib") { - crates.entry(dep).or_insert(path); + if let Some(old) = crates.insert(dep, path.clone()) { + panic!("Found multiple rlibs for crate `{}`: `{:?}` and `{:?}", dep, old, path); + } break; } } diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 64c0298c1fa4e..703b87634cec3 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -123,6 +123,7 @@ pub enum FailMode { pub enum CompareMode { Nll, Polonius, + Chalk, } impl CompareMode { @@ -130,6 +131,7 @@ impl CompareMode { match *self { CompareMode::Nll => "nll", CompareMode::Polonius => "polonius", + CompareMode::Chalk => "chalk", } } @@ -137,6 +139,7 @@ impl CompareMode { match s.as_str() { "nll" => CompareMode::Nll, "polonius" => CompareMode::Polonius, + "chalk" => CompareMode::Chalk, x => panic!("unknown --compare-mode option: {}", x), } } diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 9614707433e13..7d2c83881d13b 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -875,6 +875,7 @@ impl Config { match self.compare_mode { Some(CompareMode::Nll) => name == "compare-mode-nll", Some(CompareMode::Polonius) => name == "compare-mode-polonius", + Some(CompareMode::Chalk) => name == "compare-mode-chalk", None => false, } || (cfg!(debug_assertions) && name == "debug") || diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 93c53e779d50e..c00b0f02c3a90 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -1,5 +1,4 @@ #![crate_name = "compiletest"] -#![feature(vec_remove_item)] #![deny(warnings)] // The `test` crate is the only unstable feature // allowed here, just to share similar code. diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 18f00db3d8e12..95ea4fb078955 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1985,6 +1985,9 @@ impl<'test> TestCx<'test> { Some(CompareMode::Polonius) => { rustc.args(&["-Zpolonius", "-Zborrowck=mir"]); } + Some(CompareMode::Chalk) => { + rustc.args(&["-Zchalk"]); + } None => {} } diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 0d56bf2d20fcb..0437ff8c9440a 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -82,16 +82,22 @@ const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[ ("xcore", "xcore"), ]; -pub const ASAN_SUPPORTED_TARGETS: &'static [&'static str] = - &["aarch64-fuchsia", "x86_64-apple-darwin", "x86_64-fuchsia", "x86_64-unknown-linux-gnu"]; +pub const ASAN_SUPPORTED_TARGETS: &'static [&'static str] = &[ + "aarch64-fuchsia", + "aarch64-unknown-linux-gnu", + "x86_64-apple-darwin", + "x86_64-fuchsia", + "x86_64-unknown-linux-gnu", +]; pub const LSAN_SUPPORTED_TARGETS: &'static [&'static str] = - &["x86_64-apple-darwin", "x86_64-unknown-linux-gnu"]; + &["aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"]; -pub const MSAN_SUPPORTED_TARGETS: &'static [&'static str] = &["x86_64-unknown-linux-gnu"]; +pub const MSAN_SUPPORTED_TARGETS: &'static [&'static str] = + &["aarch64-unknown-linux-gnu", "x86_64-unknown-linux-gnu"]; pub const TSAN_SUPPORTED_TARGETS: &'static [&'static str] = - &["x86_64-apple-darwin", "x86_64-unknown-linux-gnu"]; + &["aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"]; pub fn matches_os(triple: &str, name: &str) -> bool { // For the wasm32 bare target we ignore anything also ignored on emscripten diff --git a/src/tools/miri b/src/tools/miri index faff9a7ad9f2d..59619775ee44a 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit faff9a7ad9f2d07c1702bd8be392134d27e3eaf8 +Subproject commit 59619775ee44a5e0c875efffc4ca55ae96fca7dc diff --git a/src/tools/remote-test-client/src/main.rs b/src/tools/remote-test-client/src/main.rs index efc29163455be..1fafe109d34e1 100644 --- a/src/tools/remote-test-client/src/main.rs +++ b/src/tools/remote-test-client/src/main.rs @@ -107,13 +107,23 @@ fn start_android_emulator(server: &Path) { Command::new("adb").arg("shell").arg("/data/tmp/testd").spawn().unwrap(); } -fn start_qemu_emulator(target: &str, rootfs: &Path, server: &Path, tmpdir: &Path) { +fn prepare_rootfs(target: &str, rootfs: &Path, server: &Path, rootfs_img: &Path) { + t!(fs::copy(server, rootfs.join("testd"))); + + match target { + "arm-unknown-linux-gnueabihf" | "aarch64-unknown-linux-gnu" => { + prepare_rootfs_cpio(rootfs, rootfs_img) + } + "riscv64gc-unknown-linux-gnu" => prepare_rootfs_ext4(rootfs, rootfs_img), + _ => panic!("{} is not supported", target), + } +} + +fn prepare_rootfs_cpio(rootfs: &Path, rootfs_img: &Path) { // Generate a new rootfs image now that we've updated the test server // executable. This is the equivalent of: // // find $rootfs -print 0 | cpio --null -o --format=newc > rootfs.img - t!(fs::copy(server, rootfs.join("testd"))); - let rootfs_img = tmpdir.join("rootfs.img"); let mut cmd = Command::new("cpio"); cmd.arg("--null") .arg("-o") @@ -128,6 +138,38 @@ fn start_qemu_emulator(target: &str, rootfs: &Path, server: &Path, tmpdir: &Path t!(io::copy(&mut child.stdout.take().unwrap(), &mut t!(File::create(&rootfs_img)))); assert!(t!(child.wait()).success()); + fn add_files(w: &mut dyn Write, root: &Path, cur: &Path) { + for entry in t!(cur.read_dir()) { + let entry = t!(entry); + let path = entry.path(); + let to_print = path.strip_prefix(root).unwrap(); + t!(write!(w, "{}\u{0}", to_print.to_str().unwrap())); + if t!(entry.file_type()).is_dir() { + add_files(w, root, &path); + } + } + } +} + +fn prepare_rootfs_ext4(rootfs: &Path, rootfs_img: &Path) { + let mut dd = Command::new("dd"); + dd.arg("if=/dev/zero") + .arg(&format!("of={}", rootfs_img.to_string_lossy())) + .arg("bs=1M") + .arg("count=1024"); + let mut dd_child = t!(dd.spawn()); + assert!(t!(dd_child.wait()).success()); + + let mut mkfs = Command::new("mkfs.ext4"); + mkfs.arg("-d").arg(rootfs).arg(rootfs_img); + let mut mkfs_child = t!(mkfs.spawn()); + assert!(t!(mkfs_child.wait()).success()); +} + +fn start_qemu_emulator(target: &str, rootfs: &Path, server: &Path, tmpdir: &Path) { + let rootfs_img = &tmpdir.join("rootfs.img"); + prepare_rootfs(target, rootfs, server, rootfs_img); + // Start up the emulator, in the background match target { "arm-unknown-linux-gnueabihf" => { @@ -170,19 +212,30 @@ fn start_qemu_emulator(target: &str, rootfs: &Path, server: &Path, tmpdir: &Path .arg("virtio-net-device,netdev=net0,mac=00:00:00:00:00:00"); t!(cmd.spawn()); } - _ => panic!("cannot start emulator for: {}" < target), - } - - fn add_files(w: &mut dyn Write, root: &Path, cur: &Path) { - for entry in t!(cur.read_dir()) { - let entry = t!(entry); - let path = entry.path(); - let to_print = path.strip_prefix(root).unwrap(); - t!(write!(w, "{}\u{0}", to_print.to_str().unwrap())); - if t!(entry.file_type()).is_dir() { - add_files(w, root, &path); - } + "riscv64gc-unknown-linux-gnu" => { + let mut cmd = Command::new("qemu-system-riscv64"); + cmd.arg("-nographic") + .arg("-machine") + .arg("virt") + .arg("-m") + .arg("1024") + .arg("-bios") + .arg("none") + .arg("-kernel") + .arg("/tmp/bbl") + .arg("-append") + .arg("quiet console=ttyS0 root=/dev/vda rw") + .arg("-netdev") + .arg("user,id=net0,hostfwd=tcp::12345-:12345") + .arg("-device") + .arg("virtio-net-device,netdev=net0,mac=00:00:00:00:00:00") + .arg("-device") + .arg("virtio-blk-device,drive=hd0") + .arg("-drive") + .arg(&format!("file={},format=raw,id=hd0", &rootfs_img.to_string_lossy())); + t!(cmd.spawn()); } + _ => panic!("cannot start emulator for: {}", target), } } diff --git a/src/tools/rls b/src/tools/rls index 8d7a7167c15b9..fb46b914c11b0 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit 8d7a7167c15b9154755588c39b22b2336c89ca68 +Subproject commit fb46b914c11b06828680cb526e2abe9e1d69b868 diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml index 1b1f444796654..351e2d4481c0f 100644 --- a/src/tools/rustc-workspace-hack/Cargo.toml +++ b/src/tools/rustc-workspace-hack/Cargo.toml @@ -69,8 +69,7 @@ serde = { version = "1.0.82", features = ['derive'] } serde_json = { version = "1.0.31", features = ["raw_value"] } smallvec-0_6 = { package = "smallvec", version = "0.6", features = ['union', 'may_dangle'] } smallvec = { version = "1.0", features = ['union', 'may_dangle'] } -syn = { version = "0.15", features = ['full', 'extra-traits'] } -syn-1 = { package = "syn", version = "1", features = ['fold', 'full', 'extra-traits', 'visit'] } +syn = { version = "1", features = ['fold', 'full', 'extra-traits', 'visit'] } url = { version = "2.0", features = ['serde'] } [target.'cfg(not(windows))'.dependencies] diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index 163571bc5b988..139e6f73f4216 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -269,6 +269,12 @@ function runSearch(query, expected, index, loaded, loadedFile, queryName) { break; } var entry = expected[key]; + + if (exact_check == true && entry.length !== results[key].length) { + error_text.push(queryName + "==> Expected exactly " + entry.length + + " results but found " + results[key].length + " in '" + key + "'"); + } + var prev_pos = -1; for (var i = 0; i < entry.length; ++i) { var entry_pos = lookForEntry(entry[i], results[key]); @@ -307,8 +313,11 @@ function checkResult(error_text, loadedFile, displaySuccess) { } function runChecks(testFile, loaded, index) { - var loadedFile = loadContent( - readFile(testFile) + 'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;'); + var testFileContent = readFile(testFile) + 'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;'; + if (testFileContent.indexOf("FILTER_CRATE") !== -1) { + testFileContent += "exports.FILTER_CRATE = FILTER_CRATE;"; + } + var loadedFile = loadContent(testFileContent); const expected = loadedFile.EXPECTED; const query = loadedFile.QUERY; diff --git a/src/tools/rustfmt b/src/tools/rustfmt index aedff61f7ac4f..c1e9b7b87493c 160000 --- a/src/tools/rustfmt +++ b/src/tools/rustfmt @@ -1 +1 @@ -Subproject commit aedff61f7ac4fc2b287ff76d33f2584e1f63a3af +Subproject commit c1e9b7b87493c5197c4330693bdf4ccb30a90971 diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index c08f02b972e8f..093db2a49d029 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -80,9 +80,7 @@ const WHITELIST: &[&str] = &[ "cc", "cfg-if", "chalk-derive", - "chalk-engine", "chalk-ir", - "chalk-macros", "cloudabi", "cmake", "compiler_builtins", diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index d9320e9147cff..3fa637b5a696f 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -444,10 +444,7 @@ fn map_lib_features( level: Status::Unstable, since: None, has_gate_test: false, - // FIXME(#57563): #57563 is now used as a common tracking issue, - // although we would like to have specific tracking issues for each - // `rustc_const_unstable` in the future. - tracking_issue: NonZeroU32::new(57563), + tracking_issue: find_attr_val(line, "issue").and_then(handle_issue_none), }; mf(Ok((feature_name, feature)), file, i + 1); continue; diff --git a/triagebot.toml b/triagebot.toml index fc2dbb8d4402d..5361a618d4e85 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -113,7 +113,7 @@ topic = "P-critical #{number} {title}" message_on_add = "@*WG-prioritization* issue #{number} has been assigned `P-critical`." [notify-zulip."P-high"] -required_labels = ["regression-from-stable-to-*"] +required_labels = ["regression-from-stable-to-[bn]*"] # only nightly and beta regressions zulip_stream = 227806 # #t-compiler/wg-prioritization topic = "P-high regression #{number} {title}" message_on_add = "@*WG-prioritization* issue #{number} has been assigned `P-high` and is a regression."