diff options
1177 files changed, 12586 insertions, 8180 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3651ef2c614..a2769a2c274 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,46 +1,53 @@ -############################################################# -# WARNING: automatically generated file, DO NOT CHANGE! # -############################################################# - -# This file was automatically generated by the expand-yaml-anchors tool. The -# source file that generated this one is: -# -# src/ci/github-actions/ci.yml -# -# Once you make changes to that file you need to run: -# -# ./x.py run src/tools/expand-yaml-anchors/ +# This file defines our primary CI workflow that runs on pull requests +# and also on pushes to special branches (auto, try). # -# The CI build will fail if the tool is not run after changes to this file. +# The actual definition of the executed jobs is calculated by a Python +# script located at src/ci/github-actions/calculate-job-matrix.py, which +# uses job definition data from src/ci/github-actions/jobs.yml. +# You should primarily modify the `jobs.yml` file if you want to modify +# what jobs are executed in CI. ---- name: CI -"on": +on: push: branches: - auto - try - try-perf - automation/bors/try - - master pull_request: branches: - "**" + permissions: contents: read packages: write + defaults: run: + # On Linux, macOS, and Windows, use the system-provided bash as the default + # shell. (This should only make a difference on Windows, where the default + # shell is PowerShell.) shell: bash + concurrency: - group: "${{ github.workflow }}-${{ ((github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.sha) || github.ref }}" + # For a given workflow, if we push to the same branch, cancel all previous builds on that branch. + # We add an exception for try builds (try branch) and unrolled rollup builds (try-perf), which + # are all triggered on the same branch, but which should be able to run concurrently. + group: ${{ github.workflow }}-${{ ((github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.sha) || github.ref }} cancel-in-progress: true +env: + TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate" jobs: + # The job matrix for `calculate_matrix` is defined in src/ci/github-actions/jobs.yml. + # It calculates which jobs should be executed, based on the data of the ${{ github }} context. + # If you want to modify CI jobs, take a look at src/ci/github-actions/jobs.yml. calculate_matrix: name: Calculate job matrix runs-on: ubuntu-latest outputs: - jobs: "${{ steps.jobs.outputs.jobs }}" + jobs: ${{ steps.jobs.outputs.jobs }} + run_type: ${{ steps.jobs.outputs.run_type }} steps: - name: Checkout the source code uses: actions/checkout@v4 @@ -48,171 +55,195 @@ jobs: run: python3 src/ci/github-actions/calculate-job-matrix.py >> $GITHUB_OUTPUT id: jobs job: - name: "${{ matrix.name }}" - needs: - - calculate_matrix + name: ${{ matrix.name }} + needs: [ calculate_matrix ] + runs-on: "${{ matrix.os }}" + defaults: + run: + shell: ${{ contains(matrix.os, 'windows') && 'msys2 {0}' || 'bash' }} + timeout-minutes: 600 env: - CI_JOB_NAME: "${{ matrix.image }}" + CI_JOB_NAME: ${{ matrix.image }} CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse - HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}" - DOCKER_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + # commit of PR sha or commit sha. `GITHUB_SHA` is not accurate for PRs. + HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }} + DOCKER_TOKEN: ${{ secrets.GITHUB_TOKEN }} SCCACHE_BUCKET: rust-lang-ci-sccache2 - TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate" CACHE_DOMAIN: ci-caches.rust-lang.org - continue-on-error: "${{ matrix.continue_on_error || false }}" + continue-on-error: ${{ matrix.continue_on_error || false }} strategy: matrix: - include: "${{ fromJSON(needs.calculate_matrix.outputs.jobs) }}" - if: "fromJSON(needs.calculate_matrix.outputs.jobs)[0] != null" - defaults: - run: - shell: "${{ contains(matrix.os, 'windows') && 'msys2 {0}' || 'bash' }}" - timeout-minutes: 600 - runs-on: "${{ matrix.os }}" + # Check the `calculate_matrix` job to see how is the matrix defined. + include: ${{ fromJSON(needs.calculate_matrix.outputs.jobs) }} + # GitHub Actions fails the workflow if an empty list of jobs is provided to + # the workflow, so we need to skip this job if nothing was produced by + # the Python script. + # + # Unfortunately checking whether a list is empty is not possible in a nice + # way due to GitHub Actions expressions limits. + # This hack is taken from https://github.com/ferrocene/ferrocene/blob/d43edc6b7697cf1719ec1c17c54904ab94825763/.github/workflows/release.yml#L75-L82 + if: fromJSON(needs.calculate_matrix.outputs.jobs)[0] != null steps: - - if: "contains(matrix.os, 'windows')" + - if: contains(matrix.os, 'windows') uses: msys2/setup-msys2@v2.22.0 with: - msystem: "${{ contains(matrix.name, 'i686') && 'mingw32' || 'mingw64' }}" + # i686 jobs use mingw32. x86_64 and cross-compile jobs use mingw64. + msystem: ${{ contains(matrix.name, 'i686') && 'mingw32' || 'mingw64' }} + # don't try to download updates for already installed packages update: false + # don't try to use the msys that comes built-in to the github runner, + # so we can control what is installed (i.e. not python) release: true + # Inherit the full path from the Windows environment, with MSYS2's */bin/ + # dirs placed in front. This lets us run Windows-native Python etc. path-type: inherit - install: "make dos2unix diffutils\n" + install: > + make + dos2unix + diffutils + - name: disable git crlf conversion run: git config --global core.autocrlf false + - name: checkout the source code uses: actions/checkout@v4 with: fetch-depth: 2 + + # Rust Log Analyzer can't currently detect the PR number of a GitHub + # Actions build on its own, so a hint in the log message is needed to + # point it in the right direction. - name: configure the PR in which the error message will be posted - run: "echo \"[CI_PR_NUMBER=$num]\"" + run: echo "[CI_PR_NUMBER=$num]" env: - num: "${{ github.event.number }}" - if: "success() && github.event_name == 'pull_request'" + num: ${{ github.event.number }} + if: needs.calculate_matrix.outputs.run_type == 'pr' + - name: add extra environment variables run: src/ci/scripts/setup-environment.sh env: - EXTRA_VARIABLES: "${{ toJson(matrix.env) }}" + # Since it's not possible to merge `${{ matrix.env }}` with the other + # variables in `job.<name>.env`, the variables defined in the matrix + # are passed to the `setup-environment.sh` script encoded in JSON, + # which then uses log commands to actually set them. + EXTRA_VARIABLES: ${{ toJson(matrix.env) }} + - name: ensure the channel matches the target branch run: src/ci/scripts/verify-channel.sh + - name: collect CPU statistics run: src/ci/scripts/collect-cpu-stats.sh + - name: show the current environment run: src/ci/scripts/dump-environment.sh + - name: install awscli run: src/ci/scripts/install-awscli.sh + - name: install sccache run: src/ci/scripts/install-sccache.sh + - name: select Xcode run: src/ci/scripts/select-xcode.sh + - name: install clang run: src/ci/scripts/install-clang.sh + - name: install tidy run: src/ci/scripts/install-tidy.sh + - name: install WIX run: src/ci/scripts/install-wix.sh + - name: disable git crlf conversion run: src/ci/scripts/disable-git-crlf-conversion.sh + - name: checkout submodules run: src/ci/scripts/checkout-submodules.sh + - name: install MSYS2 run: src/ci/scripts/install-msys2.sh + - name: install MinGW run: src/ci/scripts/install-mingw.sh + - name: install ninja run: src/ci/scripts/install-ninja.sh + - name: enable ipv6 on Docker run: src/ci/scripts/enable-docker-ipv6.sh + + # Disable automatic line ending conversion (again). On Windows, when we're + # installing dependencies, something switches the git configuration directory or + # re-enables autocrlf. We've not tracked down the exact cause -- and there may + # be multiple -- but this should ensure submodules are checked out with the + # appropriate line endings. - name: disable git crlf conversion run: src/ci/scripts/disable-git-crlf-conversion.sh + - name: ensure line endings are correct run: src/ci/scripts/verify-line-endings.sh + - name: ensure backported commits are in upstream branches run: src/ci/scripts/verify-backported-commits.sh + - name: ensure the stable version number is correct run: src/ci/scripts/verify-stable-version-number.sh + - name: run the build + # Redirect stderr to stdout to avoid reordering the two streams in the GHA logs. run: src/ci/scripts/run-build-from-ci.sh 2>&1 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 }}" + 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 }} + - name: create github artifacts run: src/ci/scripts/create-doc-artifacts.sh + - name: upload artifacts to github uses: actions/upload-artifact@v4 with: - name: "${{ env.DOC_ARTIFACT_NAME }}" + # name is set in previous step + name: ${{ env.DOC_ARTIFACT_NAME }} path: obj/artifacts/doc if-no-files-found: ignore retention-days: 5 + - 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() && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')" - master: - name: master + AWS_ACCESS_KEY_ID: ${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }} + # Adding a condition on DEPLOY=1 or DEPLOY_ALT=1 is not needed as all deploy + # builders *should* have the AWS credentials available. Still, explicitly + # adding the condition is helpful as this way CI will not silently skip + # deploying artifacts from a dist builder if the variables are misconfigured, + # erroring about invalid credentials instead. + if: github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1' + + # This job isused to tell bors the final status of the build, as there is no practical way to detect + # when a workflow is successful listening to webhooks only in our current bors implementation (homu). + outcome: + name: bors build finished runs-on: ubuntu-latest - env: - SCCACHE_BUCKET: rust-lang-ci-sccache2 - DEPLOY_BUCKET: rust-lang-ci2 - TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate" - TOOLSTATE_ISSUES_API_URL: "https://api.github.com/repos/rust-lang/rust/issues" - TOOLSTATE_PUBLISH: 1 - CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZI5DHEBFL - ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55 - AWS_REGION: us-west-1 - CACHE_DOMAIN: ci-caches.rust-lang.org - if: "github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'rust-lang-ci/rust'" + needs: [ calculate_matrix, job ] + # !cancelled() executes the job regardless of whether the previous jobs passed or failed + if: ${{ !cancelled() && contains(fromJSON('["auto", "try"]'), needs.calculate_matrix.outputs.run_type) }} steps: - name: checkout the source code uses: actions/checkout@v4 with: fetch-depth: 2 + # Calculate the exit status of the whole CI workflow. + # If all dependent jobs were successful, this exits with 0 (and the outcome job continues successfully). + # If a some dependent job has failed, this exits with 1. + - name: calculate the correct exit status + run: jq --exit-status 'all(.result == "success" or .result == "skipped")' <<< '${{ toJson(needs) }}' + # Publish the toolstate if an auto build succeeds (just before push to master) - name: publish toolstate run: src/ci/publish_toolstate.sh shell: bash + if: needs.calculate_matrix.outputs.run_type == 'auto' env: - TOOLSTATE_REPO_ACCESS_TOKEN: "${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}" - try-success: - needs: - - job - if: "success() && github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'" - steps: - - name: mark the job as a success - run: exit 0 - shell: bash - name: bors build finished - runs-on: ubuntu-latest - try-failure: - needs: - - job - if: "!success() && github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'" - steps: - - name: mark the job as a failure - run: exit 1 - shell: bash - name: bors build finished - runs-on: ubuntu-latest - auto-success: - needs: - - job - if: "success() && github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'" - steps: - - name: mark the job as a success - run: exit 0 - shell: bash - name: bors build finished - runs-on: ubuntu-latest - auto-failure: - needs: - - job - if: "!success() && github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'" - steps: - - name: mark the job as a failure - run: exit 1 - shell: bash - name: bors build finished - runs-on: ubuntu-latest + TOOLSTATE_REPO_ACCESS_TOKEN: ${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }} diff --git a/Cargo.lock b/Cargo.lock index ac6e7974a12..c034cbae991 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -121,6 +121,16 @@ dependencies = [ ] [[package]] +name = "annotate-snippets" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5a59f105fb9635e9eebdc1e29d53e764fa5795b9cf899a638a53e61567ef61" +dependencies = [ + "anstyle", + "unicode-width", +] + +[[package]] name = "ansi_term" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -574,7 +584,7 @@ checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "clippy" -version = "0.1.79" +version = "0.1.80" dependencies = [ "anstream", "clippy_config", @@ -595,13 +605,13 @@ dependencies = [ "termize", "tokio", "toml 0.7.8", - "ui_test 0.22.3", + "ui_test 0.23.0", "walkdir", ] [[package]] name = "clippy_config" -version = "0.1.79" +version = "0.1.80" dependencies = [ "rustc-semver", "serde", @@ -624,7 +634,7 @@ dependencies = [ [[package]] name = "clippy_lints" -version = "0.1.79" +version = "0.1.80" dependencies = [ "arrayvec", "cargo_metadata 0.18.1", @@ -649,7 +659,7 @@ dependencies = [ [[package]] name = "clippy_utils" -version = "0.1.79" +version = "0.1.80" dependencies = [ "arrayvec", "clippy_config", @@ -968,7 +978,7 @@ checksum = "a0afaad2b26fa326569eb264b1363e8ae3357618c43982b3f285f0774ce76b69" [[package]] name = "declare_clippy_lint" -version = "0.1.79" +version = "0.1.80" dependencies = [ "itertools 0.12.1", "quote", @@ -1255,14 +1265,6 @@ dependencies = [ ] [[package]] -name = "expand-yaml-anchors" -version = "0.1.0" -dependencies = [ - "yaml-merge-keys", - "yaml-rust", -] - -[[package]] name = "expect-test" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2113,7 +2115,6 @@ dependencies = [ "fs-err", "getopts", "jsonpath_lib", - "once_cell", "regex", "serde_json", "shlex", @@ -2232,17 +2233,10 @@ name = "linkchecker" version = "0.1.0" dependencies = [ "html5ever", - "once_cell", "regex", ] [[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - -[[package]] name = "lint-docs" version = "0.1.0" dependencies = [ @@ -2491,7 +2485,6 @@ dependencies = [ "directories", "getrandom", "jemalloc-sys", - "lazy_static", "libc", "libffi", "libloading", @@ -3335,6 +3328,7 @@ dependencies = [ name = "run_make_support" version = "0.0.0" dependencies = [ + "gimli", "object 0.34.0", "regex", "similar", @@ -3830,7 +3824,6 @@ dependencies = [ "rustc_session", "rustc_smir", "rustc_span", - "rustc_symbol_mangling", "rustc_target", "rustc_trait_selection", "rustc_ty_utils", @@ -4014,7 +4007,6 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_fluent_macro", - "rustc_graphviz", "rustc_hir", "rustc_hir_analysis", "rustc_hir_pretty", @@ -4474,7 +4466,6 @@ dependencies = [ "rustc_errors", "rustc_fluent_macro", "rustc_hir", - "rustc_hir_analysis", "rustc_macros", "rustc_middle", "rustc_session", @@ -4521,7 +4512,6 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", - "rustc_type_ir", "smallvec", "thin-vec", "tracing", @@ -4791,12 +4781,10 @@ dependencies = [ "arrayvec", "askama", "base64", - "byteorder", "expect-test", "indexmap", "itertools 0.12.1", "minifier", - "once_cell", "regex", "rustdoc-json-types", "serde", @@ -5178,9 +5166,9 @@ dependencies = [ [[package]] name = "spanned" -version = "0.1.6" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad48ded9f0734eca7058107cc170767b8758e41e4088fb0020e7ff7ec6b0d92d" +checksum = "ccdf4f5590b7e6fbd4f2e80d442789079a6fff7c12ef921a9de358b7b353098e" dependencies = [ "bstr", "color-eyre", @@ -5351,7 +5339,6 @@ version = "0.1.0" dependencies = [ "build_helper", "glob", - "once_cell", ] [[package]] @@ -5596,7 +5583,6 @@ version = "0.1.0" dependencies = [ "cargo_metadata 0.15.4", "ignore", - "lazy_static", "miropt-test-tools", "regex", "rustc-hash", @@ -5920,11 +5906,11 @@ dependencies = [ [[package]] name = "ui_test" -version = "0.22.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa577a42db0e211a73c069d7dbcae54bc7473a7c5535a564842cbd8a13c0441e" +checksum = "29e5f4ffcbab82453958fbf59990e981b8e8a177dcd60c2bd8f9b52c3036a6e1" dependencies = [ - "annotate-snippets 0.10.2", + "annotate-snippets 0.11.2", "anyhow", "bstr", "cargo-platform", @@ -5939,7 +5925,7 @@ dependencies = [ "prettydiff", "regex", "rustc_version", - "rustfix 0.6.1", + "rustfix 0.8.1", "serde", "serde_json", "spanned", @@ -6548,26 +6534,6 @@ dependencies = [ ] [[package]] -name = "yaml-merge-keys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd236a7dc9bb598f349fe4a8754f49181fee50284daa15cd1ba652d722280004" -dependencies = [ - "lazy_static", - "thiserror", - "yaml-rust", -] - -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] - -[[package]] name = "yansi-term" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/Cargo.toml b/Cargo.toml index 1379e4cd3bf..a601ebf4369 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,6 @@ members = [ "src/tools/miri/cargo-miri", "src/tools/rustdoc-themes", "src/tools/unicode-table-generator", - "src/tools/expand-yaml-anchors", "src/tools/jsondocck", "src/tools/jsondoclint", "src/tools/llvm-bitcode-linker", diff --git a/RELEASES.md b/RELEASES.md index 104ea497ba4..3080f03c721 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -102,6 +102,10 @@ Compatibility Notes - [Change equality of higher ranked types to not rely on subtyping](https://github.com/rust-lang/rust/pull/118247) - [When called, additionally check bounds on normalized function return type](https://github.com/rust-lang/rust/pull/118882) - [Expand coverage for `arithmetic_overflow` lint](https://github.com/rust-lang/rust/pull/119432/) +- [Fix detection of potential interior mutability in `const` initializers](https://github.com/rust-lang/rust/issues/121250) + This code was accidentally accepted. The fix can break generic code that borrows a value of unknown type, + as there is currently no way to declare "this type has no interior mutability". In the future, stabilizing + the [`Freeze` trait](https://github.com/rust-lang/rust/issues/121675) will allow proper support for such code. <a id="1.78.0-Internal-Changes"></a> diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs index 434b978ae31..7ba58406ef1 100644 --- a/compiler/rustc/src/main.rs +++ b/compiler/rustc/src/main.rs @@ -1,5 +1,3 @@ -#![feature(unix_sigpipe)] - // A note about jemalloc: rustc uses jemalloc when built for CI and // distribution. The obvious way to do this is with the `#[global_allocator]` // mechanism. However, for complicated reasons (see @@ -34,7 +32,6 @@ // https://github.com/rust-lang/rust/commit/b90cfc887c31c3e7a9e6d462e2464db1fe506175#diff-43914724af6e464c1da2171e4a9b6c7e607d5bc1203fa95c0ab85be4122605ef // for an example of how to do so. -#[unix_sigpipe = "sig_dfl"] fn main() { // See the comment at the top of this file for an explanation of this. #[cfg(feature = "jemalloc-sys")] diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 3584eea0f14..a95ef4c460f 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -251,7 +251,7 @@ pub trait LayoutCalculator { // If all the non-ZST fields have the same ABI and union ABI optimizations aren't // disabled, we can use that common ABI for the union as a whole. struct AbiMismatch; - let mut common_non_zst_abi_and_align = if repr.inhibit_union_abi_opt() { + let mut common_non_zst_abi_and_align = if repr.inhibits_union_abi_opt() { // Can't optimize Err(AbiMismatch) } else { diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 7439af7aed3..5e3f64540e4 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -21,6 +21,8 @@ use rustc_macros::{Decodable_Generic, Encodable_Generic}; use std::iter::Step; mod layout; +#[cfg(test)] +mod tests; pub use layout::LayoutCalculator; @@ -155,7 +157,7 @@ impl ReprOptions { } /// Returns `true` if this `#[repr()]` should inhibit union ABI optimisations. - pub fn inhibit_union_abi_opt(&self) -> bool { + pub fn inhibits_union_abi_opt(&self) -> bool { self.c() } } @@ -743,10 +745,20 @@ impl Align { } #[inline] + pub fn bytes_usize(self) -> usize { + self.bytes().try_into().unwrap() + } + + #[inline] pub fn bits(self) -> u64 { self.bytes() * 8 } + #[inline] + pub fn bits_usize(self) -> usize { + self.bits().try_into().unwrap() + } + /// Computes the best alignment possible for the given offset /// (the largest power of two that the offset is a multiple of). /// diff --git a/compiler/rustc_abi/src/tests.rs b/compiler/rustc_abi/src/tests.rs new file mode 100644 index 00000000000..d993012378c --- /dev/null +++ b/compiler/rustc_abi/src/tests.rs @@ -0,0 +1,7 @@ +use super::*; + +#[test] +fn align_constants() { + assert_eq!(Align::ONE, Align::from_bytes(1).unwrap()); + assert_eq!(Align::EIGHT, Align::from_bytes(8).unwrap()); +} diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index af246e31371..fa378e19f71 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -32,7 +32,7 @@ use rustc_data_structures::packed::Pu128; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::Lrc; -use rustc_macros::HashStable_Generic; +use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP}; @@ -1390,7 +1390,7 @@ pub struct StructExpr { // Adding a new variant? Please update `test_expr` in `tests/ui/macros/stringify.rs`. #[derive(Clone, Encodable, Decodable, Debug)] pub enum ExprKind { - /// An array (`[a, b, c, d]`) + /// An array (e.g, `[a, b, c, d]`). Array(ThinVec<P<Expr>>), /// Allow anonymous constants from an inline `const` block ConstBlock(AnonConst), @@ -1401,7 +1401,7 @@ pub enum ExprKind { /// This also represents calling the constructor of /// tuple-like ADTs such as tuple structs and enum variants. Call(P<Expr>, ThinVec<P<Expr>>), - /// A method call (e.g. `x.foo::<Bar, Baz>(a, b, c)`). + /// A method call (e.g., `x.foo::<Bar, Baz>(a, b, c)`). MethodCall(Box<MethodCall>), /// A tuple (e.g., `(a, b, c, d)`). Tup(ThinVec<P<Expr>>), @@ -1413,7 +1413,10 @@ pub enum ExprKind { Lit(token::Lit), /// A cast (e.g., `foo as f64`). Cast(P<Expr>, P<Ty>), - /// A type ascription (e.g., `42: usize`). + /// A type ascription (e.g., `builtin # type_ascribe(42, usize)`). + /// + /// Usually not written directly in user code but + /// indirectly via the macro `type_ascribe!(...)`. Type(P<Expr>, P<Ty>), /// A `let pat = expr` expression that is only semantically allowed in the condition /// of `if` / `while` expressions. (e.g., `if let 0 = x { .. }`). @@ -1488,7 +1491,10 @@ pub enum ExprKind { /// Output of the `asm!()` macro. InlineAsm(P<InlineAsm>), - /// Output of the `offset_of!()` macro. + /// An `offset_of` expression (e.g., `builtin # offset_of(Struct, field)`). + /// + /// Usually not written directly in user code but + /// indirectly via the macro `core::mem::offset_of!(...)`. OffsetOf(P<Ty>, P<[Ident]>), /// A macro invocation; pre-expansion. @@ -3126,6 +3132,35 @@ pub struct StaticItem { pub expr: Option<P<Expr>>, } +/// A static item in `extern` block. +// This struct is identical to StaticItem for now but it's going to have a safety attribute. +#[derive(Clone, Encodable, Decodable, Debug)] +pub struct StaticForeignItem { + pub ty: P<Ty>, + pub mutability: Mutability, + pub expr: Option<P<Expr>>, +} + +impl From<StaticItem> for StaticForeignItem { + fn from(static_item: StaticItem) -> StaticForeignItem { + StaticForeignItem { + ty: static_item.ty, + mutability: static_item.mutability, + expr: static_item.expr, + } + } +} + +impl From<StaticForeignItem> for StaticItem { + fn from(static_item: StaticForeignItem) -> StaticItem { + StaticItem { + ty: static_item.ty, + mutability: static_item.mutability, + expr: static_item.expr, + } + } +} + #[derive(Clone, Encodable, Decodable, Debug)] pub struct ConstItem { pub defaultness: Defaultness, @@ -3329,7 +3364,7 @@ impl TryFrom<ItemKind> for AssocItemKind { #[derive(Clone, Encodable, Decodable, Debug)] pub enum ForeignItemKind { /// A foreign static item (`static FOO: u8`). - Static(P<Ty>, Mutability, Option<P<Expr>>), + Static(Box<StaticForeignItem>), /// An foreign function. Fn(Box<Fn>), /// An foreign type. @@ -3341,8 +3376,8 @@ pub enum ForeignItemKind { impl From<ForeignItemKind> for ItemKind { fn from(foreign_item_kind: ForeignItemKind) -> ItemKind { match foreign_item_kind { - ForeignItemKind::Static(a, b, c) => { - ItemKind::Static(StaticItem { ty: a, mutability: b, expr: c }.into()) + ForeignItemKind::Static(box static_foreign_item) => { + ItemKind::Static(Box::new(static_foreign_item.into())) } ForeignItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind), ForeignItemKind::TyAlias(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind), @@ -3356,8 +3391,8 @@ impl TryFrom<ItemKind> for ForeignItemKind { fn try_from(item_kind: ItemKind) -> Result<ForeignItemKind, ItemKind> { Ok(match item_kind { - ItemKind::Static(box StaticItem { ty: a, mutability: b, expr: c }) => { - ForeignItemKind::Static(a, b, c) + ItemKind::Static(box static_item) => { + ForeignItemKind::Static(Box::new(static_item.into())) } ItemKind::Fn(fn_kind) => ForeignItemKind::Fn(fn_kind), ItemKind::TyAlias(ty_alias_kind) => ForeignItemKind::TyAlias(ty_alias_kind), @@ -3382,8 +3417,8 @@ mod size_asserts { static_assert_size!(Expr, 72); static_assert_size!(ExprKind, 40); static_assert_size!(Fn, 160); - static_assert_size!(ForeignItem, 96); - static_assert_size!(ForeignItemKind, 24); + static_assert_size!(ForeignItem, 88); + static_assert_size!(ForeignItemKind, 16); static_assert_size!(GenericArg, 24); static_assert_size!(GenericBound, 88); static_assert_size!(Generics, 40); diff --git a/compiler/rustc_ast/src/entry.rs b/compiler/rustc_ast/src/entry.rs index cd8a5a66920..dd231e286d5 100644 --- a/compiler/rustc_ast/src/entry.rs +++ b/compiler/rustc_ast/src/entry.rs @@ -4,11 +4,35 @@ use rustc_span::Symbol; #[derive(Debug)] pub enum EntryPointType { + /// This function is not an entrypoint. None, + /// This is a function called `main` at the root level. + /// ``` + /// fn main() {} + /// ``` MainNamed, + /// This is a function with the `#[rustc_main]` attribute. + /// Used by the testing harness to create the test entrypoint. + /// ```ignore (clashes with test entrypoint) + /// #[rustc_main] + /// fn main() {} + /// ``` RustcMainAttr, + /// This is a function with the `#[start]` attribute. + /// ```ignore (clashes with test entrypoint) + /// #[start] + /// fn main() {} + /// ``` Start, - OtherMain, // Not an entry point, but some other function named main + /// This function is **not** an entrypoint but simply named `main` (not at the root). + /// This is only used for diagnostics. + /// ``` + /// #[allow(dead_code)] + /// mod meow { + /// fn main() {} + /// } + /// ``` + OtherMain, } pub fn entry_point_type( diff --git a/compiler/rustc_ast/src/expand/allocator.rs b/compiler/rustc_ast/src/expand/allocator.rs index f825b10f489..1723501d0fe 100644 --- a/compiler/rustc_ast/src/expand/allocator.rs +++ b/compiler/rustc_ast/src/expand/allocator.rs @@ -1,3 +1,4 @@ +use rustc_macros::HashStable_Generic; use rustc_span::symbol::{sym, Symbol}; #[derive(Clone, Debug, Copy, Eq, PartialEq, HashStable_Generic)] diff --git a/compiler/rustc_ast/src/expand/mod.rs b/compiler/rustc_ast/src/expand/mod.rs index 942347383ce..37caadd0414 100644 --- a/compiler/rustc_ast/src/expand/mod.rs +++ b/compiler/rustc_ast/src/expand/mod.rs @@ -1,5 +1,6 @@ //! Definitions shared by macros / syntax extensions and e.g. `rustc_middle`. +use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::{def_id::DefId, symbol::Ident}; use crate::MetaItem; diff --git a/compiler/rustc_ast/src/format.rs b/compiler/rustc_ast/src/format.rs index 805596ff00a..49910e2283d 100644 --- a/compiler/rustc_ast/src/format.rs +++ b/compiler/rustc_ast/src/format.rs @@ -1,6 +1,7 @@ use crate::ptr::P; use crate::Expr; use rustc_data_structures::fx::FxHashMap; +use rustc_macros::{Decodable, Encodable}; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::Span; diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index 4f21ff41529..63cde3c6809 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -11,7 +11,6 @@ #![doc(rust_logo)] #![allow(internal_features)] #![feature(rustdoc_internals)] -#![cfg_attr(bootstrap, feature(associated_type_bounds))] #![feature(associated_type_defaults)] #![feature(box_patterns)] #![feature(if_let_guard)] @@ -20,12 +19,6 @@ #![feature(negative_impls)] #![feature(stmt_expr_attributes)] -#[macro_use] -extern crate rustc_macros; - -#[macro_use] -extern crate tracing; - pub mod util { pub mod case; pub mod classify; diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index fc445600e77..4d28ef56df1 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1261,7 +1261,7 @@ pub fn noop_flat_map_item<K: NoopVisitItemKind>( impl NoopVisitItemKind for ForeignItemKind { fn noop_visit(&mut self, visitor: &mut impl MutVisitor) { match self { - ForeignItemKind::Static(ty, _, expr) => { + ForeignItemKind::Static(box StaticForeignItem { ty, mutability: _, expr }) => { visitor.visit_ty(ty); visit_opt(expr, |expr| visitor.visit_expr(expr)); } diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index dcdd44c6041..6e946530749 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -9,7 +9,7 @@ use crate::util::case::Case; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; -use rustc_macros::HashStable_Generic; +use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::symbol::{kw, sym}; #[allow(clippy::useless_attribute)] // FIXME: following use of `hidden_glob_reexports` incorrectly triggers `useless_attribute` lint. #[allow(hidden_glob_reexports)] diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 08d65a5ffa5..aadcfa7fed5 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -20,7 +20,7 @@ use crate::AttrVec; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{self, Lrc}; -use rustc_macros::HashStable_Generic; +use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_serialize::{Decodable, Encodable}; use rustc_span::{sym, Span, SpanDecoder, SpanEncoder, Symbol, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index a17c7708e4a..cb73b7908c2 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -8,6 +8,7 @@ use rustc_lexer::unescape::{ use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::Span; use std::{ascii, fmt, str}; +use tracing::debug; // Escapes a string, represented as a symbol. Reuses the original symbol, // avoiding interning, if no changes are required. diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index a0ada9a7788..1d8fd63e459 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -642,7 +642,7 @@ impl WalkItemKind for ForeignItemKind { ) -> V::Result { let &Item { id, span, ident, ref vis, .. } = item; match self { - ForeignItemKind::Static(ty, _, expr) => { + ForeignItemKind::Static(box StaticForeignItem { ty, mutability: _, expr }) => { try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_expr, expr); } diff --git a/compiler/rustc_ast_ir/src/lib.rs b/compiler/rustc_ast_ir/src/lib.rs index 9ff2e32f06b..b1a77639b56 100644 --- a/compiler/rustc_ast_ir/src/lib.rs +++ b/compiler/rustc_ast_ir/src/lib.rs @@ -3,8 +3,7 @@ #![cfg_attr(feature = "nightly", allow(internal_features))] #[cfg(feature = "nightly")] -#[macro_use] -extern crate rustc_macros; +use rustc_macros::{Decodable, Encodable, HashStable_NoContext}; pub mod visit; diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index 73001c9990c..10efe6fba65 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -5,6 +5,7 @@ ast_lowering_abi_specified_multiple_times = ast_lowering_arbitrary_expression_in_pattern = arbitrary expressions aren't allowed in patterns + .pattern_from_macro_note = the `expr` fragment specifier forces the metavariable's content to be an expression ast_lowering_argument = argument diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 6f70e135c72..02744d16b42 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -368,6 +368,8 @@ pub struct NeverPatternWithGuard { pub struct ArbitraryExpressionInPattern { #[primary_span] pub span: Span, + #[note(ast_lowering_pattern_from_macro_note)] + pub pattern_from_macro_note: bool, } #[derive(Diagnostic)] diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 93be9b9b8cf..7254be2b2f4 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -7,6 +7,7 @@ use rustc_index::IndexVec; use rustc_middle::span_bug; use rustc_middle::ty::TyCtxt; use rustc_span::{Span, DUMMY_SP}; +use tracing::{debug, instrument}; /// A visitor that walks over the HIR and collects `Node`s into a HIR map. struct NodeCollector<'a, 'hir> { @@ -61,7 +62,7 @@ pub(super) fn index_hir<'hir>( if let Node::Err(span) = node.node { let hir_id = HirId { owner: item.def_id(), local_id }; let msg = format!("ID {hir_id} not encountered when visiting item HIR"); - tcx.dcx().span_delayed_bug(*span, msg); + tcx.dcx().span_delayed_bug(span, msg); } } @@ -375,7 +376,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } } - fn visit_array_length(&mut self, len: &'hir ArrayLen) { + fn visit_array_length(&mut self, len: &'hir ArrayLen<'hir>) { match len { ArrayLen::Infer(inf) => self.insert(inf.span, inf.hir_id, Node::ArrayLenInfer(inf)), ArrayLen::Body(..) => intravisit::walk_array_len(self, len), diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index dcce54d66c2..156e369c458 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -20,6 +20,7 @@ use rustc_span::{DesugaringKind, Span, Symbol}; use rustc_target::spec::abi; use smallvec::{smallvec, SmallVec}; use thin_vec::ThinVec; +use tracing::instrument; pub(super) struct ItemLowerer<'a, 'hir> { pub(super) tcx: TyCtxt<'hir>, @@ -662,10 +663,10 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ForeignItemKind::Fn(fn_dec, fn_args, generics) } - ForeignItemKind::Static(t, m, _) => { - let ty = - self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy)); - hir::ForeignItemKind::Static(ty, *m) + ForeignItemKind::Static(box StaticForeignItem { ty, mutability, expr: _ }) => { + let ty = self + .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy)); + hir::ForeignItemKind::Static(ty, *mutability) } ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"), @@ -1588,11 +1589,12 @@ impl<'hir> LoweringContext<'_, 'hir> { }), )), )), - default: Some(hir::AnonConst { + default: Some(self.arena.alloc(hir::AnonConst { def_id: anon_const, hir_id: const_id, body: const_body, - }), + span, + })), is_host_effect: true, }, colon_span: None, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 61bc7f268cf..6c54363e306 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -37,11 +37,7 @@ #![feature(box_patterns)] #![feature(let_chains)] -#[macro_use] -extern crate tracing; - use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait}; - use rustc_ast::node_id::NodeMap; use rustc_ast::ptr::P; use rustc_ast::{self as ast, *}; @@ -69,6 +65,7 @@ use rustc_span::{DesugaringKind, Span, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; use std::collections::hash_map::Entry; use thin_vec::ThinVec; +use tracing::{debug, instrument, trace}; macro_rules! arena_vec { ($this:expr; $($x:expr),*) => ( @@ -1181,14 +1178,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { tokens: None, }; - let ct = self.with_new_scopes(span, |this| hir::AnonConst { - def_id, - hir_id: this.lower_node_id(node_id), - body: this.lower_const_body(path_expr.span, Some(&path_expr)), + let ct = self.with_new_scopes(span, |this| { + self.arena.alloc(hir::AnonConst { + def_id, + hir_id: this.lower_node_id(node_id), + body: this + .lower_const_body(path_expr.span, Some(&path_expr)), + span, + }) }); return GenericArg::Const(ConstArg { value: ct, - span, is_desugared_from_effects: false, }); } @@ -1200,7 +1200,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } ast::GenericArg::Const(ct) => GenericArg::Const(ConstArg { value: self.lower_anon_const(ct), - span: self.lower_span(ct.value.span), is_desugared_from_effects: false, }), } @@ -2318,7 +2317,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable - fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen { + fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen<'hir> { match c.value.kind { ExprKind::Underscore => { if self.tcx.features().generic_arg_infer { @@ -2341,12 +2340,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst { - self.with_new_scopes(c.value.span, |this| hir::AnonConst { + fn lower_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst { + self.arena.alloc(self.with_new_scopes(c.value.span, |this| hir::AnonConst { def_id: this.local_def_id(c.id), hir_id: this.lower_node_id(c.id), body: this.lower_const_body(c.value.span, Some(&c.value)), - }) + span: this.lower_span(c.value.span), + })) } fn lower_unsafe_source(&mut self, u: UnsafeSource) -> hir::UnsafeSource { @@ -2653,8 +2653,7 @@ impl<'hir> GenericArgsCtor<'hir> { lcx.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id))); self.args.push(hir::GenericArg::Const(hir::ConstArg { - value: hir::AnonConst { def_id, hir_id, body }, - span, + value: lcx.arena.alloc(hir::AnonConst { def_id, hir_id, body, span }), is_desugared_from_effects: true, })) } diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 118a7322fbd..32de07a0755 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -339,7 +339,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ExprKind::Path(..) if allow_paths => {} ExprKind::Unary(UnOp::Neg, inner) if matches!(inner.kind, ExprKind::Lit(_)) => {} _ => { - let guar = self.dcx().emit_err(ArbitraryExpressionInPattern { span: expr.span }); + let pattern_from_macro = expr.is_approximately_pattern(); + let guar = self.dcx().emit_err(ArbitraryExpressionInPattern { + span: expr.span, + pattern_from_macro_note: pattern_from_macro, + }); return self.arena.alloc(self.expr_err(expr.span, guar)); } } diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index aeeb4bf9e76..7679424dceb 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -18,6 +18,7 @@ use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{BytePos, DesugaringKind, Span, Symbol, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; +use tracing::{debug, instrument}; impl<'a, 'hir> LoweringContext<'a, 'hir> { #[instrument(level = "trace", skip(self))] diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 1fb410253d1..172e97e7271 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -632,20 +632,19 @@ impl<'a> AstValidator<'a> { } } - fn emit_e0568(&self, span: Span, ident: Span) { - self.dcx().emit_err(errors::AutoTraitBounds { span, ident }); - } - fn deny_super_traits(&self, bounds: &GenericBounds, ident_span: Span) { if let [.., last] = &bounds[..] { let span = ident_span.shrink_to_hi().to(last.span()); - self.emit_e0568(span, ident_span); + self.dcx().emit_err(errors::AutoTraitBounds { span, ident: ident_span }); } } fn deny_where_clause(&self, where_clause: &WhereClause, ident_span: Span) { if !where_clause.predicates.is_empty() { - self.emit_e0568(where_clause.span, ident_span); + // FIXME: The current diagnostic is misleading since it only talks about + // super trait and lifetime bounds while we should just say “boundsâ€. + self.dcx() + .emit_err(errors::AutoTraitBounds { span: where_clause.span, ident: ident_span }); } } @@ -1185,8 +1184,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_foreign_ty_genericless(generics, where_clauses); self.check_foreign_item_ascii_only(fi.ident); } - ForeignItemKind::Static(_, _, body) => { - self.check_foreign_kind_bodyless(fi.ident, "static", body.as_ref().map(|b| b.span)); + ForeignItemKind::Static(box StaticForeignItem { ty: _, mutability: _, expr }) => { + self.check_foreign_kind_bodyless(fi.ident, "static", expr.as_ref().map(|b| b.span)); self.check_foreign_item_ascii_only(fi.ident); } ForeignItemKind::MacCall(..) => {} diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index 4cbdc9f256d..93400c67949 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -422,7 +422,8 @@ impl<'a> State<'a> { self.print_type(ty); } ast::ExprKind::Type(expr, ty) => { - self.word("type_ascribe!("); + self.word("builtin # type_ascribe"); + self.popen(); self.ibox(0); self.print_expr(expr, FixupContext::default()); @@ -431,7 +432,7 @@ impl<'a> State<'a> { self.print_type(ty); self.end(); - self.word(")"); + self.pclose(); } ast::ExprKind::Let(pat, scrutinee, _, _) => { self.print_let(pat, scrutinee, fixup); @@ -488,7 +489,7 @@ impl<'a> State<'a> { self.space(); } MatchKind::Postfix => { - self.print_expr_as_cond(expr); + self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX, fixup); self.word_nbsp(".match"); } } @@ -657,15 +658,15 @@ impl<'a> State<'a> { ); } ast::ExprKind::InlineAsm(a) => { - // FIXME: This should have its own syntax, distinct from a macro invocation. + // FIXME: Print `builtin # asm` once macro `asm` uses `builtin_syntax`. self.word("asm!"); self.print_inline_asm(a); } ast::ExprKind::FormatArgs(fmt) => { - // FIXME: This should have its own syntax, distinct from a macro invocation. + // FIXME: Print `builtin # format_args` once macro `format_args` uses `builtin_syntax`. self.word("format_args!"); self.popen(); - self.rbox(0, Inconsistent); + self.ibox(0); self.word(reconstruct_format_args_template_string(&fmt.template)); for arg in fmt.arguments.all_args() { self.word_space(","); @@ -677,7 +678,7 @@ impl<'a> State<'a> { ast::ExprKind::OffsetOf(container, fields) => { self.word("builtin # offset_of"); self.popen(); - self.rbox(0, Inconsistent); + self.ibox(0); self.print_type(container); self.word(","); self.space(); @@ -690,8 +691,8 @@ impl<'a> State<'a> { self.print_ident(field); } } - self.pclose(); self.end(); + self.pclose(); } ast::ExprKind::MacCall(m) => self.print_mac(m), ast::ExprKind::Paren(e) => { diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 10886aace53..61398f7d605 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -30,15 +30,17 @@ impl<'a> State<'a> { ast::ForeignItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => { self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs); } - ast::ForeignItemKind::Static(ty, mutbl, body) => self.print_item_const( - ident, - Some(*mutbl), - &ast::Generics::default(), - ty, - body.as_deref(), - vis, - ast::Defaultness::Final, - ), + ast::ForeignItemKind::Static(box ast::StaticForeignItem { ty, mutability, expr }) => { + self.print_item_const( + ident, + Some(*mutability), + &ast::Generics::default(), + ty, + expr.as_deref(), + vis, + ast::Defaultness::Final, + ) + } ast::ForeignItemKind::TyAlias(box ast::TyAlias { defaultness, generics, @@ -236,6 +238,7 @@ impl<'a> State<'a> { self.bclose(item.span, empty); } ast::ItemKind::GlobalAsm(asm) => { + // FIXME: Print `builtin # global_asm` once macro `global_asm` uses `builtin_syntax`. self.head(visibility_qualified(&item.vis, "global_asm!")); self.print_inline_asm(asm); self.word(";"); diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 1c2077372e1..c08bf287733 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -6,7 +6,7 @@ use rustc_ast::{Attribute, LitKind, MetaItem, MetaItemKind, MetaItemLit, NestedM use rustc_ast_pretty::pprust; use rustc_errors::ErrorGuaranteed; use rustc_feature::{find_gated_cfg, is_builtin_attr_name, Features, GatedCfg}; -use rustc_macros::HashStable_Generic; +use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_session::config::ExpectedValues; use rustc_session::lint::builtin::UNEXPECTED_CFGS; use rustc_session::lint::BuiltinLintDiag; diff --git a/compiler/rustc_attr/src/lib.rs b/compiler/rustc_attr/src/lib.rs index dd87a5c4dc3..c61b7ea6d82 100644 --- a/compiler/rustc_attr/src/lib.rs +++ b/compiler/rustc_attr/src/lib.rs @@ -9,9 +9,6 @@ #![doc(rust_logo)] #![feature(let_chains)] -#[macro_use] -extern crate rustc_macros; - mod builtin; mod session_diagnostics; diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs index 0ad7bd6e17e..303909de343 100644 --- a/compiler/rustc_attr/src/session_diagnostics.rs +++ b/compiler/rustc_attr/src/session_diagnostics.rs @@ -2,7 +2,7 @@ use std::num::IntErrorKind; use rustc_ast as ast; use rustc_errors::{codes::*, Applicability, Diag, DiagCtxt, Diagnostic, EmissionGuarantee, Level}; -use rustc_macros::Diagnostic; +use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Span, Symbol}; use crate::fluent_generated as fluent; diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index af5f7571074..3e6d0311b27 100644 --- a/compiler/rustc_borrowck/src/borrow_set.rs +++ b/compiler/rustc_borrowck/src/borrow_set.rs @@ -6,6 +6,7 @@ use rustc_index::bit_set::BitSet; use rustc_middle::mir::traversal; use rustc_middle::mir::visit::{MutatingUseContext, NonUseContext, PlaceContext, Visitor}; use rustc_middle::mir::{self, Body, Local, Location}; +use rustc_middle::span_bug; use rustc_middle::ty::{RegionVid, TyCtxt}; use rustc_mir_dataflow::move_paths::MoveData; use std::fmt; @@ -109,9 +110,7 @@ impl LocalsStateAtExit { has_storage_dead.visit_body(body); let mut has_storage_dead_or_moved = has_storage_dead.0; for move_out in &move_data.moves { - if let Some(index) = move_data.base_local(move_out.path) { - has_storage_dead_or_moved.insert(index); - } + has_storage_dead_or_moved.insert(move_data.base_local(move_out.path)); } LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } } diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index 6b576ba3c4c..622feb4e4c7 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -2,6 +2,7 @@ #![allow(rustc::untranslatable_diagnostic)] use rustc_errors::{codes::*, struct_span_code_err, Diag, DiagCtxt}; +use rustc_middle::span_bug; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; diff --git a/compiler/rustc_borrowck/src/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs index 6fd80d005d9..1f0b0981c8f 100644 --- a/compiler/rustc_borrowck/src/def_use.rs +++ b/compiler/rustc_borrowck/src/def_use.rs @@ -1,3 +1,4 @@ +use rustc_middle::bug; use rustc_middle::mir::visit::{ MutatingUseContext, NonMutatingUseContext, NonUseContext, PlaceContext, }; diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index da58db57525..6c82dd1489c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -13,6 +13,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{walk_block, walk_expr, Map, Visitor}; use rustc_hir::{CoroutineDesugaring, PatField}; use rustc_hir::{CoroutineKind, CoroutineSource, LangItem}; +use rustc_middle::bug; use rustc_middle::hir::nested_filter::OnlyBodies; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::{ diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 6224cda1b16..0b4018a23ce 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -12,6 +12,7 @@ use rustc_hir::CoroutineKind; use rustc_index::IndexSlice; use rustc_infer::infer::BoundRegionConversionTime; use rustc_infer::traits::{FulfillmentErrorCode, SelectionError}; +use rustc_middle::bug; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::{ AggregateKind, CallSource, ConstOperand, FakeReadCause, Local, LocalInfo, LocalKind, Location, diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 288b846daf5..1d844c3d6a2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -4,6 +4,7 @@ use rustc_errors::{Applicability, Diag}; use rustc_hir::intravisit::Visitor; use rustc_hir::{CaptureBy, ExprKind, HirId, Node}; +use rustc_middle::bug; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty}; use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex}; diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 8b314217190..5d74a01aa20 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -7,6 +7,7 @@ use rustc_errors::{Applicability, Diag}; use rustc_hir::intravisit::Visitor; use rustc_hir::{self as hir, BindingMode, ByRef, Node}; use rustc_infer::traits; +use rustc_middle::bug; use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem}; use rustc_middle::ty::{self, InstanceDef, ToPredicate, Ty, TyCtxt}; use rustc_middle::{ diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 2fe75fe2a2b..d8d582b0ad1 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -18,6 +18,7 @@ use rustc_infer::infer::{ error_reporting::unexpected_hidden_region_diagnostic, NllRegionVariableOrigin, RelateParamBound, }; +use rustc_middle::bug; use rustc_middle::hir::place::PlaceBase; use rustc_middle::mir::{ConstraintCategory, ReturnConstraint}; use rustc_middle::ty::GenericArgs; diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index cda61360404..28c5c505f79 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -11,6 +11,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_middle::ty::print::RegionHighlightMode; use rustc_middle::ty::{self, RegionVid, Ty}; use rustc_middle::ty::{GenericArgKind, GenericArgsRef}; +use rustc_middle::{bug, span_bug}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 60037d28f62..47c83e0bb2b 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -4,7 +4,6 @@ #![feature(rustdoc_internals)] #![doc(rust_logo)] #![feature(assert_matches)] -#![cfg_attr(bootstrap, feature(associated_type_bounds))] #![feature(box_patterns)] #![feature(control_flow_enum)] #![feature(let_chains)] @@ -15,8 +14,6 @@ #![feature(try_blocks)] #[macro_use] -extern crate rustc_middle; -#[macro_use] extern crate tracing; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; @@ -33,6 +30,7 @@ use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::*; use rustc_middle::query::Providers; use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt}; +use rustc_middle::{bug, span_bug}; use rustc_session::lint::builtin::UNUSED_MUT; use rustc_span::{Span, Symbol}; use rustc_target::abi::FieldIdx; diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs index c559f9d5748..ad3c3e6d079 100644 --- a/compiler/rustc_borrowck/src/places_conflict.rs +++ b/compiler/rustc_borrowck/src/places_conflict.rs @@ -54,6 +54,7 @@ use crate::ArtificialField; use crate::Overlap; use crate::{AccessDepth, Deep, Shallow}; use rustc_hir as hir; +use rustc_middle::bug; use rustc_middle::mir::{ Body, BorrowKind, FakeBorrowKind, MutBorrowKind, Place, PlaceElem, PlaceRef, ProjectionElem, }; diff --git a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs index de469080d14..a1e59977ede 100644 --- a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs @@ -1,4 +1,5 @@ use rustc_data_structures::graph::dominators::Dominators; +use rustc_middle::bug; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{ self, BasicBlock, Body, FakeBorrowKind, Location, NonDivergingIntrinsic, Place, Rvalue, diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index dd75548a15d..78465ad7975 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -11,6 +11,7 @@ use rustc_index::{IndexSlice, IndexVec}; use rustc_infer::infer::outlives::test_type_match; use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq}; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin}; +use rustc_middle::bug; use rustc_middle::mir::{ BasicBlock, Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureOutlivesSubjectTy, ClosureRegionRequirements, ConstraintCategory, Local, Location, ReturnConstraint, diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index a950f10787b..49d3f7381d9 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -2,6 +2,7 @@ use std::fmt; use rustc_errors::ErrorGuaranteed; use rustc_infer::infer::canonical::Canonical; +use rustc_middle::bug; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc_span::def_id::DefId; diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index de75a9857f8..5aa8fe21381 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -4,6 +4,7 @@ use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate}; use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound}; use rustc_infer::infer::{self, InferCtxt, SubregionOrigin}; +use rustc_middle::bug; use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory}; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::ObligationCause; diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index 51ae7d14e43..38ec9f7678e 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -2,6 +2,7 @@ use itertools::{Either, Itertools}; use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir::visit::{TyContext, Visitor}; use rustc_middle::mir::{Body, Local, Location, SourceInfo}; +use rustc_middle::span_bug; use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{GenericArgsRef, Region, RegionVid, Ty, TyCtxt}; use rustc_mir_dataflow::impls::MaybeInitializedPlaces; diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 61fa8466674..b67c5d85818 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -33,6 +33,7 @@ use rustc_middle::ty::{ OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, }; use rustc_middle::ty::{GenericArgsRef, UserArgs}; +use rustc_middle::{bug, span_bug}; use rustc_mir_dataflow::points::DenseLocationMap; use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::source_map::Spanned; diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index d67ede57e78..5e4b3e532c4 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -5,6 +5,7 @@ use rustc_infer::infer::NllRegionVariableOrigin; use rustc_infer::infer::{ObligationEmittingRelation, StructurallyRelateAliases}; use rustc_infer::traits::{Obligation, PredicateObligations}; use rustc_middle::mir::ConstraintCategory; +use rustc_middle::span_bug; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::fold::FnMutDelegate; diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 9c65f64b03f..070238fc378 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -27,6 +27,7 @@ use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty, TyCtxt}; use rustc_middle::ty::{GenericArgs, GenericArgsRef}; +use rustc_middle::{bug, span_bug}; use rustc_span::symbol::{kw, sym}; use rustc_span::Symbol; use std::iter; diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index c192b188aa6..5f63a8ae0a8 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -18,6 +18,7 @@ use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::Span; use smallvec::SmallVec; +use tracing::instrument; pub(crate) fn expand( ecx: &mut ExtCtxt<'_>, diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 2c717661a1c..2450ac8f4b3 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -307,7 +307,7 @@ fn make_format_args( return ExpandResult::Ready(Err(guar)); } - let to_span = |inner_span: rustc_parse_format::InnerSpan| { + let to_span = |inner_span: parse::InnerSpan| { is_source_literal.then(|| { fmt_span.from_inner(InnerSpan { start: inner_span.start, end: inner_span.end }) }) @@ -577,7 +577,7 @@ fn make_format_args( fn invalid_placeholder_type_error( ecx: &ExtCtxt<'_>, ty: &str, - ty_span: Option<rustc_parse_format::InnerSpan>, + ty_span: Option<parse::InnerSpan>, fmt_span: Span, ) { let sp = ty_span.map(|sp| fmt_span.from_inner(InnerSpan::new(sp.start, sp.end))); diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 7c7b9c2d65f..744c7f9d090 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -19,11 +19,7 @@ extern crate proc_macro; -#[macro_use] -extern crate tracing; - use crate::deriving::*; - use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind}; use rustc_expand::proc_macro::BangProcMacro; use rustc_span::symbol::sym; diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 134d5451b9c..1e4bf4611cf 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -12,6 +12,7 @@ use rustc_span::{ErrorGuaranteed, FileNameDisplayPreference, Span}; use std::assert_matches::assert_matches; use std::iter; use thin_vec::{thin_vec, ThinVec}; +use tracing::debug; /// #[test_case] is used by custom test authors to mark tests /// When building for test, it needs to make the item public and gensym the name diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index a2015445b42..8cf431482ff 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -266,7 +266,7 @@ fn generate_test_harness( /// /// By default this expands to /// -/// ```ignore UNSOLVED (I think I still need guidance for this one. Is it correct? Do we try to make it run? How do we nicely fill it out?) +/// ```ignore (messes with test internals) /// #[rustc_main] /// pub fn main() { /// extern crate test; diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs index 8ffa66a4894..a48c0a4450c 100644 --- a/compiler/rustc_codegen_gcc/example/mini_core.rs +++ b/compiler/rustc_codegen_gcc/example/mini_core.rs @@ -420,7 +420,6 @@ pub fn panic(_msg: &'static str) -> ! { macro_rules! panic_const { ($($lang:ident = $message:expr,)+) => { - #[cfg(not(bootstrap))] pub mod panic_const { use super::*; diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index 16a85b4e8fa..4a1f5188a80 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -6,7 +6,8 @@ use gccjit::{ use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::errors as ssa_errors; use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeMethods, MiscMethods}; -use rustc_data_structures::base_n; +use rustc_data_structures::base_n::ToBaseN; +use rustc_data_structures::base_n::ALPHANUMERIC_ONLY; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::mir::mono::CodegenUnit; use rustc_middle::span_bug; @@ -621,7 +622,7 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> { let mut name = String::with_capacity(prefix.len() + 6); name.push_str(prefix); name.push_str("."); - base_n::push_str(idx as u128, base_n::ALPHANUMERIC_ONLY, &mut name); + name.push_str(&(idx as u64).to_base(ALPHANUMERIC_ONLY)); name } } diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index b7aec97ad8c..451e5258ebd 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -1223,7 +1223,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>( tcx, ty::Binder::dummy(tcx.mk_fn_sig( iter::once(i8p), - Ty::new_unit(tcx), + tcx.types.unit, false, rustc_hir::Unsafety::Unsafe, Abi::Rust, @@ -1234,7 +1234,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>( tcx, ty::Binder::dummy(tcx.mk_fn_sig( [i8p, i8p].iter().cloned(), - Ty::new_unit(tcx), + tcx.types.unit, false, rustc_hir::Unsafety::Unsafe, Abi::Rust, diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 345c22394f2..3f2fadce9e4 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -23,7 +23,6 @@ trusted_len, hash_raw_entry )] -#![cfg_attr(bootstrap, feature(associated_type_bounds))] #![allow(broken_intra_doc_links)] #![recursion_limit = "256"] #![warn(rust_2018_idioms)] diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index f7546039540..1a1b4ae3831 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -17,7 +17,7 @@ use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::ty::layout::{ - FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout, + FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout, }; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_sanitizers::{cfi, kcfi}; @@ -1704,12 +1704,21 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { kcfi_bundle } + /// Emits a call to `llvm.instrprof.mcdc.parameters`. + /// + /// This doesn't produce any code directly, but is used as input by + /// the LLVM pass that handles coverage instrumentation. + /// + /// (See clang's [`CodeGenPGO::emitMCDCParameters`] for comparison.) + /// + /// [`CodeGenPGO::emitMCDCParameters`]: + /// https://github.com/rust-lang/llvm-project/blob/5399a24/clang/lib/CodeGen/CodeGenPGO.cpp#L1124 pub(crate) fn mcdc_parameters( &mut self, fn_name: &'ll Value, hash: &'ll Value, bitmap_bytes: &'ll Value, - ) -> &'ll Value { + ) { debug!("mcdc_parameters() with args ({:?}, {:?}, {:?})", fn_name, hash, bitmap_bytes); assert!(llvm_util::get_version() >= (18, 0, 0), "MCDC intrinsics require LLVM 18 or later"); @@ -1732,17 +1741,6 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { [].as_ptr(), 0 as c_uint, ); - // Create condition bitmap named `mcdc.addr`. - let mut bx = Builder::with_cx(self.cx); - bx.position_at_start(llvm::LLVMGetFirstBasicBlock(self.llfn())); - let cond_bitmap = { - let alloca = - llvm::LLVMBuildAlloca(bx.llbuilder, bx.cx.type_i32(), c"mcdc.addr".as_ptr()); - llvm::LLVMSetAlignment(alloca, 4); - alloca - }; - bx.store(self.const_i32(0), cond_bitmap, self.tcx().data_layout.i32_align.abi); - cond_bitmap } } @@ -1785,8 +1783,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { 0 as c_uint, ); } - let i32_align = self.tcx().data_layout.i32_align.abi; - self.store(self.const_i32(0), mcdc_temp, i32_align); + self.store(self.const_i32(0), mcdc_temp, self.tcx.data_layout.i32_align.abi); } pub(crate) fn mcdc_condbitmap_update( diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index d32baa6dc02..653abb4e41b 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -11,7 +11,8 @@ use crate::value::Value; use rustc_codegen_ssa::base::{wants_msvc_seh, wants_wasm_eh}; use rustc_codegen_ssa::errors as ssa_errors; use rustc_codegen_ssa::traits::*; -use rustc_data_structures::base_n; +use rustc_data_structures::base_n::ToBaseN; +use rustc_data_structures::base_n::ALPHANUMERIC_ONLY; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; @@ -1015,7 +1016,7 @@ impl CodegenCx<'_, '_> { let mut name = String::with_capacity(prefix.len() + 6); name.push_str(prefix); name.push('.'); - base_n::push_str(idx as u128, base_n::ALPHANUMERIC_ONLY, &mut name); + name.push_str(&(idx as u64).to_base(ALPHANUMERIC_ONLY)); name } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 085ce15d81f..c51a7744a30 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -13,10 +13,10 @@ use rustc_codegen_ssa::traits::{ use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_llvm::RustString; use rustc_middle::bug; -use rustc_middle::mir::coverage::{CoverageKind, FunctionCoverageInfo}; +use rustc_middle::mir::coverage::CoverageKind; use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::Instance; -use rustc_target::abi::Align; +use rustc_target::abi::{Align, Size}; use std::cell::RefCell; @@ -30,7 +30,7 @@ pub struct CrateCoverageContext<'ll, 'tcx> { pub(crate) function_coverage_map: RefCell<FxIndexMap<Instance<'tcx>, FunctionCoverageCollector<'tcx>>>, pub(crate) pgo_func_name_var_map: RefCell<FxHashMap<Instance<'tcx>, &'ll llvm::Value>>, - pub(crate) mcdc_condition_bitmap_map: RefCell<FxHashMap<Instance<'tcx>, &'ll llvm::Value>>, + pub(crate) mcdc_condition_bitmap_map: RefCell<FxHashMap<Instance<'tcx>, Vec<&'ll llvm::Value>>>, } impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> { @@ -49,9 +49,20 @@ impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> { } /// LLVM use a temp value to record evaluated mcdc test vector of each decision, which is called condition bitmap. - /// This value is named `mcdc.addr` (same as clang) and is a 32-bit integer. - fn try_get_mcdc_condition_bitmap(&self, instance: &Instance<'tcx>) -> Option<&'ll llvm::Value> { - self.mcdc_condition_bitmap_map.borrow().get(instance).copied() + /// In order to handle nested decisions, several condition bitmaps can be + /// allocated for a function body. + /// These values are named `mcdc.addr.{i}` and are a 32-bit integers. + /// They respectively hold the condition bitmaps for decisions with a depth of `i`. + fn try_get_mcdc_condition_bitmap( + &self, + instance: &Instance<'tcx>, + decision_depth: u16, + ) -> Option<&'ll llvm::Value> { + self.mcdc_condition_bitmap_map + .borrow() + .get(instance) + .and_then(|bitmap_map| bitmap_map.get(decision_depth as usize)) + .copied() // Dereference Option<&&Value> to Option<&Value> } } @@ -80,6 +91,42 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { } impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { + fn init_coverage(&mut self, instance: Instance<'tcx>) { + let Some(function_coverage_info) = + self.tcx.instance_mir(instance.def).function_coverage_info.as_deref() + else { + return; + }; + + // If there are no MC/DC bitmaps to set up, return immediately. + if function_coverage_info.mcdc_bitmap_bytes == 0 { + return; + } + + let fn_name = self.get_pgo_func_name_var(instance); + let hash = self.const_u64(function_coverage_info.function_source_hash); + let bitmap_bytes = self.const_u32(function_coverage_info.mcdc_bitmap_bytes); + self.mcdc_parameters(fn_name, hash, bitmap_bytes); + + // Create pointers named `mcdc.addr.{i}` to stack-allocated condition bitmaps. + let mut cond_bitmaps = vec![]; + for i in 0..function_coverage_info.mcdc_num_condition_bitmaps { + // MC/DC intrinsics will perform loads/stores that use the ABI default + // alignment for i32, so our variable declaration should match. + let align = self.tcx.data_layout.i32_align.abi; + let cond_bitmap = self.alloca(Size::from_bytes(4), align); + llvm::set_value_name(cond_bitmap, format!("mcdc.addr.{i}").as_bytes()); + self.store(self.const_i32(0), cond_bitmap, align); + cond_bitmaps.push(cond_bitmap); + } + + self.coverage_context() + .expect("always present when coverage is enabled") + .mcdc_condition_bitmap_map + .borrow_mut() + .insert(instance, cond_bitmaps); + } + #[instrument(level = "debug", skip(self))] fn add_coverage(&mut self, instance: Instance<'tcx>, kind: &CoverageKind) { // Our caller should have already taken care of inlining subtleties, @@ -98,10 +145,6 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { return; }; - if function_coverage_info.mcdc_bitmap_bytes > 0 { - ensure_mcdc_parameters(bx, instance, function_coverage_info); - } - let Some(coverage_context) = bx.coverage_context() else { return }; let mut coverage_map = coverage_context.function_coverage_map.borrow_mut(); let func_coverage = coverage_map @@ -143,7 +186,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { CoverageKind::ExpressionUsed { id } => { func_coverage.mark_expression_id_seen(id); } - CoverageKind::CondBitmapUpdate { id, value, .. } => { + CoverageKind::CondBitmapUpdate { id, value, decision_depth } => { drop(coverage_map); assert_ne!( id.as_u32(), @@ -151,7 +194,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { "ConditionId of evaluated conditions should never be zero" ); let cond_bitmap = coverage_context - .try_get_mcdc_condition_bitmap(&instance) + .try_get_mcdc_condition_bitmap(&instance, decision_depth) .expect("mcdc cond bitmap should have been allocated for updating"); let cond_loc = bx.const_i32(id.as_u32() as i32 - 1); let bool_value = bx.const_bool(value); @@ -159,10 +202,10 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { let hash = bx.const_u64(function_coverage_info.function_source_hash); bx.mcdc_condbitmap_update(fn_name, hash, cond_loc, cond_bitmap, bool_value); } - CoverageKind::TestVectorBitmapUpdate { bitmap_idx } => { + CoverageKind::TestVectorBitmapUpdate { bitmap_idx, decision_depth } => { drop(coverage_map); let cond_bitmap = coverage_context - .try_get_mcdc_condition_bitmap(&instance) + .try_get_mcdc_condition_bitmap(&instance, decision_depth) .expect("mcdc cond bitmap should have been allocated for merging into the global bitmap"); let bitmap_bytes = bx.tcx().coverage_ids_info(instance.def).mcdc_bitmap_bytes; assert!(bitmap_idx < bitmap_bytes, "bitmap index of the decision out of range"); @@ -182,27 +225,6 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { } } -fn ensure_mcdc_parameters<'ll, 'tcx>( - bx: &mut Builder<'_, 'll, 'tcx>, - instance: Instance<'tcx>, - function_coverage_info: &FunctionCoverageInfo, -) { - let Some(cx) = bx.coverage_context() else { return }; - if cx.mcdc_condition_bitmap_map.borrow().contains_key(&instance) { - return; - } - - let fn_name = bx.get_pgo_func_name_var(instance); - let hash = bx.const_u64(function_coverage_info.function_source_hash); - let bitmap_bytes = bx.const_u32(function_coverage_info.mcdc_bitmap_bytes); - let cond_bitmap = bx.mcdc_parameters(fn_name, hash, bitmap_bytes); - bx.coverage_context() - .expect("already checked above") - .mcdc_condition_bitmap_map - .borrow_mut() - .insert(instance, cond_bitmap); -} - /// Calls llvm::createPGOFuncNameVar() with the given function instance's /// mangled function name. The LLVM API returns an llvm::GlobalVariable /// containing the function name, with the specific variable name and linkage diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs index 1aec65cf949..e521d5e259c 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs @@ -5,6 +5,7 @@ use rustc_data_structures::{ fx::FxHashMap, stable_hasher::{HashStable, StableHasher}, }; +use rustc_macros::HashStable; use rustc_middle::{ bug, ty::{ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt}, @@ -23,6 +24,8 @@ use crate::{ use super::{unknown_file_metadata, SmallVec, UNKNOWN_LINE_NUMBER}; mod private { + use rustc_macros::HashStable; + // This type cannot be constructed outside of this module because // it has a private field. We make use of this in order to prevent // `UniqueTypeId` from being constructed directly, without asserting diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 41347333ea6..56550dbfa4b 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -984,7 +984,7 @@ fn get_rust_try_fn<'ll, 'tcx>( tcx, ty::Binder::dummy(tcx.mk_fn_sig( [i8p], - Ty::new_unit(tcx), + tcx.types.unit, false, hir::Unsafety::Unsafe, Abi::Rust, @@ -995,7 +995,7 @@ fn get_rust_try_fn<'ll, 'tcx>( tcx, ty::Binder::dummy(tcx.mk_fn_sig( [i8p, i8p], - Ty::new_unit(tcx), + tcx.types.unit, false, hir::Unsafety::Unsafe, Abi::Rust, diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index c84461e53eb..1cecf682e5d 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -16,8 +16,6 @@ #![feature(impl_trait_in_assoc_type)] #[macro_use] -extern crate rustc_macros; -#[macro_use] extern crate tracing; use back::owned_target_machine::OwnedTargetMachine; diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index b458f325b73..1f691d14c53 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -8,6 +8,7 @@ use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize}; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_metadata::find_native_static_library; use rustc_metadata::fs::{copy_to_stdout, emit_wrapper_file, METADATA_FILENAME}; +use rustc_middle::bug; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols::SymbolExportKind; diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 85fcc4f4f40..f85056f8ad4 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -12,6 +12,7 @@ use std::{env, mem, str}; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_metadata::find_native_static_library; +use rustc_middle::bug; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo, SymbolExportKind}; diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index ab1bc0b6cd2..264a98844ad 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -16,6 +16,7 @@ use rustc_data_structures::owned_slice::{try_slice_owned, OwnedSlice}; use rustc_metadata::creader::MetadataLoader; use rustc_metadata::fs::METADATA_FILENAME; use rustc_metadata::EncodedMetadata; +use rustc_middle::bug; use rustc_session::Session; use rustc_span::sym; use rustc_target::abi::Endian; diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index cce3f0e6f2d..0e335bf00cf 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -6,6 +6,7 @@ use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE} use rustc_data_structures::unord::UnordMap; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; +use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::exported_symbols::{ metadata_symbol_name, ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel, diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index c4f062405bb..53ba0da7d04 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -26,6 +26,7 @@ use rustc_incremental::{ }; use rustc_metadata::fs::copy_to_stdout; use rustc_metadata::EncodedMetadata; +use rustc_middle::bug; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::middle::exported_symbols::SymbolExportInfo; use rustc_middle::ty::TyCtxt; diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index ae7c0f24b40..358c24bfb82 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -24,6 +24,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::lang_items::LangItem; use rustc_metadata::EncodedMetadata; +use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType}; use rustc_middle::middle::exported_symbols; diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs index b41739867c7..e4a36b3f591 100644 --- a/compiler/rustc_codegen_ssa/src/common.rs +++ b/compiler/rustc_codegen_ssa/src/common.rs @@ -4,6 +4,7 @@ use rustc_hir::LangItem; use rustc_middle::mir; use rustc_middle::ty::Instance; use rustc_middle::ty::{self, layout::TyAndLayout, TyCtxt}; +use rustc_middle::{bug, span_bug}; use rustc_span::Span; use crate::traits::*; diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 5f0dcf9510f..e9c7606dc5a 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -16,6 +16,7 @@ use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher}; use rustc_hir::def_id::DefId; use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData}; use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Mutability}; +use rustc_middle::bug; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; use rustc_middle::ty::{self, ExistentialProjection, ParamEnv, Ty, TyCtxt}; use rustc_middle::ty::{GenericArgKind, GenericArgsRef}; diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index b843d1bdf23..ed6a0c24410 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -431,7 +431,6 @@ pub struct ProcessingDymutilFailed { #[derive(Diagnostic)] #[diag(codegen_ssa_unable_to_run_dsymutil)] -#[note] pub struct UnableToRunDsymutil { pub error: Error, } diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 80fe7e0bb78..4eb24d71009 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -4,7 +4,6 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(bootstrap, feature(associated_type_bounds))] #![feature(box_patterns)] #![feature(if_let_guard)] #![feature(let_chains)] @@ -17,11 +16,7 @@ //! have to be implemented by each backend. #[macro_use] -extern crate rustc_macros; -#[macro_use] extern crate tracing; -#[macro_use] -extern crate rustc_middle; use rustc_ast as ast; use rustc_data_structures::fx::FxHashSet; @@ -29,6 +24,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::Lrc; use rustc_data_structures::unord::UnordMap; use rustc_hir::def_id::CrateNum; +use rustc_macros::{Decodable, Encodable, HashStable}; use rustc_middle::dep_graph::WorkProduct; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::dependency_format::Dependencies; diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs index 4f7dc9968a1..23036e9bea0 100644 --- a/compiler/rustc_codegen_ssa/src/meth.rs +++ b/compiler/rustc_codegen_ssa/src/meth.rs @@ -1,5 +1,6 @@ use crate::traits::*; +use rustc_middle::bug; use rustc_middle::ty::{self, GenericArgKind, Ty}; use rustc_session::config::Lto; use rustc_symbol_mangling::typeid_for_trait_ref; diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index c1de9b76fe7..09ae7cf6410 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -10,6 +10,7 @@ use rustc_middle::mir::traversal; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::{self, DefLocation, Location, TerminatorKind}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; +use rustc_middle::{bug, span_bug}; pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fx: &FunctionCx<'a, 'tcx, Bx>, diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index d4d172c000f..be5458523d1 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -17,6 +17,7 @@ use rustc_middle::mir::{self, AssertKind, BasicBlock, SwitchTargets, UnwindTermi use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, Instance, Ty}; +use rustc_middle::{bug, span_bug}; use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphization; use rustc_session::config::OptLevel; use rustc_span::{source_map::Spanned, sym, Span}; diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index c6260d35916..dba5fbefd8a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -5,6 +5,7 @@ use rustc_middle::mir; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::{self, Ty}; +use rustc_middle::{bug, span_bug}; use rustc_target::abi::Abi; use super::FunctionCx; diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index d0e2fc2de12..50bf1ef61f3 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -1,6 +1,7 @@ use crate::traits::*; use rustc_data_structures::fx::FxHashMap; use rustc_index::IndexVec; +use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir; use rustc_middle::ty; diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index eb14a90412d..2e008460798 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -9,6 +9,7 @@ use crate::traits::*; use crate::MemFlags; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::{bug, span_bug}; use rustc_session::config::OptLevel; use rustc_span::{sym, Span}; use rustc_target::abi::{ diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index b98e90b5cde..cf6e2e8d14c 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -8,6 +8,7 @@ use rustc_middle::mir::traversal; use rustc_middle::mir::UnwindTerminateReason; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; +use rustc_middle::{bug, span_bug}; use rustc_target::abi::call::{FnAbi, PassMode}; use std::iter; @@ -258,6 +259,10 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Apply debuginfo to the newly allocated locals. fx.debug_introduce_locals(&mut start_bx); + // If the backend supports coverage, and coverage is enabled for this function, + // do any necessary start-of-function codegen (e.g. locals for MC/DC bitmaps). + start_bx.init_coverage(instance); + // The builders will be created separately for each basic block at `codegen_block`. // So drop the builder of `start_llbb` to avoid having two at the same time. drop(start_bx); diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index e5fd59657a4..38f77f2e646 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -5,6 +5,7 @@ use crate::size_of_val; use crate::traits::*; use crate::MemFlags; +use rustc_middle::bug; use rustc_middle::mir::interpret::{alloc_range, Pointer, Scalar}; use rustc_middle::mir::{self, ConstValue}; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index b23d0894da6..870a105c61d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -5,6 +5,7 @@ use crate::common::IntPredicate; use crate::size_of_val; use crate::traits::*; +use rustc_middle::bug; use rustc_middle::mir; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 7823d4c249a..4e7d251a2e9 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -8,11 +8,11 @@ use crate::traits::*; use crate::MemFlags; use rustc_hir as hir; -use rustc_middle::mir; -use rustc_middle::mir::{AggregateKind, Operand}; +use rustc_middle::mir::{self, AggregateKind, Operand}; use rustc_middle::ty::cast::{CastTy, IntTy}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, adjustment::PointerCoercion, Instance, Ty, TyCtxt}; +use rustc_middle::{bug, span_bug}; use rustc_session::config::OptLevel; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{self, FIRST_VARIANT}; diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index 2188eeae426..a0429022587 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -1,5 +1,5 @@ -use rustc_middle::mir; -use rustc_middle::mir::NonDivergingIntrinsic; +use rustc_middle::mir::{self, NonDivergingIntrinsic}; +use rustc_middle::span_bug; use rustc_session::config::OptLevel; use super::FunctionCx; diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs index df564f705bc..40921c2932f 100644 --- a/compiler/rustc_codegen_ssa/src/mono_item.rs +++ b/compiler/rustc_codegen_ssa/src/mono_item.rs @@ -5,6 +5,7 @@ use rustc_hir as hir; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::mir::mono::MonoItem; use rustc_middle::mir::mono::{Linkage, Visibility}; +use rustc_middle::span_bug; use rustc_middle::ty; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; use rustc_middle::ty::Instance; diff --git a/compiler/rustc_codegen_ssa/src/size_of_val.rs b/compiler/rustc_codegen_ssa/src/size_of_val.rs index c250cc26823..032699f1fa1 100644 --- a/compiler/rustc_codegen_ssa/src/size_of_val.rs +++ b/compiler/rustc_codegen_ssa/src/size_of_val.rs @@ -5,6 +5,7 @@ use crate::common::IntPredicate; use crate::meth; use crate::traits::*; use rustc_hir::LangItem; +use rustc_middle::bug; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, Ty}; use rustc_target::abi::WrappingRange; diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 241b0a15f78..bcddfe9fb9c 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -8,6 +8,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::LOCAL_CRATE; +use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::parse::feature_err; diff --git a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs index d1d813bd389..906d8b87d3b 100644 --- a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs +++ b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs @@ -3,6 +3,11 @@ use rustc_middle::mir::coverage::CoverageKind; use rustc_middle::ty::Instance; pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes { + /// Performs any start-of-function codegen needed for coverage instrumentation. + /// + /// Can be a no-op in backends that don't support coverage instrumentation. + fn init_coverage(&mut self, _instance: Instance<'tcx>) {} + /// Handle the MIR coverage info in a backend-specific way. /// /// This can potentially be a no-op in backends that don't support diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index 34d9e75036f..ccb35629a82 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -3,6 +3,7 @@ use super::Backend; use super::HasCodegen; use crate::common::TypeKind; use crate::mir::place::PlaceRef; +use rustc_middle::bug; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{self, Ty}; use rustc_target::abi::call::{ArgAbi, CastTarget, FnAbi, Reg}; diff --git a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs index 7b6828c6e18..afc60d33647 100644 --- a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs @@ -105,7 +105,7 @@ impl<'mir, 'tcx: 'mir> interpret::Machine<'mir, 'tcx> for DummyMachine { _destination: &interpret::MPlaceTy<'tcx, Self::Provenance>, _target: Option<BasicBlock>, _unwind: UnwindAction, - ) -> interpret::InterpResult<'tcx> { + ) -> interpret::InterpResult<'tcx, Option<ty::Instance<'tcx>>> { unimplemented!() } diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index dd835279df3..6e6fa70107b 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -459,17 +459,14 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, dest: &MPlaceTy<'tcx, Self::Provenance>, target: Option<mir::BasicBlock>, _unwind: mir::UnwindAction, - ) -> InterpResult<'tcx> { + ) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> { // Shared intrinsics. if ecx.emulate_intrinsic(instance, args, dest, target)? { - return Ok(()); + return Ok(None); } let intrinsic_name = ecx.tcx.item_name(instance.def_id()); // CTFE-specific intrinsics. - let Some(ret) = target else { - throw_unsup_format!("intrinsic `{intrinsic_name}` is not supported at compile-time"); - }; match intrinsic_name { sym::ptr_guaranteed_cmp => { let a = ecx.read_scalar(&args[0])?; @@ -536,14 +533,22 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, // not the optimization stage.) sym::is_val_statically_known => ecx.write_scalar(Scalar::from_bool(false), dest)?, _ => { - throw_unsup_format!( - "intrinsic `{intrinsic_name}` is not supported at compile-time" - ); + // We haven't handled the intrinsic, let's see if we can use a fallback body. + if ecx.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden { + throw_unsup_format!( + "intrinsic `{intrinsic_name}` is not supported at compile-time" + ); + } + return Ok(Some(ty::Instance { + def: ty::InstanceDef::Item(instance.def_id()), + args: instance.args, + })); } } - ecx.go_to_block(ret); - Ok(()) + // Intrinsic is done, jump to next block. + ecx.return_to_block(target)?; + Ok(None) } fn assert_panic( diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 4d37c3c22cd..88ce5a7cbeb 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -113,10 +113,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> InterpResult<'tcx, bool> { let instance_args = instance.args; let intrinsic_name = self.tcx.item_name(instance.def_id()); - let Some(ret) = ret else { - // We don't support any intrinsic without return place. - return Ok(false); - }; match intrinsic_name { sym::caller_location => { @@ -376,7 +372,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; M::panic_nounwind(self, &msg)?; - // Skip the `go_to_block` at the end. + // Skip the `return_to_block` at the end (we panicked, we do not return). return Ok(true); } } @@ -414,7 +410,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } self.copy_op(&self.project_index(&input, index)?, dest)?; } - sym::likely | sym::unlikely | sym::black_box => { + sym::black_box => { // These just return their argument self.copy_op(&args[0], dest)?; } @@ -437,11 +433,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.write_scalar(Scalar::from_target_usize(align.bytes(), self), dest)?; } + // Unsupported intrinsic: skip the return_to_block below. _ => return Ok(false), } trace!("{:?}", self.dump_place(&dest.clone().into())); - self.go_to_block(ret); + self.return_to_block(ret)?; Ok(true) } diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 8bc569bed54..8405d0746df 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -216,6 +216,9 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { /// Directly process an intrinsic without pushing a stack frame. It is the hook's /// responsibility to advance the instruction pointer as appropriate. + /// + /// Returns `None` if the intrinsic was fully handled. + /// Otherwise, returns an `Instance` of the function that implements the intrinsic. fn call_intrinsic( ecx: &mut InterpCx<'mir, 'tcx, Self>, instance: ty::Instance<'tcx>, @@ -223,7 +226,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { destination: &MPlaceTy<'tcx, Self::Provenance>, target: Option<mir::BasicBlock>, unwind: mir::UnwindAction, - ) -> InterpResult<'tcx>; + ) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>>; /// Called to evaluate `Assert` MIR terminators that trigger a panic. fn assert_panic( diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs index 7ede90ad13f..7d7b421f869 100644 --- a/compiler/rustc_const_eval/src/interpret/mod.rs +++ b/compiler/rustc_const_eval/src/interpret/mod.rs @@ -18,6 +18,7 @@ mod util; mod validity; mod visitor; +#[doc(no_inline)] pub use rustc_middle::mir::interpret::*; // have all the `interpret` symbols in one place: here pub use self::eval_context::{format_interp_error, Frame, FrameInfo, InterpCx, StackPopCleanup}; diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 9c31532a9ce..07425f9a686 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -539,14 +539,28 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ty::InstanceDef::Intrinsic(def_id) => { assert!(self.tcx.intrinsic(def_id).is_some()); // FIXME: Should `InPlace` arguments be reset to uninit? - M::call_intrinsic( + if let Some(fallback) = M::call_intrinsic( self, instance, &self.copy_fn_args(args), destination, target, unwind, - ) + )? { + assert!(!self.tcx.intrinsic(fallback.def_id()).unwrap().must_be_overridden); + assert!(matches!(fallback.def, ty::InstanceDef::Item(_))); + return self.eval_fn_call( + FnVal::Instance(fallback), + (caller_abi, caller_fn_abi), + args, + with_caller_location, + destination, + target, + unwind, + ); + } else { + Ok(()) + } } ty::InstanceDef::VTableShim(..) | ty::InstanceDef::ReifyShim(..) diff --git a/compiler/rustc_data_structures/src/base_n.rs b/compiler/rustc_data_structures/src/base_n.rs index a3eb2b9c416..aed89fadc4c 100644 --- a/compiler/rustc_data_structures/src/base_n.rs +++ b/compiler/rustc_data_structures/src/base_n.rs @@ -1,6 +1,7 @@ /// Converts unsigned integers into a string representation with some base. /// Bases up to and including 36 can be used for case-insensitive things. -use std::str; +use std::ascii; +use std::fmt; #[cfg(test)] mod tests; @@ -9,36 +10,101 @@ pub const MAX_BASE: usize = 64; pub const ALPHANUMERIC_ONLY: usize = 62; pub const CASE_INSENSITIVE: usize = 36; -const BASE_64: &[u8; MAX_BASE] = - b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@$"; +const BASE_64: [ascii::Char; MAX_BASE] = { + let bytes = b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@$"; + let Some(ascii) = bytes.as_ascii() else { panic!() }; + *ascii +}; -#[inline] -pub fn push_str(mut n: u128, base: usize, output: &mut String) { - debug_assert!(base >= 2 && base <= MAX_BASE); - let mut s = [0u8; 128]; - let mut index = s.len(); +pub struct BaseNString { + start: usize, + buf: [ascii::Char; 128], +} + +impl std::ops::Deref for BaseNString { + type Target = str; - let base = base as u128; + fn deref(&self) -> &str { + self.buf[self.start..].as_str() + } +} + +impl AsRef<str> for BaseNString { + fn as_ref(&self) -> &str { + self.buf[self.start..].as_str() + } +} + +impl fmt::Display for BaseNString { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self) + } +} + +// This trait just lets us reserve the exact right amount of space when doing fixed-length +// case-insensitve encoding. Add any impls you need. +pub trait ToBaseN: Into<u128> { + fn encoded_len(base: usize) -> usize; + + fn to_base_fixed_len(self, base: usize) -> BaseNString { + let mut encoded = self.to_base(base); + encoded.start = encoded.buf.len() - Self::encoded_len(base); + encoded + } - loop { - index -= 1; - s[index] = BASE_64[(n % base) as usize]; - n /= base; + fn to_base(self, base: usize) -> BaseNString { + let mut output = [ascii::Char::Digit0; 128]; - if n == 0 { - break; + let mut n: u128 = self.into(); + + let mut index = output.len(); + loop { + index -= 1; + output[index] = BASE_64[(n % base as u128) as usize]; + n /= base as u128; + + if n == 0 { + break; + } + } + assert_eq!(n, 0); + + BaseNString { start: index, buf: output } + } +} + +impl ToBaseN for u128 { + fn encoded_len(base: usize) -> usize { + let mut max = u128::MAX; + let mut len = 0; + while max > 0 { + len += 1; + max /= base as u128; } + len } +} - output.push_str(unsafe { - // SAFETY: `s` is populated using only valid utf8 characters from `BASE_64` - str::from_utf8_unchecked(&s[index..]) - }); +impl ToBaseN for u64 { + fn encoded_len(base: usize) -> usize { + let mut max = u64::MAX; + let mut len = 0; + while max > 0 { + len += 1; + max /= base as u64; + } + len + } } -#[inline] -pub fn encode(n: u128, base: usize) -> String { - let mut s = String::new(); - push_str(n, base, &mut s); - s +impl ToBaseN for u32 { + fn encoded_len(base: usize) -> usize { + let mut max = u32::MAX; + let mut len = 0; + while max > 0 { + len += 1; + max /= base as u32; + } + len + } } diff --git a/compiler/rustc_data_structures/src/base_n/tests.rs b/compiler/rustc_data_structures/src/base_n/tests.rs index 2be2f0532c9..148d8dde02a 100644 --- a/compiler/rustc_data_structures/src/base_n/tests.rs +++ b/compiler/rustc_data_structures/src/base_n/tests.rs @@ -1,9 +1,17 @@ use super::*; #[test] -fn test_encode() { +fn limits() { + assert_eq!(Ok(u128::MAX), u128::from_str_radix(&u128::MAX.to_base(36), 36)); + assert_eq!(Ok(u64::MAX), u64::from_str_radix(&u64::MAX.to_base(36), 36)); + assert_eq!(Ok(u32::MAX), u32::from_str_radix(&u32::MAX.to_base(36), 36)); +} + +#[test] +fn test_to_base() { fn test(n: u128, base: usize) { - assert_eq!(Ok(n), u128::from_str_radix(&encode(n, base), base as u32)); + assert_eq!(Ok(n), u128::from_str_radix(&n.to_base(base), base as u32)); + assert_eq!(Ok(n), u128::from_str_radix(&n.to_base_fixed_len(base), base as u32)); } for base in 2..37 { diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 2b799d6f5d3..8dd85b25e0e 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -16,6 +16,8 @@ #![doc(rust_logo)] #![feature(allocator_api)] #![feature(array_windows)] +#![feature(ascii_char)] +#![feature(ascii_char_variants)] #![feature(auto_traits)] #![feature(cfg_match)] #![feature(core_intrinsics)] @@ -25,6 +27,7 @@ #![feature(lazy_cell)] #![feature(lint_reasons)] #![feature(macro_metavar_expr)] +#![feature(map_try_insert)] #![feature(maybe_uninit_uninit_array)] #![feature(min_specialization)] #![feature(negative_impls)] @@ -41,8 +44,6 @@ #[macro_use] extern crate tracing; -#[macro_use] -extern crate rustc_macros; use std::fmt; @@ -146,9 +147,9 @@ pub fn make_display(f: impl Fn(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl Printer { f } } -// See comments in compiler/rustc_middle/src/tests.rs +// See comment in compiler/rustc_middle/src/tests.rs and issue #27438. #[doc(hidden)] -pub fn __noop_fix_for_27438() {} +pub fn __noop_fix_for_windows_dllimport_issue() {} #[macro_export] macro_rules! external_bitflags_debug { diff --git a/compiler/rustc_data_structures/src/sorted_map.rs b/compiler/rustc_data_structures/src/sorted_map.rs index 1436628139f..21d7c91ec48 100644 --- a/compiler/rustc_data_structures/src/sorted_map.rs +++ b/compiler/rustc_data_structures/src/sorted_map.rs @@ -1,4 +1,5 @@ use crate::stable_hasher::{HashStable, StableHasher, StableOrd}; +use rustc_macros::{Decodable_Generic, Encodable_Generic}; use std::borrow::Borrow; use std::fmt::Debug; use std::mem; diff --git a/compiler/rustc_data_structures/src/svh.rs b/compiler/rustc_data_structures/src/svh.rs index 1cfc9fecd47..38629ea9801 100644 --- a/compiler/rustc_data_structures/src/svh.rs +++ b/compiler/rustc_data_structures/src/svh.rs @@ -6,9 +6,9 @@ //! compiled from distinct sources. use crate::fingerprint::Fingerprint; -use std::fmt; - use crate::stable_hasher; +use rustc_macros::{Decodable_Generic, Encodable_Generic}; +use std::fmt; #[derive(Copy, Clone, PartialEq, Eq, Debug, Encodable_Generic, Decodable_Generic, Hash)] pub struct Svh { diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index eab6d8168ca..ecb85db33f7 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -46,6 +46,7 @@ use std::collections::HashMap; use std::hash::{BuildHasher, Hash}; mod lock; +#[doc(no_inline)] pub use lock::{Lock, LockGuard, Mode}; mod worker_local; @@ -199,10 +200,15 @@ cfg_match! { pub use std::rc::Rc as Lrc; pub use std::rc::Weak as Weak; + #[doc(no_inline)] pub use std::cell::Ref as ReadGuard; + #[doc(no_inline)] pub use std::cell::Ref as MappedReadGuard; + #[doc(no_inline)] pub use std::cell::RefMut as WriteGuard; + #[doc(no_inline)] pub use std::cell::RefMut as MappedWriteGuard; + #[doc(no_inline)] pub use std::cell::RefMut as MappedLockGuard; pub use std::cell::OnceCell as OnceLock; diff --git a/compiler/rustc_data_structures/src/unord.rs b/compiler/rustc_data_structures/src/unord.rs index a99e2062039..1ccd22a56c9 100644 --- a/compiler/rustc_data_structures/src/unord.rs +++ b/compiler/rustc_data_structures/src/unord.rs @@ -3,6 +3,8 @@ //! as required by the query system. use rustc_hash::{FxHashMap, FxHashSet}; +use rustc_macros::{Decodable_Generic, Encodable_Generic}; +use std::collections::hash_map::OccupiedError; use std::{ borrow::{Borrow, BorrowMut}, collections::hash_map::Entry, @@ -469,6 +471,11 @@ impl<K: Eq + Hash, V> UnordMap<K, V> { } #[inline] + pub fn try_insert(&mut self, k: K, v: V) -> Result<&mut V, OccupiedError<'_, K, V>> { + self.inner.try_insert(k, v) + } + + #[inline] pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool where K: Borrow<Q>, diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index a8bba3afb7e..cb37644d570 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -42,9 +42,8 @@ rustc_privacy = { path = "../rustc_privacy" } rustc_query_system = { path = "../rustc_query_system" } rustc_resolve = { path = "../rustc_resolve" } rustc_session = { path = "../rustc_session" } -rustc_smir ={ path = "../rustc_smir" } +rustc_smir = { path = "../rustc_smir" } rustc_span = { path = "../rustc_span" } -rustc_symbol_mangling = { path = "../rustc_symbol_mangling" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_ty_utils = { path = "../rustc_ty_utils" } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index b3cba4dbfc2..b2d38a00f0b 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -14,9 +14,6 @@ #![feature(panic_update_hook)] #![feature(result_flattening)] -#[macro_use] -extern crate tracing; - use rustc_ast as ast; use rustc_codegen_ssa::{traits::CodegenBackend, CodegenErrors, CodegenResults}; use rustc_const_eval::CTRL_C_RECEIVED; @@ -46,7 +43,6 @@ use rustc_span::symbol::sym; use rustc_span::FileName; use rustc_target::json::ToJson; use rustc_target::spec::{Target, TargetTriple}; - use std::cmp::max; use std::collections::BTreeMap; use std::env; @@ -62,6 +58,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, OnceLock}; use std::time::{Instant, SystemTime}; use time::OffsetDateTime; +use tracing::trace; #[allow(unused_macros)] macro do_not_use_print($($t:tt)*) { @@ -971,7 +968,7 @@ Available lint options: let lint_store = unerased_lint_store(sess); let (loaded, builtin): (Vec<_>, _) = - lint_store.get_lints().iter().cloned().partition(|&lint| lint.is_loaded); + lint_store.get_lints().iter().cloned().partition(|&lint| lint.is_externally_loaded); let loaded = sort_lints(sess, loaded); let builtin = sort_lints(sess, builtin); diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs index 40f6f764993..fe426b8111c 100644 --- a/compiler/rustc_driver_impl/src/pretty.rs +++ b/compiler/rustc_driver_impl/src/pretty.rs @@ -13,9 +13,9 @@ use rustc_session::Session; use rustc_smir::rustc_internal::pretty::write_smir_pretty; use rustc_span::symbol::Ident; use rustc_span::FileName; - use std::cell::Cell; use std::fmt::Write; +use tracing::debug; pub use self::PpMode::*; pub use self::PpSourceMode::*; diff --git a/compiler/rustc_error_codes/src/error_codes/E0637.md b/compiler/rustc_error_codes/src/error_codes/E0637.md index 62d5565df27..9c2a53f51cf 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0637.md +++ b/compiler/rustc_error_codes/src/error_codes/E0637.md @@ -1,5 +1,5 @@ `'_` lifetime name or `&T` without an explicit lifetime name has been used -on illegal place. +in an illegal place. Erroneous code example: @@ -13,7 +13,14 @@ fn underscore_lifetime<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { } } -fn and_without_explicit_lifetime<T>() +fn without_explicit_lifetime<T>() +where + T: Iterator<Item = &u32>, + //^ `&` without an explicit lifetime name +{ +} + +fn without_hrtb<T>() where T: Into<&u32>, //^ `&` without an explicit lifetime name @@ -40,9 +47,15 @@ fn underscore_lifetime<'a>(str1: &'a str, str2: &'a str) -> &'a str { } } -fn and_without_explicit_lifetime<'foo, T>() +fn without_explicit_lifetime<'a, T>() +where + T: Iterator<Item = &'a u32>, +{ +} + +fn without_hrtb<T>() where - T: Into<&'foo u32>, + T: for<'foo> Into<&'foo u32>, { } ``` diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 6c84eeaf888..1610135a0ef 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -7,6 +7,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_error_messages::fluent_value_from_str_list_sep_by_and; use rustc_error_messages::FluentValue; use rustc_lint_defs::{Applicability, LintExpectationId}; +use rustc_macros::{Decodable, Encodable}; use rustc_span::source_map::Spanned; use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; @@ -17,6 +18,7 @@ use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; use std::panic; use std::thread::panicking; +use tracing::debug; /// Error type for `DiagInner`'s `suggestions` field, indicating that /// `.disable_suggestions()` was called on the `DiagInner`. diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 2b10fcd8d6a..4696917554f 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -7,12 +7,13 @@ use crate::{ use rustc_ast as ast; use rustc_ast_pretty::pprust; use rustc_hir as hir; +use rustc_macros::Subdiagnostic; use rustc_span::edition::Edition; use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol}; use rustc_span::Span; use rustc_target::abi::TargetDataLayoutErrors; use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple}; -use rustc_type_ir as type_ir; +use rustc_type_ir::{ClosureKind, FloatTy}; use std::backtrace::Backtrace; use std::borrow::Cow; use std::fmt; @@ -195,7 +196,7 @@ impl IntoDiagArg for ast::token::TokenKind { } } -impl IntoDiagArg for type_ir::FloatTy { +impl IntoDiagArg for FloatTy { fn into_diag_arg(self) -> DiagArgValue { DiagArgValue::Str(Cow::Borrowed(self.name_str())) } @@ -251,7 +252,7 @@ impl IntoDiagArg for Level { } } -impl IntoDiagArg for type_ir::ClosureKind { +impl IntoDiagArg for ClosureKind { fn into_diag_arg(self) -> DiagArgValue { DiagArgValue::Str(self.as_str().into()) } diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 6074a4a30bb..5d4d2555100 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -35,6 +35,7 @@ use std::iter; use std::path::Path; use termcolor::{Buffer, BufferWriter, ColorChoice, ColorSpec, StandardStream}; use termcolor::{Color, WriteColor}; +use tracing::{debug, instrument, trace, warn}; /// Default column width, used in tests and when terminal dimensions cannot be determined. const DEFAULT_COLUMN_WIDTH: usize = 140; @@ -984,7 +985,7 @@ impl HumanEmitter { // 4 | } // | for pos in 0..=line_len { - draw_col_separator(buffer, line_offset + pos + 1, width_offset - 2); + draw_col_separator_no_space(buffer, line_offset + pos + 1, width_offset - 2); } // Write the horizontal lines for multiline annotations @@ -2260,13 +2261,23 @@ impl HumanEmitter { buffer.puts(*row_num, max_line_num_len + 1, "+ ", Style::Addition); } [] => { - draw_col_separator(buffer, *row_num, max_line_num_len + 1); + draw_col_separator_no_space(buffer, *row_num, max_line_num_len + 1); } _ => { buffer.puts(*row_num, max_line_num_len + 1, "~ ", Style::Addition); } } - buffer.append(*row_num, &normalize_whitespace(line_to_add), Style::NoStyle); + // LL | line_to_add + // ++^^^ + // | | + // | magic `3` + // `max_line_num_len` + buffer.puts( + *row_num, + max_line_num_len + 3, + &normalize_whitespace(line_to_add), + Style::NoStyle, + ); } else if let DisplaySuggestion::Add = show_code_change { buffer.puts(*row_num, 0, &self.maybe_anonymized(line_num), Style::LineNumber); buffer.puts(*row_num, max_line_num_len + 1, "+ ", Style::Addition); diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index adbac80d7cc..3b884ff864a 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -25,12 +25,6 @@ #![feature(yeet_expr)] // tidy-alphabetical-end -#[macro_use] -extern crate rustc_macros; - -#[macro_use] -extern crate tracing; - extern crate self as rustc_errors; pub use codes::*; @@ -64,6 +58,7 @@ use rustc_data_structures::stable_hasher::{Hash128, StableHasher}; use rustc_data_structures::sync::{Lock, Lrc}; use rustc_data_structures::AtomicRef; use rustc_lint_defs::LintExpectationId; +use rustc_macros::{Decodable, Encodable}; use rustc_span::source_map::SourceMap; use rustc_span::{Loc, Span, DUMMY_SP}; use std::backtrace::{Backtrace, BacktraceStatus}; @@ -76,6 +71,7 @@ use std::num::NonZero; use std::ops::DerefMut; use std::panic; use std::path::{Path, PathBuf}; +use tracing::debug; use Level::*; diff --git a/compiler/rustc_errors/src/snippet.rs b/compiler/rustc_errors/src/snippet.rs index b55f7853885..d6119fb41d2 100644 --- a/compiler/rustc_errors/src/snippet.rs +++ b/compiler/rustc_errors/src/snippet.rs @@ -1,6 +1,7 @@ // Code for annotating snippets. use crate::{Level, Loc}; +use rustc_macros::{Decodable, Encodable}; #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)] pub struct Line { diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index bf0026568ce..445e9b4fd6e 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -6,6 +6,7 @@ pub use rustc_error_messages::FluentArgs; use std::borrow::Cow; use std::env; use std::error::Report; +use tracing::{debug, trace}; /// Convert diagnostic arguments (a rustc internal type that exists to implement /// `Encodable`/`Decodable`) into `FluentArgs` which is necessary to perform translation. diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 6fe74edbd70..12868a66605 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -21,7 +21,7 @@ use rustc_session::config::CollapseMacroDebuginfo; use rustc_session::{parse::ParseSess, Limit, Session}; use rustc_span::def_id::{CrateNum, DefId, LocalDefId}; use rustc_span::edition::Edition; -use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId}; +use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId, MacroKind}; use rustc_span::source_map::SourceMap; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{FileName, Span, DUMMY_SP}; @@ -32,8 +32,6 @@ use std::path::{Path, PathBuf}; use std::rc::Rc; use thin_vec::ThinVec; -pub(crate) use rustc_span::hygiene::MacroKind; - // When adding new variants, make sure to // adjust the `visit_*` / `flat_map_*` calls in `InvocationCollector` // to use `assign_id!` @@ -573,35 +571,6 @@ impl DummyResult { tokens: None, }) } - - /// A plain dummy pattern. - pub fn raw_pat(sp: Span) -> ast::Pat { - ast::Pat { id: ast::DUMMY_NODE_ID, kind: PatKind::Wild, span: sp, tokens: None } - } - - /// A plain dummy type. - pub fn raw_ty(sp: Span) -> P<ast::Ty> { - // FIXME(nnethercote): you might expect `ast::TyKind::Dummy` to be used here, but some - // values produced here end up being lowered to HIR, which `ast::TyKind::Dummy` does not - // support, so we use an empty tuple instead. - P(ast::Ty { - id: ast::DUMMY_NODE_ID, - kind: ast::TyKind::Tup(ThinVec::new()), - span: sp, - tokens: None, - }) - } - - /// A plain dummy crate. - pub fn raw_crate() -> ast::Crate { - ast::Crate { - attrs: Default::default(), - items: Default::default(), - spans: Default::default(), - id: ast::DUMMY_NODE_ID, - is_placeholder: Default::default(), - } - } } impl MacResult for DummyResult { @@ -610,7 +579,12 @@ impl MacResult for DummyResult { } fn make_pat(self: Box<DummyResult>) -> Option<P<ast::Pat>> { - Some(P(DummyResult::raw_pat(self.span))) + Some(P(ast::Pat { + id: ast::DUMMY_NODE_ID, + kind: PatKind::Wild, + span: self.span, + tokens: None, + })) } fn make_items(self: Box<DummyResult>) -> Option<SmallVec<[P<ast::Item>; 1]>> { @@ -638,7 +612,15 @@ impl MacResult for DummyResult { } fn make_ty(self: Box<DummyResult>) -> Option<P<ast::Ty>> { - Some(DummyResult::raw_ty(self.span)) + // FIXME(nnethercote): you might expect `ast::TyKind::Dummy` to be used here, but some + // values produced here end up being lowered to HIR, which `ast::TyKind::Dummy` does not + // support, so we use an empty tuple instead. + Some(P(ast::Ty { + id: ast::DUMMY_NODE_ID, + kind: ast::TyKind::Tup(ThinVec::new()), + span: self.span, + tokens: None, + })) } fn make_arms(self: Box<DummyResult>) -> Option<SmallVec<[ast::Arm; 1]>> { @@ -670,7 +652,13 @@ impl MacResult for DummyResult { } fn make_crate(self: Box<DummyResult>) -> Option<ast::Crate> { - Some(DummyResult::raw_crate()) + Some(ast::Crate { + attrs: Default::default(), + items: Default::default(), + spans: Default::default(), + id: ast::DUMMY_NODE_ID, + is_placeholder: Default::default(), + }) } } diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 83f120525bc..1b6e191c2eb 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -175,20 +175,6 @@ impl<'a> ExtCtxt<'a> { ast::Stmt { id: ast::DUMMY_NODE_ID, span: expr.span, kind: ast::StmtKind::Expr(expr) } } - pub fn stmt_let_pat(&self, sp: Span, pat: P<ast::Pat>, ex: P<ast::Expr>) -> ast::Stmt { - let local = P(ast::Local { - pat, - ty: None, - id: ast::DUMMY_NODE_ID, - kind: LocalKind::Init(ex), - span: sp, - colon_sp: None, - attrs: AttrVec::new(), - tokens: None, - }); - self.stmt_local(local, sp) - } - pub fn stmt_let(&self, sp: Span, mutbl: bool, ident: Ident, ex: P<ast::Expr>) -> ast::Stmt { self.stmt_let_ty(sp, mutbl, ident, None, ex) } @@ -278,10 +264,6 @@ impl<'a> ExtCtxt<'a> { self.expr_ident(span, Ident::with_dummy_span(kw::SelfLower)) } - pub fn expr_field(&self, span: Span, expr: P<Expr>, field: Ident) -> P<ast::Expr> { - self.expr(span, ast::ExprKind::Field(expr, field)) - } - pub fn expr_macro_call(&self, span: Span, call: P<ast::MacCall>) -> P<ast::Expr> { self.expr(span, ast::ExprKind::MacCall(call)) } @@ -394,11 +376,6 @@ impl<'a> ExtCtxt<'a> { self.expr(span, ast::ExprKind::Lit(lit)) } - pub fn expr_char(&self, span: Span, ch: char) -> P<ast::Expr> { - let lit = token::Lit::new(token::Char, literal::escape_char_symbol(ch), None); - self.expr(span, ast::ExprKind::Lit(lit)) - } - pub fn expr_byte_str(&self, span: Span, bytes: Vec<u8>) -> P<ast::Expr> { let lit = token::Lit::new(token::ByteStr, literal::escape_byte_str_symbol(&bytes), None); self.expr(span, ast::ExprKind::Lit(lit)) @@ -414,10 +391,6 @@ impl<'a> ExtCtxt<'a> { self.expr_addr_of(sp, self.expr_array(sp, exprs)) } - pub fn expr_cast(&self, sp: Span, expr: P<ast::Expr>, ty: P<ast::Ty>) -> P<ast::Expr> { - self.expr(sp, ast::ExprKind::Cast(expr, ty)) - } - pub fn expr_some(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr> { let some = self.std_path(&[sym::option, sym::Option, sym::Some]); self.expr_call_global(sp, some, thin_vec![expr]) diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index c95d7cdeb73..897420a11cd 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -20,6 +20,7 @@ use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use thin_vec::ThinVec; +use tracing::instrument; /// A folder that strips out items that do not belong in the current configuration. pub struct StripUnconfigured<'a> { @@ -98,10 +99,11 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) - // If the declared feature is unstable, record it. if let Some(f) = UNSTABLE_FEATURES.iter().find(|f| name == f.feature.name) { (f.set_enabled)(&mut features); - // When the ICE comes from core, alloc or std (approximation of the standard library), there's a chance - // that the person hitting the ICE may be using -Zbuild-std or similar with an untested target. - // The bug is probably in the standard library and not the compiler in that case, but that doesn't - // really matter - we want a bug report. + // When the ICE comes from core, alloc or std (approximation of the standard + // library), there's a chance that the person hitting the ICE may be using + // -Zbuild-std or similar with an untested target. The bug is probably in the + // standard library and not the compiler in that case, but that doesn't really + // matter - we want a bug report. if features.internal(name) && ![sym::core, sym::alloc, sym::std].contains(&crate_name) { diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index db8e4ba07e8..b0563bfdea7 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -1,6 +1,6 @@ use rustc_ast::ast; use rustc_errors::codes::*; -use rustc_macros::Diagnostic; +use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::Limit; use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent}; use rustc_span::{Span, Symbol}; diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 503c9170cab..f61cebc0256 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -4,7 +4,6 @@ use crate::errors::{ IncompleteParse, RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported, UnsupportedKeyValue, WrongFragmentKind, }; -use crate::hygiene::SyntaxContext; use crate::mbe::diagnostics::annotate_err_with_kind; use crate::module::{mod_dir_path, parse_external_mod, DirOwnership, ParsedExternalMod}; use crate::placeholders::{placeholder, PlaceholderExpander}; @@ -32,6 +31,7 @@ use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS}; use rustc_session::lint::BuiltinLintDiag; use rustc_session::parse::feature_err; use rustc_session::{Limit, Session}; +use rustc_span::hygiene::SyntaxContext; use rustc_span::symbol::{sym, Ident}; use rustc_span::{ErrorGuaranteed, FileName, LocalExpnId, Span}; @@ -87,7 +87,7 @@ macro_rules! ast_fragments { } impl AstFragment { - pub fn add_placeholders(&mut self, placeholders: &[NodeId]) { + fn add_placeholders(&mut self, placeholders: &[NodeId]) { if placeholders.is_empty() { return; } @@ -100,14 +100,14 @@ macro_rules! ast_fragments { } } - pub fn make_opt_expr(self) -> Option<P<ast::Expr>> { + pub(crate) fn make_opt_expr(self) -> Option<P<ast::Expr>> { match self { AstFragment::OptExpr(expr) => expr, _ => panic!("AstFragment::make_* called on the wrong kind of fragment"), } } - pub fn make_method_receiver_expr(self) -> P<ast::Expr> { + pub(crate) fn make_method_receiver_expr(self) -> P<ast::Expr> { match self { AstFragment::MethodReceiverExpr(expr) => expr, _ => panic!("AstFragment::make_* called on the wrong kind of fragment"), @@ -125,7 +125,7 @@ macro_rules! ast_fragments { T::fragment_to_output(self) } - pub fn mut_visit_with<F: MutVisitor>(&mut self, vis: &mut F) { + pub(crate) fn mut_visit_with<F: MutVisitor>(&mut self, vis: &mut F) { match self { AstFragment::OptExpr(opt_expr) => { visit_clobber(opt_expr, |opt_expr| { @@ -372,6 +372,14 @@ impl Invocation { InvocationKind::Derive { path, .. } => path.span, } } + + fn span_mut(&mut self) -> &mut Span { + match &mut self.kind { + InvocationKind::Bang { span, .. } => span, + InvocationKind::Attr { attr, .. } => &mut attr.span, + InvocationKind::Derive { path, .. } => &mut path.span, + } + } } pub struct MacroExpander<'a, 'b> { @@ -432,7 +440,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { break; } invocations = mem::take(&mut undetermined_invocations); - force = !mem::replace(&mut progress, false); + force = !progress; + progress = false; if force && self.monotonic { self.cx.dcx().span_delayed_bug( invocations.last().unwrap().0.span(), @@ -471,7 +480,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx.force_mode = force; let fragment_kind = invoc.fragment_kind; - let (expanded_fragment, new_invocations) = match self.expand_invoc(invoc, &ext.kind) { + match self.expand_invoc(invoc, &ext.kind) { ExpandResult::Ready(fragment) => { let mut derive_invocations = Vec::new(); let derive_placeholders = self @@ -503,12 +512,19 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }) .unwrap_or_default(); - let (fragment, collected_invocations) = + let (expanded_fragment, collected_invocations) = self.collect_invocations(fragment, &derive_placeholders); - // We choose to expand any derive invocations associated with this macro invocation - // *before* any macro invocations collected from the output fragment + // We choose to expand any derive invocations associated with this macro + // invocation *before* any macro invocations collected from the output + // fragment. derive_invocations.extend(collected_invocations); - (fragment, derive_invocations) + + progress = true; + if expanded_fragments.len() < depth { + expanded_fragments.push(Vec::new()); + } + expanded_fragments[depth - 1].push((expn_id, expanded_fragment)); + invocations.extend(derive_invocations.into_iter().rev()); } ExpandResult::Retry(invoc) => { if force { @@ -519,17 +535,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } else { // Cannot expand, will retry this invocation later. undetermined_invocations.push((invoc, Some(ext))); - continue; } } - }; - - progress = true; - if expanded_fragments.len() < depth { - expanded_fragments.push(Vec::new()); } - expanded_fragments[depth - 1].push((expn_id, expanded_fragment)); - invocations.extend(new_invocations.into_iter().rev()); } self.cx.current_expansion = orig_expansion_data; @@ -590,11 +598,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { for (invoc, _) in invocations.iter_mut() { let expn_id = invoc.expansion_data.id; let parent_def = self.cx.resolver.invocation_parent(expn_id); - let span = match &mut invoc.kind { - InvocationKind::Bang { span, .. } => span, - InvocationKind::Attr { attr, .. } => &mut attr.span, - InvocationKind::Derive { path, .. } => &mut path.span, - }; + let span = invoc.span_mut(); *span = span.with_parent(Some(parent_def)); } } @@ -957,7 +961,7 @@ pub fn parse_ast_fragment<'a>( }) } -pub fn ensure_complete_parse<'a>( +pub(crate) fn ensure_complete_parse<'a>( parser: &Parser<'a>, macro_path: &ast::Path, kind_name: &str, diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index c9a3aeedd02..c2c3b777699 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -1,50 +1,39 @@ +// tidy-alphabetical-start +#![allow(internal_features)] +#![allow(rustc::diagnostic_outside_of_impl)] #![doc(rust_logo)] -#![feature(rustdoc_internals)] #![feature(array_windows)] -#![cfg_attr(bootstrap, feature(associated_type_bounds))] #![feature(associated_type_defaults)] #![feature(if_let_guard)] #![feature(let_chains)] -#![feature(lint_reasons)] #![feature(macro_metavar_expr)] #![feature(map_try_insert)] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_internals)] -#![feature(proc_macro_span)] +#![feature(rustdoc_internals)] #![feature(try_blocks)] #![feature(yeet_expr)] -#![allow(rustc::diagnostic_outside_of_impl)] -#![allow(internal_features)] - -#[macro_use] -extern crate rustc_macros; - -#[macro_use] -extern crate tracing; +// tidy-alphabetical-end extern crate proc_macro as pm; +mod build; +mod errors; +// FIXME(Nilstrieb) Translate macro_rules diagnostics +#[allow(rustc::untranslatable_diagnostic)] +mod mbe; mod placeholders; mod proc_macro_server; pub use mbe::macro_rules::compile_declarative_macro; -pub(crate) use rustc_span::hygiene; pub mod base; -pub mod build; -#[macro_use] pub mod config; -pub mod errors; pub mod expand; pub mod module; - // FIXME(Nilstrieb) Translate proc_macro diagnostics #[allow(rustc::untranslatable_diagnostic)] pub mod proc_macro; -// FIXME(Nilstrieb) Translate macro_rules diagnostics -#[allow(rustc::untranslatable_diagnostic)] -pub(crate) mod mbe; - // HACK(Centril, #64197): These shouldn't really be here. // Rather, they should be with their respective modules which are defined in other crates. // However, since for now constructing a `ParseSess` sorta requires `config` from this crate, diff --git a/compiler/rustc_expand/src/mbe.rs b/compiler/rustc_expand/src/mbe.rs index ca4a1f327ad..a805c4fcf7b 100644 --- a/compiler/rustc_expand/src/mbe.rs +++ b/compiler/rustc_expand/src/mbe.rs @@ -4,16 +4,18 @@ //! official terminology: "declarative macros". pub(crate) mod diagnostics; -pub(crate) mod macro_check; -pub(crate) mod macro_parser; pub(crate) mod macro_rules; -pub(crate) mod metavar_expr; -pub(crate) mod quoted; -pub(crate) mod transcribe; + +mod macro_check; +mod macro_parser; +mod metavar_expr; +mod quoted; +mod transcribe; use metavar_expr::MetaVarExpr; use rustc_ast::token::{Delimiter, NonterminalKind, Token, TokenKind}; use rustc_ast::tokenstream::{DelimSpacing, DelimSpan}; +use rustc_macros::{Decodable, Encodable}; use rustc_span::symbol::Ident; use rustc_span::Span; diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index 15193298cca..464361cb402 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -8,11 +8,13 @@ use rustc_ast::token::{self, Token, TokenKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast_pretty::pprust; use rustc_errors::{Applicability, Diag, DiagCtxt, DiagMessage}; +use rustc_macros::Subdiagnostic; use rustc_parse::parser::{Parser, Recovery}; use rustc_span::source_map::SourceMap; use rustc_span::symbol::Ident; use rustc_span::{ErrorGuaranteed, Span}; use std::borrow::Cow; +use tracing::debug; use super::macro_rules::{parser_from_cx, NoopTracker}; @@ -26,7 +28,8 @@ pub(super) fn failed_to_match_macro<'cx>( ) -> Box<dyn MacResult + 'cx> { let psess = &cx.sess.psess; - // An error occurred, try the expansion again, tracking the expansion closely for better diagnostics. + // An error occurred, try the expansion again, tracking the expansion closely for better + // diagnostics. let mut tracker = CollectTrackerAndEmitter::new(cx, sp); let try_success_result = try_match_macro(psess, name, &arg, lhses, &mut tracker); diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 7099f1b0d35..470bde232d7 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -29,6 +29,7 @@ use rustc_span::edition::Edition; use rustc_span::hygiene::Transparency; use rustc_span::symbol::{kw, sym, Ident, MacroRulesNormalizedIdent}; use rustc_span::Span; +use tracing::{debug, instrument, trace, trace_span}; use std::borrow::Cow; use std::collections::hash_map::Entry; @@ -156,8 +157,8 @@ pub(super) trait Tracker<'matcher> { /// This is called before trying to match next MatcherLoc on the current token. fn before_match_loc(&mut self, _parser: &TtParser, _matcher: &'matcher MatcherLoc) {} - /// This is called after an arm has been parsed, either successfully or unsuccessfully. When this is called, - /// `before_match_loc` was called at least once (with a `MatcherLoc::Eof`). + /// This is called after an arm has been parsed, either successfully or unsuccessfully. When + /// this is called, `before_match_loc` was called at least once (with a `MatcherLoc::Eof`). fn after_arm(&mut self, _result: &NamedParseResult<Self::Failure>) {} /// For tracing. @@ -168,7 +169,8 @@ pub(super) trait Tracker<'matcher> { } } -/// A noop tracker that is used in the hot path of the expansion, has zero overhead thanks to monomorphization. +/// A noop tracker that is used in the hot path of the expansion, has zero overhead thanks to +/// monomorphization. pub(super) struct NoopTracker; impl<'matcher> Tracker<'matcher> for NoopTracker { @@ -491,7 +493,7 @@ pub fn compile_declarative_macro( .pop() .unwrap(); // We don't handle errors here, the driver will abort - // after parsing/expansion. we can report every error in every macro this way. + // after parsing/expansion. We can report every error in every macro this way. check_emission(check_lhs_nt_follows(sess, def, &tt)); return tt; } @@ -527,7 +529,7 @@ pub fn compile_declarative_macro( check_emission(check_rhs(sess, rhs)); } - // don't abort iteration early, so that errors for multiple lhses can be reported + // Don't abort iteration early, so that errors for multiple lhses can be reported. for lhs in &lhses { check_emission(check_lhs_no_empty_seq(sess, slice::from_ref(lhs))); } diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index 81e1de5b095..8239cfd46cb 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -3,6 +3,7 @@ use rustc_ast::tokenstream::{RefTokenTreeCursor, TokenStream, TokenTree}; use rustc_ast::{LitIntType, LitKind}; use rustc_ast_pretty::pprust; use rustc_errors::{Applicability, PResult}; +use rustc_macros::{Decodable, Encodable}; use rustc_session::parse::ParseSess; use rustc_span::symbol::Ident; use rustc_span::Span; diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index dad83984c8b..011aa95c8a1 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -39,26 +39,32 @@ impl MutVisitor for Marker { } /// An iterator over the token trees in a delimited token tree (`{ ... }`) or a sequence (`$(...)`). -enum Frame<'a> { - Delimited { - tts: &'a [mbe::TokenTree], - idx: usize, - delim: Delimiter, - span: DelimSpan, - spacing: DelimSpacing, - }, - Sequence { - tts: &'a [mbe::TokenTree], - idx: usize, - sep: Option<Token>, - kleene_op: KleeneOp, - }, +struct Frame<'a> { + tts: &'a [mbe::TokenTree], + idx: usize, + kind: FrameKind, +} + +enum FrameKind { + Delimited { delim: Delimiter, span: DelimSpan, spacing: DelimSpacing }, + Sequence { sep: Option<Token>, kleene_op: KleeneOp }, } impl<'a> Frame<'a> { - /// Construct a new frame around the delimited set of tokens. - fn new(src: &'a mbe::Delimited, span: DelimSpan, spacing: DelimSpacing) -> Frame<'a> { - Frame::Delimited { tts: &src.tts, idx: 0, delim: src.delim, span, spacing } + fn new_delimited(src: &'a mbe::Delimited, span: DelimSpan, spacing: DelimSpacing) -> Frame<'a> { + Frame { + tts: &src.tts, + idx: 0, + kind: FrameKind::Delimited { delim: src.delim, span, spacing }, + } + } + + fn new_sequence( + src: &'a mbe::SequenceRepetition, + sep: Option<Token>, + kleene_op: KleeneOp, + ) -> Frame<'a> { + Frame { tts: &src.tts, idx: 0, kind: FrameKind::Sequence { sep, kleene_op } } } } @@ -66,13 +72,9 @@ impl<'a> Iterator for Frame<'a> { type Item = &'a mbe::TokenTree; fn next(&mut self) -> Option<&'a mbe::TokenTree> { - match self { - Frame::Delimited { tts, idx, .. } | Frame::Sequence { tts, idx, .. } => { - let res = tts.get(*idx); - *idx += 1; - res - } - } + let res = self.tts.get(self.idx); + self.idx += 1; + res } } @@ -111,13 +113,16 @@ pub(super) fn transcribe<'a>( // We descend into the RHS (`src`), expanding things as we go. This stack contains the things // we have yet to expand/are still expanding. We start the stack off with the whole RHS. The // choice of spacing values doesn't matter. - let mut stack: SmallVec<[Frame<'_>; 1]> = - smallvec![Frame::new(src, src_span, DelimSpacing::new(Spacing::Alone, Spacing::Alone))]; + let mut stack: SmallVec<[Frame<'_>; 1]> = smallvec![Frame::new_delimited( + src, + src_span, + DelimSpacing::new(Spacing::Alone, Spacing::Alone) + )]; // As we descend in the RHS, we will need to be able to match nested sequences of matchers. // `repeats` keeps track of where we are in matching at each level, with the last element being // the most deeply nested sequence. This is used as a stack. - let mut repeats = Vec::new(); + let mut repeats: Vec<(usize, usize)> = Vec::new(); // `result` contains resulting token stream from the TokenTree we just finished processing. At // the end, this will contain the full result of transcription, but at arbitrary points during @@ -142,11 +147,12 @@ pub(super) fn transcribe<'a>( // Otherwise, if we have just reached the end of a sequence and we can keep repeating, // go back to the beginning of the sequence. - if let Frame::Sequence { idx, sep, .. } = stack.last_mut().unwrap() { + let frame = stack.last_mut().unwrap(); + if let FrameKind::Sequence { sep, .. } = &frame.kind { let (repeat_idx, repeat_len) = repeats.last_mut().unwrap(); *repeat_idx += 1; if repeat_idx < repeat_len { - *idx = 0; + frame.idx = 0; if let Some(sep) = sep { result.push(TokenTree::Token(sep.clone(), Spacing::Alone)); } @@ -157,16 +163,16 @@ pub(super) fn transcribe<'a>( // We are done with the top of the stack. Pop it. Depending on what it was, we do // different things. Note that the outermost item must be the delimited, wrapped RHS // that was passed in originally to `transcribe`. - match stack.pop().unwrap() { + match stack.pop().unwrap().kind { // Done with a sequence. Pop from repeats. - Frame::Sequence { .. } => { + FrameKind::Sequence { .. } => { repeats.pop(); } // We are done processing a Delimited. If this is the top-level delimited, we are // done. Otherwise, we unwind the result_stack to append what we have produced to // any previous results. - Frame::Delimited { delim, span, mut spacing, .. } => { + FrameKind::Delimited { delim, span, mut spacing, .. } => { // Hack to force-insert a space after `]` in certain case. // See discussion of the `hex-literal` crate in #114571. if delim == Delimiter::Bracket { @@ -192,7 +198,7 @@ pub(super) fn transcribe<'a>( // We are descending into a sequence. We first make sure that the matchers in the RHS // and the matches in `interp` have the same shape. Otherwise, either the caller or the // macro writer has made a mistake. - seq @ mbe::TokenTree::Sequence(_, delimited) => { + seq @ mbe::TokenTree::Sequence(_, seq_rep) => { match lockstep_iter_size(seq, interp, &repeats) { LockstepIterSize::Unconstrained => { return Err(cx @@ -233,12 +239,11 @@ pub(super) fn transcribe<'a>( // The first time we encounter the sequence we push it to the stack. It // then gets reused (see the beginning of the loop) until we are done // repeating. - stack.push(Frame::Sequence { - idx: 0, - sep: seq.separator.clone(), - tts: &delimited.tts, - kleene_op: seq.kleene.op, - }); + stack.push(Frame::new_sequence( + seq_rep, + seq.separator.clone(), + seq.kleene.op, + )); } } } @@ -294,13 +299,7 @@ pub(super) fn transcribe<'a>( // the previous results (from outside the Delimited). mbe::TokenTree::Delimited(mut span, spacing, delimited) => { mut_visit::visit_delim_span(&mut span, &mut marker); - stack.push(Frame::Delimited { - tts: &delimited.tts, - delim: delimited.delim, - idx: 0, - span, - spacing: *spacing, - }); + stack.push(Frame::new_delimited(delimited, span, *spacing)); result_stack.push(mem::take(&mut result)); } @@ -358,10 +357,13 @@ fn maybe_use_metavar_location( ) -> TokenTree { let undelimited_seq = matches!( stack.last(), - Some(Frame::Sequence { + Some(Frame { tts: [_], - sep: None, - kleene_op: KleeneOp::ZeroOrMore | KleeneOp::OneOrMore, + kind: FrameKind::Sequence { + sep: None, + kleene_op: KleeneOp::ZeroOrMore | KleeneOp::OneOrMore, + .. + }, .. }) ); diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 581d71875bd..7026425e167 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -9,7 +9,7 @@ use rustc_span::DUMMY_SP; use smallvec::{smallvec, SmallVec}; use thin_vec::ThinVec; -pub fn placeholder( +pub(crate) fn placeholder( kind: AstFragmentKind, id: ast::NodeId, vis: Option<ast::Visibility>, diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index de2bd60ffad..943cc632857 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -60,7 +60,7 @@ declare_features! ( /// Allows the definition of associated constants in `trait` or `impl` blocks. (accepted, associated_consts, "1.20.0", Some(29646)), /// Allows the user of associated type bounds. - (accepted, associated_type_bounds, "CURRENT_RUSTC_VERSION", Some(52662)), + (accepted, associated_type_bounds, "1.79.0", Some(52662)), /// Allows using associated `type`s in `trait`s. (accepted, associated_types, "1.0.0", None), /// Allows free and inherent `async fn`s, `async` blocks, and `<expr>.await` expressions. @@ -99,7 +99,7 @@ declare_features! ( /// Allows using the CMPXCHG16B target feature. (accepted, cmpxchg16b_target_feature, "1.69.0", Some(44839)), /// Allows use of the `#[collapse_debuginfo]` attribute. - (accepted, collapse_debuginfo, "CURRENT_RUSTC_VERSION", Some(100758)), + (accepted, collapse_debuginfo, "1.79.0", Some(100758)), /// Allows usage of the `compile_error!` macro. (accepted, compile_error, "1.20.0", Some(40872)), /// Allows `impl Trait` in function return types. @@ -208,13 +208,13 @@ declare_features! ( /// Allows referencing `Self` and projections in impl-trait. (accepted, impl_trait_projections, "1.74.0", Some(103532)), /// Allows using imported `main` function - (accepted, imported_main, "CURRENT_RUSTC_VERSION", Some(28937)), + (accepted, imported_main, "1.79.0", Some(28937)), /// Allows using `a..=b` and `..=b` as inclusive range syntaxes. (accepted, inclusive_range_syntax, "1.26.0", Some(28237)), /// Allows inferring outlives requirements (RFC 2093). (accepted, infer_outlives_requirements, "1.30.0", Some(44493)), /// Allow anonymous constants from an inline `const` block - (accepted, inline_const, "CURRENT_RUSTC_VERSION", Some(76001)), + (accepted, inline_const, "1.79.0", Some(76001)), /// Allows irrefutable patterns in `if let` and `while let` statements (RFC 2086). (accepted, irrefutable_let_patterns, "1.33.0", Some(44495)), /// Allows `#[instruction_set(_)]` attribute. @@ -360,7 +360,7 @@ declare_features! ( /// Allows macros to appear in the type position. (accepted, type_macros, "1.13.0", Some(27245)), /// Allows using type privacy lints (`private_interfaces`, `private_bounds`, `unnameable_types`). - (accepted, type_privacy_lints, "CURRENT_RUSTC_VERSION", Some(48054)), + (accepted, type_privacy_lints, "1.79.0", Some(48054)), /// Allows `const _: TYPE = VALUE`. (accepted, underscore_const_names, "1.37.0", Some(54912)), /// Allows `use path as _;` and `extern crate c as _;`. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 9d3aac66c41..9c33cc8ed0b 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -396,10 +396,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), // Entry point: - gated!( - unix_sigpipe, Normal, template!(NameValueStr: "inherit|sig_ign|sig_dfl"), ErrorFollowing, - EncodeCrossCrate::Yes, experimental!(unix_sigpipe) - ), ungated!(start, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No), ungated!(no_start, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No), ungated!(no_main, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 132e2ddee29..fe50499db76 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -216,7 +216,7 @@ declare_features! ( /// Set the maximum pattern complexity allowed (not limited by default). (internal, pattern_complexity, "1.78.0", None), /// Allows using pattern types. - (internal, pattern_types, "CURRENT_RUSTC_VERSION", Some(123646)), + (internal, pattern_types, "1.79.0", Some(123646)), /// Allows using `#[prelude_import]` on glob `use` items. (internal, prelude_import, "1.2.0", None), /// Used to identify crates that contain the profiler runtime. @@ -384,7 +384,7 @@ declare_features! ( /// Allows `cfg(target_thread_local)`. (unstable, cfg_target_thread_local, "1.7.0", Some(29594)), /// Allows the use of `#[cfg(ub_checks)` to check if UB checks are enabled. - (unstable, cfg_ub_checks, "CURRENT_RUSTC_VERSION", Some(123499)), + (unstable, cfg_ub_checks, "1.79.0", Some(123499)), /// Allow conditional compilation depending on rust version (unstable, cfg_version, "1.45.0", Some(64796)), /// Allows to use the `#[cfi_encoding = ""]` attribute. @@ -439,7 +439,7 @@ declare_features! ( /// Allows having using `suggestion` in the `#[deprecated]` attribute. (unstable, deprecated_suggestion, "1.61.0", Some(94785)), /// Allows deref patterns. - (incomplete, deref_patterns, "CURRENT_RUSTC_VERSION", Some(87121)), + (incomplete, deref_patterns, "1.79.0", Some(87121)), /// Controls errors in trait implementations. (unstable, do_not_recommend, "1.67.0", Some(51992)), /// Tells rustdoc to automatically generate `#[doc(cfg(...))]`. @@ -530,9 +530,9 @@ declare_features! ( /// Allows the `#[must_not_suspend]` attribute. (unstable, must_not_suspend, "1.57.0", Some(83310)), /// Make `mut` not reset the binding mode on edition >= 2024. - (incomplete, mut_preserve_binding_mode_2024, "CURRENT_RUSTC_VERSION", Some(123076)), + (incomplete, mut_preserve_binding_mode_2024, "1.79.0", Some(123076)), /// Allows `mut ref` and `mut ref mut` identifier patterns. - (incomplete, mut_ref, "CURRENT_RUSTC_VERSION", Some(123076)), + (incomplete, mut_ref, "1.79.0", Some(123076)), /// Allows using `#[naked]` on functions. (unstable, naked_functions, "1.9.0", Some(90957)), /// Allows specifying the as-needed link modifier @@ -564,17 +564,17 @@ declare_features! ( /// Allows using `#[optimize(X)]`. (unstable, optimize_attribute, "1.34.0", Some(54882)), /// Allows postfix match `expr.match { ... }` - (unstable, postfix_match, "CURRENT_RUSTC_VERSION", Some(121618)), + (unstable, postfix_match, "1.79.0", Some(121618)), /// Allows `use<'a, 'b, A, B>` in `impl use<...> Trait` for precise capture of generic args. - (incomplete, precise_capturing, "CURRENT_RUSTC_VERSION", Some(123432)), + (incomplete, precise_capturing, "1.79.0", Some(123432)), /// Allows macro attributes on expressions, statements and non-inline modules. (unstable, proc_macro_hygiene, "1.30.0", Some(54727)), /// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions. (unstable, raw_ref_op, "1.41.0", Some(64490)), /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024. - (incomplete, ref_pat_eat_one_layer_2024, "CURRENT_RUSTC_VERSION", Some(123076)), + (incomplete, ref_pat_eat_one_layer_2024, "1.79.0", Some(123076)), /// Allows `&` and `&mut` patterns to consume match-ergonomics-inserted references. - (incomplete, ref_pat_everywhere, "CURRENT_RUSTC_VERSION", Some(123076)), + (incomplete, ref_pat_everywhere, "1.79.0", Some(123076)), /// Allows using the `#[register_tool]` attribute. (unstable, register_tool, "1.41.0", Some(66079)), /// Allows the `#[repr(i128)]` attribute for enums. @@ -619,8 +619,6 @@ declare_features! ( /// Allows creation of instances of a struct by moving fields that have /// not changed from prior instances of the same struct (RFC #2528) (unstable, type_changing_struct_update, "1.58.0", Some(86555)), - /// Enables rustc to generate code that instructs libstd to NOT ignore SIGPIPE. - (unstable, unix_sigpipe, "1.65.0", Some(97889)), /// Allows unnamed fields of struct and union type (incomplete, unnamed_fields, "1.74.0", Some(49804)), /// Allows unsized fn parameters. diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 37d9b2ffd6a..649a08b6972 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -5,7 +5,7 @@ use rustc_ast as ast; use rustc_ast::NodeId; use rustc_data_structures::stable_hasher::ToStableHashKey; use rustc_data_structures::unord::UnordMap; -use rustc_macros::HashStable_Generic; +use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::kw; diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index cd5da279a26..35833e258d5 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -7,14 +7,14 @@ pub use crate::def_id::DefPathHash; use crate::def_id::{CrateNum, DefIndex, LocalDefId, StableCrateId, CRATE_DEF_INDEX, LOCAL_CRATE}; use crate::def_path_hash_map::DefPathHashMap; - use rustc_data_structures::stable_hasher::{Hash64, StableHasher}; use rustc_data_structures::unord::UnordMap; use rustc_index::IndexVec; +use rustc_macros::{Decodable, Encodable}; use rustc_span::symbol::{kw, sym, Symbol}; - use std::fmt::{self, Write}; use std::hash::Hash; +use tracing::{debug, instrument}; /// The `DefPathTable` maps `DefIndex`es to `DefKey`s and vice versa. /// Internally the `DefPathTable` holds a tree of `DefKey`s, where each `DefKey` diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 1646ea50fb0..244c479120d 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3,7 +3,6 @@ use crate::def_id::{DefId, LocalDefIdMap}; pub(crate) use crate::hir_id::{HirId, ItemLocalId, ItemLocalMap, OwnerId}; use crate::intravisit::FnKind; use crate::LangItem; - use rustc_ast as ast; use rustc_ast::util::parser::ExprPrecedence; use rustc_ast::{Attribute, FloatTy, IntTy, Label, LitKind, TraitObjectSyntax, UintTy}; @@ -13,7 +12,7 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::sorted_map::SortedMap; use rustc_index::IndexVec; -use rustc_macros::HashStable_Generic; +use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -21,9 +20,9 @@ use rustc_span::ErrorGuaranteed; use rustc_span::{def_id::LocalDefId, BytePos, Span, DUMMY_SP}; use rustc_target::asm::InlineAsmRegOrRegClass; use rustc_target::spec::abi::Abi; - use smallvec::SmallVec; use std::fmt; +use tracing::debug; #[derive(Debug, Copy, Clone, HashStable_Generic)] pub struct Lifetime { @@ -230,9 +229,8 @@ impl<'hir> PathSegment<'hir> { } #[derive(Clone, Copy, Debug, HashStable_Generic)] -pub struct ConstArg { - pub value: AnonConst, - pub span: Span, +pub struct ConstArg<'hir> { + pub value: &'hir AnonConst, /// Indicates whether this comes from a `~const` desugaring. pub is_desugared_from_effects: bool, } @@ -253,7 +251,7 @@ impl InferArg { pub enum GenericArg<'hir> { Lifetime(&'hir Lifetime), Type(&'hir Ty<'hir>), - Const(ConstArg), + Const(ConstArg<'hir>), Infer(InferArg), } @@ -262,7 +260,7 @@ impl GenericArg<'_> { match self { GenericArg::Lifetime(l) => l.ident.span, GenericArg::Type(t) => t.span, - GenericArg::Const(c) => c.span, + GenericArg::Const(c) => c.value.span, GenericArg::Infer(i) => i.span, } } @@ -491,7 +489,7 @@ pub enum GenericParamKind<'hir> { Const { ty: &'hir Ty<'hir>, /// Optional default value for the const generic param - default: Option<AnonConst>, + default: Option<&'hir AnonConst>, is_host_effect: bool, }, } @@ -1563,12 +1561,12 @@ impl fmt::Display for ConstContext { pub type Lit = Spanned<LitKind>; #[derive(Copy, Clone, Debug, HashStable_Generic)] -pub enum ArrayLen { +pub enum ArrayLen<'hir> { Infer(InferArg), - Body(AnonConst), + Body(&'hir AnonConst), } -impl ArrayLen { +impl ArrayLen<'_> { pub fn hir_id(&self) -> HirId { match self { ArrayLen::Infer(InferArg { hir_id, .. }) | ArrayLen::Body(AnonConst { hir_id, .. }) => { @@ -1591,6 +1589,7 @@ pub struct AnonConst { pub hir_id: HirId, pub def_id: LocalDefId, pub body: BodyId, + pub span: Span, } /// An inline constant expression `const { something }`. @@ -2003,7 +2002,7 @@ pub enum ExprKind<'hir> { /// /// E.g., `[1; 5]`. The first expression is the element /// to be repeated; the second is the number of times to repeat it. - Repeat(&'hir Expr<'hir>, ArrayLen), + Repeat(&'hir Expr<'hir>, ArrayLen<'hir>), /// A suspension point for coroutines (i.e., `yield <expr>`). Yield(&'hir Expr<'hir>, YieldSource), @@ -2383,7 +2382,7 @@ pub struct TypeBinding<'hir> { #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum Term<'hir> { Ty(&'hir Ty<'hir>), - Const(AnonConst), + Const(&'hir AnonConst), } impl<'hir> From<&'hir Ty<'hir>> for Term<'hir> { @@ -2392,8 +2391,8 @@ impl<'hir> From<&'hir Ty<'hir>> for Term<'hir> { } } -impl<'hir> From<AnonConst> for Term<'hir> { - fn from(c: AnonConst) -> Self { +impl<'hir> From<&'hir AnonConst> for Term<'hir> { + fn from(c: &'hir AnonConst) -> Self { Term::Const(c) } } @@ -2684,7 +2683,7 @@ pub enum TyKind<'hir> { /// A variable length slice (i.e., `[T]`). Slice(&'hir Ty<'hir>), /// A fixed length array (i.e., `[T; n]`). - Array(&'hir Ty<'hir>, ArrayLen), + Array(&'hir Ty<'hir>, ArrayLen<'hir>), /// A raw pointer (i.e., `*const T` or `*mut T`). Ptr(MutTy<'hir>), /// A reference (i.e., `&'a T` or `&'a mut T`). @@ -2713,7 +2712,7 @@ pub enum TyKind<'hir> { /// where `Bound` is a trait or a lifetime. TraitObject(&'hir [PolyTraitRef<'hir>], &'hir Lifetime, TraitObjectSyntax), /// Unused for now. - Typeof(AnonConst), + Typeof(&'hir AnonConst), /// `TyKind::Infer` means the type should be inferred instead of it having been /// specified. This can appear anywhere in a type. Infer, @@ -2746,10 +2745,10 @@ pub enum InlineAsmOperand<'hir> { out_expr: Option<&'hir Expr<'hir>>, }, Const { - anon_const: AnonConst, + anon_const: &'hir AnonConst, }, SymFn { - anon_const: AnonConst, + anon_const: &'hir AnonConst, }, SymStatic { path: QPath<'hir>, @@ -2951,7 +2950,7 @@ pub struct Variant<'hir> { /// Fields and constructor id of the variant. pub data: VariantData<'hir>, /// Explicit discriminant (e.g., `Foo = 1`). - pub disr_expr: Option<AnonConst>, + pub disr_expr: Option<&'hir AnonConst>, /// Span pub span: Span, } @@ -3480,15 +3479,13 @@ impl<'hir> OwnerNode<'hir> { } } - // Span by reference to pass to `Node::Err`. - #[allow(rustc::pass_by_value)] - pub fn span(&self) -> &'hir Span { + pub fn span(&self) -> Span { match self { OwnerNode::Item(Item { span, .. }) | OwnerNode::ForeignItem(ForeignItem { span, .. }) | OwnerNode::ImplItem(ImplItem { span, .. }) - | OwnerNode::TraitItem(TraitItem { span, .. }) => span, - OwnerNode::Crate(Mod { spans: ModSpans { inner_span, .. }, .. }) => inner_span, + | OwnerNode::TraitItem(TraitItem { span, .. }) => *span, + OwnerNode::Crate(Mod { spans: ModSpans { inner_span, .. }, .. }) => *inner_span, OwnerNode::Synthetic => unreachable!(), } } @@ -3633,9 +3630,7 @@ pub enum Node<'hir> { PreciseCapturingNonLifetimeArg(&'hir PreciseCapturingNonLifetimeArg), // Created by query feeding Synthetic, - // Span by reference to minimize `Node`'s size - #[allow(rustc::pass_by_value)] - Err(&'hir Span), + Err(Span), } impl<'hir> Node<'hir> { @@ -3863,6 +3858,7 @@ impl<'hir> Node<'hir> { #[cfg(target_pointer_width = "64")] mod size_asserts { use super::*; + use rustc_data_structures::static_assert_size; // tidy-alphabetical-start static_assert_size!(Block<'_>, 48); static_assert_size!(Body<'_>, 24); @@ -3871,7 +3867,7 @@ mod size_asserts { static_assert_size!(FnDecl<'_>, 40); static_assert_size!(ForeignItem<'_>, 72); static_assert_size!(ForeignItemKind<'_>, 40); - static_assert_size!(GenericArg<'_>, 32); + static_assert_size!(GenericArg<'_>, 24); static_assert_size!(GenericBound<'_>, 48); static_assert_size!(Generics<'_>, 56); static_assert_size!(Impl<'_>, 80); diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs index 0341a482fa8..ac487469507 100644 --- a/compiler/rustc_hir/src/hir_id.rs +++ b/compiler/rustc_hir/src/hir_id.rs @@ -1,5 +1,6 @@ use crate::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_ID}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey}; +use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::{def_id::DefPathHash, HashStableContext}; use std::fmt::{self, Debug}; diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index cd9f9ff9109..fa89a4a44ef 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -338,7 +338,7 @@ pub trait Visitor<'v>: Sized { fn visit_pat_field(&mut self, f: &'v PatField<'v>) -> Self::Result { walk_pat_field(self, f) } - fn visit_array_length(&mut self, len: &'v ArrayLen) -> Self::Result { + fn visit_array_length(&mut self, len: &'v ArrayLen<'v>) -> Self::Result { walk_array_len(self, len) } fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result { @@ -703,7 +703,7 @@ pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<' visitor.visit_pat(field.pat) } -pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen) -> V::Result { +pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen<'v>) -> V::Result { match len { // FIXME: Use `visit_infer` here. ArrayLen::Infer(InferArg { hir_id, span: _ }) => visitor.visit_id(*hir_id), diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 6aee1183a10..e870a04127a 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -12,7 +12,7 @@ use crate::{MethodKind, Target}; use rustc_ast as ast; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_macros::HashStable_Generic; +use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::Span; @@ -56,7 +56,7 @@ macro_rules! language_item_table { $( $(#[$attr:meta])* $variant:ident, $module:ident :: $name:ident, $method:ident, $target:expr, $generics:expr; )* ) => { - enum_from_u32! { + rustc_data_structures::enum_from_u32! { /// A representation of all the valid lang items in Rust. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable)] pub enum LangItem { diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index c5c4075c6ba..600a0dce03b 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -10,15 +10,6 @@ #![feature(variant_count)] #![allow(internal_features)] -#[macro_use] -extern crate rustc_macros; - -#[macro_use] -extern crate tracing; - -#[macro_use] -extern crate rustc_data_structures; - extern crate self as rustc_hir; mod arena; diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 06b5ee299b8..3edea0191fa 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -201,6 +201,12 @@ hir_analysis_inherent_ty_outside_relevant = cannot define inherent `impl` for a .help = consider moving this inherent impl into the crate defining the type if possible .span_help = alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items +hir_analysis_invalid_receiver_ty = invalid `self` parameter type: `{$receiver_ty}` + .note = type of `self` must be `Self` or a type that dereferences to it + +hir_analysis_invalid_receiver_ty_help = + consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) + hir_analysis_invalid_union_field = field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union .note = union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` @@ -486,13 +492,13 @@ hir_analysis_transparent_non_zero_sized_enum = the variant of a transparent {$de hir_analysis_ty_of_assoc_const_binding_note = `{$assoc_const}` has type `{$ty}` -hir_analysis_ty_param_first_local = type parameter `{$param_ty}` must be covered by another type when it appears before the first local type (`{$local_type}`) - .label = type parameter `{$param_ty}` must be covered by another type when it appears before the first local type (`{$local_type}`) +hir_analysis_ty_param_first_local = type parameter `{$param}` must be covered by another type when it appears before the first local type (`{$local_type}`) + .label = type parameter `{$param}` must be covered by another type when it appears before the first local type (`{$local_type}`) .note = implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type .case_note = in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last -hir_analysis_ty_param_some = type parameter `{$param_ty}` must be used as the type parameter for some local type (e.g., `MyStruct<{$param_ty}>`) - .label = type parameter `{$param_ty}` must be used as the type parameter for some local type +hir_analysis_ty_param_some = type parameter `{$param}` must be used as the type parameter for some local type (e.g., `MyStruct<{$param}>`) + .label = type parameter `{$param}` must be used as the type parameter for some local type .note = implementing a foreign trait is only possible if at least one of the types for which it is implemented is local .only_note = only traits defined in the current crate can be implemented for a type parameter diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs index f2ceb470264..f101c595bdf 100644 --- a/compiler/rustc_hir_analysis/src/autoderef.rs +++ b/compiler/rustc_hir_analysis/src/autoderef.rs @@ -1,6 +1,6 @@ use crate::errors::AutoDerefReachedRecursionLimit; +use crate::traits; use crate::traits::query::evaluate_obligation::InferCtxtExt; -use crate::traits::{self, TraitEngine, TraitEngineExt}; use rustc_infer::infer::InferCtxt; use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -8,7 +8,7 @@ use rustc_session::Limit; use rustc_span::def_id::LocalDefId; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::Span; -use rustc_trait_selection::traits::StructurallyNormalizeExt; +use rustc_trait_selection::traits::ObligationCtxt; #[derive(Copy, Clone, Debug)] pub enum AutoderefKind { @@ -167,25 +167,19 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { &self, ty: Ty<'tcx>, ) -> Option<(Ty<'tcx>, Vec<traits::PredicateObligation<'tcx>>)> { - let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(self.infcx); - - let cause = traits::ObligationCause::misc(self.span, self.body_id); - let normalized_ty = match self - .infcx - .at(&cause, self.param_env) - .structurally_normalize(ty, &mut *fulfill_cx) - { - Ok(normalized_ty) => normalized_ty, - Err(errors) => { - // 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!(?errors, "encountered errors while fulfilling"); - return None; - } + let ocx = ObligationCtxt::new(self.infcx); + let Ok(normalized_ty) = ocx.structurally_normalize( + &traits::ObligationCause::misc(self.span, self.body_id), + self.param_env, + ty, + ) else { + // We shouldn't have errors here, except for evaluate/fulfill mismatches, + // but that's not a reason for an ICE (`predicate_may_hold` is conservative + // by design). + // FIXME(-Znext-solver): This *actually* shouldn't happen then. + return None; }; - - let errors = fulfill_cx.select_where_possible(self.infcx); + let errors = ocx.select_where_possible(); if !errors.is_empty() { // This shouldn't happen, except for evaluate/fulfill mismatches, // but that's not a reason for an ICE (`predicate_may_hold` is conservative @@ -194,7 +188,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { return None; } - Some((normalized_ty, fulfill_cx.pending_obligations())) + Some((normalized_ty, ocx.into_pending_obligations())) } /// Returns the final type we ended up with, which may be an inference diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs index aafb5c1c0b4..5562b81871f 100644 --- a/compiler/rustc_hir_analysis/src/bounds.rs +++ b/compiler/rustc_hir_analysis/src/bounds.rs @@ -23,7 +23,7 @@ use rustc_span::Span; /// include the self type (e.g., `trait_bounds`) but in others we do not #[derive(Default, PartialEq, Eq, Clone, Debug)] pub struct Bounds<'tcx> { - pub clauses: Vec<(ty::Clause<'tcx>, Span)>, + clauses: Vec<(ty::Clause<'tcx>, Span)>, } impl<'tcx> Bounds<'tcx> { diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 74324c8695b..eb1fa1baecc 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -208,11 +208,11 @@ pub fn check_intrinsic_type( Ty::new_tup(tcx, &[param(0), tcx.types.bool]), ), "load" => (1, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)), - "store" => (1, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], Ty::new_unit(tcx)), + "store" => (1, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], tcx.types.unit), "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" | "min" | "umax" | "umin" => (1, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], param(0)), - "fence" | "singlethreadfence" => (0, Vec::new(), Ty::new_unit(tcx)), + "fence" | "singlethreadfence" => (0, Vec::new(), tcx.types.unit), op => { tcx.dcx().emit_err(UnrecognizedAtomicOperation { span, op }); return; @@ -224,7 +224,7 @@ pub fn check_intrinsic_type( let (n_tps, n_cts, inputs, output) = match intrinsic_name { sym::abort => (0, 0, vec![], tcx.types.never), sym::unreachable => (0, 0, vec![], tcx.types.never), - sym::breakpoint => (0, 0, vec![], Ty::new_unit(tcx)), + sym::breakpoint => (0, 0, vec![], tcx.types.unit), sym::size_of | sym::pref_align_of | sym::min_align_of | sym::variant_count => { (1, 0, vec![], tcx.types.usize) } @@ -235,14 +235,14 @@ pub fn check_intrinsic_type( sym::caller_location => (0, 0, vec![], tcx.caller_location_ty()), sym::assert_inhabited | sym::assert_zero_valid - | sym::assert_mem_uninitialized_valid => (1, 0, vec![], Ty::new_unit(tcx)), - sym::forget => (1, 0, vec![param(0)], Ty::new_unit(tcx)), + | sym::assert_mem_uninitialized_valid => (1, 0, vec![], tcx.types.unit), + sym::forget => (1, 0, vec![param(0)], tcx.types.unit), sym::transmute | sym::transmute_unchecked => (2, 0, vec![param(0)], param(1)), sym::prefetch_read_data | sym::prefetch_write_data | sym::prefetch_read_instruction | sym::prefetch_write_instruction => { - (1, 0, vec![Ty::new_imm_ptr(tcx, param(0)), tcx.types.i32], Ty::new_unit(tcx)) + (1, 0, vec![Ty::new_imm_ptr(tcx, param(0)), tcx.types.i32], tcx.types.unit) } sym::needs_drop => (1, 0, vec![], tcx.types.bool), @@ -270,7 +270,7 @@ pub fn check_intrinsic_type( Ty::new_mut_ptr(tcx, param(0)), tcx.types.usize, ], - Ty::new_unit(tcx), + tcx.types.unit, ), sym::volatile_copy_memory | sym::volatile_copy_nonoverlapping_memory => ( 1, @@ -280,7 +280,7 @@ pub fn check_intrinsic_type( Ty::new_imm_ptr(tcx, param(0)), tcx.types.usize, ], - Ty::new_unit(tcx), + tcx.types.unit, ), sym::compare_bytes => { let byte_ptr = Ty::new_imm_ptr(tcx, tcx.types.u8); @@ -290,7 +290,7 @@ pub fn check_intrinsic_type( 1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), tcx.types.u8, tcx.types.usize], - Ty::new_unit(tcx), + tcx.types.unit, ), sym::sqrtf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16), @@ -409,7 +409,7 @@ pub fn check_intrinsic_type( (1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)) } sym::volatile_store | sym::unaligned_volatile_store => { - (1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], Ty::new_unit(tcx)) + (1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], tcx.types.unit) } sym::ctpop | sym::ctlz | sym::ctlz_nonzero | sym::cttz | sym::cttz_nonzero => { @@ -440,7 +440,7 @@ pub fn check_intrinsic_type( 0, 1, vec![Ty::new_mut_ptr(tcx, tcx.types.u8), tcx.types.usize, tcx.types.usize], - Ty::new_unit(tcx), + tcx.types.unit, ), sym::ptr_offset_from => ( @@ -477,16 +477,16 @@ pub fn check_intrinsic_type( | sym::frem_algebraic => (1, 0, vec![param(0), param(0)], param(0)), sym::float_to_int_unchecked => (2, 0, vec![param(0)], param(1)), - sym::assume => (0, 1, vec![tcx.types.bool], Ty::new_unit(tcx)), + sym::assume => (0, 1, vec![tcx.types.bool], tcx.types.unit), sym::likely => (0, 1, vec![tcx.types.bool], tcx.types.bool), sym::unlikely => (0, 1, vec![tcx.types.bool], tcx.types.bool), sym::read_via_copy => (1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)), sym::write_via_move => { - (1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], Ty::new_unit(tcx)) + (1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], tcx.types.unit) } - sym::typed_swap => (1, 1, vec![Ty::new_mut_ptr(tcx, param(0)); 2], Ty::new_unit(tcx)), + sym::typed_swap => (1, 1, vec![Ty::new_mut_ptr(tcx, param(0)); 2], tcx.types.unit), sym::discriminant_value => { let assoc_items = tcx.associated_item_def_ids( @@ -511,14 +511,14 @@ pub fn check_intrinsic_type( let mut_u8 = Ty::new_mut_ptr(tcx, tcx.types.u8); let try_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig( [mut_u8], - Ty::new_unit(tcx), + tcx.types.unit, false, hir::Unsafety::Normal, Abi::Rust, )); let catch_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig( [mut_u8, mut_u8], - Ty::new_unit(tcx), + tcx.types.unit, false, hir::Unsafety::Normal, Abi::Rust, @@ -532,14 +532,14 @@ pub fn check_intrinsic_type( } sym::va_start | sym::va_end => match mk_va_list_ty(hir::Mutability::Mut) { - Some((va_list_ref_ty, _)) => (0, 0, vec![va_list_ref_ty], Ty::new_unit(tcx)), + Some((va_list_ref_ty, _)) => (0, 0, vec![va_list_ref_ty], tcx.types.unit), None => bug!("`va_list` lang item needed for C-variadic intrinsics"), }, sym::va_copy => match mk_va_list_ty(hir::Mutability::Not) { Some((va_list_ref_ty, va_list_ty)) => { let va_list_ptr_ty = Ty::new_mut_ptr(tcx, va_list_ty); - (0, 0, vec![va_list_ptr_ty, va_list_ref_ty], Ty::new_unit(tcx)) + (0, 0, vec![va_list_ptr_ty, va_list_ref_ty], tcx.types.unit) } None => bug!("`va_list` lang item needed for C-variadic intrinsics"), }, @@ -550,7 +550,7 @@ pub fn check_intrinsic_type( }, sym::nontemporal_store => { - (1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], Ty::new_unit(tcx)) + (1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], tcx.types.unit) } sym::raw_eq => { @@ -570,7 +570,7 @@ pub fn check_intrinsic_type( sym::const_eval_select => (4, 1, vec![param(0), param(1), param(2)], param(3)), sym::vtable_size | sym::vtable_align => { - (0, 0, vec![Ty::new_imm_ptr(tcx, Ty::new_unit(tcx))], tcx.types.usize) + (0, 0, vec![Ty::new_imm_ptr(tcx, tcx.types.unit)], tcx.types.usize) } // This type check is not particularly useful, but the `where` bounds @@ -623,8 +623,8 @@ pub fn check_intrinsic_type( sym::simd_fma => (1, 0, vec![param(0), param(0), param(0)], param(0)), sym::simd_gather => (3, 0, vec![param(0), param(1), param(2)], param(0)), sym::simd_masked_load => (3, 0, vec![param(0), param(1), param(2)], param(2)), - sym::simd_masked_store => (3, 0, vec![param(0), param(1), param(2)], Ty::new_unit(tcx)), - sym::simd_scatter => (3, 0, vec![param(0), param(1), param(2)], Ty::new_unit(tcx)), + sym::simd_masked_store => (3, 0, vec![param(0), param(1), param(2)], tcx.types.unit), + sym::simd_scatter => (3, 0, vec![param(0), param(1), param(2)], tcx.types.unit), sym::simd_insert => (2, 0, vec![param(0), tcx.types.u32, param(1)], param(0)), sym::simd_extract => (2, 0, vec![param(0), tcx.types.u32], param(1)), sym::simd_cast diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index c26f982fa47..5b127e0bf49 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -2,6 +2,7 @@ use crate::autoderef::Autoderef; use crate::collect::CollectItemTypesVisitor; use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter}; use crate::errors; +use crate::fluent_generated as fluent; use hir::intravisit::Visitor; use rustc_ast as ast; @@ -1636,10 +1637,6 @@ fn check_fn_or_method<'tcx>( } } -const HELP_FOR_SELF_TYPE: &str = "consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, \ - `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one \ - of the previous types except `Self`)"; - #[instrument(level = "debug", skip(wfcx))] fn check_method_receiver<'tcx>( wfcx: &WfCheckingCtxt<'_, 'tcx>, @@ -1675,7 +1672,7 @@ fn check_method_receiver<'tcx>( if tcx.features().arbitrary_self_types { if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) { // Report error; `arbitrary_self_types` was enabled. - return Err(e0307(tcx, span, receiver_ty)); + return Err(tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })); } } else { if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, false) { @@ -1690,24 +1687,17 @@ fn check_method_receiver<'tcx>( the `arbitrary_self_types` feature", ), ) - .with_help(HELP_FOR_SELF_TYPE) + .with_help(fluent::hir_analysis_invalid_receiver_ty_help) .emit() } else { // Report error; would not have worked with `arbitrary_self_types`. - e0307(tcx, span, receiver_ty) + tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty }) }); } } Ok(()) } -fn e0307(tcx: TyCtxt<'_>, span: Span, receiver_ty: Ty<'_>) -> ErrorGuaranteed { - struct_span_code_err!(tcx.dcx(), span, E0307, "invalid `self` parameter type: {receiver_ty}") - .with_note("type of `self` must be `Self` or a type that dereferences to it") - .with_help(HELP_FOR_SELF_TYPE) - .emit() -} - /// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If /// `arbitrary_self_types` is enabled, `receiver_ty` must transitively deref to `self_ty`, possibly /// through a `*const/mut T` raw pointer. If the feature is not enabled, the requirements are more diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 5585d2e069c..819e0925f68 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -2,14 +2,20 @@ //! crate or pertains to a type defined in this crate. use crate::errors; + +use rustc_data_structures::fx::FxIndexSet; use rustc_errors::ErrorGuaranteed; -use rustc_hir as hir; -use rustc_middle::ty::{self, AliasKind, TyCtxt, TypeVisitableExt}; -use rustc_span::def_id::LocalDefId; -use rustc_span::Span; -use rustc_trait_selection::traits::{self, IsFirstInputType}; +use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_lint_defs::builtin::UNCOVERED_PARAM_IN_PROJECTION; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{TypeFoldable, TypeFolder, TypeSuperFoldable}; +use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; +use rustc_span::def_id::{DefId, LocalDefId}; +use rustc_trait_selection::traits::{self, IsFirstInputType, UncoveredTyParams}; +use rustc_trait_selection::traits::{OrphanCheckErr, OrphanCheckMode}; +use rustc_trait_selection::traits::{StructurallyNormalizeExt, TraitEngineExt}; -#[instrument(skip(tcx), level = "debug")] +#[instrument(level = "debug", skip(tcx))] pub(crate) fn orphan_check_impl( tcx: TyCtxt<'_>, impl_def_id: LocalDefId, @@ -17,31 +23,23 @@ pub(crate) fn orphan_check_impl( let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity(); trait_ref.error_reported()?; - let trait_def_id = trait_ref.def_id; - - match traits::orphan_check(tcx, impl_def_id.to_def_id()) { + match orphan_check(tcx, impl_def_id, OrphanCheckMode::Proper) { Ok(()) => {} - Err(err) => { - let item = tcx.hir().expect_item(impl_def_id); - let hir::ItemKind::Impl(impl_) = item.kind else { - bug!("{:?} is not an impl: {:?}", impl_def_id, item); - }; - let tr = impl_.of_trait.as_ref().unwrap(); - let sp = tcx.def_span(impl_def_id); - - emit_orphan_check_error( - tcx, - sp, - item.span, - tr.path.span, - trait_ref, - impl_.self_ty.span, - impl_.generics, - err, - )? - } + Err(err) => match orphan_check(tcx, impl_def_id, OrphanCheckMode::Compat) { + Ok(()) => match err { + OrphanCheckErr::UncoveredTyParams(uncovered_ty_params) => { + lint_uncovered_ty_params(tcx, uncovered_ty_params, impl_def_id) + } + OrphanCheckErr::NonLocalInputType(_) => { + bug!("orphanck: shouldn't've gotten non-local input tys in compat mode") + } + }, + Err(err) => return Err(emit_orphan_check_error(tcx, trait_ref, impl_def_id, err)), + }, } + let trait_def_id = trait_ref.def_id; + // In addition to the above rules, we restrict impls of auto traits // so that they can only be implemented on nominal types, such as structs, // enums or foreign types. To see why this restriction exists, consider the @@ -186,13 +184,13 @@ pub(crate) fn orphan_check_impl( // type This = T; // } // impl<T: ?Sized> AutoTrait for <T as Id>::This {} - AliasKind::Projection => "associated type", + ty::Projection => "associated type", // type Foo = (impl Sized, bool) // impl AutoTrait for Foo {} - AliasKind::Weak => "type alias", + ty::Weak => "type alias", // type Opaque = impl Trait; // impl AutoTrait for Opaque {} - AliasKind::Opaque => "opaque type", + ty::Opaque => "opaque type", // ``` // struct S<T>(T); // impl<T: ?Sized> S<T> { @@ -201,7 +199,7 @@ pub(crate) fn orphan_check_impl( // impl<T: ?Sized> AutoTrait for S<T>::This {} // ``` // FIXME(inherent_associated_types): The example code above currently leads to a cycle - AliasKind::Inherent => "associated type", + ty::Inherent => "associated type", }; (LocalImpl::Disallow { problematic_kind }, NonlocalImpl::DisallowOther) } @@ -275,34 +273,126 @@ pub(crate) fn orphan_check_impl( Ok(()) } +/// Checks the coherence orphan rules. +/// +/// `impl_def_id` should be the `DefId` of a trait impl. +/// +/// To pass, either the trait must be local, or else two conditions must be satisfied: +/// +/// 1. All type parameters in `Self` must be "covered" by some local type constructor. +/// 2. Some local type must appear in `Self`. +#[instrument(level = "debug", skip(tcx), ret)] +fn orphan_check<'tcx>( + tcx: TyCtxt<'tcx>, + impl_def_id: LocalDefId, + mode: OrphanCheckMode, +) -> Result<(), OrphanCheckErr<'tcx, FxIndexSet<DefId>>> { + // We only accept this routine to be invoked on implementations + // of a trait, not inherent implementations. + let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); + debug!(trait_ref = ?trait_ref.skip_binder()); + + // If the *trait* is local to the crate, ok. + if let Some(def_id) = trait_ref.skip_binder().def_id.as_local() { + debug!("trait {def_id:?} is local to current crate"); + return Ok(()); + } + + // (1) Instantiate all generic params with fresh inference vars. + let infcx = tcx.infer_ctxt().intercrate(true).build(); + let cause = traits::ObligationCause::dummy(); + let args = infcx.fresh_args_for_item(cause.span, impl_def_id.to_def_id()); + let trait_ref = trait_ref.instantiate(tcx, args); + + let lazily_normalize_ty = |user_ty: Ty<'tcx>| { + let ty::Alias(..) = user_ty.kind() else { return Ok(user_ty) }; + + let ocx = traits::ObligationCtxt::new(&infcx); + let ty = ocx.normalize(&cause, ty::ParamEnv::empty(), user_ty); + let ty = infcx.resolve_vars_if_possible(ty); + let errors = ocx.select_where_possible(); + if !errors.is_empty() { + return Ok(user_ty); + } + + let ty = if infcx.next_trait_solver() { + let mut fulfill_cx = <dyn traits::TraitEngine<'_>>::new(&infcx); + infcx + .at(&cause, ty::ParamEnv::empty()) + .structurally_normalize(ty, &mut *fulfill_cx) + .map(|ty| infcx.resolve_vars_if_possible(ty)) + .unwrap_or(ty) + } else { + ty + }; + + Ok(ty) + }; + + let Ok(result) = traits::orphan_check_trait_ref::<!>( + &infcx, + trait_ref, + traits::InCrate::Local { mode }, + lazily_normalize_ty, + ) else { + unreachable!() + }; + + // (2) Try to map the remaining inference vars back to generic params. + result.map_err(|err| match err { + OrphanCheckErr::UncoveredTyParams(UncoveredTyParams { uncovered, local_ty }) => { + let mut collector = + UncoveredTyParamCollector { infcx: &infcx, uncovered_params: Default::default() }; + uncovered.visit_with(&mut collector); + // FIXME(fmease): This is very likely reachable. + debug_assert!(!collector.uncovered_params.is_empty()); + + OrphanCheckErr::UncoveredTyParams(UncoveredTyParams { + uncovered: collector.uncovered_params, + local_ty, + }) + } + OrphanCheckErr::NonLocalInputType(tys) => { + let generics = tcx.generics_of(impl_def_id); + let tys = tys + .into_iter() + .map(|(ty, is_target_ty)| { + (ty.fold_with(&mut TyVarReplacer { infcx: &infcx, generics }), is_target_ty) + }) + .collect(); + OrphanCheckErr::NonLocalInputType(tys) + } + }) +} + fn emit_orphan_check_error<'tcx>( tcx: TyCtxt<'tcx>, - sp: Span, - full_impl_span: Span, - trait_span: Span, trait_ref: ty::TraitRef<'tcx>, - self_ty_span: Span, - generics: &hir::Generics<'tcx>, - err: traits::OrphanCheckErr<'tcx>, -) -> Result<!, ErrorGuaranteed> { - let self_ty = trait_ref.self_ty(); - Err(match err { + impl_def_id: LocalDefId, + err: traits::OrphanCheckErr<'tcx, FxIndexSet<DefId>>, +) -> ErrorGuaranteed { + match err { traits::OrphanCheckErr::NonLocalInputType(tys) => { - let mut diag = tcx.dcx().create_err(match self_ty.kind() { - ty::Adt(..) => errors::OnlyCurrentTraits::Outside { span: sp, note: () }, - _ if self_ty.is_primitive() => { - errors::OnlyCurrentTraits::Primitive { span: sp, note: () } + let item = tcx.hir().expect_item(impl_def_id); + let impl_ = item.expect_impl(); + let hir_trait_ref = impl_.of_trait.as_ref().unwrap(); + + let span = tcx.def_span(impl_def_id); + let mut diag = tcx.dcx().create_err(match trait_ref.self_ty().kind() { + ty::Adt(..) => errors::OnlyCurrentTraits::Outside { span, note: () }, + _ if trait_ref.self_ty().is_primitive() => { + errors::OnlyCurrentTraits::Primitive { span, note: () } } - _ => errors::OnlyCurrentTraits::Arbitrary { span: sp, note: () }, + _ => errors::OnlyCurrentTraits::Arbitrary { span, note: () }, }); for &(mut ty, is_target_ty) in &tys { let span = if matches!(is_target_ty, IsFirstInputType::Yes) { // Point at `D<A>` in `impl<A, B> for C<B> in D<A>` - self_ty_span + impl_.self_ty.span } else { // Point at `C<B>` in `impl<A, B> for C<B> in D<A>` - trait_span + hir_trait_ref.path.span }; ty = tcx.erase_regions(ty); @@ -354,12 +444,12 @@ fn emit_orphan_check_error<'tcx>( diag.subdiagnostic(tcx.dcx(), errors::OnlyCurrentTraitsOpaque { span }); } ty::RawPtr(ptr_ty, mutbl) => { - if !self_ty.has_param() { + if !trait_ref.self_ty().has_param() { diag.subdiagnostic( tcx.dcx(), errors::OnlyCurrentTraitsPointerSugg { - wrapper_span: self_ty_span, - struct_span: full_impl_span.shrink_to_lo(), + wrapper_span: impl_.self_ty.span, + struct_span: item.span.shrink_to_lo(), mut_key: mutbl.prefix_str(), ptr_ty, }, @@ -387,23 +477,112 @@ fn emit_orphan_check_error<'tcx>( diag.emit() } - traits::OrphanCheckErr::UncoveredTy(param_ty, local_type) => { - let mut sp = sp; - for param in generics.params { - if param.name.ident().to_string() == param_ty.to_string() { - sp = param.span; - } - } + traits::OrphanCheckErr::UncoveredTyParams(UncoveredTyParams { uncovered, local_ty }) => { + let mut reported = None; + for param_def_id in uncovered { + let span = tcx.def_ident_span(param_def_id).unwrap(); + let name = tcx.item_name(param_def_id); - match local_type { - Some(local_type) => tcx.dcx().emit_err(errors::TyParamFirstLocal { - span: sp, - note: (), - param_ty, - local_type, - }), - None => tcx.dcx().emit_err(errors::TyParamSome { span: sp, note: (), param_ty }), + reported.get_or_insert(match local_ty { + Some(local_type) => tcx.dcx().emit_err(errors::TyParamFirstLocal { + span, + note: (), + param: name, + local_type, + }), + None => tcx.dcx().emit_err(errors::TyParamSome { span, note: (), param: name }), + }); } + reported.unwrap() // FIXME(fmease): This is very likely reachable. } - }) + } +} + +fn lint_uncovered_ty_params<'tcx>( + tcx: TyCtxt<'tcx>, + UncoveredTyParams { uncovered, local_ty }: UncoveredTyParams<'tcx, FxIndexSet<DefId>>, + impl_def_id: LocalDefId, +) { + let hir_id = tcx.local_def_id_to_hir_id(impl_def_id); + + for param_def_id in uncovered { + let span = tcx.def_ident_span(param_def_id).unwrap(); + let name = tcx.item_name(param_def_id); + + match local_ty { + Some(local_type) => tcx.emit_node_span_lint( + UNCOVERED_PARAM_IN_PROJECTION, + hir_id, + span, + errors::TyParamFirstLocalLint { span, note: (), param: name, local_type }, + ), + None => tcx.emit_node_span_lint( + UNCOVERED_PARAM_IN_PROJECTION, + hir_id, + span, + errors::TyParamSomeLint { span, note: (), param: name }, + ), + }; + } +} + +struct UncoveredTyParamCollector<'cx, 'tcx> { + infcx: &'cx InferCtxt<'tcx>, + uncovered_params: FxIndexSet<DefId>, +} + +impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UncoveredTyParamCollector<'_, 'tcx> { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { + if !ty.has_type_flags(ty::TypeFlags::HAS_TY_INFER) { + return; + } + let Some(origin) = self.infcx.type_var_origin(ty) else { + return ty.super_visit_with(self); + }; + if let Some(def_id) = origin.param_def_id { + self.uncovered_params.insert(def_id); + } + } + + fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result { + if ct.has_type_flags(ty::TypeFlags::HAS_TY_INFER) { + ct.super_visit_with(self) + } + } +} + +struct TyVarReplacer<'cx, 'tcx> { + infcx: &'cx InferCtxt<'tcx>, + generics: &'tcx ty::Generics, +} + +impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for TyVarReplacer<'cx, 'tcx> { + fn interner(&self) -> TyCtxt<'tcx> { + self.infcx.tcx + } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + if !ty.has_type_flags(ty::TypeFlags::HAS_TY_INFER) { + return ty; + } + let Some(origin) = self.infcx.type_var_origin(ty) else { + return ty.super_fold_with(self); + }; + if let Some(def_id) = origin.param_def_id { + // The generics of an `impl` don't have a parent, we can index directly. + let index = self.generics.param_def_id_to_index[&def_id]; + let name = self.generics.params[index as usize].name; + + Ty::new_param(self.infcx.tcx, index, name) + } else { + ty + } + } + + fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { + if !ct.has_type_flags(ty::TypeFlags::HAS_TY_INFER) { + return ct; + } + ct.super_fold_with(self) + } } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 0f0736f8756..9198ceb8f59 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -143,7 +143,7 @@ impl<'v> Visitor<'v> for HirPlaceholderCollector { _ => {} } } - fn visit_array_length(&mut self, length: &'v hir::ArrayLen) { + fn visit_array_length(&mut self, length: &'v hir::ArrayLen<'v>) { if let hir::ArrayLen::Infer(inf) = length { self.0.push(inf.span); } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 9d7deebac48..5ccfd06f258 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -24,7 +24,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { let hir_id = tcx.local_def_id_to_hir_id(def_id); let node = tcx.hir_node(hir_id); - let Node::AnonConst(_) = node else { + let Node::AnonConst(&AnonConst { span, .. }) = node else { span_bug!( tcx.def_span(def_id), "expected anon const in `anon_const_type_of`, got {node:?}" @@ -134,7 +134,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { // I dont think it's possible to reach this but I'm not 100% sure - BoxyUwU return Ty::new_error_with_message( tcx, - tcx.def_span(def_id), + span, "unexpected non-GAT usage of an anon const", ); } @@ -152,7 +152,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { let Some(type_dependent_def) = tables.type_dependent_def_id(parent_node_id) else { return Ty::new_error_with_message( tcx, - tcx.def_span(def_id), + span, format!("unable to find type-dependent def for {parent_node_id:?}"), ); }; @@ -194,7 +194,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { } else { return Ty::new_error_with_message( tcx, - tcx.def_span(def_id), + span, format!("unable to find const parent for {hir_id} in pat {pat:?}"), ); } @@ -202,7 +202,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { _ => { return Ty::new_error_with_message( tcx, - tcx.def_span(def_id), + span, format!("unexpected const parent path {parent_node:?}"), ); } @@ -226,11 +226,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { .map(|idx| (idx, seg)) }) }) else { - return Ty::new_error_with_message( - tcx, - tcx.def_span(def_id), - "no arg matching AnonConst in path", - ); + return Ty::new_error_with_message(tcx, span, "no arg matching AnonConst in path"); }; let generics = match tcx.res_generics_def_id(segment.res) { @@ -238,7 +234,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { None => { return Ty::new_error_with_message( tcx, - tcx.def_span(def_id), + span, format!("unexpected anon const res {:?} in path: {:?}", segment.res, path), ); } @@ -250,7 +246,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { _ => { return Ty::new_error_with_message( tcx, - tcx.def_span(def_id), + span, format!("unexpected const parent in type_of(): {parent_node:?}"), ); } @@ -278,7 +274,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { } else { return Ty::new_error_with_message( tcx, - tcx.def_span(def_id), + span, format!("const generic parameter not found in {generics:?} at position {arg_idx:?}"), ); } diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 867ee772a30..1c99713b3ae 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1355,29 +1355,54 @@ pub struct CrossCrateTraitsDefined { pub traits: String, } +// FIXME(fmease): Deduplicate: + #[derive(Diagnostic)] #[diag(hir_analysis_ty_param_first_local, code = E0210)] #[note] -pub struct TyParamFirstLocal<'a> { +pub struct TyParamFirstLocal<'tcx> { #[primary_span] #[label] pub span: Span, #[note(hir_analysis_case_note)] pub note: (), - pub param_ty: Ty<'a>, - pub local_type: Ty<'a>, + pub param: Symbol, + pub local_type: Ty<'tcx>, +} + +#[derive(LintDiagnostic)] +#[diag(hir_analysis_ty_param_first_local, code = E0210)] +#[note] +pub struct TyParamFirstLocalLint<'tcx> { + #[label] + pub span: Span, + #[note(hir_analysis_case_note)] + pub note: (), + pub param: Symbol, + pub local_type: Ty<'tcx>, } #[derive(Diagnostic)] #[diag(hir_analysis_ty_param_some, code = E0210)] #[note] -pub struct TyParamSome<'a> { +pub struct TyParamSome { #[primary_span] #[label] pub span: Span, #[note(hir_analysis_only_note)] pub note: (), - pub param_ty: Ty<'a>, + pub param: Symbol, +} + +#[derive(LintDiagnostic)] +#[diag(hir_analysis_ty_param_some, code = E0210)] +#[note] +pub struct TyParamSomeLint { + #[label] + pub span: Span, + #[note(hir_analysis_only_note)] + pub note: (), + pub param: Symbol, } #[derive(Diagnostic)] @@ -1641,3 +1666,13 @@ pub struct NonConstRange { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_invalid_receiver_ty, code = E0307)] +#[note] +#[help(hir_analysis_invalid_receiver_ty_help)] +pub struct InvalidReceiverTy<'tcx> { + #[primary_span] + pub span: Span, + pub receiver_ty: Ty<'tcx>, +} diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 63da27246a2..f7213442ac2 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2370,7 +2370,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.lower_ty(output) } } - hir::FnRetTy::DefaultReturn(..) => Ty::new_unit(tcx), + hir::FnRetTy::DefaultReturn(..) => tcx.types.unit, }; debug!(?output_ty); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 285b99c2c69..4f5fbd024a9 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -968,7 +968,7 @@ impl<'a> State<'a> { self.print_else(elseopt) } - fn print_array_length(&mut self, len: &hir::ArrayLen) { + fn print_array_length(&mut self, len: &hir::ArrayLen<'_>) { match len { hir::ArrayLen::Infer(..) => self.word("_"), hir::ArrayLen::Body(ct) => self.print_anon_const(ct), @@ -1052,7 +1052,7 @@ impl<'a> State<'a> { self.end() } - fn print_expr_repeat(&mut self, element: &hir::Expr<'_>, count: &hir::ArrayLen) { + fn print_expr_repeat(&mut self, element: &hir::Expr<'_>, count: &hir::ArrayLen<'_>) { self.ibox(INDENT_UNIT); self.word("["); self.print_expr(element); diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml index 9e7f0776b60..73a775690d6 100644 --- a/compiler/rustc_hir_typeck/Cargo.toml +++ b/compiler/rustc_hir_typeck/Cargo.toml @@ -12,7 +12,6 @@ rustc_attr = { path = "../rustc_attr" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } -rustc_graphviz = { path = "../rustc_graphviz" } rustc_hir = { path = "../rustc_hir" } rustc_hir_analysis = { path = "../rustc_hir_analysis" } rustc_hir_pretty = { path = "../rustc_hir_pretty" } diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index 07b4948872d..0560d0d902a 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -99,6 +99,17 @@ hir_typeck_lossy_provenance_ptr2int = hir_typeck_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty_str}` +hir_typeck_never_type_fallback_flowing_into_unsafe_call = never type fallback affects this call to an `unsafe` function + .help = specify the type explicitly +hir_typeck_never_type_fallback_flowing_into_unsafe_deref = never type fallback affects this raw pointer dereference + .help = specify the type explicitly +hir_typeck_never_type_fallback_flowing_into_unsafe_method = never type fallback affects this call to an `unsafe` method + .help = specify the type explicitly +hir_typeck_never_type_fallback_flowing_into_unsafe_path = never type fallback affects this `unsafe` function + .help = specify the type explicitly +hir_typeck_never_type_fallback_flowing_into_unsafe_union_field = never type fallback affects this union access + .help = specify the type explicitly + hir_typeck_no_associated_item = no {$item_kind} named `{$item_name}` found for {$ty_prefix} `{$ty_str}`{$trait_missing_method -> [true] {""} *[other] {" "}in the current scope diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 334a424d2e2..4ff6678fc91 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -66,7 +66,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // us to give better error messages (pointing to a usually better // arm for inconsistent arms or to the whole match when a `()` type // is required). - Expectation::ExpectHasType(ety) if ety != Ty::new_unit(self.tcx) => ety, + Expectation::ExpectHasType(ety) if ety != tcx.types.unit => ety, _ => self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr.span }), }; CoerceMany::with_coercion_sites(coerce_first, arms) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 4165fa7f07d..076c1936ded 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -45,8 +45,7 @@ use rustc_hir::Expr; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; use rustc_infer::infer::type_variable::TypeVariableOrigin; use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult}; -use rustc_infer::traits::TraitEngineExt as _; -use rustc_infer::traits::{IfExpressionCause, MatchExpressionArmCause, TraitEngine}; +use rustc_infer::traits::{IfExpressionCause, MatchExpressionArmCause}; use rustc_infer::traits::{Obligation, PredicateObligation}; use rustc_middle::lint::in_external_macro; use rustc_middle::traits::BuiltinImplSource; @@ -65,7 +64,6 @@ use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; -use rustc_trait_selection::traits::TraitEngineExt as _; use rustc_trait_selection::traits::{ self, NormalizeExt, ObligationCause, ObligationCauseCode, ObligationCtxt, }; @@ -164,11 +162,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // Filter these cases out to make sure our coercion is more accurate. match res { Ok(InferOk { value, obligations }) if self.next_trait_solver() => { - let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(self); - fulfill_cx.register_predicate_obligations(self, obligations); - let errs = fulfill_cx.select_where_possible(self); - if errs.is_empty() { - Ok(InferOk { value, obligations: fulfill_cx.pending_obligations() }) + let ocx = ObligationCtxt::new(self); + ocx.register_obligations(obligations); + if ocx.select_where_possible().is_empty() { + Ok(InferOk { value, obligations: ocx.into_pending_obligations() }) } else { Err(TypeError::Mismatch) } @@ -631,13 +628,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // but we need to constrain vars before processing goals mentioning // them. Some(ty::PredicateKind::AliasRelate(..)) => { - let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(self); - fulfill_cx.register_predicate_obligation(self, obligation); - let errs = fulfill_cx.select_where_possible(self); - if !errs.is_empty() { + let ocx = ObligationCtxt::new(self); + ocx.register_obligation(obligation); + if !ocx.select_where_possible().is_empty() { return Err(TypeError::Mismatch); } - coercion.obligations.extend(fulfill_cx.pending_obligations()); + coercion.obligations.extend(ocx.into_pending_obligations()); continue; } _ => { @@ -1462,7 +1458,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { fcx, cause, None, - Ty::new_unit(fcx.tcx), + fcx.tcx.types.unit, augment_error, label_unit_as_expected, ) diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 1c4d5657b17..ba8f246fd8d 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -164,6 +164,25 @@ pub struct MissingParenthesesInRange { pub add_missing_parentheses: Option<AddMissingParenthesesInRange>, } +#[derive(LintDiagnostic)] +pub enum NeverTypeFallbackFlowingIntoUnsafe { + #[help] + #[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_call)] + Call, + #[help] + #[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_method)] + Method, + #[help] + #[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_path)] + Path, + #[help] + #[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_union_field)] + UnionField, + #[help] + #[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_deref)] + Deref, +} + #[derive(Subdiagnostic)] #[multipart_suggestion( hir_typeck_add_missing_parentheses_in_range, @@ -632,7 +651,6 @@ pub enum SuggestBoxingForReturnImplTrait { ends: Vec<Span>, }, } - #[derive(LintDiagnostic)] #[diag(hir_typeck_dereferencing_mut_binding)] pub struct DereferencingMutBinding { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 15792287a87..7b552bb7077 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -654,7 +654,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { // Otherwise, this is a break *without* a value. That's // always legal, and is equivalent to `break ()`. - e_ty = Ty::new_unit(tcx); + e_ty = tcx.types.unit; cause = self.misc(expr.span); } @@ -1133,7 +1133,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // The expected type is `bool` but this will result in `()` so we can reasonably // say that the user intended to write `lhs == rhs` instead of `lhs = rhs`. // The likely cause of this is `if foo = bar { .. }`. - let actual_ty = Ty::new_unit(self.tcx); + let actual_ty = self.tcx.types.unit; let mut err = self.demand_suptype_diag(expr.span, expected_ty, actual_ty).unwrap(); let lhs_ty = self.check_expr(lhs); let rhs_ty = self.check_expr(rhs); @@ -1256,7 +1256,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Err(guar) = (lhs_ty, rhs_ty).error_reported() { Ty::new_error(self.tcx, guar) } else { - Ty::new_unit(self.tcx) + self.tcx.types.unit } } @@ -1319,7 +1319,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if ctxt.coerce.is_none() && !ctxt.may_break { self.dcx().span_bug(body.span, "no coercion, but loop may not break"); } - ctxt.coerce.map(|c| c.complete(self)).unwrap_or_else(|| Ty::new_unit(self.tcx)) + ctxt.coerce.map(|c| c.complete(self)).unwrap_or_else(|| self.tcx.types.unit) } /// Checks a method call. @@ -1444,7 +1444,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; }; if let hir::TyKind::Array(_, length) = ty.peel_refs().kind - && let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length + && let hir::ArrayLen::Body(&hir::AnonConst { hir_id, .. }) = length { let span = self.tcx.hir().span(hir_id); self.dcx().try_steal_modify_and_emit_err( @@ -1483,7 +1483,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_expr_repeat( &self, element: &'tcx hir::Expr<'tcx>, - count: &'tcx hir::ArrayLen, + count: &'tcx hir::ArrayLen<'tcx>, expected: Expectation<'tcx>, expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { @@ -3174,7 +3174,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.dcx().emit_err(YieldExprOutsideOfCoroutine { span: expr.span }); // Avoid expressions without types during writeback (#78653). self.check_expr(value); - Ty::new_unit(self.tcx) + self.tcx.types.unit } } } diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index c0b3984e3e1..f240a53a679 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -1,11 +1,18 @@ -use crate::FnCtxt; +use std::cell::OnceCell; + +use crate::{errors, FnCtxt, TypeckRootCtxt}; use rustc_data_structures::{ graph::{self, iterate::DepthFirstSearch, vec_graph::VecGraph}, unord::{UnordBag, UnordMap, UnordSet}, }; +use rustc_hir as hir; +use rustc_hir::intravisit::Visitor; +use rustc_hir::HirId; use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable}; +use rustc_session::lint; use rustc_span::DUMMY_SP; +use rustc_span::{def_id::LocalDefId, Span}; #[derive(Copy, Clone)] pub enum DivergingFallbackBehavior { @@ -335,6 +342,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { // reach a member of N. If so, it falls back to `()`. Else // `!`. let mut diverging_fallback = UnordMap::with_capacity(diverging_vids.len()); + let unsafe_infer_vars = OnceCell::new(); for &diverging_vid in &diverging_vids { let diverging_ty = Ty::new_var(self.tcx, diverging_vid); let root_vid = self.root_var(diverging_vid); @@ -354,11 +362,51 @@ impl<'tcx> FnCtxt<'_, 'tcx> { output: infer_var_infos.items().any(|info| info.output), }; + let mut fallback_to = |ty| { + let unsafe_infer_vars = unsafe_infer_vars.get_or_init(|| { + let unsafe_infer_vars = compute_unsafe_infer_vars(self.root_ctxt, self.body_id); + debug!(?unsafe_infer_vars); + unsafe_infer_vars + }); + + let affected_unsafe_infer_vars = + graph::depth_first_search_as_undirected(&coercion_graph, root_vid) + .filter_map(|x| unsafe_infer_vars.get(&x).copied()) + .collect::<Vec<_>>(); + + for (hir_id, span, reason) in affected_unsafe_infer_vars { + self.tcx.emit_node_span_lint( + lint::builtin::NEVER_TYPE_FALLBACK_FLOWING_INTO_UNSAFE, + hir_id, + span, + match reason { + UnsafeUseReason::Call => { + errors::NeverTypeFallbackFlowingIntoUnsafe::Call + } + UnsafeUseReason::Method => { + errors::NeverTypeFallbackFlowingIntoUnsafe::Method + } + UnsafeUseReason::Path => { + errors::NeverTypeFallbackFlowingIntoUnsafe::Path + } + UnsafeUseReason::UnionField => { + errors::NeverTypeFallbackFlowingIntoUnsafe::UnionField + } + UnsafeUseReason::Deref => { + errors::NeverTypeFallbackFlowingIntoUnsafe::Deref + } + }, + ); + } + + diverging_fallback.insert(diverging_ty, ty); + }; + use DivergingFallbackBehavior::*; match behavior { FallbackToUnit => { debug!("fallback to () - legacy: {:?}", diverging_vid); - diverging_fallback.insert(diverging_ty, self.tcx.types.unit); + fallback_to(self.tcx.types.unit); } FallbackToNiko => { if found_infer_var_info.self_in_trait && found_infer_var_info.output { @@ -387,13 +435,13 @@ impl<'tcx> FnCtxt<'_, 'tcx> { // set, see the relationship finding module in // compiler/rustc_trait_selection/src/traits/relationships.rs. debug!("fallback to () - found trait and projection: {:?}", diverging_vid); - diverging_fallback.insert(diverging_ty, self.tcx.types.unit); + fallback_to(self.tcx.types.unit); } else if can_reach_non_diverging { debug!("fallback to () - reached non-diverging: {:?}", diverging_vid); - diverging_fallback.insert(diverging_ty, self.tcx.types.unit); + fallback_to(self.tcx.types.unit); } else { debug!("fallback to ! - all diverging: {:?}", diverging_vid); - diverging_fallback.insert(diverging_ty, self.tcx.types.never); + fallback_to(self.tcx.types.never); } } FallbackToNever => { @@ -401,7 +449,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { "fallback to ! - `rustc_never_type_mode = \"fallback_to_never\")`: {:?}", diverging_vid ); - diverging_fallback.insert(diverging_ty, self.tcx.types.never); + fallback_to(self.tcx.types.never); } NoFallback => { debug!( @@ -417,7 +465,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { /// Returns a graph whose nodes are (unresolved) inference variables and where /// an edge `?A -> ?B` indicates that the variable `?A` is coerced to `?B`. - fn create_coercion_graph(&self) -> VecGraph<ty::TyVid> { + fn create_coercion_graph(&self) -> VecGraph<ty::TyVid, true> { let pending_obligations = self.fulfillment_cx.borrow_mut().pending_obligations(); debug!("create_coercion_graph: pending_obligations={:?}", pending_obligations); let coercion_edges: Vec<(ty::TyVid, ty::TyVid)> = pending_obligations @@ -436,17 +484,12 @@ impl<'tcx> FnCtxt<'_, 'tcx> { // // In practice currently the two ways that this happens is // coercion and subtyping. - let (a, b) = if let ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) = atom { - (a, b) - } else if let ty::PredicateKind::Subtype(ty::SubtypePredicate { - a_is_expected: _, - a, - b, - }) = atom - { - (a, b) - } else { - return None; + let (a, b) = match atom { + ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => (a, b), + ty::PredicateKind::Subtype(ty::SubtypePredicate { a_is_expected: _, a, b }) => { + (a, b) + } + _ => return None, }; let a_vid = self.root_vid(a)?; @@ -456,6 +499,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { .collect(); debug!("create_coercion_graph: coercion_edges={:?}", coercion_edges); let num_ty_vars = self.num_ty_vars(); + VecGraph::new(num_ty_vars, coercion_edges) } @@ -464,3 +508,166 @@ impl<'tcx> FnCtxt<'_, 'tcx> { Some(self.root_var(self.shallow_resolve(ty).ty_vid()?)) } } + +#[derive(Debug, Copy, Clone)] +pub(crate) enum UnsafeUseReason { + Call, + Method, + Path, + UnionField, + Deref, +} + +/// Finds all type variables which are passed to an `unsafe` operation. +/// +/// For example, for this function `f`: +/// ```ignore (demonstrative) +/// fn f() { +/// unsafe { +/// let x /* ?X */ = core::mem::zeroed(); +/// // ^^^^^^^^^^^^^^^^^^^ -- hir_id, span, reason +/// +/// let y = core::mem::zeroed::<Option<_ /* ?Y */>>(); +/// // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- hir_id, span, reason +/// } +/// } +/// ``` +/// +/// `compute_unsafe_infer_vars` will return `{ id(?X) -> (hir_id, span, Call) }` +fn compute_unsafe_infer_vars<'a, 'tcx>( + root_ctxt: &'a TypeckRootCtxt<'tcx>, + body_id: LocalDefId, +) -> UnordMap<ty::TyVid, (HirId, Span, UnsafeUseReason)> { + let body_id = + root_ctxt.tcx.hir().maybe_body_owned_by(body_id).expect("body id must have an owner"); + let body = root_ctxt.tcx.hir().body(body_id); + let mut res = UnordMap::default(); + + struct UnsafeInferVarsVisitor<'a, 'tcx, 'r> { + root_ctxt: &'a TypeckRootCtxt<'tcx>, + res: &'r mut UnordMap<ty::TyVid, (HirId, Span, UnsafeUseReason)>, + } + + impl Visitor<'_> for UnsafeInferVarsVisitor<'_, '_, '_> { + fn visit_expr(&mut self, ex: &'_ hir::Expr<'_>) { + let typeck_results = self.root_ctxt.typeck_results.borrow(); + + match ex.kind { + hir::ExprKind::MethodCall(..) => { + if let Some(def_id) = typeck_results.type_dependent_def_id(ex.hir_id) + && let method_ty = self.root_ctxt.tcx.type_of(def_id).instantiate_identity() + && let sig = method_ty.fn_sig(self.root_ctxt.tcx) + && let hir::Unsafety::Unsafe = sig.unsafety() + { + let mut collector = InferVarCollector { + value: (ex.hir_id, ex.span, UnsafeUseReason::Method), + res: self.res, + }; + + // Collect generic arguments (incl. `Self`) of the method + typeck_results + .node_args(ex.hir_id) + .types() + .for_each(|t| t.visit_with(&mut collector)); + } + } + + hir::ExprKind::Call(func, ..) => { + let func_ty = typeck_results.expr_ty(func); + + if func_ty.is_fn() + && let sig = func_ty.fn_sig(self.root_ctxt.tcx) + && let hir::Unsafety::Unsafe = sig.unsafety() + { + let mut collector = InferVarCollector { + value: (ex.hir_id, ex.span, UnsafeUseReason::Call), + res: self.res, + }; + + // Try collecting generic arguments of the function. + // Note that we do this below for any paths (that don't have to be called), + // but there we do it with a different span/reason. + // This takes priority. + typeck_results + .node_args(func.hir_id) + .types() + .for_each(|t| t.visit_with(&mut collector)); + + // Also check the return type, for cases like `returns_unsafe_fn_ptr()()` + sig.output().visit_with(&mut collector); + } + } + + // Check paths which refer to functions. + // We do this, instead of only checking `Call` to make sure the lint can't be + // avoided by storing unsafe function in a variable. + hir::ExprKind::Path(_) => { + let ty = typeck_results.expr_ty(ex); + + // If this path refers to an unsafe function, collect inference variables which may affect it. + // `is_fn` excludes closures, but those can't be unsafe. + if ty.is_fn() + && let sig = ty.fn_sig(self.root_ctxt.tcx) + && let hir::Unsafety::Unsafe = sig.unsafety() + { + let mut collector = InferVarCollector { + value: (ex.hir_id, ex.span, UnsafeUseReason::Path), + res: self.res, + }; + + // Collect generic arguments of the function + typeck_results + .node_args(ex.hir_id) + .types() + .for_each(|t| t.visit_with(&mut collector)); + } + } + + hir::ExprKind::Unary(hir::UnOp::Deref, pointer) => { + if let ty::RawPtr(pointee, _) = typeck_results.expr_ty(pointer).kind() { + pointee.visit_with(&mut InferVarCollector { + value: (ex.hir_id, ex.span, UnsafeUseReason::Deref), + res: self.res, + }); + } + } + + hir::ExprKind::Field(base, _) => { + let base_ty = typeck_results.expr_ty(base); + + if base_ty.is_union() { + typeck_results.expr_ty(ex).visit_with(&mut InferVarCollector { + value: (ex.hir_id, ex.span, UnsafeUseReason::UnionField), + res: self.res, + }); + } + } + + _ => (), + }; + + hir::intravisit::walk_expr(self, ex); + } + } + + struct InferVarCollector<'r, V> { + value: V, + res: &'r mut UnordMap<ty::TyVid, V>, + } + + impl<'tcx, V: Copy> ty::TypeVisitor<TyCtxt<'tcx>> for InferVarCollector<'_, V> { + fn visit_ty(&mut self, t: Ty<'tcx>) { + if let Some(vid) = t.ty_vid() { + _ = self.res.try_insert(vid, self.value); + } else { + t.super_visit_with(self) + } + } + } + + UnsafeInferVarsVisitor { root_ctxt, res: &mut res }.visit_expr(&body.value); + + debug!(?res, "collected the following unsafe vars for {body_id:?}"); + + res +} diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 2060e08aacf..552747bdc52 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -438,7 +438,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn lower_array_length(&self, length: &hir::ArrayLen) -> ty::Const<'tcx> { + pub fn lower_array_length(&self, length: &hir::ArrayLen<'tcx>) -> ty::Const<'tcx> { match length { hir::ArrayLen::Infer(inf) => self.ct_infer(self.tcx.types.usize, None, inf.span), hir::ArrayLen::Body(anon_const) => { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index b729fbe844a..e45e0884aff 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1660,7 +1660,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::StmtKind::Item(_) => {} hir::StmtKind::Expr(ref expr) => { // Check with expected type of `()`. - self.check_expr_has_type_or_error(expr, Ty::new_unit(self.tcx), |err| { + self.check_expr_has_type_or_error(expr, self.tcx.types.unit, |err| { if expr.can_have_side_effects() { self.suggest_semicolon_at_end(expr.span, err); } @@ -1676,7 +1676,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } pub fn check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>) { - let unit = Ty::new_unit(self.tcx); + let unit = self.tcx.types.unit; let ty = self.check_block_with_expected(blk, ExpectHasType(unit)); // if the block produces a `!` value, that can always be @@ -1794,7 +1794,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { blk.span, blk.hir_id, expected_ty, - Ty::new_unit(self.tcx), + self.tcx.types.unit, ); } if !self.err_ctxt().consider_removing_semicolon( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 2f96cf9e373..794b854ca5f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -5,12 +5,14 @@ mod checks; mod inspect_obligations; mod suggestions; +use rustc_errors::ErrorGuaranteed; + use crate::coercion::DynamicCoerceMany; use crate::fallback::DivergingFallbackBehavior; use crate::fn_ctxt::checks::DivergingBlockBehavior; use crate::{CoroutineTypes, Diverges, EnclosingBreakables, TypeckRootCtxt}; use hir::def_id::CRATE_DEF_ID; -use rustc_errors::{DiagCtxt, ErrorGuaranteed}; +use rustc_errors::DiagCtxt; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 49d0c8bfcd1..a4f840d849d 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -39,7 +39,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = if !lhs_ty.is_ty_var() && !rhs_ty.is_ty_var() && is_builtin_binop(lhs_ty, rhs_ty, op) { self.enforce_builtin_binop_types(lhs.span, lhs_ty, rhs.span, rhs_ty, op); - Ty::new_unit(self.tcx) + self.tcx.types.unit } else { return_ty }; diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 6040b689f49..8c7ae7f8e98 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -10,7 +10,6 @@ use rustc_hir::pat_util::EnumerateAndAdjustIterator; use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability, Pat, PatKind}; use rustc_infer::infer; use rustc_infer::infer::type_variable::TypeVariableOrigin; -use rustc_lint as lint; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; @@ -684,7 +683,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { // `mut x` resets the binding mode in edition <= 2021. self.tcx.emit_node_span_lint( - lint::builtin::DEREFERENCING_MUT_BINDING, + rustc_lint::builtin::DEREFERENCING_MUT_BINDING, pat.hir_id, pat.span, errors::DereferencingMutBinding { span: pat.span }, @@ -1228,16 +1227,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } } else { - // Pattern has wrong number of fields. - let e = - self.e0023(pat.span, res, qpath, subpats, &variant.fields.raw, expected, had_err); + let e = self.emit_err_pat_wrong_number_of_fields( + pat.span, + res, + qpath, + subpats, + &variant.fields.raw, + expected, + had_err, + ); on_error(e); return Ty::new_error(tcx, e); } pat_ty } - fn e0023( + fn emit_err_pat_wrong_number_of_fields( &self, pat_span: Span, res: Res, diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index aa6f184a2d7..8c66f239f8e 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -46,6 +46,7 @@ use rustc_middle::dep_graph::{ }; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; +use rustc_middle::{bug, span_bug}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs index 0729986f32f..79402c88de4 100644 --- a/compiler/rustc_incremental/src/lib.rs +++ b/compiler/rustc_incremental/src/lib.rs @@ -7,8 +7,6 @@ #![allow(internal_features)] #[macro_use] -extern crate rustc_middle; -#[macro_use] extern crate tracing; mod assert_dep_graph; diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index bf6ee044a0b..193042b8cdf 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -104,12 +104,17 @@ //! implemented. use crate::errors; +use rustc_data_structures::base_n; +use rustc_data_structures::base_n::BaseNString; +use rustc_data_structures::base_n::ToBaseN; +use rustc_data_structures::base_n::CASE_INSENSITIVE; +use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_data_structures::svh::Svh; use rustc_data_structures::unord::{UnordMap, UnordSet}; -use rustc_data_structures::{base_n, flock}; use rustc_errors::ErrorGuaranteed; use rustc_fs_util::{link_or_copy, try_canonicalize, LinkOrCopy}; +use rustc_middle::bug; use rustc_session::config::CrateType; use rustc_session::output::{collect_crate_types, find_crate_name}; use rustc_session::{Session, StableCrateId}; @@ -332,31 +337,24 @@ pub fn finalize_session_directory(sess: &Session, svh: Option<Svh>) { debug!("finalize_session_directory() - session directory: {}", incr_comp_session_dir.display()); - let old_sub_dir_name = incr_comp_session_dir + let mut sub_dir_name = incr_comp_session_dir .file_name() .unwrap() .to_str() - .expect("malformed session dir name: contains non-Unicode characters"); + .expect("malformed session dir name: contains non-Unicode characters") + .to_string(); - // Keep the 's-{timestamp}-{random-number}' prefix, but replace the - // '-working' part with the SVH of the crate - let dash_indices: Vec<_> = old_sub_dir_name.match_indices('-').map(|(idx, _)| idx).collect(); - if dash_indices.len() != 3 { - bug!( - "Encountered incremental compilation session directory with \ - malformed name: {}", - incr_comp_session_dir.display() - ) - } - - // State: "s-{timestamp}-{random-number}-" - let mut new_sub_dir_name = String::from(&old_sub_dir_name[..=dash_indices[2]]); + // Keep the 's-{timestamp}-{random-number}' prefix, but replace "working" with the SVH of the crate + sub_dir_name.truncate(sub_dir_name.len() - "working".len()); + // Double-check that we kept this: "s-{timestamp}-{random-number}-" + assert!(sub_dir_name.ends_with('-'), "{:?}", sub_dir_name); + assert!(sub_dir_name.as_bytes().iter().filter(|b| **b == b'-').count() == 3); - // Append the svh - base_n::push_str(svh.as_u128(), INT_ENCODE_BASE, &mut new_sub_dir_name); + // Append the SVH + sub_dir_name.push_str(&svh.as_u128().to_base_fixed_len(CASE_INSENSITIVE)); // Create the full path - let new_path = incr_comp_session_dir.parent().unwrap().join(new_sub_dir_name); + let new_path = incr_comp_session_dir.parent().unwrap().join(&*sub_dir_name); debug!("finalize_session_directory() - new path: {}", new_path.display()); match rename_path_with_retry(&*incr_comp_session_dir, &new_path, 3) { @@ -452,11 +450,11 @@ fn generate_session_dir_path(crate_dir: &Path) -> PathBuf { let random_number = thread_rng().next_u32(); debug!("generate_session_dir_path: random_number = {}", random_number); - let directory_name = format!( - "s-{}-{}-working", - timestamp, - base_n::encode(random_number as u128, INT_ENCODE_BASE) - ); + // Chop the first 3 characters off the timestamp. Those 3 bytes will be zero for a while. + let (zeroes, timestamp) = timestamp.split_at(3); + assert_eq!(zeroes, "000"); + let directory_name = + format!("s-{}-{}-working", timestamp, random_number.to_base_fixed_len(CASE_INSENSITIVE)); debug!("generate_session_dir_path: directory_name = {}", directory_name); let directory_path = crate_dir.join(directory_name); debug!("generate_session_dir_path: directory_path = {}", directory_path.display()); @@ -587,10 +585,10 @@ fn extract_timestamp_from_session_dir(directory_name: &str) -> Result<SystemTime string_to_timestamp(&directory_name[dash_indices[0] + 1..dash_indices[1]]) } -fn timestamp_to_string(timestamp: SystemTime) -> String { +fn timestamp_to_string(timestamp: SystemTime) -> BaseNString { let duration = timestamp.duration_since(UNIX_EPOCH).unwrap(); let micros = duration.as_secs() * 1_000_000 + (duration.subsec_nanos() as u64) / 1000; - base_n::encode(micros as u128, INT_ENCODE_BASE) + micros.to_base_fixed_len(CASE_INSENSITIVE) } fn string_to_timestamp(s: &str) -> Result<SystemTime, &'static str> { @@ -621,9 +619,8 @@ fn crate_path(sess: &Session) -> PathBuf { sess.cfg_version, ); - let stable_crate_id = base_n::encode(stable_crate_id.as_u64() as u128, INT_ENCODE_BASE); - - let crate_name = format!("{crate_name}-{stable_crate_id}"); + let crate_name = + format!("{crate_name}-{}", stable_crate_id.as_u64().to_base_fixed_len(CASE_INSENSITIVE)); incr_dir.join(crate_name) } diff --git a/compiler/rustc_infer/src/infer/canonical/instantiate.rs b/compiler/rustc_infer/src/infer/canonical/instantiate.rs index c8adbf7f57a..f95cc13623c 100644 --- a/compiler/rustc_infer/src/infer/canonical/instantiate.rs +++ b/compiler/rustc_infer/src/infer/canonical/instantiate.rs @@ -7,6 +7,7 @@ //! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html use crate::infer::canonical::{Canonical, CanonicalVarValues}; +use rustc_macros::extension; use rustc_middle::ty::fold::{FnMutDelegate, TypeFoldable}; use rustc_middle::ty::GenericArgKind; use rustc_middle::ty::{self, TyCtxt}; diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 40a9db10956..635bbca37ec 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -68,6 +68,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; +use rustc_macros::extension; use rustc_middle::dep_graph::DepContext; use rustc_middle::ty::print::{with_forced_trimmed_paths, PrintError}; use rustc_middle::ty::relate::{self, RelateResult, TypeRelation}; diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 81130d69151..bb53aec0b4d 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -4,6 +4,7 @@ pub use lexical_region_resolve::RegionResolutionError; pub use relate::combine::CombineFields; pub use relate::combine::ObligationEmittingRelation; pub use relate::StructurallyRelateAliases; +pub use rustc_macros::{TypeFoldable, TypeVisitable}; pub use rustc_middle::ty::IntVarValue; pub use BoundRegionConversionTime::*; pub use RegionVariableOrigin::*; @@ -20,13 +21,13 @@ use opaque_types::OpaqueTypeStorage; use region_constraints::{GenericKind, VarInfos, VerifyBound}; use region_constraints::{RegionConstraintCollector, RegionConstraintStorage}; use rustc_data_structures::captures::Captures; -use rustc_data_structures::fx::FxIndexMap; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::undo_log::Rollback; use rustc_data_structures::unify as ut; use rustc_errors::{Diag, DiagCtxt, ErrorGuaranteed}; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_macros::extension; use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_middle::infer::unify_key::ConstVariableValue; use rustc_middle::infer::unify_key::EffectVarValue; @@ -478,7 +479,7 @@ pub enum SubregionOrigin<'tcx> { // `SubregionOrigin` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_pointer_width = "64")] -static_assert_size!(SubregionOrigin<'_>, 32); +rustc_data_structures::static_assert_size!(SubregionOrigin<'_>, 32); impl<'tcx> SubregionOrigin<'tcx> { pub fn to_constraint_category(&self) -> ConstraintCategory<'tcx> { diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 3d6b54721d0..223e6e3d344 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -11,6 +11,7 @@ use rustc_data_structures::sync::Lrc; use rustc_data_structures::undo_log::UndoLogs; use rustc_data_structures::unify as ut; use rustc_index::IndexVec; +use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::infer::unify_key::{RegionVariableValue, RegionVidKey}; use rustc_middle::ty::ReStatic; use rustc_middle::ty::{self, Ty, TyCtxt}; diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index a5f52420a84..0299af61d45 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -18,7 +18,6 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(bootstrap, feature(associated_type_bounds))] #![feature(box_patterns)] #![feature(control_flow_enum)] #![feature(extend_one)] @@ -31,11 +30,6 @@ #![recursion_limit = "512"] // For rustdoc #[macro_use] -extern crate rustc_macros; -#[cfg(target_pointer_width = "64")] -#[macro_use] -extern crate rustc_data_structures; -#[macro_use] extern crate tracing; #[macro_use] extern crate rustc_middle; diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index c495810858f..cb067c7a660 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -1,6 +1,7 @@ use crate::infer::InferCtxt; use crate::traits::Obligation; use rustc_hir::def_id::DefId; +use rustc_macros::extension; use rustc_middle::ty::{self, ToPredicate, Ty}; use super::FulfillmentError; diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index 7b4e085293c..f77a6115861 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -113,7 +113,7 @@ impl<'tcx> PolyTraitObligation<'tcx> { // `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_pointer_width = "64")] -static_assert_size!(PredicateObligation<'_>, 48); +rustc_data_structures::static_assert_size!(PredicateObligation<'_>, 48); pub type PredicateObligations<'tcx> = Vec<PredicateObligation<'tcx>>; @@ -206,6 +206,18 @@ impl<'tcx> FulfillmentError<'tcx> { ) -> FulfillmentError<'tcx> { FulfillmentError { obligation, code, root_obligation } } + + pub fn is_true_error(&self) -> bool { + match self.code { + FulfillmentErrorCode::SelectionError(_) + | FulfillmentErrorCode::ProjectionError(_) + | FulfillmentErrorCode::SubtypeError(_, _) + | FulfillmentErrorCode::ConstEquateError(_, _) => true, + FulfillmentErrorCode::Cycle(_) | FulfillmentErrorCode::Ambiguity { overflow: _ } => { + false + } + } + } } impl<'tcx> PolyTraitObligation<'tcx> { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index b593c41a8ea..76d5d7a3ac2 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -4,7 +4,6 @@ use crate::proc_macro_decls; use crate::util; use rustc_ast::{self as ast, visit}; -use rustc_borrowck as mir_borrowck; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::parallel; use rustc_data_structures::steal::Steal; @@ -20,7 +19,6 @@ use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, TyCtxt}; use rustc_middle::util::Providers; -use rustc_mir_build as mir_build; use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_attr}; use rustc_passes::{abi_test, hir_stats, layout_test}; use rustc_resolve::Resolver; @@ -616,8 +614,8 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| { proc_macro_decls::provide(providers); rustc_const_eval::provide(providers); rustc_middle::hir::provide(providers); - mir_borrowck::provide(providers); - mir_build::provide(providers); + rustc_borrowck::provide(providers); + rustc_mir_build::provide(providers); rustc_mir_transform::provide(providers); rustc_monomorphize::provide(providers); rustc_privacy::provide(providers); diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 68c7f187f52..36f9dda7250 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -4,12 +4,12 @@ use rustc_data_structures::profiling::TimePassesFormat; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; use rustc_session::config::{ build_configuration, build_session_options, rustc_optgroups, BranchProtection, CFGuard, Cfg, - CollapseMacroDebuginfo, CoverageOptions, DebugInfo, DumpMonoStatsFormat, ErrorOutputType, - ExternEntry, ExternLocation, Externs, FunctionReturn, InliningThreshold, Input, - InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, - NextSolverConfig, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, - Passes, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, - WasiExecModel, + CollapseMacroDebuginfo, CoverageLevel, CoverageOptions, DebugInfo, DumpMonoStatsFormat, + ErrorOutputType, ExternEntry, ExternLocation, Externs, FunctionReturn, InliningThreshold, + Input, InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, + LtoCli, NextSolverConfig, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, + PacRet, Passes, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, + SymbolManglingVersion, WasiExecModel, }; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; @@ -20,7 +20,7 @@ use rustc_span::source_map::{RealFileLoader, SourceMapInputs}; use rustc_span::symbol::sym; use rustc_span::{FileName, SourceFileHashAlgorithm}; use rustc_target::spec::{ - CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, RelocModel, WasmCAbi, + CodeModel, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel, WasmCAbi, }; use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel}; use std::collections::{BTreeMap, BTreeSet}; @@ -761,7 +761,7 @@ fn test_unstable_options_tracking_hash() { }) ); tracked!(codegen_backend, Some("abc".to_string())); - tracked!(coverage_options, CoverageOptions { branch: true, mcdc: true }); + tracked!(coverage_options, CoverageOptions { level: CoverageLevel::Mcdc }); tracked!(crate_attr, vec!["abc".to_string()]); tracked!(cross_crate_inline_threshold, InliningThreshold::Always); tracked!(debug_info_for_profiling, true); @@ -809,6 +809,7 @@ fn test_unstable_options_tracking_hash() { tracked!(no_profiler_runtime, true); tracked!(no_trait_vptr, true); tracked!(no_unique_section_names, true); + tracked!(on_broken_pipe, OnBrokenPipe::Kill); tracked!(oom, OomStrategy::Panic); tracked!(osx_rpath_install_name, true); tracked!(packed_bundled_libs, true); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 02dcfe9c8df..ce4d3825015 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -7,18 +7,16 @@ use rustc_data_structures::sync; use rustc_metadata::{load_symbol_from_dylib, DylibError}; use rustc_middle::ty::CurrentGcx; use rustc_parse::validate_attr; -use rustc_session as session; -use rustc_session::config::{Cfg, OutFileName, OutputFilenames, OutputTypes}; +use rustc_session::config::{host_triple, Cfg, OutFileName, OutputFilenames, OutputTypes}; use rustc_session::filesearch::sysroot_candidates; use rustc_session::lint::{self, BuiltinLintDiag, LintBuffer}; -use rustc_session::{filesearch, Session}; +use rustc_session::output::{categorize_crate_type, CRATE_TYPES}; +use rustc_session::{filesearch, EarlyDiagCtxt, Session}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; use rustc_span::source_map::SourceMapInputs; use rustc_span::symbol::sym; use rustc_target::spec::Target; -use session::output::{categorize_crate_type, CRATE_TYPES}; -use session::EarlyDiagCtxt; use std::env::consts::{DLL_PREFIX, DLL_SUFFIX}; use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicBool, Ordering}; @@ -286,7 +284,7 @@ fn get_codegen_sysroot( "cannot load the default codegen backend twice" ); - let target = session::config::host_triple(); + let target = host_triple(); let sysroot_candidates = sysroot_candidates(); let sysroot = iter::once(sysroot) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 82b90e1660a..676a7c21841 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -456,6 +456,8 @@ lint_non_local_definitions_macro_rules = non-local `macro_rules!` definition, th [one] `{$body_name}` *[other] `{$body_name}` and up {$depth} bodies } + .help_doctest = + remove the `#[macro_export]` or make this doc-test a standalone test with its own `fn main() {"{"} ... {"}"}` .non_local = a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute .exception = one exception to the rule are anon-const (`const _: () = {"{"} ... {"}"}`) at top-level module diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs index 3a5c585366a..8f4bae33957 100644 --- a/compiler/rustc_lint/src/array_into_iter.rs +++ b/compiler/rustc_lint/src/array_into_iter.rs @@ -3,9 +3,11 @@ use crate::{ LateContext, LateLintPass, LintContext, }; use rustc_hir as hir; +use rustc_middle::bug; use rustc_middle::ty; use rustc_middle::ty::adjustment::{Adjust, Adjustment}; use rustc_session::lint::FutureIncompatibilityReason; +use rustc_session::{declare_lint, impl_lint_pass}; use rustc_span::edition::Edition; use rustc_span::symbol::sym; use rustc_span::Span; diff --git a/compiler/rustc_lint/src/async_fn_in_trait.rs b/compiler/rustc_lint/src/async_fn_in_trait.rs index 5f7a3137d52..40778542c75 100644 --- a/compiler/rustc_lint/src/async_fn_in_trait.rs +++ b/compiler/rustc_lint/src/async_fn_in_trait.rs @@ -2,6 +2,7 @@ use crate::lints::AsyncFnInTraitDiag; use crate::LateContext; use crate::LateLintPass; use rustc_hir as hir; +use rustc_session::{declare_lint, declare_lint_pass}; use rustc_trait_selection::traits::error_reporting::suggestions::suggest_desugaring_async_fn_to_impl_future_in_trait; declare_lint! { diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 0c89e186c47..ba316e5eeb0 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -51,6 +51,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; use rustc_hir::intravisit::FnKind as HirFnKind; use rustc_hir::{Body, FnDecl, GenericParamKind, Node, PatKind, PredicateOrigin}; +use rustc_middle::bug; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -59,6 +60,7 @@ use rustc_middle::ty::ToPredicate; use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::{self, Ty, TyCtxt, VariantDef}; use rustc_session::lint::{BuiltinLintDiag, FutureIncompatibilityReason}; +use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass}; use rustc_span::edition::Edition; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index d1dcfc524b5..0931bb29963 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -27,6 +27,7 @@ use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; +use rustc_middle::bug; use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::print::{with_no_trimmed_paths, PrintError}; @@ -110,7 +111,7 @@ struct LintAlias { struct LintGroup { lint_ids: Vec<LintId>, - is_loaded: bool, + is_externally_loaded: bool, depr: Option<LintAlias>, } @@ -159,7 +160,9 @@ impl LintStore { // Don't display deprecated lint groups. depr.is_none() }) - .map(|(k, LintGroup { lint_ids, is_loaded, .. })| (*k, lint_ids.clone(), *is_loaded)) + .map(|(k, LintGroup { lint_ids, is_externally_loaded, .. })| { + (*k, lint_ids.clone(), *is_externally_loaded) + }) } pub fn register_early_pass( @@ -218,7 +221,7 @@ impl LintStore { .entry(edition.lint_name()) .or_insert(LintGroup { lint_ids: vec![], - is_loaded: lint.is_loaded, + is_externally_loaded: lint.is_externally_loaded, depr: None, }) .lint_ids @@ -231,7 +234,7 @@ impl LintStore { .entry("future_incompatible") .or_insert(LintGroup { lint_ids: vec![], - is_loaded: lint.is_loaded, + is_externally_loaded: lint.is_externally_loaded, depr: None, }) .lint_ids @@ -246,7 +249,7 @@ impl LintStore { alias, LintGroup { lint_ids: vec![], - is_loaded: false, + is_externally_loaded: false, depr: Some(LintAlias { name: lint_name, silent: true }), }, ); @@ -254,21 +257,21 @@ impl LintStore { pub fn register_group( &mut self, - is_loaded: bool, + is_externally_loaded: bool, name: &'static str, deprecated_name: Option<&'static str>, to: Vec<LintId>, ) { let new = self .lint_groups - .insert(name, LintGroup { lint_ids: to, is_loaded, depr: None }) + .insert(name, LintGroup { lint_ids: to, is_externally_loaded, depr: None }) .is_none(); if let Some(deprecated) = deprecated_name { self.lint_groups.insert( deprecated, LintGroup { lint_ids: vec![], - is_loaded, + is_externally_loaded, depr: Some(LintAlias { name, silent: false }), }, ); diff --git a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs index 0472525d49a..e9a6276192e 100644 --- a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs +++ b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs @@ -1,4 +1,5 @@ use rustc_errors::{Applicability, Diag}; +use rustc_middle::bug; use rustc_session::{config::ExpectedValues, Session}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::{sym, Span, Symbol}; diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs index 9bc81d2c46a..b671dfaa0d1 100644 --- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs +++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs @@ -6,6 +6,7 @@ use crate::{ use rustc_hir as hir; use rustc_middle::ty; use rustc_session::lint::FutureIncompatibilityReason; +use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::sym; use rustc_trait_selection::traits::supertraits; diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs index 78ac7f9b235..60b799f3c74 100644 --- a/compiler/rustc_lint/src/drop_forget_useless.rs +++ b/compiler/rustc_lint/src/drop_forget_useless.rs @@ -1,5 +1,6 @@ use rustc_hir::{Arm, Expr, ExprKind, Node}; use rustc_middle::ty; +use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::sym; use crate::{ diff --git a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs index a67f1b62fb0..958da177eda 100644 --- a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs +++ b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs @@ -5,6 +5,7 @@ use crate::{ }; use rustc_hir as hir; use rustc_middle::ty::{visit::TypeVisitableExt, Ty}; +use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::{symbol::sym, Span}; declare_lint! { diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index cb7feea16b5..ce3f45a17e9 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -10,6 +10,7 @@ use hir::{Expr, Pat}; use rustc_hir as hir; use rustc_infer::{infer::TyCtxtInferExt, traits::ObligationCause}; use rustc_middle::ty::{self, List}; +use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::{sym, Span}; use rustc_trait_selection::traits::ObligationCtxt; diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs index fae492f252e..48e5683fc0a 100644 --- a/compiler/rustc_lint/src/foreign_modules.rs +++ b/compiler/rustc_lint/src/foreign_modules.rs @@ -5,6 +5,7 @@ use rustc_hir::def::DefKind; use rustc_middle::query::Providers; use rustc_middle::ty::layout::LayoutError; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; +use rustc_session::declare_lint; use rustc_span::{sym, Span, Symbol}; use rustc_target::abi::FIRST_VARIANT; diff --git a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs index 054cfe92a3a..aa8ca1776dc 100644 --- a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs +++ b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs @@ -7,6 +7,7 @@ use crate::{ }; use ast::util::unicode::{contains_text_flow_control_chars, TEXT_FLOW_CONTROL_CHARS}; use rustc_ast as ast; +use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::{BytePos, Span, Symbol}; declare_lint! { diff --git a/compiler/rustc_lint/src/invalid_from_utf8.rs b/compiler/rustc_lint/src/invalid_from_utf8.rs index 081e3e87530..0081374922e 100644 --- a/compiler/rustc_lint/src/invalid_from_utf8.rs +++ b/compiler/rustc_lint/src/invalid_from_utf8.rs @@ -2,6 +2,7 @@ use std::str::Utf8Error; use rustc_ast::LitKind; use rustc_hir::{Expr, ExprKind}; +use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::source_map::Spanned; use rustc_span::sym; diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index 9d4d75a646a..ea82fb9f262 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -5,6 +5,7 @@ use crate::{ use rustc_errors::MultiSpan; use rustc_hir as hir; use rustc_middle::ty; +use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::{sym, Symbol}; declare_lint! { diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 5bb2942ad4b..12b3d1d2f9e 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -22,6 +22,7 @@ use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::HirId; use rustc_index::IndexVec; +use rustc_middle::bug; use rustc_middle::hir::nested_filter; use rustc_middle::lint::{ lint_level, reveal_actual_level, LevelAndSource, LintExpectation, LintLevelSource, diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index e00d8c1e6bd..a78b410f500 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -40,10 +40,6 @@ #![allow(internal_features)] #[macro_use] -extern crate rustc_middle; -#[macro_use] -extern crate rustc_session; -#[macro_use] extern crate tracing; mod array_into_iter; diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 74a0a224dba..7efa5245baa 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1350,14 +1350,18 @@ pub enum NonLocalDefinitionsDiag { const_anon: Option<Span>, }, #[diag(lint_non_local_definitions_macro_rules)] - #[help] - #[note(lint_non_local)] - #[note(lint_exception)] - #[note(lint_non_local_definitions_deprecation)] MacroRules { depth: u32, body_kind_descr: &'static str, body_name: String, + #[help] + help: Option<()>, + #[help(lint_help_doctest)] + doctest_help: Option<()>, + #[note(lint_non_local)] + #[note(lint_exception)] + #[note(lint_non_local_definitions_deprecation)] + notes: (), #[subdiagnostic] cargo_update: Option<NonLocalDefinitionsCargoUpdateNote>, }, diff --git a/compiler/rustc_lint/src/map_unit_fn.rs b/compiler/rustc_lint/src/map_unit_fn.rs index 07980cfb6fa..e355604e206 100644 --- a/compiler/rustc_lint/src/map_unit_fn.rs +++ b/compiler/rustc_lint/src/map_unit_fn.rs @@ -6,6 +6,7 @@ use rustc_middle::{ query::Key, ty::{self, Ty}, }; +use rustc_session::{declare_lint, declare_lint_pass}; declare_lint! { /// The `map_unit_fn` lint checks for `Iterator::map` receive diff --git a/compiler/rustc_lint/src/methods.rs b/compiler/rustc_lint/src/methods.rs index 9cfdaf0ce2f..b93245d58d9 100644 --- a/compiler/rustc_lint/src/methods.rs +++ b/compiler/rustc_lint/src/methods.rs @@ -4,6 +4,7 @@ use crate::LateLintPass; use crate::LintContext; use rustc_hir::{Expr, ExprKind}; use rustc_middle::ty; +use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::{symbol::sym, Span}; declare_lint! { diff --git a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs index 69d623b547b..48d140c6b7f 100644 --- a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs +++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs @@ -1,6 +1,7 @@ use crate::{LateContext, LateLintPass, LintContext}; use rustc_hir as hir; +use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::sym; declare_lint! { diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs index 79bc78ae55a..9f298a6071c 100644 --- a/compiler/rustc_lint/src/non_ascii_idents.rs +++ b/compiler/rustc_lint/src/non_ascii_idents.rs @@ -6,6 +6,7 @@ use crate::{EarlyContext, EarlyLintPass, LintContext}; use rustc_ast as ast; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::unord::UnordMap; +use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::symbol::Symbol; use unicode_security::general_security_profile::IdentifierType; diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index e81790a7348..a6057afcbd6 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -4,10 +4,12 @@ use rustc_ast as ast; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_infer::infer::TyCtxtInferExt; +use rustc_middle::bug; use rustc_middle::lint::in_external_macro; use rustc_middle::ty; use rustc_parse_format::{ParseMode, Parser, Piece}; use rustc_session::lint::FutureIncompatibilityReason; +use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::edition::Edition; use rustc_span::{hygiene, sym, symbol::kw, InnerSpan, Span, Symbol}; use rustc_trait_selection::infer::InferCtxtExt; diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 004c2c2e4f4..7bdf5ef6af4 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -5,6 +5,7 @@ use rustc_infer::infer::InferCtxt; use rustc_infer::traits::{Obligation, ObligationCause}; use rustc_middle::ty::{self, Binder, Ty, TyCtxt, TypeFoldable, TypeFolder}; use rustc_middle::ty::{EarlyBinder, TraitRef, TypeSuperFoldable}; +use rustc_session::{declare_lint, impl_lint_pass}; use rustc_span::def_id::{DefId, LOCAL_CRATE}; use rustc_span::Span; use rustc_span::{sym, symbol::kw, ExpnKind, MacroKind}; @@ -232,6 +233,12 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { ItemKind::Macro(_macro, MacroKind::Bang) if cx.tcx.has_attr(item.owner_id.def_id, sym::macro_export) => { + // determining we if are in a doctest context can't currently be determined + // by the code it-self (no specific attrs), but fortunatly rustdoc sets a + // perma-unstable env for libtest so we just re-use that env for now + let is_at_toplevel_doctest = + self.body_depth == 2 && std::env::var("UNSTABLE_RUSTDOC_TEST_PATH").is_ok(); + cx.emit_span_lint( NON_LOCAL_DEFINITIONS, item.span, @@ -242,6 +249,9 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { .map(|s| s.to_ident_string()) .unwrap_or_else(|| "<unnameable>".to_string()), cargo_update: cargo_update(), + help: (!is_at_toplevel_doctest).then_some(()), + doctest_help: is_at_toplevel_doctest.then_some(()), + notes: (), }, ) } @@ -356,7 +366,7 @@ fn path_has_local_parent( } /// Given a def id and a parent impl def id, this checks if the parent -/// def id correspond to the def id of the parent impl definition. +/// def id (modulo modules) correspond to the def id of the parent impl definition. #[inline] fn did_has_local_parent( did: DefId, @@ -364,8 +374,14 @@ fn did_has_local_parent( impl_parent: DefId, impl_parent_parent: Option<DefId>, ) -> bool { - did.is_local() && { - let res_parent = tcx.parent(did); - res_parent == impl_parent || Some(res_parent) == impl_parent_parent - } + did.is_local() + && if let Some(did_parent) = tcx.opt_parent(did) { + did_parent == impl_parent + || Some(did_parent) == impl_parent_parent + || !did_parent.is_crate_root() + && tcx.def_kind(did_parent) == DefKind::Mod + && did_has_local_parent(did_parent, tcx, impl_parent, impl_parent_parent) + } else { + false + } } diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index ee863672017..dbb0644cd63 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -11,6 +11,7 @@ use rustc_hir::intravisit::FnKind; use rustc_hir::{GenericParamKind, PatKind}; use rustc_middle::ty; use rustc_session::config::CrateType; +use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::def_id::LocalDefId; use rustc_span::symbol::{sym, Ident}; use rustc_span::{BytePos, Span}; diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs index 970d411fb06..91441248e70 100644 --- a/compiler/rustc_lint/src/noop_method_call.rs +++ b/compiler/rustc_lint/src/noop_method_call.rs @@ -8,6 +8,7 @@ use rustc_hir::def::DefKind; use rustc_hir::{Expr, ExprKind}; use rustc_middle::ty; use rustc_middle::ty::adjustment::Adjust; +use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::symbol::sym; declare_lint! { diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index ec7954536be..1ea1f496e50 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -4,6 +4,7 @@ use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{ self, fold::BottomUpFolder, print::TraitPredPrintModifiersAndPath, Ty, TypeFoldable, }; +use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::{symbol::kw, Span}; use rustc_trait_selection::traits; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs index 160d42caa9e..c1f5cd45dc8 100644 --- a/compiler/rustc_lint/src/pass_by_value.rs +++ b/compiler/rustc_lint/src/pass_by_value.rs @@ -4,6 +4,7 @@ use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::{GenericArg, PathSegment, QPath, TyKind}; use rustc_middle::ty; +use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::sym; declare_tool_lint! { @@ -73,9 +74,12 @@ fn gen_args(cx: &LateContext<'_>, segment: &PathSegment<'_>) -> String { GenericArg::Type(ty) => { cx.tcx.sess.source_map().span_to_snippet(ty.span).unwrap_or_else(|_| "_".into()) } - GenericArg::Const(c) => { - cx.tcx.sess.source_map().span_to_snippet(c.span).unwrap_or_else(|_| "_".into()) - } + GenericArg::Const(c) => cx + .tcx + .sess + .source_map() + .span_to_snippet(c.value.span) + .unwrap_or_else(|_| "_".into()), GenericArg::Infer(_) => String::from("_"), }) .collect::<Vec<_>>(); diff --git a/compiler/rustc_lint/src/redundant_semicolon.rs b/compiler/rustc_lint/src/redundant_semicolon.rs index 1681ac2f1e5..ef08e79e24a 100644 --- a/compiler/rustc_lint/src/redundant_semicolon.rs +++ b/compiler/rustc_lint/src/redundant_semicolon.rs @@ -1,5 +1,6 @@ use crate::{lints::RedundantSemicolonsDiag, EarlyContext, EarlyLintPass, LintContext}; use rustc_ast::{Block, StmtKind}; +use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::Span; declare_lint! { diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs index 9b938b34c00..9fed91f7262 100644 --- a/compiler/rustc_lint/src/reference_casting.rs +++ b/compiler/rustc_lint/src/reference_casting.rs @@ -2,6 +2,7 @@ use rustc_ast::Mutability; use rustc_hir::{Expr, ExprKind, UnOp}; use rustc_middle::ty::layout::LayoutOf as _; use rustc_middle::ty::{self, layout::TyAndLayout}; +use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::sym; use crate::{lints::InvalidReferenceCastingDiag, LateContext, LateLintPass, LintContext}; diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs index 789f154eac5..4d1b1dc4fb7 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -3,6 +3,7 @@ use crate::LateContext; use crate::LateLintPass; use crate::LintContext; use rustc_hir as hir; +use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::symbol::sym; declare_lint! { diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index e982842f536..13b6054586c 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -17,11 +17,13 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::DiagMessage; use rustc_hir as hir; use rustc_hir::{is_range_literal, Expr, ExprKind, Node}; +use rustc_middle::bug; use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton}; use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{ self, AdtKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, }; +use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass}; use rustc_span::def_id::LocalDefId; use rustc_span::source_map; use rustc_span::symbol::sym; diff --git a/compiler/rustc_lint/src/unit_bindings.rs b/compiler/rustc_lint/src/unit_bindings.rs index 6222adf58ae..8202bfa805a 100644 --- a/compiler/rustc_lint/src/unit_bindings.rs +++ b/compiler/rustc_lint/src/unit_bindings.rs @@ -1,7 +1,7 @@ use crate::lints::UnitBindingsDiag; use crate::{LateLintPass, LintContext}; use rustc_hir as hir; -use rustc_middle::ty::Ty; +use rustc_session::{declare_lint, declare_lint_pass}; declare_lint! { /// The `unit_bindings` lint detects cases where bindings are useless because they have @@ -56,8 +56,8 @@ impl<'tcx> LateLintPass<'tcx> for UnitBindings { && let Some(init) = local.init && let init_ty = tyck_results.expr_ty(init) && let local_ty = tyck_results.node_type(local.hir_id) - && init_ty == Ty::new_unit(cx.tcx) - && local_ty == Ty::new_unit(cx.tcx) + && init_ty == cx.tcx.types.unit + && local_ty == cx.tcx.types.unit && local.ty.is_none() && !matches!(init.kind, hir::ExprKind::Tup([])) && !matches!(local.pat.kind, hir::PatKind::Tuple([], ..)) diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 0b0949e4dd8..4d372d612e9 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -16,6 +16,7 @@ use rustc_hir::def_id::DefId; use rustc_infer::traits::util::elaborate; use rustc_middle::ty::adjustment; use rustc_middle::ty::{self, Ty}; +use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass}; use rustc_span::symbol::Symbol; use rustc_span::symbol::{kw, sym}; use rustc_span::{BytePos, Span}; @@ -176,6 +177,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { | hir::BinOpKind::Shr => Some("bitwise operation"), }, hir::ExprKind::AddrOf(..) => Some("borrow"), + hir::ExprKind::OffsetOf(..) => Some("`offset_of` call"), hir::ExprKind::Unary(..) => Some("unary operation"), _ => None, }; diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index e74cc388cab..c7996c27c2f 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -69,6 +69,7 @@ declare_lint_pass! { MISSING_FRAGMENT_SPECIFIER, MUST_NOT_SUSPEND, NAMED_ARGUMENTS_USED_POSITIONALLY, + NEVER_TYPE_FALLBACK_FLOWING_INTO_UNSAFE, NON_CONTIGUOUS_RANGE_ENDPOINTS, NON_EXHAUSTIVE_OMITTED_PATTERNS, ORDER_DEPENDENT_TRAIT_OBJECTS, @@ -101,6 +102,7 @@ declare_lint_pass! { TYVAR_BEHIND_RAW_POINTER, UNCONDITIONAL_PANIC, UNCONDITIONAL_RECURSION, + UNCOVERED_PARAM_IN_PROJECTION, UNDEFINED_NAKED_FUNCTION_ABI, UNEXPECTED_CFGS, UNFULFILLED_LINT_EXPECTATIONS, @@ -4245,6 +4247,85 @@ declare_lint! { } declare_lint! { + /// The `never_type_fallback_flowing_into_unsafe` lint detects cases where never type fallback + /// affects unsafe function calls. + /// + /// ### Never type fallback + /// + /// When the compiler sees a value of type [`!`] it implicitly inserts a coercion (if possible), + /// to allow type check to infer any type: + /// + /// ```ignore (illustrative-and-has-placeholders) + /// // this + /// let x: u8 = panic!(); + /// + /// // is (essentially) turned by the compiler into + /// let x: u8 = absurd(panic!()); + /// + /// // where absurd is a function with the following signature + /// // (it's sound, because `!` always marks unreachable code): + /// fn absurd<T>(_: !) -> T { ... } + // FIXME: use `core::convert::absurd` here instead, once it's merged + /// ``` + /// + /// While it's convenient to be able to use non-diverging code in one of the branches (like + /// `if a { b } else { return }`) this could lead to compilation errors: + /// + /// ```compile_fail + /// // this + /// { panic!() }; + /// + /// // gets turned into this + /// { absurd(panic!()) }; // error: can't infer the type of `absurd` + /// ``` + /// + /// To prevent such errors, compiler remembers where it inserted `absurd` calls, and if it + /// can't infer their type, it sets the type to fallback. `{ absurd::<Fallback>(panic!()) };`. + /// This is what is known as "never type fallback". + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(never_type_fallback_flowing_into_unsafe)] + /// fn main() { + /// if true { + /// // return has type `!` which, is some cases, causes never type fallback + /// return + /// } else { + /// // `zeroed` is an unsafe function, which returns an unbounded type + /// unsafe { std::mem::zeroed() } + /// }; + /// // depending on the fallback, `zeroed` may create `()` (which is completely sound), + /// // or `!` (which is instant undefined behavior) + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Due to historic reasons never type fallback was `()`, meaning that `!` got spontaneously + /// coerced to `()`. There are plans to change that, but they may make the code such as above + /// unsound. Instead of depending on the fallback, you should specify the type explicitly: + /// ``` + /// if true { + /// return + /// } else { + /// // type is explicitly specified, fallback can't hurt us no more + /// unsafe { std::mem::zeroed::<()>() } + /// }; + /// ``` + /// + /// See [Tracking Issue for making `!` fall back to `!`](https://github.com/rust-lang/rust/issues/123748). + /// + /// [`!`]: https://doc.rust-lang.org/core/primitive.never.html + /// [`()`]: https://doc.rust-lang.org/core/primitive.unit.html + pub NEVER_TYPE_FALLBACK_FLOWING_INTO_UNSAFE, + Warn, + "never type fallback affecting unsafe function calls" +} + +declare_lint! { /// The `byte_slice_in_packed_struct_with_derive` lint detects cases where a byte slice field /// (`[u8]`) or string slice field (`str`) is used in a `packed` struct that derives one or /// more built-in traits. @@ -4741,3 +4822,68 @@ declare_lint! { }; crate_level_only } + +declare_lint! { + /// The `uncovered_param_in_projection` lint detects a violation of one of Rust's orphan rules for + /// foreign trait implementations that concerns the use of type parameters inside trait associated + /// type paths ("projections") whose output may not be a local type that is mistakenly considered + /// to "cover" said parameters which is **unsound** and which may be rejected by a future version + /// of the compiler. + /// + /// Originally reported in [#99554]. + /// + /// [#99554]: https://github.com/rust-lang/rust/issues/99554 + /// + /// ### Example + /// + /// ```rust,ignore (dependent) + /// // dependency.rs + /// #![crate_type = "lib"] + /// + /// pub trait Trait<T, U> {} + /// ``` + /// + /// ```edition2021,ignore (needs dependency) + /// // dependent.rs + /// trait Identity { + /// type Output; + /// } + /// + /// impl<T> Identity for T { + /// type Output = T; + /// } + /// + /// struct Local; + /// + /// impl<T> dependency::Trait<Local, T> for <T as Identity>::Output {} + /// + /// fn main() {} + /// ``` + /// + /// This will produce: + /// + /// ```text + /// warning[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + /// --> dependent.rs:11:6 + /// | + /// 11 | impl<T> dependency::Trait<Local, T> for <T as Identity>::Output {} + /// | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + /// | + /// = 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 #124559 <https://github.com/rust-lang/rust/issues/124559> + /// = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + /// = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last + /// = note: `#[warn(uncovered_param_in_projection)]` on by default + /// ``` + /// + /// ### Explanation + /// + /// FIXME(fmease): Write explainer. + pub UNCOVERED_PARAM_IN_PROJECTION, + Warn, + "impl contains type parameters that are not covered", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, + reference: "issue #124559 <https://github.com/rust-lang/rust/issues/124559>", + }; +} diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 7f200a7b623..ed165188787 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -1,6 +1,3 @@ -#[macro_use] -extern crate rustc_macros; - pub use self::Level::*; use rustc_ast::node_id::NodeId; use rustc_ast::{AttrId, Attribute}; @@ -11,6 +8,7 @@ use rustc_data_structures::stable_hasher::{ use rustc_error_messages::{DiagMessage, MultiSpan}; use rustc_hir::HashStableContext; use rustc_hir::HirId; +use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::edition::Edition; use rustc_span::{sym, symbol::Ident, Span, Symbol}; use rustc_target::spec::abi::Abi; @@ -323,7 +321,8 @@ pub struct Lint { pub future_incompatible: Option<FutureIncompatibleInfo>, - pub is_loaded: bool, + /// `true` if this lint is being loaded by another tool (e.g. Clippy). + pub is_externally_loaded: bool, /// `Some` if this lint is feature gated, otherwise `None`. pub feature_gate: Option<Symbol>, @@ -468,7 +467,7 @@ impl Lint { default_level: Level::Forbid, desc: "", edition_lint_opts: None, - is_loaded: false, + is_externally_loaded: false, report_in_external_macro: false, future_incompatible: None, feature_gate: None, @@ -817,7 +816,7 @@ macro_rules! declare_lint { name: stringify!($NAME), default_level: $crate::$Level, desc: $desc, - is_loaded: false, + is_externally_loaded: false, $($v: true,)* $(feature_gate: Some($gate),)? $(future_incompatible: Some($crate::FutureIncompatibleInfo { @@ -859,7 +858,7 @@ macro_rules! declare_tool_lint { edition_lint_opts: None, report_in_external_macro: $external, future_incompatible: None, - is_loaded: true, + is_externally_loaded: true, $(feature_gate: Some($gate),)? crate_level_only: false, ..$crate::Lint::default_fields_for_macro() diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index b50ae057709..fb0010f2c5d 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -4,8 +4,7 @@ use std::{ }; use rustc_errors::{codes::*, Diag, DiagCtxt, Diagnostic, EmissionGuarantee, Level}; -use rustc_macros::Diagnostic; -use rustc_session::config; +use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{sym, Span, Symbol}; use rustc_target::spec::{PanicStrategy, TargetTriple}; @@ -640,9 +639,7 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for CannotFindCrate { diag.arg("locator_triple", self.locator_triple.triple()); diag.code(E0463); diag.span(self.span); - if (self.crate_name == sym::std || self.crate_name == sym::core) - && self.locator_triple != TargetTriple::from_triple(config::host_triple()) - { + if self.crate_name == sym::std || self.crate_name == sym::core { if self.missing_core { diag.note(fluent::metadata_target_not_installed); } else { diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 7dd03407bd7..c8162a1f0ee 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -20,8 +20,6 @@ extern crate proc_macro; #[macro_use] -extern crate rustc_macros; -#[macro_use] extern crate rustc_middle; #[macro_use] diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index fd42c9c1faa..2a33088513b 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1261,7 +1261,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { sess: &'a Session, ) -> impl Iterator<Item = ModChild> + 'a { iter::from_coroutine( - #[cfg_attr(not(bootstrap), coroutine)] + #[coroutine] move || { if let Some(data) = &self.root.proc_macro_data { // If we are loading as a proc macro, we want to return diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 5b0be8ac230..c9cb2f5a240 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -2,6 +2,7 @@ use crate::creader::CrateMetadataRef; use decoder::Metadata; use def_path_hash_map::DefPathHashMapRef; use rustc_data_structures::fx::FxHashMap; +use rustc_macros::{Decodable, Encodable, TyDecodable, TyEncodable}; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::lib_features::FeatureStability; use table::TableBuilder; @@ -17,6 +18,7 @@ use rustc_hir::definitions::DefKey; use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::BitSet; use rustc_index::IndexVec; +use rustc_macros::{MetadataDecodable, MetadataEncodable}; use rustc_middle::metadata::ModChild; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index 0d3cffd2047..6e622b0405f 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -1,7 +1,7 @@ use std::fmt; use rustc_errors::{codes::*, DiagArgName, DiagArgValue, DiagMessage}; -use rustc_macros::Diagnostic; +use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Span, Symbol}; use crate::ty::Ty; diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index c0c773c6285..c7aea137b68 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -885,7 +885,7 @@ impl<'hir> Map<'hir> { Node::ImplItem(impl_item) => impl_item.span, Node::Variant(variant) => variant.span, Node::Field(field) => field.span, - Node::AnonConst(constant) => self.body(constant.body).value.span, + Node::AnonConst(constant) => constant.span, Node::ConstBlock(constant) => self.body(constant.body).value.span, Node::Expr(expr) => expr.span, Node::ExprField(field) => field.span, @@ -912,7 +912,7 @@ impl<'hir> Map<'hir> { Node::ArrayLenInfer(inf) => inf.span, Node::PreciseCapturingNonLifetimeArg(param) => param.ident.span, Node::Synthetic => unreachable!(), - Node::Err(span) => *span, + Node::Err(span) => span, } } diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 94d1039c763..34748afa863 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -15,6 +15,7 @@ use rustc_data_structures::sync::{try_par_for_each_in, DynSend, DynSync}; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::*; +use rustc_macros::{Decodable, Encodable, HashStable}; use rustc_span::{ErrorGuaranteed, ExpnId}; /// Gather the LocalDefId for each item-like within a module, including items contained within diff --git a/compiler/rustc_middle/src/hir/place.rs b/compiler/rustc_middle/src/hir/place.rs index 32f3a177508..1ac35314ead 100644 --- a/compiler/rustc_middle/src/hir/place.rs +++ b/compiler/rustc_middle/src/hir/place.rs @@ -2,6 +2,7 @@ use crate::ty; use crate::ty::Ty; use rustc_hir::HirId; +use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_target::abi::{FieldIdx, VariantIdx}; #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 62d7b7c28d1..aee97d77222 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -23,7 +23,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lock; -use rustc_macros::HashStable; +use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_type_ir::Canonical as IrCanonical; use rustc_type_ir::CanonicalVarInfo as IrCanonicalVarInfo; pub use rustc_type_ir::{CanonicalTyVarKind, CanonicalVarKind}; diff --git a/compiler/rustc_middle/src/infer/mod.rs b/compiler/rustc_middle/src/infer/mod.rs index 1384611e146..f74f71b6b37 100644 --- a/compiler/rustc_middle/src/infer/mod.rs +++ b/compiler/rustc_middle/src/infer/mod.rs @@ -4,6 +4,7 @@ pub mod unify_key; use crate::ty::Region; use crate::ty::{OpaqueTypeKey, Ty}; use rustc_data_structures::sync::Lrc; +use rustc_macros::{HashStable, TypeFoldable, TypeVisitable}; use rustc_span::Span; /// Requires that `region` must be equal to one of the regions in `choice_regions`. diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 501052b7411..04fd4c8d0f7 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -37,7 +37,6 @@ #![feature(coroutines)] #![feature(stmt_expr_attributes)] #![feature(if_let_guard)] -#![cfg_attr(bootstrap, feature(inline_const))] #![feature(iter_from_coroutine)] #![feature(negative_impls)] #![feature(never_type)] @@ -48,7 +47,6 @@ #![feature(trusted_len)] #![feature(type_alias_impl_trait)] #![feature(strict_provenance)] -#![cfg_attr(bootstrap, feature(associated_type_bounds))] #![feature(rustc_attrs)] #![feature(control_flow_enum)] #![feature(trait_upcasting)] @@ -66,15 +64,7 @@ #![allow(rustc::untranslatable_diagnostic)] #[macro_use] -extern crate bitflags; -#[macro_use] -extern crate rustc_macros; -#[macro_use] -extern crate rustc_data_structures; -#[macro_use] extern crate tracing; -#[macro_use] -extern crate smallvec; #[cfg(test)] mod tests; diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 8d9e0dfd869..086582e60a3 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -4,6 +4,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sorted_map::SortedMap; use rustc_errors::{Diag, DiagMessage, MultiSpan}; use rustc_hir::{HirId, ItemLocalId}; +use rustc_macros::HashStable; use rustc_session::lint::{ builtin::{self, FORBIDDEN_LINT_GROUPS}, FutureIncompatibilityReason, Level, Lint, LintId, diff --git a/compiler/rustc_middle/src/metadata.rs b/compiler/rustc_middle/src/metadata.rs index 674402cb4bf..589f274eb17 100644 --- a/compiler/rustc_middle/src/metadata.rs +++ b/compiler/rustc_middle/src/metadata.rs @@ -1,7 +1,7 @@ use crate::ty; use rustc_hir::def::Res; -use rustc_macros::HashStable; +use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_span::def_id::DefId; use rustc_span::symbol::Ident; use smallvec::SmallVec; diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index ec9697bbd35..3fa5054baed 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -1,5 +1,6 @@ use crate::mir::mono::Linkage; use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr}; +use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_span::symbol::Symbol; use rustc_target::abi::Align; use rustc_target::spec::SanitizerSet; @@ -48,7 +49,7 @@ pub struct CodegenFnAttrs { #[derive(Clone, Copy, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)] pub struct CodegenFnAttrFlags(u32); -bitflags! { +bitflags::bitflags! { impl CodegenFnAttrFlags: u32 { /// `#[cold]`: a hint to LLVM that this function, when called, is never on /// the hot path. diff --git a/compiler/rustc_middle/src/middle/debugger_visualizer.rs b/compiler/rustc_middle/src/middle/debugger_visualizer.rs index a0497d805da..74a5dfb0400 100644 --- a/compiler/rustc_middle/src/middle/debugger_visualizer.rs +++ b/compiler/rustc_middle/src/middle/debugger_visualizer.rs @@ -1,4 +1,5 @@ use rustc_data_structures::sync::Lrc; +use rustc_macros::{Decodable, Encodable, HashStable}; use std::path::PathBuf; #[derive(HashStable)] diff --git a/compiler/rustc_middle/src/middle/dependency_format.rs b/compiler/rustc_middle/src/middle/dependency_format.rs index e079843bfbc..e7d0cffc85c 100644 --- a/compiler/rustc_middle/src/middle/dependency_format.rs +++ b/compiler/rustc_middle/src/middle/dependency_format.rs @@ -4,6 +4,7 @@ //! For all the gory details, see the provider of the `dependency_formats` //! query. +use rustc_macros::{Decodable, Encodable, HashStable}; use rustc_session::config::CrateType; /// A list of dependencies for a certain crate type. diff --git a/compiler/rustc_middle/src/middle/exported_symbols.rs b/compiler/rustc_middle/src/middle/exported_symbols.rs index 123b32f4aea..3b6eecb7fa0 100644 --- a/compiler/rustc_middle/src/middle/exported_symbols.rs +++ b/compiler/rustc_middle/src/middle/exported_symbols.rs @@ -1,7 +1,7 @@ use crate::ty::GenericArgsRef; use crate::ty::{self, Ty, TyCtxt}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; -use rustc_macros::HashStable; +use rustc_macros::{Decodable, Encodable, HashStable, TyDecodable, TyEncodable}; /// The SymbolExportLevel of a symbols specifies from which kinds of crates /// the symbol will be exported. `C` symbols will be exported from any diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs index bdb2270611a..5c395afadd7 100644 --- a/compiler/rustc_middle/src/middle/mod.rs +++ b/compiler/rustc_middle/src/middle/mod.rs @@ -5,6 +5,7 @@ pub mod exported_symbols; pub mod lang_items; pub mod lib_features { use rustc_data_structures::unord::UnordMap; + use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_span::{symbol::Symbol, Span}; #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index 5ae60e04277..de07ba9700a 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -11,7 +11,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::unord::UnordMap; use rustc_hir as hir; use rustc_hir::{HirId, HirIdMap, Node}; -use rustc_macros::HashStable; +use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_span::{Span, DUMMY_SP}; use std::fmt; @@ -153,7 +153,7 @@ rustc_index::newtype_index! { } // compilation error if size of `ScopeData` is not the same as a `u32` -static_assert_size!(ScopeData, 4); +rustc_data_structures::static_assert_size!(ScopeData, 4); impl Scope { /// Returns an item-local ID associated with this scope. diff --git a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs index 610afd95f3c..d0103f62231 100644 --- a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs +++ b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; use rustc_hir::{ItemLocalId, OwnerId}; -use rustc_macros::HashStable; +use rustc_macros::{Decodable, Encodable, HashStable, TyDecodable, TyEncodable}; #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)] pub enum ResolvedArg { diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index c393287da95..67bd53f53da 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -14,6 +14,7 @@ use rustc_feature::GateIssue; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap}; use rustc_hir::{self as hir, HirId}; +use rustc_macros::{Decodable, Encodable, HashStable}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE}; use rustc_session::lint::{BuiltinLintDiag, Level, Lint, LintBuffer}; diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs index 1086d647721..f9398b254c7 100644 --- a/compiler/rustc_middle/src/mir/basic_blocks.rs +++ b/compiler/rustc_middle/src/mir/basic_blocks.rs @@ -7,6 +7,7 @@ use rustc_data_structures::graph::dominators::{dominators, Dominators}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::OnceLock; use rustc_index::{IndexSlice, IndexVec}; +use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use smallvec::SmallVec; diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index 6ff40c53c85..d025dc360a2 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -1,6 +1,7 @@ use std::fmt::{self, Debug, Display, Formatter}; use rustc_hir::def_id::DefId; +use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_session::{config::RemapPathScopeComponents, RemapFileNameExt}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{HasDataLayout, Size}; @@ -71,7 +72,7 @@ pub enum ConstValue<'tcx> { } #[cfg(target_pointer_width = "64")] -static_assert_size!(ConstValue<'_>, 24); +rustc_data_structures::static_assert_size!(ConstValue<'_>, 24); impl<'tcx> ConstValue<'tcx> { #[inline] diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 04011fd4194..477303e2434 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -1,7 +1,7 @@ //! Metadata from source code coverage analysis and instrumentation. use rustc_index::IndexVec; -use rustc_macros::HashStable; +use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_span::{Span, Symbol}; use std::fmt::{self, Debug, Formatter}; @@ -132,7 +132,7 @@ pub enum CoverageKind { /// /// If this statement does not survive MIR optimizations, the condition would never be /// taken as evaluated. - CondBitmapUpdate { id: ConditionId, value: bool }, + CondBitmapUpdate { id: ConditionId, value: bool, decision_depth: u16 }, /// Marks the point in MIR control flow represented by a evaluated decision. /// @@ -140,7 +140,7 @@ pub enum CoverageKind { /// /// If this statement does not survive MIR optimizations, the decision would never be /// taken as evaluated. - TestVectorBitmapUpdate { bitmap_idx: u32 }, + TestVectorBitmapUpdate { bitmap_idx: u32, decision_depth: u16 }, } impl Debug for CoverageKind { @@ -151,11 +151,17 @@ impl Debug for CoverageKind { BlockMarker { id } => write!(fmt, "BlockMarker({:?})", id.index()), CounterIncrement { id } => write!(fmt, "CounterIncrement({:?})", id.index()), ExpressionUsed { id } => write!(fmt, "ExpressionUsed({:?})", id.index()), - CondBitmapUpdate { id, value } => { - write!(fmt, "CondBitmapUpdate({:?}, {:?})", id.index(), value) + CondBitmapUpdate { id, value, decision_depth } => { + write!( + fmt, + "CondBitmapUpdate({:?}, {:?}, depth={:?})", + id.index(), + value, + decision_depth + ) } - TestVectorBitmapUpdate { bitmap_idx } => { - write!(fmt, "TestVectorUpdate({:?})", bitmap_idx) + TestVectorBitmapUpdate { bitmap_idx, decision_depth } => { + write!(fmt, "TestVectorUpdate({:?}, depth={:?})", bitmap_idx, decision_depth) } } } @@ -269,6 +275,9 @@ pub struct FunctionCoverageInfo { pub mcdc_bitmap_bytes: u32, pub expressions: IndexVec<ExpressionId, Expression>, pub mappings: Vec<Mapping>, + /// The depth of the deepest decision is used to know how many + /// temp condbitmaps should be allocated for the function. + pub mcdc_num_condition_bitmaps: usize, } /// Branch information recorded during THIR-to-MIR lowering, and stored in MIR. @@ -319,6 +328,7 @@ pub struct MCDCBranchSpan { pub condition_info: Option<ConditionInfo>, pub true_marker: BlockMarkerId, pub false_marker: BlockMarkerId, + pub decision_depth: u16, } #[derive(Copy, Clone, Debug)] @@ -334,4 +344,5 @@ pub struct MCDCDecisionSpan { pub span: Span, pub conditions_num: usize, pub end_markers: Vec<BlockMarkerId>, + pub decision_depth: u16, } diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 00faa211853..791e87735f4 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -14,6 +14,7 @@ use either::{Left, Right}; use rustc_ast::Mutability; use rustc_data_structures::intern::Interned; +use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_target::abi::{Align, HasDataLayout, Size}; use super::{ @@ -28,9 +29,7 @@ use provenance_map::*; pub use init_mask::{InitChunk, InitChunkIter}; /// Functionality required for the bytes of an `Allocation`. -pub trait AllocBytes: - Clone + fmt::Debug + Eq + PartialEq + Hash + Deref<Target = [u8]> + DerefMut<Target = [u8]> -{ +pub trait AllocBytes: Clone + fmt::Debug + Deref<Target = [u8]> + DerefMut<Target = [u8]> { /// Create an `AllocBytes` from a slice of `u8`. fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, _align: Align) -> Self; @@ -345,10 +344,10 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> { } } -impl<Bytes: AllocBytes> Allocation<CtfeProvenance, (), Bytes> { +impl Allocation { /// Adjust allocation from the ones in `tcx` to a custom Machine instance - /// with a different `Provenance` and `Extra` type. - pub fn adjust_from_tcx<Prov: Provenance, Extra, Err>( + /// with a different `Provenance`, `Extra` and `Byte` type. + pub fn adjust_from_tcx<Prov: Provenance, Extra, Bytes: AllocBytes, Err>( self, cx: &impl HasDataLayout, extra: Extra, @@ -370,7 +369,7 @@ impl<Bytes: AllocBytes> Allocation<CtfeProvenance, (), Bytes> { } // Create allocation. Ok(Allocation { - bytes, + bytes: AllocBytes::from_bytes(Cow::Owned(Vec::from(bytes)), self.align), provenance: ProvenanceMap::from_presorted_ptrs(new_provenance), init_mask: self.init_mask, align: self.align, diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs index 2c6bb908f39..d60db775ff0 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs @@ -5,6 +5,7 @@ use std::hash; use std::iter; use std::ops::Range; +use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_serialize::{Decodable, Encodable}; use rustc_target::abi::Size; use rustc_type_ir::{TyDecoder, TyEncoder}; diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs index 9459af490e3..e974279f191 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs @@ -4,6 +4,7 @@ use std::cmp; use rustc_data_structures::sorted_map::SortedMap; +use rustc_macros::HashStable; use rustc_target::abi::{HasDataLayout, Size}; use super::{alloc_range, AllocError, AllocRange, AllocResult, CtfeProvenance, Provenance}; diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index a3d16d4f097..383241465c3 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -7,7 +7,7 @@ use crate::ty::{self, layout, tls, Ty, TyCtxt, ValTree}; use rustc_ast_ir::Mutability; use rustc_data_structures::sync::Lock; use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, IntoDiagArg}; -use rustc_macros::HashStable; +use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_session::CtfeBacktrace; use rustc_span::{def_id::DefId, Span, DUMMY_SP}; use rustc_target::abi::{call, Align, Size, VariantIdx, WrappingRange}; @@ -89,7 +89,7 @@ pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>; pub type EvalToValTreeResult<'tcx> = Result<Option<ValTree<'tcx>>, ErrorHandled>; #[cfg(target_pointer_width = "64")] -static_assert_size!(InterpErrorInfo<'_>, 8); +rustc_data_structures::static_assert_size!(InterpErrorInfo<'_>, 8); /// Packages the kind of error we got from the const code interpreter /// up with a Rust-level backtrace of where the error occurred. diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 6275942bafe..ee3cdf36820 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -131,7 +131,7 @@ use rustc_data_structures::sync::{HashMapExt, Lock}; use rustc_data_structures::tiny_list::TinyList; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_macros::HashStable; +use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_serialize::{Decodable, Encodable}; use rustc_target::abi::{AddressSpace, Endian, HasDataLayout}; diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index e2767ee2989..a0acacc844f 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -1,6 +1,7 @@ use super::{AllocId, InterpResult}; -use rustc_macros::HashStable; +use rustc_data_structures::static_assert_size; +use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_target::abi::{HasDataLayout, Size}; use std::{fmt, num::NonZero}; diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 9728967860a..c5c87c506b7 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -6,7 +6,7 @@ use rustc_apfloat::{ ieee::{Double, Half, Quad, Single}, Float, }; -use rustc_macros::HashStable; +use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_target::abi::{HasDataLayout, Size}; use crate::ty::ScalarInt; @@ -38,7 +38,7 @@ pub enum Scalar<Prov = CtfeProvenance> { } #[cfg(target_pointer_width = "64")] -static_assert_size!(Scalar, 24); +rustc_data_structures::static_assert_size!(Scalar, 24); // We want the `Debug` output to be readable as it is used by `derive(Debug)` for // all the Miri types. diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 8555aa48c30..25cc9ac47c8 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -20,6 +20,7 @@ use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; use rustc_hir::{ self as hir, BindingMode, ByRef, CoroutineDesugaring, CoroutineKind, HirId, ImplicitSelfKind, }; +use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_session::Session; use rustc_span::source_map::Spanned; use rustc_target::abi::{FieldIdx, VariantIdx}; diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 9eed7019782..daab6c85581 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -1,7 +1,9 @@ use crate::dep_graph::{DepNode, WorkProduct, WorkProductId}; use crate::ty::{GenericArgs, Instance, InstanceDef, SymbolName, TyCtxt}; use rustc_attr::InlineAttr; -use rustc_data_structures::base_n; +use rustc_data_structures::base_n::BaseNString; +use rustc_data_structures::base_n::ToBaseN; +use rustc_data_structures::base_n::CASE_INSENSITIVE; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxIndexMap; @@ -9,6 +11,7 @@ use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher}; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_hir::ItemId; use rustc_index::Idx; +use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_query_system::ich::StableHashingContext; use rustc_session::config::OptLevel; use rustc_span::symbol::Symbol; @@ -336,14 +339,11 @@ impl<'tcx> CodegenUnit<'tcx> { self.is_code_coverage_dead_code_cgu = true; } - pub fn mangle_name(human_readable_name: &str) -> String { - // We generate a 80 bit hash from the name. This should be enough to - // avoid collisions and is still reasonably short for filenames. + pub fn mangle_name(human_readable_name: &str) -> BaseNString { let mut hasher = StableHasher::new(); human_readable_name.hash(&mut hasher); let hash: Hash128 = hasher.finish(); - let hash = hash.as_u128() & ((1u128 << 80) - 1); - base_n::encode(hash, base_n::CASE_INSENSITIVE) + hash.as_u128().to_base_fixed_len(CASE_INSENSITIVE) } pub fn compute_size_estimate(&mut self) { diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index a350eb05226..5aaa1c30cad 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -496,20 +496,27 @@ fn write_coverage_branch_info( )?; } - for coverage::MCDCBranchSpan { span, condition_info, true_marker, false_marker } in - mcdc_branch_spans + for coverage::MCDCBranchSpan { + span, + condition_info, + true_marker, + false_marker, + decision_depth, + } in mcdc_branch_spans { writeln!( w, - "{INDENT}coverage mcdc branch {{ condition_id: {:?}, true: {true_marker:?}, false: {false_marker:?} }} => {span:?}", + "{INDENT}coverage mcdc branch {{ condition_id: {:?}, true: {true_marker:?}, false: {false_marker:?}, depth: {decision_depth:?} }} => {span:?}", condition_info.map(|info| info.condition_id) )?; } - for coverage::MCDCDecisionSpan { span, conditions_num, end_markers } in mcdc_decision_spans { + for coverage::MCDCDecisionSpan { span, conditions_num, end_markers, decision_depth } in + mcdc_decision_spans + { writeln!( w, - "{INDENT}coverage mcdc decision {{ conditions_num: {conditions_num:?}, end: {end_markers:?} }} => {span:?}" + "{INDENT}coverage mcdc decision {{ conditions_num: {conditions_num:?}, end: {end_markers:?}, depth: {decision_depth:?} }} => {span:?}" )?; } diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index e3f58729fbd..9a7af6135e4 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -7,6 +7,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::LocalDefId; use rustc_index::bit_set::BitMatrix; use rustc_index::{Idx, IndexVec}; +use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_span::symbol::Symbol; use rustc_span::Span; use rustc_target::abi::{FieldIdx, VariantIdx}; diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 5ddd71178ca..4278ce823d0 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -17,6 +17,7 @@ use rustc_data_structures::packed::Pu128; use rustc_hir::def_id::DefId; use rustc_hir::CoroutineKind; use rustc_index::IndexVec; +use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_span::source_map::Spanned; use rustc_target::abi::{FieldIdx, VariantIdx}; @@ -1522,6 +1523,7 @@ pub enum BinOp { #[cfg(target_pointer_width = "64")] mod size_asserts { use super::*; + use rustc_data_structures::static_assert_size; // tidy-alphabetical-start static_assert_size!(AggregateKind<'_>, 32); static_assert_size!(Operand<'_>, 24); diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index ded2b93d6a1..3881723c5ec 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -15,7 +15,7 @@ pub struct PlaceTy<'tcx> { // At least on 64 bit systems, `PlaceTy` should not be larger than two or three pointers. #[cfg(target_pointer_width = "64")] -static_assert_size!(PlaceTy<'_>, 16); +rustc_data_structures::static_assert_size!(PlaceTy<'_>, 16); impl<'tcx> PlaceTy<'tcx> { #[inline] diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 58a27c1f9ef..f95afb199f7 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -1,10 +1,10 @@ /// Functionality for terminators and helper types that appear in terminators. use rustc_hir::LangItem; -use smallvec::SmallVec; +use smallvec::{smallvec, SmallVec}; use super::TerminatorKind; use rustc_data_structures::packed::Pu128; -use rustc_macros::HashStable; +use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use std::slice; use super::*; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index a5d21c47e5b..c2f7a227f66 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -72,6 +72,7 @@ use rustc_hir::def_id::{ use rustc_hir::lang_items::{LangItem, LanguageItems}; use rustc_hir::{Crate, ItemLocalId, ItemLocalMap, TraitCandidate}; use rustc_index::IndexVec; +use rustc_macros::rustc_queries; use rustc_query_system::ich::StableHashingContext; use rustc_query_system::query::{try_get_cached, QueryCache, QueryMode, QueryState}; use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; @@ -846,8 +847,10 @@ rustc_queries! { separate_provide_extern } - query issue33140_self_ty(key: DefId) -> Option<ty::EarlyBinder<ty::Ty<'tcx>>> { - desc { |tcx| "computing Self type wrt issue #33140 `{}`", tcx.def_path_str(key) } + query self_ty_of_trait_impl_enabling_order_dep_trait_object_hack( + key: DefId + ) -> Option<ty::EarlyBinder<ty::Ty<'tcx>>> { + desc { |tcx| "computing self type wrt issue #33140 `{}`", tcx.def_path_str(key) } } /// Maps a `DefId` of a type to a list of its inherent impls. diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index db1b5a74f0a..2dcb58729ff 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -6,6 +6,7 @@ use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, StableCrateId, LOCAL_CRATE}; use rustc_hir::definitions::DefPathHash; use rustc_index::{Idx, IndexVec}; +use rustc_macros::{Decodable, Encodable}; use rustc_middle::dep_graph::{DepNodeIndex, SerializedDepNodeIndex}; use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use rustc_middle::mir::{self, interpret}; diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 038d3fe93c4..8a4e3ab0e61 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -12,6 +12,7 @@ use rustc_data_structures::sync::AtomicU64; use rustc_data_structures::sync::WorkerLocal; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::hir_id::OwnerId; +use rustc_macros::HashStable; use rustc_query_system::dep_graph::DepNodeIndex; use rustc_query_system::dep_graph::SerializedDepNodeIndex; pub(crate) use rustc_query_system::query::QueryJobId; diff --git a/compiler/rustc_middle/src/tests.rs b/compiler/rustc_middle/src/tests.rs index 49960cc0bb2..6c2e5f63418 100644 --- a/compiler/rustc_middle/src/tests.rs +++ b/compiler/rustc_middle/src/tests.rs @@ -1,13 +1,9 @@ -use super::*; - -// FIXME(#27438): right now the unit tests of rustc_middle don't refer to any actual -// functions generated in rustc_data_structures (all -// references are through generic functions), but statics are -// referenced from time to time. Due to this bug we won't -// actually correctly link in the statics unless we also -// reference a function, so be sure to reference a dummy -// function. +// FIXME(#27438): Right now, the unit tests of `rustc_middle` don't refer to any actual functions +// generated in `rustc_data_structures` (all references are through generic functions), +// but statics are referenced from time to time. Due to this Windows `dllimport` bug +// we won't actually correctly link in the statics unless we also reference a function, +// so be sure to reference a dummy function. #[test] fn noop() { - rustc_data_structures::__noop_fix_for_27438(); + rustc_data_structures::__noop_fix_for_windows_dllimport_issue(); } diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 99498fedcca..a7d8ead5677 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -15,6 +15,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::{BindingMode, ByRef, HirId, MatchSource, RangeEnd}; use rustc_index::newtype_index; use rustc_index::IndexVec; +use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeVisitable}; use rustc_middle::middle::region; use rustc_middle::mir::interpret::AllocId; use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, UnOp}; @@ -1209,6 +1210,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> { #[cfg(target_pointer_width = "64")] mod size_asserts { use super::*; + use rustc_data_structures::static_assert_size; // tidy-alphabetical-start static_assert_size!(Block, 48); static_assert_size!(Expr<'_>, 64); diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index b1e34dcd5f3..1ae037e09a7 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -20,10 +20,13 @@ use rustc_errors::{Applicability, Diag, EmissionGuarantee}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::HirId; +use rustc_macros::{ + Decodable, Encodable, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable, +}; use rustc_span::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; -use smallvec::SmallVec; +use smallvec::{smallvec, SmallVec}; use std::borrow::Cow; use std::hash::{Hash, Hasher}; @@ -557,7 +560,7 @@ impl<'tcx> ObligationCauseCode<'tcx> { // `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_pointer_width = "64")] -static_assert_size!(ObligationCauseCode<'_>, 48); +rustc_data_structures::static_assert_size!(ObligationCauseCode<'_>, 48); #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum StatementAsExpression { diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index 12e4f70ba57..70f3532e3ab 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -10,11 +10,13 @@ use crate::infer::canonical::{Canonical, QueryResponse}; use crate::ty::error::TypeError; use crate::ty::GenericArg; use crate::ty::{self, Ty, TyCtxt}; +use rustc_macros::{HashStable, TypeFoldable, TypeVisitable}; use rustc_span::Span; pub mod type_op { use crate::ty::fold::TypeFoldable; use crate::ty::{Predicate, Ty, TyCtxt, UserType}; + use rustc_macros::{HashStable, TypeFoldable, TypeVisitable}; use std::fmt; #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)] diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index c35524373c7..c8caf228ffb 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -10,6 +10,7 @@ use rustc_errors::ErrorGuaranteed; use crate::ty; use rustc_hir::def_id::DefId; +use rustc_macros::{HashStable, TypeVisitable}; use rustc_query_system::cache::Cache; pub type SelectionCache<'tcx> = Cache< diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 13504c6ae93..3ad6b68d129 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -1,5 +1,6 @@ use rustc_ast_ir::try_visit; use rustc_data_structures::intern::Interned; +use rustc_macros::{HashStable, TypeFoldable, TypeVisitable}; use rustc_span::def_id::DefId; use crate::infer::canonical::{CanonicalVarValues, QueryRegionConstraints}; @@ -272,6 +273,8 @@ pub enum GoalSource { /// they are from an impl where-clause. This is necessary due to /// backwards compatability, cc trait-system-refactor-initiatitive#70. ImplWhereBound, + /// Instantiating a higher-ranked goal and re-proving it. + InstantiateHigherRanked, } /// Possible ways the given goal can be proven. @@ -332,4 +335,9 @@ pub enum CandidateSource { /// } /// ``` AliasBound, + /// A candidate that is registered only during coherence to represent some + /// yet-unknown impl that could be produced downstream without violating orphan + /// rules. + // FIXME: Merge this with the forced ambiguity candidates, so those don't use `Misc`. + CoherenceUnknowable, } diff --git a/compiler/rustc_middle/src/traits/solve/inspect.rs b/compiler/rustc_middle/src/traits/solve/inspect.rs index f2283e71dc8..cddf9d5f874 100644 --- a/compiler/rustc_middle/src/traits/solve/inspect.rs +++ b/compiler/rustc_middle/src/traits/solve/inspect.rs @@ -24,6 +24,7 @@ use super::{ }; use crate::{infer::canonical::CanonicalVarValues, ty}; use format::ProofTreeFormatter; +use rustc_macros::{TypeFoldable, TypeVisitable}; use std::fmt::{Debug, Write}; mod format; @@ -60,14 +61,14 @@ pub struct GoalEvaluation<'tcx> { pub evaluation: CanonicalGoalEvaluation<'tcx>, } -#[derive(Eq, PartialEq)] +#[derive(Eq, PartialEq, Debug)] pub struct CanonicalGoalEvaluation<'tcx> { pub goal: CanonicalInput<'tcx>, pub kind: CanonicalGoalEvaluationKind<'tcx>, pub result: QueryResult<'tcx>, } -#[derive(Eq, PartialEq)] +#[derive(Eq, PartialEq, Debug)] pub enum CanonicalGoalEvaluationKind<'tcx> { Overflow, CycleInStack, @@ -86,7 +87,7 @@ pub struct AddedGoalsEvaluation<'tcx> { pub result: Result<Certainty, NoSolution>, } -#[derive(Eq, PartialEq)] +#[derive(Eq, PartialEq, Debug)] pub struct GoalEvaluationStep<'tcx> { pub instantiated_goal: QueryInput<'tcx, ty::Predicate<'tcx>>, @@ -122,6 +123,12 @@ pub enum ProbeStep<'tcx> { /// used whenever there are multiple candidates to prove the /// current goalby . NestedProbe(Probe<'tcx>), + /// A call to `EvalCtxt::evaluate_added_goals_make_canonical_response` with + /// `Certainty` was made. This is the certainty passed in, so it's not unified + /// with the certainty of the `try_evaluate_added_goals` that is done within; + /// if it's `Certainty::Yes`, then we can trust that the candidate is "finished" + /// and we didn't force ambiguity for some reason. + MakeCanonicalResponse { shallow_certainty: Certainty }, } /// What kind of probe we're in. In case the probe represents a candidate, or @@ -135,10 +142,6 @@ pub enum ProbeKind<'tcx> { TryNormalizeNonRigid { result: QueryResult<'tcx> }, /// Probe entered when normalizing the self ty during candidate assembly NormalizedSelfTyAssembly, - /// Some candidate to prove the current goal. - /// - /// FIXME: Remove this in favor of always using more strongly typed variants. - MiscCandidate { name: &'static str, result: QueryResult<'tcx> }, /// A candidate for proving a trait or alias-relate goal. TraitCandidate { source: CandidateSource, result: QueryResult<'tcx> }, /// Used in the probe that wraps normalizing the non-self type for the unsize @@ -148,4 +151,6 @@ pub enum ProbeKind<'tcx> { /// do a probe to find out what projection type(s) may be used to prove that /// the source type upholds all of the target type's object bounds. UpcastProjectionCompatibility, + /// Try to unify an opaque type with an existing key in the storage. + OpaqueTypeStorageLookup { result: QueryResult<'tcx> }, } diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs index 98f01fe8772..11aa0e10931 100644 --- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs +++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs @@ -112,8 +112,8 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { ProbeKind::UpcastProjectionCompatibility => { write!(self.f, "PROBING FOR PROJECTION COMPATIBILITY FOR UPCASTING:") } - ProbeKind::MiscCandidate { name, result } => { - write!(self.f, "CANDIDATE {name}: {result:?}") + ProbeKind::OpaqueTypeStorageLookup { result } => { + write!(self.f, "PROBING FOR AN EXISTING OPAQUE: {result:?}") } ProbeKind::TraitCandidate { source, result } => { write!(self.f, "CANDIDATE {source:?}: {result:?}") @@ -127,11 +127,15 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { let source = match source { GoalSource::Misc => "misc", GoalSource::ImplWhereBound => "impl where-bound", + GoalSource::InstantiateHigherRanked => "higher-ranked goal", }; writeln!(this.f, "ADDED GOAL ({source}): {goal:?}")? } ProbeStep::EvaluateGoals(eval) => this.format_added_goals_evaluation(eval)?, ProbeStep::NestedProbe(probe) => this.format_probe(probe)?, + ProbeStep::MakeCanonicalResponse { shallow_certainty } => { + writeln!(this.f, "EVALUATE GOALS AND MAKE RESPONSE: {shallow_certainty:?}")? + } } } Ok(()) diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs index ba29d4040a1..ff5d51bcb66 100644 --- a/compiler/rustc_middle/src/traits/specialization_graph.rs +++ b/compiler/rustc_middle/src/traits/specialization_graph.rs @@ -5,6 +5,7 @@ use crate::ty::{self, TyCtxt}; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::{DefId, DefIdMap}; +use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_span::symbol::sym; /// A per-trait graph of impls in specialization order. At the moment, this diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs index 570f896ba29..dc46b470b6f 100644 --- a/compiler/rustc_middle/src/ty/abstract_const.rs +++ b/compiler/rustc_middle/src/ty/abstract_const.rs @@ -4,6 +4,7 @@ use crate::ty::{ TypeVisitableExt, }; use rustc_errors::ErrorGuaranteed; +use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeVisitable}; #[derive(Hash, Debug, Clone, Copy, Ord, PartialOrd, PartialEq, Eq)] #[derive(TyDecodable, TyEncodable, HashStable, TypeVisitable, TypeFoldable)] diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs index c3e8991c63a..9badf65115e 100644 --- a/compiler/rustc_middle/src/ty/adjustment.rs +++ b/compiler/rustc_middle/src/ty/adjustment.rs @@ -1,7 +1,7 @@ use crate::ty::{self, Ty, TyCtxt}; use rustc_hir as hir; use rustc_hir::lang_items::LangItem; -use rustc_macros::HashStable; +use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_span::Span; use rustc_target::abi::FieldIdx; diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index a7f1ba46b61..77da3fbe1d7 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -12,6 +12,7 @@ use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_index::{IndexSlice, IndexVec}; +use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_query_system::ich::StableHashingContext; use rustc_session::DataTypeKind; use rustc_span::symbol::sym; @@ -26,7 +27,7 @@ use super::{Destructor, FieldDef, GenericPredicates, Ty, TyCtxt, VariantDef, Var #[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)] pub struct AdtFlags(u16); -bitflags! { +bitflags::bitflags! { impl AdtFlags: u16 { const NO_ADT_FLAGS = 0; /// Indicates whether the ADT is an enum. @@ -582,8 +583,7 @@ impl<'tcx> AdtDef<'tcx> { } } -#[derive(Clone, Copy, Debug)] -#[derive(HashStable)] +#[derive(Clone, Copy, Debug, HashStable)] pub enum Representability { Representable, Infinite(ErrorGuaranteed), diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index 94a5ff13158..1cdde3f057c 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -3,6 +3,7 @@ use rustc_data_structures::sorted_map::SortedIndexMultiMap; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace}; use rustc_hir::def_id::DefId; +use rustc_macros::{Decodable, Encodable, HashStable}; use rustc_span::symbol::{Ident, Symbol}; use super::{TyCtxt, Visibility}; diff --git a/compiler/rustc_middle/src/ty/cast.rs b/compiler/rustc_middle/src/ty/cast.rs index c9fd20bc112..26c5a865fdc 100644 --- a/compiler/rustc_middle/src/ty/cast.rs +++ b/compiler/rustc_middle/src/ty/cast.rs @@ -4,7 +4,7 @@ use crate::ty::{self, Ty}; use rustc_middle::mir; -use rustc_macros::HashStable; +use rustc_macros::{HashStable, TyDecodable, TyEncodable}; /// Types that are represented as ints. #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index b66c664e6ae..bade0d56415 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -11,6 +11,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::HirId; +use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_span::def_id::LocalDefIdMap; use rustc_span::symbol::Ident; use rustc_span::{Span, Symbol}; @@ -423,7 +424,7 @@ pub fn analyze_coroutine_closure_captures<'a, 'tcx: 'a, T>( mut for_each: impl FnMut((usize, &'a CapturedPlace<'tcx>), (usize, &'a CapturedPlace<'tcx>)) -> T, ) -> impl Iterator<Item = T> + Captures<'a> + Captures<'tcx> { std::iter::from_coroutine( - #[cfg_attr(not(bootstrap), coroutine)] + #[coroutine] move || { let mut child_captures = child_captures.into_iter().enumerate().peekable(); diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index fd4573c1603..a65b3a41ade 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -6,7 +6,7 @@ use rustc_error_messages::MultiSpan; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::LocalDefId; -use rustc_macros::HashStable; +use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_type_ir::ConstKind as IrConstKind; use rustc_type_ir::{ConstTy, IntoKind, TypeFlags, WithCachedTypeInfo}; @@ -23,7 +23,7 @@ pub use valtree::*; pub type ConstKind<'tcx> = IrConstKind<TyCtxt<'tcx>>; #[cfg(target_pointer_width = "64")] -static_assert_size!(ConstKind<'_>, 32); +rustc_data_structures::static_assert_size!(ConstKind<'_>, 32); /// Use this rather than `ConstData`, whenever possible. #[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)] @@ -63,7 +63,7 @@ pub struct ConstData<'tcx> { } #[cfg(target_pointer_width = "64")] -static_assert_size!(ConstData<'_>, 40); +rustc_data_structures::static_assert_size!(ConstData<'_>, 40); impl<'tcx> Const<'tcx> { #[inline] diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index a7e0a0402ce..7e49b0ac915 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -4,7 +4,7 @@ use crate::ty::abstract_const::CastKind; use crate::ty::GenericArgsRef; use crate::ty::{self, visit::TypeVisitableExt as _, List, Ty, TyCtxt}; use rustc_hir::def_id::DefId; -use rustc_macros::HashStable; +use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; /// An unevaluated (potentially generic) constant used in the type-system. #[derive(Copy, Clone, Eq, PartialEq, TyEncodable, TyDecodable)] @@ -72,4 +72,4 @@ pub enum Expr<'tcx> { } #[cfg(target_pointer_width = "64")] -static_assert_size!(Expr<'_>, 24); +rustc_data_structures::static_assert_size!(Expr<'_>, 24); diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 45fa5e8f7ca..d2eacdf762f 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -56,7 +56,7 @@ use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::{HirId, Node, TraitCandidate}; use rustc_index::IndexVec; -use rustc_macros::HashStable; +use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_query_system::dep_graph::DepNodeIndex; use rustc_query_system::ich::StableHashingContext; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; @@ -1285,7 +1285,7 @@ impl<'tcx> TyCtxt<'tcx> { let definitions = &self.untracked.definitions; std::iter::from_coroutine( - #[cfg_attr(not(bootstrap), coroutine)] + #[coroutine] || { let mut i = 0; diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index ce85c28ece8..71437ce1df9 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -4,6 +4,7 @@ use rustc_errors::pluralize; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind}; use rustc_hir::def_id::DefId; +use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_span::symbol::Symbol; use rustc_target::spec::abi; use std::borrow::Cow; diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 10b0909209a..8d7489f5f7e 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -2,6 +2,7 @@ use crate::mir::Mutability; use crate::ty::GenericArgKind; use crate::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt}; use rustc_hir::def_id::DefId; +use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use std::fmt::Debug; use std::hash::Hash; use std::iter; @@ -329,20 +330,19 @@ impl DeepRejectCtxt { } pub fn consts_may_unify(self, obligation_ct: ty::Const<'_>, impl_ct: ty::Const<'_>) -> bool { - match impl_ct.kind() { + let impl_val = match impl_ct.kind() { ty::ConstKind::Expr(_) | ty::ConstKind::Param(_) | ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => { return true; } - ty::ConstKind::Value(_) => {} + ty::ConstKind::Value(impl_val) => impl_val, ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => { bug!("unexpected impl arg: {:?}", impl_ct) } - } + }; - let k = impl_ct.kind(); match obligation_ct.kind() { ty::ConstKind::Param(_) => match self.treat_obligation_params { TreatParams::ForLookup => false, @@ -357,10 +357,7 @@ impl DeepRejectCtxt { ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => { true } - ty::ConstKind::Value(obl) => match k { - ty::ConstKind::Value(imp) => obl == imp, - _ => true, - }, + ty::ConstKind::Value(obl_val) => obl_val == impl_val, ty::ConstKind::Infer(_) => true, diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 19cef927faf..de2c01c3046 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -11,7 +11,9 @@ use rustc_ast_ir::walk_visitable_list; use rustc_data_structures::intern::Interned; use rustc_errors::{DiagArgValue, IntoDiagArg}; use rustc_hir::def_id::DefId; -use rustc_macros::HashStable; +use rustc_macros::{ + Decodable, Encodable, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable, +}; use rustc_serialize::{Decodable, Encodable}; use rustc_type_ir::WithCachedTypeInfo; use smallvec::SmallVec; diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index a99196cb363..6bf2051d67c 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -3,6 +3,7 @@ use crate::ty::{EarlyBinder, GenericArgsRef}; use rustc_ast as ast; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::DefId; +use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_span::symbol::{kw, Symbol}; use rustc_span::Span; diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs index c571ac50724..e3eea83ba49 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs @@ -1,3 +1,4 @@ +use rustc_macros::HashStable; use smallvec::SmallVec; use crate::ty::context::TyCtxt; diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 4002d0da790..a08fde976bc 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -8,7 +8,9 @@ use rustc_hir::def::Namespace; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::FiniteBitSet; -use rustc_macros::HashStable; +use rustc_macros::{ + Decodable, Encodable, HashStable, Lift, TyDecodable, TyEncodable, TypeVisitable, +}; use rustc_middle::ty::normalize_erasing_regions::NormalizationError; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::Symbol; diff --git a/compiler/rustc_middle/src/ty/intrinsic.rs b/compiler/rustc_middle/src/ty/intrinsic.rs index 18d08ed23a5..68c1d8c17ec 100644 --- a/compiler/rustc_middle/src/ty/intrinsic.rs +++ b/compiler/rustc_middle/src/ty/intrinsic.rs @@ -1,3 +1,4 @@ +use rustc_macros::{Decodable, Encodable, HashStable}; use rustc_span::{def_id::DefId, Symbol}; use super::TyCtxt; diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 897d6f5662f..f8490e5e15f 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -10,6 +10,7 @@ use rustc_errors::{ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_index::IndexVec; +use rustc_macros::{extension, HashStable, TyDecodable, TyEncodable}; use rustc_session::config::OptLevel; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP}; @@ -124,7 +125,7 @@ impl Primitive { F64 => tcx.types.f64, F128 => tcx.types.f128, // FIXME(erikdesjardins): handle non-default addrspace ptr sizes - Pointer(_) => Ty::new_mut_ptr(tcx, Ty::new_unit(tcx)), + Pointer(_) => Ty::new_mut_ptr(tcx, tcx.types.unit), } } @@ -774,7 +775,7 @@ where // (which may have no non-DST form), and will work as long // as the `Abi` or `FieldsShape` is checked by users. if i == 0 { - let nil = Ty::new_unit(tcx); + let nil = tcx.types.unit; let unit_ptr_ty = if this.ty.is_unsafe_ptr() { Ty::new_mut_ptr(tcx, nil) } else { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 094b68ce5ad..73b20f0485b 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -47,7 +47,9 @@ use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap}; use rustc_index::IndexVec; -use rustc_macros::HashStable; +use rustc_macros::{ + Decodable, Encodable, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable, +}; use rustc_query_system::ich::StableHashingContext; use rustc_serialize::{Decodable, Encodable}; use rustc_session::lint::LintBuffer; @@ -1083,7 +1085,7 @@ struct ParamTag { reveal: traits::Reveal, } -impl_tag! { +rustc_data_structures::impl_tag! { impl Tag for ParamTag; ParamTag { reveal: traits::Reveal::UserFacing }, ParamTag { reveal: traits::Reveal::All }, @@ -1222,7 +1224,7 @@ pub struct Destructor { #[derive(Clone, Copy, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] pub struct VariantFlags(u8); -bitflags! { +bitflags::bitflags! { impl VariantFlags: u8 { const NO_VARIANT_FLAGS = 0; /// Indicates whether the field list of this variant is `#[non_exhaustive]`. @@ -1501,14 +1503,14 @@ pub enum ImplOverlapKind { /// Whether or not the impl is permitted due to the trait being a `#[marker]` trait marker: bool, }, - /// These impls are allowed to overlap, but that raises - /// an issue #33140 future-compatibility warning. + /// These impls are allowed to overlap, but that raises an + /// issue #33140 future-compatibility warning (tracked in #56484). /// /// Some background: in Rust 1.0, the trait-object types `Send + Sync` (today's /// `dyn Send + Sync`) and `Sync + Send` (now `dyn Sync + Send`) were different. /// - /// The widely-used version 0.1.0 of the crate `traitobject` had accidentally relied - /// that difference, making what reduces to the following set of impls: + /// The widely-used version 0.1.0 of the crate `traitobject` had accidentally relied on + /// that difference, doing what reduces to the following set of impls: /// /// ```compile_fail,(E0119) /// trait Trait {} @@ -1533,7 +1535,7 @@ pub enum ImplOverlapKind { /// 4. Neither of the impls can have any where-clauses. /// /// Once `traitobject` 0.1.0 is no longer an active concern, this hack can be removed. - Issue33140, + FutureCompatOrderDepTraitObjects, } /// Useful source information about where a desugared associated type for an @@ -1728,27 +1730,26 @@ impl<'tcx> TyCtxt<'tcx> { | (ImplPolarity::Negative, ImplPolarity::Negative) => {} }; - let is_marker_overlap = { - let is_marker_impl = - |trait_ref: TraitRef<'_>| -> bool { self.trait_def(trait_ref.def_id).is_marker }; - is_marker_impl(trait_ref1) && is_marker_impl(trait_ref2) - }; + let is_marker_impl = |trait_ref: TraitRef<'_>| self.trait_def(trait_ref.def_id).is_marker; + let is_marker_overlap = is_marker_impl(trait_ref1) && is_marker_impl(trait_ref2); if is_marker_overlap { - Some(ImplOverlapKind::Permitted { marker: true }) - } else { - if let Some(self_ty1) = self.issue33140_self_ty(def_id1) { - if let Some(self_ty2) = self.issue33140_self_ty(def_id2) { - if self_ty1 == self_ty2 { - return Some(ImplOverlapKind::Issue33140); - } else { - debug!("found {self_ty1:?} != {self_ty2:?}"); - } - } - } + return Some(ImplOverlapKind::Permitted { marker: true }); + } - None + if let Some(self_ty1) = + self.self_ty_of_trait_impl_enabling_order_dep_trait_object_hack(def_id1) + && let Some(self_ty2) = + self.self_ty_of_trait_impl_enabling_order_dep_trait_object_hack(def_id2) + { + if self_ty1 == self_ty2 { + return Some(ImplOverlapKind::FutureCompatOrderDepTraitObjects); + } else { + debug!("found {self_ty1:?} != {self_ty2:?}"); + } } + + None } /// Returns `ty::VariantDef` if `res` refers to a struct, diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index 58543674460..791f27a9789 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -10,6 +10,7 @@ use crate::traits::query::NoSolution; use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder}; use crate::ty::{self, EarlyBinder, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt}; +use rustc_macros::{HashStable, TyDecodable, TyEncodable}; #[derive(Debug, Copy, Clone, HashStable, TyEncodable, TyDecodable)] pub enum NormalizationError<'tcx> { diff --git a/compiler/rustc_middle/src/ty/pattern.rs b/compiler/rustc_middle/src/ty/pattern.rs index 8a41ba257ec..d1875fbaea3 100644 --- a/compiler/rustc_middle/src/ty/pattern.rs +++ b/compiler/rustc_middle/src/ty/pattern.rs @@ -2,6 +2,7 @@ use std::fmt; use crate::ty; use rustc_data_structures::intern::Interned; +use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; #[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)] #[rustc_pass_by_value] diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index 05156dd5205..56dd52567fd 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -3,6 +3,7 @@ use rustc_data_structures::intern::Interned; use rustc_errors::{DiagArgValue, IntoDiagArg}; use rustc_hir::def_id::DefId; use rustc_hir::LangItem; +use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_span::Span; use rustc_type_ir::ClauseKind as IrClauseKind; use rustc_type_ir::PredicateKind as IrPredicateKind; diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index e5450182bf2..5f47aef0f32 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -16,6 +16,7 @@ use rustc_hir::def::{self, CtorKind, DefKind, Namespace}; use rustc_hir::def_id::{DefIdMap, DefIdSet, ModDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPathDataName}; use rustc_hir::LangItem; +use rustc_macros::Lift; use rustc_session::cstore::{ExternCrate, ExternCrateSource}; use rustc_session::Limit; use rustc_span::symbol::{kw, Ident, Symbol}; diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index b92800a1728..3d9be15310f 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -3,6 +3,7 @@ use rustc_data_structures::intern::Interned; use rustc_errors::MultiSpan; use rustc_hir::def_id::DefId; use rustc_index::Idx; +use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_span::symbol::sym; use rustc_span::symbol::{kw, Symbol}; use rustc_span::{ErrorGuaranteed, DUMMY_SP}; diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 3c1dea1d9f2..7063ef07201 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -10,6 +10,7 @@ use crate::ty::{GenericArg, GenericArgKind, GenericArgsRef}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; +use rustc_macros::TypeVisitable; use rustc_target::spec::abi; use std::iter; diff --git a/compiler/rustc_middle/src/ty/rvalue_scopes.rs b/compiler/rustc_middle/src/ty/rvalue_scopes.rs index 17eabec257e..cb2f7284eaa 100644 --- a/compiler/rustc_middle/src/ty/rvalue_scopes.rs +++ b/compiler/rustc_middle/src/ty/rvalue_scopes.rs @@ -1,6 +1,7 @@ use crate::middle::region::{Scope, ScopeData, ScopeTree}; use rustc_hir as hir; use rustc_hir::ItemLocalMap; +use rustc_macros::{HashStable, TyDecodable, TyEncodable}; /// `RvalueScopes` is a mapping from sub-expressions to _extended_ lifetime as determined by /// rules laid out in `rustc_hir_analysis::check::rvalue_scopes`. diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 0184ff54979..de70c4f7b65 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -17,7 +17,7 @@ use rustc_errors::{DiagArgValue, ErrorGuaranteed, IntoDiagArg, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::LangItem; -use rustc_macros::HashStable; +use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; @@ -1751,11 +1751,6 @@ impl<'tcx> Ty<'tcx> { // misc #[inline] - pub fn new_unit(tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - tcx.types.unit - } - - #[inline] pub fn new_static_str(tcx: TyCtxt<'tcx>) -> Ty<'tcx> { Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, tcx.types.str_) } diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index e06e3465eb2..cf5decffea9 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -8,7 +8,7 @@ use std::iter; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorGuaranteed; -use rustc_macros::HashStable; +use rustc_macros::{Decodable, Encodable, HashStable}; /// A trait's definition with type information. #[derive(HashStable, Encodable, Decodable)] diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 0c4409197bb..41f417dfd4b 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -18,7 +18,7 @@ use rustc_hir::{ BindingMode, ByRef, HirId, ItemLocalId, ItemLocalMap, ItemLocalSet, Mutability, }; use rustc_index::IndexVec; -use rustc_macros::HashStable; +use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_middle::mir::FakeReadCause; use rustc_session::Session; use rustc_span::Span; diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 42e0565db83..f5e973f85da 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -17,12 +17,12 @@ use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_index::bit_set::GrowableBitSet; -use rustc_macros::HashStable; +use rustc_macros::{extension, HashStable, TyDecodable, TyEncodable}; use rustc_session::Limit; use rustc_span::sym; use rustc_target::abi::{Integer, IntegerType, Primitive, Size}; use rustc_target::spec::abi::Abi; -use smallvec::SmallVec; +use smallvec::{smallvec, SmallVec}; use std::{fmt, iter}; #[derive(Copy, Clone, Debug)] diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs index 62f41921d88..2ad19431310 100644 --- a/compiler/rustc_middle/src/ty/vtable.rs +++ b/compiler/rustc_middle/src/ty/vtable.rs @@ -3,6 +3,7 @@ use std::fmt; use crate::mir::interpret::{alloc_range, AllocId, Allocation, Pointer, Scalar}; use crate::ty::{self, Instance, PolyTraitRef, Ty, TyCtxt}; use rustc_ast::Mutability; +use rustc_macros::HashStable; #[derive(Clone, Copy, PartialEq, HashStable)] pub enum VtblEntry<'tcx> { diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 7069bdcbcb9..089e61749c3 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -4,7 +4,7 @@ use crate::ty::{self, Ty}; use crate::ty::{GenericArg, GenericArgKind}; use rustc_data_structures::sso::SsoHashSet; -use smallvec::SmallVec; +use smallvec::{smallvec, SmallVec}; // The TypeWalker's stack is hot enough that it's worth going to some effort to // avoid heap allocations. diff --git a/compiler/rustc_mir_build/src/build/coverageinfo.rs b/compiler/rustc_mir_build/src/build/coverageinfo.rs index 9e9ccd3dc2d..e2a5f97a847 100644 --- a/compiler/rustc_mir_build/src/build/coverageinfo.rs +++ b/compiler/rustc_mir_build/src/build/coverageinfo.rs @@ -1,31 +1,25 @@ +mod mcdc; use std::assert_matches::assert_matches; use std::collections::hash_map::Entry; -use std::collections::VecDeque; use rustc_data_structures::fx::FxHashMap; -use rustc_middle::mir::coverage::{ - BlockMarkerId, BranchSpan, ConditionId, ConditionInfo, CoverageKind, MCDCBranchSpan, - MCDCDecisionSpan, -}; +use rustc_middle::mir::coverage::{BlockMarkerId, BranchSpan, CoverageKind}; use rustc_middle::mir::{self, BasicBlock, SourceInfo, UnOp}; -use rustc_middle::thir::{ExprId, ExprKind, LogicalOp, Thir}; +use rustc_middle::thir::{ExprId, ExprKind, Thir}; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::LocalDefId; -use rustc_span::Span; +use crate::build::coverageinfo::mcdc::MCDCInfoBuilder; use crate::build::{Builder, CFG}; -use crate::errors::MCDCExceedsConditionNumLimit; pub(crate) struct BranchInfoBuilder { /// Maps condition expressions to their enclosing `!`, for better instrumentation. nots: FxHashMap<ExprId, NotInfo>, - num_block_markers: usize, + markers: BlockMarkerGen, branch_spans: Vec<BranchSpan>, - mcdc_branch_spans: Vec<MCDCBranchSpan>, - mcdc_decision_spans: Vec<MCDCDecisionSpan>, - mcdc_state: Option<MCDCState>, + mcdc_info: Option<MCDCInfoBuilder>, } #[derive(Clone, Copy)] @@ -38,6 +32,35 @@ struct NotInfo { is_flipped: bool, } +#[derive(Default)] +struct BlockMarkerGen { + num_block_markers: usize, +} + +impl BlockMarkerGen { + fn next_block_marker_id(&mut self) -> BlockMarkerId { + let id = BlockMarkerId::from_usize(self.num_block_markers); + self.num_block_markers += 1; + id + } + + fn inject_block_marker( + &mut self, + cfg: &mut CFG<'_>, + source_info: SourceInfo, + block: BasicBlock, + ) -> BlockMarkerId { + let id = self.next_block_marker_id(); + let marker_statement = mir::Statement { + source_info, + kind: mir::StatementKind::Coverage(CoverageKind::BlockMarker { id }), + }; + cfg.push(block, marker_statement); + + id + } +} + impl BranchInfoBuilder { /// Creates a new branch info builder, but only if branch coverage instrumentation /// is enabled and `def_id` represents a function that is eligible for coverage. @@ -45,11 +68,9 @@ impl BranchInfoBuilder { if tcx.sess.instrument_coverage_branch() && tcx.is_eligible_for_coverage(def_id) { Some(Self { nots: FxHashMap::default(), - num_block_markers: 0, + markers: BlockMarkerGen::default(), branch_spans: vec![], - mcdc_branch_spans: vec![], - mcdc_decision_spans: vec![], - mcdc_state: MCDCState::new_if_enabled(tcx), + mcdc_info: tcx.sess.instrument_coverage_mcdc().then(MCDCInfoBuilder::new), }) } else { None @@ -96,44 +117,6 @@ impl BranchInfoBuilder { } } - fn fetch_mcdc_condition_info( - &mut self, - tcx: TyCtxt<'_>, - true_marker: BlockMarkerId, - false_marker: BlockMarkerId, - ) -> Option<ConditionInfo> { - let mcdc_state = self.mcdc_state.as_mut()?; - let (mut condition_info, decision_result) = - mcdc_state.take_condition(true_marker, false_marker); - if let Some(decision) = decision_result { - match decision.conditions_num { - 0 => { - unreachable!("Decision with no condition is not expected"); - } - 1..=MAX_CONDITIONS_NUM_IN_DECISION => { - self.mcdc_decision_spans.push(decision); - } - _ => { - // Do not generate mcdc mappings and statements for decisions with too many conditions. - let rebase_idx = self.mcdc_branch_spans.len() - decision.conditions_num + 1; - for branch in &mut self.mcdc_branch_spans[rebase_idx..] { - branch.condition_info = None; - } - - // ConditionInfo of this branch shall also be reset. - condition_info = None; - - tcx.dcx().emit_warn(MCDCExceedsConditionNumLimit { - span: decision.span, - conditions_num: decision.conditions_num, - max_conditions_num: MAX_CONDITIONS_NUM_IN_DECISION, - }); - } - } - } - condition_info - } - fn add_two_way_branch<'tcx>( &mut self, cfg: &mut CFG<'tcx>, @@ -141,43 +124,18 @@ impl BranchInfoBuilder { true_block: BasicBlock, false_block: BasicBlock, ) { - let true_marker = self.inject_block_marker(cfg, source_info, true_block); - let false_marker = self.inject_block_marker(cfg, source_info, false_block); + let true_marker = self.markers.inject_block_marker(cfg, source_info, true_block); + let false_marker = self.markers.inject_block_marker(cfg, source_info, false_block); self.branch_spans.push(BranchSpan { span: source_info.span, true_marker, false_marker }); } - fn next_block_marker_id(&mut self) -> BlockMarkerId { - let id = BlockMarkerId::from_usize(self.num_block_markers); - self.num_block_markers += 1; - id - } - - fn inject_block_marker( - &mut self, - cfg: &mut CFG<'_>, - source_info: SourceInfo, - block: BasicBlock, - ) -> BlockMarkerId { - let id = self.next_block_marker_id(); - - let marker_statement = mir::Statement { - source_info, - kind: mir::StatementKind::Coverage(CoverageKind::BlockMarker { id }), - }; - cfg.push(block, marker_statement); - - id - } - pub(crate) fn into_done(self) -> Option<Box<mir::coverage::BranchInfo>> { let Self { nots: _, - num_block_markers, + markers: BlockMarkerGen { num_block_markers }, branch_spans, - mcdc_branch_spans, - mcdc_decision_spans, - mcdc_state: _, + mcdc_info, } = self; if num_block_markers == 0 { @@ -185,6 +143,9 @@ impl BranchInfoBuilder { return None; } + let (mcdc_decision_spans, mcdc_branch_spans) = + mcdc_info.map(MCDCInfoBuilder::into_done).unwrap_or_default(); + Some(Box::new(mir::coverage::BranchInfo { num_block_markers, branch_spans, @@ -194,147 +155,6 @@ impl BranchInfoBuilder { } } -/// The MCDC bitmap scales exponentially (2^n) based on the number of conditions seen, -/// So llvm sets a maximum value prevents the bitmap footprint from growing too large without the user's knowledge. -/// This limit may be relaxed if the [upstream change](https://github.com/llvm/llvm-project/pull/82448) is merged. -const MAX_CONDITIONS_NUM_IN_DECISION: usize = 6; - -struct MCDCState { - /// To construct condition evaluation tree. - decision_stack: VecDeque<ConditionInfo>, - processing_decision: Option<MCDCDecisionSpan>, -} - -impl MCDCState { - fn new_if_enabled(tcx: TyCtxt<'_>) -> Option<Self> { - tcx.sess - .instrument_coverage_mcdc() - .then(|| Self { decision_stack: VecDeque::new(), processing_decision: None }) - } - - // At first we assign ConditionIds for each sub expression. - // If the sub expression is composite, re-assign its ConditionId to its LHS and generate a new ConditionId for its RHS. - // - // Example: "x = (A && B) || (C && D) || (D && F)" - // - // Visit Depth1: - // (A && B) || (C && D) || (D && F) - // ^-------LHS--------^ ^-RHS--^ - // ID=1 ID=2 - // - // Visit LHS-Depth2: - // (A && B) || (C && D) - // ^-LHS--^ ^-RHS--^ - // ID=1 ID=3 - // - // Visit LHS-Depth3: - // (A && B) - // LHS RHS - // ID=1 ID=4 - // - // Visit RHS-Depth3: - // (C && D) - // LHS RHS - // ID=3 ID=5 - // - // Visit RHS-Depth2: (D && F) - // LHS RHS - // ID=2 ID=6 - // - // Visit Depth1: - // (A && B) || (C && D) || (D && F) - // ID=1 ID=4 ID=3 ID=5 ID=2 ID=6 - // - // A node ID of '0' always means MC/DC isn't being tracked. - // - // If a "next" node ID is '0', it means it's the end of the test vector. - // - // As the compiler tracks expression in pre-order, we can ensure that condition info of parents are always properly assigned when their children are visited. - // - If the op is AND, the "false_next" of LHS and RHS should be the parent's "false_next". While "true_next" of the LHS is the RHS, the "true next" of RHS is the parent's "true_next". - // - If the op is OR, the "true_next" of LHS and RHS should be the parent's "true_next". While "false_next" of the LHS is the RHS, the "false next" of RHS is the parent's "false_next". - fn record_conditions(&mut self, op: LogicalOp, span: Span) { - let decision = match self.processing_decision.as_mut() { - Some(decision) => { - decision.span = decision.span.to(span); - decision - } - None => self.processing_decision.insert(MCDCDecisionSpan { - span, - conditions_num: 0, - end_markers: vec![], - }), - }; - - let parent_condition = self.decision_stack.pop_back().unwrap_or_default(); - let lhs_id = if parent_condition.condition_id == ConditionId::NONE { - decision.conditions_num += 1; - ConditionId::from(decision.conditions_num) - } else { - parent_condition.condition_id - }; - - decision.conditions_num += 1; - let rhs_condition_id = ConditionId::from(decision.conditions_num); - - let (lhs, rhs) = match op { - LogicalOp::And => { - let lhs = ConditionInfo { - condition_id: lhs_id, - true_next_id: rhs_condition_id, - false_next_id: parent_condition.false_next_id, - }; - let rhs = ConditionInfo { - condition_id: rhs_condition_id, - true_next_id: parent_condition.true_next_id, - false_next_id: parent_condition.false_next_id, - }; - (lhs, rhs) - } - LogicalOp::Or => { - let lhs = ConditionInfo { - condition_id: lhs_id, - true_next_id: parent_condition.true_next_id, - false_next_id: rhs_condition_id, - }; - let rhs = ConditionInfo { - condition_id: rhs_condition_id, - true_next_id: parent_condition.true_next_id, - false_next_id: parent_condition.false_next_id, - }; - (lhs, rhs) - } - }; - // We visit expressions tree in pre-order, so place the left-hand side on the top. - self.decision_stack.push_back(rhs); - self.decision_stack.push_back(lhs); - } - - fn take_condition( - &mut self, - true_marker: BlockMarkerId, - false_marker: BlockMarkerId, - ) -> (Option<ConditionInfo>, Option<MCDCDecisionSpan>) { - let Some(condition_info) = self.decision_stack.pop_back() else { - return (None, None); - }; - let Some(decision) = self.processing_decision.as_mut() else { - bug!("Processing decision should have been created before any conditions are taken"); - }; - if condition_info.true_next_id == ConditionId::NONE { - decision.end_markers.push(true_marker); - } - if condition_info.false_next_id == ConditionId::NONE { - decision.end_markers.push(false_marker); - } - - if self.decision_stack.is_empty() { - (Some(condition_info), self.processing_decision.take()) - } else { - (Some(condition_info), None) - } - } -} - impl Builder<'_, '_> { /// If branch coverage is enabled, inject marker statements into `then_block` /// and `else_block`, and record their IDs in the table of branch spans. @@ -359,30 +179,20 @@ impl Builder<'_, '_> { let source_info = SourceInfo { span: self.thir[expr_id].span, scope: self.source_scope }; // Separate path for handling branches when MC/DC is enabled. - if branch_info.mcdc_state.is_some() { - let mut inject_block_marker = - |block| branch_info.inject_block_marker(&mut self.cfg, source_info, block); - let true_marker = inject_block_marker(then_block); - let false_marker = inject_block_marker(else_block); - let condition_info = - branch_info.fetch_mcdc_condition_info(self.tcx, true_marker, false_marker); - branch_info.mcdc_branch_spans.push(MCDCBranchSpan { - span: source_info.span, - condition_info, - true_marker, - false_marker, - }); + if let Some(mcdc_info) = branch_info.mcdc_info.as_mut() { + let inject_block_marker = |source_info, block| { + branch_info.markers.inject_block_marker(&mut self.cfg, source_info, block) + }; + mcdc_info.visit_evaluated_condition( + self.tcx, + source_info, + then_block, + else_block, + inject_block_marker, + ); return; } branch_info.add_two_way_branch(&mut self.cfg, source_info, then_block, else_block); } - - pub(crate) fn visit_coverage_branch_operation(&mut self, logical_op: LogicalOp, span: Span) { - if let Some(branch_info) = self.coverage_branch_info.as_mut() - && let Some(mcdc_state) = branch_info.mcdc_state.as_mut() - { - mcdc_state.record_conditions(logical_op, span); - } - } } diff --git a/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs b/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs new file mode 100644 index 00000000000..566dba460d4 --- /dev/null +++ b/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs @@ -0,0 +1,275 @@ +use std::collections::VecDeque; + +use rustc_middle::mir::coverage::{ + BlockMarkerId, ConditionId, ConditionInfo, MCDCBranchSpan, MCDCDecisionSpan, +}; +use rustc_middle::mir::{BasicBlock, SourceInfo}; +use rustc_middle::thir::LogicalOp; +use rustc_middle::ty::TyCtxt; +use rustc_span::Span; + +use crate::build::Builder; +use crate::errors::MCDCExceedsConditionNumLimit; + +/// The MCDC bitmap scales exponentially (2^n) based on the number of conditions seen, +/// So llvm sets a maximum value prevents the bitmap footprint from growing too large without the user's knowledge. +/// This limit may be relaxed if the [upstream change](https://github.com/llvm/llvm-project/pull/82448) is merged. +const MAX_CONDITIONS_NUM_IN_DECISION: usize = 6; + +#[derive(Default)] +struct MCDCDecisionCtx { + /// To construct condition evaluation tree. + decision_stack: VecDeque<ConditionInfo>, + processing_decision: Option<MCDCDecisionSpan>, +} + +struct MCDCState { + decision_ctx_stack: Vec<MCDCDecisionCtx>, +} + +impl MCDCState { + fn new() -> Self { + Self { decision_ctx_stack: vec![MCDCDecisionCtx::default()] } + } + + /// Decision depth is given as a u16 to reduce the size of the `CoverageKind`, + /// as it is very unlikely that the depth ever reaches 2^16. + #[inline] + fn decision_depth(&self) -> u16 { + match u16::try_from(self.decision_ctx_stack.len()) + .expect( + "decision depth did not fit in u16, this is likely to be an instrumentation error", + ) + .checked_sub(1) + { + Some(d) => d, + None => bug!("Unexpected empty decision stack"), + } + } + + // At first we assign ConditionIds for each sub expression. + // If the sub expression is composite, re-assign its ConditionId to its LHS and generate a new ConditionId for its RHS. + // + // Example: "x = (A && B) || (C && D) || (D && F)" + // + // Visit Depth1: + // (A && B) || (C && D) || (D && F) + // ^-------LHS--------^ ^-RHS--^ + // ID=1 ID=2 + // + // Visit LHS-Depth2: + // (A && B) || (C && D) + // ^-LHS--^ ^-RHS--^ + // ID=1 ID=3 + // + // Visit LHS-Depth3: + // (A && B) + // LHS RHS + // ID=1 ID=4 + // + // Visit RHS-Depth3: + // (C && D) + // LHS RHS + // ID=3 ID=5 + // + // Visit RHS-Depth2: (D && F) + // LHS RHS + // ID=2 ID=6 + // + // Visit Depth1: + // (A && B) || (C && D) || (D && F) + // ID=1 ID=4 ID=3 ID=5 ID=2 ID=6 + // + // A node ID of '0' always means MC/DC isn't being tracked. + // + // If a "next" node ID is '0', it means it's the end of the test vector. + // + // As the compiler tracks expression in pre-order, we can ensure that condition info of parents are always properly assigned when their children are visited. + // - If the op is AND, the "false_next" of LHS and RHS should be the parent's "false_next". While "true_next" of the LHS is the RHS, the "true next" of RHS is the parent's "true_next". + // - If the op is OR, the "true_next" of LHS and RHS should be the parent's "true_next". While "false_next" of the LHS is the RHS, the "false next" of RHS is the parent's "false_next". + fn record_conditions(&mut self, op: LogicalOp, span: Span) { + let decision_depth = self.decision_depth(); + let Some(decision_ctx) = self.decision_ctx_stack.last_mut() else { + bug!("Unexpected empty decision_ctx_stack") + }; + let decision = match decision_ctx.processing_decision.as_mut() { + Some(decision) => { + decision.span = decision.span.to(span); + decision + } + None => decision_ctx.processing_decision.insert(MCDCDecisionSpan { + span, + conditions_num: 0, + end_markers: vec![], + decision_depth, + }), + }; + + let parent_condition = decision_ctx.decision_stack.pop_back().unwrap_or_default(); + let lhs_id = if parent_condition.condition_id == ConditionId::NONE { + decision.conditions_num += 1; + ConditionId::from(decision.conditions_num) + } else { + parent_condition.condition_id + }; + + decision.conditions_num += 1; + let rhs_condition_id = ConditionId::from(decision.conditions_num); + + let (lhs, rhs) = match op { + LogicalOp::And => { + let lhs = ConditionInfo { + condition_id: lhs_id, + true_next_id: rhs_condition_id, + false_next_id: parent_condition.false_next_id, + }; + let rhs = ConditionInfo { + condition_id: rhs_condition_id, + true_next_id: parent_condition.true_next_id, + false_next_id: parent_condition.false_next_id, + }; + (lhs, rhs) + } + LogicalOp::Or => { + let lhs = ConditionInfo { + condition_id: lhs_id, + true_next_id: parent_condition.true_next_id, + false_next_id: rhs_condition_id, + }; + let rhs = ConditionInfo { + condition_id: rhs_condition_id, + true_next_id: parent_condition.true_next_id, + false_next_id: parent_condition.false_next_id, + }; + (lhs, rhs) + } + }; + // We visit expressions tree in pre-order, so place the left-hand side on the top. + decision_ctx.decision_stack.push_back(rhs); + decision_ctx.decision_stack.push_back(lhs); + } + + fn take_condition( + &mut self, + true_marker: BlockMarkerId, + false_marker: BlockMarkerId, + ) -> (Option<ConditionInfo>, Option<MCDCDecisionSpan>) { + let Some(decision_ctx) = self.decision_ctx_stack.last_mut() else { + bug!("Unexpected empty decision_ctx_stack") + }; + let Some(condition_info) = decision_ctx.decision_stack.pop_back() else { + return (None, None); + }; + let Some(decision) = decision_ctx.processing_decision.as_mut() else { + bug!("Processing decision should have been created before any conditions are taken"); + }; + if condition_info.true_next_id == ConditionId::NONE { + decision.end_markers.push(true_marker); + } + if condition_info.false_next_id == ConditionId::NONE { + decision.end_markers.push(false_marker); + } + + if decision_ctx.decision_stack.is_empty() { + (Some(condition_info), decision_ctx.processing_decision.take()) + } else { + (Some(condition_info), None) + } + } +} + +pub struct MCDCInfoBuilder { + branch_spans: Vec<MCDCBranchSpan>, + decision_spans: Vec<MCDCDecisionSpan>, + state: MCDCState, +} + +impl MCDCInfoBuilder { + pub fn new() -> Self { + Self { branch_spans: vec![], decision_spans: vec![], state: MCDCState::new() } + } + + pub fn visit_evaluated_condition( + &mut self, + tcx: TyCtxt<'_>, + source_info: SourceInfo, + true_block: BasicBlock, + false_block: BasicBlock, + mut inject_block_marker: impl FnMut(SourceInfo, BasicBlock) -> BlockMarkerId, + ) { + let true_marker = inject_block_marker(source_info, true_block); + let false_marker = inject_block_marker(source_info, false_block); + + let decision_depth = self.state.decision_depth(); + let (mut condition_info, decision_result) = + self.state.take_condition(true_marker, false_marker); + // take_condition() returns Some for decision_result when the decision stack + // is empty, i.e. when all the conditions of the decision were instrumented, + // and the decision is "complete". + if let Some(decision) = decision_result { + match decision.conditions_num { + 0 => { + unreachable!("Decision with no condition is not expected"); + } + 1..=MAX_CONDITIONS_NUM_IN_DECISION => { + self.decision_spans.push(decision); + } + _ => { + // Do not generate mcdc mappings and statements for decisions with too many conditions. + let rebase_idx = self.branch_spans.len() - decision.conditions_num + 1; + for branch in &mut self.branch_spans[rebase_idx..] { + branch.condition_info = None; + } + + // ConditionInfo of this branch shall also be reset. + condition_info = None; + + tcx.dcx().emit_warn(MCDCExceedsConditionNumLimit { + span: decision.span, + conditions_num: decision.conditions_num, + max_conditions_num: MAX_CONDITIONS_NUM_IN_DECISION, + }); + } + } + } + self.branch_spans.push(MCDCBranchSpan { + span: source_info.span, + condition_info, + true_marker, + false_marker, + decision_depth, + }); + } + + pub fn into_done(self) -> (Vec<MCDCDecisionSpan>, Vec<MCDCBranchSpan>) { + (self.decision_spans, self.branch_spans) + } +} + +impl Builder<'_, '_> { + pub(crate) fn visit_coverage_branch_operation(&mut self, logical_op: LogicalOp, span: Span) { + if let Some(branch_info) = self.coverage_branch_info.as_mut() + && let Some(mcdc_info) = branch_info.mcdc_info.as_mut() + { + mcdc_info.state.record_conditions(logical_op, span); + } + } + + pub(crate) fn mcdc_increment_depth_if_enabled(&mut self) { + if let Some(branch_info) = self.coverage_branch_info.as_mut() + && let Some(mcdc_info) = branch_info.mcdc_info.as_mut() + { + mcdc_info.state.decision_ctx_stack.push(MCDCDecisionCtx::default()); + }; + } + + pub(crate) fn mcdc_decrement_depth_if_enabled(&mut self) { + if let Some(branch_info) = self.coverage_branch_info.as_mut() + && let Some(mcdc_info) = branch_info.mcdc_info.as_mut() + { + if mcdc_info.state.decision_ctx_stack.pop().is_none() { + bug!("Unexpected empty decision stack"); + } + }; + } +} diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index d36c51f4472..bce15267759 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -73,14 +73,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let expr_span = expr.span; match expr.kind { - ExprKind::LogicalOp { op: LogicalOp::And, lhs, rhs } => { - this.visit_coverage_branch_operation(LogicalOp::And, expr_span); + ExprKind::LogicalOp { op: op @ LogicalOp::And, lhs, rhs } => { + this.visit_coverage_branch_operation(op, expr_span); let lhs_then_block = unpack!(this.then_else_break_inner(block, lhs, args)); let rhs_then_block = unpack!(this.then_else_break_inner(lhs_then_block, rhs, args)); rhs_then_block.unit() } - ExprKind::LogicalOp { op: LogicalOp::Or, lhs, rhs } => { - this.visit_coverage_branch_operation(LogicalOp::Or, expr_span); + ExprKind::LogicalOp { op: op @ LogicalOp::Or, lhs, rhs } => { + this.visit_coverage_branch_operation(op, expr_span); let local_scope = this.local_scope(); let (lhs_success_block, failure_block) = this.in_if_then_scope(local_scope, expr_span, |this| { @@ -148,8 +148,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let mut block = block; let temp_scope = args.temp_scope_override.unwrap_or_else(|| this.local_scope()); let mutability = Mutability::Mut; + + // Increment the decision depth, in case we encounter boolean expressions + // further down. + this.mcdc_increment_depth_if_enabled(); let place = unpack!(block = this.as_temp(block, Some(temp_scope), expr_id, mutability)); + this.mcdc_decrement_depth_if_enabled(); + let operand = Operand::Move(Place::from(place)); let then_block = this.cfg.start_new_block(); diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 3c18afe1a78..794e7ebb7b4 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -566,7 +566,8 @@ fn construct_const<'a, 'tcx>( span, .. }) => (*span, ty.span), - Node::AnonConst(_) | Node::ConstBlock(_) => { + Node::AnonConst(ct) => (ct.span, ct.span), + Node::ConstBlock(_) => { let span = tcx.def_span(def); (span, span) } @@ -997,7 +998,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match self.unit_temp { Some(tmp) => tmp, None => { - let ty = Ty::new_unit(self.tcx); + let ty = self.tcx.types.unit; let fn_span = self.fn_span; let tmp = self.temp(ty, fn_span); self.unit_temp = Some(tmp); diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index 442f5fa7d17..e79e3b887fb 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -5,7 +5,6 @@ #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] #![feature(assert_matches)] -#![cfg_attr(bootstrap, feature(associated_type_bounds))] #![feature(box_patterns)] #![feature(if_let_guard)] #![feature(let_chains)] diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index f4f591d15b9..79738b54035 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -15,7 +15,7 @@ use rustc_hir::HirId; use rustc_hir::Node; use rustc_middle::middle::region; use rustc_middle::thir::*; -use rustc_middle::ty::{self, RvalueScopes, Ty, TyCtxt}; +use rustc_middle::ty::{self, RvalueScopes, TyCtxt}; pub(crate) fn thir_body( tcx: TyCtxt<'_>, @@ -39,7 +39,7 @@ pub(crate) fn thir_body( // It will always be `()` in this case. if tcx.is_coroutine(owner_def.to_def_id()) && body.params.is_empty() { cx.thir.params.push(Param { - ty: Ty::new_unit(tcx), + ty: tcx.types.unit, pat: None, ty_span: None, self_kind: None, diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 241d38f90d2..25ab9046706 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -10,9 +10,7 @@ use rustc_arena::{DroplessArena, TypedArena}; use rustc_ast::Mutability; use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_errors::{ - codes::*, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, MultiSpan, -}; +use rustc_errors::{codes::*, struct_span_code_err, Applicability, ErrorGuaranteed, MultiSpan}; use rustc_hir::def::*; use rustc_hir::def_id::LocalDefId; use rustc_hir::{self as hir, BindingMode, ByRef, HirId}; @@ -24,7 +22,6 @@ use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt}; use rustc_session::lint::builtin::{ BINDINGS_WITH_VARIANT_NAME, IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS, }; -use rustc_session::Session; use rustc_span::hygiene::DesugaringKind; use rustc_span::{sym, Span}; @@ -64,10 +61,6 @@ pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), Err visitor.error } -fn create_e0004(sess: &Session, sp: Span, error_message: String) -> Diag<'_> { - struct_span_code_err!(sess.dcx(), sp, E0004, "{}", &error_message) -} - #[derive(Debug, Copy, Clone, PartialEq)] enum RefutableFlag { Irrefutable, @@ -975,10 +968,11 @@ fn report_non_exhaustive_match<'p, 'tcx>( // FIXME: migration of this diagnostic will require list support let joined_patterns = joined_uncovered_patterns(cx, &witnesses); - let mut err = create_e0004( - cx.tcx.sess, + let mut err = struct_span_code_err!( + cx.tcx.dcx(), sp, - format!("non-exhaustive patterns: {joined_patterns} not covered"), + E0004, + "non-exhaustive patterns: {joined_patterns} not covered" ); err.span_label( sp, diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index d63db6ea8ed..185e87baed8 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -2,6 +2,7 @@ use rustc_hir::lang_items::LangItem; use rustc_index::Idx; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::*; +use rustc_middle::span_bug; use rustc_middle::traits::Reveal; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::GenericArgsRef; @@ -630,7 +631,7 @@ where let ref_ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, ty); let ref_place = self.new_temp(ref_ty); - let unit_temp = Place::from(self.new_temp(Ty::new_unit(tcx))); + let unit_temp = Place::from(self.new_temp(tcx.types.unit)); let result = BasicBlockData { statements: vec![self.assign( diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs index 44a7dcc8277..ea9cf6565e7 100644 --- a/compiler/rustc_mir_dataflow/src/framework/engine.rs +++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs @@ -13,6 +13,7 @@ use rustc_data_structures::work_queue::WorkQueue; use rustc_graphviz as dot; use rustc_hir::def_id::DefId; use rustc_index::{Idx, IndexVec}; +use rustc_middle::bug; use rustc_middle::mir::{self, traversal, BasicBlock}; use rustc_middle::mir::{create_dump_file, dump_enabled}; use rustc_middle::ty::print::with_no_trimmed_paths; diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index 720515f262d..180168c7316 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -1,5 +1,6 @@ use rustc_index::bit_set::{BitSet, ChunkedBitSet}; use rustc_index::Idx; +use rustc_middle::bug; use rustc_middle::mir::{self, Body, CallReturnPlaces, Location, TerminatorEdges}; use rustc_middle::ty::{self, TyCtxt}; diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index c5adb81b614..5e96a73f6c5 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -6,8 +6,6 @@ #[macro_use] extern crate tracing; -#[macro_use] -extern crate rustc_middle; use rustc_middle::ty; diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index d7477309400..6ae7df79d30 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -2,6 +2,7 @@ use rustc_index::IndexVec; use rustc_middle::mir::tcx::{PlaceTy, RvalueInitializationState}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::{bug, span_bug}; use smallvec::{smallvec, SmallVec}; use std::mem; diff --git a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs index 22cf3999239..830f44df5fb 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs @@ -358,20 +358,15 @@ impl<'tcx> MoveData<'tcx> { builder::gather_moves(body, tcx, param_env, filter) } - /// For the move path `mpi`, returns the root local variable (if any) that starts the path. - /// (e.g., for a path like `a.b.c` returns `Some(a)`) - pub fn base_local(&self, mut mpi: MovePathIndex) -> Option<Local> { + /// For the move path `mpi`, returns the root local variable that starts the path. + /// (e.g., for a path like `a.b.c` returns `a`) + pub fn base_local(&self, mut mpi: MovePathIndex) -> Local { loop { let path = &self.move_paths[mpi]; if let Some(l) = path.place.as_local() { - return Some(l); - } - if let Some(parent) = path.parent { - mpi = parent; - continue; - } else { - return None; + return l; } + mpi = path.parent.expect("root move paths should be locals"); } } diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 0e85f859ab2..807bef07411 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -40,6 +40,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_index::bit_set::BitSet; use rustc_index::{IndexSlice, IndexVec}; +use rustc_middle::bug; use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs index 0119b95cced..c1f9313a377 100644 --- a/compiler/rustc_mir_transform/src/copy_prop.rs +++ b/compiler/rustc_mir_transform/src/copy_prop.rs @@ -3,7 +3,6 @@ use rustc_index::IndexSlice; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; -use rustc_mir_dataflow::impls::borrowed_locals; use crate::ssa::SsaLocals; @@ -32,8 +31,8 @@ impl<'tcx> MirPass<'tcx> for CopyProp { } fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let borrowed_locals = borrowed_locals(body); - let ssa = SsaLocals::new(body); + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + let ssa = SsaLocals::new(tcx, body, param_env); let fully_moved = fully_moved_locals(&ssa, body); debug!(?fully_moved); @@ -51,7 +50,7 @@ fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { tcx, copy_classes: ssa.copy_classes(), fully_moved, - borrowed_locals, + borrowed_locals: ssa.borrowed_locals(), storage_to_remove, } .visit_body_preserves_cfg(body); @@ -101,7 +100,7 @@ struct Replacer<'a, 'tcx> { tcx: TyCtxt<'tcx>, fully_moved: BitSet<Local>, storage_to_remove: BitSet<Local>, - borrowed_locals: BitSet<Local>, + borrowed_locals: &'a BitSet<Local>, copy_classes: &'a IndexSlice<Local, Local>, } @@ -112,6 +111,12 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> { fn visit_local(&mut self, local: &mut Local, ctxt: PlaceContext, _: Location) { let new_local = self.copy_classes[*local]; + // We must not unify two locals that are borrowed. But this is fine if one is borrowed and + // the other is not. We chose to check the original local, and not the target. That way, if + // the original local is borrowed and the target is not, we do not pessimize the whole class. + if self.borrowed_locals.contains(*local) { + return; + } match ctxt { // Do not modify the local in storage statements. PlaceContext::NonUse(NonUseContext::StorageLive | NonUseContext::StorageDead) => {} @@ -122,32 +127,14 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> { } } - fn visit_place(&mut self, place: &mut Place<'tcx>, ctxt: PlaceContext, loc: Location) { + fn visit_place(&mut self, place: &mut Place<'tcx>, _: PlaceContext, loc: Location) { if let Some(new_projection) = self.process_projection(place.projection, loc) { place.projection = self.tcx().mk_place_elems(&new_projection); } - let observes_address = match ctxt { - PlaceContext::NonMutatingUse( - NonMutatingUseContext::SharedBorrow - | NonMutatingUseContext::FakeBorrow - | NonMutatingUseContext::AddressOf, - ) => true, - // For debuginfo, merging locals is ok. - PlaceContext::NonUse(NonUseContext::VarDebugInfo) => { - self.borrowed_locals.contains(place.local) - } - _ => false, - }; - if observes_address && !place.is_indirect() { - // We observe the address of `place.local`. Do not replace it. - } else { - self.visit_local( - &mut place.local, - PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy), - loc, - ) - } + // Any non-mutating use context is ok. + let ctxt = PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy); + self.visit_local(&mut place.local, ctxt, loc) } fn visit_operand(&mut self, operand: &mut Operand<'tcx>, loc: Location) { diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index b745d97567d..3008016863e 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1260,7 +1260,7 @@ fn create_coroutine_drop_shim<'tcx>( } // Replace the return variable - body.local_decls[RETURN_PLACE] = LocalDecl::with_source_info(Ty::new_unit(tcx), source_info); + body.local_decls[RETURN_PLACE] = LocalDecl::with_source_info(tcx.types.unit, source_info); make_coroutine_state_argument_indirect(tcx, &mut body); diff --git a/compiler/rustc_mir_transform/src/coverage/mappings.rs b/compiler/rustc_mir_transform/src/coverage/mappings.rs new file mode 100644 index 00000000000..d364658efb6 --- /dev/null +++ b/compiler/rustc_mir_transform/src/coverage/mappings.rs @@ -0,0 +1,275 @@ +use std::collections::BTreeSet; + +use rustc_data_structures::graph::DirectedGraph; +use rustc_index::bit_set::BitSet; +use rustc_middle::mir::coverage::{ + BlockMarkerId, BranchSpan, ConditionInfo, CoverageKind, MCDCBranchSpan, MCDCDecisionSpan, +}; +use rustc_middle::mir::{self, BasicBlock, StatementKind}; +use rustc_span::Span; + +use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph, START_BCB}; +use crate::coverage::spans::{ + extract_refined_covspans, unexpand_into_body_span_with_visible_macro, +}; +use crate::coverage::ExtractedHirInfo; +use rustc_index::IndexVec; + +#[derive(Clone, Debug)] +pub(super) enum BcbMappingKind { + /// Associates an ordinary executable code span with its corresponding BCB. + Code(BasicCoverageBlock), + + // Ordinary branch mappings are stored separately, so they don't have a + // variant in this enum. + // + /// Associates a mcdc branch span with condition info besides fields for normal branch. + MCDCBranch { + true_bcb: BasicCoverageBlock, + false_bcb: BasicCoverageBlock, + /// If `None`, this actually represents a normal branch mapping inserted + /// for code that was too complex for MC/DC. + condition_info: Option<ConditionInfo>, + decision_depth: u16, + }, + /// Associates a mcdc decision with its join BCB. + MCDCDecision { + end_bcbs: BTreeSet<BasicCoverageBlock>, + bitmap_idx: u32, + conditions_num: u16, + decision_depth: u16, + }, +} + +#[derive(Debug)] +pub(super) struct BcbMapping { + pub(super) kind: BcbMappingKind, + pub(super) span: Span, +} + +/// This is separate from [`BcbMappingKind`] to help prepare for larger changes +/// that will be needed for improved branch coverage in the future. +/// (See <https://github.com/rust-lang/rust/pull/124217>.) +#[derive(Debug)] +pub(super) struct BcbBranchPair { + pub(super) span: Span, + pub(super) true_bcb: BasicCoverageBlock, + pub(super) false_bcb: BasicCoverageBlock, +} + +pub(super) struct CoverageSpans { + bcb_has_mappings: BitSet<BasicCoverageBlock>, + pub(super) mappings: Vec<BcbMapping>, + pub(super) branch_pairs: Vec<BcbBranchPair>, + test_vector_bitmap_bytes: u32, +} + +impl CoverageSpans { + pub(super) fn bcb_has_coverage_spans(&self, bcb: BasicCoverageBlock) -> bool { + self.bcb_has_mappings.contains(bcb) + } + + pub(super) fn test_vector_bitmap_bytes(&self) -> u32 { + self.test_vector_bitmap_bytes + } +} + +/// Extracts coverage-relevant spans from MIR, and associates them with +/// their corresponding BCBs. +/// +/// Returns `None` if no coverage-relevant spans could be extracted. +pub(super) fn generate_coverage_spans( + mir_body: &mir::Body<'_>, + hir_info: &ExtractedHirInfo, + basic_coverage_blocks: &CoverageGraph, +) -> Option<CoverageSpans> { + let mut mappings = vec![]; + let mut branch_pairs = vec![]; + + if hir_info.is_async_fn { + // An async function desugars into a function that returns a future, + // with the user code wrapped in a closure. Any spans in the desugared + // outer function will be unhelpful, so just keep the signature span + // and ignore all of the spans in the MIR body. + if let Some(span) = hir_info.fn_sig_span_extended { + mappings.push(BcbMapping { kind: BcbMappingKind::Code(START_BCB), span }); + } + } else { + extract_refined_covspans(mir_body, hir_info, basic_coverage_blocks, &mut mappings); + + branch_pairs.extend(extract_branch_pairs(mir_body, hir_info, basic_coverage_blocks)); + + mappings.extend(extract_mcdc_mappings(mir_body, hir_info.body_span, basic_coverage_blocks)); + } + + if mappings.is_empty() && branch_pairs.is_empty() { + return None; + } + + // Identify which BCBs have one or more mappings. + let mut bcb_has_mappings = BitSet::new_empty(basic_coverage_blocks.num_nodes()); + let mut insert = |bcb| { + bcb_has_mappings.insert(bcb); + }; + let mut test_vector_bitmap_bytes = 0; + for BcbMapping { kind, span: _ } in &mappings { + match *kind { + BcbMappingKind::Code(bcb) => insert(bcb), + BcbMappingKind::MCDCBranch { true_bcb, false_bcb, .. } => { + insert(true_bcb); + insert(false_bcb); + } + BcbMappingKind::MCDCDecision { bitmap_idx, conditions_num, .. } => { + // `bcb_has_mappings` is used for inject coverage counters + // but they are not needed for decision BCBs. + // While the length of test vector bitmap should be calculated here. + test_vector_bitmap_bytes = test_vector_bitmap_bytes + .max(bitmap_idx + (1_u32 << conditions_num as u32).div_ceil(8)); + } + } + } + for &BcbBranchPair { true_bcb, false_bcb, .. } in &branch_pairs { + insert(true_bcb); + insert(false_bcb); + } + + Some(CoverageSpans { bcb_has_mappings, mappings, branch_pairs, test_vector_bitmap_bytes }) +} + +fn resolve_block_markers( + branch_info: &mir::coverage::BranchInfo, + mir_body: &mir::Body<'_>, +) -> IndexVec<BlockMarkerId, Option<BasicBlock>> { + let mut block_markers = IndexVec::<BlockMarkerId, Option<BasicBlock>>::from_elem_n( + None, + branch_info.num_block_markers, + ); + + // Fill out the mapping from block marker IDs to their enclosing blocks. + for (bb, data) in mir_body.basic_blocks.iter_enumerated() { + for statement in &data.statements { + if let StatementKind::Coverage(CoverageKind::BlockMarker { id }) = statement.kind { + block_markers[id] = Some(bb); + } + } + } + + block_markers +} + +// FIXME: There is currently a lot of redundancy between +// `extract_branch_pairs` and `extract_mcdc_mappings`. This is needed so +// that they can each be modified without interfering with the other, but in +// the long term we should try to bring them together again when branch coverage +// and MC/DC coverage support are more mature. + +pub(super) fn extract_branch_pairs( + mir_body: &mir::Body<'_>, + hir_info: &ExtractedHirInfo, + basic_coverage_blocks: &CoverageGraph, +) -> Vec<BcbBranchPair> { + let Some(branch_info) = mir_body.coverage_branch_info.as_deref() else { return vec![] }; + + let block_markers = resolve_block_markers(branch_info, mir_body); + + branch_info + .branch_spans + .iter() + .filter_map(|&BranchSpan { span: raw_span, true_marker, false_marker }| { + // For now, ignore any branch span that was introduced by + // expansion. This makes things like assert macros less noisy. + if !raw_span.ctxt().outer_expn_data().is_root() { + return None; + } + let (span, _) = + unexpand_into_body_span_with_visible_macro(raw_span, hir_info.body_span)?; + + let bcb_from_marker = + |marker: BlockMarkerId| basic_coverage_blocks.bcb_from_bb(block_markers[marker]?); + + let true_bcb = bcb_from_marker(true_marker)?; + let false_bcb = bcb_from_marker(false_marker)?; + + Some(BcbBranchPair { span, true_bcb, false_bcb }) + }) + .collect::<Vec<_>>() +} + +pub(super) fn extract_mcdc_mappings( + mir_body: &mir::Body<'_>, + body_span: Span, + basic_coverage_blocks: &CoverageGraph, +) -> Vec<BcbMapping> { + let Some(branch_info) = mir_body.coverage_branch_info.as_deref() else { + return vec![]; + }; + + let block_markers = resolve_block_markers(branch_info, mir_body); + + let bcb_from_marker = + |marker: BlockMarkerId| basic_coverage_blocks.bcb_from_bb(block_markers[marker]?); + + let check_branch_bcb = + |raw_span: Span, true_marker: BlockMarkerId, false_marker: BlockMarkerId| { + // For now, ignore any branch span that was introduced by + // expansion. This makes things like assert macros less noisy. + if !raw_span.ctxt().outer_expn_data().is_root() { + return None; + } + let (span, _) = unexpand_into_body_span_with_visible_macro(raw_span, body_span)?; + + let true_bcb = bcb_from_marker(true_marker)?; + let false_bcb = bcb_from_marker(false_marker)?; + Some((span, true_bcb, false_bcb)) + }; + + let mcdc_branch_filter_map = |&MCDCBranchSpan { + span: raw_span, + true_marker, + false_marker, + condition_info, + decision_depth, + }| { + check_branch_bcb(raw_span, true_marker, false_marker).map(|(span, true_bcb, false_bcb)| { + BcbMapping { + kind: BcbMappingKind::MCDCBranch { + true_bcb, + false_bcb, + condition_info, + decision_depth, + }, + span, + } + }) + }; + + let mut next_bitmap_idx = 0; + + let decision_filter_map = |decision: &MCDCDecisionSpan| { + let (span, _) = unexpand_into_body_span_with_visible_macro(decision.span, body_span)?; + + let end_bcbs = decision + .end_markers + .iter() + .map(|&marker| bcb_from_marker(marker)) + .collect::<Option<_>>()?; + + let bitmap_idx = next_bitmap_idx; + next_bitmap_idx += (1_u32 << decision.conditions_num).div_ceil(8); + + Some(BcbMapping { + kind: BcbMappingKind::MCDCDecision { + end_bcbs, + bitmap_idx, + conditions_num: decision.conditions_num as u16, + decision_depth: decision.decision_depth, + }, + span, + }) + }; + + std::iter::empty() + .chain(branch_info.mcdc_branch_spans.iter().filter_map(mcdc_branch_filter_map)) + .chain(branch_info.mcdc_decision_spans.iter().filter_map(decision_filter_map)) + .collect::<Vec<_>>() +} diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 0b15c52c281..ffe61e761c5 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -2,14 +2,14 @@ pub mod query; mod counters; mod graph; +mod mappings; mod spans; - #[cfg(test)] mod tests; use self::counters::{CounterIncrementSite, CoverageCounters}; use self::graph::{BasicCoverageBlock, CoverageGraph}; -use self::spans::{BcbBranchPair, BcbMapping, BcbMappingKind, CoverageSpans}; +use self::mappings::{BcbBranchPair, BcbMapping, BcbMappingKind, CoverageSpans}; use crate::MirPass; @@ -71,7 +71,7 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir: //////////////////////////////////////////////////// // Compute coverage spans from the `CoverageGraph`. let Some(coverage_spans) = - spans::generate_coverage_spans(mir_body, &hir_info, &basic_coverage_blocks) + mappings::generate_coverage_spans(mir_body, &hir_info, &basic_coverage_blocks) else { // No relevant spans were found in MIR, so skip instrumenting this function. return; @@ -102,12 +102,23 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir: inject_mcdc_statements(mir_body, &basic_coverage_blocks, &coverage_spans); + let mcdc_num_condition_bitmaps = coverage_spans + .mappings + .iter() + .filter_map(|bcb_mapping| match bcb_mapping.kind { + BcbMappingKind::MCDCDecision { decision_depth, .. } => Some(decision_depth), + _ => None, + }) + .max() + .map_or(0, |max| usize::from(max) + 1); + mir_body.function_coverage_info = Some(Box::new(FunctionCoverageInfo { function_source_hash: hir_info.function_source_hash, num_counters: coverage_counters.num_counters(), mcdc_bitmap_bytes: coverage_spans.test_vector_bitmap_bytes(), expressions: coverage_counters.into_expressions(), mappings, + mcdc_num_condition_bitmaps, })); } @@ -145,16 +156,17 @@ fn create_mappings<'tcx>( |BcbMapping { kind: bcb_mapping_kind, span }| { let kind = match *bcb_mapping_kind { BcbMappingKind::Code(bcb) => MappingKind::Code(term_for_bcb(bcb)), - BcbMappingKind::MCDCBranch { true_bcb, false_bcb, condition_info: None } => { - MappingKind::Branch { - true_term: term_for_bcb(true_bcb), - false_term: term_for_bcb(false_bcb), - } - } + BcbMappingKind::MCDCBranch { + true_bcb, false_bcb, condition_info: None, .. + } => MappingKind::Branch { + true_term: term_for_bcb(true_bcb), + false_term: term_for_bcb(false_bcb), + }, BcbMappingKind::MCDCBranch { true_bcb, false_bcb, condition_info: Some(mcdc_params), + .. } => MappingKind::MCDCBranch { true_term: term_for_bcb(true_bcb), false_term: term_for_bcb(false_bcb), @@ -246,24 +258,28 @@ fn inject_mcdc_statements<'tcx>( } // Inject test vector update first because `inject_statement` always insert new statement at head. - for (end_bcbs, bitmap_idx) in + for (end_bcbs, bitmap_idx, decision_depth) in coverage_spans.mappings.iter().filter_map(|mapping| match &mapping.kind { - BcbMappingKind::MCDCDecision { end_bcbs, bitmap_idx, .. } => { - Some((end_bcbs, *bitmap_idx)) + BcbMappingKind::MCDCDecision { end_bcbs, bitmap_idx, decision_depth, .. } => { + Some((end_bcbs, *bitmap_idx, *decision_depth)) } _ => None, }) { for end in end_bcbs { let end_bb = basic_coverage_blocks[*end].leader_bb(); - inject_statement(mir_body, CoverageKind::TestVectorBitmapUpdate { bitmap_idx }, end_bb); + inject_statement( + mir_body, + CoverageKind::TestVectorBitmapUpdate { bitmap_idx, decision_depth }, + end_bb, + ); } } - for (true_bcb, false_bcb, condition_id) in + for (true_bcb, false_bcb, condition_id, decision_depth) in coverage_spans.mappings.iter().filter_map(|mapping| match mapping.kind { - BcbMappingKind::MCDCBranch { true_bcb, false_bcb, condition_info } => { - Some((true_bcb, false_bcb, condition_info?.condition_id)) + BcbMappingKind::MCDCBranch { true_bcb, false_bcb, condition_info, decision_depth } => { + Some((true_bcb, false_bcb, condition_info?.condition_id, decision_depth)) } _ => None, }) @@ -271,13 +287,13 @@ fn inject_mcdc_statements<'tcx>( let true_bb = basic_coverage_blocks[true_bcb].leader_bb(); inject_statement( mir_body, - CoverageKind::CondBitmapUpdate { id: condition_id, value: true }, + CoverageKind::CondBitmapUpdate { id: condition_id, value: true, decision_depth }, true_bb, ); let false_bb = basic_coverage_blocks[false_bcb].leader_bb(); inject_statement( mir_body, - CoverageKind::CondBitmapUpdate { id: condition_id, value: false }, + CoverageKind::CondBitmapUpdate { id: condition_id, value: false, decision_depth }, false_bb, ); } diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 88f18b72085..d6432e2e9d4 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -1,146 +1,31 @@ -use rustc_data_structures::graph::DirectedGraph; -use rustc_index::bit_set::BitSet; use rustc_middle::mir; -use rustc_middle::mir::coverage::ConditionInfo; use rustc_span::{BytePos, Span}; -use std::collections::BTreeSet; -use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph, START_BCB}; +use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph}; +use crate::coverage::mappings::{BcbMapping, BcbMappingKind}; use crate::coverage::spans::from_mir::SpanFromMir; use crate::coverage::ExtractedHirInfo; mod from_mir; -#[derive(Clone, Debug)] -pub(super) enum BcbMappingKind { - /// Associates an ordinary executable code span with its corresponding BCB. - Code(BasicCoverageBlock), - - // Ordinary branch mappings are stored separately, so they don't have a - // variant in this enum. - // - /// Associates a mcdc branch span with condition info besides fields for normal branch. - MCDCBranch { - true_bcb: BasicCoverageBlock, - false_bcb: BasicCoverageBlock, - /// If `None`, this actually represents a normal branch mapping inserted - /// for code that was too complex for MC/DC. - condition_info: Option<ConditionInfo>, - }, - /// Associates a mcdc decision with its join BCB. - MCDCDecision { end_bcbs: BTreeSet<BasicCoverageBlock>, bitmap_idx: u32, conditions_num: u16 }, -} - -#[derive(Debug)] -pub(super) struct BcbMapping { - pub(super) kind: BcbMappingKind, - pub(super) span: Span, -} - -/// This is separate from [`BcbMappingKind`] to help prepare for larger changes -/// that will be needed for improved branch coverage in the future. -/// (See <https://github.com/rust-lang/rust/pull/124217>.) -#[derive(Debug)] -pub(super) struct BcbBranchPair { - pub(super) span: Span, - pub(super) true_bcb: BasicCoverageBlock, - pub(super) false_bcb: BasicCoverageBlock, -} - -pub(super) struct CoverageSpans { - bcb_has_mappings: BitSet<BasicCoverageBlock>, - pub(super) mappings: Vec<BcbMapping>, - pub(super) branch_pairs: Vec<BcbBranchPair>, - test_vector_bitmap_bytes: u32, -} - -impl CoverageSpans { - pub(super) fn bcb_has_coverage_spans(&self, bcb: BasicCoverageBlock) -> bool { - self.bcb_has_mappings.contains(bcb) - } - - pub(super) fn test_vector_bitmap_bytes(&self) -> u32 { - self.test_vector_bitmap_bytes - } -} +// FIXME(#124545) It's awkward that we have to re-export this, because it's an +// internal detail of `from_mir` that is also needed when handling branch and +// MC/DC spans. Ideally we would find a more natural home for it. +pub(super) use from_mir::unexpand_into_body_span_with_visible_macro; -/// Extracts coverage-relevant spans from MIR, and associates them with -/// their corresponding BCBs. -/// -/// Returns `None` if no coverage-relevant spans could be extracted. -pub(super) fn generate_coverage_spans( +pub(super) fn extract_refined_covspans( mir_body: &mir::Body<'_>, hir_info: &ExtractedHirInfo, basic_coverage_blocks: &CoverageGraph, -) -> Option<CoverageSpans> { - let mut mappings = vec![]; - let mut branch_pairs = vec![]; - - if hir_info.is_async_fn { - // An async function desugars into a function that returns a future, - // with the user code wrapped in a closure. Any spans in the desugared - // outer function will be unhelpful, so just keep the signature span - // and ignore all of the spans in the MIR body. - if let Some(span) = hir_info.fn_sig_span_extended { - mappings.push(BcbMapping { kind: BcbMappingKind::Code(START_BCB), span }); - } - } else { - let sorted_spans = from_mir::mir_to_initial_sorted_coverage_spans( - mir_body, - hir_info, - basic_coverage_blocks, - ); - let coverage_spans = SpansRefiner::refine_sorted_spans(sorted_spans); - mappings.extend(coverage_spans.into_iter().map(|RefinedCovspan { bcb, span, .. }| { - // Each span produced by the generator represents an ordinary code region. - BcbMapping { kind: BcbMappingKind::Code(bcb), span } - })); - - branch_pairs.extend(from_mir::extract_branch_pairs( - mir_body, - hir_info, - basic_coverage_blocks, - )); - - mappings.extend(from_mir::extract_mcdc_mappings( - mir_body, - hir_info.body_span, - basic_coverage_blocks, - )); - } - - if mappings.is_empty() && branch_pairs.is_empty() { - return None; - } - - // Identify which BCBs have one or more mappings. - let mut bcb_has_mappings = BitSet::new_empty(basic_coverage_blocks.num_nodes()); - let mut insert = |bcb| { - bcb_has_mappings.insert(bcb); - }; - let mut test_vector_bitmap_bytes = 0; - for BcbMapping { kind, span: _ } in &mappings { - match *kind { - BcbMappingKind::Code(bcb) => insert(bcb), - BcbMappingKind::MCDCBranch { true_bcb, false_bcb, .. } => { - insert(true_bcb); - insert(false_bcb); - } - BcbMappingKind::MCDCDecision { bitmap_idx, conditions_num, .. } => { - // `bcb_has_mappings` is used for inject coverage counters - // but they are not needed for decision BCBs. - // While the length of test vector bitmap should be calculated here. - test_vector_bitmap_bytes = test_vector_bitmap_bytes - .max(bitmap_idx + (1_u32 << conditions_num as u32).div_ceil(8)); - } - } - } - for &BcbBranchPair { true_bcb, false_bcb, .. } in &branch_pairs { - insert(true_bcb); - insert(false_bcb); - } - - Some(CoverageSpans { bcb_has_mappings, mappings, branch_pairs, test_vector_bitmap_bytes }) + mappings: &mut impl Extend<BcbMapping>, +) { + let sorted_spans = + from_mir::mir_to_initial_sorted_coverage_spans(mir_body, hir_info, basic_coverage_blocks); + let coverage_spans = SpansRefiner::refine_sorted_spans(sorted_spans); + mappings.extend(coverage_spans.into_iter().map(|RefinedCovspan { bcb, span, .. }| { + // Each span produced by the generator represents an ordinary code region. + BcbMapping { kind: BcbMappingKind::Code(bcb), span } + })); } #[derive(Debug)] diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs index 64f21d74b1c..4ce37b5defc 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -1,11 +1,8 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; -use rustc_index::IndexVec; -use rustc_middle::mir::coverage::{ - BlockMarkerId, BranchSpan, CoverageKind, MCDCBranchSpan, MCDCDecisionSpan, -}; +use rustc_middle::mir::coverage::CoverageKind; use rustc_middle::mir::{ - self, AggregateKind, BasicBlock, FakeReadCause, Rvalue, Statement, StatementKind, Terminator, + self, AggregateKind, FakeReadCause, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, }; use rustc_span::{ExpnKind, MacroKind, Span, Symbol}; @@ -13,7 +10,6 @@ use rustc_span::{ExpnKind, MacroKind, Span, Symbol}; use crate::coverage::graph::{ BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph, START_BCB, }; -use crate::coverage::spans::{BcbBranchPair, BcbMapping, BcbMappingKind}; use crate::coverage::ExtractedHirInfo; /// Traverses the MIR body to produce an initial collection of coverage-relevant @@ -287,7 +283,7 @@ fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Span> { /// /// [^1]Expansions result from Rust syntax including macros, syntactic sugar, /// etc.). -fn unexpand_into_body_span_with_visible_macro( +pub(crate) fn unexpand_into_body_span_with_visible_macro( original_span: Span, body_span: Span, ) -> Option<(Span, Option<Symbol>)> { @@ -365,130 +361,3 @@ impl SpanFromMir { Self { span, visible_macro, bcb, is_hole } } } - -fn resolve_block_markers( - branch_info: &mir::coverage::BranchInfo, - mir_body: &mir::Body<'_>, -) -> IndexVec<BlockMarkerId, Option<BasicBlock>> { - let mut block_markers = IndexVec::<BlockMarkerId, Option<BasicBlock>>::from_elem_n( - None, - branch_info.num_block_markers, - ); - - // Fill out the mapping from block marker IDs to their enclosing blocks. - for (bb, data) in mir_body.basic_blocks.iter_enumerated() { - for statement in &data.statements { - if let StatementKind::Coverage(CoverageKind::BlockMarker { id }) = statement.kind { - block_markers[id] = Some(bb); - } - } - } - - block_markers -} - -// FIXME: There is currently a lot of redundancy between -// `extract_branch_pairs` and `extract_mcdc_mappings`. This is needed so -// that they can each be modified without interfering with the other, but in -// the long term we should try to bring them together again when branch coverage -// and MC/DC coverage support are more mature. - -pub(super) fn extract_branch_pairs( - mir_body: &mir::Body<'_>, - hir_info: &ExtractedHirInfo, - basic_coverage_blocks: &CoverageGraph, -) -> Vec<BcbBranchPair> { - let Some(branch_info) = mir_body.coverage_branch_info.as_deref() else { return vec![] }; - - let block_markers = resolve_block_markers(branch_info, mir_body); - - branch_info - .branch_spans - .iter() - .filter_map(|&BranchSpan { span: raw_span, true_marker, false_marker }| { - // For now, ignore any branch span that was introduced by - // expansion. This makes things like assert macros less noisy. - if !raw_span.ctxt().outer_expn_data().is_root() { - return None; - } - let (span, _) = - unexpand_into_body_span_with_visible_macro(raw_span, hir_info.body_span)?; - - let bcb_from_marker = - |marker: BlockMarkerId| basic_coverage_blocks.bcb_from_bb(block_markers[marker]?); - - let true_bcb = bcb_from_marker(true_marker)?; - let false_bcb = bcb_from_marker(false_marker)?; - - Some(BcbBranchPair { span, true_bcb, false_bcb }) - }) - .collect::<Vec<_>>() -} - -pub(super) fn extract_mcdc_mappings( - mir_body: &mir::Body<'_>, - body_span: Span, - basic_coverage_blocks: &CoverageGraph, -) -> Vec<BcbMapping> { - let Some(branch_info) = mir_body.coverage_branch_info.as_deref() else { - return vec![]; - }; - - let block_markers = resolve_block_markers(branch_info, mir_body); - - let bcb_from_marker = - |marker: BlockMarkerId| basic_coverage_blocks.bcb_from_bb(block_markers[marker]?); - - let check_branch_bcb = - |raw_span: Span, true_marker: BlockMarkerId, false_marker: BlockMarkerId| { - // For now, ignore any branch span that was introduced by - // expansion. This makes things like assert macros less noisy. - if !raw_span.ctxt().outer_expn_data().is_root() { - return None; - } - let (span, _) = unexpand_into_body_span_with_visible_macro(raw_span, body_span)?; - - let true_bcb = bcb_from_marker(true_marker)?; - let false_bcb = bcb_from_marker(false_marker)?; - Some((span, true_bcb, false_bcb)) - }; - - let mcdc_branch_filter_map = - |&MCDCBranchSpan { span: raw_span, true_marker, false_marker, condition_info }| { - check_branch_bcb(raw_span, true_marker, false_marker).map( - |(span, true_bcb, false_bcb)| BcbMapping { - kind: BcbMappingKind::MCDCBranch { true_bcb, false_bcb, condition_info }, - span, - }, - ) - }; - - let mut next_bitmap_idx = 0; - - let decision_filter_map = |decision: &MCDCDecisionSpan| { - let (span, _) = unexpand_into_body_span_with_visible_macro(decision.span, body_span)?; - - let end_bcbs = decision - .end_markers - .iter() - .map(|&marker| bcb_from_marker(marker)) - .collect::<Option<_>>()?; - - let bitmap_idx = next_bitmap_idx; - next_bitmap_idx += (1_u32 << decision.conditions_num).div_ceil(8); - - Some(BcbMapping { - kind: BcbMappingKind::MCDCDecision { - end_bcbs, - bitmap_idx, - conditions_num: decision.conditions_num as u16, - }, - span, - }) - }; - - std::iter::empty() - .chain(branch_info.mcdc_branch_spans.iter().filter_map(mcdc_branch_filter_map)) - .chain(branch_info.mcdc_decision_spans.iter().filter_map(decision_filter_map)) - .collect::<Vec<_>>() -} diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 24832086b16..4dd595ce1e1 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -121,7 +121,7 @@ impl<'tcx> MirPass<'tcx> for GVN { fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); - let ssa = SsaLocals::new(body); + let ssa = SsaLocals::new(tcx, body, param_env); // Clone dominators as we need them while mutating the body. let dominators = body.basic_blocks.dominators().clone(); @@ -724,6 +724,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { // Invariant: `value` holds the value up-to the `index`th projection excluded. let mut value = self.locals[place.local]?; for (index, proj) in place.projection.iter().enumerate() { + if let Value::Projection(pointer, ProjectionElem::Deref) = *self.get(value) + && let Value::Address { place: mut pointee, kind, .. } = *self.get(pointer) + && let AddressKind::Ref(BorrowKind::Shared) = kind + && let Some(v) = self.simplify_place_value(&mut pointee, location) + { + value = v; + place_ref = pointee.project_deeper(&place.projection[index..], self.tcx).as_ref(); + } if let Some(local) = self.try_as_local(value, location) { // Both `local` and `Place { local: place.local, projection: projection[..index] }` // hold the same value. Therefore, following place holds the value in the original @@ -735,6 +743,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { value = self.project(base, value, proj)?; } + if let Value::Projection(pointer, ProjectionElem::Deref) = *self.get(value) + && let Value::Address { place: mut pointee, kind, .. } = *self.get(pointer) + && let AddressKind::Ref(BorrowKind::Shared) = kind + && let Some(v) = self.simplify_place_value(&mut pointee, location) + { + value = v; + place_ref = pointee.project_deeper(&[], self.tcx).as_ref(); + } if let Some(new_local) = self.try_as_local(value, location) { place_ref = PlaceRef { local: new_local, projection: &[] }; } diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index b8dbf8a759f..90c1c7ba63b 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -583,33 +583,21 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { val.into() } - Aggregate(ref kind, ref fields) => { - // Do not const prop union fields as they can be - // made to produce values that don't match their - // underlying layout's type (see ICE #121534). - // If the last element of the `Adt` tuple - // is `Some` it indicates the ADT is a union - if let AggregateKind::Adt(_, _, _, _, Some(_)) = **kind { - return None; - }; - Value::Aggregate { - fields: fields - .iter() - .map(|field| { - self.eval_operand(field).map_or(Value::Uninit, Value::Immediate) - }) - .collect(), - variant: match **kind { - AggregateKind::Adt(_, variant, _, _, _) => variant, - AggregateKind::Array(_) - | AggregateKind::Tuple - | AggregateKind::RawPtr(_, _) - | AggregateKind::Closure(_, _) - | AggregateKind::Coroutine(_, _) - | AggregateKind::CoroutineClosure(_, _) => VariantIdx::ZERO, - }, - } - } + Aggregate(ref kind, ref fields) => Value::Aggregate { + fields: fields + .iter() + .map(|field| self.eval_operand(field).map_or(Value::Uninit, Value::Immediate)) + .collect(), + variant: match **kind { + AggregateKind::Adt(_, variant, _, _, _) => variant, + AggregateKind::Array(_) + | AggregateKind::Tuple + | AggregateKind::RawPtr(_, _) + | AggregateKind::Closure(_, _) + | AggregateKind::Coroutine(_, _) + | AggregateKind::CoroutineClosure(_, _) => VariantIdx::ZERO, + }, + }, Repeat(ref op, n) => { trace!(?op, ?n); @@ -896,13 +884,20 @@ impl CanConstProp { }; for (local, val) in cpv.can_const_prop.iter_enumerated_mut() { let ty = body.local_decls[local].ty; - match tcx.layout_of(param_env.and(ty)) { - Ok(layout) if layout.size < Size::from_bytes(MAX_ALLOC_LIMIT) => {} - // Either the layout fails to compute, then we can't use this local anyway - // or the local is too large, then we don't want to. - _ => { - *val = ConstPropMode::NoPropagation; - continue; + if ty.is_union() { + // Unions are incompatible with the current implementation of + // const prop because Rust has no concept of an active + // variant of a union + *val = ConstPropMode::NoPropagation; + } else { + match tcx.layout_of(param_env.and(ty)) { + Ok(layout) if layout.size < Size::from_bytes(MAX_ALLOC_LIMIT) => {} + // Either the layout fails to compute, then we can't use this local anyway + // or the local is too large, then we don't want to. + _ => { + *val = ConstPropMode::NoPropagation; + continue; + } } } } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index e42755ca7bf..e69c5da757e 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -4,7 +4,6 @@ #![feature(cow_is_borrowed)] #![feature(decl_macro)] #![feature(impl_trait_in_assoc_type)] -#![cfg_attr(bootstrap, feature(inline_const))] #![feature(is_sorted)] #![feature(let_chains)] #![feature(map_try_insert)] diff --git a/compiler/rustc_mir_transform/src/normalize_array_len.rs b/compiler/rustc_mir_transform/src/normalize_array_len.rs index 128634bd7f2..c26a5461633 100644 --- a/compiler/rustc_mir_transform/src/normalize_array_len.rs +++ b/compiler/rustc_mir_transform/src/normalize_array_len.rs @@ -22,7 +22,8 @@ impl<'tcx> MirPass<'tcx> for NormalizeArrayLen { } fn normalize_array_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let ssa = SsaLocals::new(body); + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + let ssa = SsaLocals::new(tcx, body, param_env); let slice_lengths = compute_slice_length(tcx, &ssa, body); debug!(?slice_lengths); diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index d5642be5513..044ae32c1d4 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -82,7 +82,8 @@ impl<'tcx> MirPass<'tcx> for ReferencePropagation { } fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { - let ssa = SsaLocals::new(body); + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + let ssa = SsaLocals::new(tcx, body, param_env); let mut replacer = compute_replacement(tcx, body, &ssa); debug!(?replacer.targets); diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs index fddc62e6652..55fed7d9da2 100644 --- a/compiler/rustc_mir_transform/src/ssa.rs +++ b/compiler/rustc_mir_transform/src/ssa.rs @@ -2,8 +2,9 @@ //! 1/ They are only assigned-to once, either as a function parameter, or in an assign statement; //! 2/ This single assignment dominates all uses; //! -//! As a consequence of rule 2, we consider that borrowed locals are not SSA, even if they are -//! `Freeze`, as we do not track that the assignment dominates all uses of the borrow. +//! As we do not track indirect assignments, a local that has its address taken (either by +//! AddressOf or by borrowing) is considered non-SSA. However, it is UB to modify through an +//! immutable borrow of a `Freeze` local. Those can still be considered to be SSA. use rustc_data_structures::graph::dominators::Dominators; use rustc_index::bit_set::BitSet; @@ -11,6 +12,7 @@ use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::middle::resolve_bound_vars::Set1; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; +use rustc_middle::ty::{ParamEnv, TyCtxt}; pub struct SsaLocals { /// Assignments to each local. This defines whether the local is SSA. @@ -24,6 +26,8 @@ pub struct SsaLocals { /// Number of "direct" uses of each local, ie. uses that are not dereferences. /// We ignore non-uses (Storage statements, debuginfo). direct_uses: IndexVec<Local, u32>, + /// Set of SSA locals that are immutably borrowed. + borrowed_locals: BitSet<Local>, } pub enum AssignedValue<'a, 'tcx> { @@ -33,15 +37,22 @@ pub enum AssignedValue<'a, 'tcx> { } impl SsaLocals { - pub fn new<'tcx>(body: &Body<'tcx>) -> SsaLocals { + pub fn new<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, param_env: ParamEnv<'tcx>) -> SsaLocals { let assignment_order = Vec::with_capacity(body.local_decls.len()); let assignments = IndexVec::from_elem(Set1::Empty, &body.local_decls); let dominators = body.basic_blocks.dominators(); let direct_uses = IndexVec::from_elem(0, &body.local_decls); - let mut visitor = - SsaVisitor { body, assignments, assignment_order, dominators, direct_uses }; + let borrowed_locals = BitSet::new_empty(body.local_decls.len()); + let mut visitor = SsaVisitor { + body, + assignments, + assignment_order, + dominators, + direct_uses, + borrowed_locals, + }; for local in body.args_iter() { visitor.assignments[local] = Set1::One(DefLocation::Argument); @@ -58,6 +69,16 @@ impl SsaLocals { visitor.visit_var_debug_info(var_debug_info); } + // The immutability of shared borrows only works on `Freeze` locals. If the visitor found + // borrows, we need to check the types. For raw pointers and mutable borrows, the locals + // have already been marked as non-SSA. + debug!(?visitor.borrowed_locals); + for local in visitor.borrowed_locals.iter() { + if !body.local_decls[local].ty.is_freeze(tcx, param_env) { + visitor.assignments[local] = Set1::Many; + } + } + debug!(?visitor.assignments); debug!(?visitor.direct_uses); @@ -70,6 +91,7 @@ impl SsaLocals { assignments: visitor.assignments, assignment_order: visitor.assignment_order, direct_uses: visitor.direct_uses, + borrowed_locals: visitor.borrowed_locals, // This is filled by `compute_copy_classes`. copy_classes: IndexVec::default(), }; @@ -174,6 +196,11 @@ impl SsaLocals { &self.copy_classes } + /// Set of SSA locals that are immutably borrowed. + pub fn borrowed_locals(&self) -> &BitSet<Local> { + &self.borrowed_locals + } + /// Make a property uniform on a copy equivalence class by removing elements. pub fn meet_copy_equivalence(&self, property: &mut BitSet<Local>) { // Consolidate to have a local iff all its copies are. @@ -208,6 +235,8 @@ struct SsaVisitor<'tcx, 'a> { assignments: IndexVec<Local, Set1<DefLocation>>, assignment_order: Vec<Local>, direct_uses: IndexVec<Local, u32>, + // Track locals that are immutably borrowed, so we can check their type is `Freeze` later. + borrowed_locals: BitSet<Local>, } impl SsaVisitor<'_, '_> { @@ -232,16 +261,18 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor<'tcx, '_> { PlaceContext::MutatingUse(MutatingUseContext::Projection) | PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) => bug!(), // Anything can happen with raw pointers, so remove them. - // We do not verify that all uses of the borrow dominate the assignment to `local`, - // so we have to remove them too. - PlaceContext::NonMutatingUse( - NonMutatingUseContext::SharedBorrow - | NonMutatingUseContext::FakeBorrow - | NonMutatingUseContext::AddressOf, - ) + PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) | PlaceContext::MutatingUse(_) => { self.assignments[local] = Set1::Many; } + // Immutable borrows are ok, but we need to delay a check that the type is `Freeze`. + PlaceContext::NonMutatingUse( + NonMutatingUseContext::SharedBorrow | NonMutatingUseContext::FakeBorrow, + ) => { + self.borrowed_locals.insert(local); + self.check_dominates(local, loc); + self.direct_uses[local] += 1; + } PlaceContext::NonMutatingUse(_) => { self.check_dominates(local, loc); self.direct_uses[local] += 1; diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index a8fa6fe002d..dd1065590b3 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -228,6 +228,7 @@ use rustc_middle::ty::{ TypeVisitableExt, VtblEntry, }; use rustc_middle::ty::{GenericArgKind, GenericArgs}; +use rustc_middle::{bug, span_bug}; use rustc_session::config::EntryFnType; use rustc_session::Limit; use rustc_span::source_map::{dummy_spanned, respan, Spanned}; diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index 2a91d69529a..cbab2006186 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -4,10 +4,9 @@ #[macro_use] extern crate tracing; -#[macro_use] -extern crate rustc_middle; use rustc_hir::lang_items::LangItem; +use rustc_middle::bug; use rustc_middle::query::{Providers, TyCtxtAt}; use rustc_middle::traits; use rustc_middle::ty::adjustment::CustomCoerceUnsized; diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 23e07890bb6..8f7b4c6472c 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -103,6 +103,7 @@ use rustc_data_structures::sync; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE}; use rustc_hir::definitions::DefPathDataName; +use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel}; use rustc_middle::mir::mono::{ diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index ed51710564a..848277c4611 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1191,7 +1191,11 @@ impl<'a> Parser<'a> { ident_span: ident.span, const_span, }); - ForeignItemKind::Static(ty, Mutability::Not, expr) + ForeignItemKind::Static(Box::new(StaticForeignItem { + ty, + mutability: Mutability::Not, + expr, + })) } _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"), }, diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index a545c170297..9d58d301e2b 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -49,12 +49,6 @@ passes_attr_crate_level = passes_attr_only_in_functions = `{$attr}` attribute can only be used on functions -passes_attr_only_on_main = - `{$attr}` attribute can only be used on `fn main()` - -passes_attr_only_on_root_main = - `{$attr}` attribute can only be used on root `fn main()` - passes_both_ffi_const_and_pure = `#[ffi_const]` function cannot be `#[ffi_pure]` @@ -695,9 +689,6 @@ passes_transparent_incompatible = passes_undefined_naked_function_abi = Rust ABI is unsupported in naked functions -passes_unix_sigpipe_values = - valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl` - passes_unknown_external_lang_item = unknown external lang item: `{$lang_item}` diff --git a/compiler/rustc_passes/src/abi_test.rs b/compiler/rustc_passes/src/abi_test.rs index 986ef69ad88..0c3dd649997 100644 --- a/compiler/rustc_passes/src/abi_test.rs +++ b/compiler/rustc_passes/src/abi_test.rs @@ -1,6 +1,7 @@ use rustc_ast::Attribute; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; +use rustc_middle::span_bug; use rustc_middle::ty::layout::{FnAbiError, LayoutError}; use rustc_middle::ty::{self, GenericArgs, Instance, Ty, TyCtxt}; use rustc_span::source_map::Spanned; diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index a2388b3bd52..e60aa27dba2 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -19,6 +19,7 @@ use rustc_hir::{ }; use rustc_hir::{MethodKind, Target, Unsafety}; use rustc_macros::LintDiagnostic; +use rustc_middle::bug; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault; use rustc_middle::query::Providers; @@ -2522,7 +2523,6 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { sym::automatically_derived, sym::start, sym::rustc_main, - sym::unix_sigpipe, sym::derive, sym::test, sym::test_case, diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index 4a1a2049083..eb29a65cb29 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -13,6 +13,7 @@ use rustc_hir::def_id::{LocalDefId, LocalModDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::hir::nested_filter; use rustc_middle::query::Providers; +use rustc_middle::span_bug; use rustc_middle::ty::TyCtxt; use rustc_session::parse::feature_err; use rustc_span::{sym, Span, Symbol}; diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 51f288b3c95..933412f677c 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -16,6 +16,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::privacy::Level; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::{bug, span_bug}; use rustc_session::lint; use rustc_session::lint::builtin::DEAD_CODE; use rustc_span::symbol::{sym, Symbol}; diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index 438c583db49..b43c8282db1 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -12,17 +12,16 @@ use rustc_span::symbol::sym; use rustc_span::{Span, Symbol}; use crate::errors::{ - AttrOnlyInFunctions, AttrOnlyOnMain, AttrOnlyOnRootMain, ExternMain, MultipleRustcMain, - MultipleStartFunctions, NoMainErr, UnixSigpipeValues, + AttrOnlyInFunctions, ExternMain, MultipleRustcMain, MultipleStartFunctions, NoMainErr, }; struct EntryContext<'tcx> { tcx: TyCtxt<'tcx>, - /// The function that has attribute named `main`. - attr_main_fn: Option<(LocalDefId, Span)>, + /// The function has the `#[rustc_main]` attribute. + rustc_main_fn: Option<(LocalDefId, Span)>, - /// The function that has the attribute 'start' on it. + /// The function that has the attribute `#[start]` on it. start_fn: Option<(LocalDefId, Span)>, /// The functions that one might think are `main` but aren't, e.g. @@ -43,10 +42,10 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> { } let mut ctxt = - EntryContext { tcx, attr_main_fn: None, start_fn: None, non_main_fns: Vec::new() }; + EntryContext { tcx, rustc_main_fn: None, start_fn: None, non_main_fns: Vec::new() }; for id in tcx.hir().items() { - find_item(id, &mut ctxt); + check_and_search_item(id, &mut ctxt); } configure_main(tcx, &ctxt) @@ -57,7 +56,16 @@ fn attr_span_by_symbol(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol) -> Opti attr::find_by_name(attrs, sym).map(|attr| attr.span) } -fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { +fn check_and_search_item(id: ItemId, ctxt: &mut EntryContext<'_>) { + if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) { + for attr in [sym::start, sym::rustc_main] { + if let Some(span) = attr_span_by_symbol(ctxt, id, attr) { + ctxt.tcx.dcx().emit_err(AttrOnlyInFunctions { span, attr }); + } + } + return; + } + let at_root = ctxt.tcx.opt_local_parent(id.owner_id.def_id) == Some(CRATE_DEF_ID); let attrs = ctxt.tcx.hir().attrs(id.hir_id()); @@ -66,41 +74,25 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { at_root, ctxt.tcx.opt_item_name(id.owner_id.to_def_id()), ); + match entry_point_type { - EntryPointType::None => { - if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) { - ctxt.tcx.dcx().emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe }); - } - } - _ if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) => { - for attr in [sym::start, sym::rustc_main] { - if let Some(span) = attr_span_by_symbol(ctxt, id, attr) { - ctxt.tcx.dcx().emit_err(AttrOnlyInFunctions { span, attr }); - } - } - } - EntryPointType::MainNamed => (), + EntryPointType::None => {} + EntryPointType::MainNamed => {} EntryPointType::OtherMain => { - if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) { - ctxt.tcx.dcx().emit_err(AttrOnlyOnRootMain { span, attr: sym::unix_sigpipe }); - } ctxt.non_main_fns.push(ctxt.tcx.def_span(id.owner_id)); } EntryPointType::RustcMainAttr => { - if ctxt.attr_main_fn.is_none() { - ctxt.attr_main_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id))); + if ctxt.rustc_main_fn.is_none() { + ctxt.rustc_main_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id))); } else { ctxt.tcx.dcx().emit_err(MultipleRustcMain { span: ctxt.tcx.def_span(id.owner_id.to_def_id()), - first: ctxt.attr_main_fn.unwrap().1, + first: ctxt.rustc_main_fn.unwrap().1, additional: ctxt.tcx.def_span(id.owner_id.to_def_id()), }); } } EntryPointType::Start => { - if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) { - ctxt.tcx.dcx().emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe }); - } if ctxt.start_fn.is_none() { ctxt.start_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id))); } else { @@ -118,10 +110,11 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, EntryFnType)> { if let Some((def_id, _)) = visitor.start_fn { Some((def_id.to_def_id(), EntryFnType::Start)) - } else if let Some((local_def_id, _)) = visitor.attr_main_fn { + } else if let Some((local_def_id, _)) = visitor.rustc_main_fn { let def_id = local_def_id.to_def_id(); - Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx, def_id) })) + Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx) })) } else { + // The actual resolution of main happens in the resolver, this here if let Some(main_def) = tcx.resolutions(()).main_def && let Some(def_id) = main_def.opt_fn_def_id() { @@ -133,31 +126,19 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, return None; } - return Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx, def_id) })); + return Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx) })); } no_main_err(tcx, visitor); None } } -fn sigpipe(tcx: TyCtxt<'_>, def_id: DefId) -> u8 { - if let Some(attr) = tcx.get_attr(def_id, sym::unix_sigpipe) { - match (attr.value_str(), attr.meta_item_list()) { - (Some(sym::inherit), None) => sigpipe::INHERIT, - (Some(sym::sig_ign), None) => sigpipe::SIG_IGN, - (Some(sym::sig_dfl), None) => sigpipe::SIG_DFL, - (Some(_), None) => { - tcx.dcx().emit_err(UnixSigpipeValues { span: attr.span }); - sigpipe::DEFAULT - } - _ => { - // Keep going so that `fn emit_malformed_attribute()` can print - // an excellent error message - sigpipe::DEFAULT - } - } - } else { - sigpipe::DEFAULT +fn sigpipe(tcx: TyCtxt<'_>) -> u8 { + match tcx.sess.opts.unstable_opts.on_broken_pipe { + rustc_target::spec::OnBrokenPipe::Default => sigpipe::DEFAULT, + rustc_target::spec::OnBrokenPipe::Kill => sigpipe::SIG_DFL, + rustc_target::spec::OnBrokenPipe::Error => sigpipe::SIG_IGN, + rustc_target::spec::OnBrokenPipe::Inherit => sigpipe::INHERIT, } } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 03a607348e8..65cad82cc8c 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1207,22 +1207,6 @@ pub struct NakedFunctionsMustUseNoreturn { } #[derive(Diagnostic)] -#[diag(passes_attr_only_on_main)] -pub struct AttrOnlyOnMain { - #[primary_span] - pub span: Span, - pub attr: Symbol, -} - -#[derive(Diagnostic)] -#[diag(passes_attr_only_on_root_main)] -pub struct AttrOnlyOnRootMain { - #[primary_span] - pub span: Span, - pub attr: Symbol, -} - -#[derive(Diagnostic)] #[diag(passes_attr_only_in_functions)] pub struct AttrOnlyInFunctions { #[primary_span] @@ -1259,13 +1243,6 @@ pub struct ExternMain { pub span: Span, } -#[derive(Diagnostic)] -#[diag(passes_unix_sigpipe_values)] -pub struct UnixSigpipeValues { - #[primary_span] - pub span: Span, -} - pub struct NoMainErr { pub sp: Span, pub crate_name: Symbol, diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs index 8d223c23363..82d43f078ee 100644 --- a/compiler/rustc_passes/src/layout_test.rs +++ b/compiler/rustc_passes/src/layout_test.rs @@ -1,6 +1,7 @@ use rustc_ast::Attribute; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; +use rustc_middle::span_bug; use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; use rustc_span::source_map::Spanned; diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index bce29e2af09..d3608759eec 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -13,8 +13,6 @@ #![feature(try_blocks)] #[macro_use] -extern crate rustc_middle; -#[macro_use] extern crate tracing; use rustc_middle::query::Providers; diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index c7729302783..b50cb158b1f 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -94,6 +94,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Expr, HirId, HirIdMap, HirIdSet}; use rustc_index::IndexVec; use rustc_middle::query::Providers; +use rustc_middle::span_bug; use rustc_middle::ty::{self, RootVariableMinCaptureList, Ty, TyCtxt}; use rustc_session::lint; use rustc_span::symbol::{kw, sym, Symbol}; diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs index e10a22cdf31..4b5c4dfe991 100644 --- a/compiler/rustc_passes/src/loops.rs +++ b/compiler/rustc_passes/src/loops.rs @@ -6,6 +6,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Destination, Node}; use rustc_middle::hir::nested_filter; use rustc_middle::query::Providers; +use rustc_middle::span_bug; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_span::hygiene::DesugaringKind; diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 869cbebbc0d..d5e1a70fd45 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -17,6 +17,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::Node; +use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::middle::privacy::{self, Level}; use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc}; diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 6e8843d9049..4155540886a 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -14,12 +14,6 @@ pub mod pat_column; pub mod rustc; pub mod usefulness; -#[macro_use] -extern crate tracing; -#[cfg(feature = "rustc")] -#[macro_use] -extern crate rustc_middle; - #[cfg(feature = "rustc")] rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs index 3ca5ebdb0dd..1d10c9df4ab 100644 --- a/compiler/rustc_pattern_analysis/src/lints.rs +++ b/compiler/rustc_pattern_analysis/src/lints.rs @@ -1,11 +1,11 @@ -use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; -use rustc_span::ErrorGuaranteed; - use crate::constructor::Constructor; use crate::errors::{NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Uncovered}; use crate::pat_column::PatternColumn; use crate::rustc::{RevealedTy, RustcPatCtxt, WitnessPat}; use crate::MatchArm; +use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; +use rustc_span::ErrorGuaranteed; +use tracing::instrument; /// Traverse the patterns to collect any variants of a non_exhaustive enum that fail to be mentioned /// in a given column. diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 548a7b43005..ff68dd81bea 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -11,6 +11,7 @@ use rustc_middle::mir::{self, Const}; use rustc_middle::thir::{self, FieldPat, Pat, PatKind, PatRange, PatRangeBoundary}; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{self, FieldDef, OpaqueTypeKey, Ty, TyCtxt, TypeVisitableExt, VariantDef}; +use rustc_middle::{bug, span_bug}; use rustc_session::lint; use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP}; use rustc_target::abi::{FieldIdx, Integer, VariantIdx, FIRST_VARIANT}; diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 7246039174a..74af9154f85 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -709,16 +709,15 @@ //! I (Nadrieril) prefer to put new tests in `ui/pattern/usefulness` unless there's a specific //! reason not to, for example if they crucially depend on a particular feature like `or_patterns`. +use self::PlaceValidity::*; +use crate::constructor::{Constructor, ConstructorSet, IntRange}; +use crate::pat::{DeconstructedPat, PatId, PatOrWild, WitnessPat}; +use crate::{Captures, MatchArm, PatCx, PrivateUninhabitedField}; use rustc_hash::FxHashSet; use rustc_index::bit_set::BitSet; use smallvec::{smallvec, SmallVec}; use std::fmt; - -use crate::constructor::{Constructor, ConstructorSet, IntRange}; -use crate::pat::{DeconstructedPat, PatId, PatOrWild, WitnessPat}; -use crate::{Captures, MatchArm, PatCx, PrivateUninhabitedField}; - -use self::PlaceValidity::*; +use tracing::{debug, instrument}; #[cfg(feature = "rustc")] use rustc_data_structures::stack::ensure_sufficient_stack; diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml index e7a32771f35..f998e0ff154 100644 --- a/compiler/rustc_privacy/Cargo.toml +++ b/compiler/rustc_privacy/Cargo.toml @@ -11,7 +11,6 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } -rustc_hir_analysis = { path = "../rustc_hir_analysis" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_session = { path = "../rustc_session" } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 2039e994aaa..a78f7e65981 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -6,9 +6,6 @@ #![feature(try_blocks)] #![feature(let_chains)] -#[macro_use] -extern crate tracing; - mod errors; use rustc_ast::visit::{try_visit, VisitorResult}; @@ -31,6 +28,7 @@ use rustc_session::lint; use rustc_span::hygiene::Transparency; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Span; +use tracing::debug; use std::fmt; use std::marker::PhantomData; diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml index 6ea87a4a633..4d845ab0d07 100644 --- a/compiler/rustc_query_system/Cargo.toml +++ b/compiler/rustc_query_system/Cargo.toml @@ -19,7 +19,6 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } -rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } thin-vec = "0.2.12" tracing = "0.1" diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs index 17f96896a50..5f1a03502a7 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -49,6 +49,7 @@ use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey}; use rustc_data_structures::AtomicRef; use rustc_hir::definitions::DefPathHash; +use rustc_macros::{Decodable, Encodable}; use std::fmt; use std::hash::Hash; @@ -75,8 +76,6 @@ impl DepKind { } } -static_assert_size!(DepKind, 2); - pub fn default_dep_kind_debug(kind: DepKind, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("DepKind").field("variant", &kind.variant).finish() } @@ -96,15 +95,6 @@ pub struct DepNode { pub hash: PackedFingerprint, } -// We keep a lot of `DepNode`s in memory during compilation. It's not -// required that their size stay the same, but we don't want to change -// it inadvertently. This assert just ensures we're aware of any change. -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -static_assert_size!(DepNode, 18); - -#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -static_assert_size!(DepNode, 24); - impl DepNode { /// Creates a new, parameterless DepNode. This method will assert /// that the DepNode corresponding to the given DepKind actually @@ -285,8 +275,7 @@ pub struct DepKindStruct<Tcx: DepContext> { /// some independent path or string that persists between runs without /// the need to be mapped or unmapped. (This ensures we can serialize /// them even in the absence of a tcx.) -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[derive(Encodable, Decodable)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] pub struct WorkProductId { hash: Fingerprint, } @@ -316,3 +305,17 @@ unsafe impl StableOrd for WorkProductId { // Fingerprint can use unstable (just a tuple of `u64`s), so WorkProductId can as well const CAN_USE_UNSTABLE_SORT: bool = true; } + +// Some types are used a lot. Make sure they don't unintentionally get bigger. +#[cfg(target_pointer_width = "64")] +mod size_asserts { + use super::*; + use rustc_data_structures::static_assert_size; + // tidy-alphabetical-start + static_assert_size!(DepKind, 2); + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + static_assert_size!(DepNode, 18); + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + static_assert_size!(DepNode, 24); + // tidy-alphabetical-end +} diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 2b3fa7f6cfa..76227a78c3d 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -6,6 +6,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, Lrc}; use rustc_data_structures::unord::UnordMap; use rustc_index::IndexVec; +use rustc_macros::{Decodable, Encodable}; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use std::assert_matches::assert_matches; use std::collections::hash_map::Entry; @@ -14,6 +15,7 @@ use std::hash::Hash; use std::marker::PhantomData; use std::sync::atomic::Ordering; use std::sync::Arc; +use tracing::{debug, instrument}; use super::query::DepGraphQuery; use super::serialized::{GraphEncoder, SerializedDepGraph, SerializedDepNodeIndex}; @@ -40,6 +42,11 @@ rustc_index::newtype_index! { pub struct DepNodeIndex {} } +// We store a large collection of these in `prev_index_to_index` during +// non-full incremental builds, and want to ensure that the element size +// doesn't inadvertently increase. +rustc_data_structures::static_assert_size!(Option<DepNodeIndex>, 4); + impl DepNodeIndex { const SINGLETON_DEPENDENCYLESS_ANON_NODE: DepNodeIndex = DepNodeIndex::ZERO; pub const FOREVER_RED_NODE: DepNodeIndex = DepNodeIndex::from_u32(1); @@ -1106,11 +1113,6 @@ impl<D: Deps> CurrentDepGraph<D> { Err(_) => None, }; - // We store a large collection of these in `prev_index_to_index` during - // non-full incremental builds, and want to ensure that the element size - // doesn't inadvertently increase. - static_assert_size!(Option<DepNodeIndex>, 4); - let new_node_count_estimate = 102 * prev_graph_node_count / 100 + 200; CurrentDepGraph { diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index feb69ecd078..cbd80295887 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -11,13 +11,12 @@ pub use graph::{hash_result, DepGraph, DepNodeIndex, TaskDepsRef, WorkProduct, W pub use query::DepGraphQuery; pub use serialized::{SerializedDepGraph, SerializedDepNodeIndex}; +use self::graph::{print_markframe_trace, MarkFrame}; use crate::ich::StableHashingContext; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_session::Session; - use std::panic; - -use self::graph::{print_markframe_trace, MarkFrame}; +use tracing::instrument; pub trait DepContext: Copy { type Deps: Deps; diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index 6042aa6a2d2..b426bb888f4 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -51,6 +51,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use std::iter; use std::marker::PhantomData; use std::sync::Arc; +use tracing::{debug, instrument}; // The maximum value of `SerializedDepNodeIndex` leaves the upper two bits // unused so that we can store multiple index types in `CompressedHybridIndex`, diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index 416f556f57d..fa07877ab9f 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -5,13 +5,6 @@ #![feature(let_chains)] #![allow(rustc::potential_query_instability, internal_features)] -#[macro_use] -extern crate tracing; -#[macro_use] -extern crate rustc_data_structures; -#[macro_use] -extern crate rustc_macros; - pub mod cache; pub mod dep_graph; mod error; diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 91a0026f281..ab4f48fcd32 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -20,6 +20,7 @@ use rustc_data_structures::stable_hasher::Hash64; use rustc_data_structures::sync::Lock; use rustc_errors::DiagInner; use rustc_hir::def::DefKind; +use rustc_macros::{Decodable, Encodable}; use rustc_span::def_id::DefId; use rustc_span::Span; use thin_vec::ThinVec; diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 3d9848395a2..d37d5bce9cc 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -27,6 +27,7 @@ use std::fmt::Debug; use std::hash::Hash; use std::mem; use thin_vec::ThinVec; +use tracing::instrument; use super::QueryConfig; diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index d4d999f6f9c..a27a6bceda3 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -209,7 +209,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { fn visit_foreign_item(&mut self, fi: &'a ForeignItem) { let def_kind = match fi.kind { - ForeignItemKind::Static(_, mutability, _) => { + ForeignItemKind::Static(box StaticForeignItem { ty: _, mutability, expr: _ }) => { DefKind::Static { mutability, nested: false } } ForeignItemKind::Fn(_) => DefKind::Fn, diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 12484462f82..01e279b6d04 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1617,7 +1617,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let post = format!(", consider renaming `{}` into `{snippet}`", suggestion.candidate); (span, snippet, post) } else { - (span, suggestion.candidate.to_string(), String::new()) + (span, suggestion.candidate.to_ident_string(), String::new()) }; let msg = match suggestion.target { SuggestionTarget::SimilarlyNamed => format!( diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 82e41b6c314..35bf3f761df 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -141,7 +141,7 @@ pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools { } // We implicitly add `rustfmt`, `clippy`, `diagnostic` to known tools, // but it's not an error to register them explicitly. - let predefined_tools = [sym::clippy, sym::rustfmt, sym::diagnostic]; + let predefined_tools = [sym::clippy, sym::rustfmt, sym::diagnostic, sym::miri]; registered_tools.extend(predefined_tools.iter().cloned().map(Ident::with_dummy_span)); registered_tools } diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index 0bc7579918c..aace0f3fef9 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -6,8 +6,8 @@ use rustc_middle::ty::TyCtxt; use rustc_span::def_id::DefId; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{InnerSpan, Span, DUMMY_SP}; +use std::mem; use std::ops::Range; -use std::{cmp, mem}; #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum DocFragmentKind { @@ -129,17 +129,20 @@ pub fn unindent_doc_fragments(docs: &mut [DocFragment]) { let Some(min_indent) = docs .iter() .map(|fragment| { - fragment.doc.as_str().lines().fold(usize::MAX, |min_indent, line| { - if line.chars().all(|c| c.is_whitespace()) { - min_indent - } else { + fragment + .doc + .as_str() + .lines() + .filter(|line| line.chars().any(|c| !c.is_whitespace())) + .map(|line| { // Compare against either space or tab, ignoring whether they are // mixed or not. let whitespace = line.chars().take_while(|c| *c == ' ' || *c == '\t').count(); - cmp::min(min_indent, whitespace) - + if fragment.kind == DocFragmentKind::SugaredDoc { 0 } else { add } - } - }) + whitespace + + (if fragment.kind == DocFragmentKind::SugaredDoc { 0 } else { add }) + }) + .min() + .unwrap_or(usize::MAX) }) .min() else { @@ -151,13 +154,13 @@ pub fn unindent_doc_fragments(docs: &mut [DocFragment]) { continue; } - let min_indent = if fragment.kind != DocFragmentKind::SugaredDoc && min_indent > 0 { + let indent = if fragment.kind != DocFragmentKind::SugaredDoc && min_indent > 0 { min_indent - add } else { min_indent }; - fragment.indent = min_indent; + fragment.indent = indent; } } diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index 40cd0c14b05..d67132d2dd4 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -4,7 +4,9 @@ //! //! For more information about LLVM CFI and cross-language LLVM CFI support for the Rust compiler, //! see design document in the tracking issue #89653. -use rustc_data_structures::base_n; +use rustc_data_structures::base_n::ToBaseN; +use rustc_data_structures::base_n::ALPHANUMERIC_ONLY; +use rustc_data_structures::base_n::CASE_INSENSITIVE; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_middle::bug; @@ -736,7 +738,7 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String { /// <https://rust-lang.github.io/rfcs/2603-rust-symbol-name-mangling-v0.html>). fn to_disambiguator(num: u64) -> String { if let Some(num) = num.checked_sub(1) { - format!("s{}_", base_n::encode(num as u128, base_n::ALPHANUMERIC_ONLY)) + format!("s{}_", num.to_base(ALPHANUMERIC_ONLY)) } else { "s_".to_string() } @@ -746,7 +748,7 @@ fn to_disambiguator(num: u64) -> String { /// <https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangle.seq-id>). fn to_seq_id(num: usize) -> String { if let Some(num) = num.checked_sub(1) { - base_n::encode(num as u128, base_n::CASE_INSENSITIVE).to_uppercase() + (num as u64).to_base(CASE_INSENSITIVE).to_uppercase() } else { "".to_string() } diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs index 19f4e6994ac..532b749f913 100644 --- a/compiler/rustc_serialize/src/lib.rs +++ b/compiler/rustc_serialize/src/lib.rs @@ -8,10 +8,8 @@ #![doc(rust_logo)] #![allow(internal_features)] #![feature(rustdoc_internals)] -#![cfg_attr(bootstrap, feature(associated_type_bounds))] #![feature(const_option)] #![feature(core_intrinsics)] -#![cfg_attr(bootstrap, feature(inline_const))] #![feature(min_specialization)] #![feature(never_type)] #![feature(ptr_sub_ptr)] diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 4f259960ac3..f2bdabbf394 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -15,6 +15,7 @@ use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey}; use rustc_errors::emitter::HumanReadableErrorType; use rustc_errors::{ColorConfig, DiagArgValue, DiagCtxtFlags, IntoDiagArg}; use rustc_feature::UnstableFeatures; +use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION}; use rustc_span::source_map::FilePathMapping; use rustc_span::{FileName, FileNameDisplayPreference, RealFileName, SourceFileHashAlgorithm}; @@ -32,6 +33,7 @@ use std::iter; use std::path::{Path, PathBuf}; use std::str::{self, FromStr}; use std::sync::LazyLock; +use tracing::debug; mod cfg; pub mod sigpipe; @@ -146,10 +148,26 @@ pub enum InstrumentCoverage { /// Individual flag values controlled by `-Z coverage-options`. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)] pub struct CoverageOptions { - /// Add branch coverage instrumentation. - pub branch: bool, - /// Add mcdc coverage instrumentation. - pub mcdc: bool, + pub level: CoverageLevel, + // Other boolean or enum-valued options might be added here. +} + +/// Controls whether branch coverage or MC/DC coverage is enabled. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +pub enum CoverageLevel { + /// Instrument for coverage at the MIR block level. + Block, + /// Also instrument branch points (includes block coverage). + Branch, + /// Instrument for MC/DC. Mostly a superset of branch coverage, but might + /// differ in some corner cases. + Mcdc, +} + +impl Default for CoverageLevel { + fn default() -> Self { + Self::Block + } } /// Settings for `-Z instrument-xray` flag. @@ -2891,7 +2909,9 @@ pub(crate) mod dep_tracking { use rustc_feature::UnstableFeatures; use rustc_span::edition::Edition; use rustc_span::RealFileName; - use rustc_target::spec::{CodeModel, MergeFunctions, PanicStrategy, RelocModel, WasmCAbi}; + use rustc_target::spec::{ + CodeModel, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel, WasmCAbi, + }; use rustc_target::spec::{ RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, }; @@ -2955,6 +2975,7 @@ pub(crate) mod dep_tracking { InstrumentXRay, CrateType, MergeFunctions, + OnBrokenPipe, PanicStrategy, RelroLevel, OptLevel, diff --git a/compiler/rustc_session/src/config/sigpipe.rs b/compiler/rustc_session/src/config/sigpipe.rs index 1fadc75cfd0..1830ee03485 100644 --- a/compiler/rustc_session/src/config/sigpipe.rs +++ b/compiler/rustc_session/src/config/sigpipe.rs @@ -1,6 +1,6 @@ //! NOTE: Keep these constants in sync with `library/std/src/sys/pal/unix/mod.rs`! -/// The default value if `#[unix_sigpipe]` is not specified. This resolves +/// The default value if `-Zon-broken-pipe=...` is not specified. This resolves /// to `SIG_IGN` in `library/std/src/sys/pal/unix/mod.rs`. /// /// Note that `SIG_IGN` has been the Rust default since 2014. See diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs index 83377b66095..2c20c3f0e1a 100644 --- a/compiler/rustc_session/src/cstore.rs +++ b/compiler/rustc_session/src/cstore.rs @@ -10,6 +10,7 @@ use rustc_hir::def_id::{ CrateNum, DefId, LocalDefId, StableCrateId, StableCrateIdMap, LOCAL_CRATE, }; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions}; +use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::symbol::Symbol; use rustc_span::Span; use rustc_target::spec::abi::Abi; diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 2e4c7d14ecd..dce56382a53 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -6,7 +6,7 @@ use rustc_errors::{ codes::*, Diag, DiagCtxt, DiagMessage, Diagnostic, EmissionGuarantee, ErrorGuaranteed, Level, MultiSpan, }; -use rustc_macros::Diagnostic; +use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Span, Symbol}; use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple}; diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index aecf5954c4c..f4e2436efb9 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -1,13 +1,12 @@ //! A module for searching for libraries -use rustc_fs_util::try_canonicalize; +use crate::search_paths::{PathKind, SearchPath}; +use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize}; use smallvec::{smallvec, SmallVec}; use std::env; use std::fs; use std::path::{Path, PathBuf}; - -use crate::search_paths::{PathKind, SearchPath}; -use rustc_fs_util::fix_windows_verbatim_for_gcc; +use tracing::debug; #[derive(Clone)] pub struct FileSearch<'a> { diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 58e1394c090..ce866906e1e 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -6,13 +6,8 @@ #![feature(iter_intersperse)] #![allow(internal_features)] -#[macro_use] -extern crate rustc_macros; pub mod errors; -#[macro_use] -extern crate tracing; - pub mod utils; pub use lint::{declare_lint, declare_lint_pass, declare_tool_lint, impl_lint_pass}; pub use rustc_lint_defs as lint; diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index e1474ee365b..65660286dd7 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -12,7 +12,7 @@ use rustc_span::edition::Edition; use rustc_span::RealFileName; use rustc_span::SourceFileHashAlgorithm; use rustc_target::spec::{ - CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, SanitizerSet, WasmCAbi, + CodeModel, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy, SanitizerSet, WasmCAbi, }; use rustc_target::spec::{ RelocModel, RelroLevel, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, @@ -378,6 +378,7 @@ mod desc { pub const parse_time_passes_format: &str = "`text` (default) or `json`"; 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_on_broken_pipe: &str = "either `kill`, `error`, or `inherit`"; pub const parse_opt_panic_strategy: &str = parse_panic_strategy; pub const parse_oom_strategy: &str = "either `panic` or `abort`"; pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`"; @@ -394,7 +395,7 @@ mod desc { pub const parse_optimization_fuel: &str = "crate=integer"; pub const parse_dump_mono_stats: &str = "`markdown` (default) or `json`"; pub const parse_instrument_coverage: &str = parse_bool; - pub const parse_coverage_options: &str = "either `no-branch`, `branch` or `mcdc`"; + pub const parse_coverage_options: &str = "`block` | `branch` | `mcdc`"; pub const parse_instrument_xray: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or a comma separated list of settings: `always` or `never` (mutually exclusive), `ignore-loops`, `instruction-threshold=N`, `skip-entry`, `skip-exit`"; pub const parse_unpretty: &str = "`string` or `string=string`"; pub const parse_treat_err_as_bug: &str = "either no value or a non-negative number"; @@ -708,6 +709,17 @@ mod parse { true } + pub(crate) fn parse_on_broken_pipe(slot: &mut OnBrokenPipe, v: Option<&str>) -> bool { + match v { + // OnBrokenPipe::Default can't be explicitly specified + Some("kill") => *slot = OnBrokenPipe::Kill, + Some("error") => *slot = OnBrokenPipe::Error, + Some("inherit") => *slot = OnBrokenPipe::Inherit, + _ => return false, + } + true + } + pub(crate) fn parse_oom_strategy(slot: &mut OomStrategy, v: Option<&str>) -> bool { match v { Some("panic") => *slot = OomStrategy::Panic, @@ -946,15 +958,9 @@ mod parse { for option in v.split(',') { match option { - "no-branch" => { - slot.branch = false; - slot.mcdc = false; - } - "branch" => slot.branch = true, - "mcdc" => { - slot.branch = true; - slot.mcdc = true; - } + "block" => slot.level = CoverageLevel::Block, + "branch" => slot.level = CoverageLevel::Branch, + "mcdc" => slot.level = CoverageLevel::Mcdc, _ => return false, } } @@ -1839,6 +1845,8 @@ options! { "do not use unique names for text and data sections when -Z function-sections is used"), normalize_docs: bool = (false, parse_bool, [TRACKED], "normalize associated items in rustdoc when generating documentation"), + on_broken_pipe: OnBrokenPipe = (OnBrokenPipe::Default, parse_on_broken_pipe, [TRACKED], + "behavior of std::io::ErrorKind::BrokenPipe (SIGPIPE)"), oom: OomStrategy = (OomStrategy::Abort, parse_oom_strategy, [TRACKED], "panic strategy for out-of-memory handling"), osx_rpath_install_name: bool = (false, parse_bool, [TRACKED], diff --git a/compiler/rustc_session/src/search_paths.rs b/compiler/rustc_session/src/search_paths.rs index bc2f2a8af1f..5e8adffc249 100644 --- a/compiler/rustc_session/src/search_paths.rs +++ b/compiler/rustc_session/src/search_paths.rs @@ -1,5 +1,6 @@ use crate::filesearch::make_target_lib_path; use crate::EarlyDiagCtxt; +use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_target::spec::TargetTriple; use std::path::{Path, PathBuf}; diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 2bc14b43234..db01bb90d6f 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1,8 +1,8 @@ use crate::code_stats::CodeStats; pub use crate::code_stats::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo}; use crate::config::{ - self, CrateType, FunctionReturn, InstrumentCoverage, OptLevel, OutFileName, OutputType, - RemapPathScopeComponents, SwitchWithOptPath, + self, CoverageLevel, CrateType, FunctionReturn, InstrumentCoverage, OptLevel, OutFileName, + OutputType, RemapPathScopeComponents, SwitchWithOptPath, }; use crate::config::{ErrorOutputType, Input}; use crate::errors; @@ -349,11 +349,13 @@ impl Session { } pub fn instrument_coverage_branch(&self) -> bool { - self.instrument_coverage() && self.opts.unstable_opts.coverage_options.branch + self.instrument_coverage() + && self.opts.unstable_opts.coverage_options.level >= CoverageLevel::Branch } pub fn instrument_coverage_mcdc(&self) -> bool { - self.instrument_coverage() && self.opts.unstable_opts.coverage_options.mcdc + self.instrument_coverage() + && self.opts.unstable_opts.coverage_options.level >= CoverageLevel::Mcdc } pub fn is_sanitizer_cfi_enabled(&self) -> bool { diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs index 58de5cb31a5..f70a53eeb41 100644 --- a/compiler/rustc_session/src/utils.rs +++ b/compiler/rustc_session/src/utils.rs @@ -1,6 +1,7 @@ use crate::session::Session; use rustc_data_structures::profiling::VerboseTimingGuard; use rustc_fs_util::try_canonicalize; +use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use std::{ path::{Path, PathBuf}, sync::OnceLock, diff --git a/compiler/rustc_session/src/version.rs b/compiler/rustc_session/src/version.rs index c0c088bcef7..39e4541349e 100644 --- a/compiler/rustc_session/src/version.rs +++ b/compiler/rustc_session/src/version.rs @@ -1,3 +1,4 @@ +use rustc_macros::{current_rustc_version, Decodable, Encodable, HashStable_Generic}; use std::fmt::{self, Display}; #[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index 8925b7a42d4..1ac3a817bba 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -6,7 +6,7 @@ use rustc_data_structures::stable_hasher::{ use rustc_data_structures::unhash::Unhasher; use rustc_data_structures::AtomicRef; use rustc_index::Idx; -use rustc_macros::HashStable_Generic; +use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_serialize::{Decodable, Encodable}; use std::fmt; use std::hash::{BuildHasherDefault, Hash, Hasher}; diff --git a/compiler/rustc_span/src/edition.rs b/compiler/rustc_span/src/edition.rs index 78ac61fa31d..fe09daf522c 100644 --- a/compiler/rustc_span/src/edition.rs +++ b/compiler/rustc_span/src/edition.rs @@ -1,7 +1,7 @@ use std::fmt; use std::str::FromStr; -use rustc_macros::HashStable_Generic; +use rustc_macros::{Decodable, Encodable, HashStable_Generic}; /// The edition of the compiler. (See [RFC 2052](https://github.com/rust-lang/rfcs/blob/master/text/2052-epochs.md).) #[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Debug, Encodable, Decodable, Eq)] diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 6093df94179..aa4bcefab93 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -34,7 +34,7 @@ use rustc_data_structures::stable_hasher::{Hash64, HashStable, HashingControls, use rustc_data_structures::sync::{Lock, Lrc, WorkerLocal}; use rustc_data_structures::unhash::UnhashMap; use rustc_index::IndexVec; -use rustc_macros::HashStable_Generic; +use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use std::cell::RefCell; use std::collections::hash_map::Entry; diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index f749d4eb833..f83bacdcebe 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -36,13 +36,10 @@ extern crate self as rustc_span; #[macro_use] -extern crate rustc_macros; - -#[macro_use] extern crate tracing; use rustc_data_structures::{outline, AtomicRef}; -use rustc_macros::HashStable_Generic; +use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_serialize::opaque::{FileEncoder, MemDecoder}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 33bd11cc807..2093dcf0e83 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -12,6 +12,7 @@ use crate::*; use rustc_data_structures::sync::{IntoDynSyncSend, MappedReadGuard, ReadGuard, RwLock}; use rustc_data_structures::unhash::UnhashMap; +use rustc_macros::{Decodable, Encodable}; use std::fs; use std::io::{self, BorrowedBuf, Read}; use std::path; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 99591b5e144..9c556f1152a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -8,7 +8,7 @@ use rustc_data_structures::stable_hasher::{ HashStable, StableCompare, StableHasher, ToStableHashKey, }; use rustc_data_structures::sync::Lock; -use rustc_macros::HashStable_Generic; +use rustc_macros::{symbols, Decodable, Encodable, HashStable_Generic}; use std::fmt; use std::hash::{Hash, Hasher}; @@ -754,6 +754,7 @@ symbols! { enable, encode, end, + enumerate_method, env, env_CFG_RELEASE: env!("CFG_RELEASE"), eprint_macro, @@ -1935,7 +1936,6 @@ symbols! { unit, universal_impl_trait, unix, - unix_sigpipe, unlikely, unmarked_api, unnamed_fields, diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index f1c3512315f..0ed1f67bb82 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -1,12 +1,13 @@ use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher}; use rustc_hir::def_id::CrateNum; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; +use rustc_middle::bug; use rustc_middle::ty::print::{PrettyPrinter, Print, PrintError, Printer}; use rustc_middle::ty::{self, Instance, ReifyReason, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{GenericArg, GenericArgKind}; - use std::fmt::{self, Write}; use std::mem::{self, discriminant}; +use tracing::debug; pub(super) fn mangle<'tcx>( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index b9509478702..745ae41085b 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -93,12 +93,6 @@ #![feature(let_chains)] #![allow(internal_features)] -#[macro_use] -extern crate rustc_middle; - -#[macro_use] -extern crate tracing; - use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; @@ -107,6 +101,7 @@ use rustc_middle::mir::mono::{InstantiationMode, MonoItem}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, Instance, TyCtxt}; use rustc_session::config::SymbolManglingVersion; +use tracing::debug; mod hashed; mod legacy; diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 58b67c77a61..5cdfb773b5c 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -1,10 +1,11 @@ -use rustc_data_structures::base_n; +use rustc_data_structures::base_n::ToBaseN; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::intern::Interned; use rustc_hir as hir; use rustc_hir::def::CtorKind; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; +use rustc_middle::bug; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::print::{Print, PrintError, Printer}; use rustc_middle::ty::{ @@ -831,7 +832,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { /// e.g. `1` becomes `"0_"`, `62` becomes `"Z_"`, etc. pub(crate) fn push_integer_62(x: u64, output: &mut String) { if let Some(x) = x.checked_sub(1) { - base_n::push_str(x as u128, base_n::ALPHANUMERIC_ONLY, output); + output.push_str(&x.to_base(62)); } output.push('_'); } diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index cdd82aa9dbc..3ddea42f67b 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -1,6 +1,7 @@ use crate::abi::{self, Abi, Align, FieldsShape, Size}; use crate::abi::{HasDataLayout, TyAbiInterface, TyAndLayout}; use crate::spec::{self, HasTargetSpec, HasWasmCAbiOpt}; +use rustc_macros::HashStable_Generic; use rustc_span::Symbol; use std::fmt; use std::str::FromStr; @@ -100,6 +101,8 @@ pub use attr_impl::ArgAttribute; #[allow(non_upper_case_globals)] #[allow(unused)] mod attr_impl { + use rustc_macros::HashStable_Generic; + // The subset of llvm::Attribute needed for arguments, packed into a bitfield. #[derive(Clone, Copy, Default, Hash, PartialEq, Eq, HashStable_Generic)] pub struct ArgAttribute(u8); diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs index 5ae9a2e2058..1a3218da1af 100644 --- a/compiler/rustc_target/src/asm/aarch64.rs +++ b/compiler/rustc_target/src/asm/aarch64.rs @@ -1,7 +1,6 @@ use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; use crate::spec::{RelocModel, Target}; use rustc_data_structures::fx::FxIndexSet; -use rustc_macros::HashStable_Generic; use rustc_span::Symbol; use std::fmt; diff --git a/compiler/rustc_target/src/asm/arm.rs b/compiler/rustc_target/src/asm/arm.rs index f56dbac708b..37184393a73 100644 --- a/compiler/rustc_target/src/asm/arm.rs +++ b/compiler/rustc_target/src/asm/arm.rs @@ -1,7 +1,6 @@ use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; use crate::spec::{RelocModel, Target}; use rustc_data_structures::fx::FxIndexSet; -use rustc_macros::HashStable_Generic; use rustc_span::{sym, Symbol}; use std::fmt; diff --git a/compiler/rustc_target/src/asm/avr.rs b/compiler/rustc_target/src/asm/avr.rs index eab38a4a4f4..6943fd9b5d7 100644 --- a/compiler/rustc_target/src/asm/avr.rs +++ b/compiler/rustc_target/src/asm/avr.rs @@ -1,5 +1,4 @@ use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; -use rustc_macros::HashStable_Generic; use rustc_span::Symbol; use std::fmt; diff --git a/compiler/rustc_target/src/asm/bpf.rs b/compiler/rustc_target/src/asm/bpf.rs index 9bc94274675..faaeabb3c90 100644 --- a/compiler/rustc_target/src/asm/bpf.rs +++ b/compiler/rustc_target/src/asm/bpf.rs @@ -1,5 +1,4 @@ use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; -use rustc_macros::HashStable_Generic; use rustc_span::Symbol; use std::fmt; diff --git a/compiler/rustc_target/src/asm/csky.rs b/compiler/rustc_target/src/asm/csky.rs index 64607ee4b81..db6cdecfe19 100644 --- a/compiler/rustc_target/src/asm/csky.rs +++ b/compiler/rustc_target/src/asm/csky.rs @@ -1,5 +1,4 @@ use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; -use rustc_macros::HashStable_Generic; use rustc_span::Symbol; use std::fmt; diff --git a/compiler/rustc_target/src/asm/hexagon.rs b/compiler/rustc_target/src/asm/hexagon.rs index 19da7b80848..7a809efee6f 100644 --- a/compiler/rustc_target/src/asm/hexagon.rs +++ b/compiler/rustc_target/src/asm/hexagon.rs @@ -1,5 +1,4 @@ use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; -use rustc_macros::HashStable_Generic; use rustc_span::Symbol; use std::fmt; diff --git a/compiler/rustc_target/src/asm/loongarch.rs b/compiler/rustc_target/src/asm/loongarch.rs index 15d0f54ce3b..534b696f7ed 100644 --- a/compiler/rustc_target/src/asm/loongarch.rs +++ b/compiler/rustc_target/src/asm/loongarch.rs @@ -1,5 +1,4 @@ use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; -use rustc_macros::HashStable_Generic; use rustc_span::Symbol; use std::fmt; diff --git a/compiler/rustc_target/src/asm/m68k.rs b/compiler/rustc_target/src/asm/m68k.rs index ac94dcc03dc..ea367e3d2f9 100644 --- a/compiler/rustc_target/src/asm/m68k.rs +++ b/compiler/rustc_target/src/asm/m68k.rs @@ -1,5 +1,4 @@ use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; -use rustc_macros::HashStable_Generic; use rustc_span::Symbol; use std::fmt; diff --git a/compiler/rustc_target/src/asm/mips.rs b/compiler/rustc_target/src/asm/mips.rs index 0ac1a43ae18..f0d659c9b97 100644 --- a/compiler/rustc_target/src/asm/mips.rs +++ b/compiler/rustc_target/src/asm/mips.rs @@ -1,5 +1,4 @@ use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; -use rustc_macros::HashStable_Generic; use rustc_span::Symbol; use std::fmt; diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 49de92b86cb..5f4ce5ed599 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -1,7 +1,7 @@ use crate::spec::Target; use crate::{abi::Size, spec::RelocModel}; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; -use rustc_macros::HashStable_Generic; +use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::Symbol; use std::fmt; use std::str::FromStr; @@ -24,7 +24,7 @@ macro_rules! def_reg_class { $class:ident, )* }) => { - #[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, PartialOrd, Hash, HashStable_Generic)] + #[derive(Copy, Clone, rustc_macros::Encodable, rustc_macros::Decodable, Debug, Eq, PartialEq, PartialOrd, Hash, rustc_macros::HashStable_Generic)] #[allow(non_camel_case_types)] pub enum $arch_regclass { $($class,)* @@ -73,7 +73,7 @@ macro_rules! def_regs { )* }) => { #[allow(unreachable_code)] - #[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, PartialOrd, Hash, HashStable_Generic)] + #[derive(Copy, Clone, rustc_macros::Encodable, rustc_macros::Decodable, Debug, Eq, PartialEq, PartialOrd, Hash, rustc_macros::HashStable_Generic)] #[allow(non_camel_case_types)] pub enum $arch_reg { $($reg,)* diff --git a/compiler/rustc_target/src/asm/msp430.rs b/compiler/rustc_target/src/asm/msp430.rs index 439f3ba0b57..14013cd8a7b 100644 --- a/compiler/rustc_target/src/asm/msp430.rs +++ b/compiler/rustc_target/src/asm/msp430.rs @@ -1,5 +1,4 @@ use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; -use rustc_macros::HashStable_Generic; use rustc_span::Symbol; use std::fmt; diff --git a/compiler/rustc_target/src/asm/nvptx.rs b/compiler/rustc_target/src/asm/nvptx.rs index 57aa50fceb8..6c066ad7ac8 100644 --- a/compiler/rustc_target/src/asm/nvptx.rs +++ b/compiler/rustc_target/src/asm/nvptx.rs @@ -1,5 +1,4 @@ use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; -use rustc_macros::HashStable_Generic; use rustc_span::Symbol; def_reg_class! { diff --git a/compiler/rustc_target/src/asm/powerpc.rs b/compiler/rustc_target/src/asm/powerpc.rs index 4e8cbe34de9..45e9ace0f29 100644 --- a/compiler/rustc_target/src/asm/powerpc.rs +++ b/compiler/rustc_target/src/asm/powerpc.rs @@ -1,5 +1,4 @@ use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; -use rustc_macros::HashStable_Generic; use rustc_span::Symbol; use std::fmt; diff --git a/compiler/rustc_target/src/asm/riscv.rs b/compiler/rustc_target/src/asm/riscv.rs index 2505d36f5b8..3845a0e14af 100644 --- a/compiler/rustc_target/src/asm/riscv.rs +++ b/compiler/rustc_target/src/asm/riscv.rs @@ -1,7 +1,6 @@ use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; use crate::spec::{RelocModel, Target}; use rustc_data_structures::fx::FxIndexSet; -use rustc_macros::HashStable_Generic; use rustc_span::{sym, Symbol}; use std::fmt; diff --git a/compiler/rustc_target/src/asm/s390x.rs b/compiler/rustc_target/src/asm/s390x.rs index 6bc668454b1..2bab41cd8a1 100644 --- a/compiler/rustc_target/src/asm/s390x.rs +++ b/compiler/rustc_target/src/asm/s390x.rs @@ -1,5 +1,4 @@ use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; -use rustc_macros::HashStable_Generic; use rustc_span::Symbol; use std::fmt; diff --git a/compiler/rustc_target/src/asm/spirv.rs b/compiler/rustc_target/src/asm/spirv.rs index d13a6131f9a..f242faec026 100644 --- a/compiler/rustc_target/src/asm/spirv.rs +++ b/compiler/rustc_target/src/asm/spirv.rs @@ -1,5 +1,4 @@ use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; -use rustc_macros::HashStable_Generic; use rustc_span::Symbol; def_reg_class! { diff --git a/compiler/rustc_target/src/asm/wasm.rs b/compiler/rustc_target/src/asm/wasm.rs index eb0b23ef43d..b5f4d10fb2b 100644 --- a/compiler/rustc_target/src/asm/wasm.rs +++ b/compiler/rustc_target/src/asm/wasm.rs @@ -1,5 +1,4 @@ use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; -use rustc_macros::HashStable_Generic; use rustc_span::Symbol; def_reg_class! { diff --git a/compiler/rustc_target/src/asm/x86.rs b/compiler/rustc_target/src/asm/x86.rs index 3b5da8806cc..28413a5bcbd 100644 --- a/compiler/rustc_target/src/asm/x86.rs +++ b/compiler/rustc_target/src/asm/x86.rs @@ -1,7 +1,6 @@ use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; use crate::spec::{RelocModel, Target}; use rustc_data_structures::fx::FxIndexSet; -use rustc_macros::HashStable_Generic; use rustc_span::Symbol; use std::fmt; diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index ba359ac6de1..84d7930663a 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -20,12 +20,6 @@ use std::path::{Path, PathBuf}; -#[macro_use] -extern crate rustc_macros; - -#[macro_use] -extern crate tracing; - pub mod abi; pub mod asm; pub mod json; diff --git a/compiler/rustc_target/src/spec/abi/mod.rs b/compiler/rustc_target/src/spec/abi/mod.rs index 388e76d83e2..bf51bb4bf82 100644 --- a/compiler/rustc_target/src/spec/abi/mod.rs +++ b/compiler/rustc_target/src/spec/abi/mod.rs @@ -1,6 +1,6 @@ use std::fmt; -use rustc_macros::HashStable_Generic; +use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol}; diff --git a/compiler/rustc_target/src/spec/base/fuchsia.rs b/compiler/rustc_target/src/spec/base/fuchsia.rs index 4c2775850d1..d1ac22f3a09 100644 --- a/compiler/rustc_target/src/spec/base/fuchsia.rs +++ b/compiler/rustc_target/src/spec/base/fuchsia.rs @@ -1,4 +1,6 @@ -use crate::spec::{crt_objects, cvs, Cc, LinkOutputKind, LinkerFlavor, Lld, TargetOptions}; +use crate::spec::{ + crt_objects, cvs, Cc, FramePointer, LinkOutputKind, LinkerFlavor, Lld, TargetOptions, +}; pub fn opts() -> TargetOptions { // This mirrors the linker options provided by clang. We presume lld for @@ -38,6 +40,7 @@ pub fn opts() -> TargetOptions { ]), position_independent_executables: true, has_thread_local: true, + frame_pointer: FramePointer::NonLeaf, ..Default::default() } } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 291a761913b..cbb248a0fc2 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -40,6 +40,7 @@ use crate::json::{Json, ToJson}; use crate::spec::abi::Abi; use crate::spec::crt_objects::CrtObjects; use rustc_fs_util::try_canonicalize; +use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_span::symbol::{kw, sym, Symbol}; use serde_json::Value; @@ -50,8 +51,7 @@ use std::ops::{Deref, DerefMut}; use std::path::{Path, PathBuf}; use std::str::FromStr; use std::{fmt, io}; - -use rustc_macros::HashStable_Generic; +use tracing::debug; pub mod abi; pub mod crt_objects; @@ -778,6 +778,14 @@ pub enum PanicStrategy { Abort, } +#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)] +pub enum OnBrokenPipe { + Default, + Kill, + Error, + Inherit, +} + impl PanicStrategy { pub fn desc(&self) -> &str { match *self { diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 9b08a86ef16..7228a9ba016 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -3,7 +3,7 @@ use rustc_errors::{ codes::*, Applicability, Diag, DiagCtxt, Diagnostic, EmissionGuarantee, Level, SubdiagMessageOp, Subdiagnostic, }; -use rustc_macros::Diagnostic; +use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::ty::{self, ClosureKind, PolyTraitRef, Ty}; use rustc_span::{Span, Symbol}; diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 0595e82b39e..3dc55509dad 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -1,10 +1,10 @@ use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use crate::traits::{self, ObligationCtxt, SelectionContext}; -use crate::traits::TraitEngineExt as _; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; -use rustc_infer::traits::{Obligation, TraitEngine, TraitEngineExt as _}; +use rustc_infer::traits::Obligation; +use rustc_macros::extension; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::infer::canonical::{Canonical, CanonicalQueryResponse, QueryResponse}; use rustc_middle::traits::query::NoSolution; @@ -94,9 +94,9 @@ impl<'tcx> InferCtxt<'tcx> { ty::TraitRef::new(self.tcx, trait_def_id, [ty]), )) { Ok(Some(selection)) => { - let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(self); - fulfill_cx.register_predicate_obligations(self, selection.nested_obligations()); - Some(fulfill_cx.select_all_or_error(self)) + let ocx = ObligationCtxt::new(self); + ocx.register_obligations(selection.nested_obligations()); + Some(ocx.select_all_or_error()) } Ok(None) | Err(_) => None, } diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index d54f714b22c..f1f03b810a9 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -17,7 +17,6 @@ #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] #![feature(assert_matches)] -#![cfg_attr(bootstrap, feature(associated_type_bounds))] #![feature(associated_type_defaults)] #![feature(box_patterns)] #![feature(control_flow_enum)] @@ -30,16 +29,9 @@ #![recursion_limit = "512"] // For rustdoc #[macro_use] -extern crate rustc_macros; -#[cfg(target_pointer_width = "64")] -#[macro_use] -extern crate rustc_data_structures; -#[macro_use] extern crate tracing; #[macro_use] extern crate rustc_middle; -#[macro_use] -extern crate smallvec; pub mod errors; pub mod infer; diff --git a/compiler/rustc_trait_selection/src/regions.rs b/compiler/rustc_trait_selection/src/regions.rs index 222d0b4d5e7..5e0d7da4f06 100644 --- a/compiler/rustc_trait_selection/src/regions.rs +++ b/compiler/rustc_trait_selection/src/regions.rs @@ -1,5 +1,6 @@ use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{InferCtxt, RegionResolutionError}; +use rustc_macros::extension; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::ObligationCause; diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 95221529093..f2ca42a0be9 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -2,7 +2,6 @@ use crate::solve::GoalSource; use crate::solve::{inspect, EvalCtxt, SolverMode}; -use crate::traits::coherence; use rustc_hir::def_id::DefId; use rustc_infer::traits::query::NoSolution; use rustc_middle::traits::solve::inspect::ProbeKind; @@ -48,24 +47,26 @@ pub(super) trait GoalKind<'tcx>: /// [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]). fn probe_and_match_goal_against_assumption( ecx: &mut EvalCtxt<'_, 'tcx>, + source: CandidateSource, goal: Goal<'tcx, Self>, assumption: ty::Clause<'tcx>, then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>, - ) -> QueryResult<'tcx>; + ) -> Result<Candidate<'tcx>, NoSolution>; /// Consider a clause, which consists of a "assumption" and some "requirements", /// to satisfy a goal. If the requirements hold, then attempt to satisfy our /// goal by equating it with the assumption. - fn consider_implied_clause( + fn probe_and_consider_implied_clause( ecx: &mut EvalCtxt<'_, 'tcx>, + parent_source: CandidateSource, goal: Goal<'tcx, Self>, assumption: ty::Clause<'tcx>, - requirements: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>, - ) -> QueryResult<'tcx> { - Self::probe_and_match_goal_against_assumption(ecx, goal, assumption, |ecx| { - // FIXME(-Znext-solver=coinductive): check whether this should be - // `GoalSource::ImplWhereBound` for any caller. - ecx.add_goals(GoalSource::Misc, requirements); + requirements: impl IntoIterator<Item = (GoalSource, Goal<'tcx, ty::Predicate<'tcx>>)>, + ) -> Result<Candidate<'tcx>, NoSolution> { + Self::probe_and_match_goal_against_assumption(ecx, parent_source, goal, assumption, |ecx| { + for (nested_source, goal) in requirements { + ecx.add_goal(nested_source, goal); + } ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } @@ -73,19 +74,19 @@ pub(super) trait GoalKind<'tcx>: /// Consider a clause specifically for a `dyn Trait` self type. This requires /// additionally checking all of the supertraits and object bounds to hold, /// since they're not implied by the well-formedness of the object type. - fn consider_object_bound_candidate( + fn probe_and_consider_object_bound_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, + source: CandidateSource, goal: Goal<'tcx, Self>, assumption: ty::Clause<'tcx>, - ) -> QueryResult<'tcx> { - Self::probe_and_match_goal_against_assumption(ecx, goal, assumption, |ecx| { + ) -> Result<Candidate<'tcx>, NoSolution> { + Self::probe_and_match_goal_against_assumption(ecx, source, goal, assumption, |ecx| { let tcx = ecx.tcx(); let ty::Dynamic(bounds, _, _) = *goal.predicate.self_ty().kind() else { - bug!("expected object type in `consider_object_bound_candidate`"); + bug!("expected object type in `probe_and_consider_object_bound_candidate`"); }; - // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`? ecx.add_goals( - GoalSource::Misc, + GoalSource::ImplWhereBound, structural_traits::predicates_for_object_candidate( ecx, goal.param_env, @@ -112,7 +113,7 @@ pub(super) trait GoalKind<'tcx>: fn consider_error_guaranteed_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, guar: ErrorGuaranteed, - ) -> QueryResult<'tcx>; + ) -> Result<Candidate<'tcx>, NoSolution>; /// A type implements an `auto trait` if its components do as well. /// @@ -121,13 +122,13 @@ pub(super) trait GoalKind<'tcx>: fn consider_auto_trait_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx>; + ) -> Result<Candidate<'tcx>, NoSolution>; /// A trait alias holds if the RHS traits and `where` clauses hold. fn consider_trait_alias_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx>; + ) -> Result<Candidate<'tcx>, NoSolution>; /// A type is `Sized` if its tail component is `Sized`. /// @@ -136,7 +137,7 @@ pub(super) trait GoalKind<'tcx>: fn consider_builtin_sized_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx>; + ) -> Result<Candidate<'tcx>, NoSolution>; /// A type is `Copy` or `Clone` if its components are `Copy` or `Clone`. /// @@ -145,20 +146,20 @@ pub(super) trait GoalKind<'tcx>: fn consider_builtin_copy_clone_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx>; + ) -> Result<Candidate<'tcx>, NoSolution>; /// A type is `PointerLike` if we can compute its layout, and that layout /// matches the layout of `usize`. fn consider_builtin_pointer_like_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx>; + ) -> Result<Candidate<'tcx>, NoSolution>; /// A type is a `FnPtr` if it is of `FnPtr` type. fn consider_builtin_fn_ptr_trait_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx>; + ) -> Result<Candidate<'tcx>, NoSolution>; /// A callable type (a closure, fn def, or fn ptr) is known to implement the `Fn<A>` /// family of traits where `A` is given by the signature of the type. @@ -166,7 +167,7 @@ pub(super) trait GoalKind<'tcx>: ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, kind: ty::ClosureKind, - ) -> QueryResult<'tcx>; + ) -> Result<Candidate<'tcx>, NoSolution>; /// An async closure is known to implement the `AsyncFn<A>` family of traits /// where `A` is given by the signature of the type. @@ -174,7 +175,7 @@ pub(super) trait GoalKind<'tcx>: ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, kind: ty::ClosureKind, - ) -> QueryResult<'tcx>; + ) -> Result<Candidate<'tcx>, NoSolution>; /// Compute the built-in logic of the `AsyncFnKindHelper` helper trait, which /// is used internally to delay computation for async closures until after @@ -182,13 +183,13 @@ pub(super) trait GoalKind<'tcx>: fn consider_builtin_async_fn_kind_helper_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx>; + ) -> Result<Candidate<'tcx>, NoSolution>; /// `Tuple` is implemented if the `Self` type is a tuple. fn consider_builtin_tuple_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx>; + ) -> Result<Candidate<'tcx>, NoSolution>; /// `Pointee` is always implemented. /// @@ -198,7 +199,7 @@ pub(super) trait GoalKind<'tcx>: fn consider_builtin_pointee_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx>; + ) -> Result<Candidate<'tcx>, NoSolution>; /// A coroutine (that comes from an `async` desugaring) is known to implement /// `Future<Output = O>`, where `O` is given by the coroutine's return type @@ -206,7 +207,7 @@ pub(super) trait GoalKind<'tcx>: fn consider_builtin_future_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx>; + ) -> Result<Candidate<'tcx>, NoSolution>; /// A coroutine (that comes from a `gen` desugaring) is known to implement /// `Iterator<Item = O>`, where `O` is given by the generator's yield type @@ -214,19 +215,19 @@ pub(super) trait GoalKind<'tcx>: fn consider_builtin_iterator_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx>; + ) -> Result<Candidate<'tcx>, NoSolution>; /// A coroutine (that comes from a `gen` desugaring) is known to implement /// `FusedIterator` fn consider_builtin_fused_iterator_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx>; + ) -> Result<Candidate<'tcx>, NoSolution>; fn consider_builtin_async_iterator_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx>; + ) -> Result<Candidate<'tcx>, NoSolution>; /// A coroutine (that doesn't come from an `async` or `gen` desugaring) is known to /// implement `Coroutine<R, Yield = Y, Return = O>`, given the resume, yield, @@ -234,27 +235,27 @@ pub(super) trait GoalKind<'tcx>: fn consider_builtin_coroutine_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx>; + ) -> Result<Candidate<'tcx>, NoSolution>; fn consider_builtin_discriminant_kind_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx>; + ) -> Result<Candidate<'tcx>, NoSolution>; fn consider_builtin_async_destruct_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx>; + ) -> Result<Candidate<'tcx>, NoSolution>; fn consider_builtin_destruct_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx>; + ) -> Result<Candidate<'tcx>, NoSolution>; fn consider_builtin_transmute_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx>; + ) -> Result<Candidate<'tcx>, NoSolution>; /// Consider (possibly several) candidates to upcast or unsize a type to another /// type, excluding the coercion of a sized type into a `dyn Trait`. @@ -266,7 +267,7 @@ pub(super) trait GoalKind<'tcx>: fn consider_structural_builtin_unsize_candidates( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> Vec<(CanonicalResponse<'tcx>, BuiltinImplSource)>; + ) -> Vec<Candidate<'tcx>>; } impl<'tcx> EvalCtxt<'_, 'tcx> { @@ -282,7 +283,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { if normalized_self_ty.is_ty_var() { debug!("self type has been normalized to infer"); - return self.forced_ambiguity(MaybeCause::Ambiguity); + return self.forced_ambiguity(MaybeCause::Ambiguity).into_iter().collect(); } let goal = @@ -315,7 +316,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { candidates } - fn forced_ambiguity(&mut self, cause: MaybeCause) -> Vec<Candidate<'tcx>> { + pub(super) fn forced_ambiguity( + &mut self, + cause: MaybeCause, + ) -> Result<Candidate<'tcx>, NoSolution> { // This may fail if `try_evaluate_added_goals` overflows because it // fails to reach a fixpoint but ends up getting an error after // running for some additional step. @@ -323,10 +327,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { // cc trait-system-refactor-initiative#105 let source = CandidateSource::BuiltinImpl(BuiltinImplSource::Misc); let certainty = Certainty::Maybe(cause); - let result = self - .probe_trait_candidate(source) - .enter(|this| this.evaluate_added_goals_and_make_canonical_response(certainty)); - if let Ok(cand) = result { vec![cand] } else { vec![] } + self.probe_trait_candidate(source) + .enter(|this| this.evaluate_added_goals_and_make_canonical_response(certainty)) } #[instrument(level = "debug", skip_all)] @@ -533,20 +535,12 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { Err(NoSolution) }; - match result { - Ok(result) => candidates.push(Candidate { - source: CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), - result, - }), - Err(NoSolution) => (), - } + candidates.extend(result); // There may be multiple unsize candidates for a trait with several supertraits: // `trait Foo: Bar<A> + Bar<B>` and `dyn Foo: Unsize<dyn Bar<_>>` if lang_items.unsize_trait() == Some(trait_def_id) { - for (result, source) in G::consider_structural_builtin_unsize_candidates(self, goal) { - candidates.push(Candidate { source: CandidateSource::BuiltinImpl(source), result }); - } + candidates.extend(G::consider_structural_builtin_unsize_candidates(self, goal)); } } @@ -557,12 +551,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { candidates: &mut Vec<Candidate<'tcx>>, ) { for (i, assumption) in goal.param_env.caller_bounds().iter().enumerate() { - match G::consider_implied_clause(self, goal, assumption, []) { - Ok(result) => { - candidates.push(Candidate { source: CandidateSource::ParamEnv(i), result }) - } - Err(NoSolution) => (), - } + candidates.extend(G::probe_and_consider_implied_clause( + self, + CandidateSource::ParamEnv(i), + goal, + assumption, + [], + )); } } @@ -648,12 +643,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { for assumption in self.tcx().item_bounds(alias_ty.def_id).instantiate(self.tcx(), alias_ty.args) { - match G::consider_implied_clause(self, goal, assumption, []) { - Ok(result) => { - candidates.push(Candidate { source: CandidateSource::AliasBound, result }); - } - Err(NoSolution) => {} - } + candidates.extend(G::probe_and_consider_implied_clause( + self, + CandidateSource::AliasBound, + goal, + assumption, + [], + )); } if kind != ty::Projection { @@ -728,17 +724,12 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } ty::ExistentialPredicate::Projection(_) | ty::ExistentialPredicate::AutoTrait(_) => { - match G::consider_object_bound_candidate( + candidates.extend(G::probe_and_consider_object_bound_candidate( self, + CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, bound.with_self_ty(tcx, self_ty), - ) { - Ok(result) => candidates.push(Candidate { - source: CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), - result, - }), - Err(NoSolution) => (), - } + )); } } } @@ -749,15 +740,12 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { if let Some(principal) = bounds.principal() { let principal_trait_ref = principal.with_self_ty(tcx, self_ty); self.walk_vtable(principal_trait_ref, |ecx, assumption, vtable_base, _| { - match G::consider_object_bound_candidate(ecx, goal, assumption.to_predicate(tcx)) { - Ok(result) => candidates.push(Candidate { - source: CandidateSource::BuiltinImpl(BuiltinImplSource::Object { - vtable_base, - }), - result, - }), - Err(NoSolution) => (), - } + candidates.extend(G::probe_and_consider_object_bound_candidate( + ecx, + CandidateSource::BuiltinImpl(BuiltinImplSource::Object { vtable_base }), + goal, + assumption.to_predicate(tcx), + )); }); } } @@ -775,25 +763,17 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { candidates: &mut Vec<Candidate<'tcx>>, ) { let tcx = self.tcx(); - let result = self.probe_misc_candidate("coherence unknowable").enter(|ecx| { - let trait_ref = goal.predicate.trait_ref(tcx); - let lazily_normalize_ty = |ty| ecx.structurally_normalize_ty(goal.param_env, ty); - match coherence::trait_ref_is_knowable(tcx, trait_ref, lazily_normalize_ty)? { - Ok(()) => Err(NoSolution), - Err(_) => { + candidates.extend(self.probe_trait_candidate(CandidateSource::CoherenceUnknowable).enter( + |ecx| { + let trait_ref = goal.predicate.trait_ref(tcx); + if ecx.trait_ref_is_knowable(goal.param_env, trait_ref)? { + Err(NoSolution) + } else { ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) } - } - }); - - match result { - Ok(result) => candidates.push(Candidate { - source: CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), - result, - }), - Err(NoSolution) => {} - } + }, + )) } /// If there's a where-bound for the current goal, do not use any impl candidates @@ -838,6 +818,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { false } CandidateSource::ParamEnv(_) | CandidateSource::AliasBound => true, + CandidateSource::CoherenceUnknowable => bug!("uh oh"), }); } // If it is still ambiguous we instead just force the whole goal @@ -845,7 +826,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { // tests/ui/traits/next-solver/env-shadows-impls/ambig-env-no-shadow.rs Certainty::Maybe(cause) => { debug!(?cause, "force ambiguity"); - *candidates = self.forced_ambiguity(cause); + *candidates = self.forced_ambiguity(cause).into_iter().collect(); } } } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index a778414d9d1..a8b1a182d3c 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -4,6 +4,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::LangItem; use rustc_hir::{def_id::DefId, Movability, Mutability}; use rustc_infer::traits::query::NoSolution; +use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::traits::solve::Goal; use rustc_middle::ty::{ self, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index 9edeb0fa71b..d6bf2b596ef 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -90,6 +90,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { &mut self, certainty: Certainty, ) -> QueryResult<'tcx> { + self.inspect.make_canonical_response(certainty); + let goals_certainty = self.try_evaluate_added_goals()?; assert_eq!( self.tainted, diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 21efce74879..bae1c6b6011 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -9,6 +9,7 @@ use rustc_infer::infer::{ use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::solve::{MaybeCause, NestedNormalizationGoals}; use rustc_infer::traits::ObligationCause; +use rustc_macros::{extension, HashStable}; use rustc_middle::infer::canonical::CanonicalVarInfos; use rustc_middle::infer::unify_key::ConstVariableOrigin; use rustc_middle::traits::solve::inspect; @@ -26,6 +27,7 @@ use rustc_span::DUMMY_SP; use std::io::Write; use std::ops::ControlFlow; +use crate::traits::coherence; use crate::traits::vtable::{count_own_vtable_entries, prepare_vtable_segments, VtblSegment}; use super::inspect::ProofTreeBuilder; @@ -452,7 +454,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { } else { self.infcx.enter_forall(kind, |kind| { let goal = goal.with(self.tcx(), ty::Binder::dummy(kind)); - self.add_goal(GoalSource::Misc, goal); + self.add_goal(GoalSource::InstantiateHigherRanked, goal); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } @@ -941,6 +943,17 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } + pub(super) fn trait_ref_is_knowable( + &mut self, + param_env: ty::ParamEnv<'tcx>, + trait_ref: ty::TraitRef<'tcx>, + ) -> Result<bool, NoSolution> { + let infcx = self.infcx; + let lazily_normalize_ty = |ty| self.structurally_normalize_ty(param_env, ty); + coherence::trait_ref_is_knowable(infcx, trait_ref, lazily_normalize_ty) + .map(|is_knowable| is_knowable.is_ok()) + } + pub(super) fn can_define_opaque_ty(&self, def_id: impl Into<DefId>) -> bool { self.infcx.can_define_opaque_ty(def_id) } @@ -998,19 +1011,24 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { if candidate_key.def_id != key.def_id { continue; } - values.extend(self.probe_misc_candidate("opaque type storage").enter(|ecx| { - for (a, b) in std::iter::zip(candidate_key.args, key.args) { - ecx.eq(param_env, a, b)?; - } - ecx.eq(param_env, candidate_ty, ty)?; - ecx.add_item_bounds_for_hidden_type( - candidate_key.def_id.to_def_id(), - candidate_key.args, - param_env, - candidate_ty, - ); - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - })); + values.extend( + self.probe(|result| inspect::ProbeKind::OpaqueTypeStorageLookup { + result: *result, + }) + .enter(|ecx| { + for (a, b) in std::iter::zip(candidate_key.args, key.args) { + ecx.eq(param_env, a, b)?; + } + ecx.eq(param_env, candidate_ty, ty)?; + ecx.add_item_bounds_for_hidden_type( + candidate_key.def_id.to_def_id(), + candidate_key.args, + param_env, + candidate_ty, + ); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }), + ); } values } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs index 9d59723e441..ee23f49939b 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs @@ -1,6 +1,7 @@ use crate::solve::assembly::Candidate; use super::EvalCtxt; +use rustc_infer::traits::BuiltinImplSource; use rustc_middle::traits::{ query::NoSolution, solve::{inspect, CandidateSource, QueryResult}, @@ -75,24 +76,12 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { ProbeCtxt { ecx: self, probe_kind, _result: PhantomData } } - pub(in crate::solve) fn probe_misc_candidate( + pub(in crate::solve) fn probe_builtin_trait_candidate( &mut self, - name: &'static str, - ) -> ProbeCtxt< - '_, - 'a, - 'tcx, - impl FnOnce(&QueryResult<'tcx>) -> inspect::ProbeKind<'tcx>, - QueryResult<'tcx>, - > { - ProbeCtxt { - ecx: self, - probe_kind: move |result: &QueryResult<'tcx>| inspect::ProbeKind::MiscCandidate { - name, - result: *result, - }, - _result: PhantomData, - } + source: BuiltinImplSource, + ) -> TraitProbeCtxt<'_, 'a, 'tcx, impl FnOnce(&QueryResult<'tcx>) -> inspect::ProbeKind<'tcx>> + { + self.probe_trait_candidate(CandidateSource::BuiltinImpl(source)) } pub(in crate::solve) fn probe_trait_candidate( diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs index 6644d3c77af..16fe045b82d 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs @@ -1,21 +1,17 @@ -use rustc_hir as hir; +use std::ops::ControlFlow; + use rustc_hir::def_id::DefId; -use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt}; +use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; +use rustc_infer::traits::solve::inspect::ProbeKind; +use rustc_infer::traits::solve::{CandidateSource, Certainty, Goal}; use rustc_infer::traits::{ - Obligation, PolyTraitObligation, PredicateObligation, Selection, SelectionResult, TraitEngine, -}; -use rustc_middle::traits::solve::{CandidateSource, CanonicalInput, Certainty, Goal}; -use rustc_middle::traits::{ - BuiltinImplSource, ImplSource, ImplSourceUserDefinedData, ObligationCause, SelectionError, + BuiltinImplSource, ImplSource, ImplSourceUserDefinedData, Obligation, ObligationCause, + PolyTraitObligation, PredicateObligation, Selection, SelectionError, SelectionResult, }; -use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::DUMMY_SP; +use rustc_macros::extension; +use rustc_span::Span; -use crate::solve::assembly::Candidate; -use crate::solve::eval_ctxt::{EvalCtxt, GenerateProofTree}; -use crate::solve::inspect::ProofTreeBuilder; -use crate::traits::StructurallyNormalizeExt; -use crate::traits::TraitEngineExt; +use crate::solve::inspect::{self, ProofTreeInferCtxtExt}; #[extension(pub trait InferCtxtSelectExt<'tcx>)] impl<'tcx> InferCtxt<'tcx> { @@ -25,357 +21,192 @@ impl<'tcx> InferCtxt<'tcx> { ) -> SelectionResult<'tcx, Selection<'tcx>> { assert!(self.next_trait_solver()); - self.enter_forall(obligation.predicate, |pred| { - let trait_goal = Goal::new(self.tcx, obligation.param_env, pred); - - let (result, _) = EvalCtxt::enter_root(self, GenerateProofTree::Never, |ecx| { - let goal = Goal::new(ecx.tcx(), trait_goal.param_env, trait_goal.predicate); - let (orig_values, canonical_goal) = ecx.canonicalize_goal(goal); - let mut candidates = ecx.compute_canonical_trait_candidates(canonical_goal); + self.visit_proof_tree( + Goal::new(self.tcx, obligation.param_env, obligation.predicate), + &mut Select { span: obligation.cause.span }, + ) + .break_value() + .unwrap() + } +} - // pseudo-winnow - if candidates.len() == 0 { - return Err(SelectionError::Unimplemented); - } else if candidates.len() > 1 { - let mut i = 0; - while i < candidates.len() { - let should_drop_i = (0..candidates.len()).filter(|&j| i != j).any(|j| { - candidate_should_be_dropped_in_favor_of( - ecx.tcx(), - &candidates[i], - &candidates[j], - ) - }); - if should_drop_i { - candidates.swap_remove(i); - } else { - i += 1; - if i > 1 { - return Ok(None); - } - } - } - } +struct Select { + span: Span, +} - let candidate = candidates.pop().unwrap(); - let (normalization_nested_goals, certainty) = ecx - .instantiate_and_apply_query_response( - trait_goal.param_env, - orig_values, - candidate.result, - ); - assert!(normalization_nested_goals.is_empty()); - Ok(Some((candidate, certainty))) - }); +impl<'tcx> inspect::ProofTreeVisitor<'tcx> for Select { + type Result = ControlFlow<SelectionResult<'tcx, Selection<'tcx>>>; - let (candidate, certainty) = match result { - Ok(Some(result)) => result, - Ok(None) => return Ok(None), - Err(e) => return Err(e), - }; + fn span(&self) -> Span { + self.span + } - let goal = self.resolve_vars_if_possible(trait_goal); - match (certainty, candidate.source) { - // Rematching the implementation will instantiate the same nested goals that - // would have caused the ambiguity, so we can still make progress here regardless. - (_, CandidateSource::Impl(def_id)) => rematch_impl(self, goal, def_id), + fn visit_goal(&mut self, goal: &inspect::InspectGoal<'_, 'tcx>) -> Self::Result { + let mut candidates = goal.candidates(); + candidates.retain(|cand| cand.result().is_ok()); - // If an unsize goal is ambiguous, then we can manually rematch it to make - // selection progress for coercion during HIR typeck. If it is *not* ambiguous, - // but is `BuiltinImplSource::Misc`, it may have nested `Unsize` goals, - // and we need to rematch those to detect tuple unsizing and trait upcasting. - // FIXME: This will be wrong if we have param-env or where-clause bounds - // with the unsize goal -- we may need to mark those with different impl - // sources. - (Certainty::Maybe(_), CandidateSource::BuiltinImpl(src)) - | (Certainty::Yes, CandidateSource::BuiltinImpl(src @ BuiltinImplSource::Misc)) - if self.tcx.lang_items().unsize_trait() == Some(goal.predicate.def_id()) => - { - rematch_unsize(self, goal, src, certainty) - } + // No candidates -- not implemented. + if candidates.is_empty() { + return ControlFlow::Break(Err(SelectionError::Unimplemented)); + } - // Technically some builtin impls have nested obligations, but if - // `Certainty::Yes`, then they should've all been verified and don't - // need re-checking. - (Certainty::Yes, CandidateSource::BuiltinImpl(src)) => { - Ok(Some(ImplSource::Builtin(src, vec![]))) - } + // One candidate, no need to winnow. + if candidates.len() == 1 { + return ControlFlow::Break(Ok(to_selection( + self.span, + candidates.into_iter().next().unwrap(), + ))); + } - // It's fine not to do anything to rematch these, since there are no - // nested obligations. - (Certainty::Yes, CandidateSource::ParamEnv(_) | CandidateSource::AliasBound) => { - Ok(Some(ImplSource::Param(vec![]))) + // We need to winnow. See comments on `candidate_should_be_dropped_in_favor_of`. + let mut i = 0; + while i < candidates.len() { + let should_drop_i = (0..candidates.len()) + .filter(|&j| i != j) + .any(|j| candidate_should_be_dropped_in_favor_of(&candidates[i], &candidates[j])); + if should_drop_i { + candidates.swap_remove(i); + } else { + i += 1; + if i > 1 { + return ControlFlow::Break(Ok(None)); } - - (Certainty::Maybe(_), _) => Ok(None), } - }) - } -} + } -impl<'tcx> EvalCtxt<'_, 'tcx> { - fn compute_canonical_trait_candidates( - &mut self, - canonical_input: CanonicalInput<'tcx>, - ) -> Vec<Candidate<'tcx>> { - // This doesn't record the canonical goal on the stack during the - // candidate assembly step, but that's fine. Selection is conceptually - // outside of the solver, and if there were any cycles, we'd encounter - // the cycle anyways one step later. - EvalCtxt::enter_canonical( - self.tcx(), - self.search_graph, - canonical_input, - // FIXME: This is wrong, idk if we even want to track stuff here. - &mut ProofTreeBuilder::new_noop(), - |ecx, goal| { - let trait_goal = Goal { - param_env: goal.param_env, - predicate: goal - .predicate - .to_opt_poly_trait_pred() - .expect("we canonicalized a trait goal") - .no_bound_vars() - .expect("we instantiated all bound vars"), - }; - ecx.assemble_and_evaluate_candidates(trait_goal) - }, - ) + ControlFlow::Break(Ok(to_selection(self.span, candidates.into_iter().next().unwrap()))) } } +/// This is a lot more limited than the old solver's equivalent method. This may lead to more `Ok(None)` +/// results when selecting traits in polymorphic contexts, but we should never rely on the lack of ambiguity, +/// and should always just gracefully fail here. We shouldn't rely on this incompleteness. fn candidate_should_be_dropped_in_favor_of<'tcx>( - tcx: TyCtxt<'tcx>, - victim: &Candidate<'tcx>, - other: &Candidate<'tcx>, + victim: &inspect::InspectCandidate<'_, 'tcx>, + other: &inspect::InspectCandidate<'_, 'tcx>, ) -> bool { - match (victim.source, other.source) { - (CandidateSource::ParamEnv(victim_idx), CandidateSource::ParamEnv(other_idx)) => { - victim_idx >= other_idx + // Don't winnow until `Certainty::Yes` -- we don't need to winnow until + // codegen, technically. + if matches!(other.result().unwrap(), Certainty::Maybe(..)) { + return false; + } + + let inspect::ProbeKind::TraitCandidate { source: victim_source, result: _ } = victim.kind() + else { + return false; + }; + let inspect::ProbeKind::TraitCandidate { source: other_source, result: _ } = other.kind() + else { + return false; + }; + + match (victim_source, other_source) { + (_, CandidateSource::CoherenceUnknowable) | (CandidateSource::CoherenceUnknowable, _) => { + bug!("should not have assembled a CoherenceUnknowable candidate") } - (_, CandidateSource::ParamEnv(_)) => true, - // FIXME: we could prefer earlier vtable bases perhaps... + // Prefer dyn candidates over non-dyn candidates. This is necessary to + // handle the unsoundness between `impl<T: ?Sized> Any for T` and `dyn Any: Any`. ( CandidateSource::BuiltinImpl(BuiltinImplSource::Object { .. }), CandidateSource::BuiltinImpl(BuiltinImplSource::Object { .. }), ) => false, - (_, CandidateSource::BuiltinImpl(BuiltinImplSource::Object { .. })) => true, + ( + CandidateSource::Impl(_) | CandidateSource::ParamEnv(_) | CandidateSource::AliasBound, + CandidateSource::BuiltinImpl(BuiltinImplSource::Object { .. }), + ) => true, + // Prefer specializing candidates over specialized candidates. (CandidateSource::Impl(victim_def_id), CandidateSource::Impl(other_def_id)) => { - tcx.specializes((other_def_id, victim_def_id)) - && other.result.value.certainty == Certainty::Yes + victim.goal().infcx().tcx.specializes((other_def_id, victim_def_id)) } _ => false, } } +fn to_selection<'tcx>( + span: Span, + cand: inspect::InspectCandidate<'_, 'tcx>, +) -> Option<Selection<'tcx>> { + if let Certainty::Maybe(..) = cand.shallow_certainty() { + return None; + } + + let make_nested = || { + cand.instantiate_nested_goals(span) + .into_iter() + .map(|nested| { + Obligation::new( + nested.infcx().tcx, + ObligationCause::dummy_with_span(span), + nested.goal().param_env, + nested.goal().predicate, + ) + }) + .collect() + }; + + Some(match cand.kind() { + ProbeKind::TraitCandidate { source, result: _ } => match source { + CandidateSource::Impl(impl_def_id) => { + // FIXME: Remove this in favor of storing this in the tree + // For impl candidates, we do the rematch manually to compute the args. + ImplSource::UserDefined(rematch_impl(cand.goal(), impl_def_id, span)) + } + CandidateSource::BuiltinImpl(builtin) => ImplSource::Builtin(builtin, make_nested()), + CandidateSource::ParamEnv(_) => ImplSource::Param(make_nested()), + CandidateSource::AliasBound => { + ImplSource::Builtin(BuiltinImplSource::Misc, make_nested()) + } + CandidateSource::CoherenceUnknowable => { + span_bug!(span, "didn't expect to select an unknowable candidate") + } + }, + ProbeKind::TryNormalizeNonRigid { result: _ } + | ProbeKind::NormalizedSelfTyAssembly + | ProbeKind::UnsizeAssembly + | ProbeKind::UpcastProjectionCompatibility + | ProbeKind::OpaqueTypeStorageLookup { result: _ } + | ProbeKind::Root { result: _ } => { + span_bug!(span, "didn't expect to assemble trait candidate from {:#?}", cand.kind()) + } + }) +} + fn rematch_impl<'tcx>( - infcx: &InferCtxt<'tcx>, - goal: Goal<'tcx, ty::TraitPredicate<'tcx>>, + goal: &inspect::InspectGoal<'_, 'tcx>, impl_def_id: DefId, -) -> SelectionResult<'tcx, Selection<'tcx>> { - let args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id); + span: Span, +) -> ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>> { + let infcx = goal.infcx(); + let goal_trait_ref = infcx + .enter_forall_and_leak_universe(goal.goal().predicate.to_opt_poly_trait_pred().unwrap()) + .trait_ref; + + let args = infcx.fresh_args_for_item(span, impl_def_id); let impl_trait_ref = infcx.tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(infcx.tcx, args); - let mut nested = infcx - .at(&ObligationCause::dummy(), goal.param_env) - // New solver ignores DefineOpaqueTypes, so choose Yes for consistency - .eq(DefineOpaqueTypes::Yes, goal.predicate.trait_ref, impl_trait_ref) - .map_err(|_| SelectionError::Unimplemented)? - .into_obligations(); + let InferOk { value: (), obligations: mut nested } = infcx + .at(&ObligationCause::dummy_with_span(span), goal.goal().param_env) + .eq(DefineOpaqueTypes::Yes, goal_trait_ref, impl_trait_ref) + .expect("rematching impl failed"); + + // FIXME(-Znext-solver=coinductive): We need to add supertraits here eventually. nested.extend( infcx.tcx.predicates_of(impl_def_id).instantiate(infcx.tcx, args).into_iter().map( - |(pred, _)| Obligation::new(infcx.tcx, ObligationCause::dummy(), goal.param_env, pred), - ), - ); - - Ok(Some(ImplSource::UserDefined(ImplSourceUserDefinedData { impl_def_id, args, nested }))) -} - -/// The `Unsize` trait is particularly important to coercion, so we try rematch it. -/// NOTE: This must stay in sync with `consider_builtin_unsize_candidate` in trait -/// goal assembly in the solver, both for soundness and in order to avoid ICEs. -fn rematch_unsize<'tcx>( - infcx: &InferCtxt<'tcx>, - goal: Goal<'tcx, ty::TraitPredicate<'tcx>>, - source: BuiltinImplSource, - certainty: Certainty, -) -> SelectionResult<'tcx, Selection<'tcx>> { - let tcx = infcx.tcx; - let mut nested = vec![]; - let a_ty = structurally_normalize(goal.predicate.self_ty(), infcx, goal.param_env, &mut nested); - let b_ty = structurally_normalize( - goal.predicate.trait_ref.args.type_at(1), - infcx, - goal.param_env, - &mut nested, - ); - - match (a_ty.kind(), b_ty.kind()) { - // Don't try to coerce `?0` to `dyn Trait` - (ty::Infer(ty::TyVar(_)), _) | (_, ty::Infer(ty::TyVar(_))) => Ok(None), - // Stall any ambiguous upcasting goals, since we can't rematch those - (ty::Dynamic(_, _, ty::Dyn), ty::Dynamic(_, _, ty::Dyn)) => match certainty { - Certainty::Yes => Ok(Some(ImplSource::Builtin(source, nested))), - _ => Ok(None), - }, - // `T` -> `dyn Trait` upcasting - (_, &ty::Dynamic(data, region, ty::Dyn)) => { - // Check that the type implements all of the predicates of the def-id. - // (i.e. the principal, all of the associated types match, and any auto traits) - nested.extend(data.iter().map(|pred| { + |(clause, _)| { Obligation::new( infcx.tcx, - ObligationCause::dummy(), - goal.param_env, - pred.with_self_ty(tcx, a_ty), + ObligationCause::dummy_with_span(span), + goal.goal().param_env, + clause, ) - })); - // The type must be Sized to be unsized. - let sized_def_id = tcx.require_lang_item(hir::LangItem::Sized, None); - nested.push(Obligation::new( - infcx.tcx, - ObligationCause::dummy(), - goal.param_env, - ty::TraitRef::new(tcx, sized_def_id, [a_ty]), - )); - // The type must outlive the lifetime of the `dyn` we're unsizing into. - nested.push(Obligation::new( - infcx.tcx, - ObligationCause::dummy(), - goal.param_env, - ty::OutlivesPredicate(a_ty, region), - )); - - Ok(Some(ImplSource::Builtin(source, nested))) - } - // `[T; n]` -> `[T]` unsizing - (&ty::Array(a_elem_ty, ..), &ty::Slice(b_elem_ty)) => { - nested.extend( - infcx - .at(&ObligationCause::dummy(), goal.param_env) - // New solver ignores DefineOpaqueTypes, so choose Yes for consistency - .eq(DefineOpaqueTypes::Yes, a_elem_ty, b_elem_ty) - .expect("expected rematch to succeed") - .into_obligations(), - ); - - Ok(Some(ImplSource::Builtin(source, nested))) - } - // Struct unsizing `Struct<T>` -> `Struct<U>` where `T: Unsize<U>` - (&ty::Adt(a_def, a_args), &ty::Adt(b_def, b_args)) - if a_def.is_struct() && a_def.did() == b_def.did() => - { - let unsizing_params = tcx.unsizing_params_for_adt(a_def.did()); - // We must be unsizing some type parameters. This also implies - // that the struct has a tail field. - if unsizing_params.is_empty() { - bug!("expected rematch to succeed") - } - - let tail_field = a_def - .non_enum_variant() - .fields - .raw - .last() - .expect("expected unsized ADT to have a tail field"); - let tail_field_ty = tcx.type_of(tail_field.did); - - let a_tail_ty = tail_field_ty.instantiate(tcx, a_args); - let b_tail_ty = tail_field_ty.instantiate(tcx, b_args); - - // Instantiate just the unsizing params from B into A. The type after - // this instantiation must be equal to B. This is so we don't unsize - // unrelated type parameters. - let new_a_args = tcx.mk_args_from_iter( - a_args - .iter() - .enumerate() - .map(|(i, a)| if unsizing_params.contains(i as u32) { b_args[i] } else { a }), - ); - let unsized_a_ty = Ty::new_adt(tcx, a_def, new_a_args); - - nested.extend( - infcx - .at(&ObligationCause::dummy(), goal.param_env) - // New solver ignores DefineOpaqueTypes, so choose Yes for consistency - .eq(DefineOpaqueTypes::Yes, unsized_a_ty, b_ty) - .expect("expected rematch to succeed") - .into_obligations(), - ); - - // Finally, we require that `TailA: Unsize<TailB>` for the tail field - // types. - nested.push(Obligation::new( - tcx, - ObligationCause::dummy(), - goal.param_env, - ty::TraitRef::new(tcx, goal.predicate.def_id(), [a_tail_ty, b_tail_ty]), - )); - - Ok(Some(ImplSource::Builtin(source, nested))) - } - // Tuple unsizing `(.., T)` -> `(.., U)` where `T: Unsize<U>` - (&ty::Tuple(a_tys), &ty::Tuple(b_tys)) - if a_tys.len() == b_tys.len() && !a_tys.is_empty() => - { - let (a_last_ty, a_rest_tys) = a_tys.split_last().unwrap(); - let b_last_ty = b_tys.last().unwrap(); - - // Instantiate just the tail field of B., and require that they're equal. - let unsized_a_ty = - Ty::new_tup_from_iter(tcx, a_rest_tys.iter().chain([b_last_ty]).copied()); - nested.extend( - infcx - .at(&ObligationCause::dummy(), goal.param_env) - // New solver ignores DefineOpaqueTypes, so choose Yes for consistency - .eq(DefineOpaqueTypes::Yes, unsized_a_ty, b_ty) - .expect("expected rematch to succeed") - .into_obligations(), - ); - - // Similar to ADTs, require that we can unsize the tail. - nested.push(Obligation::new( - tcx, - ObligationCause::dummy(), - goal.param_env, - ty::TraitRef::new(tcx, goal.predicate.def_id(), [*a_last_ty, *b_last_ty]), - )); - - // We need to be able to detect tuple unsizing to require its feature gate. - assert_eq!( - source, - BuiltinImplSource::TupleUnsizing, - "compiler-errors wants to know if this can ever be triggered..." - ); - Ok(Some(ImplSource::Builtin(source, nested))) - } - _ => { - assert_ne!(certainty, Certainty::Yes); - Ok(None) - } - } -} + }, + ), + ); -fn structurally_normalize<'tcx>( - ty: Ty<'tcx>, - infcx: &InferCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - nested: &mut Vec<PredicateObligation<'tcx>>, -) -> Ty<'tcx> { - if matches!(ty.kind(), ty::Alias(..)) { - let mut engine = <dyn TraitEngine<'tcx>>::new(infcx); - let normalized_ty = infcx - .at(&ObligationCause::dummy(), param_env) - .structurally_normalize(ty, &mut *engine) - .expect("normalization shouldn't fail if we got to here"); - nested.extend(engine.pending_obligations()); - normalized_ty - } else { - ty - } + ImplSourceUserDefinedData { impl_def_id, nested, args } } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 3fa409eefff..796222129f1 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -1,15 +1,19 @@ use std::mem; +use std::ops::ControlFlow; use rustc_infer::infer::InferCtxt; -use rustc_infer::traits::solve::MaybeCause; +use rustc_infer::traits::query::NoSolution; +use rustc_infer::traits::solve::inspect::ProbeKind; +use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause}; use rustc_infer::traits::{ - query::NoSolution, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, - PredicateObligation, SelectionError, TraitEngine, + self, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation, + ObligationCause, PredicateObligation, SelectionError, TraitEngine, }; -use rustc_middle::ty; use rustc_middle::ty::error::{ExpectedFound, TypeError}; +use rustc_middle::ty::{self, TyCtxt}; use super::eval_ctxt::GenerateProofTree; +use super::inspect::{ProofTreeInferCtxtExt, ProofTreeVisitor}; use super::{Certainty, InferCtxtEvalExt}; /// A trait engine using the new trait solver. @@ -133,9 +137,9 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { .collect(); errors.extend(self.obligations.overflowed.drain(..).map(|obligation| FulfillmentError { - root_obligation: obligation.clone(), + obligation: find_best_leaf_obligation(infcx, &obligation), code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) }, - obligation, + root_obligation: obligation, })); errors @@ -192,8 +196,10 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { fn fulfillment_error_for_no_solution<'tcx>( infcx: &InferCtxt<'tcx>, - obligation: PredicateObligation<'tcx>, + root_obligation: PredicateObligation<'tcx>, ) -> FulfillmentError<'tcx> { + let obligation = find_best_leaf_obligation(infcx, &root_obligation); + let code = match obligation.predicate.kind().skip_binder() { ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => { FulfillmentErrorCode::ProjectionError( @@ -234,7 +240,8 @@ fn fulfillment_error_for_no_solution<'tcx>( bug!("unexpected goal: {obligation:?}") } }; - FulfillmentError { root_obligation: obligation.clone(), code, obligation } + + FulfillmentError { obligation, code, root_obligation } } fn fulfillment_error_for_stalled<'tcx>( @@ -258,5 +265,136 @@ fn fulfillment_error_for_stalled<'tcx>( } }); - FulfillmentError { obligation: obligation.clone(), code, root_obligation: obligation } + FulfillmentError { + obligation: find_best_leaf_obligation(infcx, &obligation), + code, + root_obligation: obligation, + } +} + +fn find_best_leaf_obligation<'tcx>( + infcx: &InferCtxt<'tcx>, + obligation: &PredicateObligation<'tcx>, +) -> PredicateObligation<'tcx> { + let obligation = infcx.resolve_vars_if_possible(obligation.clone()); + infcx + .visit_proof_tree( + obligation.clone().into(), + &mut BestObligation { obligation: obligation.clone() }, + ) + .break_value() + .unwrap_or(obligation) +} + +struct BestObligation<'tcx> { + obligation: PredicateObligation<'tcx>, +} + +impl<'tcx> BestObligation<'tcx> { + fn with_derived_obligation( + &mut self, + derived_obligation: PredicateObligation<'tcx>, + and_then: impl FnOnce(&mut Self) -> <Self as ProofTreeVisitor<'tcx>>::Result, + ) -> <Self as ProofTreeVisitor<'tcx>>::Result { + let old_obligation = std::mem::replace(&mut self.obligation, derived_obligation); + let res = and_then(self); + self.obligation = old_obligation; + res + } +} + +impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { + type Result = ControlFlow<PredicateObligation<'tcx>>; + + fn span(&self) -> rustc_span::Span { + self.obligation.cause.span + } + + fn visit_goal(&mut self, goal: &super::inspect::InspectGoal<'_, 'tcx>) -> Self::Result { + // FIXME: Throw out candidates that have no failing WC and >0 failing misc goal. + // This most likely means that the goal just didn't unify at all, e.g. a param + // candidate with an alias in it. + let candidates = goal.candidates(); + + let [candidate] = candidates.as_slice() else { + return ControlFlow::Break(self.obligation.clone()); + }; + + // FIXME: Could we extract a trait ref from a projection here too? + // FIXME: Also, what about considering >1 layer up the stack? May be necessary + // for normalizes-to. + let Some(parent_trait_pred) = goal.goal().predicate.to_opt_poly_trait_pred() else { + return ControlFlow::Break(self.obligation.clone()); + }; + + let tcx = goal.infcx().tcx; + let mut impl_where_bound_count = 0; + for nested_goal in candidate.instantiate_nested_goals(self.span()) { + let obligation; + match nested_goal.source() { + GoalSource::Misc => { + continue; + } + GoalSource::ImplWhereBound => { + obligation = Obligation { + cause: derive_cause( + tcx, + candidate.kind(), + self.obligation.cause.clone(), + impl_where_bound_count, + parent_trait_pred, + ), + param_env: nested_goal.goal().param_env, + predicate: nested_goal.goal().predicate, + recursion_depth: self.obligation.recursion_depth + 1, + }; + impl_where_bound_count += 1; + } + GoalSource::InstantiateHigherRanked => { + obligation = self.obligation.clone(); + } + } + + // Skip nested goals that hold. + //FIXME: We should change the max allowed certainty based on if we're + // visiting an ambiguity or error obligation. + if matches!(nested_goal.result(), Ok(Certainty::Yes)) { + continue; + } + + self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?; + } + + ControlFlow::Break(self.obligation.clone()) + } +} + +fn derive_cause<'tcx>( + tcx: TyCtxt<'tcx>, + candidate_kind: ProbeKind<'tcx>, + mut cause: ObligationCause<'tcx>, + idx: usize, + parent_trait_pred: ty::PolyTraitPredicate<'tcx>, +) -> ObligationCause<'tcx> { + match candidate_kind { + ProbeKind::TraitCandidate { source: CandidateSource::Impl(impl_def_id), result: _ } => { + if let Some((_, span)) = + tcx.predicates_of(impl_def_id).instantiate_identity(tcx).iter().nth(idx) + { + cause = cause.derived_cause(parent_trait_pred, |derived| { + traits::ImplDerivedObligation(Box::new(traits::ImplDerivedObligationCause { + derived, + impl_or_alias_def_id: impl_def_id, + impl_def_predicate_index: Some(idx), + span, + })) + }) + } + } + ProbeKind::TraitCandidate { source: CandidateSource::BuiltinImpl(..), result: _ } => { + cause = cause.derived_cause(parent_trait_pred, traits::BuiltinDerivedObligation); + } + _ => {} + }; + cause } diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index f137780c536..4f79f1b2aaf 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -14,6 +14,7 @@ use rustc_ast_ir::visit::VisitorResult; use rustc_infer::infer::resolve::EagerResolver; use rustc_infer::infer::type_variable::TypeVariableOrigin; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; +use rustc_macros::extension; use rustc_middle::infer::unify_key::ConstVariableOrigin; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{inspect, QueryResult}; @@ -21,11 +22,12 @@ use rustc_middle::traits::solve::{Certainty, Goal}; use rustc_middle::traits::ObligationCause; use rustc_middle::ty; use rustc_middle::ty::TypeFoldable; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use crate::solve::eval_ctxt::canonical; use crate::solve::{EvalCtxt, GoalEvaluationKind, GoalSource}; use crate::solve::{GenerateProofTree, InferCtxtEvalExt}; +use crate::traits::ObligationCtxt; pub struct InspectConfig { pub max_depth: usize, @@ -34,17 +36,65 @@ pub struct InspectConfig { pub struct InspectGoal<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, depth: usize, - orig_values: &'a [ty::GenericArg<'tcx>], + orig_values: Vec<ty::GenericArg<'tcx>>, goal: Goal<'tcx, ty::Predicate<'tcx>>, - evaluation: &'a inspect::GoalEvaluation<'tcx>, + result: Result<Certainty, NoSolution>, + evaluation_kind: inspect::CanonicalGoalEvaluationKind<'tcx>, + normalizes_to_term_hack: Option<NormalizesToTermHack<'tcx>>, + source: GoalSource, +} + +/// The expected term of a `NormalizesTo` goal gets replaced +/// with an unconstrained inference variable when computing +/// `NormalizesTo` goals and we return the nested goals to the +/// caller, who also equates the actual term with the expected. +/// +/// This is an implementation detail of the trait solver and +/// not something we want to leak to users. We therefore +/// treat `NormalizesTo` goals as if they apply the expected +/// type at the end of each candidate. +#[derive(Copy, Clone)] +struct NormalizesToTermHack<'tcx> { + term: ty::Term<'tcx>, + unconstrained_term: ty::Term<'tcx>, +} + +impl<'tcx> NormalizesToTermHack<'tcx> { + /// Relate the `term` with the new `unconstrained_term` created + /// when computing the proof tree for this `NormalizesTo` goals. + /// This handles nested obligations. + fn constrain( + self, + infcx: &InferCtxt<'tcx>, + span: Span, + param_env: ty::ParamEnv<'tcx>, + ) -> Result<Certainty, NoSolution> { + infcx + .at(&ObligationCause::dummy_with_span(span), param_env) + .eq(DefineOpaqueTypes::Yes, self.term, self.unconstrained_term) + .map_err(|_| NoSolution) + .and_then(|InferOk { value: (), obligations }| { + let ocx = ObligationCtxt::new(infcx); + ocx.register_obligations(obligations); + let errors = ocx.select_all_or_error(); + if errors.is_empty() { + Ok(Certainty::Yes) + } else if errors.iter().all(|e| !e.is_true_error()) { + Ok(Certainty::AMBIGUOUS) + } else { + Err(NoSolution) + } + }) + } } pub struct InspectCandidate<'a, 'tcx> { goal: &'a InspectGoal<'a, 'tcx>, kind: inspect::ProbeKind<'tcx>, - nested_goals: Vec<inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>>, + nested_goals: Vec<(GoalSource, inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>)>, final_state: inspect::CanonicalState<'tcx, ()>, result: QueryResult<'tcx>, + shallow_certainty: Certainty, } impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { @@ -56,84 +106,111 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { self.result.map(|c| c.value.certainty) } + pub fn goal(&self) -> &'a InspectGoal<'a, 'tcx> { + self.goal + } + + /// Certainty passed into `evaluate_added_goals_and_make_canonical_response`. + /// + /// If this certainty is `Yes`, then we must be confident that the candidate + /// must hold iff it's nested goals hold. This is not true if the certainty is + /// `Maybe(..)`, which suggests we forced ambiguity instead. + /// + /// This is *not* the certainty of the candidate's full nested evaluation, which + /// can be accessed with [`Self::result`] instead. + pub fn shallow_certainty(&self) -> Certainty { + self.shallow_certainty + } + /// Visit all nested goals of this candidate without rolling /// back their inference constraints. This function modifies /// the state of the `infcx`. pub fn visit_nested_no_probe<V: ProofTreeVisitor<'tcx>>(&self, visitor: &mut V) -> V::Result { - if self.goal.depth < visitor.config().max_depth { - let infcx = self.goal.infcx; - let param_env = self.goal.goal.param_env; - let mut orig_values = self.goal.orig_values.to_vec(); - let mut instantiated_goals = vec![]; - for goal in &self.nested_goals { - let goal = canonical::instantiate_canonical_state( - infcx, - visitor.span(), - param_env, - &mut orig_values, - *goal, - ); - instantiated_goals.push(goal); - } - - let () = canonical::instantiate_canonical_state( - infcx, - visitor.span(), - param_env, - &mut orig_values, - self.final_state, - ); - - for &goal in &instantiated_goals { - let proof_tree = match goal.predicate.kind().no_bound_vars() { - Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => { - let unconstrained_term = match term.unpack() { - ty::TermKind::Ty(_) => infcx - .next_ty_var(TypeVariableOrigin { - param_def_id: None, - span: visitor.span(), - }) - .into(), - ty::TermKind::Const(ct) => infcx - .next_const_var( - ct.ty(), - ConstVariableOrigin { - param_def_id: None, - span: visitor.span(), - }, - ) - .into(), - }; - let goal = goal - .with(infcx.tcx, ty::NormalizesTo { alias, term: unconstrained_term }); - let proof_tree = - EvalCtxt::enter_root(infcx, GenerateProofTree::Yes, |ecx| { - ecx.evaluate_goal_raw( - GoalEvaluationKind::Root, - GoalSource::Misc, - goal, - ) - }) - .1; - let InferOk { value: (), obligations: _ } = infcx - .at(&ObligationCause::dummy(), param_env) - .eq(DefineOpaqueTypes::Yes, term, unconstrained_term) - .unwrap(); - proof_tree - } - _ => infcx.evaluate_root_goal(goal, GenerateProofTree::Yes).1, - }; - try_visit!(visitor.visit_goal(&InspectGoal::new( - infcx, - self.goal.depth + 1, - &proof_tree.unwrap(), - ))); - } + for goal in self.instantiate_nested_goals(visitor.span()) { + try_visit!(goal.visit_with(visitor)); } V::Result::output() } + /// Instantiate the nested goals for the candidate without rolling back their + /// inference constraints. This function modifies the state of the `infcx`. + pub fn instantiate_nested_goals(&self, span: Span) -> Vec<InspectGoal<'a, 'tcx>> { + let infcx = self.goal.infcx; + let param_env = self.goal.goal.param_env; + let mut orig_values = self.goal.orig_values.to_vec(); + let instantiated_goals: Vec<_> = self + .nested_goals + .iter() + .map(|(source, goal)| { + ( + *source, + canonical::instantiate_canonical_state( + infcx, + span, + param_env, + &mut orig_values, + *goal, + ), + ) + }) + .collect(); + + let () = canonical::instantiate_canonical_state( + infcx, + span, + param_env, + &mut orig_values, + self.final_state, + ); + + if let Some(term_hack) = self.goal.normalizes_to_term_hack { + // FIXME: We ignore the expected term of `NormalizesTo` goals + // when computing the result of its candidates. This is + // scuffed. + let _ = term_hack.constrain(infcx, span, param_env); + } + + instantiated_goals + .into_iter() + .map(|(source, goal)| match goal.predicate.kind().no_bound_vars() { + Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => { + let unconstrained_term = match term.unpack() { + ty::TermKind::Ty(_) => infcx + .next_ty_var(TypeVariableOrigin { param_def_id: None, span }) + .into(), + ty::TermKind::Const(ct) => infcx + .next_const_var( + ct.ty(), + ConstVariableOrigin { param_def_id: None, span }, + ) + .into(), + }; + let goal = + goal.with(infcx.tcx, ty::NormalizesTo { alias, term: unconstrained_term }); + let proof_tree = EvalCtxt::enter_root(infcx, GenerateProofTree::Yes, |ecx| { + ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal) + }) + .1; + InspectGoal::new( + infcx, + self.goal.depth + 1, + proof_tree.unwrap(), + Some(NormalizesToTermHack { term, unconstrained_term }), + source, + ) + } + _ => InspectGoal::new( + infcx, + self.goal.depth + 1, + infcx.evaluate_root_goal(goal, GenerateProofTree::Yes).1.unwrap(), + None, + source, + ), + }) + .collect() + } + /// Visit all nested goals of this candidate, rolling back /// all inference constraints. pub fn visit_nested_in_probe<V: ProofTreeVisitor<'tcx>>(&self, visitor: &mut V) -> V::Result { @@ -151,19 +228,26 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { } pub fn result(&self) -> Result<Certainty, NoSolution> { - self.evaluation.evaluation.result.map(|c| c.value.certainty) + self.result + } + + pub fn source(&self) -> GoalSource { + self.source } fn candidates_recur( &'a self, candidates: &mut Vec<InspectCandidate<'a, 'tcx>>, - nested_goals: &mut Vec<inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>>, + nested_goals: &mut Vec<( + GoalSource, + inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>, + )>, probe: &inspect::Probe<'tcx>, ) { - let num_candidates = candidates.len(); + let mut shallow_certainty = None; for step in &probe.steps { match step { - &inspect::ProbeStep::AddGoal(_source, goal) => nested_goals.push(goal), + &inspect::ProbeStep::AddGoal(source, goal) => nested_goals.push((source, goal)), inspect::ProbeStep::NestedProbe(ref probe) => { // Nested probes have to prove goals added in their parent // but do not leak them, so we truncate the added goals @@ -172,6 +256,9 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { self.candidates_recur(candidates, nested_goals, probe); nested_goals.truncate(num_goals); } + inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty: c } => { + assert_eq!(shallow_certainty.replace(*c), None); + } inspect::ProbeStep::EvaluateGoals(_) => (), } } @@ -180,44 +267,36 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { inspect::ProbeKind::NormalizedSelfTyAssembly | inspect::ProbeKind::UnsizeAssembly | inspect::ProbeKind::UpcastProjectionCompatibility => (), - // We add a candidate for the root evaluation if there + + // We add a candidate even for the root evaluation if there // is only one way to prove a given goal, e.g. for `WellFormed`. - // - // FIXME: This is currently wrong if we don't even try any - // candidates, e.g. for a trait goal, as in this case `candidates` is - // actually supposed to be empty. inspect::ProbeKind::Root { result } - | inspect::ProbeKind::TryNormalizeNonRigid { result } => { - if candidates.len() == num_candidates { + | inspect::ProbeKind::TryNormalizeNonRigid { result } + | inspect::ProbeKind::TraitCandidate { source: _, result } + | inspect::ProbeKind::OpaqueTypeStorageLookup { result } => { + // We only add a candidate if `shallow_certainty` was set, which means + // that we ended up calling `evaluate_added_goals_and_make_canonical_response`. + if let Some(shallow_certainty) = shallow_certainty { candidates.push(InspectCandidate { goal: self, kind: probe.kind, nested_goals: nested_goals.clone(), final_state: probe.final_state, result, - }) + shallow_certainty, + }); } } - inspect::ProbeKind::MiscCandidate { name: _, result } - | inspect::ProbeKind::TraitCandidate { source: _, result } => { - candidates.push(InspectCandidate { - goal: self, - kind: probe.kind, - nested_goals: nested_goals.clone(), - final_state: probe.final_state, - result, - }); - } } } pub fn candidates(&'a self) -> Vec<InspectCandidate<'a, 'tcx>> { let mut candidates = vec![]; - let last_eval_step = match self.evaluation.evaluation.kind { + let last_eval_step = match self.evaluation_kind { inspect::CanonicalGoalEvaluationKind::Overflow | inspect::CanonicalGoalEvaluationKind::CycleInStack | inspect::CanonicalGoalEvaluationKind::ProvisionalCacheHit => { - warn!("unexpected root evaluation: {:?}", self.evaluation); + warn!("unexpected root evaluation: {:?}", self.evaluation_kind); return vec![]; } inspect::CanonicalGoalEvaluationKind::Evaluation { revisions } => { @@ -249,19 +328,42 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { fn new( infcx: &'a InferCtxt<'tcx>, depth: usize, - root: &'a inspect::GoalEvaluation<'tcx>, + root: inspect::GoalEvaluation<'tcx>, + normalizes_to_term_hack: Option<NormalizesToTermHack<'tcx>>, + source: GoalSource, ) -> Self { - match root.kind { - inspect::GoalEvaluationKind::Root { ref orig_values } => InspectGoal { - infcx, - depth, - orig_values, - goal: root.uncanonicalized_goal.fold_with(&mut EagerResolver::new(infcx)), - evaluation: root, - }, - inspect::GoalEvaluationKind::Nested { .. } => unreachable!(), + let inspect::GoalEvaluation { uncanonicalized_goal, kind, evaluation } = root; + let inspect::GoalEvaluationKind::Root { orig_values } = kind else { unreachable!() }; + + let result = evaluation.result.and_then(|ok| { + if let Some(term_hack) = normalizes_to_term_hack { + infcx + .probe(|_| term_hack.constrain(infcx, DUMMY_SP, uncanonicalized_goal.param_env)) + .map(|certainty| ok.value.certainty.unify_with(certainty)) + } else { + Ok(ok.value.certainty) + } + }); + + InspectGoal { + infcx, + depth, + orig_values, + goal: uncanonicalized_goal.fold_with(&mut EagerResolver::new(infcx)), + result, + evaluation_kind: evaluation.kind, + normalizes_to_term_hack, + source, } } + + pub(crate) fn visit_with<V: ProofTreeVisitor<'tcx>>(&self, visitor: &mut V) -> V::Result { + if self.depth < visitor.config().max_depth { + try_visit!(visitor.visit_goal(self)); + } + + V::Result::output() + } } /// The public API to interact with proof trees. @@ -286,6 +388,6 @@ impl<'tcx> InferCtxt<'tcx> { ) -> V::Result { let (_, proof_tree) = self.evaluate_root_goal(goal, GenerateProofTree::Yes); let proof_tree = proof_tree.unwrap(); - visitor.visit_goal(&InspectGoal::new(self, 0, &proof_tree)) + visitor.visit_goal(&InspectGoal::new(self, 0, proof_tree, None, GoalSource::Misc)) } } diff --git a/compiler/rustc_trait_selection/src/solve/inspect/build.rs b/compiler/rustc_trait_selection/src/solve/inspect/build.rs index c3651517d49..466d0d80060 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/build.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/build.rs @@ -241,6 +241,7 @@ enum WipProbeStep<'tcx> { AddGoal(GoalSource, inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>), EvaluateGoals(WipAddedGoalsEvaluation<'tcx>), NestedProbe(WipProbe<'tcx>), + MakeCanonicalResponse { shallow_certainty: Certainty }, } impl<'tcx> WipProbeStep<'tcx> { @@ -249,6 +250,9 @@ impl<'tcx> WipProbeStep<'tcx> { WipProbeStep::AddGoal(source, goal) => inspect::ProbeStep::AddGoal(source, goal), WipProbeStep::EvaluateGoals(eval) => inspect::ProbeStep::EvaluateGoals(eval.finalize()), WipProbeStep::NestedProbe(probe) => inspect::ProbeStep::NestedProbe(probe.finalize()), + WipProbeStep::MakeCanonicalResponse { shallow_certainty } => { + inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty } + } } } } @@ -530,6 +534,19 @@ impl<'tcx> ProofTreeBuilder<'tcx> { } } + pub fn make_canonical_response(&mut self, shallow_certainty: Certainty) { + match self.as_mut() { + Some(DebugSolver::GoalEvaluationStep(state)) => { + state + .current_evaluation_scope() + .steps + .push(WipProbeStep::MakeCanonicalResponse { shallow_certainty }); + } + None => {} + _ => {} + } + } + pub fn finish_probe(mut self) -> ProofTreeBuilder<'tcx> { match self.as_mut() { None => {} diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index e58babe3208..b2b076e28e6 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -16,6 +16,7 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_infer::traits::query::NoSolution; +use rustc_macros::extension; use rustc_middle::infer::canonical::CanonicalVarInfos; use rustc_middle::traits::solve::{ CanonicalResponse, Certainty, ExternalConstraintsData, Goal, GoalSource, QueryResult, Response, diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index c662ab23c53..f886c588650 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -8,11 +8,10 @@ use rustc_hir::def_id::DefId; use rustc_hir::LangItem; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::solve::inspect::ProbeKind; +use rustc_infer::traits::solve::MaybeCause; use rustc_infer::traits::specialization_graph::LeafDef; use rustc_infer::traits::Reveal; -use rustc_middle::traits::solve::{ - CandidateSource, CanonicalResponse, Certainty, Goal, QueryResult, -}; +use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal, QueryResult}; use rustc_middle::traits::BuiltinImplSource; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_middle::ty::NormalizesTo; @@ -119,14 +118,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { fn probe_and_match_goal_against_assumption( ecx: &mut EvalCtxt<'_, 'tcx>, + source: CandidateSource, goal: Goal<'tcx, Self>, assumption: ty::Clause<'tcx>, then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { if let Some(projection_pred) = assumption.as_projection_clause() { if projection_pred.projection_def_id() == goal.predicate.def_id() { let tcx = ecx.tcx(); - ecx.probe_misc_candidate("assumption").enter(|ecx| { + ecx.probe_trait_candidate(source).enter(|ecx| { let assumption_projection_pred = ecx.instantiate_binder_with_infer(projection_pred); ecx.eq( @@ -300,14 +300,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { fn consider_error_guaranteed_candidate( _ecx: &mut EvalCtxt<'_, 'tcx>, _guar: ErrorGuaranteed, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { Err(NoSolution) } fn consider_auto_trait_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { ecx.tcx().dcx().span_delayed_bug( ecx.tcx().def_span(goal.predicate.def_id()), "associated types not allowed on auto traits", @@ -318,35 +318,35 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { fn consider_trait_alias_candidate( _ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { bug!("trait aliases do not have associated types: {:?}", goal); } fn consider_builtin_sized_candidate( _ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { bug!("`Sized` does not have an associated type: {:?}", goal); } fn consider_builtin_copy_clone_candidate( _ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { bug!("`Copy`/`Clone` does not have an associated type: {:?}", goal); } fn consider_builtin_pointer_like_candidate( _ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { bug!("`PointerLike` does not have an associated type: {:?}", goal); } fn consider_builtin_fn_ptr_trait_candidate( _ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { bug!("`FnPtr` does not have an associated type: {:?}", goal); } @@ -354,7 +354,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, goal_kind: ty::ClosureKind, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { let tcx = ecx.tcx(); let tupled_inputs_and_output = match structural_traits::extract_tupled_inputs_and_output_from_callable( @@ -364,8 +364,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { )? { Some(tupled_inputs_and_output) => tupled_inputs_and_output, None => { - return ecx - .evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS); + return ecx.forced_ambiguity(MaybeCause::Ambiguity); } }; let output_is_sized_pred = tupled_inputs_and_output.map_bound(|(_, output)| { @@ -385,14 +384,20 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { // A built-in `Fn` impl only holds if the output is sized. // (FIXME: technically we only need to check this if the type is a fn ptr...) - Self::consider_implied_clause(ecx, goal, pred, [goal.with(tcx, output_is_sized_pred)]) + Self::probe_and_consider_implied_clause( + ecx, + CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), + goal, + pred, + [(GoalSource::ImplWhereBound, goal.with(tcx, output_is_sized_pred))], + ) } fn consider_builtin_async_fn_trait_candidates( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, goal_kind: ty::ClosureKind, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { let tcx = ecx.tcx(); let env_region = match goal_kind { @@ -461,20 +466,22 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { // A built-in `AsyncFn` impl only holds if the output is sized. // (FIXME: technically we only need to check this if the type is a fn ptr...) - Self::consider_implied_clause( + Self::probe_and_consider_implied_clause( ecx, + CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, pred, [goal.with(tcx, output_is_sized_pred)] .into_iter() - .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred))), + .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred))) + .map(|goal| (GoalSource::ImplWhereBound, goal)), ) } fn consider_builtin_async_fn_kind_helper_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { let [ closure_fn_kind_ty, goal_kind_ty, @@ -489,7 +496,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { // Bail if the upvars haven't been constrained. if tupled_upvars_ty.expect_ty().is_ty_var() { - return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS); + return ecx.forced_ambiguity(MaybeCause::Ambiguity); } let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else { @@ -512,25 +519,27 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { borrow_region.expect_region(), ); - ecx.instantiate_normalizes_to_term(goal, upvars_ty.into()); - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { + ecx.instantiate_normalizes_to_term(goal, upvars_ty.into()); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) } fn consider_builtin_tuple_candidate( _ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { bug!("`Tuple` does not have an associated type: {:?}", goal); } fn consider_builtin_pointee_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { let tcx = ecx.tcx(); let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None); assert_eq!(metadata_def_id, goal.predicate.def_id()); - ecx.probe_misc_candidate("builtin pointee").enter(|ecx| { + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { let metadata_ty = match goal.predicate.self_ty().kind() { ty::Bool | ty::Char @@ -609,7 +618,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { fn consider_builtin_future_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { let self_ty = goal.predicate.self_ty(); let ty::Coroutine(def_id, args) = *self_ty.kind() else { return Err(NoSolution); @@ -623,8 +632,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { let term = args.as_coroutine().return_ty().into(); - Self::consider_implied_clause( + Self::probe_and_consider_implied_clause( ecx, + CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, ty::ProjectionPredicate { projection_ty: ty::AliasTy::new(ecx.tcx(), goal.predicate.def_id(), [self_ty]), @@ -640,7 +650,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { fn consider_builtin_iterator_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { let self_ty = goal.predicate.self_ty(); let ty::Coroutine(def_id, args) = *self_ty.kind() else { return Err(NoSolution); @@ -654,8 +664,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { let term = args.as_coroutine().yield_ty().into(); - Self::consider_implied_clause( + Self::probe_and_consider_implied_clause( ecx, + CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, ty::ProjectionPredicate { projection_ty: ty::AliasTy::new(ecx.tcx(), goal.predicate.def_id(), [self_ty]), @@ -671,14 +682,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { fn consider_builtin_fused_iterator_candidate( _ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { bug!("`FusedIterator` does not have an associated type: {:?}", goal); } fn consider_builtin_async_iterator_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { let self_ty = goal.predicate.self_ty(); let ty::Coroutine(def_id, args) = *self_ty.kind() else { return Err(NoSolution); @@ -690,7 +701,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { return Err(NoSolution); } - ecx.probe_misc_candidate("builtin AsyncIterator kind").enter(|ecx| { + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { let expected_ty = ecx.next_ty_infer(); // Take `AsyncIterator<Item = I>` and turn it into the corresponding // coroutine yield ty `Poll<Option<I>>`. @@ -714,7 +725,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { fn consider_builtin_coroutine_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { let self_ty = goal.predicate.self_ty(); let ty::Coroutine(def_id, args) = *self_ty.kind() else { return Err(NoSolution); @@ -737,8 +748,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { bug!("unexpected associated item `<{self_ty} as Coroutine>::{name}`") }; - Self::consider_implied_clause( + Self::probe_and_consider_implied_clause( ecx, + CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, ty::ProjectionPredicate { projection_ty: ty::AliasTy::new( @@ -758,14 +770,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { fn consider_structural_builtin_unsize_candidates( _ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> Vec<(CanonicalResponse<'tcx>, BuiltinImplSource)> { + ) -> Vec<Candidate<'tcx>> { bug!("`Unsize` does not have an associated type: {:?}", goal); } fn consider_builtin_discriminant_kind_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { let self_ty = goal.predicate.self_ty(); let discriminant_ty = match *self_ty.kind() { ty::Bool @@ -808,7 +820,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ), }; - ecx.probe_misc_candidate("builtin discriminant kind").enter(|ecx| { + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { ecx.instantiate_normalizes_to_term(goal, discriminant_ty.into()); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) @@ -817,7 +829,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { fn consider_builtin_async_destruct_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { let self_ty = goal.predicate.self_ty(); let async_destructor_ty = match *self_ty.kind() { ty::Bool @@ -860,7 +872,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ), }; - ecx.probe_misc_candidate("builtin async destruct").enter(|ecx| { + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { ecx.eq(goal.param_env, goal.predicate.term, async_destructor_ty.into()) .expect("expected goal term to be fully unconstrained"); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) @@ -870,14 +882,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { fn consider_builtin_destruct_candidate( _ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { bug!("`Destruct` does not have an associated type: {:?}", goal); } fn consider_builtin_transmute_candidate( _ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { bug!("`BikeshedIntrinsicFrom` does not have an associated type: {:?}", goal) } } diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index f6d12a9a013..d2b893d6383 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -9,10 +9,9 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def_id::DefId; use rustc_hir::{LangItem, Movability}; use rustc_infer::traits::query::NoSolution; +use rustc_infer::traits::solve::MaybeCause; use rustc_middle::traits::solve::inspect::ProbeKind; -use rustc_middle::traits::solve::{ - CandidateSource, CanonicalResponse, Certainty, Goal, QueryResult, -}; +use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal, QueryResult}; use rustc_middle::traits::{BuiltinImplSource, Reveal}; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; @@ -94,21 +93,24 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { fn consider_error_guaranteed_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, _guar: ErrorGuaranteed, - ) -> QueryResult<'tcx> { - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + ) -> Result<Candidate<'tcx>, NoSolution> { + // FIXME: don't need to enter a probe here. + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) + .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } fn probe_and_match_goal_against_assumption( ecx: &mut EvalCtxt<'_, 'tcx>, + source: CandidateSource, goal: Goal<'tcx, Self>, assumption: ty::Clause<'tcx>, then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { if let Some(trait_clause) = assumption.as_trait_clause() { if trait_clause.def_id() == goal.predicate.def_id() && trait_clause.polarity() == goal.predicate.polarity { - ecx.probe_misc_candidate("assumption").enter(|ecx| { + ecx.probe_trait_candidate(source).enter(|ecx| { let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause); ecx.eq( goal.param_env, @@ -128,7 +130,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { fn consider_auto_trait_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } @@ -162,6 +164,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } ecx.probe_and_evaluate_goal_for_constituent_tys( + CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, structural_traits::instantiate_constituent_tys_for_auto_trait, ) @@ -170,14 +173,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { fn consider_trait_alias_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } let tcx = ecx.tcx(); - ecx.probe_misc_candidate("trait alias").enter(|ecx| { + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { let nested_obligations = tcx .predicates_of(goal.predicate.def_id()) .instantiate(tcx, goal.predicate.trait_ref.args); @@ -193,12 +196,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { fn consider_builtin_sized_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } ecx.probe_and_evaluate_goal_for_constituent_tys( + CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, structural_traits::instantiate_constituent_tys_for_sized_trait, ) @@ -207,12 +211,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { fn consider_builtin_copy_clone_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } ecx.probe_and_evaluate_goal_for_constituent_tys( + CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, structural_traits::instantiate_constituent_tys_for_copy_clone_trait, ) @@ -221,7 +226,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { fn consider_builtin_pointer_like_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } @@ -234,14 +239,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { let key = tcx.erase_regions(goal.param_env.and(goal.predicate.self_ty())); // But if there are inference variables, we have to wait until it's resolved. if key.has_non_region_infer() { - return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS); + return ecx.forced_ambiguity(MaybeCause::Ambiguity); } if let Ok(layout) = tcx.layout_of(key) && layout.layout.is_pointer_like(&tcx.data_layout) { // FIXME: We could make this faster by making a no-constraints response - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) + .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } else { Err(NoSolution) } @@ -250,13 +256,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { fn consider_builtin_fn_ptr_trait_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { let self_ty = goal.predicate.self_ty(); match goal.predicate.polarity { // impl FnPtr for FnPtr {} ty::PredicatePolarity::Positive => { if self_ty.is_fn_ptr() { - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) } else { Err(NoSolution) } @@ -266,7 +274,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { // If a type is rigid and not a fn ptr, then we know for certain // that it does *not* implement `FnPtr`. if !self_ty.is_fn_ptr() && self_ty.is_known_rigid() { - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) } else { Err(NoSolution) } @@ -278,7 +288,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, goal_kind: ty::ClosureKind, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } @@ -292,8 +302,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { )? { Some(a) => a, None => { - return ecx - .evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS); + return ecx.forced_ambiguity(MaybeCause::Ambiguity); } }; let output_is_sized_pred = tupled_inputs_and_output.map_bound(|(_, output)| { @@ -307,14 +316,20 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { .to_predicate(tcx); // A built-in `Fn` impl only holds if the output is sized. // (FIXME: technically we only need to check this if the type is a fn ptr...) - Self::consider_implied_clause(ecx, goal, pred, [goal.with(tcx, output_is_sized_pred)]) + Self::probe_and_consider_implied_clause( + ecx, + CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), + goal, + pred, + [(GoalSource::ImplWhereBound, goal.with(tcx, output_is_sized_pred))], + ) } fn consider_builtin_async_fn_trait_candidates( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, goal_kind: ty::ClosureKind, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } @@ -345,20 +360,22 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { .to_predicate(tcx); // A built-in `AsyncFn` impl only holds if the output is sized. // (FIXME: technically we only need to check this if the type is a fn ptr...) - Self::consider_implied_clause( + Self::probe_and_consider_implied_clause( ecx, + CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, pred, [goal.with(tcx, output_is_sized_pred)] .into_iter() - .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred))), + .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred))) + .map(|goal| (GoalSource::ImplWhereBound, goal)), ) } fn consider_builtin_async_fn_kind_helper_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { let [closure_fn_kind_ty, goal_kind_ty] = **goal.predicate.trait_ref.args else { bug!(); }; @@ -369,7 +386,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { }; let goal_kind = goal_kind_ty.expect_ty().to_opt_closure_kind().unwrap(); if closure_kind.extends(goal_kind) { - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) + .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } else { Err(NoSolution) } @@ -384,13 +402,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { fn consider_builtin_tuple_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } if let ty::Tuple(..) = goal.predicate.self_ty().kind() { - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) + .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } else { Err(NoSolution) } @@ -399,18 +418,19 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { fn consider_builtin_pointee_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) + .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } fn consider_builtin_future_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } @@ -428,13 +448,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { // Async coroutine unconditionally implement `Future` // Technically, we need to check that the future output type is Sized, // but that's already proven by the coroutine being WF. - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + // FIXME: use `consider_implied` + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) + .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } fn consider_builtin_iterator_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } @@ -452,13 +474,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { // Gen coroutines unconditionally implement `Iterator` // Technically, we need to check that the iterator output type is Sized, // but that's already proven by the coroutines being WF. - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + // FIXME: use `consider_implied` + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) + .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } fn consider_builtin_fused_iterator_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } @@ -474,13 +498,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } // Gen coroutines unconditionally implement `FusedIterator` - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + // FIXME: use `consider_implied` + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) + .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } fn consider_builtin_async_iterator_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } @@ -498,13 +524,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { // Gen coroutines unconditionally implement `Iterator` // Technically, we need to check that the iterator output type is Sized, // but that's already proven by the coroutines being WF. - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + // FIXME: use `consider_implied` + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) + .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } fn consider_builtin_coroutine_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } @@ -521,8 +549,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } let coroutine = args.as_coroutine(); - Self::consider_implied_clause( + Self::probe_and_consider_implied_clause( ecx, + CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, ty::TraitRef::new(tcx, goal.predicate.def_id(), [self_ty, coroutine.resume_ty()]) .to_predicate(tcx), @@ -535,31 +564,33 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { fn consider_builtin_discriminant_kind_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } // `DiscriminantKind` is automatically implemented for every type. - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) + .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } fn consider_builtin_async_destruct_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } // `AsyncDestruct` is automatically implemented for every type. - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) + .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } fn consider_builtin_destruct_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } @@ -568,13 +599,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { // `Destruct` is automatically implemented for every type in // non-const environments. - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) + .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } fn consider_builtin_transmute_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } @@ -594,11 +626,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { return Err(NoSolution); }; - let certainty = ecx.is_transmutable( - rustc_transmute::Types { dst: args.type_at(0), src: args.type_at(1) }, - assume, - )?; - ecx.evaluate_added_goals_and_make_canonical_response(certainty) + // FIXME: This actually should destructure the `Result` we get from transmutability and + // register candiates. We probably need to register >1 since we may have an OR of ANDs. + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { + let certainty = ecx.is_transmutable( + rustc_transmute::Types { dst: args.type_at(0), src: args.type_at(1) }, + assume, + )?; + ecx.evaluate_added_goals_and_make_canonical_response(certainty) + }) } /// ```ignore (builtin impl example) @@ -611,20 +647,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { fn consider_structural_builtin_unsize_candidates( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> Vec<(CanonicalResponse<'tcx>, BuiltinImplSource)> { + ) -> Vec<Candidate<'tcx>> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return vec![]; } - let misc_candidate = |ecx: &mut EvalCtxt<'_, 'tcx>, certainty| { - ( - ecx.evaluate_added_goals_and_make_canonical_response(certainty).unwrap(), - BuiltinImplSource::Misc, - ) - }; - - let result_to_single = |result, source| match result { - Ok(resp) => vec![(resp, source)], + let result_to_single = |result| match result { + Ok(resp) => vec![resp], Err(NoSolution) => vec![], }; @@ -642,7 +671,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { let goal = goal.with(ecx.tcx(), (a_ty, b_ty)); match (a_ty.kind(), b_ty.kind()) { (ty::Infer(ty::TyVar(..)), ..) => bug!("unexpected infer {a_ty:?} {b_ty:?}"), - (_, ty::Infer(ty::TyVar(..))) => vec![misc_candidate(ecx, Certainty::AMBIGUOUS)], + + (_, ty::Infer(ty::TyVar(..))) => { + result_to_single(ecx.forced_ambiguity(MaybeCause::Ambiguity)) + } // Trait upcasting, or `dyn Trait + Auto + 'a` -> `dyn Trait + 'b`. ( @@ -655,14 +687,12 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { // `T` -> `dyn Trait` unsizing. (_, &ty::Dynamic(b_region, b_data, ty::Dyn)) => result_to_single( ecx.consider_builtin_unsize_to_dyn_candidate(goal, b_region, b_data), - BuiltinImplSource::Misc, ), // `[T; N]` -> `[T]` unsizing - (&ty::Array(a_elem_ty, ..), &ty::Slice(b_elem_ty)) => result_to_single( - ecx.consider_builtin_array_unsize(goal, a_elem_ty, b_elem_ty), - BuiltinImplSource::Misc, - ), + (&ty::Array(a_elem_ty, ..), &ty::Slice(b_elem_ty)) => { + result_to_single(ecx.consider_builtin_array_unsize(goal, a_elem_ty, b_elem_ty)) + } // `Struct<T>` -> `Struct<U>` where `T: Unsize<U>` (&ty::Adt(a_def, a_args), &ty::Adt(b_def, b_args)) @@ -670,7 +700,6 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { { result_to_single( ecx.consider_builtin_struct_unsize(goal, a_def, a_args, b_args), - BuiltinImplSource::Misc, ) } @@ -678,10 +707,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { (&ty::Tuple(a_tys), &ty::Tuple(b_tys)) if a_tys.len() == b_tys.len() && !a_tys.is_empty() => { - result_to_single( - ecx.consider_builtin_tuple_unsize(goal, a_tys, b_tys), - BuiltinImplSource::TupleUnsizing, - ) + result_to_single(ecx.consider_builtin_tuple_unsize(goal, a_tys, b_tys)) } _ => vec![], @@ -707,7 +733,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { a_region: ty::Region<'tcx>, b_data: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>, b_region: ty::Region<'tcx>, - ) -> Vec<(CanonicalResponse<'tcx>, BuiltinImplSource)> { + ) -> Vec<Candidate<'tcx>> { let tcx = self.tcx(); let Goal { predicate: (a_ty, _b_ty), .. } = goal; @@ -715,35 +741,32 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { // If the principal def ids match (or are both none), then we're not doing // trait upcasting. We're just removing auto traits (or shortening the lifetime). if a_data.principal_def_id() == b_data.principal_def_id() { - if let Ok(resp) = self.consider_builtin_upcast_to_principal( + responses.extend(self.consider_builtin_upcast_to_principal( goal, + CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), a_data, a_region, b_data, b_region, a_data.principal(), - ) { - responses.push((resp, BuiltinImplSource::Misc)); - } + )); } else if let Some(a_principal) = a_data.principal() { self.walk_vtable( a_principal.with_self_ty(tcx, a_ty), |ecx, new_a_principal, _, vtable_vptr_slot| { - if let Ok(resp) = ecx.probe_misc_candidate("dyn upcast").enter(|ecx| { - ecx.consider_builtin_upcast_to_principal( - goal, - a_data, - a_region, - b_data, - b_region, - Some(new_a_principal.map_bound(|trait_ref| { - ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref) - })), - ) - }) { - responses - .push((resp, BuiltinImplSource::TraitUpcasting { vtable_vptr_slot })); - } + responses.extend(ecx.consider_builtin_upcast_to_principal( + goal, + CandidateSource::BuiltinImpl(BuiltinImplSource::TraitUpcasting { + vtable_vptr_slot, + }), + a_data, + a_region, + b_data, + b_region, + Some(new_a_principal.map_bound(|trait_ref| { + ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref) + })), + )); }, ); } @@ -756,7 +779,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { goal: Goal<'tcx, (Ty<'tcx>, Ty<'tcx>)>, b_data: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>, b_region: ty::Region<'tcx>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { let tcx = self.tcx(); let Goal { predicate: (a_ty, _), .. } = goal; @@ -765,37 +788,40 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { return Err(NoSolution); } - // Check that the type implements all of the predicates of the trait object. - // (i.e. the principal, all of the associated types match, and any auto traits) - self.add_goals( - GoalSource::ImplWhereBound, - b_data.iter().map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty))), - ); - - // The type must be `Sized` to be unsized. - if let Some(sized_def_id) = tcx.lang_items().sized_trait() { - self.add_goal( + self.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { + // Check that the type implements all of the predicates of the trait object. + // (i.e. the principal, all of the associated types match, and any auto traits) + ecx.add_goals( GoalSource::ImplWhereBound, - goal.with(tcx, ty::TraitRef::new(tcx, sized_def_id, [a_ty])), + b_data.iter().map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty))), ); - } else { - return Err(NoSolution); - } - // The type must outlive the lifetime of the `dyn` we're unsizing into. - self.add_goal(GoalSource::Misc, goal.with(tcx, ty::OutlivesPredicate(a_ty, b_region))); - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + // The type must be `Sized` to be unsized. + if let Some(sized_def_id) = tcx.lang_items().sized_trait() { + ecx.add_goal( + GoalSource::ImplWhereBound, + goal.with(tcx, ty::TraitRef::new(tcx, sized_def_id, [a_ty])), + ); + } else { + return Err(NoSolution); + } + + // The type must outlive the lifetime of the `dyn` we're unsizing into. + ecx.add_goal(GoalSource::Misc, goal.with(tcx, ty::OutlivesPredicate(a_ty, b_region))); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) } fn consider_builtin_upcast_to_principal( &mut self, goal: Goal<'tcx, (Ty<'tcx>, Ty<'tcx>)>, + source: CandidateSource, a_data: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>, a_region: ty::Region<'tcx>, b_data: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>, b_region: ty::Region<'tcx>, upcast_principal: Option<ty::PolyExistentialTraitRef<'tcx>>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { let param_env = goal.param_env; // We may upcast to auto traits that are either explicitly listed in @@ -814,7 +840,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { // having any inference side-effects. We process obligations because // unification may initially succeed due to deferred projection equality. let projection_may_match = - |ecx: &mut Self, + |ecx: &mut EvalCtxt<'_, 'tcx>, source_projection: ty::PolyExistentialProjection<'tcx>, target_projection: ty::PolyExistentialProjection<'tcx>| { source_projection.item_def_id() == target_projection.item_def_id() @@ -828,54 +854,60 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { .is_ok() }; - for bound in b_data { - match bound.skip_binder() { - // Check that a's supertrait (upcast_principal) is compatible - // with the target (b_ty). - ty::ExistentialPredicate::Trait(target_principal) => { - self.eq(param_env, upcast_principal.unwrap(), bound.rebind(target_principal))?; - } - // Check that b_ty's projection is satisfied by exactly one of - // a_ty's projections. First, we look through the list to see if - // any match. If not, error. Then, if *more* than one matches, we - // return ambiguity. Otherwise, if exactly one matches, equate - // it with b_ty's projection. - ty::ExistentialPredicate::Projection(target_projection) => { - let target_projection = bound.rebind(target_projection); - let mut matching_projections = - a_data.projection_bounds().filter(|source_projection| { - projection_may_match(self, *source_projection, target_projection) - }); - let Some(source_projection) = matching_projections.next() else { - return Err(NoSolution); - }; - if matching_projections.next().is_some() { - return self.evaluate_added_goals_and_make_canonical_response( - Certainty::AMBIGUOUS, - ); + self.probe_trait_candidate(source).enter(|ecx| { + for bound in b_data { + match bound.skip_binder() { + // Check that a's supertrait (upcast_principal) is compatible + // with the target (b_ty). + ty::ExistentialPredicate::Trait(target_principal) => { + ecx.eq( + param_env, + upcast_principal.unwrap(), + bound.rebind(target_principal), + )?; } - self.eq(param_env, source_projection, target_projection)?; - } - // Check that b_ty's auto traits are present in a_ty's bounds. - ty::ExistentialPredicate::AutoTrait(def_id) => { - if !a_auto_traits.contains(&def_id) { - return Err(NoSolution); + // Check that b_ty's projection is satisfied by exactly one of + // a_ty's projections. First, we look through the list to see if + // any match. If not, error. Then, if *more* than one matches, we + // return ambiguity. Otherwise, if exactly one matches, equate + // it with b_ty's projection. + ty::ExistentialPredicate::Projection(target_projection) => { + let target_projection = bound.rebind(target_projection); + let mut matching_projections = + a_data.projection_bounds().filter(|source_projection| { + projection_may_match(ecx, *source_projection, target_projection) + }); + let Some(source_projection) = matching_projections.next() else { + return Err(NoSolution); + }; + if matching_projections.next().is_some() { + return ecx.evaluate_added_goals_and_make_canonical_response( + Certainty::AMBIGUOUS, + ); + } + ecx.eq(param_env, source_projection, target_projection)?; + } + // Check that b_ty's auto traits are present in a_ty's bounds. + ty::ExistentialPredicate::AutoTrait(def_id) => { + if !a_auto_traits.contains(&def_id) { + return Err(NoSolution); + } } } } - } - // Also require that a_ty's lifetime outlives b_ty's lifetime. - self.add_goal( - GoalSource::ImplWhereBound, - Goal::new( - self.tcx(), - param_env, - ty::Binder::dummy(ty::OutlivesPredicate(a_region, b_region)), - ), - ); + // Also require that a_ty's lifetime outlives b_ty's lifetime. + ecx.add_goal( + GoalSource::ImplWhereBound, + Goal::new( + ecx.tcx(), + param_env, + ty::Binder::dummy(ty::OutlivesPredicate(a_region, b_region)), + ), + ); - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) } /// We have the following builtin impls for arrays: @@ -891,9 +923,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { goal: Goal<'tcx, (Ty<'tcx>, Ty<'tcx>)>, a_elem_ty: Ty<'tcx>, b_elem_ty: Ty<'tcx>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { self.eq(goal.param_env, a_elem_ty, b_elem_ty)?; - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + self.probe_builtin_trait_candidate(BuiltinImplSource::Misc) + .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } /// We generate a builtin `Unsize` impls for structs with generic parameters only @@ -915,7 +948,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { def: ty::AdtDef<'tcx>, a_args: ty::GenericArgsRef<'tcx>, b_args: ty::GenericArgsRef<'tcx>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { let tcx = self.tcx(); let Goal { predicate: (_a_ty, b_ty), .. } = goal; @@ -957,7 +990,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { ), ), ); - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + self.probe_builtin_trait_candidate(BuiltinImplSource::Misc) + .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } /// We generate the following builtin impl for tuples of all sizes. @@ -975,7 +1009,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { goal: Goal<'tcx, (Ty<'tcx>, Ty<'tcx>)>, a_tys: &'tcx ty::List<Ty<'tcx>>, b_tys: &'tcx ty::List<Ty<'tcx>>, - ) -> QueryResult<'tcx> { + ) -> Result<Candidate<'tcx>, NoSolution> { let tcx = self.tcx(); let Goal { predicate: (_a_ty, b_ty), .. } = goal; @@ -999,7 +1033,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { ), ), ); - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + self.probe_builtin_trait_candidate(BuiltinImplSource::TupleUnsizing) + .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } // Return `Some` if there is an impl (built-in or user provided) that may @@ -1009,7 +1044,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { fn disqualify_auto_trait_candidate_due_to_possible_impl( &mut self, goal: Goal<'tcx, TraitPredicate<'tcx>>, - ) -> Option<QueryResult<'tcx>> { + ) -> Option<Result<Candidate<'tcx>, NoSolution>> { let self_ty = goal.predicate.self_ty(); match *self_ty.kind() { // Stall int and float vars until they are resolved to a concrete @@ -1018,7 +1053,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { // we probably don't want to treat an `impl !AutoTrait for i32` as // disqualifying the built-in auto impl for `i64: AutoTrait` either. ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => { - Some(self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)) + Some(self.forced_ambiguity(MaybeCause::Ambiguity)) } // These types cannot be structurally decomposed into constituent @@ -1039,9 +1074,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { { match self.tcx().coroutine_movability(def_id) { Movability::Static => Some(Err(NoSolution)), - Movability::Movable => { - Some(self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) - } + Movability::Movable => Some( + self.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }), + ), } } @@ -1106,13 +1143,14 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { /// wrapped in one. fn probe_and_evaluate_goal_for_constituent_tys( &mut self, + source: CandidateSource, goal: Goal<'tcx, TraitPredicate<'tcx>>, constituent_tys: impl Fn( &EvalCtxt<'_, 'tcx>, Ty<'tcx>, ) -> Result<Vec<ty::Binder<'tcx, Ty<'tcx>>>, NoSolution>, - ) -> QueryResult<'tcx> { - self.probe_misc_candidate("constituent tys").enter(|ecx| { + ) -> Result<Candidate<'tcx>, NoSolution> { + self.probe_trait_candidate(source).enter(|ecx| { ecx.add_goals( GoalSource::ImplWhereBound, constituent_tys(ecx, goal.predicate.self_ty())? diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index a4208cdc3c6..59725ce9de0 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -6,12 +6,9 @@ use crate::infer::outlives::env::OutlivesEnvironment; use crate::infer::InferOk; -use crate::regions::InferCtxtRegionExt; use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor}; -use crate::solve::{deeply_normalize_for_diagnostics, inspect, FulfillmentCtxt}; -use crate::traits::engine::TraitEngineExt as _; +use crate::solve::{deeply_normalize_for_diagnostics, inspect}; use crate::traits::select::IntercrateAmbiguityCause; -use crate::traits::structural_normalize::StructurallyNormalizeExt; use crate::traits::NormalizeExt; use crate::traits::SkipLeakCheck; use crate::traits::{ @@ -20,30 +17,45 @@ use crate::traits::{ use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{Diag, EmissionGuarantee}; use rustc_hir::def::DefKind; -use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_hir::def_id::DefId; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt}; -use rustc_infer::traits::{util, FulfillmentErrorCode, TraitEngine, TraitEngineExt}; +use rustc_infer::traits::{util, FulfillmentErrorCode}; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal}; use rustc_middle::traits::specialization_graph::OverlapMode; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; -use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt}; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor}; +use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::symbol::sym; use rustc_span::{Span, DUMMY_SP}; use std::fmt::Debug; use std::ops::ControlFlow; use super::error_reporting::suggest_new_overflow_limit; +use super::ObligationCtxt; -/// Whether we do the orphan check relative to this crate or -/// to some remote crate. +/// Whether we do the orphan check relative to this crate or to some remote crate. #[derive(Copy, Clone, Debug)] -enum InCrate { - Local, +pub enum InCrate { + Local { mode: OrphanCheckMode }, Remote, } +#[derive(Copy, Clone, Debug)] +pub enum OrphanCheckMode { + /// Proper orphan check. + Proper, + /// Improper orphan check for backward compatibility. + /// + /// In this mode, type params inside projections are considered to be covered + /// even if the projection may normalize to a type that doesn't actually cover + /// them. This is unsound. See also [#124559] and [#99554]. + /// + /// [#124559]: https://github.com/rust-lang/rust/issues/124559 + /// [#99554]: https://github.com/rust-lang/rust/issues/99554 + Compat, +} + #[derive(Debug, Copy, Clone)] pub enum Conflict { Upstream, @@ -347,23 +359,27 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>( let infcx = selcx.infcx; if infcx.next_trait_solver() { - let mut fulfill_cx = FulfillmentCtxt::new(infcx); - fulfill_cx.register_predicate_obligations(infcx, obligations.iter().cloned()); - + let ocx = ObligationCtxt::new(infcx); + ocx.register_obligations(obligations.iter().cloned()); + let errors_and_ambiguities = ocx.select_all_or_error(); // We only care about the obligations that are *definitely* true errors. // Ambiguities do not prove the disjointness of two impls. - let errors = fulfill_cx.select_where_possible(infcx); + let (errors, ambiguities): (Vec<_>, Vec<_>) = + errors_and_ambiguities.into_iter().partition(|error| error.is_true_error()); + if errors.is_empty() { - let overflow_errors = fulfill_cx.collect_remaining_errors(infcx); - let overflowing_predicates = overflow_errors - .into_iter() - .filter(|e| match e.code { - FulfillmentErrorCode::Ambiguity { overflow: Some(true) } => true, - _ => false, - }) - .map(|e| infcx.resolve_vars_if_possible(e.obligation.predicate)) - .collect(); - IntersectionHasImpossibleObligations::No { overflowing_predicates } + IntersectionHasImpossibleObligations::No { + overflowing_predicates: ambiguities + .into_iter() + .filter(|error| { + matches!( + error.code, + FulfillmentErrorCode::Ambiguity { overflow: Some(true) } + ) + }) + .map(|e| infcx.resolve_vars_if_possible(e.obligation.predicate)) + .collect(), + } } else { IntersectionHasImpossibleObligations::Yes } @@ -575,13 +591,14 @@ fn try_prove_negated_where_clause<'tcx>( // Without this, we over-eagerly register coherence ambiguity candidates when // impl candidates do exist. let ref infcx = root_infcx.fork_with_intercrate(false); - let mut fulfill_cx = FulfillmentCtxt::new(infcx); - - fulfill_cx.register_predicate_obligation( - infcx, - Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, negative_predicate), - ); - if !fulfill_cx.select_all_or_error(infcx).is_empty() { + let ocx = ObligationCtxt::new(infcx); + ocx.register_obligation(Obligation::new( + infcx.tcx, + ObligationCause::dummy(), + param_env, + negative_predicate, + )); + if !ocx.select_all_or_error().is_empty() { return false; } @@ -589,8 +606,7 @@ fn try_prove_negated_where_clause<'tcx>( // if that wasn't implemented just for LocalDefId, and we'd need to do // the normalization ourselves since this is totally fallible... let outlives_env = OutlivesEnvironment::new(param_env); - - let errors = infcx.resolve_regions(&outlives_env); + let errors = ocx.resolve_regions(&outlives_env); if !errors.is_empty() { return false; } @@ -604,19 +620,20 @@ fn try_prove_negated_where_clause<'tcx>( /// This both checks whether any downstream or sibling crates could /// implement it and whether an upstream crate can add this impl /// without breaking backwards compatibility. -#[instrument(level = "debug", skip(tcx, lazily_normalize_ty), ret)] +#[instrument(level = "debug", skip(infcx, lazily_normalize_ty), ret)] pub fn trait_ref_is_knowable<'tcx, E: Debug>( - tcx: TyCtxt<'tcx>, + infcx: &InferCtxt<'tcx>, trait_ref: ty::TraitRef<'tcx>, mut lazily_normalize_ty: impl FnMut(Ty<'tcx>) -> Result<Ty<'tcx>, E>, ) -> Result<Result<(), Conflict>, E> { - if orphan_check_trait_ref(trait_ref, InCrate::Remote, &mut lazily_normalize_ty)?.is_ok() { + if orphan_check_trait_ref(infcx, trait_ref, InCrate::Remote, &mut lazily_normalize_ty)?.is_ok() + { // A downstream or cousin crate is allowed to implement some // generic parameters of this trait-ref. return Ok(Err(Conflict::Downstream)); } - if trait_ref_is_local_or_fundamental(tcx, trait_ref) { + if trait_ref_is_local_or_fundamental(infcx.tcx, trait_ref) { // This is a local or fundamental trait, so future-compatibility // is no concern. We know that downstream/cousin crates are not // allowed to implement a generic parameter of this trait ref, @@ -633,7 +650,14 @@ pub fn trait_ref_is_knowable<'tcx, E: Debug>( // and if we are an intermediate owner, then we don't care // about future-compatibility, which means that we're OK if // we are an owner. - if orphan_check_trait_ref(trait_ref, InCrate::Local, &mut lazily_normalize_ty)?.is_ok() { + if orphan_check_trait_ref( + infcx, + trait_ref, + InCrate::Local { mode: OrphanCheckMode::Proper }, + &mut lazily_normalize_ty, + )? + .is_ok() + { Ok(Ok(())) } else { Ok(Err(Conflict::Upstream)) @@ -644,7 +668,7 @@ pub fn trait_ref_is_local_or_fundamental<'tcx>( tcx: TyCtxt<'tcx>, trait_ref: ty::TraitRef<'tcx>, ) -> bool { - trait_ref.def_id.krate == LOCAL_CRATE || tcx.has_attr(trait_ref.def_id, sym::fundamental) + trait_ref.def_id.is_local() || tcx.has_attr(trait_ref.def_id, sym::fundamental) } #[derive(Debug, Copy, Clone)] @@ -663,31 +687,15 @@ impl From<bool> for IsFirstInputType { } #[derive(Debug)] -pub enum OrphanCheckErr<'tcx> { +pub enum OrphanCheckErr<'tcx, T> { NonLocalInputType(Vec<(Ty<'tcx>, IsFirstInputType)>), - UncoveredTy(Ty<'tcx>, Option<Ty<'tcx>>), + UncoveredTyParams(UncoveredTyParams<'tcx, T>), } -/// Checks the coherence orphan rules. `impl_def_id` should be the -/// `DefId` of a trait impl. To pass, either the trait must be local, or else -/// two conditions must be satisfied: -/// -/// 1. All type parameters in `Self` must be "covered" by some local type constructor. -/// 2. Some local type must appear in `Self`. -#[instrument(level = "debug", skip(tcx), ret)] -pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanCheckErr<'_>> { - // We only except this routine to be invoked on implementations - // of a trait, not inherent implementations. - let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity(); - debug!(?trait_ref); - - // If the *trait* is local to the crate, ok. - if trait_ref.def_id.is_local() { - debug!("trait {:?} is local to current crate", trait_ref.def_id); - return Ok(()); - } - - orphan_check_trait_ref::<!>(trait_ref, InCrate::Local, |ty| Ok(ty)).unwrap() +#[derive(Debug)] +pub struct UncoveredTyParams<'tcx, T> { + pub uncovered: T, + pub local_ty: Option<Ty<'tcx>>, } /// Checks whether a trait-ref is potentially implementable by a crate. @@ -735,6 +743,9 @@ pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanChe /// To check that a local impl follows the orphan rules, we check it in /// InCrate::Local mode, using type parameters for the "generic" types. /// +/// In InCrate::Local mode the orphan check succeeds if the current crate +/// is definitely allowed to implement the given trait (no false positives). +/// /// 2. They ground negative reasoning for coherence. If a user wants to /// write both a conditional blanket impl and a specific impl, we need to /// make sure they do not overlap. For example, if we write @@ -753,6 +764,9 @@ pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanChe /// try to implement this trait-ref. To check for this, we use InCrate::Remote /// mode. That is sound because we already know all the impls from known crates. /// +/// In InCrate::Remote mode the orphan check succeeds if a foreign crate +/// *could* implement the given trait (no false negatives). +/// /// 3. For non-`#[fundamental]` traits, they guarantee that parent crates can /// add "non-blanket" impls without breaking negative reasoning in dependent /// crates. This is the "rebalancing coherence" (RFC 1023) restriction. @@ -776,54 +790,56 @@ pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanChe /// /// Note that this function is never called for types that have both type /// parameters and inference variables. -#[instrument(level = "trace", skip(lazily_normalize_ty), ret)] -fn orphan_check_trait_ref<'tcx, E: Debug>( +#[instrument(level = "trace", skip(infcx, lazily_normalize_ty), ret)] +pub fn orphan_check_trait_ref<'tcx, E: Debug>( + infcx: &InferCtxt<'tcx>, trait_ref: ty::TraitRef<'tcx>, in_crate: InCrate, lazily_normalize_ty: impl FnMut(Ty<'tcx>) -> Result<Ty<'tcx>, E>, -) -> Result<Result<(), OrphanCheckErr<'tcx>>, E> { - if trait_ref.has_infer() && trait_ref.has_param() { - bug!( - "can't orphan check a trait ref with both params and inference variables {:?}", - trait_ref - ); +) -> Result<Result<(), OrphanCheckErr<'tcx, Ty<'tcx>>>, E> { + if trait_ref.has_param() { + bug!("orphan check only expects inference variables: {trait_ref:?}"); } - let mut checker = OrphanChecker::new(in_crate, lazily_normalize_ty); + let mut checker = OrphanChecker::new(infcx, in_crate, lazily_normalize_ty); Ok(match trait_ref.visit_with(&mut checker) { ControlFlow::Continue(()) => Err(OrphanCheckErr::NonLocalInputType(checker.non_local_tys)), - ControlFlow::Break(OrphanCheckEarlyExit::NormalizationFailure(err)) => return Err(err), - ControlFlow::Break(OrphanCheckEarlyExit::ParamTy(ty)) => { - // Does there exist some local type after the `ParamTy`. - checker.search_first_local_ty = true; - if let Some(OrphanCheckEarlyExit::LocalTy(local_ty)) = - trait_ref.visit_with(&mut checker).break_value() - { - Err(OrphanCheckErr::UncoveredTy(ty, Some(local_ty))) - } else { - Err(OrphanCheckErr::UncoveredTy(ty, None)) + ControlFlow::Break(residual) => match residual { + OrphanCheckEarlyExit::NormalizationFailure(err) => return Err(err), + OrphanCheckEarlyExit::UncoveredTyParam(ty) => { + // Does there exist some local type after the `ParamTy`. + checker.search_first_local_ty = true; + let local_ty = match trait_ref.visit_with(&mut checker).break_value() { + Some(OrphanCheckEarlyExit::LocalTy(local_ty)) => Some(local_ty), + _ => None, + }; + Err(OrphanCheckErr::UncoveredTyParams(UncoveredTyParams { + uncovered: ty, + local_ty, + })) } - } - ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(_)) => Ok(()), + OrphanCheckEarlyExit::LocalTy(_) => Ok(()), + }, }) } -struct OrphanChecker<'tcx, F> { +struct OrphanChecker<'a, 'tcx, F> { + infcx: &'a InferCtxt<'tcx>, in_crate: InCrate, in_self_ty: bool, lazily_normalize_ty: F, - /// Ignore orphan check failures and exclusively search for the first - /// local type. + /// Ignore orphan check failures and exclusively search for the first local type. search_first_local_ty: bool, non_local_tys: Vec<(Ty<'tcx>, IsFirstInputType)>, } -impl<'tcx, F, E> OrphanChecker<'tcx, F> +impl<'a, 'tcx, F, E> OrphanChecker<'a, 'tcx, F> where F: FnOnce(Ty<'tcx>) -> Result<Ty<'tcx>, E>, { - fn new(in_crate: InCrate, lazily_normalize_ty: F) -> Self { + fn new(infcx: &'a InferCtxt<'tcx>, in_crate: InCrate, lazily_normalize_ty: F) -> Self { OrphanChecker { + infcx, in_crate, in_self_ty: true, lazily_normalize_ty, @@ -837,17 +853,20 @@ where ControlFlow::Continue(()) } - fn found_param_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<OrphanCheckEarlyExit<'tcx, E>> { + fn found_uncovered_ty_param( + &mut self, + ty: Ty<'tcx>, + ) -> ControlFlow<OrphanCheckEarlyExit<'tcx, E>> { if self.search_first_local_ty { - ControlFlow::Continue(()) - } else { - ControlFlow::Break(OrphanCheckEarlyExit::ParamTy(t)) + return ControlFlow::Continue(()); } + + ControlFlow::Break(OrphanCheckEarlyExit::UncoveredTyParam(ty)) } fn def_id_is_local(&mut self, def_id: DefId) -> bool { match self.in_crate { - InCrate::Local => def_id.is_local(), + InCrate::Local { .. } => def_id.is_local(), InCrate::Remote => false, } } @@ -855,23 +874,25 @@ where enum OrphanCheckEarlyExit<'tcx, E> { NormalizationFailure(E), - ParamTy(Ty<'tcx>), + UncoveredTyParam(Ty<'tcx>), LocalTy(Ty<'tcx>), } -impl<'tcx, F, E> TypeVisitor<TyCtxt<'tcx>> for OrphanChecker<'tcx, F> +impl<'a, 'tcx, F, E> TypeVisitor<TyCtxt<'tcx>> for OrphanChecker<'a, 'tcx, F> where F: FnMut(Ty<'tcx>) -> Result<Ty<'tcx>, E>, { type Result = ControlFlow<OrphanCheckEarlyExit<'tcx, E>>; + fn visit_region(&mut self, _r: ty::Region<'tcx>) -> Self::Result { ControlFlow::Continue(()) } fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { - // Need to lazily normalize here in with `-Znext-solver=coherence`. + let ty = self.infcx.shallow_resolve(ty); let ty = match (self.lazily_normalize_ty)(ty) { - Ok(ty) => ty, + Ok(norm_ty) if norm_ty.is_ty_var() => ty, + Ok(norm_ty) => norm_ty, Err(err) => return ControlFlow::Break(OrphanCheckEarlyExit::NormalizationFailure(err)), }; @@ -889,19 +910,46 @@ where | ty::Slice(..) | ty::RawPtr(..) | ty::Never - | ty::Tuple(..) - | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..) => { - self.found_non_local_ty(ty) + | ty::Tuple(..) => self.found_non_local_ty(ty), + + ty::Param(..) => bug!("unexpected ty param"), + + ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) => { + match self.in_crate { + InCrate::Local { .. } => self.found_uncovered_ty_param(ty), + // The inference variable might be unified with a local + // type in that remote crate. + InCrate::Remote => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)), + } } - ty::Param(..) => self.found_param_ty(ty), + ty::Alias(kind @ (ty::Projection | ty::Inherent | ty::Weak), ..) => { + if ty.has_type_flags(ty::TypeFlags::HAS_TY_PARAM) { + bug!("unexpected ty param in alias ty"); + } - ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) => match self.in_crate { - InCrate::Local => self.found_non_local_ty(ty), - // The inference variable might be unified with a local - // type in that remote crate. - InCrate::Remote => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)), - }, + if ty.has_type_flags( + ty::TypeFlags::HAS_TY_PLACEHOLDER + | ty::TypeFlags::HAS_TY_BOUND + | ty::TypeFlags::HAS_TY_INFER, + ) { + match self.in_crate { + InCrate::Local { mode } => match kind { + ty::Projection if let OrphanCheckMode::Compat = mode => { + ControlFlow::Continue(()) + } + _ => self.found_uncovered_ty_param(ty), + }, + InCrate::Remote => { + // The inference variable might be unified with a local + // type in that remote crate. + ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)) + } + } + } else { + ControlFlow::Continue(()) + } + } // For fundamental types, we just look inside of them. ty::Ref(_, ty, _) => ty.visit_with(self), @@ -1078,32 +1126,26 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { // Add ambiguity causes for unknowable goals. let mut ambiguity_cause = None; for cand in goal.candidates() { - // FIXME: boiiii, using string comparisions here sure is scuffed. - if let inspect::ProbeKind::MiscCandidate { - name: "coherence unknowable", + if let inspect::ProbeKind::TraitCandidate { + source: CandidateSource::CoherenceUnknowable, result: Ok(_), } = cand.kind() { - let lazily_normalize_ty = |ty: Ty<'tcx>| { - let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(infcx); + let lazily_normalize_ty = |mut ty: Ty<'tcx>| { if matches!(ty.kind(), ty::Alias(..)) { - // FIXME(-Znext-solver=coherence): we currently don't - // normalize opaque types here, resulting in diverging behavior - // for TAITs. - match infcx - .at(&ObligationCause::dummy(), param_env) - .structurally_normalize(ty, &mut *fulfill_cx) - { - Ok(ty) => Ok(ty), - Err(_errs) => Err(()), + let ocx = ObligationCtxt::new(infcx); + ty = ocx + .structurally_normalize(&ObligationCause::dummy(), param_env, ty) + .map_err(|_| ())?; + if !ocx.select_where_possible().is_empty() { + return Err(()); } - } else { - Ok(ty) } + Ok(ty) }; infcx.probe(|_| { - match trait_ref_is_knowable(infcx.tcx, trait_ref, lazily_normalize_ty) { + match trait_ref_is_knowable(infcx, trait_ref, lazily_normalize_ty) { Err(()) => {} Ok(Ok(())) => warn!("expected an unknowable trait ref: {trait_ref:?}"), Ok(Err(conflict)) => { diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 9fbec174ce8..551c8e7702e 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -7,6 +7,7 @@ use crate::regions::InferCtxtRegionExt; use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt; use crate::traits::error_reporting::TypeErrCtxtExt; use crate::traits::NormalizeExt; +use crate::traits::StructurallyNormalizeExt; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -15,10 +16,12 @@ use rustc_infer::infer::canonical::{ Canonical, CanonicalQueryResponse, CanonicalVarValues, QueryResponse, }; use rustc_infer::infer::outlives::env::OutlivesEnvironment; +use rustc_infer::infer::RegionResolutionError; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; use rustc_infer::traits::{ FulfillmentError, Obligation, ObligationCause, PredicateObligation, TraitEngineExt as _, }; +use rustc_macros::extension; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::error::TypeError; @@ -116,6 +119,17 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { self.infcx.at(cause, param_env).deeply_normalize(value, &mut **self.engine.borrow_mut()) } + pub fn structurally_normalize( + &self, + cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + value: Ty<'tcx>, + ) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>> { + self.infcx + .at(cause, param_env) + .structurally_normalize(value, &mut **self.engine.borrow_mut()) + } + pub fn eq<T: ToTrace<'tcx>>( &self, cause: &ObligationCause<'tcx>, @@ -181,6 +195,18 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { self.engine.borrow_mut().select_all_or_error(self.infcx) } + /// Returns the not-yet-processed and stalled obligations from the + /// `ObligationCtxt`. + /// + /// Takes ownership of the context as doing operations such as + /// [`ObligationCtxt::eq`] afterwards will result in other obligations + /// getting ignored. You can make a new `ObligationCtxt` if this + /// needs to be done in a loop, for example. + #[must_use] + pub fn into_pending_obligations(self) -> Vec<PredicateObligation<'tcx>> { + self.engine.borrow().pending_obligations() + } + /// Resolves regions and reports errors. /// /// Takes ownership of the context as doing trait solving afterwards @@ -198,6 +224,18 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { } } + /// Resolves regions and reports errors. + /// + /// Takes ownership of the context as doing trait solving afterwards + /// will result in region constraints getting ignored. + #[must_use] + pub fn resolve_regions( + self, + outlives_env: &OutlivesEnvironment<'tcx>, + ) -> Vec<RegionResolutionError<'tcx>> { + self.infcx.resolve_regions(outlives_env) + } + pub fn assumed_wf_types_and_report_errors( &self, param_env: ty::ParamEnv<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs index d41d43bad71..9e5701ffffc 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs @@ -4,6 +4,7 @@ use crate::traits::{Obligation, ObligationCause, ObligationCtxt}; use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, Diag}; use rustc_hir as hir; use rustc_hir::Node; +use rustc_macros::extension; use rustc_middle::ty::{self, Ty}; use rustc_span::{Span, DUMMY_SP}; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index b418219fb95..07bd209e623 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -9,6 +9,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_errors::{codes::*, struct_span_code_err, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_macros::{extension, LintDiagnostic}; use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt}; use rustc_parse_format::{ParseMode, Parser, Piece, Position}; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index d24942f3f46..3d2574ac92b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -26,6 +26,7 @@ use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId use rustc_infer::infer::error_reporting::TypeErrCtxt; use rustc_infer::infer::type_variable::TypeVariableOrigin; use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk}; +use rustc_macros::extension; use rustc_middle::hir::map; use rustc_middle::traits::IsConstable; use rustc_middle::ty::error::TypeError::{self, Sorts}; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 1971136e54c..e50cb2af4b8 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -32,6 +32,7 @@ use rustc_hir::intravisit::Visitor; use rustc_hir::{GenericParam, Item, Node}; use rustc_infer::infer::error_reporting::TypeErrCtxt; use rustc_infer::infer::{InferOk, TypeTrace}; +use rustc_macros::extension; use rustc_middle::traits::select::OverflowError; use rustc_middle::traits::SignatureMismatchData; use rustc_middle::ty::abstract_const::NotConstEvaluatable; @@ -780,7 +781,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { && self.fallback_has_occurred { let predicate = trait_predicate.map_bound(|trait_pred| { - trait_pred.with_self_ty(self.tcx, Ty::new_unit(self.tcx)) + trait_pred.with_self_ty(self.tcx, tcx.types.unit) }); let unit_obligation = obligation.with(tcx, predicate); if self.predicate_may_hold(&unit_obligation) { diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 8cd9f39d5d8..1f10cb71543 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -73,7 +73,7 @@ pub struct PendingPredicateObligation<'tcx> { // `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_pointer_width = "64")] -static_assert_size!(PendingPredicateObligation<'_>, 72); +rustc_data_structures::static_assert_size!(PendingPredicateObligation<'_>, 72); impl<'tcx> FulfillmentContext<'tcx> { /// Creates a new fulfillment context. diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 88ebf8754d3..56f8b4b9cdb 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -41,8 +41,9 @@ use rustc_span::Span; use std::fmt::Debug; use std::ops::ControlFlow; -pub use self::coherence::{add_placeholder_note, orphan_check, overlapping_impls}; -pub use self::coherence::{IsFirstInputType, OrphanCheckErr, OverlapResult}; +pub use self::coherence::{add_placeholder_note, orphan_check_trait_ref, overlapping_impls}; +pub use self::coherence::{InCrate, IsFirstInputType, UncoveredTyParams}; +pub use self::coherence::{OrphanCheckErr, OrphanCheckMode, OverlapResult}; pub use self::engine::{ObligationCtxt, TraitEngineExt}; pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation}; pub use self::normalize::NormalizeExt; diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index b4969926f64..43f4fa8e81c 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -8,6 +8,7 @@ use rustc_infer::infer::at::At; use rustc_infer::infer::InferOk; use rustc_infer::traits::PredicateObligation; use rustc_infer::traits::{FulfillmentError, Normalized, Obligation, TraitEngine}; +use rustc_macros::extension; use rustc_middle::traits::{ObligationCause, ObligationCauseCode, Reveal}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFolder}; use rustc_middle::ty::{TypeFoldable, TypeSuperFoldable, TypeVisitable, TypeVisitableExt}; diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 5e1343b50ce..0e15dd27537 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -519,7 +519,7 @@ fn virtual_call_violations_for_method<'tcx>( // e.g., `Rc<()>` let unit_receiver_ty = - receiver_for_self_ty(tcx, receiver_ty, Ty::new_unit(tcx), method.def_id); + receiver_for_self_ty(tcx, receiver_ty, tcx.types.unit, method.def_id); match abi_of_ty(unit_receiver_ty) { Some(Abi::Scalar(..)) => (), diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index c4110df45db..1dd2ada3356 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -3,6 +3,7 @@ use crate::traits::{ObligationCause, ObligationCtxt}; use rustc_data_structures::fx::FxIndexSet; use rustc_infer::infer::resolve::OpportunisticRegionResolver; use rustc_infer::infer::InferOk; +use rustc_macros::extension; use rustc_middle::infer::canonical::{OriginalQueryValues, QueryRegionConstraints}; use rustc_middle::ty::{self, ParamEnv, Ty, TypeFolder, TypeVisitableExt}; use rustc_span::def_id::LocalDefId; diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs index 16ee9fadab4..87d240cf8ac 100644 --- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs +++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs @@ -1,8 +1,10 @@ -use rustc_infer::traits::{TraitEngine, TraitEngineExt}; +use rustc_macros::extension; use crate::infer::canonical::OriginalQueryValues; use crate::infer::InferCtxt; -use crate::traits::{EvaluationResult, OverflowError, PredicateObligation, SelectionContext}; +use crate::traits::{ + EvaluationResult, ObligationCtxt, OverflowError, PredicateObligation, SelectionContext, +}; #[extension(pub trait InferCtxtExt<'tcx>)] impl<'tcx> InferCtxt<'tcx> { @@ -66,21 +68,22 @@ impl<'tcx> InferCtxt<'tcx> { if self.next_trait_solver() { self.probe(|snapshot| { - let mut fulfill_cx = crate::solve::FulfillmentCtxt::new(self); - fulfill_cx.register_predicate_obligation(self, obligation.clone()); - // True errors - // FIXME(-Znext-solver): Overflows are reported as ambig here, is that OK? - if !fulfill_cx.select_where_possible(self).is_empty() { - Ok(EvaluationResult::EvaluatedToErr) - } else if !fulfill_cx.select_all_or_error(self).is_empty() { - Ok(EvaluationResult::EvaluatedToAmbig) - } else if self.opaque_types_added_in_snapshot(snapshot) { - Ok(EvaluationResult::EvaluatedToOkModuloOpaqueTypes) + let ocx = ObligationCtxt::new(self); + ocx.register_obligation(obligation.clone()); + let mut result = EvaluationResult::EvaluatedToOk; + for error in ocx.select_all_or_error() { + if error.is_true_error() { + return Ok(EvaluationResult::EvaluatedToErr); + } else { + result = result.max(EvaluationResult::EvaluatedToAmbig); + } + } + if self.opaque_types_added_in_snapshot(snapshot) { + result = result.max(EvaluationResult::EvaluatedToOkModuloOpaqueTypes); } else if self.region_constraints_added_in_snapshot(snapshot) { - Ok(EvaluationResult::EvaluatedToOkModuloRegions) - } else { - Ok(EvaluationResult::EvaluatedToOk) + result = result.max(EvaluationResult::EvaluatedToOkModuloRegions); } + Ok(result) }) } else { assert!(!self.intercrate); diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index c520e699bf5..8b39c23da56 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -13,6 +13,7 @@ use crate::traits::{ObligationCause, PredicateObligation, Reveal}; use rustc_data_structures::sso::SsoHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_infer::traits::Normalized; +use rustc_macros::extension; use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor}; diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index 423ed0f7105..f7e84a46639 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -7,6 +7,7 @@ use rustc_infer::infer::canonical::Canonical; use rustc_infer::infer::outlives::components::{push_outlives_components, Component}; use rustc_infer::infer::resolve::OpportunisticRegionResolver; use rustc_infer::traits::query::OutlivesBound; +use rustc_macros::{HashStable, TypeFoldable, TypeVisitable}; use rustc_middle::infer::canonical::CanonicalQueryResponse; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeFolder, TypeVisitableExt}; diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs index 07587e37411..3e7aa52dcfe 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs @@ -3,6 +3,7 @@ use crate::traits::query::dropck_outlives::{ compute_dropck_outlives_inner, trivial_dropck_outlives, }; use crate::traits::ObligationCtxt; +use rustc_macros::{HashStable, TypeFoldable, TypeVisitable}; use rustc_middle::traits::query::{DropckOutlivesResult, NoSolution}; use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt}; diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index fc12fed3537..18cb3184fe1 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1497,7 +1497,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // bound regions. let trait_ref = predicate.skip_binder().trait_ref; - coherence::trait_ref_is_knowable::<!>(self.tcx(), trait_ref, |ty| Ok(ty)).unwrap() + coherence::trait_ref_is_knowable::<!>(self.infcx, trait_ref, |ty| Ok(ty)).unwrap() } /// Returns `true` if the global caches can be used. @@ -2001,7 +2001,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // any associated items and there are no where-clauses. // // We can just arbitrarily drop one of the impls. - Some(ty::ImplOverlapKind::Issue33140) => { + Some(ty::ImplOverlapKind::FutureCompatOrderDepTraitObjects) => { assert_eq!(other.evaluation, victim.evaluation); DropVictim::Yes } diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 46a0a4eb5ef..390e711a18d 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -453,7 +453,7 @@ fn report_conflicting_impls<'tcx>( overlap.trait_ref.print_trait_sugared(), overlap.self_ty.map_or_else(String::new, |ty| format!(" for type `{ty}`")), match used_to_be_allowed { - Some(FutureCompatOverlapErrorKind::Issue33140) => ": (E0119)", + Some(FutureCompatOverlapErrorKind::OrderDepTraitObjects) => ": (E0119)", _ => "", } ) @@ -480,7 +480,7 @@ fn report_conflicting_impls<'tcx>( } Some(kind) => { let lint = match kind { - FutureCompatOverlapErrorKind::Issue33140 => ORDER_DEPENDENT_TRAIT_OBJECTS, + FutureCompatOverlapErrorKind::OrderDepTraitObjects => ORDER_DEPENDENT_TRAIT_OBJECTS, FutureCompatOverlapErrorKind::LeakCheck => COHERENCE_LEAK_CHECK, }; tcx.node_span_lint( diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs index dba014d58b0..b6c2fcb46eb 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs @@ -3,6 +3,7 @@ use super::OverlapError; use crate::traits; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; +use rustc_macros::extension; use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams}; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; @@ -10,7 +11,7 @@ pub use rustc_middle::traits::specialization_graph::*; #[derive(Copy, Clone, Debug)] pub enum FutureCompatOverlapErrorKind { - Issue33140, + OrderDepTraitObjects, LeakCheck, } @@ -149,10 +150,10 @@ impl<'tcx> Children { { match overlap_kind { ty::ImplOverlapKind::Permitted { marker: _ } => {} - ty::ImplOverlapKind::Issue33140 => { + ty::ImplOverlapKind::FutureCompatOrderDepTraitObjects => { *last_lint_mut = Some(FutureCompatOverlapError { error: create_overlap_error(overlap), - kind: FutureCompatOverlapErrorKind::Issue33140, + kind: FutureCompatOverlapErrorKind::OrderDepTraitObjects, }); } } diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs index 5746e20490d..64ab8378abb 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs @@ -1,6 +1,7 @@ use rustc_infer::infer::at::At; use rustc_infer::infer::type_variable::TypeVariableOrigin; use rustc_infer::traits::{FulfillmentError, TraitEngine}; +use rustc_macros::extension; use rustc_middle::ty::{self, Ty}; use crate::traits::{NormalizeExt, Obligation}; diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index a8ca7d164a0..b2ba7854f18 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -10,7 +10,7 @@ use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{self, ImplSubject, ToPredicate, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_span::Span; -use smallvec::SmallVec; +use smallvec::{smallvec, SmallVec}; pub use rustc_infer::traits::util::*; diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 46a68508753..178f3c63ef7 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -10,7 +10,7 @@ use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::GenericArgs; use rustc_middle::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry}; use rustc_span::{sym, Span}; -use smallvec::SmallVec; +use smallvec::{smallvec, SmallVec}; use std::fmt::Debug; use std::ops::ControlFlow; diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index b2b5c6cd909..b96b1b67a74 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -4,14 +4,15 @@ // general routines. use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits::{FulfillmentErrorCode, TraitEngineExt as _}; +use rustc_infer::traits::FulfillmentErrorCode; +use rustc_middle::bug; use rustc_middle::traits::CodegenObligationError; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::{ - ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine, TraitEngineExt, - Unimplemented, + ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext, Unimplemented, }; +use tracing::debug; /// Attempts to resolve an obligation to an `ImplSource`. The result is /// a shallow `ImplSource` resolution, meaning that we do not @@ -49,15 +50,15 @@ pub fn codegen_select_candidate<'tcx>( // Currently, we use a fulfillment context to completely resolve // all nested obligations. This is because they can inform the // inference of the impl's type parameters. - let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(&infcx); - let impl_source = selection.map(|predicate| { - fulfill_cx.register_predicate_obligation(&infcx, predicate); + let ocx = ObligationCtxt::new(&infcx); + let impl_source = selection.map(|obligation| { + ocx.register_obligation(obligation); }); // In principle, we only need to do this so long as `impl_source` // contains unbound type parameters. It could be a slight // optimization to stop iterating early. - let errors = fulfill_cx.select_all_or_error(&infcx); + let errors = ocx.select_all_or_error(); if !errors.is_empty() { // `rustc_monomorphize::collector` assumes there are no type errors. // Cycle errors are the only post-monomorphization errors possible; emit them now so diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs index f40c3614e1c..55abd6098ec 100644 --- a/compiler/rustc_traits/src/dropck_outlives.rs +++ b/compiler/rustc_traits/src/dropck_outlives.rs @@ -2,6 +2,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::DefId; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::TyCtxtInferExt; +use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::traits::query::{DropckConstraint, DropckOutlivesResult}; use rustc_middle::ty::GenericArgs; @@ -11,6 +12,7 @@ use rustc_trait_selection::traits::query::dropck_outlives::{ compute_dropck_outlives_inner, dtorck_constraint_for_ty_inner, }; use rustc_trait_selection::traits::query::{CanonicalTyGoal, NoSolution}; +use tracing::debug; pub(crate) fn provide(p: &mut Providers) { *p = Providers { dropck_outlives, adt_dtorck_constraint, ..*p }; diff --git a/compiler/rustc_traits/src/evaluate_obligation.rs b/compiler/rustc_traits/src/evaluate_obligation.rs index ce22da23fff..c9ad096c6e9 100644 --- a/compiler/rustc_traits/src/evaluate_obligation.rs +++ b/compiler/rustc_traits/src/evaluate_obligation.rs @@ -6,6 +6,7 @@ use rustc_trait_selection::traits::query::CanonicalPredicateGoal; use rustc_trait_selection::traits::{ EvaluationResult, Obligation, ObligationCause, OverflowError, SelectionContext, TraitQueryMode, }; +use tracing::debug; pub(crate) fn provide(p: &mut Providers) { *p = Providers { evaluate_obligation, ..*p }; diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs index e73bbf6048e..bc5436f76f1 100644 --- a/compiler/rustc_traits/src/lib.rs +++ b/compiler/rustc_traits/src/lib.rs @@ -2,11 +2,6 @@ #![recursion_limit = "256"] -#[macro_use] -extern crate tracing; -#[macro_use] -extern crate rustc_middle; - mod codegen; mod dropck_outlives; mod evaluate_obligation; diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index 0576fe01027..c5ebc2d26a7 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -4,6 +4,7 @@ use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; use rustc_trait_selection::traits::{Normalized, ObligationCause}; +use tracing::debug; pub(crate) fn provide(p: &mut Providers) { *p = Providers { diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index 92a19fb9119..559c05eb3e7 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -10,6 +10,7 @@ use rustc_trait_selection::traits::query::{ use rustc_trait_selection::traits::{ self, FulfillmentErrorCode, ObligationCause, SelectionContext, }; +use tracing::debug; pub(crate) fn provide(p: &mut Providers) { *p = Providers { diff --git a/compiler/rustc_transmute/src/layout/dfa.rs b/compiler/rustc_transmute/src/layout/dfa.rs index 77d5a48f158..3378d1c6754 100644 --- a/compiler/rustc_transmute/src/layout/dfa.rs +++ b/compiler/rustc_transmute/src/layout/dfa.rs @@ -2,6 +2,7 @@ use super::{nfa, Byte, Nfa, Ref}; use crate::Map; use std::fmt; use std::sync::atomic::{AtomicU32, Ordering}; +use tracing::instrument; #[derive(PartialEq, Clone, Debug)] pub(crate) struct Dfa<R> diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs index edd3227210b..604b68d2cd4 100644 --- a/compiler/rustc_transmute/src/layout/tree.rs +++ b/compiler/rustc_transmute/src/layout/tree.rs @@ -266,7 +266,7 @@ pub(crate) mod rustc { ty::Ref(lifetime, ty, mutability) => { let ty_and_layout = cx.layout_of(*ty)?; - let align = ty_and_layout.align.abi.bytes() as usize; + let align = ty_and_layout.align.abi.bytes_usize(); let size = ty_and_layout.size.bytes_usize(); Ok(Tree::Ref(Ref { lifetime: *lifetime, diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index 12312271646..8d7d81d8f73 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -2,9 +2,6 @@ #![feature(never_type)] #![allow(unused_variables)] -#[macro_use] -extern crate tracing; - pub(crate) use rustc_data_structures::fx::{FxIndexMap as Map, FxIndexSet as Set}; pub mod layout; diff --git a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs index 2789fe8f6b1..dee5a72c3bc 100644 --- a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs +++ b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs @@ -1,3 +1,5 @@ +use tracing::{debug, instrument, trace}; + pub(crate) mod query_context; #[cfg(test)] mod tests; diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index f0cea1f0baf..c6b83628506 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -854,7 +854,7 @@ fn make_thin_self_ptr<'tcx>( // we now have a type like `*mut RcBox<dyn Trait>` // change its layout to that of `*mut ()`, a thin pointer, but keep the same type // this is understood as a special case elsewhere in the compiler - let unit_ptr_ty = Ty::new_mut_ptr(tcx, Ty::new_unit(tcx)); + let unit_ptr_ty = Ty::new_mut_ptr(tcx, tcx.types.unit); TyAndLayout { ty: fat_pointer_ty, diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 2139b8c665b..fa1085c7cd7 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -243,37 +243,39 @@ fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamE tcx.param_env(def_id).with_reveal_all_normalized(tcx) } -/// If `def_id` is an issue 33140 hack impl, returns its self type; otherwise, returns `None`. +/// If the given trait impl enables exploiting the former order dependence of trait objects, +/// returns its self type; otherwise, returns `None`. /// -/// See [`ty::ImplOverlapKind::Issue33140`] for more details. -fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<EarlyBinder<Ty<'_>>> { - debug!("issue33140_self_ty({:?})", def_id); - - let impl_ = tcx - .impl_trait_header(def_id) - .unwrap_or_else(|| bug!("issue33140_self_ty called on inherent impl {:?}", def_id)); +/// See [`ty::ImplOverlapKind::FutureCompatOrderDepTraitObjects`] for more details. +#[instrument(level = "debug", skip(tcx))] +fn self_ty_of_trait_impl_enabling_order_dep_trait_object_hack( + tcx: TyCtxt<'_>, + def_id: DefId, +) -> Option<EarlyBinder<Ty<'_>>> { + let impl_ = + tcx.impl_trait_header(def_id).unwrap_or_else(|| bug!("called on inherent impl {def_id:?}")); let trait_ref = impl_.trait_ref.skip_binder(); - debug!("issue33140_self_ty({:?}), trait-ref={:?}", def_id, trait_ref); + debug!(?trait_ref); let is_marker_like = impl_.polarity == ty::ImplPolarity::Positive && tcx.associated_item_def_ids(trait_ref.def_id).is_empty(); // Check whether these impls would be ok for a marker trait. if !is_marker_like { - debug!("issue33140_self_ty - not marker-like!"); + debug!("not marker-like!"); return None; } // impl must be `impl Trait for dyn Marker1 + Marker2 + ...` if trait_ref.args.len() != 1 { - debug!("issue33140_self_ty - impl has args!"); + debug!("impl has args!"); return None; } let predicates = tcx.predicates_of(def_id); if predicates.parent.is_some() || !predicates.predicates.is_empty() { - debug!("issue33140_self_ty - impl has predicates {:?}!", predicates); + debug!(?predicates, "impl has predicates!"); return None; } @@ -284,10 +286,10 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<EarlyBinder<Ty<' }; if self_ty_matches { - debug!("issue33140_self_ty - MATCHES!"); + debug!("MATCHES!"); Some(EarlyBinder::bind(self_ty)) } else { - debug!("issue33140_self_ty - non-matching self type"); + debug!("non-matching self type"); None } } @@ -351,7 +353,7 @@ pub(crate) fn provide(providers: &mut Providers) { adt_sized_constraint, param_env, param_env_reveal_all_normalized, - issue33140_self_ty, + self_ty_of_trait_impl_enabling_order_dep_trait_object_hack, defaultness, unsizing_params_for_adt, ..*providers diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index 06a5051956a..f041c5831fc 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -1,5 +1,7 @@ use rustc_ast_ir::try_visit; use rustc_ast_ir::visit::VisitorResult; +#[cfg(feature = "nightly")] +use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; use std::fmt; use std::hash::Hash; diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index 5b08140db3a..c1506f9252b 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -1,5 +1,7 @@ #[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +#[cfg(feature = "nightly")] +use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; use std::fmt; use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx}; diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index 997b410f819..6a1ac642b70 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -1,4 +1,4 @@ -bitflags! { +bitflags::bitflags! { /// Flags that we track on types. These flags are propagated upwards /// through the type during type construction, so that we can quickly check /// whether the type has various kinds of types in it without recursing diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index a5b33a8125d..ef7437c2542 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -8,14 +8,10 @@ #[cfg(feature = "nightly")] extern crate self as rustc_type_ir; -#[macro_use] -extern crate bitflags; -#[cfg(feature = "nightly")] -#[macro_use] -extern crate rustc_macros; - #[cfg(feature = "nightly")] use rustc_data_structures::sync::Lrc; +#[cfg(feature = "nightly")] +use rustc_macros::{Decodable, Encodable, HashStable_NoContext}; use std::fmt; use std::hash::Hash; #[cfg(not(feature = "nightly"))] diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs index 112f617fe16..5260d9061cf 100644 --- a/compiler/rustc_type_ir/src/predicate_kind.rs +++ b/compiler/rustc_type_ir/src/predicate_kind.rs @@ -1,5 +1,7 @@ use rustc_ast_ir::try_visit; use rustc_ast_ir::visit::VisitorResult; +#[cfg(feature = "nightly")] +use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable}; use std::fmt; use crate::fold::{FallibleTypeFolder, TypeFoldable}; diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index e1247e2661a..d1b86b495e9 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -1,5 +1,7 @@ #[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +#[cfg(feature = "nightly")] +use rustc_macros::{TyDecodable, TyEncodable}; use std::fmt; use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx}; diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 3924b371bbc..f2e4afecc40 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -3,6 +3,8 @@ use rustc_ast_ir::try_visit; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; #[cfg(feature = "nightly")] use rustc_data_structures::unify::{EqUnifyValue, UnifyKey}; +#[cfg(feature = "nightly")] +use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable}; use std::fmt; use crate::fold::{FallibleTypeFolder, TypeFoldable}; diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs index e82d1f4813e..231d9ba49a3 100644 --- a/compiler/stable_mir/src/compiler_interface.rs +++ b/compiler/stable_mir/src/compiler_interface.rs @@ -221,7 +221,7 @@ pub trait Context { // A thread local variable that stores a pointer to the tables mapping between TyCtxt // datastructures and stable MIR datastructures -scoped_thread_local!(static TLV: Cell<*const ()>); +scoped_tls::scoped_thread_local!(static TLV: Cell<*const ()>); pub fn run<F, T>(context: &dyn Context, f: F) -> Result<T, Error> where diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs index d1a2948ea77..d9f988935ab 100644 --- a/compiler/stable_mir/src/lib.rs +++ b/compiler/stable_mir/src/lib.rs @@ -16,8 +16,6 @@ //! //! The goal is to eventually be published on //! [crates.io](https://crates.io). -#[macro_use] -extern crate scoped_tls; use std::fmt; use std::fmt::Debug; diff --git a/config.example.toml b/config.example.toml index 5c1fac7672a..3b76952504f 100644 --- a/config.example.toml +++ b/config.example.toml @@ -254,6 +254,10 @@ # executing the debuginfo test suite. #gdb = "gdb" +# The path to (or name of) the LLDB executable to use. This is only used for +# executing the debuginfo test suite. +#lldb = "lldb" + # The node.js executable to use. Note that this is only used for the emscripten # target when running tests, otherwise this can be omitted. #nodejs = "node" diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs index b6b6246baa6..42f8a08a9e4 100644 --- a/library/alloc/src/borrow.rs +++ b/library/alloc/src/borrow.rs @@ -4,9 +4,9 @@ use core::cmp::Ordering; use core::hash::{Hash, Hasher}; -use core::ops::Deref; #[cfg(not(no_global_oom_handling))] use core::ops::{Add, AddAssign}; +use core::ops::{Deref, DerefPure}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::borrow::{Borrow, BorrowMut}; @@ -343,6 +343,9 @@ where } } +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl<B: ?Sized + ToOwned> DerefPure for Cow<'_, B> where B::Owned: Borrow<B> {} + #[stable(feature = "rust1", since = "1.0.0")] impl<B: ?Sized> Eq for Cow<'_, B> where B: Eq + ToOwned {} diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index 6a64eaf576b..f143e557871 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -41,6 +41,7 @@ use crate::sync::Arc; /// or anything that implements <code>[Into]<[Vec]<[u8]>></code> (for /// example, you can build a `CString` straight out of a [`String`] or /// a <code>&[str]</code>, since both implement that trait). +/// You can create a `CString` from a literal with `CString::from(c"Text")`. /// /// The [`CString::new`] method will actually check that the provided <code>&[[u8]]</code> /// does not have 0 bytes in the middle, and return an error if it @@ -1069,27 +1070,22 @@ impl CStr { /// /// # Examples /// - /// Calling `to_string_lossy` on a `CStr` containing valid UTF-8: + /// Calling `to_string_lossy` on a `CStr` containing valid UTF-8. The leading + /// `c` on the string literal denotes a `CStr`. /// /// ``` /// use std::borrow::Cow; - /// use std::ffi::CStr; /// - /// let cstr = CStr::from_bytes_with_nul(b"Hello World\0") - /// .expect("CStr::from_bytes_with_nul failed"); - /// assert_eq!(cstr.to_string_lossy(), Cow::Borrowed("Hello World")); + /// assert_eq!(c"Hello World".to_string_lossy(), Cow::Borrowed("Hello World")); /// ``` /// /// Calling `to_string_lossy` on a `CStr` containing invalid UTF-8: /// /// ``` /// use std::borrow::Cow; - /// use std::ffi::CStr; /// - /// let cstr = CStr::from_bytes_with_nul(b"Hello \xF0\x90\x80World\0") - /// .expect("CStr::from_bytes_with_nul failed"); /// assert_eq!( - /// cstr.to_string_lossy(), + /// c"Hello \xF0\x90\x80World".to_string_lossy(), /// Cow::Owned(String::from("Hello �World")) as Cow<'_, str> /// ); /// ``` diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 2bd8fca7e01..b93936869b3 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -137,7 +137,6 @@ #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array)] #![feature(maybe_uninit_uninit_array_transpose)] -#![feature(non_null_convenience)] #![feature(panic_internals)] #![feature(pattern)] #![feature(ptr_internals)] @@ -166,9 +165,6 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(associated_type_bounds))] -#![cfg_attr(bootstrap, feature(inline_const))] -#![cfg_attr(not(bootstrap), rustc_preserve_ub_checks)] #![cfg_attr(not(test), feature(coroutine_trait))] #![cfg_attr(test, feature(panic_update_hook))] #![cfg_attr(test, feature(test))] @@ -199,6 +195,7 @@ #![feature(unboxed_closures)] #![feature(unsized_fn_params)] #![feature(with_negative_coherence)] +#![rustc_preserve_ub_checks] // tidy-alphabetical-end // // Rustdoc features: diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index d88639c4092..c0d292cd208 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -53,7 +53,7 @@ pub use core::str::{RSplit, Split}; pub use core::str::{RSplitN, SplitN}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::str::{RSplitTerminator, SplitTerminator}; -#[stable(feature = "utf8_chunks", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "utf8_chunks", since = "1.79.0")] pub use core::str::{Utf8Chunk, Utf8Chunks}; /// Note: `str` in `Concat<str>` is not meaningful here. diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 7c9f13e30ff..2a859ad55ee 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -1382,7 +1382,7 @@ impl String { /// Shortens this `String` to the specified length. /// - /// If `new_len` is greater than the string's current length, this has no + /// If `new_len` is greater than or equal to the string's current length, this has no /// effect. /// /// Note that this method has no effect on the allocated capacity diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index b5175a8487f..0eae4ca4b8b 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -1,4 +1,3 @@ -#![cfg_attr(bootstrap, feature(associated_type_bounds))] #![feature(allocator_api)] #![feature(alloc_layout_extra)] #![feature(iter_array_chunks)] diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index ae0436bc520..4b491ffdafa 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -239,7 +239,7 @@ use crate::cmp::Ordering; use crate::fmt::{self, Debug, Display}; use crate::marker::{PhantomData, Unsize}; use crate::mem::{self, size_of}; -use crate::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn}; +use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn}; use crate::ptr::{self, NonNull}; mod lazy; @@ -1452,6 +1452,9 @@ impl<T: ?Sized> Deref for Ref<'_, T> { } } +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl<T: ?Sized> DerefPure for Ref<'_, T> {} + impl<'b, T: ?Sized> Ref<'b, T> { /// Copies a `Ref`. /// @@ -1844,6 +1847,9 @@ impl<T: ?Sized> DerefMut for RefMut<'_, T> { } } +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl<T: ?Sized> DerefPure for RefMut<'_, T> {} + #[unstable(feature = "coerce_unsized", issue = "18598")] impl<'b, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<RefMut<'b, U>> for RefMut<'b, T> {} diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 2fd9e17c994..fc6022ab753 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -379,7 +379,7 @@ pub struct AssertParamIsEq<T: Eq + ?Sized> { // This is a lang item only so that `BinOp::Cmp` in MIR can return it. // It has no special behaviour, but does require that the three variants // `Less`/`Equal`/`Greater` remain `-1_i8`/`0_i8`/`+1_i8` respectively. -#[cfg_attr(not(bootstrap), lang = "Ordering")] +#[lang = "Ordering"] #[repr(i8)] pub enum Ordering { /// An ordering where a compared value is less than another. @@ -852,7 +852,7 @@ pub trait Ord: Eq + PartialOrd<Self> { #[stable(feature = "ord_max_min", since = "1.21.0")] #[inline] #[must_use] - #[cfg_attr(not(bootstrap), rustc_diagnostic_item = "cmp_ord_max")] + #[rustc_diagnostic_item = "cmp_ord_max"] fn max(self, other: Self) -> Self where Self: Sized, @@ -873,7 +873,7 @@ pub trait Ord: Eq + PartialOrd<Self> { #[stable(feature = "ord_max_min", since = "1.21.0")] #[inline] #[must_use] - #[cfg_attr(not(bootstrap), rustc_diagnostic_item = "cmp_ord_min")] + #[rustc_diagnostic_item = "cmp_ord_min"] fn min(self, other: Self) -> Self where Self: Sized, @@ -1160,7 +1160,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(bootstrap), rustc_diagnostic_item = "cmp_partialord_cmp")] + #[rustc_diagnostic_item = "cmp_partialord_cmp"] fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>; /// This method tests less than (for `self` and `other`) and is used by the `<` operator. @@ -1175,7 +1175,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(bootstrap), rustc_diagnostic_item = "cmp_partialord_lt")] + #[rustc_diagnostic_item = "cmp_partialord_lt"] fn lt(&self, other: &Rhs) -> bool { matches!(self.partial_cmp(other), Some(Less)) } @@ -1193,7 +1193,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(bootstrap), rustc_diagnostic_item = "cmp_partialord_le")] + #[rustc_diagnostic_item = "cmp_partialord_le"] fn le(&self, other: &Rhs) -> bool { matches!(self.partial_cmp(other), Some(Less | Equal)) } @@ -1210,7 +1210,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(bootstrap), rustc_diagnostic_item = "cmp_partialord_gt")] + #[rustc_diagnostic_item = "cmp_partialord_gt"] fn gt(&self, other: &Rhs) -> bool { matches!(self.partial_cmp(other), Some(Greater)) } @@ -1228,7 +1228,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(bootstrap), rustc_diagnostic_item = "cmp_partialord_ge")] + #[rustc_diagnostic_item = "cmp_partialord_ge"] fn ge(&self, other: &Rhs) -> bool { matches!(self.partial_cmp(other), Some(Greater | Equal)) } @@ -1558,14 +1558,7 @@ mod impls { impl PartialOrd for $t { #[inline] fn partial_cmp(&self, other: &$t) -> Option<Ordering> { - #[cfg(bootstrap)] - { - Some(self.cmp(other)) - } - #[cfg(not(bootstrap))] - { - Some(crate::intrinsics::three_way_compare(*self, *other)) - } + Some(crate::intrinsics::three_way_compare(*self, *other)) } #[inline(always)] fn lt(&self, other: &$t) -> bool { (*self) < (*other) } @@ -1581,18 +1574,7 @@ mod impls { impl Ord for $t { #[inline] fn cmp(&self, other: &$t) -> Ordering { - #[cfg(bootstrap)] - { - // The order here is important to generate more optimal assembly. - // See <https://github.com/rust-lang/rust/issues/63758> for more info. - if *self < *other { Less } - else if *self == *other { Equal } - else { Greater } - } - #[cfg(not(bootstrap))] - { - crate::intrinsics::three_way_compare(*self, *other) - } + crate::intrinsics::three_way_compare(*self, *other) } } )*) diff --git a/library/core/src/default.rs b/library/core/src/default.rs index e717a8d022f..4524b352ec8 100644 --- a/library/core/src/default.rs +++ b/library/core/src/default.rs @@ -178,9 +178,7 @@ default_impl! { i32, 0, "Returns the default value of `0`" } default_impl! { i64, 0, "Returns the default value of `0`" } default_impl! { i128, 0, "Returns the default value of `0`" } -#[cfg(not(bootstrap))] default_impl! { f16, 0.0f16, "Returns the default value of `0.0`" } default_impl! { f32, 0.0f32, "Returns the default value of `0.0`" } default_impl! { f64, 0.0f64, "Returns the default value of `0.0`" } -#[cfg(not(bootstrap))] default_impl! { f128, 0.0f128, "Returns the default value of `0.0`" } diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index f4f33f8584b..297f52e756b 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -23,28 +23,32 @@ use crate::str; /// /// This type represents a borrowed reference to a nul-terminated /// array of bytes. It can be constructed safely from a <code>&[[u8]]</code> -/// slice, or unsafely from a raw `*const c_char`. It can then be -/// converted to a Rust <code>&[str]</code> by performing UTF-8 validation, or -/// into an owned `CString`. +/// slice, or unsafely from a raw `*const c_char`. It can be expressed as a +/// literal in the form `c"Hello world"`. +/// +/// The `CStr` can then be converted to a Rust <code>&[str]</code> by performing +/// UTF-8 validation, or into an owned `CString`. /// /// `&CStr` is to `CString` as <code>&[str]</code> is to `String`: the former /// in each pair are borrowed references; the latter are owned /// strings. /// /// Note that this structure does **not** have a guaranteed layout (the `repr(transparent)` -/// notwithstanding) and is not recommended to be placed in the signatures of FFI functions. -/// Instead, safe wrappers of FFI functions may leverage the unsafe [`CStr::from_ptr`] constructor -/// to provide a safe interface to other consumers. +/// notwithstanding) and should not be placed in the signatures of FFI functions. +/// Instead, safe wrappers of FFI functions may leverage [`CStr::as_ptr`] and the unsafe +/// [`CStr::from_ptr`] constructor to provide a safe interface to other consumers. /// /// # Examples /// /// Inspecting a foreign C string: /// -/// ```ignore (extern-declaration) +/// ``` /// use std::ffi::CStr; /// use std::os::raw::c_char; /// +/// # /* Extern functions are awkward in doc comments - fake it instead /// extern "C" { fn my_string() -> *const c_char; } +/// # */ unsafe extern "C" fn my_string() -> *const c_char { c"hello".as_ptr() } /// /// unsafe { /// let slice = CStr::from_ptr(my_string()); @@ -54,12 +58,14 @@ use crate::str; /// /// Passing a Rust-originating C string: /// -/// ```ignore (extern-declaration) +/// ``` /// use std::ffi::{CString, CStr}; /// use std::os::raw::c_char; /// /// fn work(data: &CStr) { +/// # /* Extern functions are awkward in doc comments - fake it instead /// extern "C" { fn work_with(data: *const c_char); } +/// # */ unsafe extern "C" fn work_with(s: *const c_char) {} /// /// unsafe { work_with(data.as_ptr()) } /// } @@ -70,11 +76,13 @@ use crate::str; /// /// Converting a foreign C string into a Rust `String`: /// -/// ```ignore (extern-declaration) +/// ``` /// use std::ffi::CStr; /// use std::os::raw::c_char; /// +/// # /* Extern functions are awkward in doc comments - fake it instead /// extern "C" { fn my_string() -> *const c_char; } +/// # */ unsafe extern "C" fn my_string() -> *const c_char { c"hello".as_ptr() } /// /// fn my_string_safe() -> String { /// let cstr = unsafe { CStr::from_ptr(my_string()) }; @@ -241,16 +249,16 @@ impl CStr { /// /// # Examples /// - /// ```ignore (extern-declaration) + /// ``` /// use std::ffi::{c_char, CStr}; /// - /// extern "C" { - /// fn my_string() -> *const c_char; + /// fn my_string() -> *const c_char { + /// c"hello".as_ptr() /// } /// /// unsafe { /// let slice = CStr::from_ptr(my_string()); - /// println!("string returned: {}", slice.to_str().unwrap()); + /// assert_eq!(slice.to_str().unwrap(), "hello"); /// } /// ``` /// @@ -264,6 +272,8 @@ impl CStr { /// BYTES.as_ptr().cast() /// }; /// const HELLO: &CStr = unsafe { CStr::from_ptr(HELLO_PTR) }; + /// + /// assert_eq!(c"Hello, world!", HELLO); /// ``` /// /// [valid]: core::ptr#safety @@ -528,7 +538,7 @@ impl CStr { #[inline] #[must_use] #[doc(alias("len", "strlen"))] - #[stable(feature = "cstr_count_bytes", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "cstr_count_bytes", since = "1.79.0")] #[rustc_const_unstable(feature = "const_cstr_from_ptr", issue = "113219")] pub const fn count_bytes(&self) -> usize { self.inner.len() - 1 @@ -549,6 +559,7 @@ impl CStr { /// /// let empty_cstr = CStr::from_bytes_with_nul(b"\0")?; /// assert!(empty_cstr.is_empty()); + /// assert!(c"".is_empty()); /// # Ok(()) /// # } /// ``` diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index cbdae2ac766..27dacbb23d9 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -213,7 +213,7 @@ impl fmt::Debug for c_void { not(target_arch = "s390x"), not(target_arch = "x86_64") ), - all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios", target_os = "tvos")), + all(target_arch = "aarch64", target_vendor = "apple"), target_family = "wasm", target_os = "uefi", windows, @@ -241,7 +241,7 @@ pub struct VaListImpl<'f> { not(target_arch = "s390x"), not(target_arch = "x86_64") ), - all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios", target_os = "tvos")), + all(target_arch = "aarch64", target_vendor = "apple"), target_family = "wasm", target_os = "uefi", windows, @@ -265,7 +265,7 @@ impl<'f> fmt::Debug for VaListImpl<'f> { /// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf #[cfg(all( target_arch = "aarch64", - not(any(target_os = "macos", target_os = "ios", target_os = "tvos")), + not(target_vendor = "apple"), not(target_os = "uefi"), not(windows), ))] @@ -362,10 +362,7 @@ pub struct VaList<'a, 'f: 'a> { not(target_arch = "s390x"), not(target_arch = "x86_64") ), - all( - target_arch = "aarch64", - any(target_os = "macos", target_os = "ios", target_os = "tvos") - ), + all(target_arch = "aarch64", target_vendor = "apple"), target_family = "wasm", target_os = "uefi", windows, @@ -379,10 +376,7 @@ pub struct VaList<'a, 'f: 'a> { target_arch = "s390x", target_arch = "x86_64" ), - any( - not(target_arch = "aarch64"), - not(any(target_os = "macos", target_os = "ios", target_os = "tvos")) - ), + any(not(target_arch = "aarch64"), not(target_vendor = "apple")), not(target_family = "wasm"), not(target_os = "uefi"), not(windows), @@ -399,7 +393,7 @@ pub struct VaList<'a, 'f: 'a> { not(target_arch = "s390x"), not(target_arch = "x86_64") ), - all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios", target_os = "tvos")), + all(target_arch = "aarch64", target_vendor = "apple"), target_family = "wasm", target_os = "uefi", windows, @@ -425,10 +419,7 @@ impl<'f> VaListImpl<'f> { target_arch = "s390x", target_arch = "x86_64" ), - any( - not(target_arch = "aarch64"), - not(any(target_os = "macos", target_os = "ios", target_os = "tvos")) - ), + any(not(target_arch = "aarch64"), not(target_vendor = "apple")), not(target_family = "wasm"), not(target_os = "uefi"), not(windows), diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs index c3bd18e30aa..873cccc7e96 100644 --- a/library/core/src/future/mod.rs +++ b/library/core/src/future/mod.rs @@ -12,7 +12,6 @@ use crate::ptr::NonNull; use crate::task::Context; -#[cfg(not(bootstrap))] mod async_drop; mod future; mod into_future; @@ -38,7 +37,6 @@ pub use ready::{ready, Ready}; #[stable(feature = "future_poll_fn", since = "1.64.0")] pub use poll_fn::{poll_fn, PollFn}; -#[cfg(not(bootstrap))] #[unstable(feature = "async_drop", issue = "none")] pub use async_drop::{async_drop, async_drop_in_place, AsyncDrop, AsyncDropInPlace}; diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 7ace874fa90..d1450bf12ce 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -987,6 +987,7 @@ pub const unsafe fn assume(b: bool) { #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] #[rustc_nounwind] +#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_checks_ub)] pub const fn likely(b: bool) -> bool { b } @@ -1006,6 +1007,7 @@ pub const fn likely(b: bool) -> bool { #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] #[rustc_nounwind] +#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_checks_ub)] pub const fn unlikely(b: bool) -> bool { b } @@ -1128,7 +1130,7 @@ extern "rust-intrinsic" { /// any safety invariants. /// /// Consider using [`core::panic::Location::caller`] instead. - #[rustc_const_stable(feature = "const_caller_location", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_caller_location", since = "1.79.0")] #[rustc_safe_intrinsic] #[rustc_nounwind] pub fn caller_location() -> &'static crate::panic::Location<'static>; @@ -1987,18 +1989,11 @@ extern "rust-intrinsic" { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `count_ones` method. For example, /// [`u32::count_ones`] - #[cfg(not(bootstrap))] #[rustc_const_stable(feature = "const_ctpop", since = "1.40.0")] #[rustc_safe_intrinsic] #[rustc_nounwind] pub fn ctpop<T: Copy>(x: T) -> u32; - #[cfg(bootstrap)] - #[rustc_const_stable(feature = "const_ctpop", since = "1.40.0")] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn ctpop<T: Copy>(x: T) -> T; - /// Returns the number of leading unset bits (zeroes) in an integer type `T`. /// /// Note that, unlike most intrinsics, this is safe to call; @@ -2035,18 +2030,11 @@ extern "rust-intrinsic" { /// let num_leading = ctlz(x); /// assert_eq!(num_leading, 16); /// ``` - #[cfg(not(bootstrap))] #[rustc_const_stable(feature = "const_ctlz", since = "1.40.0")] #[rustc_safe_intrinsic] #[rustc_nounwind] pub fn ctlz<T: Copy>(x: T) -> u32; - #[cfg(bootstrap)] - #[rustc_const_stable(feature = "const_ctlz", since = "1.40.0")] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn ctlz<T: Copy>(x: T) -> T; - /// Like `ctlz`, but extra-unsafe as it returns `undef` when /// given an `x` with value `0`. /// @@ -2064,16 +2052,10 @@ extern "rust-intrinsic" { /// let num_leading = unsafe { ctlz_nonzero(x) }; /// assert_eq!(num_leading, 3); /// ``` - #[cfg(not(bootstrap))] #[rustc_const_stable(feature = "constctlz", since = "1.50.0")] #[rustc_nounwind] pub fn ctlz_nonzero<T: Copy>(x: T) -> u32; - #[cfg(bootstrap)] - #[rustc_const_stable(feature = "constctlz", since = "1.50.0")] - #[rustc_nounwind] - pub fn ctlz_nonzero<T: Copy>(x: T) -> T; - /// Returns the number of trailing unset bits (zeroes) in an integer type `T`. /// /// Note that, unlike most intrinsics, this is safe to call; @@ -2110,18 +2092,11 @@ extern "rust-intrinsic" { /// let num_trailing = cttz(x); /// assert_eq!(num_trailing, 16); /// ``` - #[cfg(not(bootstrap))] #[rustc_const_stable(feature = "const_cttz", since = "1.40.0")] #[rustc_safe_intrinsic] #[rustc_nounwind] pub fn cttz<T: Copy>(x: T) -> u32; - #[cfg(bootstrap)] - #[rustc_const_stable(feature = "const_cttz", since = "1.40.0")] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn cttz<T: Copy>(x: T) -> T; - /// Like `cttz`, but extra-unsafe as it returns `undef` when /// given an `x` with value `0`. /// @@ -2139,16 +2114,10 @@ extern "rust-intrinsic" { /// let num_trailing = unsafe { cttz_nonzero(x) }; /// assert_eq!(num_trailing, 3); /// ``` - #[cfg(not(bootstrap))] #[rustc_const_stable(feature = "const_cttz_nonzero", since = "1.53.0")] #[rustc_nounwind] pub fn cttz_nonzero<T: Copy>(x: T) -> u32; - #[cfg(bootstrap)] - #[rustc_const_stable(feature = "const_cttz_nonzero", since = "1.53.0")] - #[rustc_nounwind] - pub fn cttz_nonzero<T: Copy>(x: T) -> T; - /// Reverses the bytes in an integer type `T`. /// /// Note that, unlike most intrinsics, this is safe to call; @@ -2186,7 +2155,6 @@ extern "rust-intrinsic" { /// large and difficult to optimize. /// /// The stabilized version of this intrinsic is [`Ord::cmp`]. - #[cfg(not(bootstrap))] #[rustc_const_unstable(feature = "const_three_way_compare", issue = "none")] #[rustc_safe_intrinsic] pub fn three_way_compare<T: Copy>(lhs: T, rhs: T) -> crate::cmp::Ordering; @@ -2269,7 +2237,6 @@ extern "rust-intrinsic" { /// Safe wrappers for this intrinsic are available on the integer /// primitives via the `checked_shl` method. For example, /// [`u32::checked_shl`] - #[cfg(not(bootstrap))] #[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")] #[rustc_nounwind] pub fn unchecked_shl<T: Copy, U: Copy>(x: T, y: U) -> T; @@ -2279,7 +2246,6 @@ extern "rust-intrinsic" { /// Safe wrappers for this intrinsic are available on the integer /// primitives via the `checked_shr` method. For example, /// [`u32::checked_shr`] - #[cfg(not(bootstrap))] #[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")] #[rustc_nounwind] pub fn unchecked_shr<T: Copy, U: Copy>(x: T, y: U) -> T; @@ -2289,7 +2255,7 @@ extern "rust-intrinsic" { /// /// The stable counterpart of this intrinsic is `unchecked_add` on the various /// integer types, such as [`u16::unchecked_add`] and [`i64::unchecked_add`]. - #[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "unchecked_math", since = "1.79.0")] #[rustc_nounwind] pub fn unchecked_add<T: Copy>(x: T, y: T) -> T; @@ -2298,7 +2264,7 @@ extern "rust-intrinsic" { /// /// The stable counterpart of this intrinsic is `unchecked_sub` on the various /// integer types, such as [`u16::unchecked_sub`] and [`i64::unchecked_sub`]. - #[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "unchecked_math", since = "1.79.0")] #[rustc_nounwind] pub fn unchecked_sub<T: Copy>(x: T, y: T) -> T; @@ -2307,7 +2273,7 @@ extern "rust-intrinsic" { /// /// The stable counterpart of this intrinsic is `unchecked_mul` on the various /// integer types, such as [`u16::unchecked_mul`] and [`i64::unchecked_mul`]. - #[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "unchecked_math", since = "1.79.0")] #[rustc_nounwind] pub fn unchecked_mul<T: Copy>(x: T, y: T) -> T; @@ -2321,18 +2287,11 @@ extern "rust-intrinsic" { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `rotate_left` method. For example, /// [`u32::rotate_left`] - #[cfg(not(bootstrap))] #[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")] #[rustc_safe_intrinsic] #[rustc_nounwind] pub fn rotate_left<T: Copy>(x: T, shift: u32) -> T; - #[cfg(bootstrap)] - #[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn rotate_left<T: Copy>(x: T, y: T) -> T; - /// Performs rotate right. /// /// Note that, unlike most intrinsics, this is safe to call; @@ -2343,18 +2302,11 @@ extern "rust-intrinsic" { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `rotate_right` method. For example, /// [`u32::rotate_right`] - #[cfg(not(bootstrap))] #[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")] #[rustc_safe_intrinsic] #[rustc_nounwind] pub fn rotate_right<T: Copy>(x: T, shift: u32) -> T; - #[cfg(bootstrap)] - #[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn rotate_right<T: Copy>(x: T, y: T) -> T; - /// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits. /// /// Note that, unlike most intrinsics, this is safe to call; @@ -2507,12 +2459,6 @@ extern "rust-intrinsic" { #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] #[rustc_nounwind] pub fn ptr_offset_from_unsigned<T>(ptr: *const T, base: *const T) -> usize; - - #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - #[cfg(bootstrap)] - pub fn ptr_guaranteed_cmp<T>(ptr: *const T, other: *const T) -> u8; } /// See documentation of `<*const T>::guaranteed_eq` for details. @@ -2522,10 +2468,10 @@ extern "rust-intrinsic" { #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] -#[cfg(not(bootstrap))] #[rustc_nounwind] #[rustc_do_not_const_check] #[inline] +#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_checks_ub)] pub const fn ptr_guaranteed_cmp<T>(ptr: *const T, other: *const T) -> u8 { (ptr == other) as u8 } @@ -2581,28 +2527,6 @@ extern "rust-intrinsic" { #[rustc_safe_intrinsic] #[rustc_nounwind] pub fn black_box<T>(dummy: T) -> T; - - #[rustc_nounwind] - #[cfg(bootstrap)] - pub fn vtable_size(ptr: *const ()) -> usize; - - /// `ptr` must point to a vtable. - /// The intrinsic will return the alignment stored in that vtable. - #[rustc_nounwind] - #[cfg(bootstrap)] - pub fn vtable_align(ptr: *const ()) -> usize; - - #[rustc_const_unstable(feature = "const_eval_select", issue = "none")] - #[rustc_safe_intrinsic] - #[cfg(bootstrap)] - pub fn const_eval_select<ARG: Tuple, F, G, RET>( - arg: ARG, - called_in_const: F, - called_at_rt: G, - ) -> RET - where - G: FnOnce<ARG, Output = RET>, - F: FnOnce<ARG, Output = RET>; } /// Selects which function to call depending on the context. @@ -2637,11 +2561,9 @@ extern "rust-intrinsic" { /// #![feature(const_eval_select)] /// #![feature(core_intrinsics)] /// # #![allow(internal_features)] -/// # #![cfg_attr(bootstrap, allow(unused))] /// use std::intrinsics::const_eval_select; /// /// // Standard library -/// # #[cfg(not(bootstrap))] /// pub const fn inconsistent() -> i32 { /// fn runtime() -> i32 { 1 } /// const fn compiletime() -> i32 { 2 } @@ -2650,8 +2572,6 @@ extern "rust-intrinsic" { /// // and `runtime`. /// const_eval_select((), compiletime, runtime) /// } -/// # #[cfg(bootstrap)] -/// # pub const fn inconsistent() -> i32 { 0 } /// /// // User Crate /// const X: i32 = inconsistent(); @@ -2661,9 +2581,7 @@ extern "rust-intrinsic" { /// /// Currently such an assertion would always succeed; until Rust decides /// otherwise, that principle should not be violated. -#[rustc_const_unstable(feature = "const_eval_select", issue = "none")] -#[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg(not(bootstrap))] +#[rustc_const_unstable(feature = "const_eval_select", issue = "124625")] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn const_eval_select<ARG: Tuple, F, G, RET>( @@ -2717,10 +2635,45 @@ where /// particular value, ever. However, the compiler will generally make it /// return `true` only if the value of the argument is actually known. /// -/// When calling this in a `const fn`, both paths must be semantically -/// equivalent, that is, the result of the `true` branch and the `false` -/// branch must return the same value and have the same side-effects *no -/// matter what*. +/// # Stability concerns +/// +/// While it is safe to call, this intrinsic may behave differently in +/// a `const` context than otherwise. See the [`const_eval_select`] +/// documentation for an explanation of the issues this can cause. Unlike +/// `const_eval_select`, this intrinsic isn't guaranteed to behave +/// deterministically even in a `const` context. +/// +/// # Type Requirements +/// +/// `T` must be either a `bool`, a `char`, a primitive numeric type (e.g. `f32`, +/// but not `NonZeroISize`), or any thin pointer (e.g. `*mut String`). +/// Any other argument types *may* cause a compiler error. +/// +/// ## Pointers +/// +/// When the input is a pointer, only the pointer itself is +/// ever considered. The pointee has no effect. Currently, these functions +/// behave identically: +/// +/// ``` +/// #![feature(is_val_statically_known)] +/// #![feature(core_intrinsics)] +/// # #![allow(internal_features)] +/// #![feature(strict_provenance)] +/// use std::intrinsics::is_val_statically_known; +/// +/// fn foo(x: &i32) -> bool { +/// is_val_statically_known(x) +/// } +/// +/// fn bar(x: &i32) -> bool { +/// is_val_statically_known( +/// (x as *const i32).addr() +/// ) +/// } +/// # _ = foo(&5_i32); +/// # _ = bar(&5_i32); +/// ``` #[rustc_const_unstable(feature = "is_val_statically_known", issue = "none")] #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] @@ -2741,7 +2694,7 @@ pub const fn is_val_statically_known<T: Copy>(_arg: T) -> bool { /// `x` and `y` are readable and writable as `T`, and non-overlapping. #[rustc_nounwind] #[inline] -#[cfg_attr(not(bootstrap), rustc_intrinsic)] +#[rustc_intrinsic] // This has fallback `const fn` MIR, so shouldn't need stability, see #122652 #[rustc_const_unstable(feature = "const_typed_swap", issue = "none")] pub const unsafe fn typed_swap<T>(x: *mut T, y: *mut T) { @@ -2766,8 +2719,8 @@ pub const unsafe fn typed_swap<T>(x: *mut T, y: *mut T) { #[rustc_const_unstable(feature = "const_ub_checks", issue = "none")] #[unstable(feature = "core_intrinsics", issue = "none")] #[inline(always)] -#[cfg_attr(not(bootstrap), rustc_intrinsic)] // just make it a regular fn in bootstrap -pub(crate) const fn ub_checks() -> bool { +#[rustc_intrinsic] +pub const fn ub_checks() -> bool { cfg!(debug_assertions) } @@ -2783,8 +2736,10 @@ pub(crate) const fn ub_checks() -> bool { #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_nounwind] #[rustc_intrinsic] +#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_checks_ub)] pub const unsafe fn const_allocate(_size: usize, _align: usize) -> *mut u8 { - // const eval overrides this function, but runtime code should always just return null pointers. + // const eval overrides this function, but runtime code for now just returns null pointers. + // See <https://github.com/rust-lang/rust/issues/93935>. crate::ptr::null_mut() } @@ -2802,7 +2757,10 @@ pub const unsafe fn const_allocate(_size: usize, _align: usize) -> *mut u8 { #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_nounwind] #[rustc_intrinsic] -pub const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} +#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_checks_ub)] +pub const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) { + // Runtime NOP +} /// `ptr` must point to a vtable. /// The intrinsic will return the size stored in that vtable. @@ -2810,7 +2768,6 @@ pub const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] -#[cfg(not(bootstrap))] pub unsafe fn vtable_size(_ptr: *const ()) -> usize { unreachable!() } @@ -2821,7 +2778,6 @@ pub unsafe fn vtable_size(_ptr: *const ()) -> usize { #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] -#[cfg(not(bootstrap))] pub unsafe fn vtable_align(_ptr: *const ()) -> usize { unreachable!() } @@ -2836,7 +2792,6 @@ pub unsafe fn vtable_align(_ptr: *const ()) -> usize { #[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] -#[cfg(not(bootstrap))] pub const fn aggregate_raw_ptr<P: AggregateRawPtr<D, Metadata = M>, D, M>(_data: D, _meta: M) -> P { // To implement a fallback we'd have to assume the layout of the pointer, // but the whole point of this intrinsic is that we shouldn't do that. diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs index eeff4ec609a..ceea6790129 100644 --- a/library/core/src/intrinsics/simd.rs +++ b/library/core/src/intrinsics/simd.rs @@ -540,12 +540,8 @@ extern "rust-intrinsic" { /// `T` must be a vector of pointers. /// /// `U` must be a vector of `usize` with the same length as `T`. - #[cfg(not(bootstrap))] #[rustc_nounwind] pub fn simd_expose_provenance<T, U>(ptr: T) -> U; - #[cfg(bootstrap)] - #[rustc_nounwind] - pub fn simd_expose_addr<T, U>(ptr: T) -> U; /// Create a vector of pointers from a vector of addresses. /// @@ -553,11 +549,7 @@ extern "rust-intrinsic" { /// /// `U` must be a vector of pointers, with the same length as `T`. #[rustc_nounwind] - #[cfg(not(bootstrap))] pub fn simd_with_exposed_provenance<T, U>(addr: T) -> U; - #[rustc_nounwind] - #[cfg(bootstrap)] - pub fn simd_from_exposed_addr<T, U>(addr: T) -> U; /// Swap bytes of each element. /// @@ -663,8 +655,3 @@ extern "rust-intrinsic" { #[rustc_nounwind] pub fn simd_flog<T>(a: T) -> T; } - -#[cfg(bootstrap)] -pub use simd_expose_addr as simd_expose_provenance; -#[cfg(bootstrap)] -pub use simd_from_exposed_addr as simd_with_exposed_provenance; diff --git a/library/core/src/iter/sources/from_coroutine.rs b/library/core/src/iter/sources/from_coroutine.rs index 9bac9037a02..710ba504ded 100644 --- a/library/core/src/iter/sources/from_coroutine.rs +++ b/library/core/src/iter/sources/from_coroutine.rs @@ -14,7 +14,7 @@ use crate::pin::Pin; /// #![feature(coroutines)] /// #![feature(iter_from_coroutine)] /// -/// let it = std::iter::from_coroutine(#[cfg_attr(not(bootstrap), coroutine)] || { +/// let it = std::iter::from_coroutine(#[coroutine] || { /// yield 1; /// yield 2; /// yield 3; diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index 2ebbe2bf274..563781230c0 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -169,7 +169,7 @@ pub trait FromIterator<A>: Sized { /// assert_eq!(lengths, [1, 1, 3, 1]); /// # Ok(()) } /// ``` -#[stable(feature = "from_iterator_for_tuple", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "from_iterator_for_tuple", since = "1.79.0")] impl<A, B, AE, BE> FromIterator<(AE, BE)> for (A, B) where A: Default + Extend<AE>, diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 7c1c6122efe..cee99e28b5a 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -974,6 +974,7 @@ pub trait Iterator { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_do_not_const_check] + #[cfg_attr(not(test), rustc_diagnostic_item = "enumerate_method")] fn enumerate(self) -> Enumerate<Self> where Self: Sized, diff --git a/library/core/src/iter/traits/marker.rs b/library/core/src/iter/traits/marker.rs index ad4d63d83b5..2e756a6dd67 100644 --- a/library/core/src/iter/traits/marker.rs +++ b/library/core/src/iter/traits/marker.rs @@ -28,7 +28,7 @@ pub unsafe trait TrustedFused {} #[rustc_unsafe_specialization_marker] // FIXME: this should be a #[marker] and have another blanket impl for T: TrustedFused // but that ICEs iter::Fuse specializations. -#[cfg_attr(not(bootstrap), lang = "fused_iterator")] +#[lang = "fused_iterator"] pub trait FusedIterator: Iterator {} #[stable(feature = "fused", since = "1.26.0")] diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 6925a7d1da1..dcf68b36c7a 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -90,7 +90,7 @@ ))] #![no_core] #![rustc_coherence_is_core] -#![cfg_attr(not(bootstrap), rustc_preserve_ub_checks)] +#![rustc_preserve_ub_checks] // // Lints: #![deny(rust_2021_incompatible_or_patterns)] @@ -109,7 +109,6 @@ // // Library features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(associated_type_bounds))] #![feature(array_ptr_get)] #![feature(asm_experimental_arch)] #![feature(char_indices_offset)] @@ -180,7 +179,6 @@ #![feature(isqrt)] #![feature(link_cfg)] #![feature(maybe_uninit_uninit_array)] -#![feature(non_null_convenience)] #![feature(offset_of_enum)] #![feature(offset_of_nested)] #![feature(panic_internals)] @@ -188,11 +186,11 @@ #![feature(ptr_metadata)] #![feature(set_ptr_value)] #![feature(slice_ptr_get)] -#![feature(split_at_checked)] #![feature(str_internals)] #![feature(str_split_inclusive_remainder)] #![feature(str_split_remainder)] #![feature(strict_provenance)] +#![feature(ub_checks)] #![feature(unchecked_shifts)] #![feature(utf16_extra)] #![feature(utf16_extra_const)] @@ -201,7 +199,6 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(inline_const))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] @@ -370,7 +367,8 @@ pub mod hint; pub mod intrinsics; pub mod mem; pub mod ptr; -mod ub_checks; +#[unstable(feature = "ub_checks", issue = "none")] +pub mod ub_checks; /* Core language traits */ @@ -401,7 +399,6 @@ pub mod net; pub mod option; pub mod panic; pub mod panicking; -#[cfg(not(bootstrap))] #[unstable(feature = "core_pattern_types", issue = "none")] pub mod pat; pub mod pin; diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 6da05a1ca86..2ddedfa37fe 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1711,11 +1711,11 @@ pub(crate) mod builtin { issue = "23416", reason = "placeholder syntax for type ascription" )] + #[rustfmt::skip] pub macro type_ascribe($expr:expr, $ty:ty) { builtin # type_ascribe($expr, $ty) } - #[cfg(not(bootstrap))] /// Unstable placeholder for deref patterns. #[allow_internal_unstable(builtin_syntax)] #[unstable( diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index 98cff3493a7..955efb9b0f9 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -1,4 +1,4 @@ -use crate::ops::{Deref, DerefMut}; +use crate::ops::{Deref, DerefMut, DerefPure}; use crate::ptr; /// A wrapper to inhibit compiler from automatically calling `T`’s destructor. @@ -161,3 +161,6 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> { &mut self.value } } + +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl<T: ?Sized> DerefPure for ManuallyDrop<T> {} diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 75d42edbaa0..9054ade2d79 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1340,8 +1340,8 @@ impl<T> SizedTypeProperties for T {} /// assert_eq!(mem::offset_of!(Option<&u8>, Some.0), 0); /// ``` #[stable(feature = "offset_of", since = "1.77.0")] -#[allow_internal_unstable(builtin_syntax, hint_must_use)] +#[allow_internal_unstable(builtin_syntax)] pub macro offset_of($Container:ty, $($fields:expr)+ $(,)?) { // The `{}` is for better error messages - crate::hint::must_use({builtin # offset_of($Container, $($fields)+)}) + {builtin # offset_of($Container, $($fields)+)} } diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index a92da88dd3f..77b1039039b 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -481,8 +481,8 @@ macro_rules! int_impl { /// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked #[doc = concat!("[`checked_add`]: ", stringify!($SelfT), "::checked_add")] #[doc = concat!("[`wrapping_add`]: ", stringify!($SelfT), "::wrapping_add")] - #[stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unchecked_math", since = "1.79.0")] + #[rustc_const_stable(feature = "unchecked_math", since = "1.79.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -623,8 +623,8 @@ macro_rules! int_impl { /// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked #[doc = concat!("[`checked_sub`]: ", stringify!($SelfT), "::checked_sub")] #[doc = concat!("[`wrapping_sub`]: ", stringify!($SelfT), "::wrapping_sub")] - #[stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unchecked_math", since = "1.79.0")] + #[rustc_const_stable(feature = "unchecked_math", since = "1.79.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -765,8 +765,8 @@ macro_rules! int_impl { /// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked #[doc = concat!("[`checked_mul`]: ", stringify!($SelfT), "::checked_mul")] #[doc = concat!("[`wrapping_mul`]: ", stringify!($SelfT), "::wrapping_mul")] - #[stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unchecked_math", since = "1.79.0")] + #[rustc_const_stable(feature = "unchecked_math", since = "1.79.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -1234,18 +1234,9 @@ macro_rules! int_impl { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self { - #[cfg(bootstrap)] - { - // For bootstrapping, just use built-in primitive shift. - // panicking is a legal manifestation of UB - self << rhs - } - #[cfg(not(bootstrap))] - { // SAFETY: the caller must uphold the safety contract for // `unchecked_shl`. unsafe { intrinsics::unchecked_shl(self, rhs) } - } } /// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is @@ -1332,18 +1323,9 @@ macro_rules! int_impl { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self { - #[cfg(bootstrap)] - { - // For bootstrapping, just use built-in primitive shift. - // panicking is a legal manifestation of UB - self >> rhs - } - #[cfg(not(bootstrap))] - { - // SAFETY: the caller must uphold the safety contract for - // `unchecked_shr`. - unsafe { intrinsics::unchecked_shr(self, rhs) } - } + // SAFETY: the caller must uphold the safety contract for + // `unchecked_shr`. + unsafe { intrinsics::unchecked_shr(self, rhs) } } /// Checked absolute value. Computes `self.abs()`, returning `None` if diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 443401c5dba..c02f73fdf03 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -67,7 +67,7 @@ pub use error::ParseIntError; )] pub use nonzero::ZeroablePrimitive; -#[stable(feature = "generic_nonzero", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "generic_nonzero", since = "1.79.0")] pub use nonzero::NonZero; #[stable(feature = "signed_nonzero", since = "1.34.0")] diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 5a0958fdc89..5d3ae7316b1 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -109,7 +109,7 @@ impl_zeroable_primitive!( /// /// assert_eq!(size_of::<Option<NonZero<u32>>>(), size_of::<u32>()); /// ``` -#[stable(feature = "generic_nonzero", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "generic_nonzero", since = "1.79.0")] #[repr(transparent)] #[rustc_nonnull_optimization_guaranteed] #[rustc_diagnostic_item = "NonZero"] @@ -528,10 +528,7 @@ macro_rules! nonzero_integer { pub const fn leading_zeros(self) -> u32 { // SAFETY: since `self` cannot be zero, it is safe to call `ctlz_nonzero`. unsafe { - #[cfg(not(bootstrap))] - return intrinsics::ctlz_nonzero(self.get() as $UnsignedPrimitive); - #[cfg(bootstrap)] - return intrinsics::ctlz_nonzero(self.get() as $UnsignedPrimitive) as u32; + intrinsics::ctlz_nonzero(self.get() as $UnsignedPrimitive) } } @@ -557,10 +554,7 @@ macro_rules! nonzero_integer { pub const fn trailing_zeros(self) -> u32 { // SAFETY: since `self` cannot be zero, it is safe to call `cttz_nonzero`. unsafe { - #[cfg(not(bootstrap))] - return intrinsics::cttz_nonzero(self.get() as $UnsignedPrimitive); - #[cfg(bootstrap)] - return intrinsics::cttz_nonzero(self.get() as $UnsignedPrimitive) as u32; + intrinsics::cttz_nonzero(self.get() as $UnsignedPrimitive) } } @@ -861,7 +855,7 @@ macro_rules! nonzero_integer_signedness_dependent_impls { } } - #[stable(feature = "nonzero_div_assign", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "nonzero_div_assign", since = "1.79.0")] impl DivAssign<$Ty> for $Int { /// This operation rounds towards zero, /// truncating any fractional part of the exact result, and cannot panic. @@ -884,7 +878,7 @@ macro_rules! nonzero_integer_signedness_dependent_impls { } } - #[stable(feature = "nonzero_div_assign", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "nonzero_div_assign", since = "1.79.0")] impl RemAssign<$Ty> for $Int { /// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic. #[inline] diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index ea14d769cc1..673144cb328 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -77,10 +77,7 @@ macro_rules! uint_impl { without modifying the original"] #[inline(always)] pub const fn count_ones(self) -> u32 { - #[cfg(not(bootstrap))] - return intrinsics::ctpop(self as $ActualT); - #[cfg(bootstrap)] - return intrinsics::ctpop(self as $ActualT) as u32; + return intrinsics::ctpop(self); } /// Returns the number of zeros in the binary representation of `self`. @@ -122,10 +119,7 @@ macro_rules! uint_impl { without modifying the original"] #[inline(always)] pub const fn leading_zeros(self) -> u32 { - #[cfg(not(bootstrap))] return intrinsics::ctlz(self as $ActualT); - #[cfg(bootstrap)] - return intrinsics::ctlz(self as $ActualT) as u32; } /// Returns the number of trailing zeros in the binary representation @@ -146,10 +140,7 @@ macro_rules! uint_impl { without modifying the original"] #[inline(always)] pub const fn trailing_zeros(self) -> u32 { - #[cfg(not(bootstrap))] return intrinsics::cttz(self); - #[cfg(bootstrap)] - return intrinsics::cttz(self) as u32; } /// Returns the number of leading ones in the binary representation of `self`. @@ -214,10 +205,7 @@ macro_rules! uint_impl { without modifying the original"] #[inline(always)] pub const fn rotate_left(self, n: u32) -> Self { - #[cfg(not(bootstrap))] return intrinsics::rotate_left(self, n); - #[cfg(bootstrap)] - return intrinsics::rotate_left(self, n as $SelfT); } /// Shifts the bits to the right by a specified amount, `n`, @@ -242,10 +230,7 @@ macro_rules! uint_impl { without modifying the original"] #[inline(always)] pub const fn rotate_right(self, n: u32) -> Self { - #[cfg(not(bootstrap))] return intrinsics::rotate_right(self, n); - #[cfg(bootstrap)] - return intrinsics::rotate_right(self, n as $SelfT); } /// Reverses the byte order of the integer. @@ -503,8 +488,8 @@ macro_rules! uint_impl { /// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked #[doc = concat!("[`checked_add`]: ", stringify!($SelfT), "::checked_add")] #[doc = concat!("[`wrapping_add`]: ", stringify!($SelfT), "::wrapping_add")] - #[stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unchecked_math", since = "1.79.0")] + #[rustc_const_stable(feature = "unchecked_math", since = "1.79.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -651,6 +636,31 @@ macro_rules! uint_impl { /// If you're just trying to avoid the panic in debug mode, then **do not** /// use this. Instead, you're looking for [`wrapping_sub`]. /// + /// If you find yourself writing code like this: + /// + /// ``` + /// # let foo = 30_u32; + /// # let bar = 20; + /// if foo >= bar { + /// // SAFETY: just checked it will not overflow + /// let diff = unsafe { foo.unchecked_sub(bar) }; + /// // ... use diff ... + /// } + /// ``` + /// + /// Consider changing it to + /// + /// ``` + /// # let foo = 30_u32; + /// # let bar = 20; + /// if let Some(diff) = foo.checked_sub(bar) { + /// // ... use diff ... + /// } + /// ``` + /// + /// As that does exactly the same thing -- including telling the optimizer + /// that the subtraction cannot overflow -- but avoids needing `unsafe`. + /// /// # Safety /// /// This results in undefined behavior when @@ -660,8 +670,8 @@ macro_rules! uint_impl { /// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked #[doc = concat!("[`checked_sub`]: ", stringify!($SelfT), "::checked_sub")] #[doc = concat!("[`wrapping_sub`]: ", stringify!($SelfT), "::wrapping_sub")] - #[stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unchecked_math", since = "1.79.0")] + #[rustc_const_stable(feature = "unchecked_math", since = "1.79.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -746,8 +756,8 @@ macro_rules! uint_impl { /// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked #[doc = concat!("[`checked_mul`]: ", stringify!($SelfT), "::checked_mul")] #[doc = concat!("[`wrapping_mul`]: ", stringify!($SelfT), "::wrapping_mul")] - #[stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unchecked_math", since = "1.79.0")] + #[rustc_const_stable(feature = "unchecked_math", since = "1.79.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -1324,18 +1334,9 @@ macro_rules! uint_impl { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self { - #[cfg(bootstrap)] - { - // For bootstrapping, just use built-in primitive shift. - // panicking is a legal manifestation of UB - self << rhs - } - #[cfg(not(bootstrap))] - { - // SAFETY: the caller must uphold the safety contract for - // `unchecked_shl`. - unsafe { intrinsics::unchecked_shl(self, rhs) } - } + // SAFETY: the caller must uphold the safety contract for + // `unchecked_shl`. + unsafe { intrinsics::unchecked_shl(self, rhs) } } /// Checked shift right. Computes `self >> rhs`, returning `None` @@ -1422,18 +1423,9 @@ macro_rules! uint_impl { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self { - #[cfg(bootstrap)] - { - // For bootstrapping, just use built-in primitive shift. - // panicking is a legal manifestation of UB - self >> rhs - } - #[cfg(not(bootstrap))] - { // SAFETY: the caller must uphold the safety contract for // `unchecked_shr`. unsafe { intrinsics::unchecked_shr(self, rhs) } - } } /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if diff --git a/library/core/src/ops/coroutine.rs b/library/core/src/ops/coroutine.rs index 5250be15fe4..6a6c5db1ab1 100644 --- a/library/core/src/ops/coroutine.rs +++ b/library/core/src/ops/coroutine.rs @@ -46,7 +46,7 @@ pub enum CoroutineState<Y, R> { /// use std::pin::Pin; /// /// fn main() { -/// let mut coroutine = #[cfg_attr(not(bootstrap), coroutine)] || { +/// let mut coroutine = #[coroutine] || { /// yield 1; /// "foo" /// }; diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index 3795a81c2c1..9849410d484 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -285,7 +285,7 @@ impl<T: ?Sized> DerefMut for &mut T { /// is concerned. Calls to `deref`/`deref_mut`` must leave the pointer itself likewise /// unchanged. #[unstable(feature = "deref_pure_trait", issue = "87121")] -#[cfg_attr(not(bootstrap), lang = "deref_pure")] +#[lang = "deref_pure"] pub unsafe trait DerefPure {} #[unstable(feature = "deref_pure_trait", issue = "87121")] diff --git a/library/core/src/ops/drop.rs b/library/core/src/ops/drop.rs index 1325d90e4f3..36ae581e3f7 100644 --- a/library/core/src/ops/drop.rs +++ b/library/core/src/ops/drop.rs @@ -240,7 +240,6 @@ pub trait Drop { } /// Fallback function to call surface level `Drop::drop` function -#[cfg(not(bootstrap))] #[allow(drop_bounds)] #[lang = "fallback_surface_drop"] pub(crate) fn fallback_surface_drop<T: Drop + ?Sized>(x: &mut T) { diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index 81d5e5c949e..7bcfaadbe37 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -174,7 +174,6 @@ pub use self::deref::Receiver; #[stable(feature = "rust1", since = "1.0.0")] pub use self::drop::Drop; -#[cfg(not(bootstrap))] pub(crate) use self::drop::fallback_surface_drop; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/panic/location.rs b/library/core/src/panic/location.rs index 4ad507d8b86..eb27da1724e 100644 --- a/library/core/src/panic/location.rs +++ b/library/core/src/panic/location.rs @@ -81,7 +81,7 @@ impl<'a> Location<'a> { /// ``` #[must_use] #[stable(feature = "track_caller", since = "1.46.0")] - #[rustc_const_stable(feature = "const_caller_location", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_caller_location", since = "1.79.0")] #[track_caller] #[inline] pub const fn caller() -> &'static Location<'static> { @@ -123,7 +123,7 @@ impl<'a> Location<'a> { /// ``` #[must_use] #[stable(feature = "panic_hooks", since = "1.10.0")] - #[rustc_const_stable(feature = "const_location_fields", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_location_fields", since = "1.79.0")] #[inline] pub const fn file(&self) -> &str { self.file @@ -148,7 +148,7 @@ impl<'a> Location<'a> { /// ``` #[must_use] #[stable(feature = "panic_hooks", since = "1.10.0")] - #[rustc_const_stable(feature = "const_location_fields", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_location_fields", since = "1.79.0")] #[inline] pub const fn line(&self) -> u32 { self.line @@ -173,7 +173,7 @@ impl<'a> Location<'a> { /// ``` #[must_use] #[stable(feature = "panic_col", since = "1.25.0")] - #[rustc_const_stable(feature = "const_location_fields", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_location_fields", since = "1.79.0")] #[inline] pub const fn column(&self) -> u32 { self.col diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 3ee56e6c579..ca06e059b75 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -156,7 +156,6 @@ pub const fn panic(expr: &'static str) -> ! { // reducing binary size impact. macro_rules! panic_const { ($($lang:ident = $message:expr,)+) => { - #[cfg(not(bootstrap))] pub mod panic_const { use super::*; diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index a11c6c742d7..d8fc3b7177f 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -923,7 +923,7 @@ use crate::cmp; use crate::fmt; use crate::hash::{Hash, Hasher}; -use crate::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Receiver}; +use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, Receiver}; #[allow(unused_imports)] use crate::{ @@ -1684,6 +1684,9 @@ impl<Ptr: DerefMut<Target: Unpin>> DerefMut for Pin<Ptr> { } } +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl<Ptr: DerefPure> DerefPure for Pin<Ptr> {} + #[unstable(feature = "receiver_trait", issue = "none")] impl<Ptr: Receiver> Receiver for Pin<Ptr> {} @@ -1809,7 +1812,7 @@ impl<Ptr, U> DispatchFromDyn<Pin<U>> for Pin<Ptr> where Ptr: DispatchFromDyn<U> /// fn coroutine_fn() -> impl Coroutine<Yield = usize, Return = ()> /* not Unpin */ { /// // Allow coroutine to be self-referential (not `Unpin`) /// // vvvvvv so that locals can cross yield points. -/// #[cfg_attr(not(bootstrap), coroutine)] static || { +/// #[coroutine] static || { /// let foo = String::from("foo"); /// let foo_ref = &foo; // ------+ /// yield 0; // | <- crosses yield point! diff --git a/library/core/src/prelude/common.rs b/library/core/src/prelude/common.rs index b98f3a4659b..afc6817aa1d 100644 --- a/library/core/src/prelude/common.rs +++ b/library/core/src/prelude/common.rs @@ -97,7 +97,6 @@ pub use crate::macros::builtin::cfg_eval; )] pub use crate::macros::builtin::type_ascribe; -#[cfg(not(bootstrap))] #[unstable( feature = "deref_patterns", issue = "87121", diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index bda1ee6f457..18a9503cfd2 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -268,6 +268,53 @@ mod prim_bool {} /// [`Debug`]: fmt::Debug /// [`default()`]: Default::default /// +/// # Never type fallback +/// +/// When the compiler sees a value of type `!` in a [coercion site], it implicitly inserts a +/// coercion to allow the type checker to infer any type: +/// +/// ```rust,ignore (illustrative-and-has-placeholders) +/// // this +/// let x: u8 = panic!(); +/// +/// // is (essentially) turned by the compiler into +/// let x: u8 = absurd(panic!()); +/// +/// // where absurd is a function with the following signature +/// // (it's sound, because `!` always marks unreachable code): +/// fn absurd<T>(_: !) -> T { ... } +// FIXME: use `core::convert::absurd` here instead, once it's merged +/// ``` +/// +/// This can lead to compilation errors if the type cannot be inferred: +/// +/// ```compile_fail +/// // this +/// { panic!() }; +/// +/// // gets turned into this +/// { absurd(panic!()) }; // error: can't infer the type of `absurd` +/// ``` +/// +/// To prevent such errors, the compiler remembers where it inserted `absurd` calls, and +/// if it can't infer the type, it uses the fallback type instead: +/// ```rust, ignore +/// type Fallback = /* An arbitrarily selected type! */; +/// { absurd::<Fallback>(panic!()) } +/// ``` +/// +/// This is what is known as "never type fallback". +/// +/// Historically, the fallback type was [`()`], causing confusing behavior where `!` spontaneously +/// coerced to `()`, even when it would not infer `()` without the fallback. There are plans to +/// change it in the [2024 edition] (and possibly in all editions on a later date); see +/// [Tracking Issue for making `!` fall back to `!`][fallback-ti]. +/// +/// [coercion site]: <https://doc.rust-lang.org/reference/type-coercions.html#coercion-sites> +/// [`()`]: prim@unit +/// [fallback-ti]: <https://github.com/rust-lang/rust/issues/123748> +/// [2024 edition]: <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/index.html> +/// #[unstable(feature = "never_type", issue = "35121")] mod prim_never {} diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 9737fb8816e..73bb256518d 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -358,6 +358,54 @@ impl<T: ?Sized> *const T { if self.is_null() { None } else { unsafe { Some(&*self) } } } + /// Returns a shared reference to the value behind the pointer. + /// If the pointer may be null or the value may be uninitialized, [`as_uninit_ref`] must be used instead. + /// If the pointer may be null, but the value is known to have been initialized, [`as_ref`] must be used instead. + /// + /// [`as_ref`]: #method.as_ref + /// [`as_uninit_ref`]: #method.as_uninit_ref + /// + /// # Safety + /// + /// When calling this method, you have to ensure that all of the following is true: + /// + /// * The pointer must be properly aligned. + /// + /// * It must be "dereferenceable" in the sense defined in [the module documentation]. + /// + /// * The pointer must point to an initialized instance of `T`. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, while this reference exists, the memory the pointer points to must + /// not get mutated (except inside `UnsafeCell`). + /// + /// This applies even if the result of this method is unused! + /// (The part about being initialized is not yet fully decided, but until + /// it is, the only safe approach is to ensure that they are indeed initialized.) + /// + /// [the module documentation]: crate::ptr#safety + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_as_ref_unchecked)] + /// let ptr: *const u8 = &10u8 as *const u8; + /// + /// unsafe { + /// println!("We got back the value: {}!", ptr.as_ref_unchecked()); + /// } + /// ``` + // FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized. + #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] + #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[inline] + #[must_use] + pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T { + // SAFETY: the caller must guarantee that `self` is valid for a reference + unsafe { &*self } + } + /// Returns `None` if the pointer is null, or else returns a shared reference to /// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require /// that the value has to be initialized. @@ -1496,7 +1544,7 @@ impl<T: ?Sized> *const T { /// [tracking issue]: https://github.com/rust-lang/rust/issues/104203 #[must_use] #[inline] - #[stable(feature = "pointer_is_aligned", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "pointer_is_aligned", since = "1.79.0")] #[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")] pub const fn is_aligned(self) -> bool where @@ -1653,8 +1701,8 @@ impl<T> *const [T] { /// assert_eq!(slice.len(), 3); /// ``` #[inline] - #[stable(feature = "slice_ptr_len", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "const_slice_ptr_len", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_ptr_len", since = "1.79.0")] + #[rustc_const_stable(feature = "const_slice_ptr_len", since = "1.79.0")] #[rustc_allow_const_fn_unstable(ptr_metadata)] pub const fn len(self) -> usize { metadata(self) @@ -1671,8 +1719,8 @@ impl<T> *const [T] { /// assert!(!slice.is_empty()); /// ``` #[inline(always)] - #[stable(feature = "slice_ptr_len", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "const_slice_ptr_len", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_ptr_len", since = "1.79.0")] + #[rustc_const_stable(feature = "const_slice_ptr_len", since = "1.79.0")] pub const fn is_empty(self) -> bool { self.len() == 0 } diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index 1226c8e2419..eb815b6d822 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -2,7 +2,6 @@ use crate::fmt; use crate::hash::{Hash, Hasher}; -#[cfg(not(bootstrap))] use crate::intrinsics::aggregate_raw_ptr; use crate::marker::Freeze; @@ -115,17 +114,7 @@ pub const fn from_raw_parts<T: ?Sized>( data_pointer: *const (), metadata: <T as Pointee>::Metadata, ) -> *const T { - #[cfg(bootstrap)] - { - // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T - // and PtrComponents<T> have the same memory layouts. Only std can make this - // guarantee. - unsafe { PtrRepr { components: PtrComponents { data_pointer, metadata } }.const_ptr } - } - #[cfg(not(bootstrap))] - { - aggregate_raw_ptr(data_pointer, metadata) - } + aggregate_raw_ptr(data_pointer, metadata) } /// Performs the same functionality as [`from_raw_parts`], except that a @@ -139,17 +128,7 @@ pub const fn from_raw_parts_mut<T: ?Sized>( data_pointer: *mut (), metadata: <T as Pointee>::Metadata, ) -> *mut T { - #[cfg(bootstrap)] - { - // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T - // and PtrComponents<T> have the same memory layouts. Only std can make this - // guarantee. - unsafe { PtrRepr { components: PtrComponents { data_pointer, metadata } }.mut_ptr } - } - #[cfg(not(bootstrap))] - { - aggregate_raw_ptr(data_pointer, metadata) - } + aggregate_raw_ptr(data_pointer, metadata) } #[repr(C)] diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index f12ab3d50cd..5f3815859c8 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1784,15 +1784,6 @@ pub(crate) const unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usiz assume, cttz_nonzero, exact_div, mul_with_overflow, unchecked_rem, unchecked_sub, wrapping_add, wrapping_mul, wrapping_sub, }; - #[cfg(bootstrap)] - const unsafe fn unchecked_shl(value: usize, shift: usize) -> usize { - value << shift - } - #[cfg(bootstrap)] - const unsafe fn unchecked_shr(value: usize, shift: usize) -> usize { - value >> shift - } - #[cfg(not(bootstrap))] use intrinsics::{unchecked_shl, unchecked_shr}; /// Calculate multiplicative modular inverse of `x` modulo `m`. diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index d8f91f1996b..b67930503e0 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -367,6 +367,57 @@ impl<T: ?Sized> *mut T { if self.is_null() { None } else { unsafe { Some(&*self) } } } + /// Returns a shared reference to the value behind the pointer. + /// If the pointer may be null or the value may be uninitialized, [`as_uninit_ref`] must be used instead. + /// If the pointer may be null, but the value is known to have been initialized, [`as_ref`] must be used instead. + /// + /// For the mutable counterpart see [`as_mut_unchecked`]. + /// + /// [`as_ref`]: #method.as_ref + /// [`as_uninit_ref`]: #method.as_uninit_ref + /// [`as_mut_unchecked`]: #method.as_mut_unchecked + /// + /// # Safety + /// + /// When calling this method, you have to ensure that all of the following is true: + /// + /// * The pointer must be properly aligned. + /// + /// * It must be "dereferenceable" in the sense defined in [the module documentation]. + /// + /// * The pointer must point to an initialized instance of `T`. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, while this reference exists, the memory the pointer points to must + /// not get mutated (except inside `UnsafeCell`). + /// + /// This applies even if the result of this method is unused! + /// (The part about being initialized is not yet fully decided, but until + /// it is, the only safe approach is to ensure that they are indeed initialized.) + /// + /// [the module documentation]: crate::ptr#safety + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_as_ref_unchecked)] + /// let ptr: *mut u8 = &mut 10u8 as *mut u8; + /// + /// unsafe { + /// println!("We got back the value: {}!", ptr.as_ref_unchecked()); + /// } + /// ``` + // FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized. + #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] + #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[inline] + #[must_use] + pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T { + // SAFETY: the caller must guarantee that `self` is valid for a reference + unsafe { &*self } + } + /// Returns `None` if the pointer is null, or else returns a shared reference to /// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require /// that the value has to be initialized. @@ -688,6 +739,58 @@ impl<T: ?Sized> *mut T { if self.is_null() { None } else { unsafe { Some(&mut *self) } } } + /// Returns a unique reference to the value behind the pointer. + /// If the pointer may be null or the value may be uninitialized, [`as_uninit_mut`] must be used instead. + /// If the pointer may be null, but the value is known to have been initialized, [`as_mut`] must be used instead. + /// + /// For the shared counterpart see [`as_ref_unchecked`]. + /// + /// [`as_mut`]: #method.as_mut + /// [`as_uninit_mut`]: #method.as_uninit_mut + /// [`as_ref_unchecked`]: #method.as_mut_unchecked + /// + /// # Safety + /// + /// When calling this method, you have to ensure that all of the following is true: + /// + /// * The pointer must be properly aligned. + /// + /// * It must be "dereferenceable" in the sense defined in [the module documentation]. + /// + /// * The pointer must point to an initialized instance of `T`. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, while this reference exists, the memory the pointer points to must + /// not get mutated (except inside `UnsafeCell`). + /// + /// This applies even if the result of this method is unused! + /// (The part about being initialized is not yet fully decided, but until + /// it is, the only safe approach is to ensure that they are indeed initialized.) + /// + /// [the module documentation]: crate::ptr#safety + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_as_ref_unchecked)] + /// let mut s = [1, 2, 3]; + /// let ptr: *mut u32 = s.as_mut_ptr(); + /// let first_value = unsafe { ptr.as_mut_unchecked() }; + /// *first_value = 4; + /// # assert_eq!(s, [4, 2, 3]); + /// println!("{s:?}"); // It'll print: "[4, 2, 3]". + /// ``` + // FIXME: mention it in the docs for `as_mut` and `as_uninit_mut` once stabilized. + #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] + #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[inline] + #[must_use] + pub const unsafe fn as_mut_unchecked<'a>(self) -> &'a mut T { + // SAFETY: the caller must guarantee that `self` is valid for a reference + unsafe { &mut *self } + } + /// Returns `None` if the pointer is null, or else returns a unique reference to /// the value wrapped in `Some`. In contrast to [`as_mut`], this does not require /// that the value has to be initialized. @@ -1756,7 +1859,7 @@ impl<T: ?Sized> *mut T { /// [tracking issue]: https://github.com/rust-lang/rust/issues/104203 #[must_use] #[inline] - #[stable(feature = "pointer_is_aligned", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "pointer_is_aligned", since = "1.79.0")] #[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")] pub const fn is_aligned(self) -> bool where @@ -1915,8 +2018,8 @@ impl<T> *mut [T] { /// assert_eq!(slice.len(), 3); /// ``` #[inline(always)] - #[stable(feature = "slice_ptr_len", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "const_slice_ptr_len", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_ptr_len", since = "1.79.0")] + #[rustc_const_stable(feature = "const_slice_ptr_len", since = "1.79.0")] #[rustc_allow_const_fn_unstable(ptr_metadata)] pub const fn len(self) -> usize { metadata(self) @@ -1933,8 +2036,8 @@ impl<T> *mut [T] { /// assert!(!slice.is_empty()); /// ``` #[inline(always)] - #[stable(feature = "slice_ptr_len", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "const_slice_ptr_len", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_ptr_len", since = "1.79.0")] + #[rustc_const_stable(feature = "const_slice_ptr_len", since = "1.79.0")] pub const fn is_empty(self) -> bool { self.len() == 0 } diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 96ce3cd3a3f..617890cf083 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -512,7 +512,6 @@ impl<T: ?Sized> NonNull<T> { /// # Examples /// /// ``` - /// #![feature(non_null_convenience)] /// use std::ptr::NonNull; /// /// let mut s = [1, 2, 3]; @@ -523,12 +522,12 @@ impl<T: ?Sized> NonNull<T> { /// println!("{}", ptr.offset(2).read()); /// } /// ``` - #[unstable(feature = "non_null_convenience", issue = "117691")] - #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] - #[must_use = "returns a new pointer rather than modifying its argument"] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - pub const unsafe fn offset(self, count: isize) -> NonNull<T> + #[must_use = "returns a new pointer rather than modifying its argument"] + #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] + pub const unsafe fn offset(self, count: isize) -> Self where T: Sized, { @@ -549,11 +548,11 @@ impl<T: ?Sized> NonNull<T> { /// /// For non-`Sized` pointees this operation changes only the data pointer, /// leaving the metadata untouched. - #[unstable(feature = "non_null_convenience", issue = "117691")] - #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] #[must_use] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn byte_offset(self, count: isize) -> Self { // SAFETY: the caller must uphold the safety contract for `offset` and `byte_offset` has // the same safety contract. @@ -599,7 +598,6 @@ impl<T: ?Sized> NonNull<T> { /// # Examples /// /// ``` - /// #![feature(non_null_convenience)] /// use std::ptr::NonNull; /// /// let s: &str = "123"; @@ -610,11 +608,11 @@ impl<T: ?Sized> NonNull<T> { /// println!("{}", ptr.add(2).read() as char); /// } /// ``` - #[unstable(feature = "non_null_convenience", issue = "117691")] - #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] - #[must_use = "returns a new pointer rather than modifying its argument"] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[must_use = "returns a new pointer rather than modifying its argument"] + #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn add(self, count: usize) -> Self where T: Sized, @@ -636,12 +634,12 @@ impl<T: ?Sized> NonNull<T> { /// /// For non-`Sized` pointees this operation changes only the data pointer, /// leaving the metadata untouched. - #[unstable(feature = "non_null_convenience", issue = "117691")] - #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] #[must_use] #[inline(always)] - #[rustc_allow_const_fn_unstable(set_ptr_value)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_allow_const_fn_unstable(set_ptr_value)] + #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn byte_add(self, count: usize) -> Self { // SAFETY: the caller must uphold the safety contract for `add` and `byte_add` has the same // safety contract. @@ -688,7 +686,6 @@ impl<T: ?Sized> NonNull<T> { /// # Examples /// /// ``` - /// #![feature(non_null_convenience)] /// use std::ptr::NonNull; /// /// let s: &str = "123"; @@ -699,11 +696,11 @@ impl<T: ?Sized> NonNull<T> { /// println!("{}", end.sub(2).read() as char); /// } /// ``` - #[unstable(feature = "non_null_convenience", issue = "117691")] - #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] - #[must_use = "returns a new pointer rather than modifying its argument"] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[must_use = "returns a new pointer rather than modifying its argument"] + #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn sub(self, count: usize) -> Self where T: Sized, @@ -730,12 +727,12 @@ impl<T: ?Sized> NonNull<T> { /// /// For non-`Sized` pointees this operation changes only the data pointer, /// leaving the metadata untouched. - #[unstable(feature = "non_null_convenience", issue = "117691")] - #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] #[must_use] #[inline(always)] - #[rustc_allow_const_fn_unstable(set_ptr_value)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_allow_const_fn_unstable(set_ptr_value)] + #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn byte_sub(self, count: usize) -> Self { // SAFETY: the caller must uphold the safety contract for `sub` and `byte_sub` has the same // safety contract. @@ -816,7 +813,6 @@ impl<T: ?Sized> NonNull<T> { /// Basic usage: /// /// ``` - /// #![feature(non_null_convenience)] /// use std::ptr::NonNull; /// /// let a = [0; 5]; @@ -833,7 +829,7 @@ impl<T: ?Sized> NonNull<T> { /// *Incorrect* usage: /// /// ```rust,no_run - /// #![feature(non_null_convenience, strict_provenance)] + /// #![feature(strict_provenance)] /// use std::ptr::NonNull; /// /// let ptr1 = NonNull::new(Box::into_raw(Box::new(0u8))).unwrap(); @@ -845,14 +841,13 @@ impl<T: ?Sized> NonNull<T> { /// // Since ptr2_other and ptr2 are derived from pointers to different objects, /// // computing their offset is undefined behavior, even though /// // they point to the same address! - /// unsafe { - /// let zero = ptr2_other.offset_from(ptr2); // Undefined Behavior - /// } + /// + /// let zero = unsafe { ptr2_other.offset_from(ptr2) }; // Undefined Behavior /// ``` - #[unstable(feature = "non_null_convenience", issue = "117691")] - #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn offset_from(self, origin: NonNull<T>) -> isize where T: Sized, @@ -870,10 +865,10 @@ impl<T: ?Sized> NonNull<T> { /// /// For non-`Sized` pointees this operation considers only the data pointers, /// ignoring the metadata. - #[unstable(feature = "non_null_convenience", issue = "117691")] - #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn byte_offset_from<U: ?Sized>(self, origin: NonNull<U>) -> isize { // SAFETY: the caller must uphold the safety contract for `byte_offset_from`. unsafe { self.pointer.byte_offset_from(origin.pointer) } @@ -897,7 +892,7 @@ impl<T: ?Sized> NonNull<T> { /// to [`sub`](#method.sub)). The following are all equivalent, assuming /// that their safety preconditions are met: /// ```rust - /// # #![feature(non_null_convenience)] + /// # #![feature(ptr_sub_ptr)] /// # unsafe fn blah(ptr: std::ptr::NonNull<u32>, origin: std::ptr::NonNull<u32>, count: usize) -> bool { /// ptr.sub_ptr(origin) == count /// # && @@ -926,7 +921,7 @@ impl<T: ?Sized> NonNull<T> { /// # Examples /// /// ``` - /// #![feature(non_null_convenience)] + /// #![feature(ptr_sub_ptr)] /// use std::ptr::NonNull; /// /// let a = [0; 5]; @@ -942,12 +937,10 @@ impl<T: ?Sized> NonNull<T> { /// // This would be incorrect, as the pointers are not correctly ordered: /// // ptr1.sub_ptr(ptr2) /// ``` - #[unstable(feature = "non_null_convenience", issue = "117691")] - #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] - // #[unstable(feature = "ptr_sub_ptr", issue = "95892")] - // #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[unstable(feature = "ptr_sub_ptr", issue = "95892")] + #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] pub const unsafe fn sub_ptr(self, subtracted: NonNull<T>) -> usize where T: Sized, @@ -962,10 +955,10 @@ impl<T: ?Sized> NonNull<T> { /// See [`ptr::read`] for safety concerns and examples. /// /// [`ptr::read`]: crate::ptr::read() - #[unstable(feature = "non_null_convenience", issue = "117691")] - #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn read(self) -> T where T: Sized, @@ -984,9 +977,9 @@ impl<T: ?Sized> NonNull<T> { /// See [`ptr::read_volatile`] for safety concerns and examples. /// /// [`ptr::read_volatile`]: crate::ptr::read_volatile() - #[unstable(feature = "non_null_convenience", issue = "117691")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] pub unsafe fn read_volatile(self) -> T where T: Sized, @@ -1003,10 +996,10 @@ impl<T: ?Sized> NonNull<T> { /// See [`ptr::read_unaligned`] for safety concerns and examples. /// /// [`ptr::read_unaligned`]: crate::ptr::read_unaligned() - #[unstable(feature = "non_null_convenience", issue = "117691")] - #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn read_unaligned(self) -> T where T: Sized, @@ -1023,10 +1016,10 @@ impl<T: ?Sized> NonNull<T> { /// See [`ptr::copy`] for safety concerns and examples. /// /// [`ptr::copy`]: crate::ptr::copy() - #[unstable(feature = "non_null_convenience", issue = "117691")] - #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] pub const unsafe fn copy_to(self, dest: NonNull<T>, count: usize) where T: Sized, @@ -1043,10 +1036,10 @@ impl<T: ?Sized> NonNull<T> { /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() - #[unstable(feature = "non_null_convenience", issue = "117691")] - #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] pub const unsafe fn copy_to_nonoverlapping(self, dest: NonNull<T>, count: usize) where T: Sized, @@ -1063,10 +1056,10 @@ impl<T: ?Sized> NonNull<T> { /// See [`ptr::copy`] for safety concerns and examples. /// /// [`ptr::copy`]: crate::ptr::copy() - #[unstable(feature = "non_null_convenience", issue = "117691")] - #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] pub const unsafe fn copy_from(self, src: NonNull<T>, count: usize) where T: Sized, @@ -1083,10 +1076,10 @@ impl<T: ?Sized> NonNull<T> { /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() - #[unstable(feature = "non_null_convenience", issue = "117691")] - #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] pub const unsafe fn copy_from_nonoverlapping(self, src: NonNull<T>, count: usize) where T: Sized, @@ -1100,8 +1093,8 @@ impl<T: ?Sized> NonNull<T> { /// See [`ptr::drop_in_place`] for safety concerns and examples. /// /// [`ptr::drop_in_place`]: crate::ptr::drop_in_place() - #[unstable(feature = "non_null_convenience", issue = "117691")] #[inline(always)] + #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] pub unsafe fn drop_in_place(self) { // SAFETY: the caller must uphold the safety contract for `drop_in_place`. unsafe { ptr::drop_in_place(self.as_ptr()) } @@ -1113,11 +1106,10 @@ impl<T: ?Sized> NonNull<T> { /// See [`ptr::write`] for safety concerns and examples. /// /// [`ptr::write`]: crate::ptr::write() - #[unstable(feature = "non_null_convenience", issue = "117691")] - #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] - //#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] pub const unsafe fn write(self, val: T) where T: Sized, @@ -1132,12 +1124,11 @@ impl<T: ?Sized> NonNull<T> { /// See [`ptr::write_bytes`] for safety concerns and examples. /// /// [`ptr::write_bytes`]: crate::ptr::write_bytes() - #[doc(alias = "memset")] - #[unstable(feature = "non_null_convenience", issue = "117691")] - #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] - //#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] #[inline(always)] + #[doc(alias = "memset")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] pub const unsafe fn write_bytes(self, val: u8, count: usize) where T: Sized, @@ -1156,9 +1147,9 @@ impl<T: ?Sized> NonNull<T> { /// See [`ptr::write_volatile`] for safety concerns and examples. /// /// [`ptr::write_volatile`]: crate::ptr::write_volatile() - #[unstable(feature = "non_null_convenience", issue = "117691")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] pub unsafe fn write_volatile(self, val: T) where T: Sized, @@ -1175,11 +1166,10 @@ impl<T: ?Sized> NonNull<T> { /// See [`ptr::write_unaligned`] for safety concerns and examples. /// /// [`ptr::write_unaligned`]: crate::ptr::write_unaligned() - #[unstable(feature = "non_null_convenience", issue = "117691")] - #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] - //#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] pub const unsafe fn write_unaligned(self, val: T) where T: Sized, @@ -1194,8 +1184,8 @@ impl<T: ?Sized> NonNull<T> { /// See [`ptr::replace`] for safety concerns and examples. /// /// [`ptr::replace`]: crate::ptr::replace() - #[unstable(feature = "non_null_convenience", issue = "117691")] #[inline(always)] + #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] pub unsafe fn replace(self, src: T) -> T where T: Sized, @@ -1211,10 +1201,9 @@ impl<T: ?Sized> NonNull<T> { /// See [`ptr::swap`] for safety concerns and examples. /// /// [`ptr::swap`]: crate::ptr::swap() - #[unstable(feature = "non_null_convenience", issue = "117691")] - #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] - //#[rustc_const_unstable(feature = "const_swap", issue = "83163")] #[inline(always)] + #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_unstable(feature = "const_swap", issue = "83163")] pub const unsafe fn swap(self, with: NonNull<T>) where T: Sized, @@ -1246,7 +1235,6 @@ impl<T: ?Sized> NonNull<T> { /// Accessing adjacent `u8` as `u16` /// /// ``` - /// #![feature(non_null_convenience)] /// use std::mem::align_of; /// use std::ptr::NonNull; /// @@ -1264,11 +1252,10 @@ impl<T: ?Sized> NonNull<T> { /// } /// # } /// ``` - #[unstable(feature = "non_null_convenience", issue = "117691")] - #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] - //#[rustc_const_unstable(feature = "const_align_offset", issue = "90962")] - #[must_use] #[inline] + #[must_use] + #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_unstable(feature = "const_align_offset", issue = "90962")] pub const fn align_offset(self, align: usize) -> usize where T: Sized, @@ -1312,10 +1299,9 @@ impl<T: ?Sized> NonNull<T> { /// underlying allocation. /// /// ``` - /// #![feature(const_pointer_is_aligned)] - /// #![feature(non_null_convenience)] - /// #![feature(const_option)] /// #![feature(const_nonnull_new)] + /// #![feature(const_option)] + /// #![feature(const_pointer_is_aligned)] /// use std::ptr::NonNull; /// /// // On some platforms, the alignment of primitives is less than their size. @@ -1390,10 +1376,10 @@ impl<T: ?Sized> NonNull<T> { /// ``` /// /// [tracking issue]: https://github.com/rust-lang/rust/issues/104203 - #[stable(feature = "pointer_is_aligned", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")] - #[must_use] #[inline] + #[must_use] + #[stable(feature = "pointer_is_aligned", since = "1.79.0")] + #[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")] pub const fn is_aligned(self) -> bool where T: Sized, @@ -1505,10 +1491,10 @@ impl<T: ?Sized> NonNull<T> { /// ``` /// /// [tracking issue]: https://github.com/rust-lang/rust/issues/104203 + #[inline] + #[must_use] #[unstable(feature = "pointer_is_aligned_to", issue = "96284")] #[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")] - #[must_use] - #[inline] pub const fn is_aligned_to(self, align: usize) -> bool { self.pointer.is_aligned_to(align) } @@ -1578,11 +1564,8 @@ impl<T> NonNull<[T]> { /// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3); /// assert!(!slice.is_empty()); /// ``` - #[stable(feature = "slice_ptr_is_empty_nonnull", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable( - feature = "const_slice_ptr_is_empty_nonnull", - since = "CURRENT_RUSTC_VERSION" - )] + #[stable(feature = "slice_ptr_is_empty_nonnull", since = "1.79.0")] + #[rustc_const_stable(feature = "const_slice_ptr_is_empty_nonnull", since = "1.79.0")] #[must_use] #[inline] pub const fn is_empty(self) -> bool { diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 6e1ba74f72b..ed7bcec89b9 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -9,7 +9,7 @@ use crate::cmp::Ordering::{self, Equal, Greater, Less}; use crate::fmt; use crate::hint; -use crate::intrinsics::exact_div; +use crate::intrinsics::{exact_div, unchecked_sub}; use crate::mem::{self, SizedTypeProperties}; use crate::num::NonZero; use crate::ops::{Bound, OneSidedRange, Range, RangeBounds}; @@ -1964,7 +1964,7 @@ impl<T> [T] { /// assert_eq!(right, []); /// } /// ``` - #[stable(feature = "slice_split_at_unchecked", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_split_at_unchecked", since = "1.79.0")] #[rustc_const_stable(feature = "const_slice_split_at_unchecked", since = "1.77.0")] #[inline] #[must_use] @@ -1983,7 +1983,7 @@ impl<T> [T] { ); // SAFETY: Caller has to check that `0 <= mid <= self.len()` - unsafe { (from_raw_parts(ptr, mid), from_raw_parts(ptr.add(mid), len - mid)) } + unsafe { (from_raw_parts(ptr, mid), from_raw_parts(ptr.add(mid), unchecked_sub(len, mid))) } } /// Divides one mutable slice into two at an index, without doing bounds checking. @@ -2017,7 +2017,7 @@ impl<T> [T] { /// } /// assert_eq!(v, [1, 2, 3, 4, 5, 6]); /// ``` - #[stable(feature = "slice_split_at_unchecked", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_split_at_unchecked", since = "1.79.0")] #[rustc_const_unstable(feature = "const_slice_split_at_mut", issue = "101804")] #[inline] #[must_use] @@ -2035,7 +2035,12 @@ impl<T> [T] { // // `[ptr; mid]` and `[mid; len]` are not overlapping, so returning a mutable reference // is fine. - unsafe { (from_raw_parts_mut(ptr, mid), from_raw_parts_mut(ptr.add(mid), len - mid)) } + unsafe { + ( + from_raw_parts_mut(ptr, mid), + from_raw_parts_mut(ptr.add(mid), unchecked_sub(len, mid)), + ) + } } /// Divides one slice into two at an index, returning `None` if the slice is @@ -2051,8 +2056,6 @@ impl<T> [T] { /// # Examples /// /// ``` - /// #![feature(split_at_checked)] - /// /// let v = [1, -2, 3, -4, 5, -6]; /// /// { @@ -2075,8 +2078,8 @@ impl<T> [T] { /// /// assert_eq!(None, v.split_at_checked(7)); /// ``` - #[unstable(feature = "split_at_checked", reason = "new API", issue = "119128")] - #[rustc_const_unstable(feature = "split_at_checked", issue = "119128")] + #[stable(feature = "split_at_checked", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "split_at_checked", since = "CURRENT_RUSTC_VERSION")] #[inline] #[must_use] pub const fn split_at_checked(&self, mid: usize) -> Option<(&[T], &[T])> { @@ -2102,8 +2105,6 @@ impl<T> [T] { /// # Examples /// /// ``` - /// #![feature(split_at_checked)] - /// /// let mut v = [1, 0, 3, 0, 5, 6]; /// /// if let Some((left, right)) = v.split_at_mut_checked(2) { @@ -2116,8 +2117,8 @@ impl<T> [T] { /// /// assert_eq!(None, v.split_at_mut_checked(7)); /// ``` - #[unstable(feature = "split_at_checked", reason = "new API", issue = "119128")] - #[rustc_const_unstable(feature = "split_at_checked", issue = "119128")] + #[stable(feature = "split_at_checked", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_unstable(feature = "const_slice_split_at_mut", issue = "101804")] #[inline] #[must_use] pub const fn split_at_mut_checked(&mut self, mid: usize) -> Option<(&mut [T], &mut [T])> { diff --git a/library/core/src/str/lossy.rs b/library/core/src/str/lossy.rs index f8ecf1f3a7c..51a0777c2d6 100644 --- a/library/core/src/str/lossy.rs +++ b/library/core/src/str/lossy.rs @@ -40,7 +40,7 @@ impl [u8] { /// assert_eq!(lit, expected); /// } /// ``` - #[stable(feature = "utf8_chunks", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "utf8_chunks", since = "1.79.0")] pub fn utf8_chunks(&self) -> Utf8Chunks<'_> { Utf8Chunks { source: self } } @@ -66,7 +66,7 @@ impl [u8] { /// // The fourth character is broken /// assert_eq!(b"\xF1\x80", chunk.invalid()); /// ``` -#[stable(feature = "utf8_chunks", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "utf8_chunks", since = "1.79.0")] #[derive(Clone, Debug, PartialEq, Eq)] pub struct Utf8Chunk<'a> { valid: &'a str, @@ -79,7 +79,7 @@ impl<'a> Utf8Chunk<'a> { /// This substring can be empty at the start of the string or between /// broken UTF-8 characters. #[must_use] - #[stable(feature = "utf8_chunks", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "utf8_chunks", since = "1.79.0")] pub fn valid(&self) -> &'a str { self.valid } @@ -99,7 +99,7 @@ impl<'a> Utf8Chunk<'a> { /// [`valid`]: Self::valid /// [`U+FFFD REPLACEMENT CHARACTER`]: crate::char::REPLACEMENT_CHARACTER #[must_use] - #[stable(feature = "utf8_chunks", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "utf8_chunks", since = "1.79.0")] pub fn invalid(&self) -> &'a [u8] { self.invalid } @@ -172,7 +172,7 @@ impl fmt::Debug for Debug<'_> { /// /// [`String::from_utf8_lossy`]: ../../std/string/struct.String.html#method.from_utf8_lossy #[must_use = "iterators are lazy and do nothing unless consumed"] -#[stable(feature = "utf8_chunks", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "utf8_chunks", since = "1.79.0")] #[derive(Clone)] pub struct Utf8Chunks<'a> { source: &'a [u8], @@ -186,7 +186,7 @@ impl<'a> Utf8Chunks<'a> { } } -#[stable(feature = "utf8_chunks", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "utf8_chunks", since = "1.79.0")] impl<'a> Iterator for Utf8Chunks<'a> { type Item = Utf8Chunk<'a>; @@ -285,10 +285,10 @@ impl<'a> Iterator for Utf8Chunks<'a> { } } -#[stable(feature = "utf8_chunks", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "utf8_chunks", since = "1.79.0")] impl FusedIterator for Utf8Chunks<'_> {} -#[stable(feature = "utf8_chunks", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "utf8_chunks", since = "1.79.0")] impl fmt::Debug for Utf8Chunks<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("Utf8Chunks").field("source", &self.debug()).finish() diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 3313da9dce7..b6f65907d3c 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -24,7 +24,7 @@ use crate::slice::{self, SliceIndex}; pub mod pattern; mod lossy; -#[stable(feature = "utf8_chunks", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "utf8_chunks", since = "1.79.0")] pub use lossy::{Utf8Chunk, Utf8Chunks}; #[stable(feature = "rust1", since = "1.0.0")] @@ -721,8 +721,6 @@ impl str { /// # Examples /// /// ``` - /// #![feature(split_at_checked)] - /// /// let s = "Per Martin-Löf"; /// /// let (first, last) = s.split_at_checked(3).unwrap(); @@ -734,7 +732,7 @@ impl str { /// ``` #[inline] #[must_use] - #[unstable(feature = "split_at_checked", reason = "new API", issue = "119128")] + #[stable(feature = "split_at_checked", since = "CURRENT_RUSTC_VERSION")] pub fn split_at_checked(&self, mid: usize) -> Option<(&str, &str)> { // is_char_boundary checks that the index is in [0, .len()] if self.is_char_boundary(mid) { @@ -761,8 +759,6 @@ impl str { /// # Examples /// /// ``` - /// #![feature(split_at_checked)] - /// /// let mut s = "Per Martin-Löf".to_string(); /// if let Some((first, last)) = s.split_at_mut_checked(3) { /// first.make_ascii_uppercase(); @@ -776,7 +772,7 @@ impl str { /// ``` #[inline] #[must_use] - #[unstable(feature = "split_at_checked", reason = "new API", issue = "119128")] + #[stable(feature = "split_at_checked", since = "CURRENT_RUSTC_VERSION")] pub fn split_at_mut_checked(&mut self, mid: usize) -> Option<(&mut str, &mut str)> { // is_char_boundary checks that the index is in [0, .len()] if self.is_char_boundary(mid) { diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 073459fcb00..232ec589093 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -512,7 +512,6 @@ impl AtomicBool { /// /// ``` /// #![feature(atomic_from_mut)] - /// # #![cfg_attr(bootstrap, feature(inline_const))] /// use std::sync::atomic::{AtomicBool, Ordering}; /// /// let mut some_bools = [const { AtomicBool::new(false) }; 10]; @@ -579,7 +578,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "atomic_access", since = "1.15.0")] - #[rustc_const_stable(feature = "const_atomic_into_inner", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0")] pub const fn into_inner(self) -> bool { self.v.primitive_into_inner() != 0 } @@ -1315,7 +1314,6 @@ impl<T> AtomicPtr<T> { /// /// ``` /// #![feature(atomic_from_mut)] - /// # #![cfg_attr(bootstrap, feature(inline_const))] /// use std::ptr::null_mut; /// use std::sync::atomic::{AtomicPtr, Ordering}; /// @@ -1399,7 +1397,7 @@ impl<T> AtomicPtr<T> { /// ``` #[inline] #[stable(feature = "atomic_access", since = "1.15.0")] - #[rustc_const_stable(feature = "const_atomic_into_inner", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0")] pub const fn into_inner(self) -> *mut T { self.p.primitive_into_inner() } @@ -2306,7 +2304,6 @@ macro_rules! atomic_int { /// /// ``` /// #![feature(atomic_from_mut)] - /// # #![cfg_attr(bootstrap, feature(inline_const))] #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] /// #[doc = concat!("let mut some_ints = [const { ", stringify!($atomic_type), "::new(0) }; 10];")] @@ -2381,7 +2378,7 @@ macro_rules! atomic_int { /// ``` #[inline] #[$stable_access] - #[rustc_const_stable(feature = "const_atomic_into_inner", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0")] pub const fn into_inner(self) -> $int_type { self.v.primitive_into_inner() } diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 78494b866b1..72f6a3b773b 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -1437,10 +1437,10 @@ impl TryFromFloatSecsError { const fn description(&self) -> &'static str { match self.kind { TryFromFloatSecsErrorKind::Negative => { - "can not convert float seconds to Duration: value is negative" + "cannot convert float seconds to Duration: value is negative" } TryFromFloatSecsErrorKind::OverflowOrNan => { - "can not convert float seconds to Duration: value is either too big or NaN" + "cannot convert float seconds to Duration: value is either too big or NaN" } } } diff --git a/library/core/src/ub_checks.rs b/library/core/src/ub_checks.rs index ff6b2d30539..1aa6a288e70 100644 --- a/library/core/src/ub_checks.rs +++ b/library/core/src/ub_checks.rs @@ -46,6 +46,8 @@ use crate::intrinsics::{self, const_eval_select}; /// variables cannot be optimized out in MIR, an innocent-looking `let` can produce enough /// debuginfo to have a measurable compile-time impact on debug builds. #[allow_internal_unstable(const_ub_checks)] // permit this to be called in stably-const fn +#[macro_export] +#[unstable(feature = "ub_checks", issue = "none")] macro_rules! assert_unsafe_precondition { ($kind:ident, $message:expr, ($($name:ident:$ty:ty = $arg:expr),*$(,)?) => $e:expr $(,)?) => { { @@ -75,11 +77,13 @@ macro_rules! assert_unsafe_precondition { } }; } -pub(crate) use assert_unsafe_precondition; +#[unstable(feature = "ub_checks", issue = "none")] +pub use assert_unsafe_precondition; /// Checking library UB is always enabled when UB-checking is done /// (and we use a reexport so that there is no unnecessary wrapper function). -pub(crate) use intrinsics::ub_checks as check_library_ub; +#[unstable(feature = "ub_checks", issue = "none")] +pub use intrinsics::ub_checks as check_library_ub; /// Determines whether we should check for language UB. /// diff --git a/library/core/tests/intrinsics.rs b/library/core/tests/intrinsics.rs index eb1e1a0b9b1..8b731cf5b25 100644 --- a/library/core/tests/intrinsics.rs +++ b/library/core/tests/intrinsics.rs @@ -100,7 +100,6 @@ fn test_const_deallocate_at_runtime() { } } -#[cfg(not(bootstrap))] #[test] fn test_three_way_compare_in_const_contexts() { use core::cmp::Ordering::{self, *}; diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 8a35fdd1857..797108a8425 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -21,7 +21,7 @@ #![feature(const_pointer_is_aligned)] #![feature(const_ptr_as_ref)] #![feature(const_ptr_write)] -#![cfg_attr(not(bootstrap), feature(const_three_way_compare))] +#![feature(const_three_way_compare)] #![feature(const_trait_impl)] #![feature(const_likely)] #![feature(core_intrinsics)] @@ -46,7 +46,6 @@ #![feature(hasher_prefixfree_extras)] #![feature(hashmap_internals)] #![feature(try_find)] -#![cfg_attr(bootstrap, feature(inline_const))] #![feature(is_sorted)] #![feature(layout_for_ptr)] #![feature(pattern)] diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 1ceff2e506c..23ae2e7dc0d 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -1360,7 +1360,7 @@ impl Literal { } /// Byte character literal. - #[stable(feature = "proc_macro_byte_character", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "proc_macro_byte_character", since = "1.79.0")] pub fn byte_character(byte: u8) -> Literal { let string = [byte].escape_ascii().to_string(); Literal::new(bridge::LitKind::Byte, &string, None) @@ -1374,7 +1374,7 @@ impl Literal { } /// C string literal. - #[stable(feature = "proc_macro_c_str_literals", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "proc_macro_c_str_literals", since = "1.79.0")] pub fn c_string(string: &CStr) -> Literal { let string = string.to_bytes().escape_ascii().to_string(); Literal::new(bridge::LitKind::CStr, &string, None) diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index cba9ff4485d..52729ba1f84 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -64,12 +64,10 @@ r-efi-alloc = { version = "1.0.0", features = ['rustc-dep-of-std'] } [features] backtrace = [ - "gimli-symbolize", 'addr2line/rustc-dep-of-std', 'object/rustc-dep-of-std', 'miniz_oxide/rustc-dep-of-std', ] -gimli-symbolize = [] panic-unwind = ["panic_unwind"] profiler = ["profiler_builtins"] diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index dc0e302a810..b98fbbf762f 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -353,6 +353,12 @@ fn default_alloc_error_hook(layout: Layout) { if unsafe { __rust_alloc_error_handler_should_panic != 0 } { panic!("memory allocation of {} bytes failed", layout.size()); } else { + // This is the default path taken on OOM, and the only path taken on stable with std. + // Crucially, it does *not* call any user-defined code, and therefore users do not have to + // worry about allocation failure causing reentrancy issues. That makes it different from + // the default `__rdl_oom` defined in alloc (i.e., the default alloc error handler that is + // called when there is no `#[alloc_error_handler]`), which triggers a regular panic and + // thus can invoke a user-defined panic hook, executing arbitrary user-defined code. rtprintpanic!("memory allocation of {} bytes failed\n", layout.size()); } } diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index de9bde51f2a..4fc82fec0ad 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -371,9 +371,10 @@ impl f32 { /// It might have a different sequence of rounding operations than `powf`, /// so the results are not guaranteed to agree. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -393,9 +394,10 @@ impl f32 { /// Raises a number to a floating point power. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -444,9 +446,10 @@ impl f32 { /// Returns `e^(self)`, (the exponential function). /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -470,9 +473,10 @@ impl f32 { /// Returns `2^(self)`. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -494,9 +498,10 @@ impl f32 { /// Returns the natural logarithm of the number. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -524,9 +529,10 @@ impl f32 { /// `self.log2()` can produce more accurate results for base 2, and /// `self.log10()` can produce more accurate results for base 10. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -548,9 +554,10 @@ impl f32 { /// Returns the base 2 logarithm of the number. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -572,9 +579,10 @@ impl f32 { /// Returns the base 10 logarithm of the number. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -599,9 +607,10 @@ impl f32 { /// * If `self <= other`: `0.0` /// * Else: `self - other` /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `fdimf` from libc on Unix /// and Windows. Note that this might change in the future. /// @@ -637,9 +646,10 @@ impl f32 { /// Returns the cube root of a number. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `cbrtf` from libc on Unix /// and Windows. Note that this might change in the future. /// @@ -666,9 +676,10 @@ impl f32 { /// right-angle triangle with other sides having length `x.abs()` and /// `y.abs()`. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `hypotf` from libc on Unix /// and Windows. Note that this might change in the future. /// @@ -693,9 +704,10 @@ impl f32 { /// Computes the sine of a number (in radians). /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -716,9 +728,10 @@ impl f32 { /// Computes the cosine of a number (in radians). /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -739,9 +752,10 @@ impl f32 { /// Computes the tangent of a number (in radians). /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `tanf` from libc on Unix and /// Windows. Note that this might change in the future. /// @@ -765,9 +779,10 @@ impl f32 { /// the range [-pi/2, pi/2] or NaN if the number is outside the range /// [-1, 1]. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `asinf` from libc on Unix /// and Windows. Note that this might change in the future. /// @@ -794,9 +809,10 @@ impl f32 { /// the range [0, pi] or NaN if the number is outside the range /// [-1, 1]. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `acosf` from libc on Unix /// and Windows. Note that this might change in the future. /// @@ -822,9 +838,10 @@ impl f32 { /// Computes the arctangent of a number. Return value is in radians in the /// range [-pi/2, pi/2]; /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `atanf` from libc on Unix /// and Windows. Note that this might change in the future. /// @@ -854,9 +871,10 @@ impl f32 { /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]` /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)` /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `atan2f` from libc on Unix /// and Windows. Note that this might change in the future. /// @@ -890,9 +908,10 @@ impl f32 { /// Simultaneously computes the sine and cosine of the number, `x`. Returns /// `(sin(x), cos(x))`. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `(f32::sin(x), /// f32::cos(x))`. Note that this might change in the future. /// @@ -919,9 +938,10 @@ impl f32 { /// Returns `e^(self) - 1` in a way that is accurate even if the /// number is close to zero. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `expm1f` from libc on Unix /// and Windows. Note that this might change in the future. /// @@ -947,9 +967,10 @@ impl f32 { /// Returns `ln(1+n)` (natural logarithm) more accurately than if /// the operations were performed separately. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `log1pf` from libc on Unix /// and Windows. Note that this might change in the future. /// @@ -975,9 +996,10 @@ impl f32 { /// Hyperbolic sine function. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `sinhf` from libc on Unix /// and Windows. Note that this might change in the future. /// @@ -1004,9 +1026,10 @@ impl f32 { /// Hyperbolic cosine function. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `coshf` from libc on Unix /// and Windows. Note that this might change in the future. /// @@ -1033,9 +1056,10 @@ impl f32 { /// Hyperbolic tangent function. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `tanhf` from libc on Unix /// and Windows. Note that this might change in the future. /// @@ -1062,9 +1086,10 @@ impl f32 { /// Inverse hyperbolic sine function. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -1089,9 +1114,10 @@ impl f32 { /// Inverse hyperbolic cosine function. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -1118,9 +1144,10 @@ impl f32 { /// Inverse hyperbolic tangent function. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -1143,9 +1170,10 @@ impl f32 { /// Gamma function. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `tgammaf` from libc on Unix /// and Windows. Note that this might change in the future. /// @@ -1171,9 +1199,10 @@ impl f32 { /// /// The integer part of the tuple indicates the sign of the gamma function. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `lgamma_r` from libc on Unix /// and Windows. Note that this might change in the future. /// diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index 944186d602c..f8c66a3e717 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -371,9 +371,10 @@ impl f64 { /// It might have a different sequence of rounding operations than `powf`, /// so the results are not guaranteed to agree. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -393,9 +394,10 @@ impl f64 { /// Raises a number to a floating point power. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -444,9 +446,10 @@ impl f64 { /// Returns `e^(self)`, (the exponential function). /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -470,9 +473,10 @@ impl f64 { /// Returns `2^(self)`. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -494,9 +498,10 @@ impl f64 { /// Returns the natural logarithm of the number. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -524,9 +529,10 @@ impl f64 { /// `self.log2()` can produce more accurate results for base 2, and /// `self.log10()` can produce more accurate results for base 10. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -548,9 +554,10 @@ impl f64 { /// Returns the base 2 logarithm of the number. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -572,9 +579,10 @@ impl f64 { /// Returns the base 10 logarithm of the number. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -599,9 +607,10 @@ impl f64 { /// * If `self <= other`: `0.0` /// * Else: `self - other` /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `fdim` from libc on Unix and /// Windows. Note that this might change in the future. /// @@ -637,9 +646,10 @@ impl f64 { /// Returns the cube root of a number. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `cbrt` from libc on Unix and /// Windows. Note that this might change in the future. /// @@ -666,9 +676,10 @@ impl f64 { /// right-angle triangle with other sides having length `x.abs()` and /// `y.abs()`. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `hypot` from libc on Unix /// and Windows. Note that this might change in the future. /// @@ -693,9 +704,10 @@ impl f64 { /// Computes the sine of a number (in radians). /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -716,9 +728,10 @@ impl f64 { /// Computes the cosine of a number (in radians). /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -739,9 +752,10 @@ impl f64 { /// Computes the tangent of a number (in radians). /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `tan` from libc on Unix and /// Windows. Note that this might change in the future. /// @@ -765,9 +779,10 @@ impl f64 { /// the range [-pi/2, pi/2] or NaN if the number is outside the range /// [-1, 1]. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `asin` from libc on Unix and /// Windows. Note that this might change in the future. /// @@ -794,9 +809,10 @@ impl f64 { /// the range [0, pi] or NaN if the number is outside the range /// [-1, 1]. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `acos` from libc on Unix and /// Windows. Note that this might change in the future. /// @@ -822,9 +838,10 @@ impl f64 { /// Computes the arctangent of a number. Return value is in radians in the /// range [-pi/2, pi/2]; /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `atan` from libc on Unix and /// Windows. Note that this might change in the future. /// @@ -854,9 +871,10 @@ impl f64 { /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]` /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)` /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `atan2` from libc on Unix /// and Windows. Note that this might change in the future. /// @@ -890,9 +908,10 @@ impl f64 { /// Simultaneously computes the sine and cosine of the number, `x`. Returns /// `(sin(x), cos(x))`. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `(f64::sin(x), /// f64::cos(x))`. Note that this might change in the future. /// @@ -919,9 +938,10 @@ impl f64 { /// Returns `e^(self) - 1` in a way that is accurate even if the /// number is close to zero. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `expm1` from libc on Unix /// and Windows. Note that this might change in the future. /// @@ -947,9 +967,10 @@ impl f64 { /// Returns `ln(1+n)` (natural logarithm) more accurately than if /// the operations were performed separately. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `log1p` from libc on Unix /// and Windows. Note that this might change in the future. /// @@ -975,9 +996,10 @@ impl f64 { /// Hyperbolic sine function. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `sinh` from libc on Unix /// and Windows. Note that this might change in the future. /// @@ -1004,9 +1026,10 @@ impl f64 { /// Hyperbolic cosine function. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `cosh` from libc on Unix /// and Windows. Note that this might change in the future. /// @@ -1033,9 +1056,10 @@ impl f64 { /// Hyperbolic tangent function. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `tanh` from libc on Unix /// and Windows. Note that this might change in the future. /// @@ -1062,9 +1086,10 @@ impl f64 { /// Inverse hyperbolic sine function. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -1089,9 +1114,10 @@ impl f64 { /// Inverse hyperbolic cosine function. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -1118,9 +1144,10 @@ impl f64 { /// Inverse hyperbolic tangent function. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// /// # Examples /// @@ -1143,9 +1170,10 @@ impl f64 { /// Gamma function. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `tgamma` from libc on Unix /// and Windows. Note that this might change in the future. /// @@ -1171,9 +1199,10 @@ impl f64 { /// /// The integer part of the tuple indicates the sign of the gamma function. /// - /// # Platform-specific precision + /// # Unspecified precision /// - /// The precision of this function varies by platform and Rust version. + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. /// This function currently corresponds to the `lgamma_r` from libc on Unix /// and Windows. Note that this might change in the future. /// diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index ff399a0acd5..dfa05671ab0 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1657,23 +1657,9 @@ fn test_file_times() { let accessed = SystemTime::UNIX_EPOCH + Duration::from_secs(12345); let modified = SystemTime::UNIX_EPOCH + Duration::from_secs(54321); times = times.set_accessed(accessed).set_modified(modified); - #[cfg(any( - windows, - target_os = "macos", - target_os = "ios", - target_os = "watchos", - target_os = "visionos", - target_os = "tvos", - ))] + #[cfg(any(windows, target_vendor = "apple"))] let created = SystemTime::UNIX_EPOCH + Duration::from_secs(32123); - #[cfg(any( - windows, - target_os = "macos", - target_os = "ios", - target_os = "watchos", - target_os = "visionos", - target_os = "tvos", - ))] + #[cfg(any(windows, target_vendor = "apple"))] { times = times.set_created(created); } @@ -1698,27 +1684,14 @@ fn test_file_times() { let metadata = file.metadata().unwrap(); assert_eq!(metadata.accessed().unwrap(), accessed); assert_eq!(metadata.modified().unwrap(), modified); - #[cfg(any( - windows, - target_os = "macos", - target_os = "ios", - target_os = "watchos", - target_os = "visionos", - target_os = "tvos", - ))] + #[cfg(any(windows, target_vendor = "apple"))] { assert_eq!(metadata.created().unwrap(), created); } } #[test] -#[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos" -))] +#[cfg(target_vendor = "apple")] fn test_file_times_pre_epoch_with_nanos() { #[cfg(target_os = "ios")] use crate::os::ios::fs::FileTimesExt; diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index 5b782fff7e5..37492e9efab 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -95,7 +95,7 @@ impl<T> Cursor<T> { /// # force_inference(&buff); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_io_structs", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_io_structs", since = "1.79.0")] pub const fn new(inner: T) -> Cursor<T> { Cursor { pos: 0, inner } } @@ -132,7 +132,7 @@ impl<T> Cursor<T> { /// let reference = buff.get_ref(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_io_structs", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_io_structs", since = "1.79.0")] pub const fn get_ref(&self) -> &T { &self.inner } @@ -178,7 +178,7 @@ impl<T> Cursor<T> { /// assert_eq!(buff.position(), 1); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_io_structs", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_io_structs", since = "1.79.0")] pub const fn position(&self) -> u64 { self.pos } @@ -364,6 +364,27 @@ where self.pos += n as u64; Ok(()) } + + fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { + let content = self.remaining_slice(); + let len = content.len(); + buf.try_reserve(len)?; + buf.extend_from_slice(content); + self.pos += len as u64; + + Ok(len) + } + + fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> { + let content = + crate::str::from_utf8(self.remaining_slice()).map_err(|_| io::Error::INVALID_UTF8)?; + let len = content.len(); + buf.try_reserve(len)?; + buf.push_str(content); + self.pos += len as u64; + + Ok(len) + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 801621c6112..f366cb8f42b 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -921,7 +921,7 @@ impl Error { /// assert!(io_error.raw_os_error().is_none()); /// # } /// ``` - #[stable(feature = "io_error_downcast", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_downcast", since = "1.79.0")] pub fn downcast<E>(self) -> result::Result<E, Self> where E: error::Error + Send + Sync + 'static, diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index dd7e0725176..46f04c7cd39 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -329,8 +329,9 @@ impl Read for &[u8] { #[inline] fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> { let content = str::from_utf8(self).map_err(|_| io::Error::INVALID_UTF8)?; - buf.push_str(content); let len = self.len(); + buf.try_reserve(len)?; + buf.push_str(content); *self = &self[len..]; Ok(len) } @@ -473,14 +474,8 @@ impl<A: Allocator> Read for VecDeque<u8, A> { #[inline] fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> { - // We have to use a single contiguous slice because the `VecDequeue` might be split in the - // middle of an UTF-8 character. - let len = self.len(); - let content = self.make_contiguous(); - let string = str::from_utf8(content).map_err(|_| io::Error::INVALID_UTF8)?; - buf.push_str(string); - self.clear(); - Ok(len) + // SAFETY: We only append to the buffer + unsafe { io::append_to_string(buf, |buf| self.read_to_end(buf)) } } } diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 98973a43e1d..af055152cbe 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -266,7 +266,7 @@ //! its file descriptors with no operations being performed by any other part of the program. //! //! Note that exclusive ownership of a file descriptor does *not* imply exclusive ownership of the -//! underlying kernel object that the file descriptor references (also called "file description" on +//! underlying kernel object that the file descriptor references (also called "open file description" on //! some operating systems). File descriptors basically work like [`Arc`]: when you receive an owned //! file descriptor, you cannot know whether there are any other file descriptors that reference the //! same kernel object. However, when you create a new kernel object, you know that you are holding @@ -384,7 +384,10 @@ where { let mut g = Guard { len: buf.len(), buf: buf.as_mut_vec() }; let ret = f(g.buf); - if str::from_utf8(&g.buf[g.len..]).is_err() { + + // SAFETY: the caller promises to only append data to `buf` + let appended = g.buf.get_unchecked(g.len..); + if str::from_utf8(appended).is_err() { ret.and_then(|_| Err(Error::INVALID_UTF8)) } else { g.len = g.buf.len(); diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs index 266a447f06b..b4c4dffc371 100644 --- a/library/std/src/io/util.rs +++ b/library/std/src/io/util.rs @@ -51,7 +51,7 @@ pub struct Empty; /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "const_io_structs", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_io_structs", since = "1.79.0")] pub const fn empty() -> Empty { Empty } @@ -173,7 +173,7 @@ pub struct Repeat { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "const_io_structs", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_io_structs", since = "1.79.0")] pub const fn repeat(byte: u8) -> Repeat { Repeat { byte } } @@ -276,7 +276,7 @@ pub struct Sink; /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "const_io_structs", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_io_structs", since = "1.79.0")] pub const fn sink() -> Sink { Sink } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 3d4f1872f38..27b46b46204 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -224,7 +224,7 @@ `#![no_std]` or overriding this warning by enabling this feature." ) )] -#![cfg_attr(not(bootstrap), rustc_preserve_ub_checks)] +#![rustc_preserve_ub_checks] #![doc( html_playground_url = "https://play.rust-lang.org/", issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", @@ -356,6 +356,7 @@ #![feature(str_internals)] #![feature(strict_provenance)] #![feature(strict_provenance_atomic_ptr)] +#![feature(ub_checks)] // tidy-alphabetical-end // // Library features (alloc): @@ -591,7 +592,6 @@ pub mod net; pub mod num; pub mod os; pub mod panic; -#[cfg(not(bootstrap))] #[unstable(feature = "core_pattern_types", issue = "none")] pub mod pat; pub mod path; diff --git a/library/std/src/num.rs b/library/std/src/num.rs index fbe68f7e303..8910cdea7c0 100644 --- a/library/std/src/num.rs +++ b/library/std/src/num.rs @@ -23,7 +23,7 @@ pub use core::num::{FpCategory, ParseFloatError, ParseIntError, TryFromIntError} )] pub use core::num::ZeroablePrimitive; -#[stable(feature = "generic_nonzero", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "generic_nonzero", since = "1.79.0")] pub use core::num::NonZero; #[stable(feature = "signed_nonzero", since = "1.34.0")] diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index 010ce4e5076..8c7fc4cb2e4 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -176,7 +176,12 @@ impl Drop for OwnedFd { // something like EINTR), we might close another valid file descriptor // opened after we closed ours. #[cfg(not(target_os = "hermit"))] - let _ = libc::close(self.fd); + { + #[cfg(unix)] + crate::sys::fs::debug_assert_fd_is_open(self.fd); + + let _ = libc::close(self.fd); + } #[cfg(target_os = "hermit")] let _ = hermit_abi::close(self.fd); } diff --git a/library/std/src/os/unix/io/mod.rs b/library/std/src/os/unix/io/mod.rs index 827278f8b26..6d4090ee31c 100644 --- a/library/std/src/os/unix/io/mod.rs +++ b/library/std/src/os/unix/io/mod.rs @@ -12,8 +12,8 @@ //! | Type | Analogous to | //! | ------------------ | ------------ | //! | [`RawFd`] | `*const _` | -//! | [`BorrowedFd<'a>`] | `&'a _` | -//! | [`OwnedFd`] | `Box<_>` | +//! | [`BorrowedFd<'a>`] | `&'a Arc<_>` | +//! | [`OwnedFd`] | `Arc<_>` | //! //! Like raw pointers, `RawFd` values are primitive values. And in new code, //! they should be considered unsafe to do I/O on (analogous to dereferencing @@ -23,22 +23,31 @@ //! either by adding `unsafe` to APIs that dereference `RawFd` values, or by //! using to `BorrowedFd` or `OwnedFd` instead. //! +//! The use of `Arc` for borrowed/owned file descriptors may be surprising. Unix file descriptors +//! are mere references to internal kernel objects called "open file descriptions", and the same +//! open file description can be referenced by multiple file descriptors (e.g. if `dup` is used). +//! State such as the offset within the file is shared among all file descriptors that refer to the +//! same open file description, and the kernel internally does reference-counting to only close the +//! underlying resource once all file descriptors referencing it are closed. That's why `Arc` (and +//! not `Box`) is the closest Rust analogy to an "owned" file descriptor. +//! //! Like references, `BorrowedFd` values are tied to a lifetime, to ensure //! that they don't outlive the resource they point to. These are safe to //! use. `BorrowedFd` values may be used in APIs which provide safe access to //! any system call except for: //! //! - `close`, because that would end the dynamic lifetime of the resource -//! without ending the lifetime of the file descriptor. +//! without ending the lifetime of the file descriptor. (Equivalently: +//! an `&Arc<_>` cannot be `drop`ed.) //! //! - `dup2`/`dup3`, in the second argument, because this argument is -//! closed and assigned a new resource, which may break the assumptions +//! closed and assigned a new resource, which may break the assumptions of //! other code using that file descriptor. //! -//! `BorrowedFd` values may be used in APIs which provide safe access to `dup` -//! system calls, so types implementing `AsFd` or `From<OwnedFd>` should not -//! assume they always have exclusive access to the underlying file -//! description. +//! `BorrowedFd` values may be used in APIs which provide safe access to `dup` system calls, so code +//! working with `OwnedFd` cannot assume to have exclusive access to the underlying open file +//! description. (Equivalently: `&Arc` may be used in APIs that provide safe access to `clone`, so +//! code working with an `Arc` cannot assume that the reference count is 1.) //! //! `BorrowedFd` values may also be used with `mmap`, since `mmap` uses the //! provided file descriptor in a manner similar to `dup` and does not require @@ -52,8 +61,10 @@ //! take full responsibility for ensuring that safe Rust code cannot evoke //! undefined behavior through it. //! -//! Like boxes, `OwnedFd` values conceptually own the resource they point to, -//! and free (close) it when they are dropped. +//! Like `Arc`, `OwnedFd` values conceptually own one reference to the resource they point to, +//! and decrement the reference count when they are dropped (by calling `close`). +//! When the reference count reaches 0, the underlying open file description will be freed +//! by the kernel. //! //! See the [`io` module docs][io-safety] for a general explanation of I/O safety. //! diff --git a/library/std/src/os/unix/net/mod.rs b/library/std/src/os/unix/net/mod.rs index 16d9cd915ac..3e45e3533ed 100644 --- a/library/std/src/os/unix/net/mod.rs +++ b/library/std/src/os/unix/net/mod.rs @@ -17,14 +17,10 @@ mod tests; target_os = "linux", target_os = "dragonfly", target_os = "freebsd", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos", - target_os = "macos", target_os = "netbsd", target_os = "openbsd", target_os = "nto", + target_vendor = "apple", ))] mod ucred; @@ -44,14 +40,10 @@ pub use self::stream::*; target_os = "linux", target_os = "dragonfly", target_os = "freebsd", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos", - target_os = "macos", target_os = "netbsd", target_os = "openbsd", target_os = "nto", + target_vendor = "apple", ))] #[unstable(feature = "peer_credentials_unix_socket", issue = "42839", reason = "unstable")] pub use self::ucred::*; diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index 82b24dca1c4..19fc7b3d853 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -3,14 +3,10 @@ target_os = "linux", target_os = "dragonfly", target_os = "freebsd", - target_os = "ios", - target_os = "tvos", - target_os = "macos", - target_os = "watchos", - target_os = "visionos", target_os = "netbsd", target_os = "openbsd", - target_os = "nto" + target_os = "nto", + target_vendor = "apple", ))] use super::{peer_cred, UCred}; #[cfg(any(doc, target_os = "android", target_os = "linux"))] @@ -231,14 +227,10 @@ impl UnixStream { target_os = "linux", target_os = "dragonfly", target_os = "freebsd", - target_os = "ios", - target_os = "tvos", - target_os = "macos", - target_os = "watchos", - target_os = "visionos", target_os = "netbsd", target_os = "openbsd", - target_os = "nto" + target_os = "nto", + target_vendor = "apple", ))] pub fn peer_cred(&self) -> io::Result<UCred> { peer_cred(self) diff --git a/library/std/src/os/unix/net/ucred.rs b/library/std/src/os/unix/net/ucred.rs index 3a752a53a50..1497e730bbf 100644 --- a/library/std/src/os/unix/net/ucred.rs +++ b/library/std/src/os/unix/net/ucred.rs @@ -35,14 +35,8 @@ pub(super) use self::impl_linux::peer_cred; ))] pub(super) use self::impl_bsd::peer_cred; -#[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos" -))] -pub(super) use self::impl_mac::peer_cred; +#[cfg(target_vendor = "apple")] +pub(super) use self::impl_apple::peer_cred; #[cfg(any(target_os = "linux", target_os = "android"))] mod impl_linux { @@ -103,14 +97,8 @@ mod impl_bsd { } } -#[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos" -))] -mod impl_mac { +#[cfg(target_vendor = "apple")] +mod impl_apple { use super::UCred; use crate::os::unix::io::AsRawFd; use crate::os::unix::net::UnixStream; diff --git a/library/std/src/os/unix/net/ucred/tests.rs b/library/std/src/os/unix/net/ucred/tests.rs index 2a0797877c6..a6cc81318fc 100644 --- a/library/std/src/os/unix/net/ucred/tests.rs +++ b/library/std/src/os/unix/net/ucred/tests.rs @@ -7,12 +7,8 @@ use libc::{getegid, geteuid, getpid}; target_os = "linux", target_os = "dragonfly", target_os = "freebsd", - target_os = "ios", - target_os = "tvos", - target_os = "macos", - target_os = "watchos", - target_os = "visionos", - target_os = "openbsd" + target_os = "openbsd", + target_vendor = "apple", ))] fn test_socket_pair() { // Create two connected sockets and get their peer credentials. They should be equal. @@ -28,14 +24,7 @@ fn test_socket_pair() { } #[test] -#[cfg(any( - target_os = "linux", - target_os = "ios", - target_os = "macos", - target_os = "watchos", - target_os = "visionos", - target_os = "tvos", -))] +#[cfg(any(target_os = "linux", target_vendor = "apple"))] fn test_socket_pair_pids(arg: Type) -> RetType { // Create two connected sockets and get their peer credentials. let (sock_a, sock_b) = UnixStream::pair().unwrap(); diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 85355435100..79d800ff072 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -3374,7 +3374,7 @@ impl Error for StripPrefixError { /// /// [posix-semantics]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13 /// [windows-path]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfullpathnamew -#[stable(feature = "absolute_path", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "absolute_path", since = "1.79.0")] pub fn absolute<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> { let path = path.as_ref(); if path.as_os_str().is_empty() { diff --git a/library/std/src/prelude/common.rs b/library/std/src/prelude/common.rs index f61e04e02b6..01936734d75 100644 --- a/library/std/src/prelude/common.rs +++ b/library/std/src/prelude/common.rs @@ -84,7 +84,6 @@ pub use core::prelude::v1::cfg_eval; )] pub use core::prelude::v1::type_ascribe; -#[cfg(not(bootstrap))] // Do not `doc(no_inline)` either. #[unstable( feature = "deref_patterns", diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 4a73a9be88b..d1848224251 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -486,6 +486,10 @@ impl Read for ChildStderr { fn is_read_vectored(&self) -> bool { self.inner.is_read_vectored() } + + fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { + self.inner.read_to_end(buf) + } } impl AsInner<AnonPipe> for ChildStderr { diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index 59e118f81ab..46f691d7b75 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -74,7 +74,7 @@ macro_rules! rtunwrap { // // Since 2014, the Rust runtime on Unix has set the `SIGPIPE` handler to // `SIG_IGN`. Applications have good reasons to want a different behavior -// though, so there is a `#[unix_sigpipe = "..."]` attribute on `fn main()` that +// though, so there is a `-Zon-broken-pipe` compiler flag that // can be used to select how `SIGPIPE` shall be setup (if changed at all) before // `fn main()` is called. See <https://github.com/rust-lang/rust/issues/97889> // for more info. diff --git a/library/std/src/sys/pal/sgx/thread.rs b/library/std/src/sys/pal/sgx/thread.rs index e2df57b1a1f..7d271e6d2b6 100644 --- a/library/std/src/sys/pal/sgx/thread.rs +++ b/library/std/src/sys/pal/sgx/thread.rs @@ -67,7 +67,7 @@ mod task_queue { pub mod wait_notify { use crate::pin::Pin; use crate::sync::Arc; - use crate::sys_common::thread_parking::Parker; + use crate::sys::sync::Parker; pub struct Notifier(Arc<Parker>); diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs index c392a0ea264..6dd465a12ed 100644 --- a/library/std/src/sys/pal/teeos/mod.rs +++ b/library/std/src/sys/pal/teeos/mod.rs @@ -30,8 +30,6 @@ pub mod thread; pub mod thread_local_dtor; #[path = "../unix/thread_local_key.rs"] pub mod thread_local_key; -#[path = "../unsupported/thread_parking.rs"] -pub mod thread_parking; #[allow(non_upper_case_globals)] #[path = "../unix/time.rs"] pub mod time; diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs index 562b00c2c01..48b74df1384 100644 --- a/library/std/src/sys/pal/uefi/mod.rs +++ b/library/std/src/sys/pal/uefi/mod.rs @@ -30,8 +30,6 @@ pub mod stdio; pub mod thread; #[path = "../unsupported/thread_local_key.rs"] pub mod thread_local_key; -#[path = "../unsupported/thread_parking.rs"] -pub mod thread_parking; pub mod time; mod helpers; diff --git a/library/std/src/sys/pal/unix/args.rs b/library/std/src/sys/pal/unix/args.rs index afe703bcb2f..2a3298e8b4c 100644 --- a/library/std/src/sys/pal/unix/args.rs +++ b/library/std/src/sys/pal/unix/args.rs @@ -168,13 +168,7 @@ mod imp { } } -#[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "watchos", - target_os = "visionos", - target_os = "tvos" -))] +#[cfg(target_vendor = "apple")] mod imp { use super::Args; use crate::ffi::CStr; @@ -215,12 +209,7 @@ mod imp { // for i in (0..[args count]) // res.push([args objectAtIndex:i]) // res - #[cfg(any( - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos" - ))] + #[cfg(not(target_os = "macos"))] pub fn args() -> Args { use crate::ffi::{c_char, c_void, OsString}; use crate::mem; diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index c37332ac6b1..32cdd13fbeb 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -20,14 +20,7 @@ use crate::sys::time::SystemTime; use crate::sys::{cvt, cvt_r}; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; -#[cfg(any( - all(target_os = "linux", target_env = "gnu"), - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos", -))] +#[cfg(any(all(target_os = "linux", target_env = "gnu"), target_vendor = "apple"))] use crate::sys::weak::syscall; #[cfg(any(target_os = "android", target_os = "macos", target_os = "solaris"))] use crate::sys::weak::weak; @@ -35,13 +28,9 @@ use crate::sys::weak::weak; use libc::{c_int, mode_t}; #[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos", target_os = "solaris", - all(target_os = "linux", target_env = "gnu") + all(target_os = "linux", target_env = "gnu"), + target_vendor = "apple", ))] use libc::c_char; #[cfg(any( @@ -375,13 +364,7 @@ pub struct FilePermissions { pub struct FileTimes { accessed: Option<SystemTime>, modified: Option<SystemTime>, - #[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "watchos", - target_os = "visionos", - target_os = "tvos" - ))] + #[cfg(target_vendor = "apple")] created: Option<SystemTime>, } @@ -554,15 +537,7 @@ impl FileAttr { SystemTime::new(self.stat.st_atim.tv_sec as i64, self.stat.st_atim.tv_nsec as i64) } - #[cfg(any( - target_os = "freebsd", - target_os = "openbsd", - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos", - ))] + #[cfg(any(target_os = "freebsd", target_os = "openbsd", target_vendor = "apple"))] pub fn created(&self) -> io::Result<SystemTime> { SystemTime::new(self.stat.st_birthtime as i64, self.stat.st_birthtime_nsec as i64) } @@ -570,12 +545,8 @@ impl FileAttr { #[cfg(not(any( target_os = "freebsd", target_os = "openbsd", - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos", target_os = "vita", + target_vendor = "apple", )))] pub fn created(&self) -> io::Result<SystemTime> { cfg_has_statx! { @@ -655,13 +626,7 @@ impl FileTimes { self.modified = Some(t); } - #[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "watchos", - target_os = "visionos", - target_os = "tvos" - ))] + #[cfg(target_vendor = "apple")] pub fn set_created(&mut self, t: SystemTime) { self.created = Some(t); } @@ -864,8 +829,43 @@ impl Iterator for ReadDir { } } +/// Aborts the process if a file desceriptor is not open, if debug asserts are enabled +/// +/// Many IO syscalls can't be fully trusted about EBADF error codes because those +/// might get bubbled up from a remote FUSE server rather than the file descriptor +/// in the current process being invalid. +/// +/// So we check file flags instead which live on the file descriptor and not the underlying file. +/// The downside is that it costs an extra syscall, so we only do it for debug. +#[inline] +pub(crate) fn debug_assert_fd_is_open(fd: RawFd) { + use crate::sys::os::errno; + + // this is similar to assert_unsafe_precondition!() but it doesn't require const + if core::ub_checks::check_library_ub() { + if unsafe { libc::fcntl(fd, libc::F_GETFD) } == -1 && errno() == libc::EBADF { + rtabort!("IO Safety violation: owned file descriptor already closed"); + } + } +} + impl Drop for Dir { fn drop(&mut self) { + // dirfd isn't supported everywhere + #[cfg(not(any( + miri, + target_os = "redox", + target_os = "nto", + target_os = "vita", + target_os = "hurd", + target_os = "espidf", + target_os = "fuchsia", + target_os = "horizon", + )))] + { + let fd = unsafe { libc::dirfd(self.0) }; + debug_assert_fd_is_open(fd); + } let r = unsafe { libc::closedir(self.0) }; assert!( r == 0 || crate::io::Error::last_os_error().is_interrupted(), @@ -962,11 +962,6 @@ impl DirEntry { } #[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos", target_os = "linux", target_os = "emscripten", target_os = "android", @@ -983,6 +978,7 @@ impl DirEntry { target_os = "aix", target_os = "nto", target_os = "hurd", + target_vendor = "apple", ))] pub fn ino(&self) -> u64 { self.entry.d_ino as u64 @@ -999,15 +995,11 @@ impl DirEntry { } #[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos", target_os = "netbsd", target_os = "openbsd", target_os = "freebsd", - target_os = "dragonfly" + target_os = "dragonfly", + target_vendor = "apple", ))] fn name_bytes(&self) -> &[u8] { use crate::slice; @@ -1019,15 +1011,11 @@ impl DirEntry { } } #[cfg(not(any( - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos", target_os = "netbsd", target_os = "openbsd", target_os = "freebsd", - target_os = "dragonfly" + target_os = "dragonfly", + target_vendor = "apple", )))] fn name_bytes(&self) -> &[u8] { self.name_cstr().to_bytes() @@ -1205,23 +1193,11 @@ impl File { cvt_r(|| unsafe { os_fsync(self.as_raw_fd()) })?; return Ok(()); - #[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos", - ))] + #[cfg(target_vendor = "apple")] unsafe fn os_fsync(fd: c_int) -> c_int { libc::fcntl(fd, libc::F_FULLFSYNC) } - #[cfg(not(any( - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos", - )))] + #[cfg(not(target_vendor = "apple"))] unsafe fn os_fsync(fd: c_int) -> c_int { libc::fsync(fd) } @@ -1231,13 +1207,7 @@ impl File { cvt_r(|| unsafe { os_datasync(self.as_raw_fd()) })?; return Ok(()); - #[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos", - ))] + #[cfg(target_vendor = "apple")] unsafe fn os_datasync(fd: c_int) -> c_int { libc::fcntl(fd, libc::F_FULLFSYNC) } @@ -1256,16 +1226,12 @@ impl File { #[cfg(not(any( target_os = "android", target_os = "freebsd", - target_os = "ios", - target_os = "tvos", target_os = "linux", - target_os = "macos", target_os = "netbsd", target_os = "openbsd", - target_os = "watchos", - target_os = "visionos", target_os = "nto", target_os = "hurd", + target_vendor = "apple", )))] unsafe fn os_datasync(fd: c_int) -> c_int { libc::fsync(fd) @@ -1374,7 +1340,7 @@ impl File { io::ErrorKind::Unsupported, "setting file times not supported", )) - } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))] { + } else if #[cfg(target_vendor = "apple")] { let mut buf = [mem::MaybeUninit::<libc::timespec>::uninit(); 3]; let mut num_times = 0; let mut attrlist: libc::attrlist = unsafe { mem::zeroed() }; @@ -1906,15 +1872,7 @@ fn open_to_and_set_permissions( Ok((writer, writer_metadata)) } -#[cfg(not(any( - target_os = "linux", - target_os = "android", - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos", -)))] +#[cfg(not(any(target_os = "linux", target_os = "android", target_vendor = "apple")))] pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { let (mut reader, reader_metadata) = open_from(from)?; let (mut writer, _) = open_to_and_set_permissions(to, reader_metadata)?; @@ -1940,13 +1898,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { } } -#[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "watchos", - target_os = "visionos", - target_os = "tvos" -))] +#[cfg(target_vendor = "apple")] pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { use crate::sync::atomic::{AtomicBool, Ordering}; diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index 3ef43a923a3..1ac5729c02f 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -55,8 +55,8 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { // want! // // Hence, we set SIGPIPE to ignore when the program starts up in order - // to prevent this problem. Add `#[unix_sigpipe = "..."]` above `fn main()` to - // alter this behavior. + // to prevent this problem. Use `-Zon-broken-pipe=...` to alter this + // behavior. reset_sigpipe(sigpipe); stack_overflow::init(); @@ -78,16 +78,12 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { target_os = "emscripten", target_os = "fuchsia", target_os = "vxworks", - // The poll on Darwin doesn't set POLLNVAL for closed fds. - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos", target_os = "redox", target_os = "l4re", target_os = "horizon", target_os = "vita", + // The poll on Darwin doesn't set POLLNVAL for closed fds. + target_vendor = "apple", )))] 'poll: { use crate::sys::os::errno; @@ -194,7 +190,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { _ => unreachable!(), }; if sigpipe_attr_specified { - UNIX_SIGPIPE_ATTR_SPECIFIED.store(true, crate::sync::atomic::Ordering::Relaxed); + ON_BROKEN_PIPE_FLAG_USED.store(true, crate::sync::atomic::Ordering::Relaxed); } if let Some(handler) = handler { rtassert!(signal(libc::SIGPIPE, handler) != libc::SIG_ERR); @@ -214,7 +210,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { target_os = "fuchsia", target_os = "horizon", )))] -static UNIX_SIGPIPE_ATTR_SPECIFIED: crate::sync::atomic::AtomicBool = +static ON_BROKEN_PIPE_FLAG_USED: crate::sync::atomic::AtomicBool = crate::sync::atomic::AtomicBool::new(false); #[cfg(not(any( @@ -223,8 +219,8 @@ static UNIX_SIGPIPE_ATTR_SPECIFIED: crate::sync::atomic::AtomicBool = target_os = "fuchsia", target_os = "horizon", )))] -pub(crate) fn unix_sigpipe_attr_specified() -> bool { - UNIX_SIGPIPE_ATTR_SPECIFIED.load(crate::sync::atomic::Ordering::Relaxed) +pub(crate) fn on_broken_pipe_flag_used() -> bool { + ON_BROKEN_PIPE_FLAG_USED.load(crate::sync::atomic::Ordering::Relaxed) } // SAFETY: must be called only once during runtime cleanup. @@ -406,7 +402,7 @@ cfg_if::cfg_if! { } else if #[cfg(target_os = "macos")] { #[link(name = "System")] extern "C" {} - } else if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))] { + } else if #[cfg(all(target_vendor = "apple", not(target_os = "macos")))] { #[link(name = "System")] #[link(name = "objc")] #[link(name = "Foundation", kind = "framework")] diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index 96492fedece..3a281525f8d 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -63,17 +63,7 @@ extern "C" { )] #[cfg_attr(any(target_os = "solaris", target_os = "illumos"), link_name = "___errno")] #[cfg_attr(target_os = "nto", link_name = "__get_errno_ptr")] - #[cfg_attr( - any( - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "freebsd", - target_os = "watchos", - target_os = "visionos", - ), - link_name = "__error" - )] + #[cfg_attr(any(target_os = "freebsd", target_vendor = "apple"), link_name = "__error")] #[cfg_attr(target_os = "haiku", link_name = "_errnop")] #[cfg_attr(target_os = "aix", link_name = "_Errno")] fn errno_location() -> *mut c_int; @@ -431,13 +421,7 @@ pub fn current_exe() -> io::Result<PathBuf> { Ok(PathBuf::from(OsString::from_vec(e))) } -#[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "watchos", - target_os = "visionos", - target_os = "tvos" -))] +#[cfg(target_vendor = "apple")] pub fn current_exe() -> io::Result<PathBuf> { unsafe { let mut sz: u32 = 0; @@ -703,32 +687,26 @@ pub fn home_dir() -> Option<PathBuf> { #[cfg(any( target_os = "android", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos", target_os = "emscripten", target_os = "redox", target_os = "vxworks", target_os = "espidf", target_os = "horizon", target_os = "vita", + all(target_vendor = "apple", not(target_os = "macos")), ))] unsafe fn fallback() -> Option<OsString> { None } #[cfg(not(any( target_os = "android", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos", target_os = "emscripten", target_os = "redox", target_os = "vxworks", target_os = "espidf", target_os = "horizon", target_os = "vita", + all(target_vendor = "apple", not(target_os = "macos")), )))] unsafe fn fallback() -> Option<OsString> { let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) { diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs index d65657790c4..e2fca8c7e63 100644 --- a/library/std/src/sys/pal/unix/process/process_unix.rs +++ b/library/std/src/sys/pal/unix/process/process_unix.rs @@ -353,11 +353,11 @@ impl Command { // Inherit the signal mask from the parent rather than resetting it (i.e. do not call // pthread_sigmask). - // If #[unix_sigpipe] is specified, don't reset SIGPIPE to SIG_DFL. - // If #[unix_sigpipe] is not specified, reset SIGPIPE to SIG_DFL for backward compatibility. + // If -Zon-broken-pipe is used, don't reset SIGPIPE to SIG_DFL. + // If -Zon-broken-pipe is not used, reset SIGPIPE to SIG_DFL for backward compatibility. // - // #[unix_sigpipe] is an opportunity to change the default here. - if !crate::sys::pal::unix_sigpipe_attr_specified() { + // -Zon-broken-pipe is an opportunity to change the default here. + if !crate::sys::pal::on_broken_pipe_flag_used() { #[cfg(target_os = "android")] // see issue #88585 { let mut action: libc::sigaction = mem::zeroed(); @@ -420,13 +420,11 @@ impl Command { } #[cfg(not(any( - target_os = "macos", - target_os = "tvos", - target_os = "watchos", target_os = "freebsd", all(target_os = "linux", target_env = "gnu"), all(target_os = "linux", target_env = "musl"), target_os = "nto", + target_vendor = "apple", )))] fn posix_spawn( &mut self, @@ -439,14 +437,11 @@ impl Command { // Only support platforms for which posix_spawn() can return ENOENT // directly. #[cfg(any( - target_os = "macos", - // FIXME: `target_os = "ios"`? - target_os = "tvos", - target_os = "watchos", target_os = "freebsd", all(target_os = "linux", target_env = "gnu"), all(target_os = "linux", target_env = "musl"), target_os = "nto", + target_vendor = "apple", ))] fn posix_spawn( &mut self, @@ -455,7 +450,7 @@ impl Command { ) -> io::Result<Option<Process>> { use crate::mem::MaybeUninit; use crate::sys::weak::weak; - use crate::sys::{self, cvt_nz, unix_sigpipe_attr_specified}; + use crate::sys::{self, cvt_nz, on_broken_pipe_flag_used}; if self.get_gid().is_some() || self.get_uid().is_some() @@ -530,7 +525,7 @@ impl Command { } let addchdir = match self.get_cwd() { Some(cwd) => { - if cfg!(any(target_os = "macos", target_os = "tvos", target_os = "watchos")) { + if cfg!(target_vendor = "apple") { // There is a bug in macOS where a relative executable // path like "../myprogram" will cause `posix_spawn` to // successfully launch the program, but erroneously return @@ -617,11 +612,11 @@ impl Command { // Inherit the signal mask from this process rather than resetting it (i.e. do not call // posix_spawnattr_setsigmask). - // If #[unix_sigpipe] is specified, don't reset SIGPIPE to SIG_DFL. - // If #[unix_sigpipe] is not specified, reset SIGPIPE to SIG_DFL for backward compatibility. + // If -Zon-broken-pipe is used, don't reset SIGPIPE to SIG_DFL. + // If -Zon-broken-pipe is not used, reset SIGPIPE to SIG_DFL for backward compatibility. // - // #[unix_sigpipe] is an opportunity to change the default here. - if !unix_sigpipe_attr_specified() { + // -Zon-broken-pipe is an opportunity to change the default here. + if !on_broken_pipe_flag_used() { let mut default_set = MaybeUninit::<libc::sigset_t>::uninit(); cvt(sigemptyset(default_set.as_mut_ptr()))?; cvt(sigaddset(default_set.as_mut_ptr(), libc::SIGPIPE))?; @@ -1040,24 +1035,20 @@ fn signal_string(signal: i32) -> &'static str { #[cfg(any(target_os = "linux", target_os = "nto"))] libc::SIGPWR => " (SIGPWR)", #[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "tvos", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", target_os = "dragonfly", target_os = "nto", + target_vendor = "apple", ))] libc::SIGEMT => " (SIGEMT)", #[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "tvos", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", - target_os = "dragonfly" + target_os = "dragonfly", + target_vendor = "apple", ))] libc::SIGINFO => " (SIGINFO)", #[cfg(target_os = "hurd")] diff --git a/library/std/src/sys/pal/unix/rand.rs b/library/std/src/sys/pal/unix/rand.rs index de087d98eb8..d8f227b4ef4 100644 --- a/library/std/src/sys/pal/unix/rand.rs +++ b/library/std/src/sys/pal/unix/rand.rs @@ -12,11 +12,6 @@ pub fn hashmap_random_keys() -> (u64, u64) { #[cfg(all( unix, - not(target_os = "macos"), - not(target_os = "ios"), - not(target_os = "tvos"), - not(target_os = "watchos"), - not(target_os = "visionos"), not(target_os = "openbsd"), not(target_os = "netbsd"), not(target_os = "fuchsia"), @@ -24,6 +19,7 @@ pub fn hashmap_random_keys() -> (u64, u64) { not(target_os = "vxworks"), not(target_os = "emscripten"), not(target_os = "vita"), + not(target_vendor = "apple"), ))] mod imp { use crate::fs::File; diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index 6a6bfc77a85..853ef8736de 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -150,13 +150,7 @@ impl Thread { } } - #[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "watchos", - target_os = "visionos", - target_os = "tvos" - ))] + #[cfg(target_vendor = "apple")] pub fn set_name(name: &CStr) { unsafe { let name = truncate_cstr::<{ libc::MAXTHREADNAMESIZE }>(name); @@ -301,14 +295,10 @@ impl Drop for Thread { #[cfg(any( target_os = "linux", - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos", target_os = "nto", target_os = "solaris", target_os = "illumos", + target_vendor = "apple", ))] fn truncate_cstr<const MAX_WITH_NUL: usize>(cstr: &CStr) -> [libc::c_char; MAX_WITH_NUL] { let mut result = [0; MAX_WITH_NUL]; @@ -325,11 +315,9 @@ pub fn available_parallelism() -> io::Result<NonZero<usize>> { target_os = "emscripten", target_os = "fuchsia", target_os = "hurd", - target_os = "ios", - target_os = "tvos", target_os = "linux", - target_os = "macos", target_os = "aix", + target_vendor = "apple", ))] { #[allow(unused_assignments)] #[allow(unused_mut)] diff --git a/library/std/src/sys/pal/unix/thread_local_dtor.rs b/library/std/src/sys/pal/unix/thread_local_dtor.rs index 1164c1782f4..75db6e112ed 100644 --- a/library/std/src/sys/pal/unix/thread_local_dtor.rs +++ b/library/std/src/sys/pal/unix/thread_local_dtor.rs @@ -76,13 +76,7 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { // workaround below is to register, via _tlv_atexit, a custom DTOR list once per // thread. thread_local dtors are pushed to the DTOR list without calling // _tlv_atexit. -#[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "watchos", - target_os = "visionos", - target_os = "tvos" -))] +#[cfg(target_vendor = "apple")] pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { use crate::cell::{Cell, RefCell}; use crate::ptr; diff --git a/library/std/src/sys/pal/unix/thread_parking/netbsd.rs b/library/std/src/sys/pal/unix/thread_parking.rs index 5eeb37f8763..66ffc006057 100644 --- a/library/std/src/sys/pal/unix/thread_parking/netbsd.rs +++ b/library/std/src/sys/pal/unix/thread_parking.rs @@ -1,3 +1,7 @@ +// Only used on NetBSD. If other platforms start using id-based parking, use +// separate modules for each platform. +#![cfg(target_os = "netbsd")] + use crate::ffi::{c_int, c_void}; use crate::ptr; use crate::time::Duration; diff --git a/library/std/src/sys/pal/unix/thread_parking/mod.rs b/library/std/src/sys/pal/unix/thread_parking/mod.rs deleted file mode 100644 index 3348d4b366d..00000000000 --- a/library/std/src/sys/pal/unix/thread_parking/mod.rs +++ /dev/null @@ -1,33 +0,0 @@ -//! Thread parking on systems without futex support. - -#![cfg(not(any( - target_os = "linux", - target_os = "android", - all(target_os = "emscripten", target_feature = "atomics"), - target_os = "freebsd", - target_os = "openbsd", - target_os = "dragonfly", - target_os = "fuchsia", -)))] - -cfg_if::cfg_if! { - if #[cfg(all( - any( - target_os = "macos", - target_os = "ios", - target_os = "watchos", - target_os = "visionos", - target_os = "tvos", - ), - not(miri), - ))] { - mod darwin; - pub use darwin::Parker; - } else if #[cfg(target_os = "netbsd")] { - mod netbsd; - pub use netbsd::{current, park, park_timeout, unpark, ThreadId}; - } else { - mod pthread; - pub use pthread::Parker; - } -} diff --git a/library/std/src/sys/pal/unix/time.rs b/library/std/src/sys/pal/unix/time.rs index e69775be8cf..535fe6b27d9 100644 --- a/library/std/src/sys/pal/unix/time.rs +++ b/library/std/src/sys/pal/unix/time.rs @@ -86,13 +86,7 @@ impl Timespec { // Please note that Apple OS nonetheless accepts the standard unix format when // setting file times, which makes this compensation round-trippable and generally // transparent. - #[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos", - ))] + #[cfg(target_vendor = "apple")] let (tv_sec, tv_nsec) = if (tv_sec <= 0 && tv_sec > i64::MIN) && (tv_nsec < 0 && tv_nsec > -1_000_000_000) { (tv_sec - 1, tv_nsec + 1_000_000_000) @@ -275,21 +269,9 @@ impl Instant { // // Instant on macos was historically implemented using mach_absolute_time; // we preserve this value domain out of an abundance of caution. - #[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "watchos", - target_os = "visionos", - target_os = "tvos" - ))] + #[cfg(target_vendor = "apple")] const clock_id: libc::clockid_t = libc::CLOCK_UPTIME_RAW; - #[cfg(not(any( - target_os = "macos", - target_os = "ios", - target_os = "watchos", - target_os = "visionos", - target_os = "tvos" - )))] + #[cfg(not(target_vendor = "apple"))] const clock_id: libc::clockid_t = libc::CLOCK_MONOTONIC; Instant { t: Timespec::now(clock_id) } } diff --git a/library/std/src/sys/pal/unsupported/mod.rs b/library/std/src/sys/pal/unsupported/mod.rs index be344fb7cae..01f5cfd4297 100644 --- a/library/std/src/sys/pal/unsupported/mod.rs +++ b/library/std/src/sys/pal/unsupported/mod.rs @@ -14,7 +14,6 @@ pub mod thread; #[cfg(target_thread_local)] pub mod thread_local_dtor; pub mod thread_local_key; -pub mod thread_parking; pub mod time; mod common; diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs index a78547261ad..c1266619b36 100644 --- a/library/std/src/sys/pal/wasi/mod.rs +++ b/library/std/src/sys/pal/wasi/mod.rs @@ -39,13 +39,6 @@ pub mod thread_local_dtor; pub mod thread_local_key; pub mod time; -cfg_if::cfg_if! { - if #[cfg(not(target_feature = "atomics"))] { - #[path = "../unsupported/thread_parking.rs"] - pub mod thread_parking; - } -} - #[path = "../unsupported/common.rs"] #[deny(unsafe_op_in_unsafe_fn)] #[allow(unused)] diff --git a/library/std/src/sys/pal/wasip2/mod.rs b/library/std/src/sys/pal/wasip2/mod.rs index 94aa458d2f9..6787ffb4bed 100644 --- a/library/std/src/sys/pal/wasip2/mod.rs +++ b/library/std/src/sys/pal/wasip2/mod.rs @@ -41,15 +41,6 @@ pub mod thread_local_key; #[path = "../wasi/time.rs"] pub mod time; -cfg_if::cfg_if! { - if #[cfg(target_feature = "atomics")] { - compile_error!("The wasm32-wasip2 target does not support atomics"); - } else { - #[path = "../unsupported/thread_parking.rs"] - pub mod thread_parking; - } -} - #[path = "../unsupported/common.rs"] #[deny(unsafe_op_in_unsafe_fn)] #[allow(unused)] diff --git a/library/std/src/sys/pal/wasm/mod.rs b/library/std/src/sys/pal/wasm/mod.rs index 5cbc3e45341..75dd10826cc 100644 --- a/library/std/src/sys/pal/wasm/mod.rs +++ b/library/std/src/sys/pal/wasm/mod.rs @@ -50,8 +50,6 @@ cfg_if::cfg_if! { } else { #[path = "../unsupported/thread.rs"] pub mod thread; - #[path = "../unsupported/thread_parking.rs"] - pub mod thread_parking; } } diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index ff41f6e77be..402a205977b 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -33,7 +33,6 @@ pub mod stdio; pub mod thread; pub mod thread_local_dtor; pub mod thread_local_key; -pub mod thread_parking; pub mod time; cfg_if::cfg_if! { if #[cfg(not(target_vendor = "uwp"))] { diff --git a/library/std/src/sys/pal/xous/mod.rs b/library/std/src/sys/pal/xous/mod.rs index 7914a255aea..68189bcc2e3 100644 --- a/library/std/src/sys/pal/xous/mod.rs +++ b/library/std/src/sys/pal/xous/mod.rs @@ -18,7 +18,6 @@ pub mod process; pub mod stdio; pub mod thread; pub mod thread_local_key; -pub mod thread_parking; pub mod time; #[path = "../unsupported/common.rs"] diff --git a/library/std/src/sys/pal/zkvm/mod.rs b/library/std/src/sys/pal/zkvm/mod.rs index 4f79f8c4961..0b22eabca6d 100644 --- a/library/std/src/sys/pal/zkvm/mod.rs +++ b/library/std/src/sys/pal/zkvm/mod.rs @@ -32,9 +32,6 @@ pub mod time; #[path = "../unsupported/thread.rs"] pub mod thread; -#[path = "../unsupported/thread_parking.rs"] -pub mod thread_parking; - mod abi; use crate::io as std_io; diff --git a/library/std/src/sys/sync/condvar/pthread.rs b/library/std/src/sys/sync/condvar/pthread.rs index 0475f985078..a2a96410d93 100644 --- a/library/std/src/sys/sync/condvar/pthread.rs +++ b/library/std/src/sys/sync/condvar/pthread.rs @@ -30,14 +30,10 @@ impl LazyInit for AllocatedCondvar { cfg_if::cfg_if! { if #[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos", target_os = "l4re", target_os = "android", - target_os = "redox" + target_os = "redox", + target_vendor = "apple", ))] { // `pthread_condattr_setclock` is unfortunately not supported on these platforms. } else if #[cfg(any(target_os = "espidf", target_os = "horizon"))] { @@ -124,14 +120,10 @@ impl Condvar { // default system clock). This approach avoids all problems that result // from changes made to the system time. #[cfg(not(any( - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos", target_os = "android", target_os = "espidf", - target_os = "horizon" + target_os = "horizon", + target_vendor = "apple", )))] pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { use crate::sys::time::Timespec; @@ -160,14 +152,10 @@ impl Condvar { // https://github.com/llvm-mirror/libcxx/blob/release_35/src/condition_variable.cpp#L46 // https://github.com/llvm-mirror/libcxx/blob/release_35/include/__mutex_base#L367 #[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos", target_os = "android", target_os = "espidf", - target_os = "horizon" + target_os = "horizon", + target_vendor = "apple", ))] pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { use crate::sys::time::SystemTime; diff --git a/library/std/src/sys/sync/mod.rs b/library/std/src/sys/sync/mod.rs index 623e6bccd51..52fac5902a2 100644 --- a/library/std/src/sys/sync/mod.rs +++ b/library/std/src/sys/sync/mod.rs @@ -2,8 +2,10 @@ mod condvar; mod mutex; mod once; mod rwlock; +mod thread_parking; pub use condvar::Condvar; pub use mutex::Mutex; pub use once::{Once, OnceState}; pub use rwlock::RwLock; +pub use thread_parking::Parker; diff --git a/library/std/src/sys/pal/unix/thread_parking/darwin.rs b/library/std/src/sys/sync/thread_parking/darwin.rs index 8231f3cba2d..973c08f0317 100644 --- a/library/std/src/sys/pal/unix/thread_parking/darwin.rs +++ b/library/std/src/sys/sync/thread_parking/darwin.rs @@ -10,6 +10,8 @@ //! provided by libdispatch, as the underlying Mach semaphore is only dubiously //! public. +#![allow(non_camel_case_types)] + use crate::pin::Pin; use crate::sync::atomic::{ AtomicI8, diff --git a/library/std/src/sys_common/thread_parking/futex.rs b/library/std/src/sys/sync/thread_parking/futex.rs index 588e7b27826..588e7b27826 100644 --- a/library/std/src/sys_common/thread_parking/futex.rs +++ b/library/std/src/sys/sync/thread_parking/futex.rs diff --git a/library/std/src/sys_common/thread_parking/id.rs b/library/std/src/sys/sync/thread_parking/id.rs index 04667439660..04667439660 100644 --- a/library/std/src/sys_common/thread_parking/id.rs +++ b/library/std/src/sys/sync/thread_parking/id.rs diff --git a/library/std/src/sys_common/thread_parking/mod.rs b/library/std/src/sys/sync/thread_parking/mod.rs index c4d3f9ea2f4..ed1a6437faa 100644 --- a/library/std/src/sys_common/thread_parking/mod.rs +++ b/library/std/src/sys/sync/thread_parking/mod.rs @@ -18,7 +18,20 @@ cfg_if::cfg_if! { ))] { mod id; pub use id::Parker; + } else if #[cfg(target_os = "windows")] { + mod windows; + pub use windows::Parker; + } else if #[cfg(all(target_vendor = "apple", not(miri)))] { + mod darwin; + pub use darwin::Parker; + } else if #[cfg(target_os = "xous")] { + mod xous; + pub use xous::Parker; + } else if #[cfg(target_family = "unix")] { + mod pthread; + pub use pthread::Parker; } else { - pub use crate::sys::thread_parking::Parker; + mod unsupported; + pub use unsupported::Parker; } } diff --git a/library/std/src/sys/pal/unix/thread_parking/pthread.rs b/library/std/src/sys/sync/thread_parking/pthread.rs index d0ad3e2ce3e..fdac1096dbf 100644 --- a/library/std/src/sys/pal/unix/thread_parking/pthread.rs +++ b/library/std/src/sys/sync/thread_parking/pthread.rs @@ -43,15 +43,7 @@ unsafe fn wait_timeout( ) { // Use the system clock on systems that do not support pthread_condattr_setclock. // This unfortunately results in problems when the system time changes. - #[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos", - target_os = "espidf", - target_os = "horizon", - ))] + #[cfg(any(target_os = "espidf", target_os = "horizon", target_vendor = "apple"))] let (now, dur) = { use crate::cmp::min; use crate::sys::time::SystemTime; @@ -72,15 +64,7 @@ unsafe fn wait_timeout( (now, dur) }; // Use the monotonic clock on other systems. - #[cfg(not(any( - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos", - target_os = "espidf", - target_os = "horizon", - )))] + #[cfg(not(any(target_os = "espidf", target_os = "horizon", target_vendor = "apple")))] let (now, dur) = { use crate::sys::time::Timespec; @@ -122,15 +106,11 @@ impl Parker { cfg_if::cfg_if! { if #[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos", target_os = "l4re", target_os = "android", target_os = "redox", target_os = "vita", + target_vendor = "apple", ))] { addr_of_mut!((*parker).cvar).write(UnsafeCell::new(libc::PTHREAD_COND_INITIALIZER)); } else if #[cfg(any(target_os = "espidf", target_os = "horizon"))] { @@ -154,7 +134,7 @@ impl Parker { // This implementation doesn't require `unsafe`, but other implementations // may assume this is only called by the thread that owns the Parker. // - // For memory ordering, see std/src/sys_common/thread_parking/futex.rs + // For memory ordering, see futex.rs pub unsafe fn park(self: Pin<&Self>) { // If we were previously notified then we consume this notification and // return quickly. diff --git a/library/std/src/sys/pal/unsupported/thread_parking.rs b/library/std/src/sys/sync/thread_parking/unsupported.rs index 197078bb186..197078bb186 100644 --- a/library/std/src/sys/pal/unsupported/thread_parking.rs +++ b/library/std/src/sys/sync/thread_parking/unsupported.rs diff --git a/library/std/src/sys/pal/windows/thread_parking.rs b/library/std/src/sys/sync/thread_parking/windows.rs index 4b8102d505a..4b8102d505a 100644 --- a/library/std/src/sys/pal/windows/thread_parking.rs +++ b/library/std/src/sys/sync/thread_parking/windows.rs diff --git a/library/std/src/sys/pal/xous/thread_parking.rs b/library/std/src/sys/sync/thread_parking/xous.rs index 0bd0462d77d..0bd0462d77d 100644 --- a/library/std/src/sys/pal/xous/thread_parking.rs +++ b/library/std/src/sys/sync/thread_parking/xous.rs diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index cc21560fff5..3a38ba1100f 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -26,7 +26,6 @@ pub mod io; pub mod lazy_box; pub mod process; pub mod thread_local_dtor; -pub mod thread_parking; pub mod wstr; pub mod wtf8; diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs index 6a268633f72..95ca67fc2e0 100644 --- a/library/std/src/sys_common/net.rs +++ b/library/std/src/sys_common/net.rs @@ -17,10 +17,17 @@ use crate::ffi::{c_int, c_void}; cfg_if::cfg_if! { if #[cfg(any( - target_os = "dragonfly", target_os = "freebsd", - target_os = "ios", target_os = "tvos", target_os = "macos", target_os = "watchos", target_os = "visionos", - target_os = "openbsd", target_os = "netbsd", target_os = "illumos", - target_os = "solaris", target_os = "haiku", target_os = "l4re", target_os = "nto"))] { + target_os = "dragonfly", + target_os = "freebsd", + target_os = "openbsd", + target_os = "netbsd", + target_os = "illumos", + target_os = "solaris", + target_os = "haiku", + target_os = "l4re", + target_os = "nto", + target_vendor = "apple", + ))] { use crate::sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP; use crate::sys::net::netc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP; } else { diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 604eb05040b..78bc9af6c4d 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -174,8 +174,8 @@ use crate::ptr::addr_of_mut; use crate::str; use crate::sync::atomic::{AtomicUsize, Ordering}; use crate::sync::Arc; +use crate::sys::sync::Parker; use crate::sys::thread as imp; -use crate::sys_common::thread_parking::Parker; use crate::sys_common::{AsInner, IntoInner}; use crate::time::{Duration, Instant}; @@ -703,9 +703,14 @@ thread_local! { /// Sets the thread handle for the current thread. /// -/// Panics if the handle has been set already or when called from a TLS destructor. +/// Aborts if the handle has been set already to reduce code size. pub(crate) fn set_current(thread: Thread) { - CURRENT.with(|current| current.set(thread).unwrap()); + // Using `unwrap` here can add ~3kB to the binary size. We have complete + // control over where this is called, so just abort if there is a bug. + CURRENT.with(|current| match current.set(thread) { + Ok(()) => {} + Err(_) => rtabort!("thread::set_current should only be called once per thread"), + }); } /// Gets a handle to the thread that invokes it. diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs index 494513f2c75..1fb1333be0e 100644 --- a/library/std/src/thread/tests.rs +++ b/library/std/src/thread/tests.rs @@ -40,11 +40,7 @@ fn test_named_thread() { #[cfg(any( // Note: musl didn't add pthread_getname_np until 1.2.3 all(target_os = "linux", target_env = "gnu"), - target_os = "macos", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "visionos", + target_vendor = "apple", ))] #[test] fn test_named_thread_truncation() { diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index f3a26e25938..7bd08a0605f 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -589,7 +589,9 @@ pub fn run_test( // If the platform is single-threaded we're just going to run // the test synchronously, regardless of the concurrency // level. - let supports_threads = !cfg!(target_os = "emscripten") && !cfg!(target_family = "wasm"); + let supports_threads = !cfg!(target_os = "emscripten") + && !cfg!(target_family = "wasm") + && !cfg!(target_os = "zkvm"); if supports_threads { let cfg = thread::Builder::new().name(name.as_slice().to_owned()); let mut runtest = Arc::new(Mutex::new(Some(runtest))); diff --git a/rustfmt.toml b/rustfmt.toml index 0b0674af8b4..850d01ea7cb 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -13,7 +13,13 @@ ignore = [ # tests for now are not formatted, as they are sometimes pretty-printing constrained # (and generally rustfmt can move around comments in UI-testing incompatible ways) - "/tests/", + "/tests/*", + + # but we still want to format rmake.rs files in tests/run-make/ so we need to do this + # dance to avoid the parent directory from being excluded + "!/tests/run-make/", + "/tests/run-make/*/*.rs", + "!/tests/run-make/*/rmake.rs", # do not format submodules # FIXME: sync submodule list with tidy/bootstrap/etc diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 1d46a158f9e..48a6602e2df 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1006,6 +1006,13 @@ pub fn rustc_cargo( cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)"); + // If the rustc output is piped to e.g. `head -n1` we want the process to be + // killed, rather than having an error bubble up and cause a panic. + // FIXME: Synthetic #[cfg(bootstrap)]. Remove when the bootstrap compiler supports it. + if compiler.stage != 0 { + cargo.rustflag("-Zon-broken-pipe=kill"); + } + // We currently don't support cross-crate LTO in stage0. This also isn't hugely necessary // and may just be a time sink. if compiler.stage != 0 { diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 770a5cdb232..5bc9d7615e2 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -25,7 +25,7 @@ use crate::core::build_steps::llvm; use crate::core::build_steps::tool::{self, Tool}; use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step}; use crate::core::config::TargetSelection; -use crate::utils::channel; +use crate::utils::channel::{self, Info}; use crate::utils::helpers::{exe, is_dylib, output, t, target_supports_cranelift_backend, timeit}; use crate::utils::tarball::{GeneratedTarball, OverlayKind, Tarball}; use crate::{Compiler, DependencyType, Mode, LLVM_TOOLS}; @@ -991,10 +991,17 @@ impl Step for PlainSourceTarball { // Create the version file builder.create(&plain_dst_src.join("version"), &builder.rust_version()); - if let Some(info) = builder.rust_info().info() { - channel::write_commit_hash_file(plain_dst_src, &info.sha); - channel::write_commit_info_file(plain_dst_src, info); - } + + // Create the files containing git info, to ensure --version outputs the same. + let write_git_info = |info: Option<&Info>, path: &Path| { + if let Some(info) = info { + t!(std::fs::create_dir_all(path)); + channel::write_commit_hash_file(path, &info.sha); + channel::write_commit_info_file(path, info); + } + }; + write_git_info(builder.rust_info().info(), plain_dst_src); + write_git_info(builder.cargo_info.info(), &plain_dst_src.join("./src/tools/cargo")); // If we're building from git or tarball sources, we need to vendor // a complete distribution. diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 9fc65a0a73a..d9dc34c0137 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -115,7 +115,11 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { let rustfmt_config: RustfmtConfig = t!(toml::from_str(&rustfmt_config)); let mut fmt_override = ignore::overrides::OverrideBuilder::new(&build.src); for ignore in rustfmt_config.ignore { - fmt_override.add(&format!("!{ignore}")).expect(&ignore); + if let Some(ignore) = ignore.strip_prefix('!') { + fmt_override.add(ignore).expect(ignore); + } else { + fmt_override.add(&format!("!{ignore}")).expect(&ignore); + } } let git_available = match Command::new("git") .arg("--version") diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs index 0a428ec5ca0..354eb2b6003 100644 --- a/src/bootstrap/src/core/build_steps/run.rs +++ b/src/bootstrap/src/core/build_steps/run.rs @@ -15,32 +15,6 @@ use crate::core::config::TargetSelection; use crate::utils::helpers::output; use crate::Mode; -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct ExpandYamlAnchors; - -impl Step for ExpandYamlAnchors { - type Output = (); - - /// Runs the `expand-yaml_anchors` tool. - /// - /// This tool in `src/tools` reads the CI configuration files written in YAML and expands the - /// anchors in them, since GitHub Actions doesn't support them. - fn run(self, builder: &Builder<'_>) { - builder.info("Expanding YAML anchors in the GitHub Actions configuration"); - builder.run_delaying_failure( - builder.tool_cmd(Tool::ExpandYamlAnchors).arg("generate").arg(&builder.src), - ); - } - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src/tools/expand-yaml-anchors") - } - - fn make_run(run: RunConfig<'_>) { - run.builder.ensure(ExpandYamlAnchors); - } -} - #[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)] pub struct BuildManifest; diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 411ed99532f..360bd3840d4 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1146,8 +1146,6 @@ HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to builder.info("tidy check"); builder.run_delaying_failure(&mut cmd); - builder.ensure(ExpandYamlAnchors); - builder.info("x.py completions check"); let [bash, zsh, fish, powershell] = ["x.py.sh", "x.py.zsh", "x.py.fish", "x.py.ps1"] .map(|filename| builder.src.join("src/etc/completions").join(filename)); @@ -1175,39 +1173,6 @@ HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct ExpandYamlAnchors; - -impl Step for ExpandYamlAnchors { - type Output = (); - const ONLY_HOSTS: bool = true; - - /// Ensure the `generate-ci-config` tool was run locally. - /// - /// The tool in `src/tools` reads the CI definition in `src/ci/builders.yml` and generates the - /// appropriate configuration for all our CI providers. This step ensures the tool was called - /// by the user before committing CI changes. - fn run(self, builder: &Builder<'_>) { - // NOTE: `.github/` is not included in dist-src tarballs - if !builder.src.join(".github/workflows/ci.yml").exists() { - builder.info("Skipping YAML anchors check: GitHub Actions config not found"); - return; - } - builder.info("Ensuring the YAML anchors in the GitHub Actions config were expanded"); - builder.run_delaying_failure( - builder.tool_cmd(Tool::ExpandYamlAnchors).arg("check").arg(&builder.src), - ); - } - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src/tools/expand-yaml-anchors") - } - - fn make_run(run: RunConfig<'_>) { - run.builder.ensure(ExpandYamlAnchors); - } -} - fn testdir(builder: &Builder<'_>, host: TargetSelection) -> PathBuf { builder.out.join(host.triple).join("test") } @@ -1927,15 +1892,16 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the .to_string() }) }; - let lldb_exe = "lldb"; - let lldb_version = Command::new(lldb_exe) + + let lldb_exe = builder.config.lldb.clone().unwrap_or_else(|| PathBuf::from("lldb")); + let lldb_version = Command::new(&lldb_exe) .arg("--version") .output() .map(|output| String::from_utf8_lossy(&output.stdout).to_string()) .ok(); if let Some(ref vers) = lldb_version { cmd.arg("--lldb-version").arg(vers); - let lldb_python_dir = run(Command::new(lldb_exe).arg("-P")).ok(); + let lldb_python_dir = run(Command::new(&lldb_exe).arg("-P")).ok(); if let Some(ref dir) = lldb_python_dir { cmd.arg("--lldb-python-dir").arg(dir); } diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 994f0bef0dc..21344a4224e 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -302,7 +302,6 @@ bootstrap_tool!( RemoteTestClient, "src/tools/remote-test-client", "remote-test-client"; RustInstaller, "src/tools/rust-installer", "rust-installer"; RustdocTheme, "src/tools/rustdoc-themes", "rustdoc-themes"; - ExpandYamlAnchors, "src/tools/expand-yaml-anchors", "expand-yaml-anchors"; LintDocs, "src/tools/lint-docs", "lint-docs"; JsonDocCk, "src/tools/jsondocck", "jsondocck"; JsonDocLint, "src/tools/jsondoclint", "jsondoclint"; @@ -472,7 +471,7 @@ impl Step for Rustdoc { features.push("jemalloc".to_string()); } - let cargo = prepare_tool_cargo( + let mut cargo = prepare_tool_cargo( builder, build_compiler, Mode::ToolRustc, @@ -483,6 +482,14 @@ impl Step for Rustdoc { features.as_slice(), ); + // If the rustdoc output is piped to e.g. `head -n1` we want the process + // to be killed, rather than having an error bubble up and cause a + // panic. + // FIXME: Synthetic #[cfg(bootstrap)]. Remove when the bootstrap compiler supports it. + if build_compiler.stage > 0 { + cargo.rustflag("-Zon-broken-pipe=kill"); + } + let _guard = builder.msg_tool( Kind::Build, Mode::ToolRustc, diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index ae5440de572..0ad6c959309 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -791,7 +791,6 @@ impl<'a> Builder<'a> { ), Kind::Test => describe!( crate::core::build_steps::toolstate::ToolStateCheck, - test::ExpandYamlAnchors, test::Tidy, test::Ui, test::Crashes, @@ -933,7 +932,6 @@ impl<'a> Builder<'a> { install::Src, ), Kind::Run => describe!( - run::ExpandYamlAnchors, run::BuildManifest, run::BumpStage0, run::ReplaceVersionPlaceholder, @@ -2126,13 +2124,10 @@ impl<'a> Builder<'a> { // during incremental builds" heuristic for the standard library. rustflags.arg("-Zinline-mir"); - // FIXME: always pass this after the next `#[cfg(bootstrap)]` update. - if compiler.stage != 0 { - // Similarly, we need to keep debug info for functions inlined into other std functions, - // even if we're not going to output debuginfo for the crate we're currently building, - // so that it'll be available when downstream consumers of std try to use it. - rustflags.arg("-Zinline-mir-preserve-debug"); - } + // Similarly, we need to keep debug info for functions inlined into other std functions, + // even if we're not going to output debuginfo for the crate we're currently building, + // so that it'll be available when downstream consumers of std try to use it. + rustflags.arg("-Zinline-mir-preserve-debug"); } if self.config.rustc_parallel diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 149a62f88c9..0167c51fc7e 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -329,6 +329,7 @@ pub struct Config { pub nodejs: Option<PathBuf>, pub npm: Option<PathBuf>, pub gdb: Option<PathBuf>, + pub lldb: Option<PathBuf>, pub python: Option<PathBuf>, pub reuse: Option<PathBuf>, pub cargo_native_static: bool, @@ -834,6 +835,7 @@ define_config! { docs_minification: Option<bool> = "docs-minification", submodules: Option<bool> = "submodules", gdb: Option<String> = "gdb", + lldb: Option<String> = "lldb", nodejs: Option<String> = "nodejs", npm: Option<String> = "npm", python: Option<String> = "python", @@ -1410,6 +1412,7 @@ impl Config { docs_minification, submodules, gdb, + lldb, nodejs, npm, python, @@ -1502,6 +1505,7 @@ impl Config { config.nodejs = nodejs.map(PathBuf::from); config.npm = npm.map(PathBuf::from); config.gdb = gdb.map(PathBuf::from); + config.lldb = lldb.map(PathBuf::from); config.python = python.map(PathBuf::from); config.reuse = reuse.map(PathBuf::from); config.submodules = submodules; @@ -2492,11 +2496,6 @@ impl Config { b } - // FIXME: "if-available" is deprecated. Remove this block later (around mid 2024) - // to not break builds between the recent-to-old checkouts. - Some(StringOrBool::String(s)) if s == "if-available" => { - llvm::is_ci_llvm_available(self, asserts) - } Some(StringOrBool::String(s)) if s == "if-unchanged" => if_unchanged(), Some(StringOrBool::String(other)) => { panic!("unrecognized option for download-ci-llvm: {:?}", other) diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index a5af87ad5c7..f4ed7e76fba 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -420,7 +420,7 @@ pub enum Subcommand { Arguments: This subcommand accepts a number of paths to tools to build and run. For example: - ./x.py run src/tools/expand-yaml-anchors + ./x.py run src/tools/bump-stage0 At least a tool needs to be called.")] /// Run tools contained in this repository Run { diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 6ccf29fb6cb..0c069a54069 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -26,6 +26,17 @@ pub struct Finder { path: OsString, } +// During sanity checks, we search for target names to determine if they exist in the compiler's built-in +// target list (`rustc --print target-list`). While a target name may be present in the stage2 compiler, +// it might not yet be included in stage0. In such cases, we handle the targets missing from stage0 in this list. +// +// Targets can be removed from this list once they are present in the stage0 compiler (usually by updating the beta compiler of the bootstrap). +const STAGE0_MISSING_TARGETS: &[&str] = &[ + // just a dummy comment so the list doesn't get onelined + "aarch64-apple-visionos", + "aarch64-apple-visionos-sim", +]; + impl Finder { pub fn new() -> Self { Self { cache: HashMap::new(), path: env::var_os("PATH").unwrap_or_default() } @@ -178,32 +189,40 @@ than building it. continue; } - // Check if there exists a built-in target in the list of supported targets. - let mut has_target = false; let target_str = target.to_string(); - let supported_target_list = - output(Command::new(&build.config.initial_rustc).args(["--print", "target-list"])); + // Ignore fake targets that are only used for unit tests in bootstrap. + if !["A", "B", "C"].contains(&target_str.as_str()) { + let mut has_target = false; + + let supported_target_list = + output(Command::new(&build.config.initial_rustc).args(["--print", "target-list"])); + + // Check if it's a built-in target. + has_target |= supported_target_list.contains(&target_str); + has_target |= STAGE0_MISSING_TARGETS.contains(&target_str.as_str()); - has_target |= supported_target_list.contains(&target_str); + if !has_target { + // This might also be a custom target, so check the target file that could have been specified by the user. + if let Some(custom_target_path) = env::var_os("RUST_TARGET_PATH") { + let mut target_filename = OsString::from(&target_str); + // Target filename ends with `.json`. + target_filename.push(".json"); - // If not, check for a valid file location that may have been specified - // by the user for the custom target. - if let Some(custom_target_path) = env::var_os("RUST_TARGET_PATH") { - let mut target_os_str = OsString::from(&target_str); - target_os_str.push(".json"); - // Recursively traverse through nested directories. - let walker = WalkDir::new(custom_target_path).into_iter(); - for entry in walker.filter_map(|e| e.ok()) { - has_target |= entry.file_name() == target_os_str; + // Recursively traverse through nested directories. + let walker = WalkDir::new(custom_target_path).into_iter(); + for entry in walker.filter_map(|e| e.ok()) { + has_target |= entry.file_name() == target_filename; + } + } } - } - if !has_target && !["A", "B", "C"].contains(&target_str.as_str()) { - panic!( - "No such target exists in the target list, + if !has_target { + panic!( + "No such target exists in the target list, specify a correct location of the JSON specification file for custom targets!" - ); + ); + } } if !build.config.dry_run() { diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 663a2d8e17c..c599709a322 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -376,11 +376,16 @@ impl Build { .expect("failed to read src/version"); let version = version.trim(); - let bootstrap_out = std::env::current_exe() + let mut bootstrap_out = std::env::current_exe() .expect("could not determine path to running process") .parent() .unwrap() .to_path_buf(); + // Since bootstrap is hardlink to deps/bootstrap-*, Solaris can sometimes give + // path with deps/ which is bad and needs to be avoided. + if bootstrap_out.ends_with("deps") { + bootstrap_out.pop(); + } if !bootstrap_out.join(exe("rustc", config.build)).exists() && !cfg!(test) { // this restriction can be lifted whenever https://github.com/rust-lang/rfcs/pull/3028 is implemented panic!( diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index db3df598a0c..c3a03693f71 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -175,4 +175,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Warning, summary: "The deprecated field `changelog-seen` has been removed. Using that field in `config.toml` from now on will result in breakage.", }, + ChangeInfo { + change_id: 124501, + severity: ChangeSeverity::Info, + summary: "New option `build.lldb` that will override the default lldb binary path used in debuginfo tests", + }, ]; diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index 0eff7ca5962..d0da7d30660 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -42,11 +42,10 @@ COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/ ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1 -ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \ - # Check library crates on all tier 1 targets. - # We disable optimized compiler built-ins because that requires a C toolchain for the target. - # We also skip the x86_64-unknown-linux-gnu target as it is well-tested by other jobs. - python3 ../x.py check --stage 0 --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \ +# Check library crates on all tier 1 targets. +# We disable optimized compiler built-ins because that requires a C toolchain for the target. +# We also skip the x86_64-unknown-linux-gnu target as it is well-tested by other jobs. +ENV SCRIPT python3 ../x.py check --stage 0 --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \ python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \ python3 ../x.py clippy bootstrap -Dwarnings && \ python3 ../x.py clippy compiler library -Aclippy::all -Dclippy::correctness && \ diff --git a/src/ci/github-actions/calculate-job-matrix.py b/src/ci/github-actions/calculate-job-matrix.py index 124c22bd979..68565f489c9 100755 --- a/src/ci/github-actions/calculate-job-matrix.py +++ b/src/ci/github-actions/calculate-job-matrix.py @@ -44,7 +44,7 @@ def add_base_env(jobs: List[Job], environment: Dict[str, str]) -> List[Job]: return jobs -class JobType(enum.Enum): +class WorkflowRunType(enum.Enum): PR = enum.auto() Try = enum.auto() Auto = enum.auto() @@ -57,9 +57,9 @@ class GitHubCtx: repository: str -def find_job_type(ctx: GitHubCtx) -> Optional[JobType]: +def find_run_type(ctx: GitHubCtx) -> Optional[WorkflowRunType]: if ctx.event_name == "pull_request": - return JobType.PR + return WorkflowRunType.PR elif ctx.event_name == "push": old_bors_try_build = ( ctx.ref in ("refs/heads/try", "refs/heads/try-perf") and @@ -72,20 +72,20 @@ def find_job_type(ctx: GitHubCtx) -> Optional[JobType]: try_build = old_bors_try_build or new_bors_try_build if try_build: - return JobType.Try + return WorkflowRunType.Try if ctx.ref == "refs/heads/auto" and ctx.repository == "rust-lang-ci/rust": - return JobType.Auto + return WorkflowRunType.Auto return None -def calculate_jobs(job_type: JobType, job_data: Dict[str, Any]) -> List[Job]: - if job_type == JobType.PR: +def calculate_jobs(run_type: WorkflowRunType, job_data: Dict[str, Any]) -> List[Job]: + if run_type == WorkflowRunType.PR: return add_base_env(name_jobs(job_data["pr"], "PR"), job_data["envs"]["pr"]) - elif job_type == JobType.Try: + elif run_type == WorkflowRunType.Try: return add_base_env(name_jobs(job_data["try"], "try"), job_data["envs"]["try"]) - elif job_type == JobType.Auto: + elif run_type == WorkflowRunType.Auto: return add_base_env(name_jobs(job_data["auto"], "auto"), job_data["envs"]["auto"]) return [] @@ -106,6 +106,17 @@ def get_github_ctx() -> GitHubCtx: ) +def format_run_type(run_type: WorkflowRunType) -> str: + if run_type == WorkflowRunType.PR: + return "pr" + elif run_type == WorkflowRunType.Auto: + return "auto" + elif run_type == WorkflowRunType.Try: + return "try" + else: + raise AssertionError() + + if __name__ == "__main__": logging.basicConfig(level=logging.INFO) @@ -114,16 +125,18 @@ if __name__ == "__main__": github_ctx = get_github_ctx() - job_type = find_job_type(github_ctx) - logging.info(f"Job type: {job_type}") + run_type = find_run_type(github_ctx) + logging.info(f"Job type: {run_type}") with open(CI_DIR / "channel") as f: channel = f.read().strip() jobs = [] - if job_type is not None: - jobs = calculate_jobs(job_type, data) + if run_type is not None: + jobs = calculate_jobs(run_type, data) jobs = skip_jobs(jobs, channel) + run_type = format_run_type(run_type) - logging.info(f"Output:\n{yaml.dump(jobs, indent=4)}") + logging.info(f"Output:\n{yaml.dump(dict(jobs=jobs, run_type=run_type), indent=4)}") print(f"jobs={json.dumps(jobs)}") + print(f"run_type={run_type}") diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml deleted file mode 100644 index bc4b1b815cf..00000000000 --- a/src/ci/github-actions/ci.yml +++ /dev/null @@ -1,390 +0,0 @@ -###################################################### -# WARNING! Action needed when changing this file # -###################################################### - -# Due to GitHub Actions limitations, we can't use YAML Anchors directly in the -# CI configuration stored on the repository. To work around that this file is -# expanded by a tool in the repository, and the expansion is committed as well. -# -# After you make any change to the file you'll need to run this command: -# -# ./x.py run src/tools/expand-yaml-anchors -# -# ...and commit the file it updated in addition to this one. If you forget this -# step CI will fail. - ---- -############################### -# YAML Anchors Definition # -############################### - -# This key contains most of the YAML anchors that will be used later in the -# document. YAML anchors allows us to greatly reduce duplication inside the CI -# configuration by reusing parts of the configuration. -# -# YAML anchors work by defining an anchor with `&anchor-name` and reusing its -# content in another place with `*anchor-name`. The special `<<` map key merges -# the content of the map with the content of the anchor (or list of anchors). -# -# The expand-yaml-anchors tool will automatically remove this block from the -# output YAML file. -x--expand-yaml-anchors--remove: - - &shared-ci-variables - CI_JOB_NAME: ${{ matrix.name }} - CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse - # commit of PR sha or commit sha. `GITHUB_SHA` is not accurate for PRs. - HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }} - DOCKER_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - &public-variables - SCCACHE_BUCKET: rust-lang-ci-sccache2 - TOOLSTATE_REPO: https://github.com/rust-lang-nursery/rust-toolstate - CACHE_DOMAIN: ci-caches.rust-lang.org - - - &prod-variables - SCCACHE_BUCKET: rust-lang-ci-sccache2 - DEPLOY_BUCKET: rust-lang-ci2 - TOOLSTATE_REPO: https://github.com/rust-lang-nursery/rust-toolstate - TOOLSTATE_ISSUES_API_URL: https://api.github.com/repos/rust-lang/rust/issues - TOOLSTATE_PUBLISH: 1 - # AWS_SECRET_ACCESS_KEYs are stored in GitHub's secrets storage, named - # AWS_SECRET_ACCESS_KEY_<keyid>. Including the key id in the name allows to - # rotate them in a single branch while keeping the old key in another - # branch, which wouldn't be possible if the key was named with the kind - # (caches, artifacts...). - CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZI5DHEBFL - ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55 - AWS_REGION: us-west-1 - CACHE_DOMAIN: ci-caches.rust-lang.org - - - &dummy-variables - SCCACHE_BUCKET: rust-lang-gha-caches - DEPLOY_BUCKET: rust-lang-gha - TOOLSTATE_REPO: https://github.com/pietroalbini/rust-toolstate - TOOLSTATE_ISSUES_API_URL: https://api.github.com/repos/pietroalbini/rust-toolstate/issues - TOOLSTATE_PUBLISH: 1 - # AWS_SECRET_ACCESS_KEYs are stored in GitHub's secrets storage, named - # AWS_SECRET_ACCESS_KEY_<keyid>. Including the key id in the name allows to - # rotate them in a single branch while keeping the old key in another - # branch, which wouldn't be possible if the key was named with the kind - # (caches, artifacts...). - CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZOMUQATD5 - ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZH5AYXDVF - AWS_REGION: us-west-1 - CACHE_DOMAIN: ci-caches-gha.rust-lang.org - - - &base-job - env: {} - - - &job-linux-4c - os: ubuntu-20.04-4core-16gb - <<: *base-job - - - &job-linux-8c - os: ubuntu-20.04-8core-32gb - <<: *base-job - - - &job-linux-16c - os: ubuntu-20.04-16core-64gb - <<: *base-job - - - &job-macos-xl - os: macos-13 # We use the standard runner for now - <<: *base-job - - - &job-macos-m1 - os: macos-14 - <<: *base-job - - - &job-windows-8c - os: windows-2019-8core-32gb - <<: *base-job - - - &job-windows-16c - os: windows-2019-16core-64gb - <<: *base-job - - - &job-aarch64-linux - os: [self-hosted, ARM64, linux] - - - &base-ci-job - defaults: - run: - shell: ${{ contains(matrix.os, 'windows') && 'msys2 {0}' || 'bash' }} - timeout-minutes: 600 - runs-on: "${{ matrix.os }}" - env: *shared-ci-variables - steps: - - if: contains(matrix.os, 'windows') - uses: msys2/setup-msys2@v2.22.0 - with: - # i686 jobs use mingw32. x86_64 and cross-compile jobs use mingw64. - msystem: ${{ contains(matrix.name, 'i686') && 'mingw32' || 'mingw64' }} - # don't try to download updates for already installed packages - update: false - # don't try to use the msys that comes built-in to the github runner, - # so we can control what is installed (i.e. not python) - release: true - # Inherit the full path from the Windows environment, with MSYS2's */bin/ - # dirs placed in front. This lets us run Windows-native Python etc. - path-type: inherit - install: > - make - dos2unix - diffutils - - - name: disable git crlf conversion - run: git config --global core.autocrlf false - - - name: checkout the source code - uses: actions/checkout@v4 - with: - fetch-depth: 2 - - # Rust Log Analyzer can't currently detect the PR number of a GitHub - # Actions build on its own, so a hint in the log message is needed to - # point it in the right direction. - - name: configure the PR in which the error message will be posted - run: echo "[CI_PR_NUMBER=$num]" - env: - num: ${{ github.event.number }} - if: success() && github.event_name == 'pull_request' - - - name: add extra environment variables - run: src/ci/scripts/setup-environment.sh - env: - # Since it's not possible to merge `${{ matrix.env }}` with the other - # variables in `job.<name>.env`, the variables defined in the matrix - # are passed to the `setup-environment.sh` script encoded in JSON, - # which then uses log commands to actually set them. - EXTRA_VARIABLES: ${{ toJson(matrix.env) }} - - - name: ensure the channel matches the target branch - run: src/ci/scripts/verify-channel.sh - - - name: collect CPU statistics - run: src/ci/scripts/collect-cpu-stats.sh - - - name: show the current environment - run: src/ci/scripts/dump-environment.sh - - - name: install awscli - run: src/ci/scripts/install-awscli.sh - - - name: install sccache - run: src/ci/scripts/install-sccache.sh - - - name: select Xcode - run: src/ci/scripts/select-xcode.sh - - - name: install clang - run: src/ci/scripts/install-clang.sh - - - name: install tidy - run: src/ci/scripts/install-tidy.sh - - - name: install WIX - run: src/ci/scripts/install-wix.sh - - - name: disable git crlf conversion - run: src/ci/scripts/disable-git-crlf-conversion.sh - - - name: checkout submodules - run: src/ci/scripts/checkout-submodules.sh - - - name: install MSYS2 - run: src/ci/scripts/install-msys2.sh - - - name: install MinGW - run: src/ci/scripts/install-mingw.sh - - - name: install ninja - run: src/ci/scripts/install-ninja.sh - - - name: enable ipv6 on Docker - run: src/ci/scripts/enable-docker-ipv6.sh - - # Disable automatic line ending conversion (again). On Windows, when we're - # installing dependencies, something switches the git configuration directory or - # re-enables autocrlf. We've not tracked down the exact cause -- and there may - # be multiple -- but this should ensure submodules are checked out with the - # appropriate line endings. - - name: disable git crlf conversion - run: src/ci/scripts/disable-git-crlf-conversion.sh - - - name: ensure line endings are correct - run: src/ci/scripts/verify-line-endings.sh - - - name: ensure backported commits are in upstream branches - run: src/ci/scripts/verify-backported-commits.sh - - - name: ensure the stable version number is correct - run: src/ci/scripts/verify-stable-version-number.sh - - - name: run the build - # Redirect stderr to stdout to avoid reordering the two streams in the GHA logs. - run: src/ci/scripts/run-build-from-ci.sh 2>&1 - 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 }} - - - name: create github artifacts - run: src/ci/scripts/create-doc-artifacts.sh - - - name: upload artifacts to github - uses: actions/upload-artifact@v4 - with: - # name is set in previous step - name: ${{ env.DOC_ARTIFACT_NAME }} - path: obj/artifacts/doc - if-no-files-found: ignore - retention-days: 5 - - - name: upload artifacts to S3 - run: src/ci/scripts/upload-artifacts.sh - env: - AWS_ACCESS_KEY_ID: ${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }} - # Adding a condition on DEPLOY=1 or DEPLOY_ALT=1 is not needed as all deploy - # builders *should* have the AWS credentials available. Still, explicitly - # adding the condition is helpful as this way CI will not silently skip - # deploying artifacts from a dist builder if the variables are misconfigured, - # erroring about invalid credentials instead. - if: success() && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1') - - # These snippets are used by the try-success, try-failure, auto-success and auto-failure jobs. - # Check out their documentation for more information on why they're needed. - - - &base-outcome-job - name: bors build finished - runs-on: ubuntu-latest - - - &base-success-job - steps: - - name: mark the job as a success - run: exit 0 - shell: bash - <<: *base-outcome-job - - - &base-failure-job - steps: - - name: mark the job as a failure - run: exit 1 - shell: bash - <<: *base-outcome-job - -########################### -# Builders definition # -########################### - -name: CI -on: - push: - branches: - - auto - - try - - try-perf - - automation/bors/try - - master - pull_request: - branches: - - "**" - -permissions: - contents: read - packages: write - -defaults: - run: - # On Linux, macOS, and Windows, use the system-provided bash as the default - # shell. (This should only make a difference on Windows, where the default - # shell is PowerShell.) - shell: bash - -concurrency: - # For a given workflow, if we push to the same branch, cancel all previous builds on that branch. - # We add an exception for try builds (try branch) and unrolled rollup builds (try-perf), which - # are all triggered on the same branch, but which should be able to run concurrently. - group: ${{ github.workflow }}-${{ ((github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.sha) || github.ref }} - cancel-in-progress: true - -jobs: - # The job matrix for `calculate_matrix` is defined in src/ci/github-actions/jobs.yml. - # It calculates which jobs should be executed, based on the data of the ${{ github }} context. - # If you want to modify CI jobs, take a look at src/ci/github-actions/jobs.yml. - calculate_matrix: - name: Calculate job matrix - runs-on: ubuntu-latest - outputs: - jobs: ${{ steps.jobs.outputs.jobs }} - steps: - - name: Checkout the source code - uses: actions/checkout@v4 - - name: Calculate the CI job matrix - run: python3 src/ci/github-actions/calculate-job-matrix.py >> $GITHUB_OUTPUT - id: jobs - job: - <<: *base-ci-job - name: ${{ matrix.name }} - needs: [ calculate_matrix ] - env: - CI_JOB_NAME: ${{ matrix.image }} - CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse - # commit of PR sha or commit sha. `GITHUB_SHA` is not accurate for PRs. - HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }} - DOCKER_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SCCACHE_BUCKET: rust-lang-ci-sccache2 - TOOLSTATE_REPO: https://github.com/rust-lang-nursery/rust-toolstate - CACHE_DOMAIN: ci-caches.rust-lang.org - continue-on-error: ${{ matrix.continue_on_error || false }} - strategy: - matrix: - # Check the `calculate_matrix` job to see how is the matrix defined. - include: ${{ fromJSON(needs.calculate_matrix.outputs.jobs) }} - # GitHub Actions fails the workflow if an empty list of jobs is provided to - # the workflow, so we need to skip this job if nothing was produced by - # the Python script. - # - # Unfortunately checking whether a list is empty is not possible in a nice - # way due to GitHub Actions expressions limits. - # This hack is taken from https://github.com/ferrocene/ferrocene/blob/d43edc6b7697cf1719ec1c17c54904ab94825763/.github/workflows/release.yml#L75-L82 - if: fromJSON(needs.calculate_matrix.outputs.jobs)[0] != null - - master: - name: master - runs-on: ubuntu-latest - env: - <<: [*prod-variables] - if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'rust-lang-ci/rust' - steps: - - name: checkout the source code - uses: actions/checkout@v4 - with: - fetch-depth: 2 - - - name: publish toolstate - run: src/ci/publish_toolstate.sh - shell: bash - env: - TOOLSTATE_REPO_ACCESS_TOKEN: ${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }} - - # These jobs don't actually test anything, but they're used to tell bors the - # build completed, as there is no practical way to detect when a workflow is - # successful listening to webhooks only. - try-success: - needs: [ job ] - if: "success() && github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'" - <<: *base-success-job - try-failure: - needs: [ job ] - if: "!success() && github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'" - <<: *base-failure-job - auto-success: - needs: [ job ] - if: "success() && github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'" - <<: *base-success-job - auto-failure: - needs: [ job ] - if: "!success() && github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'" - <<: *base-failure-job diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index df6c5d6079d..20b1a55ffb8 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -1,7 +1,5 @@ # This file contains definitions of CI job parameters that are loaded # dynamically in CI from ci.yml. -# You *do not* need to re-run `src/tools/expand-yaml-anchors` when you -# modify this file. runners: - &base-job env: { } @@ -27,10 +25,18 @@ runners: <<: *base-job - &job-windows-8c - os: windows-2019-8core-32gb + os: windows-2022-8core-32gb <<: *base-job - &job-windows-16c + os: windows-2022-16core-64gb + <<: *base-job + + - &job-windows-2019-8c + os: windows-2019-8core-32gb + <<: *base-job + + - &job-windows-2019-16c os: windows-2019-16core-64gb <<: *base-job @@ -38,6 +44,17 @@ runners: os: [ self-hosted, ARM64, linux ] envs: + env-x86_64-apple-tests: &env-x86_64-apple-tests + SCRIPT: ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc --skip tests/run-make-fulldeps + 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.12 + MACOSX_STD_DEPLOYMENT_TARGET: 10.12 + SELECT_XCODE: /Applications/Xcode_14.3.1.app + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + NO_OVERFLOW_CHECKS: 1 + production: &production DEPLOY_BUCKET: rust-lang-ci2 @@ -274,16 +291,8 @@ auto: <<: *job-macos-xl - image: x86_64-apple-1 - env: &env-x86_64-apple-tests - SCRIPT: ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc --skip tests/run-make-fulldeps - 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.12 - MACOSX_STD_DEPLOYMENT_TARGET: 10.12 - SELECT_XCODE: /Applications/Xcode_14.3.1.app - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - NO_OVERFLOW_CHECKS: 1 + env: + <<: *env-x86_64-apple-tests <<: *job-macos-xl - image: x86_64-apple-2 @@ -340,13 +349,13 @@ auto: env: RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler SCRIPT: make ci-msvc - <<: *job-windows-8c + <<: *job-windows-2019-8c - image: i686-msvc env: RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc SCRIPT: make ci-msvc - <<: *job-windows-8c + <<: *job-windows-2019-8c - image: x86_64-msvc-ext env: @@ -354,7 +363,7 @@ auto: HOST_TARGET: x86_64-pc-windows-msvc RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld --save-toolstates=/tmp/toolstate/toolstates.json DEPLOY_TOOLSTATES_JSON: toolstates-windows.json - <<: *job-windows-8c + <<: *job-windows-2019-8c # 32/64-bit MinGW builds. # @@ -405,7 +414,7 @@ auto: --set rust.codegen-units=1 SCRIPT: python x.py build --set rust.debug=true opt-dist && PGO_HOST=x86_64-pc-windows-msvc ./build/x86_64-pc-windows-msvc/stage0-tools-bin/opt-dist windows-ci -- python x.py dist bootstrap --include-default-paths DIST_REQUIRE_ALL_TOOLS: 1 - <<: *job-windows-8c + <<: *job-windows-2019-8c - image: dist-i686-msvc env: @@ -417,7 +426,7 @@ auto: --enable-profiler SCRIPT: python x.py dist bootstrap --include-default-paths DIST_REQUIRE_ALL_TOOLS: 1 - <<: *job-windows-8c + <<: *job-windows-2019-8c - image: dist-aarch64-msvc env: @@ -428,7 +437,7 @@ auto: --enable-profiler SCRIPT: python x.py dist bootstrap --include-default-paths DIST_REQUIRE_ALL_TOOLS: 1 - <<: *job-windows-8c + <<: *job-windows-2019-8c - image: dist-i686-mingw env: @@ -462,4 +471,4 @@ auto: env: RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler SCRIPT: python x.py dist bootstrap --include-default-paths - <<: *job-windows-8c + <<: *job-windows-2019-8c diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 31096b6df92..c9c0ee4067f 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -3,6 +3,7 @@ - [What is rustc?](what-is-rustc.md) - [Command-line Arguments](command-line-arguments.md) - [Codegen Options](codegen-options/index.md) +- [Jobserver](jobserver.md) - [Lints](lints/index.md) - [Lint Levels](lints/levels.md) - [Lint Groups](lints/groups.md) @@ -55,6 +56,11 @@ - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md) - [riscv32*-unknown-none-elf](platform-support/riscv32-unknown-none-elf.md) - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md) + - [thumbv6m-none-eabi](./platform-support/thumbv6m-none-eabi.md) + - [thumbv7m-none-eabi](./platform-support/thumbv7m-none-eabi.md) + - [thumbv7em-none-eabi\*](./platform-support/thumbv7em-none-eabi.md) + - [thumbv8m.base-none-eabi](./platform-support/thumbv8m.base-none-eabi.md) + - [thumbv8m.main-none-eabi\*](./platform-support/thumbv8m.main-none-eabi.md) - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md) - [\*-nto-qnx-\*](platform-support/nto-qnx.md) - [*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md) diff --git a/src/doc/rustc/src/instrument-coverage.md b/src/doc/rustc/src/instrument-coverage.md index bbd81e7437c..32dc992c42f 100644 --- a/src/doc/rustc/src/instrument-coverage.md +++ b/src/doc/rustc/src/instrument-coverage.md @@ -348,11 +348,7 @@ $ llvm-cov report \ ## `-Z coverage-options=<options>` -This unstable option provides finer control over some aspects of coverage -instrumentation. Pass one or more of the following values, separated by commas. - -- Either `no-branch`, `branch` or `mcdc` - - `branch` enables branch coverage instrumentation and `mcdc` further enables modified condition/decision coverage instrumentation. `no-branch` disables branch coverage instrumentation, which is same as do not pass `branch` or `mcdc`. +[This unstable option is described in the Unstable Book.](../unstable-book/compiler-flags/coverage-options.html) ## Other references diff --git a/src/doc/rustc/src/jobserver.md b/src/doc/rustc/src/jobserver.md new file mode 100644 index 00000000000..da82b0df7c6 --- /dev/null +++ b/src/doc/rustc/src/jobserver.md @@ -0,0 +1,86 @@ +# Jobserver + +Internally, `rustc` may take advantage of parallelism. `rustc` will coordinate +with the build system calling it if a [GNU Make jobserver] is passed in the +`MAKEFLAGS` environment variable. Other flags may have an effect as well, such +as [`CARGO_MAKEFLAGS`]. If a jobserver is not passed, then `rustc` will choose +the number of jobs to use. + +Starting with Rust 1.76.0, `rustc` will warn if a jobserver appears to be +available but is not accessible, e.g.: + +```console +$ echo 'fn main() {}' | MAKEFLAGS=--jobserver-auth=3,4 rustc - +warning: failed to connect to jobserver from environment variable `MAKEFLAGS="--jobserver-auth=3,4"`: cannot open file descriptor 3 from the jobserver environment variable value: Bad file descriptor (os error 9) + | + = note: the build environment is likely misconfigured +``` + +## Integration with build systems + +The following subsections contain recommendations on how to integrate `rustc` +with build systems so that the jobserver is handled appropriately. + +### GNU Make + +When calling `rustc` from GNU Make, it is recommended that all `rustc` +invocations are marked as recursive in the `Makefile` (by prefixing the command +line with the `+` indicator), so that GNU Make enables the jobserver for them. +For instance: + +<!-- ignore-tidy-tab --> + +```make +x: + +@echo 'fn main() {}' | rustc - +``` + +In particular, GNU Make 4.3 (a widely used version as of 2024) passes a simple +pipe jobserver in `MAKEFLAGS` even when it was not made available for the child +process, which in turn means `rustc` will warn about it. For instance, if the +`+` indicator is removed from the example above and GNU Make is called with e.g. +`make -j2`, then the aforementioned warning will trigger. + +For calls to `rustc` inside `$(shell ...)` inside a recursive Make, one can +disable the jobserver manually by clearing the `MAKEFLAGS` variable, e.g.: + +```make +S := $(shell MAKEFLAGS= rustc --print sysroot) + +x: + @$(MAKE) y + +y: + @echo $(S) +``` + +### CMake + +CMake 3.28 supports the `JOB_SERVER_AWARE` option in its [`add_custom_target`] +command, e.g.: + +```cmake +cmake_minimum_required(VERSION 3.28) +project(x) +add_custom_target(x + JOB_SERVER_AWARE TRUE + COMMAND echo 'fn main() {}' | rustc - +) +``` + +For earlier versions, when using CMake with the Makefile generator, one +workaround is to have [`$(MAKE)`] somewhere in the command so that GNU Make +treats it as a recursive Make call, e.g.: + +```cmake +cmake_minimum_required(VERSION 3.22) +project(x) +add_custom_target(x + COMMAND DUMMY_VARIABLE=$(MAKE) echo 'fn main() {}' | rustc - +) +``` + +[GNU Make jobserver]: https://www.gnu.org/software/make/manual/html_node/POSIX-Jobserver.html +[`CARGO_MAKEFLAGS`]: https://doc.rust-lang.org/cargo/reference/environment-variables.html +[`add_custom_target`]: https://cmake.org/cmake/help/latest/command/add_custom_target.html +[`$(MAKE)`]: https://www.gnu.org/software/make/manual/html_node/MAKE-Variable.html diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 2578b71a158..764798a80e6 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -89,9 +89,9 @@ target | notes `aarch64-apple-darwin` | ARM64 macOS (11.0+, Big Sur+) `aarch64-pc-windows-msvc` | ARM64 Windows MSVC `aarch64-unknown-linux-musl` | ARM64 Linux with musl 1.2.3 -`arm-unknown-linux-gnueabi` | ARMv6 Linux (kernel 3.2, glibc 2.17) -`arm-unknown-linux-gnueabihf` | ARMv6 Linux, hardfloat (kernel 3.2, glibc 2.17) -`armv7-unknown-linux-gnueabihf` | ARMv7-A Linux, hardfloat (kernel 3.2, glibc 2.17) +`arm-unknown-linux-gnueabi` | Armv6 Linux (kernel 3.2, glibc 2.17) +`arm-unknown-linux-gnueabihf` | Armv6 Linux, hardfloat (kernel 3.2, glibc 2.17) +`armv7-unknown-linux-gnueabihf` | Armv7-A Linux, hardfloat (kernel 3.2, glibc 2.17) [`loongarch64-unknown-linux-gnu`](platform-support/loongarch-linux.md) | LoongArch64 Linux, LP64D ABI (kernel 5.19, glibc 2.36) `powerpc-unknown-linux-gnu` | PowerPC Linux (kernel 3.2, glibc 2.17) `powerpc64-unknown-linux-gnu` | PPC64 Linux (kernel 3.2, glibc 2.17) @@ -143,21 +143,21 @@ target | std | notes `aarch64-unknown-none-softfloat` | * | Bare ARM64, softfloat `aarch64-unknown-none` | * | Bare ARM64, hardfloat [`aarch64-unknown-uefi`](platform-support/unknown-uefi.md) | ? | ARM64 UEFI -[`arm-linux-androideabi`](platform-support/android.md) | ✓ | ARMv6 Android -`arm-unknown-linux-musleabi` | ✓ | ARMv6 Linux with musl 1.2.3 -`arm-unknown-linux-musleabihf` | ✓ | ARMv6 Linux with musl 1.2.3, hardfloat -[`armebv7r-none-eabi`](platform-support/armv7r-none-eabi.md) | * | Bare ARMv7-R, Big Endian -[`armebv7r-none-eabihf`](platform-support/armv7r-none-eabi.md) | * | Bare ARMv7-R, Big Endian, hardfloat -`armv5te-unknown-linux-gnueabi` | ✓ | ARMv5TE Linux (kernel 4.4, glibc 2.23) -`armv5te-unknown-linux-musleabi` | ✓ | ARMv5TE Linux with musl 1.2.3 -[`armv7-linux-androideabi`](platform-support/android.md) | ✓ | ARMv7-A Android -`armv7-unknown-linux-gnueabi` | ✓ | ARMv7-A Linux (kernel 4.15, glibc 2.27) -`armv7-unknown-linux-musleabi` | ✓ | ARMv7-A Linux with musl 1.2.3 -`armv7-unknown-linux-musleabihf` | ✓ | ARMv7-A Linux with musl 1.2.3, hardfloat -[`armv7-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | ARMv7-A OpenHarmony -[`armv7a-none-eabi`](platform-support/arm-none-eabi.md) | * | Bare ARMv7-A -[`armv7r-none-eabi`](platform-support/armv7r-none-eabi.md) | * | Bare ARMv7-R -[`armv7r-none-eabihf`](platform-support/armv7r-none-eabi.md) | * | Bare ARMv7-R, hardfloat +[`arm-linux-androideabi`](platform-support/android.md) | ✓ | Armv6 Android +`arm-unknown-linux-musleabi` | ✓ | Armv6 Linux with musl 1.2.3 +`arm-unknown-linux-musleabihf` | ✓ | Armv6 Linux with musl 1.2.3, hardfloat +[`armebv7r-none-eabi`](platform-support/armv7r-none-eabi.md) | * | Bare Armv7-R, Big Endian +[`armebv7r-none-eabihf`](platform-support/armv7r-none-eabi.md) | * | Bare Armv7-R, Big Endian, hardfloat +`armv5te-unknown-linux-gnueabi` | ✓ | Armv5TE Linux (kernel 4.4, glibc 2.23) +`armv5te-unknown-linux-musleabi` | ✓ | Armv5TE Linux with musl 1.2.3 +[`armv7-linux-androideabi`](platform-support/android.md) | ✓ | Armv7-A Android +`armv7-unknown-linux-gnueabi` | ✓ | Armv7-A Linux (kernel 4.15, glibc 2.27) +`armv7-unknown-linux-musleabi` | ✓ | Armv7-A Linux with musl 1.2.3 +`armv7-unknown-linux-musleabihf` | ✓ | Armv7-A Linux with musl 1.2.3, hardfloat +[`armv7-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | Armv7-A OpenHarmony +[`armv7a-none-eabi`](platform-support/arm-none-eabi.md) | * | Bare Armv7-A +[`armv7r-none-eabi`](platform-support/armv7r-none-eabi.md) | * | Bare Armv7-R +[`armv7r-none-eabihf`](platform-support/armv7r-none-eabi.md) | * | Bare Armv7-R, hardfloat `i586-pc-windows-msvc` | * | 32-bit Windows w/o SSE [^x86_32-floats-x87] `i586-unknown-linux-gnu` | ✓ | 32-bit Linux w/o SSE (kernel 3.2, glibc 2.17) [^x86_32-floats-x87] `i586-unknown-linux-musl` | ✓ | 32-bit Linux w/o SSE, musl 1.2.3 [^x86_32-floats-x87] @@ -178,15 +178,15 @@ target | std | notes `riscv64imac-unknown-none-elf` | * | Bare RISC-V (RV64IMAC ISA) `sparc64-unknown-linux-gnu` | ✓ | SPARC Linux (kernel 4.4, glibc 2.23) `sparcv9-sun-solaris` | ✓ | SPARC Solaris 11, illumos -[`thumbv6m-none-eabi`](platform-support/arm-none-eabi.md) | * | Bare ARMv6-M -[`thumbv7em-none-eabi`](platform-support/arm-none-eabi.md) | * | Bare ARMv7E-M -[`thumbv7em-none-eabihf`](platform-support/arm-none-eabi.md) | * | Bare ARMV7E-M, hardfloat -[`thumbv7m-none-eabi`](platform-support/arm-none-eabi.md) | * | Bare ARMv7-M -[`thumbv7neon-linux-androideabi`](platform-support/android.md) | ✓ | Thumb2-mode ARMv7-A Android with NEON -`thumbv7neon-unknown-linux-gnueabihf` | ✓ | Thumb2-mode ARMv7-A Linux with NEON (kernel 4.4, glibc 2.23) -[`thumbv8m.base-none-eabi`](platform-support/arm-none-eabi.md) | * | Bare ARMv8-M Baseline -[`thumbv8m.main-none-eabi`](platform-support/arm-none-eabi.md) | * | Bare ARMv8-M Mainline -[`thumbv8m.main-none-eabihf`](platform-support/arm-none-eabi.md) | * | Bare ARMv8-M Mainline, hardfloat +[`thumbv6m-none-eabi`](platform-support/thumbv6m-none-eabi.md) | * | Bare Armv6-M +[`thumbv7em-none-eabi`](platform-support/thumbv7em-none-eabi.md) | * | Bare Armv7E-M +[`thumbv7em-none-eabihf`](platform-support/thumbv7em-none-eabi.md) | * | Bare Armv7E-M, hardfloat +[`thumbv7m-none-eabi`](platform-support/thumbv7m-none-eabi.md) | * | Bare Armv7-M +[`thumbv7neon-linux-androideabi`](platform-support/android.md) | ✓ | Thumb2-mode Armv7-A Android with NEON +`thumbv7neon-unknown-linux-gnueabihf` | ✓ | Thumb2-mode Armv7-A Linux with NEON (kernel 4.4, glibc 2.23) +[`thumbv8m.base-none-eabi`](platform-support/thumbv8m.base-none-eabi.md) | * | Bare Armv8-M Baseline +[`thumbv8m.main-none-eabi`](platform-support/thumbv8m.main-none-eabi.md) | * | Bare Armv8-M Mainline +[`thumbv8m.main-none-eabihf`](platform-support/thumbv8m.main-none-eabi.md) | * | Bare Armv8-M Mainline, hardfloat `wasm32-unknown-emscripten` | ✓ | WebAssembly via Emscripten `wasm32-unknown-unknown` | ✓ | WebAssembly `wasm32-wasi` | ✓ | WebAssembly with WASI (undergoing a [rename to `wasm32-wasip1`][wasi-rename]) @@ -264,27 +264,27 @@ target | std | host | notes `aarch64_be-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (big-endian, ILP32 ABI) `aarch64_be-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (big-endian) [`aarch64_be-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD (big-endian) -[`arm64_32-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | ARM Apple WatchOS 64-bit with 32-bit pointers -[`armeb-unknown-linux-gnueabi`](platform-support/armeb-unknown-linux-gnueabi.md) | ✓ | ? | ARM BE8 the default ARM big-endian architecture since [ARMv6](https://developer.arm.com/documentation/101754/0616/armlink-Reference/armlink-Command-line-Options/--be8?lang=en). -[`armv4t-none-eabi`](platform-support/armv4t-none-eabi.md) | * | | Bare ARMv4T -`armv4t-unknown-linux-gnueabi` | ? | | ARMv4T Linux -[`armv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | Bare ARMv5TE -`armv5te-unknown-linux-uclibceabi` | ? | | ARMv5TE Linux with uClibc -`armv6-unknown-freebsd` | ✓ | ✓ | ARMv6 FreeBSD -[`armv6-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | ARMv6 NetBSD w/hard-float -[`armv6k-nintendo-3ds`](platform-support/armv6k-nintendo-3ds.md) | ? | | ARMv6K Nintendo 3DS, Horizon (Requires devkitARM toolchain) -[`armv7-sony-vita-newlibeabihf`](platform-support/armv7-sony-vita-newlibeabihf.md) | ✓ | | ARMv7-A Cortex-A9 Sony PlayStation Vita (requires VITASDK toolchain) -[`armv7-unknown-linux-uclibceabi`](platform-support/armv7-unknown-linux-uclibceabi.md) | ✓ | ✓ | ARMv7-A Linux with uClibc, softfloat -[`armv7-unknown-linux-uclibceabihf`](platform-support/armv7-unknown-linux-uclibceabihf.md) | ✓ | ? | ARMv7-A Linux with uClibc, hardfloat -`armv7-unknown-freebsd` | ✓ | ✓ | ARMv7-A FreeBSD -[`armv7-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | ARMv7-A NetBSD w/hard-float -`armv7-wrs-vxworks-eabihf` | ? | | ARMv7-A for VxWorks +[`arm64_32-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | Arm Apple WatchOS 64-bit with 32-bit pointers +[`armeb-unknown-linux-gnueabi`](platform-support/armeb-unknown-linux-gnueabi.md) | ✓ | ? | Arm BE8 the default Arm big-endian architecture since [Armv6](https://developer.arm.com/documentation/101754/0616/armlink-Reference/armlink-Command-line-Options/--be8?lang=en). +[`armv4t-none-eabi`](platform-support/armv4t-none-eabi.md) | * | | Bare Armv4T +`armv4t-unknown-linux-gnueabi` | ? | | Armv4T Linux +[`armv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | Bare Armv5TE +`armv5te-unknown-linux-uclibceabi` | ? | | Armv5TE Linux with uClibc +`armv6-unknown-freebsd` | ✓ | ✓ | Armv6 FreeBSD +[`armv6-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | Armv6 NetBSD w/hard-float +[`armv6k-nintendo-3ds`](platform-support/armv6k-nintendo-3ds.md) | ? | | Armv6k Nintendo 3DS, Horizon (Requires devkitARM toolchain) +[`armv7-sony-vita-newlibeabihf`](platform-support/armv7-sony-vita-newlibeabihf.md) | ✓ | | Armv7-A Cortex-A9 Sony PlayStation Vita (requires VITASDK toolchain) +[`armv7-unknown-linux-uclibceabi`](platform-support/armv7-unknown-linux-uclibceabi.md) | ✓ | ✓ | Armv7-A Linux with uClibc, softfloat +[`armv7-unknown-linux-uclibceabihf`](platform-support/armv7-unknown-linux-uclibceabihf.md) | ✓ | ? | Armv7-A Linux with uClibc, hardfloat +`armv7-unknown-freebsd` | ✓ | ✓ | Armv7-A FreeBSD +[`armv7-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | Armv7-A NetBSD w/hard-float +`armv7-wrs-vxworks-eabihf` | ? | | Armv7-A for VxWorks [`armv7a-kmc-solid_asp3-eabi`](platform-support/kmc-solid.md) | ✓ | | ARM SOLID with TOPPERS/ASP3 [`armv7a-kmc-solid_asp3-eabihf`](platform-support/kmc-solid.md) | ✓ | | ARM SOLID with TOPPERS/ASP3, hardfloat -[`armv7a-none-eabihf`](platform-support/arm-none-eabi.md) | * | | Bare ARMv7-A, hardfloat -[`armv7k-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | ARMv7-A Apple WatchOS -`armv7s-apple-ios` | ✓ | | ARMv7-A Apple-A6 Apple iOS -[`armv8r-none-eabihf`](platform-support/armv8r-none-eabihf.md) | * | | Bare ARMv8-R, hardfloat +[`armv7a-none-eabihf`](platform-support/arm-none-eabi.md) | * | | Bare Armv7-A, hardfloat +[`armv7k-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | Armv7-A Apple WatchOS +`armv7s-apple-ios` | ✓ | | Armv7-A Apple-A6 Apple iOS +[`armv8r-none-eabihf`](platform-support/armv8r-none-eabihf.md) | * | | Bare Armv8-R, hardfloat `avr-unknown-gnu-atmega328` | * | | AVR. Requires `-Z build-std=core` `bpfeb-unknown-none` | * | | BPF (big endian) `bpfel-unknown-none` | * | | BPF (little endian) @@ -360,11 +360,11 @@ target | std | host | notes [`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * | | Bare 32-bit SPARC V7+ [`sparc64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/sparc64 [`sparc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/sparc64 -[`thumbv4t-none-eabi`](platform-support/armv4t-none-eabi.md) | * | | Thumb-mode Bare ARMv4T -[`thumbv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | Thumb-mode Bare ARMv5TE +[`thumbv4t-none-eabi`](platform-support/armv4t-none-eabi.md) | * | | Thumb-mode Bare Armv4T +[`thumbv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | Thumb-mode Bare Armv5TE `thumbv7a-pc-windows-msvc` | ? | | `thumbv7a-uwp-windows-msvc` | ✓ | | -`thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode ARMv7-A Linux with NEON, musl 1.2.3 +`thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode Armv7-A Linux with NEON, musl 1.2.3 [`wasm32-wasip2`](platform-support/wasm32-wasip2.md) | ✓ | | WebAssembly [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly `x86_64-apple-ios-macabi` | ✓ | | Apple Catalyst on x86_64 diff --git a/src/doc/rustc/src/platform-support/arm-none-eabi.md b/src/doc/rustc/src/platform-support/arm-none-eabi.md index 6335a6405a1..0b1b10e4762 100644 --- a/src/doc/rustc/src/platform-support/arm-none-eabi.md +++ b/src/doc/rustc/src/platform-support/arm-none-eabi.md @@ -1,25 +1,131 @@ # `{arm,thumb}*-none-eabi(hf)?` -**Tier: 2** -- [arm(eb)?v7r-none-eabi(hf)?](armv7r-none-eabi.md) -- armv7a-none-eabi -- thumbv6m-none-eabi -- thumbv7m-none-eabi -- thumbv7em-none-eabi(hf)? -- thumbv8m.base-none-eabi -- thumbv8m.main-none-eabi(hf)? - -**Tier: 3** -- [{arm,thumb}v4t-none-eabi](armv4t-none-eabi.md) -- [{arm,thumb}v5te-none-eabi](armv5te-none-eabi.md) -- armv7a-none-eabihf -- [armv8r-none-eabihf](armv8r-none-eabihf.md) - -Bare-metal target for 32-bit ARM CPUs. - -If a target has a `*hf` variant, that variant uses the hardware floating-point -ABI and enables some minimum set of floating-point features based on the FPU(s) -available in that processor family. +## Tier 2 Target List + +- Arm A-Profile Architectures + - `armv7a-none-eabi` +- Arm R-Profile Architectures + - [`armv7r-none-eabi` and `armv7r-none-eabihf`](armv7r-none-eabi.md) + - [`armebv7r-none-eabi` and `armebv7r-none-eabihf`](armv7r-none-eabi.md) +- Arm M-Profile Architectures + - [`thumbv6m-none-eabi`](thumbv6m-none-eabi.md) + - [`thumbv7m-none-eabi`](thumbv7m-none-eabi.md) + - [`thumbv7em-none-eabi` and `thumbv7em-none-eabihf`](thumbv7em-none-eabi.md) + - [`thumbv8m.base-none-eabi`](thumbv8m.base-none-eabi.md) + - [`thumbv8m.main-none-eabi` and `thumbv8m.main-none-eabihf`](thumbv8m.main-none-eabi.md) +- *Legacy* Arm Architectures + - None + +## Tier 3 Target List + +- Arm A-Profile Architectures + - `armv7a-none-eabihf` +- Arm R-Profile Architectures + - [`armv8r-none-eabihf`](armv8r-none-eabihf.md) +- Arm M-Profile Architectures + - None +- *Legacy* Arm Architectures + - [`armv4t-none-eabi` and `thumbv4t-none-eabi`](armv4t-none-eabi.md) + - [`armv5te-none-eabi` and `thumbv5te-none-eabi`](armv5te-none-eabi.md) + +## Common Target Details + +This documentation covers details that apply to a range of bare-metal targets +for 32-bit Arm CPUs. In addition, target specific details may be covered in +their own document. + +There are two 32-bit instruction set architectures (ISAs) defined by Arm: + +- The [*A32 ISA*][a32-isa], with fixed-width 32-bit instructions. Previously + known as the *Arm* ISA, this originated with the original ARM1 of 1985 and has + been updated by various revisions to the architecture specifications ever + since. +- The [*T32 ISA*][t32-isa], with a mix of 16-bit and 32-bit width instructions. + Note that this term includes both the original 16-bit width *Thumb* ISA + introduced with the Armv4T architecture in 1994, and the later 16/32-bit sized + *Thumb-2* ISA introduced with the Armv6T2 architecture in 2003. Again, these + ISAs have been revised by subsequent revisions to the relevant Arm + architecture specifications. + +There is also a 64-bit ISA with fixed-width 32-bit instructions called the *A64 +ISA*, but targets which implement that instruction set generally start with +`aarch64*` and are discussed elsewhere. + +Rust targets starting with `arm*` generate Arm (A32) code by default, whilst +targets named `thumb*` generate Thumb (T32) code by default. Most Arm chips +support both Thumb mode and Arm mode, with the notable exception that M-profile +processors (`thumbv*m*-none-eabi*` targets) *only* support Thumb-mode. + +Rust targets ending with `eabi` use the so-called *soft-float ABI*: functions +which take `f32` or `f64` as arguments will have those values packed into +integer registers. This means that an FPU is not required from an ABI +perspective, but within a function floating-point instructions may still be used +if the code is compiled with a `target-cpu` or `target-feature` option that +enables FPU support. + +Rust targets ending in `eabihf` use the so-called *hard-float ABI*: functions +which take `f32` or `f64` as arguments will have them passed via FPU registers. +These targets therefore require the availability of an FPU and will assume some +baseline level of floating-point support is available (which can vary depending +on the target). More advanced floating-point instructions may be generated if +the code is compiled with a `target-cpu` or `target-feature` option that enables +such additional FPU support. For example, if a given hard-float target has +baseline *single-precision* (`f32`) support in hardware, there may be +`target-cpu` or `target-feature` options that tell LLVM to assume your processor +in fact also has *double-precision* (`f64`) support. + +You may of course use the `f32` and `f64` types in your code, regardless of the +ABI being used, or the level of support your processor has for performing such +operations in hardware. Any floating-point operations that LLVM assumes your +processor cannot support will be lowered to library calls (like `__aeabi_dadd`) +which perform the floating-point operation in software using integer +instructions. + +[t32-isa]: https://developer.arm.com/Architectures/T32%20Instruction%20Set%20Architecture +[a32-isa]: https://developer.arm.com/Architectures/A32%20Instruction%20Set%20Architecture + +## Target CPU and Target Feature options + +It is possible to tell Rust (or LLVM) that you have a specific model of Arm +processor, using the [`-C target-cpu`][target-cpu] option. You can also control +whether Rust (or LLVM) will include instructions that target optional hardware +features, e.g. hardware floating-point, or Advanced SIMD operations, using [`-C +target-feature`][target-feature]. + +It is important to note that selecting a *target-cpu* will typically enable +*all* the optional features available from Arm on that model of CPU and your +particular implementation of that CPU may not have those features available. In +that case, you can use `-C target-feature=-option` to turn off the specific CPU +features you do not have available, leaving you with the optimized instruction +scheduling and support for the features you do have. More details are available +in the detailed target-specific documentation. + +**Note:** Many target-features are currently unstable and subject to change, and +if you use them you should disassemble the compiler output and manually inspect +it to ensure only appropriate instructions for your CPU have been generated. + +If you wish to use the *target-cpu* and *target-feature* options, you can add +them to your `.cargo/config.toml` file alongside any other flags your project +uses (likely linker related ones): + +```toml +rustflags = [ + # Usual Arm bare-metal linker setup + "-Clink-arg=-Tlink.x", + "-Clink-arg=--nmagic", + # tell Rust we have a Cortex-M55 + "-Ctarget-cpu=cortex-m55", + # tell Rust our Cortex-M55 doesn't have Floating-Point M-Profile Vector + # Extensions (but it does have everything else a Cortex-M55 could have). + "-Ctarget-feature=-mve.fp" +] + +[build] +target = "thumbv8m.main-none-eabihf" +``` + +[target-cpu]: https://doc.rust-lang.org/rustc/codegen-options/index.html#target-cpu +[target-feature]: https://doc.rust-lang.org/rustc/codegen-options/index.html#target-feature ## Requirements @@ -45,14 +151,11 @@ according to the specific device you are using. Pass `-Clink-arg=-Tyour_script.ld` as a rustc argument to make the linker use `your_script.ld` during linking. -Targets named `thumb*` instead of `arm*` -generate Thumb-mode code by default. M-profile processors (`thumbv*m*-*` -targets) only support Thumb-mode code. -For the `arm*` targets, Thumb-mode code generation can be enabled by using -`-C target-feature=+thumb-mode`. Using the unstable -`#![feature(arm_target_feature)]`, the attribute -`#[target_feature(enable = "thumb-mode")]` can be applied to individual -`unsafe` functions to cause those functions to be compiled to Thumb-mode code. +For the `arm*` targets, Thumb-mode code generation can be enabled by using `-C +target-feature=+thumb-mode`. Using the unstable +`#![feature(arm_target_feature)]`, the attribute `#[target_feature(enable = +"thumb-mode")]` can be applied to individual `unsafe` functions to cause those +functions to be compiled to Thumb-mode code. ## Building Rust Programs @@ -69,16 +172,27 @@ build-std = ["core"] ``` Most of `core` should work as expected, with the following notes: -* If the target is not `*hf`, then floating-point operations are emulated in - software. + +* Floating-point operations are emulated in software unless LLVM is told to + enable FPU support (either by using an `eabihf` target, specifying a + `target-cpu` with FPU support, or using a `target-feature` to support for a + specific kind of FPU) * Integer division is also emulated in software on some targets, depending on - the CPU. -* Architectures prior to ARMv7 don't have atomic instructions. + the target, `target-cpu` and `target-feature`s. +* Older Arm architectures (e.g. Armv4, Armv5TE and Armv6-M) are limited to basic + [`load`][atomic-load] and [`store`][atomic-store] operations, and not more + advanced operations like [`fetch_add`][fetch-add] or + [`compare_exchange`][compare-exchange]. `alloc` is also supported, as long as you provide your own global allocator. Rust programs are output as ELF files. +[atomic-load]: https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicU32.html#method.load +[atomic-store]: https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicU32.html#method.store +[fetch-add]: https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicU32.html#method.fetch_add +[compare-exchange]: https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicU32.html#method.compare_exchange + ## Testing This is a cross-compiled target that you will need to emulate during testing. diff --git a/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md b/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md index 32d3440f1dc..e7e3fd01c4d 100644 --- a/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md +++ b/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md @@ -1,22 +1,22 @@ # armeb-unknown-linux-gnueabi **Tier: 3** -Target for cross-compiling Linux user-mode applications targeting the ARM BE8 architecture. +Target for cross-compiling Linux user-mode applications targeting the Arm BE8 architecture. ## Overview -BE8 architecture retains the same little-endian ordered code-stream used by conventional little endian ARM systems, however the data accesses are in big-endian. BE8 is used primarily in high-performance networking applications where the ability to read packets in their native "Network Byte Order" is important (many network protocols transmit data in big-endian byte order for their wire formats). +BE8 architecture retains the same little-endian ordered code-stream used by conventional little endian Arm systems, however the data accesses are in big-endian. BE8 is used primarily in high-performance networking applications where the ability to read packets in their native "Network Byte Order" is important (many network protocols transmit data in big-endian byte order for their wire formats). ## History -BE8 architecture is the default big-endian architecture for ARM since [ARMv6](https://developer.arm.com/documentation/101754/0616/armlink-Reference/armlink-Command-line-Options/--be8?lang=en). It's predecessor, used for ARMv4 and ARMv5 devices was [BE32](https://developer.arm.com/documentation/dui0474/j/linker-command-line-options/--be32). On ARMv6 architecture, endianness can be configured via [system registers](https://developer.arm.com/documentation/ddi0290/g/unaligned-and-mixed-endian-data-access-support/mixed-endian-access-support/interaction-between-the-bus-protocol-and-the-core-endianness). However, BE32 was withdrawn for [ARMv7](https://developer.arm.com/documentation/ddi0406/cb/Appendixes/Deprecated-and-Obsolete-Features/Obsolete-features/Support-for-BE-32-endianness-model) onwards. +BE8 architecture is the default big-endian architecture for Arm since [Armv6](https://developer.arm.com/documentation/101754/0616/armlink-Reference/armlink-Command-line-Options/--be8?lang=en). It's predecessor, used for Armv4 and Armv5 devices was [BE32](https://developer.arm.com/documentation/dui0474/j/linker-command-line-options/--be32). On Armv6 architecture, endianness can be configured via [system registers](https://developer.arm.com/documentation/ddi0290/g/unaligned-and-mixed-endian-data-access-support/mixed-endian-access-support/interaction-between-the-bus-protocol-and-the-core-endianness). However, BE32 was withdrawn for [Armv7](https://developer.arm.com/documentation/ddi0406/cb/Appendixes/Deprecated-and-Obsolete-Features/Obsolete-features/Support-for-BE-32-endianness-model) onwards. ## Target Maintainers * [@WorksButNotTested](https://github.com/WorksButNotTested) ## Requirements -The target is cross-compiled. This target supports `std` in the normal way (indeed only nominal changes are required from the standard ARM configuration). +The target is cross-compiled. This target supports `std` in the normal way (indeed only nominal changes are required from the standard Arm configuration). ## Target definition -The target definition can be seen [here](https://github.com/rust-lang/rust/tree/master/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs). In particular, it should be noted that the `features` specify that this target is built for the ARMv8 core. Though this can likely be modified as required. +The target definition can be seen [here](https://github.com/rust-lang/rust/tree/master/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs). In particular, it should be noted that the `features` specify that this target is built for the Armv8 core. Though this can likely be modified as required. ## Building the target Because it is Tier 3, rust does not yet ship pre-compiled artifacts for this target. diff --git a/src/doc/rustc/src/platform-support/armv4t-none-eabi.md b/src/doc/rustc/src/platform-support/armv4t-none-eabi.md index 29c47db8351..f4c8dd46f1d 100644 --- a/src/doc/rustc/src/platform-support/armv4t-none-eabi.md +++ b/src/doc/rustc/src/platform-support/armv4t-none-eabi.md @@ -2,12 +2,12 @@ Tier 3 -Bare-metal target for any cpu in the ARMv4T architecture family, supporting -ARM/Thumb code interworking (aka `a32`/`t32`), with ARM code as the default code +Bare-metal target for any cpu in the Armv4T architecture family, supporting +ARM/Thumb code interworking (aka `A32`/`T32`), with ARM code as the default code generation. In particular this supports the Game Boy Advance (GBA), but there's nothing -GBA-specific with this target, so any ARMv4T device should work fine. +GBA-specific with this target, so any Armv4T device should work fine. See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all `arm-none-eabi` targets. diff --git a/src/doc/rustc/src/platform-support/armv5te-none-eabi.md b/src/doc/rustc/src/platform-support/armv5te-none-eabi.md index 37284ba7209..41621e070bb 100644 --- a/src/doc/rustc/src/platform-support/armv5te-none-eabi.md +++ b/src/doc/rustc/src/platform-support/armv5te-none-eabi.md @@ -2,11 +2,11 @@ **Tier: 3** -Bare-metal target for any cpu in the ARMv5TE architecture family, supporting -ARM/Thumb code interworking (aka `a32`/`t32`), with `a32` code as the default code +Bare-metal target for any cpu in the Armv5TE architecture family, supporting +ARM/Thumb code interworking (aka `A32`/`T32`), with `A32` code as the default code generation. -The `thumbv5te-none-eabi` target is the same as this one, but the instruction set defaults to `t32`. +The `thumbv5te-none-eabi` target is the same as this one, but the instruction set defaults to `T32`. See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all `arm-none-eabi` targets. diff --git a/src/doc/rustc/src/platform-support/armv6k-nintendo-3ds.md b/src/doc/rustc/src/platform-support/armv6k-nintendo-3ds.md index 540e5a4af93..160986aeae9 100644 --- a/src/doc/rustc/src/platform-support/armv6k-nintendo-3ds.md +++ b/src/doc/rustc/src/platform-support/armv6k-nintendo-3ds.md @@ -2,7 +2,7 @@ **Tier: 3** -The Nintendo 3DS platform, which has an ARMv6K processor, and its associated +The Nintendo 3DS platform, which has an Armv6k processor, and its associated operating system (`horizon`). Rust support for this target is not affiliated with Nintendo, and is not derived diff --git a/src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabi.md b/src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabi.md index e351ea00130..f22a20835c1 100644 --- a/src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabi.md +++ b/src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabi.md @@ -2,7 +2,7 @@ **Tier: 3** -This target supports ARMv7 softfloat CPUs and uses the uclibc-ng standard library. This is a common configuration on many consumer routers (e.g., Netgear R7000, Asus RT-AC68U). +This target supports Armv7-A softfloat CPUs and uses the uclibc-ng standard library. This is a common configuration on many consumer routers (e.g., Netgear R7000, Asus RT-AC68U). ## Target maintainers @@ -16,7 +16,7 @@ This target supports host tools and std. ## Building the target -You will need to download or build a `'C'` cross toolchain that targets ARMv7 softfloat and that uses the uclibc-ng standard library. If your target hardware is something like a router or an embedded device, keep in mind that manufacturer supplied SDKs for this class of CPU could be outdated and potentially unsuitable for bootstrapping rust. +You will need to download or build a `'C'` cross toolchain that targets Armv7-A softfloat and that uses the uclibc-ng standard library. If your target hardware is something like a router or an embedded device, keep in mind that manufacturer supplied SDKs for this class of CPU could be outdated and potentially unsuitable for bootstrapping rust. [Here](https://github.com/lancethepants/tomatoware-toolchain) is a sample toolchain that is built using [buildroot](https://buildroot.org/). It uses modern toolchain components, older thus universal kernel headers (2.6.36.4), and is used for a project called [Tomatoware](https://github.com/lancethepants/tomatoware). This toolchain is patched so that its sysroot is located at /mmc (e.g., /mmc/bin, /mmc/lib, /mmc/include). This is useful in scenarios where the root filesystem is read-only but you are able attach external storage loaded with user applications. Tomatoware is an example of this that even allows you to run various compilers and developer tools natively on the target device. @@ -46,7 +46,7 @@ The following assumes you are using the Tomatoware toolchain and environment. Ad ### Native compilation -Since this target supports host tools, you can natively build rust applications directly on your target device. This can be convenient because it removes the complexities of cross compiling and you can immediately test and deploy your binaries. One downside is that compiling on your ARMv7 CPU will probably be much slower than cross compilation on your x86 machine. +Since this target supports host tools, you can natively build rust applications directly on your target device. This can be convenient because it removes the complexities of cross compiling and you can immediately test and deploy your binaries. One downside is that compiling on your Armv7-A CPU will probably be much slower than cross compilation on your x86 machine. To setup native compilation: diff --git a/src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabihf.md b/src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabihf.md index 1f029406367..1c8acc09c77 100644 --- a/src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabihf.md +++ b/src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabihf.md @@ -2,7 +2,7 @@ **Tier: 3** -This tier supports the ARMv7 processor running a Linux kernel and uClibc-ng standard library. It provides full support for rust and the rust standard library. +This tier supports the Armv7-A processor running a Linux kernel and uClibc-ng standard library. It provides full support for rust and the rust standard library. ## Designated Developers diff --git a/src/doc/rustc/src/platform-support/armv7r-none-eabi.md b/src/doc/rustc/src/platform-support/armv7r-none-eabi.md index 670cead9e00..5f0dc6a7115 100644 --- a/src/doc/rustc/src/platform-support/armv7r-none-eabi.md +++ b/src/doc/rustc/src/platform-support/armv7r-none-eabi.md @@ -2,7 +2,7 @@ **Tier: 2** -Bare-metal target for CPUs in the ARMv7-R architecture family, supporting +Bare-metal target for CPUs in the Armv7-R architecture family, supporting dual ARM/Thumb mode, with ARM mode as the default. Processors in this family include the [Arm Cortex-R4, 5, 7, and 8][cortex-r]. diff --git a/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md b/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md index 588e5d7c994..6f80a06020f 100644 --- a/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md +++ b/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md @@ -2,7 +2,7 @@ **Tier: 3** -Bare-metal target for CPUs in the ARMv8-R architecture family, supporting +Bare-metal target for CPUs in the Armv8-R architecture family, supporting dual ARM/Thumb mode, with ARM mode as the default. Processors in this family include the Arm [Cortex-R52][cortex-r52] diff --git a/src/doc/rustc/src/platform-support/thumbv6m-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv6m-none-eabi.md new file mode 100644 index 00000000000..f4ed6201bbd --- /dev/null +++ b/src/doc/rustc/src/platform-support/thumbv6m-none-eabi.md @@ -0,0 +1,62 @@ +# `thumbv6m-none-eabi` + +**Tier: 2** + +Bare-metal target for CPUs in the [Armv6-M] architecture family, supporting a +subset of the [T32 ISA][t32-isa]. + +Processors in this family include the: + +* [Arm Cortex-M0][cortex-m0] +* [Arm Cortex-M0+][cortex-m0plus] +* [Arm Cortex-M1][cortex-m1] + +See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all +`arm-none-eabi` targets. + +This target uses the soft-float ABI: functions which take `f32` or `f64` as +arguments will have those values packed into integer registers. This is the +only option because there is no FPU support in [Armv6-M]. + +[t32-isa]: https://developer.arm.com/Architectures/T32%20Instruction%20Set%20Architecture +[Armv6-M]: https://developer.arm.com/documentation/ddi0419/latest/ +[cortex-m0]: https://developer.arm.com/Processors/Cortex-M0 +[cortex-m0plus]: https://developer.arm.com/Processors/Cortex-M0+ +[cortex-m1]: https://developer.arm.com/Processors/Cortex-M1 + +## Target maintainers + +* [Rust Embedded Devices Working Group Cortex-M + Team](https://github.com/rust-embedded), `cortex-m@teams.rust-embedded.org` + +## Target CPU and Target Feature options + +See [the bare-metal Arm +docs](arm-none-eabi.md#target-cpu-and-target-feature-options) for details on how +to use these flags. + +### Table of supported CPUs + +| CPU | FPU | Target CPU | Target Features | +| ---------- | --- | --------------- | --------------------- | +| Cortex-M0 | No | `cortex-m0` | None | +| Cortex-M0+ | No | `cortex-m0plus` | None | +| Cortex-M1 | No | `cortex-m1` | None | + +### Arm Cortex-M0 + +The target CPU option is `cortex-m0`. + +There are no relevant feature flags, and the FPU is not available. + +### Arm Cortex-M0+ + +The target CPU option is `cortex-m0plus`. + +There are no relevant feature flags, and the FPU is not available. + +### Arm Cortex-M1 + +The target CPU option is `cortex-m1`. + +There are no relevant feature flags, and the FPU is not available. diff --git a/src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md new file mode 100644 index 00000000000..f25ef0383b1 --- /dev/null +++ b/src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md @@ -0,0 +1,74 @@ +# `thumbv7em-none-eabi` and `thumbv7em-none-eabihf` + +**Tier: 2** + +Bare-metal target for CPUs in the [Armv7E-M] architecture family, supporting a +subset of the [T32 ISA][t32-isa]. + +Processors in this family include the: + +* [Arm Cortex-M4][cortex-m4] and Arm Cortex-M4F +* [Arm Cortex-M7][cortex-m7] and Arm Cortex-M7F + +See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all +`arm-none-eabi` targets, in particular the difference between the `eabi` and +`eabihf` ABI. + +[t32-isa]: https://developer.arm.com/Architectures/T32%20Instruction%20Set%20Architecture +[Armv7E-M]: https://developer.arm.com/documentation/ddi0403/latest/ +[cortex-m4]: https://developer.arm.com/Processors/Cortex-M4 +[cortex-m7]: https://developer.arm.com/Processors/Cortex-M7 + +## Target maintainers + +* [Rust Embedded Devices Working Group Cortex-M + Team](https://github.com/rust-embedded), `cortex-m@teams.rust-embedded.org` + +## Target CPU and Target Feature options + +See [the bare-metal Arm +docs](arm-none-eabi.md#target-cpu-and-target-feature-options) for details on how +to use these flags. + +### Table of supported CPUs for `thumbv7em-none-eabi` + +| CPU | FPU | DSP | Target CPU | Target Features | +| ---------- | --- | --- | ----------- | --------------- | +| Any | No | Yes | None | None | +| Cortex-M4 | No | Yes | `cortex-m4` | `+soft-float` | +| Cortex-M4F | SP | Yes | `cortex-m4` | None | +| Cortex-M7 | No | Yes | `cortex-m7` | `+soft-float` | +| Cortex-M7F | SP | Yes | `cortex-m7` | `-fp64` | +| Cortex-M7F | DP | Yes | `cortex-m7` | None | + +### Table of supported CPUs for `thumbv7em-none-eabihf` + +| CPU | FPU | DSP | Target CPU | Target Features | +| ---------- | --- | --- | ----------- | --------------- | +| Any | SP | Yes | None | None | +| Cortex-M4F | SP | Yes | `cortex-m4` | None | +| Cortex-M7F | SP | Yes | `cortex-m7` | `-fp64` | +| Cortex-M7F | DP | Yes | `cortex-m7` | None | + +### Arm Cortex-M4 and Arm Cortex-M4F + +The target CPU is `cortex-m4`. + +* All Cortex-M4 have DSP extensions + * support is controlled by the `dsp` *target-feature* + * enabled by default with this *target* +* Cortex-M4F has a single precision FPU + * support is enabled by default with this *target-cpu* + * disable support using the `+soft-float` feature (`eabi` only) + +### Arm Cortex-M7 and Arm Cortex-M7F + +The target CPU is `cortex-m7`. + +* All Cortex-M7 have DSP extensions + * support is controlled by the `dsp` *target-feature* + * enabled by default with this *target* +* Cortex-M7F have either a single-precision or double-precision FPU + * double-precision support is enabled by default with this *target-cpu* + * opt-out by using the `-f64` *target-feature* + * disable support entirely using the `+soft-float` feature (`eabi` only) diff --git a/src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md new file mode 100644 index 00000000000..b258033bb0f --- /dev/null +++ b/src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md @@ -0,0 +1,44 @@ +# `thumbv7m-none-eabi` + +**Tier: 2** + +Bare-metal target for CPUs in the [Armv7-M] architecture family, supporting a +subset of the [T32 ISA][t32-isa]. + +Processors in this family include the: + +* [Arm Cortex-M3][cortex-m3] + +See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all +`arm-none-eabi` targets. + +This target uses the soft-float ABI: functions which take `f32` or `f64` as +arguments will have those values packed into integer registers. This is the +only option because there is no FPU support in [Armv7-M]. + +[t32-isa]: https://developer.arm.com/Architectures/T32%20Instruction%20Set%20Architecture +[Armv7-M]: https://developer.arm.com/documentation/ddi0403/latest/ +[cortex-m3]: https://developer.arm.com/Processors/Cortex-M3 + +## Target maintainers + +* [Rust Embedded Devices Working Group Cortex-M + Team](https://github.com/rust-embedded), `cortex-m@teams.rust-embedded.org` + +## Target CPU and Target Feature options + +See [the bare-metal Arm +docs](arm-none-eabi.md#target-cpu-and-target-feature-options) for details on how +to use these flags. + +### Table of supported CPUs + +| CPU | FPU | Target CPU | Target Features | +| ---------- | --- | ----------- | --------------------- | +| Cortex-M3 | No | `cortex-m3` | None | + +### Arm Cortex-M3 + +The target CPU option is `cortex-m3`. + +There are no relevant feature flags, and the FPU is not available. diff --git a/src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md new file mode 100644 index 00000000000..0ae4e3e94bd --- /dev/null +++ b/src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md @@ -0,0 +1,44 @@ +# `thumbv8m.base-none-eabi` + +**Tier: 2** + +Bare-metal target for CPUs in the Baseline [Armv8-M] architecture family, +supporting a subset of the [T32 ISA][t32-isa]. + +Processors in this family include the: + +* [Arm Cortex-M23][cortex-m23] + +See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all +`arm-none-eabi` targets. + +This target uses the soft-float ABI: functions which take `f32` or `f64` as +arguments will have those values packed into integer registers. This is the +only option because there is no FPU support in [Armv8-M] Baseline. + +[t32-isa]: https://developer.arm.com/Architectures/T32%20Instruction%20Set%20Architecture +[Armv8-M]: https://developer.arm.com/documentation/ddi0553/latest/ +[cortex-m23]: https://developer.arm.com/Processors/Cortex-M23 + +## Target maintainers + +* [Rust Embedded Devices Working Group Cortex-M + Team](https://github.com/rust-embedded), `cortex-m@teams.rust-embedded.org` + +## Target CPU and Target Feature options + +See [the bare-metal Arm +docs](arm-none-eabi.md#target-cpu-and-target-feature-options) for details on how +to use these flags. + +### Table of supported CPUs + +| CPU | FPU | Target CPU | Target Features | +| ----------- | --- | ------------ | --------------------- | +| Cortex-M23 | No | `cortex-m23` | None | + +### Arm Cortex-M23 + +The target CPU option is `cortex-m23`. + +There are no relevant feature flags, and the FPU is not available. diff --git a/src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md new file mode 100644 index 00000000000..4e696f9c304 --- /dev/null +++ b/src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md @@ -0,0 +1,135 @@ +# `thumbv8m.main-none-eabi` and `thumbv8m.main-none-eabihf` + +**Tier: 2** + +Bare-metal target for CPUs in the Mainline [Armv8-M] architecture family, +supporting a subset of the [T32 ISA][t32-isa]. + +Processors in this family include the: + +* [Arm Cortex-M33][cortex-m33] +* [Arm Cortex-M35P][cortex-m35p] +* [Arm Cortex-M55][cortex-m55] +* [Arm Cortex-M85][cortex-m85] + +See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all +`arm-none-eabi` targets, in particular the difference between the `eabi` and +`eabihf` ABI. + +[t32-isa]: https://developer.arm.com/Architectures/T32%20Instruction%20Set%20Architecture +[Armv8-M]: https://developer.arm.com/documentation/ddi0553/latest/ +[cortex-m33]: https://developer.arm.com/Processors/Cortex-M33 +[cortex-m35p]: https://developer.arm.com/Processors/Cortex-M35P +[cortex-m55]: https://developer.arm.com/Processors/Cortex-M55 +[cortex-m85]: https://developer.arm.com/Processors/Cortex-M85 + +## Target maintainers + +* [Rust Embedded Devices Working Group Cortex-M + Team](https://github.com/rust-embedded), `cortex-m@teams.rust-embedded.org` + +## Target CPU and Target Feature options + +See [the bare-metal Arm +docs](arm-none-eabi.md#target-cpu-and-target-feature-options) for details on how +to use these flags. + +### Table of supported CPUs for `thumbv8m.main-none-eabi` + +| CPU | FPU | DSP | MVE | Target CPU | Target Features | +| ----------- | --- | --- | --------- | ------------- | --------------------- | +| Unspecified | No | No | No | None | None | +| Cortex-M33 | No | No | No | `cortex-m33` | `+soft-float,-dsp` | +| Cortex-M33 | No | Yes | No | `cortex-m33` | `+soft-float` | +| Cortex-M33 | SP | No | No | `cortex-m33` | `-dsp` | +| Cortex-M33 | SP | Yes | No | `cortex-m33` | None | +| Cortex-M35P | No | No | No | `cortex-m35p` | `+soft-float,-dsp` | +| Cortex-M35P | No | Yes | No | `cortex-m35p` | `+soft-float` | +| Cortex-M35P | SP | No | No | `cortex-m35p` | `-dsp` | +| Cortex-M35P | SP | Yes | No | `cortex-m35p` | None | +| Cortex-M55 | No | Yes | No | `cortex-m55` | `+soft-float,-mve` | +| Cortex-M55 | DP | Yes | No | `cortex-m55` | `-mve` | +| Cortex-M55 | No | Yes | Int | `cortex-m55` | `+soft-float,-mve.fp` | +| Cortex-M55 | DP | Yes | Int | `cortex-m55` | `-mve.fp` | +| Cortex-M55 | DP | Yes | Int+Float | `cortex-m55` | None | +| Cortex-M85 | No | Yes | No | `cortex-m85` | `+soft-float,-mve` | +| Cortex-M85 | DP | Yes | No | `cortex-m85` | `-mve` | +| Cortex-M85 | No | Yes | Int | `cortex-m85` | `+soft-float,-mve.fp` | +| Cortex-M85 | DP | Yes | Int | `cortex-m85` | `-mve.fp` | +| Cortex-M85 | DP | Yes | Int+Float | `cortex-m85` | None | + +### Table of supported CPUs for `thumbv8m.main-none-eabihf` + +| CPU | FPU | DSP | MVE | Target CPU | Target Features | +| ----------- | --- | --- | --------- | ------------- | --------------------- | +| Unspecified | SP | No | No | None | None | +| Cortex-M33 | SP | No | No | `cortex-m33` | `-dsp` | +| Cortex-M33 | SP | Yes | No | `cortex-m33` | None | +| Cortex-M33P | SP | No | No | `cortex-m35p` | `-dsp` | +| Cortex-M33P | SP | Yes | No | `cortex-m35p` | None | +| Cortex-M55 | DP | Yes | No | `cortex-m55` | `-mve` | +| Cortex-M55 | DP | Yes | Int | `cortex-m55` | `-mve.fp` | +| Cortex-M55 | DP | Yes | Int+Float | `cortex-m55` | None | +| Cortex-M85 | DP | Yes | No | `cortex-m85` | `-mve` | +| Cortex-M85 | DP | Yes | Int | `cortex-m85` | `-mve.fp` | +| Cortex-M85 | DP | Yes | Int+Float | `cortex-m85` | None | + +### Arm Cortex-M33 + +The target CPU is `cortex-m33`. + +* Has optional DSP extensions + * support is controlled by the `dsp` *target-feature* + * enabled by default with this *target-cpu* +* Has an optional single precision FPU + * support is enabled by default with this *target-cpu* + * disable support using the `+soft-float` feature (`eabi` only) + +### Arm Cortex-M35P + +The target CPU is `cortex-m35p`. + +* Has optional DSP extensions + * support is controlled by the `dsp` *target-feature* + * enabled by default with this *target-cpu* +* Has an optional single precision FPU + * support is enabled by default with this *target-cpu* + * disable support using the `+soft-float` feature (`eabi` only) + +### Arm Cortex-M55 + +The target CPU is `cortex-m55`. + +* Has DSP extensions + * support is controlled by the `dsp` *target-feature* + * enabled by default with this *target-cpu* +* Has an optional double-precision FPU that also supports half-precision FP16 + values + * support is enabled by default with this *target-cpu* + * disable support using the `+soft-float` feature (`eabi` only) +* Has optional support for M-Profile Vector Extensions + * Also known as *Helium Technology* + * Available with only integer support, or both integer/float support + * The appropriate feature for the MVE is either `mve` (integer) or `mve.fp` + (float) + * `mve.fp` is enabled by default on this target CPU + * disable using `-mve.fp` (disable float MVE) or `-mve` (disable all MVE) + +### Arm Cortex-M85 + +The target CPU is `cortex-m85`. + +* Has DSP extensions + * support is controlled by the `dsp` *target-feature* + * enabled by default with this *target-cpu* +* Has an optional double-precision FPU that also supports half-precision FP16 + values + * support is enabled by default with this *target-cpu* + * disable support using the `+soft-float` feature (`eabi` only) +* Has optional support for M-Profile Vector Extensions + * Also known as *Helium Technology* + * Available with only integer support, or both integer/float support + * The appropriate feature for the MVE is either `mve` (integer) or `mve.fp` + (float) + * `mve.fp` is enabled by default on this target CPU + * disable using `-mve.fp` (disable float MVE) or `-mve` (disable all MVE) diff --git a/src/doc/unstable-book/src/compiler-flags/coverage-options.md b/src/doc/unstable-book/src/compiler-flags/coverage-options.md index 5e192d9aca1..21278833550 100644 --- a/src/doc/unstable-book/src/compiler-flags/coverage-options.md +++ b/src/doc/unstable-book/src/compiler-flags/coverage-options.md @@ -5,4 +5,13 @@ This option controls details of the coverage instrumentation performed by Multiple options can be passed, separated by commas. Valid options are: -- `no-branch`, `branch` or `mcdc`: `branch` enables branch coverage instrumentation and `mcdc` further enables modified condition/decision coverage instrumentation. `no-branch` disables branch coverage instrumentation as well as mcdc instrumentation, which is same as do not pass `branch` or `mcdc`. +- `block`, `branch`, `mcdc`: + Sets the level of coverage instrumentation. + Setting the level will override any previously-specified level. + - `block` (default): + Blocks in the control-flow graph will be instrumented for coverage. + - `branch`: + In addition to block coverage, also enables branch coverage instrumentation. + - `mcdc`: + In addition to block and branch coverage, also enables MC/DC instrumentation. + (Branch coverage instrumentation may differ in some cases.) diff --git a/src/doc/unstable-book/src/compiler-flags/on-broken-pipe.md b/src/doc/unstable-book/src/compiler-flags/on-broken-pipe.md new file mode 100644 index 00000000000..bdc175f3b0a --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/on-broken-pipe.md @@ -0,0 +1,84 @@ +# `on-broken-pipe` + +-------------------- + +The tracking issue for this feature is: [#97889] + +Note: The ui for this feature was previously an attribute named `#[unix_sigpipe = "..."]`. + +[#97889]: https://github.com/rust-lang/rust/issues/97889 + +--- + + +## Overview + +The `-Zon-broken-pipe=...` compiler flag can be used to specify how libstd shall setup `SIGPIPE` on Unix platforms before invoking `fn main()`. This flag is ignored on non-Unix targets. The flag can be used with three different values or be omitted entirely. It affects `SIGPIPE` before `fn main()` and before children get `exec()`'ed: + +| Compiler flag | `SIGPIPE` before `fn main()` | `SIGPIPE` before child `exec()` | +|----------------------------|------------------------------|---------------------------------| +| not used | `SIG_IGN` | `SIG_DFL` | +| `-Zon-broken-pipe=kill` | `SIG_DFL` | not touched | +| `-Zon-broken-pipe=error` | `SIG_IGN` | not touched | +| `-Zon-broken-pipe=inherit` | not touched | not touched | + + +## `-Zon-broken-pipe` not used + +If `-Zon-broken-pipe` is not used, libstd will behave in the manner it has since 2014, before Rust 1.0. `SIGPIPE` will be set to `SIG_IGN` before `fn main()` and result in `EPIPE` errors which are converted to `std::io::ErrorKind::BrokenPipe`. + +When spawning child processes, `SIGPIPE` will be set to `SIG_DFL` before doing the underlying `exec()` syscall. + + +## `-Zon-broken-pipe=kill` + +Set the `SIGPIPE` handler to `SIG_DFL` before invoking `fn main()`. This will result in your program getting killed if it tries to write to a closed pipe. This is normally what you want if your program produces textual output. + +When spawning child processes, `SIGPIPE` will not be touched. This normally means child processes inherit `SIG_DFL` for `SIGPIPE`. + +### Example + +```rust,no_run +fn main() { + loop { + println!("hello world"); + } +} +``` + +```console +$ rustc -Zon-broken-pipe=kill main.rs +$ ./main | head -n1 +hello world +``` + +## `-Zon-broken-pipe=error` + +Set the `SIGPIPE` handler to `SIG_IGN` before invoking `fn main()`. This will result in `ErrorKind::BrokenPipe` errors if you program tries to write to a closed pipe. This is normally what you want if you for example write socket servers, socket clients, or pipe peers. + +When spawning child processes, `SIGPIPE` will not be touched. This normally means child processes inherit `SIG_IGN` for `SIGPIPE`. + +### Example + +```rust,no_run +fn main() { + loop { + println!("hello world"); + } +} +``` + +```console +$ rustc -Zon-broken-pipe=error main.rs +$ ./main | head -n1 +hello world +thread 'main' panicked at library/std/src/io/stdio.rs:1118:9: +failed printing to stdout: Broken pipe (os error 32) +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +``` + +## `-Zon-broken-pipe=inherit` + +Leave `SIGPIPE` untouched before entering `fn main()`. Unless the parent process has changed the default `SIGPIPE` handler from `SIG_DFL` to something else, this will behave the same as `-Zon-broken-pipe=kill`. + +When spawning child processes, `SIGPIPE` will not be touched. This normally means child processes inherit `SIG_DFL` for `SIGPIPE`. diff --git a/src/doc/unstable-book/src/language-features/unix-sigpipe.md b/src/doc/unstable-book/src/language-features/unix-sigpipe.md deleted file mode 100644 index 7ed6a7de895..00000000000 --- a/src/doc/unstable-book/src/language-features/unix-sigpipe.md +++ /dev/null @@ -1,62 +0,0 @@ -# `unix_sigpipe` - -The tracking issue for this feature is: [#97889] - -[#97889]: https://github.com/rust-lang/rust/issues/97889 - ---- - -The `#[unix_sigpipe = "..."]` attribute on `fn main()` can be used to specify how libstd shall setup `SIGPIPE` on Unix platforms before invoking `fn main()`. This attribute is ignored on non-Unix targets. There are three variants: -* `#[unix_sigpipe = "inherit"]` -* `#[unix_sigpipe = "sig_dfl"]` -* `#[unix_sigpipe = "sig_ign"]` - -## `#[unix_sigpipe = "inherit"]` - -Leave `SIGPIPE` untouched before entering `fn main()`. Unless the parent process has changed the default `SIGPIPE` handler from `SIG_DFL` to something else, this will behave the same as `#[unix_sigpipe = "sig_dfl"]`. - -## `#[unix_sigpipe = "sig_dfl"]` - -Set the `SIGPIPE` handler to `SIG_DFL`. This will result in your program getting killed if it tries to write to a closed pipe. This is normally what you want if your program produces textual output. - -### Example - -```rust,no_run -#![feature(unix_sigpipe)] -#[unix_sigpipe = "sig_dfl"] -fn main() { loop { println!("hello world"); } } -``` - -```bash -% ./main | head -n 1 -hello world -``` - -## `#[unix_sigpipe = "sig_ign"]` - -Set the `SIGPIPE` handler to `SIG_IGN` before invoking `fn main()`. This will result in `ErrorKind::BrokenPipe` errors if you program tries to write to a closed pipe. This is normally what you want if you for example write socket servers, socket clients, or pipe peers. - -This is what libstd has done by default since 2014. (However, see the note on child processes below.) - -### Example - -```rust,no_run -#![feature(unix_sigpipe)] -#[unix_sigpipe = "sig_ign"] -fn main() { loop { println!("hello world"); } } -``` - -```bash -% ./main | head -n 1 -hello world -thread 'main' panicked at 'failed printing to stdout: Broken pipe (os error 32)', library/std/src/io/stdio.rs:1016:9 -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -``` - -### Note on child processes - -When spawning child processes, the legacy Rust behavior if `#[unix_sigpipe]` is not specified is to -reset `SIGPIPE` to `SIG_DFL`. - -If `#[unix_sigpipe = "..."]` is specified, no matter what its value is, the signal disposition of -`SIGPIPE` is no longer reset. This means that the child inherits the parent's `SIGPIPE` behavior. diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 9a23811ed3f..31222f213d8 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -10,11 +10,9 @@ path = "lib.rs" arrayvec = { version = "0.7", default-features = false } askama = { version = "0.12", default-features = false, features = ["config"] } base64 = "0.21.7" -byteorder = "1.5" itertools = "0.12" indexmap = "2" minifier = "0.3.0" -once_cell = "1.10.0" regex = "1" rustdoc-json-types = { path = "../rustdoc-json-types" } serde_json = "1.0" diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index fc4f48262e5..f437c7d319d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -281,7 +281,10 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) -> Lifetime(lifetime.ident.name) } -pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg, cx: &mut DocContext<'tcx>) -> Constant { +pub(crate) fn clean_const<'tcx>( + constant: &hir::ConstArg<'_>, + cx: &mut DocContext<'tcx>, +) -> Constant { let def_id = cx.tcx.hir().body_owner_def_id(constant.value.body).to_def_id(); Constant { type_: Box::new(clean_middle_ty( @@ -2450,7 +2453,7 @@ pub(crate) fn clean_variant_def_with_args<'tcx>( fn clean_variant_data<'tcx>( variant: &hir::VariantData<'tcx>, - disr_expr: &Option<hir::AnonConst>, + disr_expr: &Option<&hir::AnonConst>, cx: &mut DocContext<'tcx>, ) -> Variant { let discriminant = disr_expr diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 64f0e096cd0..5c5651f3ef0 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -35,13 +35,13 @@ use rustc_resolve::rustdoc::may_be_doc_link; use rustc_span::edition::Edition; use rustc_span::{Span, Symbol}; -use once_cell::sync::Lazy; use std::borrow::Cow; use std::collections::VecDeque; use std::fmt::Write; use std::iter::Peekable; use std::ops::{ControlFlow, Range}; use std::str::{self, CharIndices}; +use std::sync::OnceLock; use crate::clean::RenderedLink; use crate::doctest; @@ -1994,7 +1994,7 @@ pub struct IdMap { } // The map is pre-initialized and cloned each time to avoid reinitializing it repeatedly. -static DEFAULT_ID_MAP: Lazy<FxHashMap<Cow<'static, str>, usize>> = Lazy::new(|| init_id_map()); +static DEFAULT_ID_MAP: OnceLock<FxHashMap<Cow<'static, str>, usize>> = OnceLock::new(); fn init_id_map() -> FxHashMap<Cow<'static, str>, usize> { let mut map = FxHashMap::default(); @@ -2051,7 +2051,7 @@ fn init_id_map() -> FxHashMap<Cow<'static, str>, usize> { impl IdMap { pub fn new() -> Self { - IdMap { map: DEFAULT_ID_MAP.clone() } + IdMap { map: DEFAULT_ID_MAP.get_or_init(init_id_map).clone() } } pub(crate) fn derive<S: AsRef<str> + ToString>(&mut self, candidate: S) -> String { diff --git a/src/librustdoc/html/render/search_index/encode.rs b/src/librustdoc/html/render/search_index/encode.rs index 54407c614c4..8d715814faa 100644 --- a/src/librustdoc/html/render/search_index/encode.rs +++ b/src/librustdoc/html/render/search_index/encode.rs @@ -166,13 +166,12 @@ pub(crate) fn write_bitmap_to_bytes( containers.push(container); } // https://github.com/RoaringBitmap/RoaringFormatSpec - use byteorder::{WriteBytesExt, LE}; const SERIAL_COOKIE_NO_RUNCONTAINER: u32 = 12346; const SERIAL_COOKIE: u32 = 12347; const NO_OFFSET_THRESHOLD: u32 = 4; let size: u32 = containers.len().try_into().unwrap(); let start_offset = if has_run { - out.write_u32::<LE>(SERIAL_COOKIE | ((size - 1) << 16))?; + out.write_all(&u32::to_le_bytes(SERIAL_COOKIE | ((size - 1) << 16)))?; for set in containers.chunks(8) { let mut b = 0; for (i, container) in set.iter().enumerate() { @@ -180,7 +179,7 @@ pub(crate) fn write_bitmap_to_bytes( b |= 1 << i; } } - out.write_u8(b)?; + out.write_all(&[b])?; } if size < NO_OFFSET_THRESHOLD { 4 + 4 * size + ((size + 7) / 8) @@ -188,21 +187,21 @@ pub(crate) fn write_bitmap_to_bytes( 4 + 8 * size + ((size + 7) / 8) } } else { - out.write_u32::<LE>(SERIAL_COOKIE_NO_RUNCONTAINER)?; - out.write_u32::<LE>(containers.len().try_into().unwrap())?; + out.write_all(&u32::to_le_bytes(SERIAL_COOKIE_NO_RUNCONTAINER))?; + out.write_all(&u32::to_le_bytes(containers.len().try_into().unwrap()))?; 4 + 4 + 4 * size + 4 * size }; for (&key, container) in keys.iter().zip(&containers) { // descriptive header let key: u32 = key.into(); let count: u32 = container.popcount() - 1; - out.write_u32::<LE>((count << 16) | key)?; + out.write_all(&u32::to_le_bytes((count << 16) | key))?; } if !has_run || size >= NO_OFFSET_THRESHOLD { // offset header let mut starting_offset = start_offset; for container in &containers { - out.write_u32::<LE>(starting_offset)?; + out.write_all(&u32::to_le_bytes(starting_offset))?; starting_offset += match container { Container::Bits(_) => 8192u32, Container::Array(array) => u32::try_from(array.len()).unwrap() * 2, @@ -214,19 +213,19 @@ pub(crate) fn write_bitmap_to_bytes( match container { Container::Bits(bits) => { for chunk in bits.iter() { - out.write_u64::<LE>(*chunk)?; + out.write_all(&u64::to_le_bytes(*chunk))?; } } Container::Array(array) => { for value in array.iter() { - out.write_u16::<LE>(*value)?; + out.write_all(&u16::to_le_bytes(*value))?; } } Container::Run(runs) => { - out.write_u16::<LE>((runs.len()).try_into().unwrap())?; + out.write_all(&u16::to_le_bytes(runs.len().try_into().unwrap()))?; for (start, lenm1) in runs.iter().copied() { - out.write_u16::<LE>(start)?; - out.write_u16::<LE>(lenm1)?; + out.write_all(&u16::to_le_bytes(start))?; + out.write_all(&u16::to_le_bytes(lenm1))?; } } } diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 74c9130fd77..80a4ea0424a 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1133,6 +1133,7 @@ so that we can apply CSS-filters to change the arrow color in themes */ .setting-check input:checked { background-color: var(--settings-input-color); border-width: 1px; + /* cross-mark image in the settings checkboxes */ content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40">\ <path d="M7,25L17,32L33,12" fill="none" stroke="black" stroke-width="5"/>\ <path d="M7,23L17,30L33,10" fill="none" stroke="white" stroke-width="5"/></svg>'); @@ -1608,12 +1609,26 @@ a.tooltip:hover::after { font-size: 0; } #settings-menu > a:before { - content: url('wheel-63255fc4502dca9a.svg'); + /* Wheel <https://www.svgrepo.com/svg/384069/settings-cog-gear> */ + content: url('data:image/svg+xml,<svg width="22" height="22" viewBox="0 0 12 12" \ + enable-background="new 0 0 12 12" xmlns="http://www.w3.org/2000/svg">\ + <path d="M10.25,6c0-0.1243286-0.0261841-0.241333-0.0366211-0.362915l1.6077881-1.5545654l\ + -1.25-2.1650391 c0,0-1.2674561,0.3625488-2.1323853,0.6099854c-0.2034912-0.1431885-0.421875\ + -0.2639771-0.6494751-0.3701782L7.25,0h-2.5 c0,0-0.3214111,1.2857666-0.5393066,2.1572876\ + C3.9830933,2.2634888,3.7647095,2.3842773,3.5612183,2.5274658L1.428833,1.9174805 \ + l-1.25,2.1650391c0,0,0.9641113,0.9321899,1.6077881,1.5545654C1.7761841,5.758667,\ + 1.75,5.8756714,1.75,6 s0.0261841,0.241333,0.0366211,0.362915L0.178833,7.9174805l1.25,\ + 2.1650391l2.1323853-0.6099854 c0.2034912,0.1432495,0.421875,0.2639771,0.6494751,0.3701782\ + L4.75,12h2.5l0.5393066-2.1572876 c0.2276001-0.1062012,0.4459839-0.2269287,0.6494751\ + -0.3701782l2.1323853,0.6099854l1.25-2.1650391L10.2133789,6.362915 C10.2238159,6.241333,\ + 10.25,6.1243286,10.25,6z M6,7.5C5.1715698,7.5,4.5,6.8284302,4.5,6S5.1715698,4.5,6,4.5S7.5\ + ,5.1715698,7.5,6 S6.8284302,7.5,6,7.5z" fill="black"/></svg>'); width: 22px; height: 22px; } #sidebar-button > a:before { + /* sidebar resizer image */ content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22" \ fill="none" stroke="black">\ <rect x="1" y="1" width="20" height="20" ry="1.5" stroke-width="1.5"/>\ @@ -1636,7 +1651,17 @@ a.tooltip:hover::after { } #copy-path::before { filter: var(--copy-path-img-filter); - content: url('clipboard-24048e6d87f63d07.svg'); + /* clipboard <https://github.com/rust-lang/crates.io/commits/main/public/assets/copy.svg> */ + content: url('data:image/svg+xml,<svg width="19" height="18" viewBox="0 0 24 25" \ +xmlns="http://www.w3.org/2000/svg" aria-label="Copy to clipboard">\ +<path d="M18 20h2v3c0 1-1 2-2 2H2c-.998 0-2-1-2-2V5c0-.911.755-1.667 1.667-1.667h5A3.323 3.323 0 \ +0110 0a3.323 3.323 0 013.333 3.333h5C19.245 3.333 20 4.09 20 5v8.333h-2V9H2v14h16v-3zM3 \ +7h14c0-.911-.793-1.667-1.75-1.667H13.5c-.957 0-1.75-.755-1.75-1.666C11.75 2.755 10.957 2 10 \ +2s-1.75.755-1.75 1.667c0 .911-.793 1.666-1.75 1.666H4.75C3.793 5.333 3 6.09 3 7z"/>\ +<path d="M4 19h6v2H4zM12 11H4v2h8zM4 17h4v-2H4zM15 15v-3l-4.5 4.5L15 21v-3l8.027-.032L23 15z"/>\ +</svg>'); + width: 19px; + height: 18px; } #copy-path:hover::before { filter: var(--copy-path-img-hover-filter); @@ -1837,6 +1862,7 @@ However, it's not needed with smaller screen width because the doc/code block is /* sidebar button opens modal use hamburger button */ .src #sidebar-button > a:before, .sidebar-menu-toggle:before { + /* hamburger button image */ content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" \ viewBox="0 0 22 22" fill="none" stroke="black">\ <path d="M3,5h16M3,11h16M3,17h16" stroke-width="2.75"/></svg>'); @@ -1850,6 +1876,7 @@ However, it's not needed with smaller screen width because the doc/code block is /* src sidebar button opens a folder view */ .src #sidebar-button > a:before { + /* folder image */ content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" \ viewBox="0 0 22 22" fill="none" stroke="black">\ <path d="M16,9v-4h-6v-1l-2,-2h-4l-2,2v16h13L21,9h-15L2,19" stroke-width="1.25"/>\ diff --git a/src/librustdoc/html/static/images/clipboard.svg b/src/librustdoc/html/static/images/clipboard.svg deleted file mode 100644 index e437c83fb6b..00000000000 --- a/src/librustdoc/html/static/images/clipboard.svg +++ /dev/null @@ -1 +0,0 @@ -<svg width="19" height="18" viewBox="0 0 24 25" xmlns="http://www.w3.org/2000/svg" aria-label="Copy to clipboard"><path d="M18 20h2v3c0 1-1 2-2 2H2c-.998 0-2-1-2-2V5c0-.911.755-1.667 1.667-1.667h5A3.323 3.323 0 0110 0a3.323 3.323 0 013.333 3.333h5C19.245 3.333 20 4.09 20 5v8.333h-2V9H2v14h16v-3zM3 7h14c0-.911-.793-1.667-1.75-1.667H13.5c-.957 0-1.75-.755-1.75-1.666C11.75 2.755 10.957 2 10 2s-1.75.755-1.75 1.667c0 .911-.793 1.666-1.75 1.666H4.75C3.793 5.333 3 6.09 3 7z"/><path d="M4 19h6v2H4zM12 11H4v2h8zM4 17h4v-2H4zM15 15v-3l-4.5 4.5L15 21v-3l8.027-.032L23 15z"/></svg> diff --git a/src/librustdoc/html/static/images/wheel.svg b/src/librustdoc/html/static/images/wheel.svg deleted file mode 100644 index ba30f13dd58..00000000000 --- a/src/librustdoc/html/static/images/wheel.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" enable-background="new 0 0 22 22" viewBox="0 0 27.434 29.5"><path d="M27.316 18.39a2.696 2.696 0 0 0-.98-1.46 1.62 1.62 0 0 1-.016-.762l.035-.176v-1.191c0-1.246-.003-1.278-.046-1.473a1.717 1.717 0 0 1 .007-.805c.477-.343.829-.859.997-1.472.257-.957.074-2.094-.508-3.117l-.594-1.032c-.746-1.304-1.965-2.117-3.18-2.117-.379 0-.75.078-1.086.235a1.958 1.958 0 0 1-.855-.391l-.102-.082-.117-.063-1.855-1.07-.094-.055-.106-.043c-.378-.156-.66-.41-.77-.554C17.919 1.172 16.349 0 14.297 0h-1.155c-2.043 0-3.61 1.152-3.75 2.723-.114.14-.391.382-.758.527l-.102.04-.094.05-1.94 1.066-.134.074-.117.094a2.019 2.019 0 0 1-.832.403 2.518 2.518 0 0 0-1.008-.211c-1.199 0-2.414.82-3.168 2.14l-.59 1.032c-.41.718-.64 1.523-.64 2.257-.004.953.36 1.758 1.012 2.258.035.152.058.445-.016.785-.04.168-.063.282-.063 1.563 0 1.148 0 1.148.016 1.261l.008.075.015.074c.075.344.047.64.012.8-.644.5-1.004 1.302-.992 2.259.008.726.238 1.52.648 2.242l.59 1.027c.758 1.332 1.965 2.16 3.149 2.16.324 0 .644-.062.937-.187.168.039.492.156.813.418l.11.086.124.07 2.047 1.156.102.059.105.043c.363.144.648.379.766.52.164 1.519 1.718 2.632 3.746 2.632h1.156c2.035 0 3.598-1.133 3.746-2.672.117-.144.402-.394.773-.55l.114-.047.101-.063 1.961-1.156.106-.063.097-.078c.309-.246.653-.37.832-.398.313.136.66.21 1.016.21 1.2 0 2.41-.82 3.164-2.14l.594-1.031c.59-1.028.777-2.164.52-3.117Zm-2.043 2.247-.59 1.031c-.437.766-1.105 1.25-1.636 1.25a.7.7 0 0 1-.371-.094 1.146 1.146 0 0 0-.567-.129c-.593 0-1.382.297-2.007.797l-1.961 1.156c-1.016.426-1.848 1.293-1.848 1.93 0 .64-.898 1.16-1.996 1.16H13.14c-1.102 0-2-.515-2-1.14 0-.63-.832-1.477-1.852-1.887l-2.047-1.16c-.637-.512-1.426-.813-2.008-.813-.199 0-.379.035-.515.114a.648.648 0 0 1-.332.085c-.52 0-1.18-.5-1.621-1.273l-.59-1.031c-.543-.953-.555-1.98-.024-2.285.532-.305.782-1.434.551-2.504V14.8c0-1.09.02-1.18.02-1.18.238-1.074-.008-2.203-.551-2.516-.54-.304-.54-1.34.008-2.293l.59-1.03c.437-.766 1.101-1.255 1.636-1.255a.73.73 0 0 1 .364.094c.152.086.343.125.566.125.594 0 1.379-.297 2.004-.793l1.945-1.066c1.02-.407 1.856-1.278 1.856-1.934 0-.656.898-1.191 2-1.191h1.156c1.098 0 1.996.543 1.996 1.21 0 .669.832 1.555 1.848 1.973L20 6.012c.617.492 1.402.777 2.012.777.242 0 .453-.047.62-.14a.79.79 0 0 1 .403-.102c.55 0 1.223.476 1.652 1.23l.59 1.032c.543.953.52 2.004-.062 2.336-.574.332-.86 1.48-.625 2.554 0 0 .008.04.008 1.102v1.011c-.215 1.051.07 2.176.636 2.5.567.325.586 1.368.04 2.325Zm0 0"/><path d="M13.61 7.61a7.084 7.084 0 0 0-7.083 7.085 7.085 7.085 0 1 0 14.168 0A7.088 7.088 0 0 0 13.61 7.61Zm0 12.41a5.33 5.33 0 0 1-5.325-5.325 5.33 5.33 0 0 1 5.324-5.32 5.327 5.327 0 0 1 5.325 5.32 5.328 5.328 0 0 1-5.325 5.325Zm0 0"/><path d="M13.684 9.906a4.722 4.722 0 0 0-4.72 4.719 4.722 4.722 0 0 0 4.72 4.719 4.724 4.724 0 0 0 4.714-4.719 4.724 4.724 0 0 0-4.714-4.719Zm0 7.676a2.954 2.954 0 1 1 0-5.91 2.953 2.953 0 0 1 2.953 2.953 2.957 2.957 0 0 1-2.953 2.957Zm0 0"/></svg> \ No newline at end of file diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs index d8874c2fda0..035376bace9 100644 --- a/src/librustdoc/html/static_files.rs +++ b/src/librustdoc/html/static_files.rs @@ -99,8 +99,6 @@ static_files! { src_script_js => "static/js/src-script.js", storage_js => "static/js/storage.js", scrape_examples_js => "static/js/scrape-examples.js", - wheel_svg => "static/images/wheel.svg", - clipboard_svg => "static/images/clipboard.svg", copyright => "static/COPYRIGHT.txt", license_apache => "static/LICENSE-APACHE.txt", license_mit => "static/LICENSE-MIT.txt", diff --git a/src/stage0.json b/src/stage0.json index a85fbf254fc..a9a53a7528f 100644 --- a/src/stage0.json +++ b/src/stage0.json @@ -18,431 +18,439 @@ "tool is executed." ], "compiler": { - "date": "2024-03-19", + "date": "2024-04-29", "version": "beta" }, "rustfmt": { - "date": "2024-03-19", + "date": "2024-04-29", "version": "nightly" }, "checksums_sha256": { - "dist/2024-03-19/cargo-beta-aarch64-apple-darwin.tar.gz": "d8aeeb8d427c346112020b84de85c1498d1ea043a01a45dd63d38da8ae0d35d1", - "dist/2024-03-19/cargo-beta-aarch64-apple-darwin.tar.xz": "f4c3aec8e916a93412c6c798c43dab1dd64c0095509a2a255191751a230730ad", - "dist/2024-03-19/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "d6161a55f808b6d54a061f9ffd9c33489b844f450f07a40e2f6cdb7def75792b", - "dist/2024-03-19/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "cba6e510866f9d920ee40e66069e8d152c0bfdabcc280ba0175a103460614839", - "dist/2024-03-19/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "e99299705d9b596554a4156ca7e8cd1bab95d926b519fd79e24d7b4c00bf4bbe", - "dist/2024-03-19/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "d006ecc2215a0b7b1d3040c64d72094589bfe11f1ffd34f63e5aaa8fb52ee4b2", - "dist/2024-03-19/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "9f6b9bd599948b48085bf592630963a5b69608abff67dd3674327d7efdcbf695", - "dist/2024-03-19/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "e3bd8ad798b098f1e03333bece43fe163f4d4b613bf38de4809106ca98b99c05", - "dist/2024-03-19/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "5ec13385ad03d14fa8fd48fd3f92df123a1626bb8a594df33c0bdee02d5a811c", - "dist/2024-03-19/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "bf201ad295272ee9435da1afcd4888c31bb14e467edb9638fdfe95b071bc869d", - "dist/2024-03-19/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "0e09177180c2822378bdb66dca69fb8bc7e7d5c51f414bdd95b9497c683d466f", - "dist/2024-03-19/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "5815c1421d474d8cd238fff80db5ba5231155abbd8642eeced84842d34f49ba9", - "dist/2024-03-19/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "36967ecac443fdcace710bae63eedcf65a4c2015793ed30ea3edae3d93f24707", - "dist/2024-03-19/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "1932898203f99c2aee95e71226c66b48d8dcbe40aa3a8b0782856fedcd291b13", - "dist/2024-03-19/cargo-beta-i686-pc-windows-gnu.tar.gz": "948157661b4b54b4c963933d97d4721efb6c8134242b96a82b86ee4be8dfe043", - "dist/2024-03-19/cargo-beta-i686-pc-windows-gnu.tar.xz": "26afbb06b1a47945172cee64470803670d1e41529f4e0f357f48633565efc489", - "dist/2024-03-19/cargo-beta-i686-pc-windows-msvc.tar.gz": "82e81f26ba6a207ac891a13bd9eb58c2cc33d31e78d354a210c4518b2d2b4dfd", - "dist/2024-03-19/cargo-beta-i686-pc-windows-msvc.tar.xz": "2b697674c4535bb58910dea6fdb9948a3b06ecdb723a638c01558615cbbf3fb0", - "dist/2024-03-19/cargo-beta-i686-unknown-linux-gnu.tar.gz": "2273118fc50fe605d53b078b5859d2694555f6c9ce2a61478f5af1765cffb997", - "dist/2024-03-19/cargo-beta-i686-unknown-linux-gnu.tar.xz": "53ae185d70ead1a251aac0793cbc784858d7a666530cacb63404541bef2a8bbd", - "dist/2024-03-19/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz": "f37429c8406938888600b180b60db99a5343866e8ba6c595350c60a631d6cc2e", - "dist/2024-03-19/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz": "ca49cac7f00c94ab5ac936c500a96092fc44a2cf9f1e10d52aa877ad9a57c548", - "dist/2024-03-19/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "262a48b6cfe9ebc8e19847e5ffa22459398395a9f9c9bb0891bf7b247b9d800a", - "dist/2024-03-19/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "6300c528f7457e0349eb2ff25e24122e5448855a4f05f265b810b328d4310516", - "dist/2024-03-19/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "e0dd3b037664c468eee9340235454b0a01310eae6025d5e2fb142027ff079cd5", - "dist/2024-03-19/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "36de5c67fdbc1eacdf00a51e2b44df5c1ee50ecd83755e893b6cb41bf49f30b5", - "dist/2024-03-19/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "cb5cdabb2d9d0398895b491f3cd128bd16488464fb3b8bc24f8e2e115154bbbf", - "dist/2024-03-19/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "e597718951b6f2973a68d587b84b6d4ce51e180e74b1060fdcbc3cfd05e04291", - "dist/2024-03-19/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "0a860fccb3f7ca44ca94ed76b1b81a2033e9c6806b32b428b49794508529e5be", - "dist/2024-03-19/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "10eaa329dc9a40337df22edd21a7396fd87852afcd0e68f1334cb374a56aa5bf", - "dist/2024-03-19/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "2f511c9d6ba6b489d96f531778af89baa3cce98ddc2e015198a0fbda95c0077a", - "dist/2024-03-19/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "d510515fa11961e56c05a946fb7200ce42b3831280177fda78260915f9b0192f", - "dist/2024-03-19/cargo-beta-x86_64-apple-darwin.tar.gz": "e4d542ce10c993bbdd1103d605c5c15771629750f204c5de76af93b0f0278391", - "dist/2024-03-19/cargo-beta-x86_64-apple-darwin.tar.xz": "36ff8a7806bd8bcb2c0054f994ec32bc5b30907c3ea2dd3cd07a440b6ee031c3", - "dist/2024-03-19/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "d3daaa2be8f7b761c37cfca9a1a242e2b0231795e1cb868246ed1e379c3969d8", - "dist/2024-03-19/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "1cda9d7c448336878071e6eb27338bd0346ec5ea28a8d29a6dcb3caa9b96fc54", - "dist/2024-03-19/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "cd1539eca02777df1ff8bf70d4f4abe59ea3a2d1cc625fb714b941502f863198", - "dist/2024-03-19/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "e97a05c1ba1a4aec2d424845b0b874712f15568c2e9cd61222663b96b759bb3f", - "dist/2024-03-19/cargo-beta-x86_64-unknown-freebsd.tar.gz": "aa2de3a607bc0fd4b4f99b2a6c8c024a75823d7ebea553748d24ad2841f3c919", - "dist/2024-03-19/cargo-beta-x86_64-unknown-freebsd.tar.xz": "6546733a7b4a34b5739b9a1d1cfac8eb7ae320a14a242e8298564e33b2b4208e", - "dist/2024-03-19/cargo-beta-x86_64-unknown-illumos.tar.gz": "e48ad6cfa052ee84226e79cd037b4ff02d6974139225a69edac26db10f894c12", - "dist/2024-03-19/cargo-beta-x86_64-unknown-illumos.tar.xz": "2a55ac5d8aecb87d7625a90a5f1560859f516a44825b189b7d0cbbe0de787bd6", - "dist/2024-03-19/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "19db36d6b51c3e16869fc4be4133e321b103211fa8fd7a072dfb8dfa5dd108b6", - "dist/2024-03-19/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "97a90f062125ed14fc9723ecf3e68e12fc5853efb83e0afeef97dadd1b0e032f", - "dist/2024-03-19/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "231529bb7dbefbdba9b741a03ed210963966e217b684b05bfe8ff61af46577c9", - "dist/2024-03-19/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "b5e82d094176f729dc500d67ef5f4102df558718020f43536155ac4a74d6a01b", - "dist/2024-03-19/cargo-beta-x86_64-unknown-netbsd.tar.gz": "c6b836aa6f7cd086a7316fbcaf9e3de080d310db60eacc0910a3b90bbf5c224e", - "dist/2024-03-19/cargo-beta-x86_64-unknown-netbsd.tar.xz": "dcb398fb25568a0e5374be22be14f8dc1c0a7221fc5e60dc9258d4767f774058", - "dist/2024-03-19/clippy-beta-aarch64-apple-darwin.tar.gz": "7f4cf1177f0f22f471b8bf219d13b59b626089b3c2a563b3559dc66a573c8375", - "dist/2024-03-19/clippy-beta-aarch64-apple-darwin.tar.xz": "78d5efca461180bfdcde7e4672ac06221a0809386624b4f6892e0037df8be572", - "dist/2024-03-19/clippy-beta-aarch64-pc-windows-msvc.tar.gz": "8d3443465b4f0cbd6ba7e5bd8614071ce826798f80d7c6e35cc71ef463675952", - "dist/2024-03-19/clippy-beta-aarch64-pc-windows-msvc.tar.xz": "4ea23f92b8f36a271c36df93008a00e0a0519dfdc0da69cc920f7edf317b4ae9", - "dist/2024-03-19/clippy-beta-aarch64-unknown-linux-gnu.tar.gz": "1eabd5f5bce761972022f52dc86cd408f7106a7df2a0d9b1701afc1bcb39ed39", - "dist/2024-03-19/clippy-beta-aarch64-unknown-linux-gnu.tar.xz": "05feb29e8c526ed85e331f091b046767c4a01d68129c6a873536703dee529323", - "dist/2024-03-19/clippy-beta-aarch64-unknown-linux-musl.tar.gz": "c023d628e7d23ad3d94791e595b0ce4033c24b5e53f806947b88a6cddd93e1b8", - "dist/2024-03-19/clippy-beta-aarch64-unknown-linux-musl.tar.xz": "96b29dba180d5bf4caa40b5c8538248b0b820991d91eab819b2ce0fe093640b9", - "dist/2024-03-19/clippy-beta-arm-unknown-linux-gnueabi.tar.gz": "5d9a8237c5d2258e7ff18cee7cad2308e6ce3935251c8fb74932ed84b1e23a52", - "dist/2024-03-19/clippy-beta-arm-unknown-linux-gnueabi.tar.xz": "625f0415d85c08281efb4cdd6d362636876360774297487ed92337e72058c896", - "dist/2024-03-19/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz": "5d9e03efe64eb1a60dfa011b1641a74979295cf6540e081672deed82fd130132", - "dist/2024-03-19/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz": "e9bed26481e7678e7e4388c0e6885ab323b9cecc270a3044b08cb681eed5333d", - "dist/2024-03-19/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz": "26e0a630657c7abe765132bfab93aa39013ff19aec1978e41968cb53e6c46693", - "dist/2024-03-19/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz": "30abee9b263f4ff6f7e696a41f5356957daae5953c224fcd1f253ce41dcd94ea", - "dist/2024-03-19/clippy-beta-i686-pc-windows-gnu.tar.gz": "845732a863b79922ed5057ddf7c911bae71381082bdcf68799c8f79c0f48d192", - "dist/2024-03-19/clippy-beta-i686-pc-windows-gnu.tar.xz": "75f1abca075af64656d176ac1ea37e24c000378f1750a708924b44fdc223c389", - "dist/2024-03-19/clippy-beta-i686-pc-windows-msvc.tar.gz": "e5a7d0ff6d1f8d9bfeaab8f8aaf1c18528c1eb447169454c965838a2b836c201", - "dist/2024-03-19/clippy-beta-i686-pc-windows-msvc.tar.xz": "ad5a7313ca6fbd8051c0db761bbae67d3405cc5a98ec20891f26c15b31b5b2b0", - "dist/2024-03-19/clippy-beta-i686-unknown-linux-gnu.tar.gz": "cf67172fcc26b9b45138f0ac12721c1fe226a892346145b4a0ff1931d60fb756", - "dist/2024-03-19/clippy-beta-i686-unknown-linux-gnu.tar.xz": "3adb4d8a782a80d85f4cdfc433f63656449a06dddc67f0b11bf399d9a8aae97a", - "dist/2024-03-19/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz": "175d58f41d0b08bc1ac733bee1d16db31a4a64f7703a87ea1f13ec72b19be4d7", - "dist/2024-03-19/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz": "73925325e092d84ba3a8aff695953142962221fecaab9d57dc61b4d03338bb12", - "dist/2024-03-19/clippy-beta-powerpc-unknown-linux-gnu.tar.gz": "cec90ecbdfd252e49de68fa69806f5662bd4f4ab093708104e19b228564c0ee4", - "dist/2024-03-19/clippy-beta-powerpc-unknown-linux-gnu.tar.xz": "eb085114c178c8e16ec77657fb658b537eff1125f3de5d7e07f1ccd62e8b834e", - "dist/2024-03-19/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz": "b599d42a4100a7b1304eee34571abe1e6e38e873f8197e46d0d4d92dbb0ccd27", - "dist/2024-03-19/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz": "57338b860b283cfed3cf1eb38083113f026cfc91135e439b75de1a3acc9e42b3", - "dist/2024-03-19/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz": "00f756d858949ad83ad32dca5c5a93cd283da3c91f4976564afd5be3b4f5927b", - "dist/2024-03-19/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz": "4a8d250c30312dfd4f8d259ca4376555bbc6cf290a884aff92e6b06a852acf6d", - "dist/2024-03-19/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz": "992a77181709bf235c1e0a335a82b0ee01fe8f749956f2aad52a386685aeae6b", - "dist/2024-03-19/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz": "b523cf81d4ffbcc0bb9f4f5805eeb39624901eea591c852f9594690350848c54", - "dist/2024-03-19/clippy-beta-s390x-unknown-linux-gnu.tar.gz": "5f22463a8c138fb3934a405bc0f7de4b5ea51c86b75f7739eccd7181fbeb4e9a", - "dist/2024-03-19/clippy-beta-s390x-unknown-linux-gnu.tar.xz": "2b507322b80e562a0dfaba16210a2f1d65051a740869ce5a952bf83a9099e0f2", - "dist/2024-03-19/clippy-beta-x86_64-apple-darwin.tar.gz": "6873e1a437b6783e349d4fe1cd69f996f579b623c231d55933ec194de19d0a15", - "dist/2024-03-19/clippy-beta-x86_64-apple-darwin.tar.xz": "4b8f43b267b25bc5f60541fe6b98254c2731f0ee55129cc132e28c4f3b2bbc24", - "dist/2024-03-19/clippy-beta-x86_64-pc-windows-gnu.tar.gz": "e697e4c34422519db58b44bf8ed164fc45dadf4ac114c3e662f6990d4d9a5522", - "dist/2024-03-19/clippy-beta-x86_64-pc-windows-gnu.tar.xz": "5ffd1038684dc68bf97f9a74c08beca4c3eb66b39b11e32e7da45b763fe1f7f2", - "dist/2024-03-19/clippy-beta-x86_64-pc-windows-msvc.tar.gz": "7e334464dbbe5be014de9ef6872a1b2066016204e7ae8c11e55fbf64bedb93da", - "dist/2024-03-19/clippy-beta-x86_64-pc-windows-msvc.tar.xz": "55b4aaa0a64d9e3cc2489a678935277d91b1f8223186c52b59bd33dbd403d52a", - "dist/2024-03-19/clippy-beta-x86_64-unknown-freebsd.tar.gz": "6fa2e2bdd09242ab44ad35853cf9493ad57d602536406ecd3504db5af87b827a", - "dist/2024-03-19/clippy-beta-x86_64-unknown-freebsd.tar.xz": "b1b79f8130d61c92d3d101a4d24416ef37fd446f18de0745be2c1fed7b276b57", - "dist/2024-03-19/clippy-beta-x86_64-unknown-illumos.tar.gz": "ee1af20cc23288fecf8ebe33e877e1de3184711a38ea378a6f4da158919b4059", - "dist/2024-03-19/clippy-beta-x86_64-unknown-illumos.tar.xz": "af724f142b19b7436547a5eb2b2b40d1acf959a73feca03efd9178948af9326a", - "dist/2024-03-19/clippy-beta-x86_64-unknown-linux-gnu.tar.gz": "376cf1787e41ba9d231191f6cae260895be18c3ececc2f2e934e850de7f1cbda", - "dist/2024-03-19/clippy-beta-x86_64-unknown-linux-gnu.tar.xz": "8d7af83d3594a151564f351eed4cdfd1c7eb5b07e073e12c6d7b7ef9ad597007", - "dist/2024-03-19/clippy-beta-x86_64-unknown-linux-musl.tar.gz": "218168e4817f70f65651f3b9561ba8e8dd3e0d8c8a33a88ba9ad0a4a501468bd", - "dist/2024-03-19/clippy-beta-x86_64-unknown-linux-musl.tar.xz": "f55143ece3326ac8c004b77e59c1a60a70b3f1189c7e2e442183097f1cf639c2", - "dist/2024-03-19/clippy-beta-x86_64-unknown-netbsd.tar.gz": "9a5c08d2e00d2f38de5a9882fe7dcadd6307a333b8caf5826687301f8d97d09a", - "dist/2024-03-19/clippy-beta-x86_64-unknown-netbsd.tar.xz": "7be02599b4c2cd26365075ebfbb1534f6875d85501fe5a300895506e41ad0824", - "dist/2024-03-19/rust-std-beta-aarch64-apple-darwin.tar.gz": "7238015aa0e8553b6e820483e15f08119fa0b6c074abe127be99fa990f132c8f", - "dist/2024-03-19/rust-std-beta-aarch64-apple-darwin.tar.xz": "0dc783f3865ddf6512721abcd9c668f6d8533c3581015cfd4740b40cb09ce199", - "dist/2024-03-19/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "90541bf8f4c1fb838fff2620b55addee59687b16d3f10f92b59a41936ffa143d", - "dist/2024-03-19/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "b0d14d73d404197994e41deb2d92049ec043c875a81dda52c4e4fc64e53c8065", - "dist/2024-03-19/rust-std-beta-aarch64-apple-ios.tar.gz": "3105f19fd78bcdc5171cf4041aca9da236150e43ef9c32ee1163aafbc79d311f", - "dist/2024-03-19/rust-std-beta-aarch64-apple-ios.tar.xz": "13629cec9404312c6b42fd7aac14edc5eee98947be5152ae5708db899d2ebb4e", - "dist/2024-03-19/rust-std-beta-aarch64-linux-android.tar.gz": "3fb671809fafdabcb4cd8ea6c00caf3cfa2da3421770c08abf761456f079c425", - "dist/2024-03-19/rust-std-beta-aarch64-linux-android.tar.xz": "8f8f22bd89a29db1a549414440da19f3100abb689fb095c3e09ef28a223ee3cd", - "dist/2024-03-19/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "2326cc5061a6acc3cfea5a0e2ea965e07a0103052cfb4435e5dc947573b62e11", - "dist/2024-03-19/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "87327aa9f683ef9f574348cc0ec58b0f88fdcd6563d51b69664b3588897783ca", - "dist/2024-03-19/rust-std-beta-aarch64-unknown-fuchsia.tar.gz": "5f589736703a21a17366dd93c36ee6f597a40999ce6c305ff1e007918fe6aaef", - "dist/2024-03-19/rust-std-beta-aarch64-unknown-fuchsia.tar.xz": "65386ce4aa697b74c463e1c8d793ded996f6dbf1327242aaf61471968212c1e7", - "dist/2024-03-19/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "590b12f5fdf32251c1e0ad2af619b70b73a888d3a33a705f023b81369bcbbfa8", - "dist/2024-03-19/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "c22e0e88e1fd0041c95317bbc0e39e7d4e4e6a8d73eedc141628ec9e41d844f5", - "dist/2024-03-19/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "7e8e04e2bd58ac03c5dcf017562d3ad92993896a5f5a31e199990685adb206b7", - "dist/2024-03-19/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "8d0c5b70230122904e36731290f62dcf24fca2390d4c892aeb9b8f241d380563", - "dist/2024-03-19/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz": "89d476e9654dce23fb77cef86831813d143435e4e1a9547936f5eabb9a7e649b", - "dist/2024-03-19/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz": "b1b5c25e682961301e60f115eba6177a1be97b3157a0671c0ec64563765ddfdd", - "dist/2024-03-19/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "e8b2b4cd75800e5cd5b8f5ad97d6ef9fef8e6a7852a227406e89a3f7f50d33d2", - "dist/2024-03-19/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "e5c603df1515777eb1af5c9532194fde8ea3554abfefb93499025a9a98fdc182", - "dist/2024-03-19/rust-std-beta-aarch64-unknown-none.tar.gz": "55605666a2bde23365937c811899f9e61855a28668d4b050834b83f5af8b03b5", - "dist/2024-03-19/rust-std-beta-aarch64-unknown-none.tar.xz": "f68fa43e4ee4d86b7bba6c316efba5ef6e3d500b0659ba4a0295df814beca459", - "dist/2024-03-19/rust-std-beta-aarch64-unknown-uefi.tar.gz": "5b9dbe42c686670836ba26acab3afa218fa70b616d3a7951298ce5cf2eff88bd", - "dist/2024-03-19/rust-std-beta-aarch64-unknown-uefi.tar.xz": "fcc8316db3cef3a3c3240a490d18162cf724fceecb595a0c40067c6a20a53caf", - "dist/2024-03-19/rust-std-beta-arm-linux-androideabi.tar.gz": "abdd4c98992cf2f9a9a558c5c74283826de3bb48d7743e67ef1f9d1dbc40f534", - "dist/2024-03-19/rust-std-beta-arm-linux-androideabi.tar.xz": "c597c457071b82c8842958c6ad383db30741952b06b40f138a5bed3bbca62c70", - "dist/2024-03-19/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "2a11714a2e5d18f7f255feece850a4c8ab7e1b14f6eb116c47eb972825abfdc2", - "dist/2024-03-19/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "5a6f054ebf50bf4bb196a32019276bed1cbcb74cbd3d46877a48ed77c09638c9", - "dist/2024-03-19/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "422d4d3a2f32a1739d18c208e89e5c490ce9b85c771726b21d265cb7632ffd49", - "dist/2024-03-19/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "d9fb3be5b4d577a469f4dc9cce5e4631741d6661a994d15cc1db847ab4edcaed", - "dist/2024-03-19/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "6a9c25b659a7d16f01148144883e47bddb29e2d79f7b590f58efd4b002abe38e", - "dist/2024-03-19/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "2c797105730a6a2a9d8ec5506f2028d42aef48d7ae09fad11e1ef3a0dc3c9a81", - "dist/2024-03-19/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "4f58e423159b7b5a8d546c288572dc644e73cfd5e22eb87f98670e1bdd4cfb42", - "dist/2024-03-19/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "d549997c4be8efe2feee163096b370ca6ddb0884dbf82af0c1d08e5f652a3b26", - "dist/2024-03-19/rust-std-beta-armebv7r-none-eabi.tar.gz": "2e199f5246edf22faf1b8876bec5290a7a111a38cffb831fedef3f4d4e57dded", - "dist/2024-03-19/rust-std-beta-armebv7r-none-eabi.tar.xz": "ffc4118d0520df6d4101c05c4df31bdbe91ce302b37d9d41e3dfdfd8fcb5b49a", - "dist/2024-03-19/rust-std-beta-armebv7r-none-eabihf.tar.gz": "39e2a7464ef3e48104873f59b6198cad8333835a0fe46805b00f2a3a8f1989aa", - "dist/2024-03-19/rust-std-beta-armebv7r-none-eabihf.tar.xz": "ff22a6f9b7c7873fe84943bbcffabba04e2632166ce63e405056ca0ee8fcdb62", - "dist/2024-03-19/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "51128c12bcd8935bed76a555da1e403e1b374155278ed957d078a2c887512a15", - "dist/2024-03-19/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "5370c2da10bc8efe00f0840d8ea6f664d38518288ed402a4ac164ae71cf1dfe9", - "dist/2024-03-19/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "ba104dbdcc3c8689dadb75c6a85d83419e32fe78f43039f5294020da2ab3b73a", - "dist/2024-03-19/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "7bb849dae31f472febd722dc7dd324f073b2739dc57c40a6590b10f61c26133e", - "dist/2024-03-19/rust-std-beta-armv7-linux-androideabi.tar.gz": "c44211a45a1ecb9b5800fb7a3b7fa88de4562845888588012b34e282e26cb4f8", - "dist/2024-03-19/rust-std-beta-armv7-linux-androideabi.tar.xz": "3a92cdd368559d06d290af58fda93eac98e6d4bfd4e6ad03db0f91fe01789504", - "dist/2024-03-19/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "f00db0fd04a921cebe68a21d3c923e44f8a1828cdfffa201826d333feb0b9bd6", - "dist/2024-03-19/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "af5ec7e114c8558080b8891269cca098b530809085577485ea96435d5f664e4b", - "dist/2024-03-19/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "5b2aa8f0c2a005a5c98dd08a6d4d231a11992356f857b706a19cefa66d62dc9a", - "dist/2024-03-19/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "7ab1a7cda6ae70836df20a70283af166ad2d5413755485d818d8760f3bf69f6c", - "dist/2024-03-19/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "9b970f2b3e0a01ecf56a9d32cdfbc47d76a2518838bc231d4488c2f4a9426fa7", - "dist/2024-03-19/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "934272fbb78cd09728ef03557fad7e2b1b9302f88579dee8a5a1f58c8f4b15bd", - "dist/2024-03-19/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "f70a1adf38b2d22b1706af807023154b626f656efb8d91c8ed7235bfe0855edf", - "dist/2024-03-19/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "a665e05bb8dff2e8dd0479cb8a63460c73ee3e86ec7e1b6f48fece2985c85e52", - "dist/2024-03-19/rust-std-beta-armv7-unknown-linux-ohos.tar.gz": "e0ec71714bceee0df1bcdb85e094b58359d41f273dc9abab7ac05346fcd3f4b9", - "dist/2024-03-19/rust-std-beta-armv7-unknown-linux-ohos.tar.xz": "afbcd9b7ecc92f69801d77185af0139136ba6c352d14a6c8ed76de64a87645f5", - "dist/2024-03-19/rust-std-beta-armv7a-none-eabi.tar.gz": "a0e55f17c1bab81bf836c1e373f77d25c42fbd05f04b8b0e96f66f1f744481d2", - "dist/2024-03-19/rust-std-beta-armv7a-none-eabi.tar.xz": "f2dd0221e76d7b9f51e9efdee2e40c8d7539b1d5f52257f89431f29931394510", - "dist/2024-03-19/rust-std-beta-armv7r-none-eabi.tar.gz": "e97324f421bb354bc841a20e8b1c0357e633595bec4fca510f06e56fb89b2a6a", - "dist/2024-03-19/rust-std-beta-armv7r-none-eabi.tar.xz": "1ce1ca60b9536ede90452621ba91539b8ca6b6bdf7cbda3bd6d0b04a28c09580", - "dist/2024-03-19/rust-std-beta-armv7r-none-eabihf.tar.gz": "9bffa04e8cd3f67d8892f851b269f9cd91f6c9e5f2c87c641e9f6ef24bf7b644", - "dist/2024-03-19/rust-std-beta-armv7r-none-eabihf.tar.xz": "2a3cd2ab92cc37698057629167a553d0654f7882bfc1eb46687e1014b4b8e379", - "dist/2024-03-19/rust-std-beta-i586-pc-windows-msvc.tar.gz": "284f13947d990587090beb32262e4a83089c56ce2c3a1ffb89ed0fc5f4661eb3", - "dist/2024-03-19/rust-std-beta-i586-pc-windows-msvc.tar.xz": "22e641bdd54b3a7030c2eda0ff20a5517607fb6e60ea6d3195a2cd3afb0e984a", - "dist/2024-03-19/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "adaaf6d3a291640ddaa3d522d8331cb27ea899999681d57713b57c879b55de96", - "dist/2024-03-19/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "ebe80c2420c0eedd219cd539b87de75ffc0ed3b1656284cb81e2b2e8a927c738", - "dist/2024-03-19/rust-std-beta-i586-unknown-linux-musl.tar.gz": "c2e4691bf6956f97a214ef80f015a77ec4ece4ee32e9bc73300fe1c0267dcabe", - "dist/2024-03-19/rust-std-beta-i586-unknown-linux-musl.tar.xz": "e67059e579532ceb06a46702cc561acbeb3ba6258eda47418da587ec45759e26", - "dist/2024-03-19/rust-std-beta-i686-linux-android.tar.gz": "f112053adbcce7710383afe1681bd0096444a516f78f576e29f2f3c76468e7f0", - "dist/2024-03-19/rust-std-beta-i686-linux-android.tar.xz": "e63ae04fc20519fb5a56c2bae49f767807cb1ae1c01cab34dee1d129b34c4dee", - "dist/2024-03-19/rust-std-beta-i686-pc-windows-gnu.tar.gz": "14b36d2952ebaa84bf24645cd5d3464ae2b9df4d3ffee4bd48fedb07a4fdb09d", - "dist/2024-03-19/rust-std-beta-i686-pc-windows-gnu.tar.xz": "fef8c1bd4e1ceab680e1856b35f4ed426d07c224fa60c92d12efe0dfe700abc9", - "dist/2024-03-19/rust-std-beta-i686-pc-windows-msvc.tar.gz": "b42794fb8feda98c99d36dd978373afbfab56fd374fe42318107c453ab4d0fb7", - "dist/2024-03-19/rust-std-beta-i686-pc-windows-msvc.tar.xz": "855ed5996d9d8e4bc2424ce5ea6da6155b23357d700f1fc07d69d0bd12672a8f", - "dist/2024-03-19/rust-std-beta-i686-unknown-freebsd.tar.gz": "0ac04b35b62c7d8fe42ee29854b6a40b7dcf0d3deb174031a7620d2c87a8b206", - "dist/2024-03-19/rust-std-beta-i686-unknown-freebsd.tar.xz": "0287daaa3042c644d3190c6262b60b580a0cdfd80c64c299a36e0636d38e5674", - "dist/2024-03-19/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "647dd5ba2f4d842d6bd6377e99b67b3d65d3ee47ea800ace9d172e9d24f63eb0", - "dist/2024-03-19/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "d705b0cce3492e863c5d8fb28b4f2bedce68637fd7093d24a9e86ff6d2d0ca56", - "dist/2024-03-19/rust-std-beta-i686-unknown-linux-musl.tar.gz": "561ca95399cbd2f6692e5194ab550e9e0f0f5016aa2802522131c1361d3ef467", - "dist/2024-03-19/rust-std-beta-i686-unknown-linux-musl.tar.xz": "d4751c26585e512211157e162f0d1504a1854249dd6eff7262a55b09834d29fd", - "dist/2024-03-19/rust-std-beta-i686-unknown-uefi.tar.gz": "4e0a84f3dbc742d589d35cd58980157072f17090472c31ed0e306dad049a75ec", - "dist/2024-03-19/rust-std-beta-i686-unknown-uefi.tar.xz": "e11820072ae90861c96b0c1c931d691a157cccbf5d44685e3d5ff9b075aa7500", - "dist/2024-03-19/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz": "4357b6646ed0f379d9d74358457db1a18289967a880567b9bbff480e72f13711", - "dist/2024-03-19/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz": "3ffb178cb4c24b3b6df4aacbfaa4280eb6e781cd471fe52ed0b9be8fa555617b", - "dist/2024-03-19/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz": "bc32e2189cfb3efd8365bcd31fad504cab0fdf62c9fe04a6a0389ff23486cc2b", - "dist/2024-03-19/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz": "0d2894fe5fa5360cb31e5267e980faddd8d9f7adc415747991381aae535210eb", - "dist/2024-03-19/rust-std-beta-loongarch64-unknown-none.tar.gz": "16c134291f43694fb92d3efd92abc9c957d3ffa8ba8dee0c792d77f3b4d2cdd7", - "dist/2024-03-19/rust-std-beta-loongarch64-unknown-none.tar.xz": "ca06f72e2bd7309831464152cc7532a27406c18e2d6cd02918109aa65896be1e", - "dist/2024-03-19/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "a2d4f9671514673abc87ade8237508bd41df1bb6b75b0ea92bb27dd7ab75303e", - "dist/2024-03-19/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "69a8f2751d0a86878b92bb052ca0d3394f5bc0545fd3f2c1ce7e03e1ecc6d0b5", - "dist/2024-03-19/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "95c4f0f944b4b8ad08c4d0350a09be233796991b8790fc0d48dbae895953d73d", - "dist/2024-03-19/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "8ae7b77e0c7be184f4f279365eb2d9b7e9182ec9ea10f987814d4f4b50937f95", - "dist/2024-03-19/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "4f886546746f227bff157959a9982529895d52737b6137bf44545e82fe522672", - "dist/2024-03-19/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "b9fd4eda7aa2d5eb70e47405ba5fac8d5d3d15d1de76bb5d2f9d0ba8da4a2115", - "dist/2024-03-19/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "8e81b39b1d7cbc180fe9540e9420f68216aa9b3bd46d6cc6f758f473d8d54ae7", - "dist/2024-03-19/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "29d4e64b6e2a326bb695e42354e4f8a21382c63cd8a93fae64a44f3398de0a96", - "dist/2024-03-19/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "66eb8d049d50532512d442efef67993fa3da0fc0a585e549559d2e843c7e3c89", - "dist/2024-03-19/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "1919690c47b603ff6ddcf6d8f16573cc3acd960d27dfb97358dd9c92a907c766", - "dist/2024-03-19/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "e66c025f225b3cfc3399992b0dc3e5f6829ef03b6527656376a0575c970dd43a", - "dist/2024-03-19/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "75373475011adc1d3340dcf222e594be505116fa4c1099b493a6eb1018dc5f92", - "dist/2024-03-19/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz": "2dc076319958052445c0de0d34567162745d9a6de18edff2edbf6afa05feb124", - "dist/2024-03-19/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz": "f1225e56a378ac5b8790e9299815987c618f5d712a11e2a039580965679119a1", - "dist/2024-03-19/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "26bb1e505811310fecd47e7aa5b75cbbaf6794ce209df200ac554ff84a353392", - "dist/2024-03-19/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "35b4799e26da0d6220c0372bce45e6b3b18a4035b82a36505c052e0990cba754", - "dist/2024-03-19/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "5a79d8992906ab3db7be9716de2c6434e1c8d81c1ebf725a1b413af13f9c9091", - "dist/2024-03-19/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "7d63304af691b1ade5f9d6e50bf82eb9958f8b3da977fbf894f3c5dab15d0ff5", - "dist/2024-03-19/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "1a93efe919bcb44cae9fea48aa22a1591f041041e7c59e64461ddc3298ec954b", - "dist/2024-03-19/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "0e17193cec07704e02fec9f4393a457f0f57082c86d4833f687a72be0a439008", - "dist/2024-03-19/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "3ccd73bfa0926858f95f1535f1297d6adf8be62afe0a94581d267782b4e8803c", - "dist/2024-03-19/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "e7b4ef2f7a7d9bee1b0dd6a12aec4d52150db2fed29af2668ef5a65b727f6ce8", - "dist/2024-03-19/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "3e755b9a8fc8b66da6795ef57d9d80ed239e10adb17c23a8a64ba96f0d0b6296", - "dist/2024-03-19/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "936807926232e6fdbd2e93a646460ca9d8850367afd82bb56d21245936f73b17", - "dist/2024-03-19/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "168c1fb8b6f633abb699c905eaf4e970ea94c789746d7cc3a7984ffb046df446", - "dist/2024-03-19/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "d64b6a01542d504fe2d4ccdba0e7574e5521841a0a4fffc3d66e78086e0343a3", - "dist/2024-03-19/rust-std-beta-sparcv9-sun-solaris.tar.gz": "34992b0a74cedbaf58057f965858cf26ffdff8bece7b2b0e167c8a1d61b6651d", - "dist/2024-03-19/rust-std-beta-sparcv9-sun-solaris.tar.xz": "957c38d5485d96d62fe46c4dff5726233d7c402708c4dbb0337cd740ad759a10", - "dist/2024-03-19/rust-std-beta-thumbv6m-none-eabi.tar.gz": "7eab40ea23f0758c5ace93224e1268e2929fb7d165b7877ea2540cc2b45664ce", - "dist/2024-03-19/rust-std-beta-thumbv6m-none-eabi.tar.xz": "d0c428c5a1aae6e78842577a5e8f3e4b393d4d3ec9c240ed3c3a0a36d4c0b19a", - "dist/2024-03-19/rust-std-beta-thumbv7em-none-eabi.tar.gz": "450b39802145dc6ebcaad6fdf99b606fda18d3f272f18d0a5e21bffa930ec877", - "dist/2024-03-19/rust-std-beta-thumbv7em-none-eabi.tar.xz": "649532a1c17da2afbcf0fb9395305bb46a76846bbc8c4fd5c153a170b525d35d", - "dist/2024-03-19/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "8068584665ce0468bd420d146cfb4643e745c4ee782b352bfc16c9e7f18ed25d", - "dist/2024-03-19/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "04c1d047e2ec0347cac5ab5591ae0eda6f52c6f9281aaa4d2f4ffcd8c5af11c8", - "dist/2024-03-19/rust-std-beta-thumbv7m-none-eabi.tar.gz": "6e954aeddadbbaf088fc8d671e590eba87d4317f8716a7cca286c764131c0d73", - "dist/2024-03-19/rust-std-beta-thumbv7m-none-eabi.tar.xz": "15f8ea37798f20559f5c6c91c42acd4c883852e14228bbfe5b65865d998beba7", - "dist/2024-03-19/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "1c7b6e92d8727602b8e41d44b66369ddf8e65937fb1a934b2115c18816cd66eb", - "dist/2024-03-19/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "5679ddb9d7404a776861195ca708fc6132ce1e35fc5994946ba7a17ce61afa9c", - "dist/2024-03-19/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "44280bcc42edb6ff3f2d91c8a3e7005703150e7be749480577df96100d516b1c", - "dist/2024-03-19/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "abf86ce8dfd3bd5548cbc8c9c958eb75fbbff77cb7ae8a5e231e5ac9d46d3876", - "dist/2024-03-19/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "ca4fc4970411a503d11a30bbea94487a10dc5925cdf7b1dc3bea095c72e5d381", - "dist/2024-03-19/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "9752a30a7a2dbf64092cfb1901ef4e49e9521b794644710060eaf62c8acd1d5c", - "dist/2024-03-19/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "14d29c09f788bdc63550cb9cc0ecb8040b0e28e6e5a5bc65c06dca6a0fb34821", - "dist/2024-03-19/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "201eff5b741c735547226e9a4d22aed0e09f1c31a48673ce7fc094fb7fc95ba7", - "dist/2024-03-19/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "1a641bcc8c904a0c5b4e7ff0d52d105a1ce45c24d10bb1cdc1dc284222851d6d", - "dist/2024-03-19/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "48f8abb5d1dae87c22e4d24610be6a98d646150d7bddc1ca471a6a27976090e0", - "dist/2024-03-19/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "102f692ecc5233a2e8063c305a0d37ffb9689fc1a4927dcd8f4fa14501a04a0b", - "dist/2024-03-19/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "cd0407c881219b7586500c05b711ed78de9356d7c0db1065baab3833b5d2b738", - "dist/2024-03-19/rust-std-beta-wasm32-unknown-unknown.tar.gz": "3e588580f9298626c4bc3e4b0ad52495d97e4dfc61ca8778e97da3e67c624266", - "dist/2024-03-19/rust-std-beta-wasm32-unknown-unknown.tar.xz": "665dd07fe6ab4d2bcbdc7e88b674e90ff4ea8caff9251d572ff0a7edb32a509d", - "dist/2024-03-19/rust-std-beta-wasm32-wasi.tar.gz": "c0249f7a3e1f8275323adc2a49840cfc677ce8ac3365886753135703a9276572", - "dist/2024-03-19/rust-std-beta-wasm32-wasi.tar.xz": "aad18dde6feaf251af10398b9e7ba2e39828a4640a8f30cc66ee72cd2b1278b3", - "dist/2024-03-19/rust-std-beta-wasm32-wasip1-threads.tar.gz": "95f5700c74feeecea7705d90d3022637e4fa96ee5db165d8fc76d4db05101005", - "dist/2024-03-19/rust-std-beta-wasm32-wasip1-threads.tar.xz": "6787b24af02a7216a524104379517a158938bc2c940b56a60be2ac143d3de7f8", - "dist/2024-03-19/rust-std-beta-wasm32-wasip1.tar.gz": "38d2130daea2bd3c71a456e4dfc44ad900838d15a18af123bfe971f036b43951", - "dist/2024-03-19/rust-std-beta-wasm32-wasip1.tar.xz": "a766d6af0392e913f42930a02fbe5c7b481120ebceadf6b33c7c21ba6067c7f0", - "dist/2024-03-19/rust-std-beta-x86_64-apple-darwin.tar.gz": "3de58d464ee9cfd01d245016b752d1740f9b3feca7c84dddcfeeefd288a4966e", - "dist/2024-03-19/rust-std-beta-x86_64-apple-darwin.tar.xz": "8854dbc047727f11dcdc2f243536a5a6c5e7d8986c4ecea026820630aa2cce59", - "dist/2024-03-19/rust-std-beta-x86_64-apple-ios.tar.gz": "79477ea1afc524ed9d4f3ae57df132affe03a3fa7a14b17214181543918b2391", - "dist/2024-03-19/rust-std-beta-x86_64-apple-ios.tar.xz": "b830688a420e5631406b00d40756739d71a5f8f9789a4b6f4a601db167893814", - "dist/2024-03-19/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "ceb9ac35511e08cbd14dcf6c4faed57107f0facd5ebe1b1634f2ce2b41781c27", - "dist/2024-03-19/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "532b77cbb488b445e0291997a21d0a94c44970c5793ecca07eedca2dc4b02be7", - "dist/2024-03-19/rust-std-beta-x86_64-linux-android.tar.gz": "5333bf0c8ea592ed316e21bb2938ed07d247f0f873b45f34abcaa62f2e33f741", - "dist/2024-03-19/rust-std-beta-x86_64-linux-android.tar.xz": "ab18128d48a1eac2e8577e4268d95efe9619a4789cf4ee322d5bd651f33c24c1", - "dist/2024-03-19/rust-std-beta-x86_64-pc-solaris.tar.gz": "6976af5df3468680d83f54e87f57b94ac121ee82d7887e3e21200434b993a219", - "dist/2024-03-19/rust-std-beta-x86_64-pc-solaris.tar.xz": "932ffbff886919acb32f77ab70560a0262bbf5ee83a78679598ec13fcad39e3b", - "dist/2024-03-19/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "0429be318b55a9c36bc2fdb0b9654a3cf39527cb05d75f46890f6fcc2ed003a3", - "dist/2024-03-19/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "7e3f64dc9b5b6653e6adbc58499857c0df8f1765d8fb777f6cb2ada3f40543d4", - "dist/2024-03-19/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "07a7bb2d07bb72693e0bf0ddc365394dde55063ad572259a5d171e08cda592f2", - "dist/2024-03-19/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "efc20d952b248815bda4ab3950b2998b5326e2c5008e72ede921eacb79b3b504", - "dist/2024-03-19/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "04a46c5cbfe620dc5d3d05134e0501aa466c081f848df679c554d51ecc6e8bb6", - "dist/2024-03-19/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "9ed41c7d0c09409fbecf33eab630ec847a4af7ea5bcaf42d8e14e1074ed30bf4", - "dist/2024-03-19/rust-std-beta-x86_64-unknown-fuchsia.tar.gz": "de0c88a91d325087e5c28e9ca5d3092443c875b55ed08b8486e8fd1c01c7b7e8", - "dist/2024-03-19/rust-std-beta-x86_64-unknown-fuchsia.tar.xz": "e403921f889381097628bcb2c431e3b8a8c0773c0d5062d4d1a9ec8e7f88fa45", - "dist/2024-03-19/rust-std-beta-x86_64-unknown-illumos.tar.gz": "ee045b5102673d085fbeead4d5b9daeb9497f90d341bd51c8ac85b666e9c9821", - "dist/2024-03-19/rust-std-beta-x86_64-unknown-illumos.tar.xz": "bd24fda28c9b69cc68c90b910a75cd652ad3b4d4430f802d8a2354c2cd5d19e7", - "dist/2024-03-19/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "8c70c2d12202054329cf6fca88adf20d9d9f493cb057c30211454a49f96ad4e5", - "dist/2024-03-19/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "ea6673ea519a6eba60836b810c0531cac858ca74d0d756538a45a375ffb7db9f", - "dist/2024-03-19/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "52e104ce39ac5e8e44fbb332bc08f7ac3d564408f48a459f79ba2149caf47b32", - "dist/2024-03-19/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "fa098772e186acba6e85ea2f4d0270f01e00cbdd27eec1e92cbda808b7807284", - "dist/2024-03-19/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "d6785e6574b4a7ba61f66c1e7938a46a02f9430983a7aee1c3400eb5f8b57f0f", - "dist/2024-03-19/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "17c3e8254fbfed0f0a9b3209976e44a136d0f581d0713ddf7114753cfd0b983d", - "dist/2024-03-19/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz": "407f9c2d5d3bd76698af04711d9a06b7aa86d4c55cee9d8ed1ce3aa37055068e", - "dist/2024-03-19/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz": "5e0869bf268c9824c284e841b2bf5a13a6dc1bd2e55ce3b7b09788ba5608c9dc", - "dist/2024-03-19/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "9b5aa240c2a696af0d342ec26a6b6ea4f5888070e8b590122379302910a978f8", - "dist/2024-03-19/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "064c1925a8ac82d1474c240c6c9414b422a7b04211a49a7660625193a0c21c64", - "dist/2024-03-19/rust-std-beta-x86_64-unknown-none.tar.gz": "8e48a645b2b8dda6deb5b706e415697d303830775032b69521265acfc9f8608e", - "dist/2024-03-19/rust-std-beta-x86_64-unknown-none.tar.xz": "a3d28304c75a71680d7d40aca43bf638bb4def5ec10f873aca5261692b114743", - "dist/2024-03-19/rust-std-beta-x86_64-unknown-redox.tar.gz": "e645a81d4884f09c9d7da242ae448cadaf7a9232475707ece014a57d02a23527", - "dist/2024-03-19/rust-std-beta-x86_64-unknown-redox.tar.xz": "0cf089464b1949a4f24092e2782b306e9530489cc415df69ae433c23a438518e", - "dist/2024-03-19/rust-std-beta-x86_64-unknown-uefi.tar.gz": "ba7eec56d4e8a5f8a6c206b6a12fcae77da9a24ffea824c1db128dcd4a7d9fbe", - "dist/2024-03-19/rust-std-beta-x86_64-unknown-uefi.tar.xz": "76aa9bf6ed668667d1d47feb2fb8e941f5446f2ce5b4e94aacf34f964ebb3171", - "dist/2024-03-19/rustc-beta-aarch64-apple-darwin.tar.gz": "e40614daaa2b0270d5f3153c8216f68419b96dd167632dc67c1fd641ac0a21ff", - "dist/2024-03-19/rustc-beta-aarch64-apple-darwin.tar.xz": "7c2106ea1a3d358e2893a62fcc2162e041ecbdd9143f2dabbe0fa7a6b5827aaa", - "dist/2024-03-19/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "7eb0678bc1b4dfcf366641dbb02390262e47ecade1db9007ae1d5bbc39b6c7c6", - "dist/2024-03-19/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "0caef4825f0a6e51fd05c5c32365fb3a80a2b7692de71ff0af10ce9aea1ecafe", - "dist/2024-03-19/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "bbf59310c1e60725aebed09a09f0df4b1c21c2d0744f34734472e46cd7248fee", - "dist/2024-03-19/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "a7687c89bf94d64119ee76029ed12d27d594d7716fbf542852333185385a5b44", - "dist/2024-03-19/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "d2bda016eaf8b988e3b5899ab1239c582ef9119c40267b79be2efa453ceb9ee1", - "dist/2024-03-19/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "940f0611384175521401f352f4fc18a587b3816f99c88a0e130b895918c340a9", - "dist/2024-03-19/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "3ef861f5980f899b6575e50844c14ad30fe739f80538118acc8e29fd8b00cbed", - "dist/2024-03-19/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "191a2bb6966e05d1db83acafeb3caf0e0421eec539e221837e3dcff5e9db4152", - "dist/2024-03-19/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "9999f60a513864257a14ee58ac3b87d9e557e0c2fe720a5d4ba31d250debc378", - "dist/2024-03-19/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "7c824f67a45aaeb7cf4c7519aa72ce8a81013cf2edec2fb5600f68aaf6eaf84e", - "dist/2024-03-19/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "83fa3927f92945845c6cc5a6f123ce5301a24af81c9371e5c6bcc8964a182688", - "dist/2024-03-19/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "3469f087248e671351dc0bdda06c1a9b8d12fc64854148cc9404d419db8fdb02", - "dist/2024-03-19/rustc-beta-i686-pc-windows-gnu.tar.gz": "a219c9829d7e33a822947faeb3f8826d7f2f5c46aeaa9c338bc27bf7b1561395", - "dist/2024-03-19/rustc-beta-i686-pc-windows-gnu.tar.xz": "ee5f30b90bc43738eb9c9a3678a09768bcffd3bed413c50ec23fa14fea1157ac", - "dist/2024-03-19/rustc-beta-i686-pc-windows-msvc.tar.gz": "acdc6345b76ed52b5b58d2832ae61c904aa6d74955f2e31432ab363f217397ec", - "dist/2024-03-19/rustc-beta-i686-pc-windows-msvc.tar.xz": "13161baa6a6e0771fcfb65b0e26f77a1ce07c5dcdb029a624723231d5d3c1012", - "dist/2024-03-19/rustc-beta-i686-unknown-linux-gnu.tar.gz": "7188f7c598cd4f1579ca06819cac5461679513ff648f03b7f28e15fd5636467e", - "dist/2024-03-19/rustc-beta-i686-unknown-linux-gnu.tar.xz": "42e03380ac0070f1cbf47c674c1d529cb065960f5e8c0f92e24a5f994dfeca83", - "dist/2024-03-19/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz": "67a57b0a8a057a1d39b99e5232145d7c5a48b9e3ff0e97b9ad1f4cbda004587b", - "dist/2024-03-19/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz": "1c85e17bd524294ac64c2defce82eae336cc3c5d9795dab68e0d7419ede35a6a", - "dist/2024-03-19/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "1c243f95e823164a4b112fef4a70bd3cb0f368dfbff7efd106b7ec3a718f49dc", - "dist/2024-03-19/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "318d69391381a142b72a27c6e53be624691e465ffec2497676c2454bdc06f856", - "dist/2024-03-19/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "f8423ac9a207c9a43746b9299dab7ff55a747aba1980313f98b5aef67e489d66", - "dist/2024-03-19/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "f6e3552a9ad8a90dc0830f7c8beaaf10c90e4760bcb48904d4197c53a54a8b1e", - "dist/2024-03-19/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "3ab2d798cf0812b874198691993686e9c884d24806628242110dacfa5bc3446a", - "dist/2024-03-19/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "6cae9a4e5e88054800f11f028b92211173de4038ad1bb0a871cdd05bc6a0b8c1", - "dist/2024-03-19/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "368351e98c1e71b3fe40c687f478d52a43ba388811521e7807b314d750cb4f65", - "dist/2024-03-19/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "116171252c2f153066e9f8fa6eb1e63962aebdd67d14368560200c984ae38ccf", - "dist/2024-03-19/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "0445ba1954a7e6bbaf64561a33c01988a4f48aa8401669acd7c5e8ac11d27696", - "dist/2024-03-19/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "23aeed13a2c0143d14ab9fb26be47314318ee3014190ba08f5889bed14205799", - "dist/2024-03-19/rustc-beta-x86_64-apple-darwin.tar.gz": "91a1040d4b0d309fadae1b180c5cdf30c9c073245599064a075849795a8c84d6", - "dist/2024-03-19/rustc-beta-x86_64-apple-darwin.tar.xz": "996bb8bf522509e5ddf5e2d4fdfe0c19d4198605107575faba4a80e1f4de616c", - "dist/2024-03-19/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "82024a5d02148c7a0a0309105114f54dcdc6b9bb763d1e0456f0c18f96b16f57", - "dist/2024-03-19/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "b6c00535af0ef5815cfaf88bcf21b83935539785345b22abeb9d4fa97e2cc445", - "dist/2024-03-19/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "409a22e9a1ae89640059cb33d614abe84eef4096817b0fa750b3a38e0a153061", - "dist/2024-03-19/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "8fcc030bcbafdcfbd894653ce935ecb82fc04b3717718d34dd6b2a4e8d553889", - "dist/2024-03-19/rustc-beta-x86_64-unknown-freebsd.tar.gz": "79d39890188af98e9eaa1b5a15606517ad7e0b3c493bad09a59c5400bfff3d9d", - "dist/2024-03-19/rustc-beta-x86_64-unknown-freebsd.tar.xz": "b69b370559cdf73f26b83a4b5276d10988f44d39d57608c44defa6b79f92121d", - "dist/2024-03-19/rustc-beta-x86_64-unknown-illumos.tar.gz": "f4bc2b510a230a09bae4b243f1297863907c9239a94bdf739f43c31a76238a04", - "dist/2024-03-19/rustc-beta-x86_64-unknown-illumos.tar.xz": "131b02eab07b50d8a99e0185090afd6c3fd1bd20b98fc0a4830910fea5b12ec5", - "dist/2024-03-19/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "ed9d98b20a4868330c88563ec367078a4c5ed7bca497680ea690cb9da2d6ddbc", - "dist/2024-03-19/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "b6c0fec4e295b8eec2b7c8bbddec48aaba1d3c4d73803eaf887554d368b4efa5", - "dist/2024-03-19/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "e972c5ec3f9cc2661845bbb2e7153b9e90e59af2d4fcd74c588e3f326bbe9e6c", - "dist/2024-03-19/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "d576799dcd59b48ddb6d96545ec48ef517b5a7d9875033de6583387fc1d4b79a", - "dist/2024-03-19/rustc-beta-x86_64-unknown-netbsd.tar.gz": "39f5a43f70692f1bcfc6b82ef901fa86be82aa7db0f6161ea5025577976a0780", - "dist/2024-03-19/rustc-beta-x86_64-unknown-netbsd.tar.xz": "596e6681bb15420754ab1a7210157884f5e31b34a885b1d1cfcb8838ba5c28b3", - "dist/2024-03-19/rustc-nightly-aarch64-apple-darwin.tar.gz": "f91204bc62d9236adc75e2a7ba4ae41e0d9ea9c6b6bcaf0d211459cfc7d17d21", - "dist/2024-03-19/rustc-nightly-aarch64-apple-darwin.tar.xz": "7562f89f9bc9f2968ddcef0258cd5a1435855d87a1c40b9ead6b82c1cb5c58c3", - "dist/2024-03-19/rustc-nightly-aarch64-pc-windows-msvc.tar.gz": "2f1ab532837469eba7dca3cb4b45ce983384e30917b0af3108d2a8c7c88f38c5", - "dist/2024-03-19/rustc-nightly-aarch64-pc-windows-msvc.tar.xz": "fa69006e8189b1e624e0d9a9a212c15423fc1b428785f651a309eae045199f11", - "dist/2024-03-19/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz": "21905a47c616e3e43b05135621c17db635dfa897e2e64b124c03b042f74dff00", - "dist/2024-03-19/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz": "1efea63747a88b3baefe6602e047e84323867a3eeb77093b9e662ff254a85f28", - "dist/2024-03-19/rustc-nightly-aarch64-unknown-linux-musl.tar.gz": "1b693de287b60428bc1a0a23088c08680db2d0fbf4f7cf0d6e3f413cd9cfb150", - "dist/2024-03-19/rustc-nightly-aarch64-unknown-linux-musl.tar.xz": "7803e124610ad092f88b7cf4b65cd3fa1a80cb2cf5a36fe4391535ca4f3d9369", - "dist/2024-03-19/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz": "744bef406b6df5c610b605234375d8520abe24d8407b8bd22a0fe15de41d62b6", - "dist/2024-03-19/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz": "b90dc87a68c134e6fcdaa3ea20e9d0fc33b0422e4dc989c1cf0c85c8140fdfce", - "dist/2024-03-19/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz": "e235fd3258b7d1e42ff6609f1660a94aaafc00875c371543ad2b12ae226dd8c7", - "dist/2024-03-19/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz": "b37ea15820c88ae1ab534277f8f7a7ad18b3d365f1d2d499a887665b715c6c21", - "dist/2024-03-19/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "bf7cb8f0b21f2b0b8b067f88e31a2ce9e5754044b68437d4d52324fd95010161", - "dist/2024-03-19/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "3595940730b4cbcb00e0441458b07253677d148f4850b464d6df7706c203d1aa", - "dist/2024-03-19/rustc-nightly-i686-pc-windows-gnu.tar.gz": "3135f03a8388c13c6439ef0464e2086949a528cee7bebdfb955defd59e55952d", - "dist/2024-03-19/rustc-nightly-i686-pc-windows-gnu.tar.xz": "54b6ca29f64e454189f27135f9a40f0bc0d0b5abf4d2912aeb857f733721005e", - "dist/2024-03-19/rustc-nightly-i686-pc-windows-msvc.tar.gz": "d3b70b07c8c9cedd30dbebfff2bfe45316752a13d49c9feedfdae4f71bb74865", - "dist/2024-03-19/rustc-nightly-i686-pc-windows-msvc.tar.xz": "653a821d9a7789e19fdd32f82466e906c23e03e42752f7277c05b692c1459e20", - "dist/2024-03-19/rustc-nightly-i686-unknown-linux-gnu.tar.gz": "4a37e87a3280997bb09deb6a3617395b1e898ecd07f0bd5469cb21e55c3c5f81", - "dist/2024-03-19/rustc-nightly-i686-unknown-linux-gnu.tar.xz": "a66bd9287cc958a61f9989d5efb6162255f7eb9211af9a4ea98769971350384b", - "dist/2024-03-19/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz": "3ce931c54c96c72034392efcbcd73061d6f8a7c7f40f1e86c14ae6fd5248d2a6", - "dist/2024-03-19/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz": "cab19b60b91cd6549f89398f46b31fe440323c9669606f48a4029e8d3cdc1ee5", - "dist/2024-03-19/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz": "3d50b95e8f9ce5a2721e1ba0649378e8426fc4ba531bfa13bd9b96ef627aa46d", - "dist/2024-03-19/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz": "9286d55547a438008574267cc3a067ca50005a9397bf8aeccd76ea27233de2fe", - "dist/2024-03-19/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz": "61843b55a45909408b3005cee338de42d31aef852155c8bcd8f6cf9aa3077dfa", - "dist/2024-03-19/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz": "2de14af7b540c3302e6b1a0f77472362429c0a1a0026c2fc799b263817e3c942", - "dist/2024-03-19/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "816575061e2879d6855fa497b3bbced57f3201d64c6649c89ba9020c69889fd6", - "dist/2024-03-19/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "58962496e51cdc60f9a98fb2fdbbb2f4124beb3fdbb065cc6b52871eb4bdc2f9", - "dist/2024-03-19/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "cd649970e9b8a98e9dd0c1f506624832cb08516aa9cfd001381ad265cc42ee66", - "dist/2024-03-19/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "1a9a2bcdd263a205bd85c8fbb9733711ceeee372953a7573420fcb55d59d59b0", - "dist/2024-03-19/rustc-nightly-s390x-unknown-linux-gnu.tar.gz": "98d6631c6dbca97491d5f518dceddc07c53aa309c7db8da0a919eed96f9e45bd", - "dist/2024-03-19/rustc-nightly-s390x-unknown-linux-gnu.tar.xz": "ee1fcc2a1d3181c2a7b97df8525363159c47b1348c0db78f74c7181ad6c44166", - "dist/2024-03-19/rustc-nightly-x86_64-apple-darwin.tar.gz": "c2768511ca6e9c228e13815040eb56f43ba1ec223c7753ea0e613400989a20d9", - "dist/2024-03-19/rustc-nightly-x86_64-apple-darwin.tar.xz": "6c10e9e824d1bc7a3c75172375e3490e33627bcaef6315552147b89b81ecf328", - "dist/2024-03-19/rustc-nightly-x86_64-pc-windows-gnu.tar.gz": "6d3a1f7c97fd4115b524f990426b795be1b9ca9a10fc6fd68db1cf4355d3953b", - "dist/2024-03-19/rustc-nightly-x86_64-pc-windows-gnu.tar.xz": "86fbb08c51664be63b234b82894b1b8012d8f6bbbbd96b6fc7188c22b887049e", - "dist/2024-03-19/rustc-nightly-x86_64-pc-windows-msvc.tar.gz": "39b673d694aee6c5d25ba88ba7e9f38b6264f01ed6a5785ea44e07594b9a7d1a", - "dist/2024-03-19/rustc-nightly-x86_64-pc-windows-msvc.tar.xz": "43ebc08539300d736d1d41af2306b1bbcb0d9e04795033725807d4c9c06d590a", - "dist/2024-03-19/rustc-nightly-x86_64-unknown-freebsd.tar.gz": "cd263eb4b6e027b834723f3748139db6f1742f885c2cfa2a4842c23c806b48fc", - "dist/2024-03-19/rustc-nightly-x86_64-unknown-freebsd.tar.xz": "22fc109ec6293b799fd52398b72f90966b9efb95c433f826e31f54fe643132cb", - "dist/2024-03-19/rustc-nightly-x86_64-unknown-illumos.tar.gz": "20b01c262d54731c471d6dd856fbe8c9a58674f88d0dea19c7e9b7adff6b5474", - "dist/2024-03-19/rustc-nightly-x86_64-unknown-illumos.tar.xz": "584d1e3b9e6e2006767a6a1a46aacff34a2042b4094e51be0a1a82a50a4ab27e", - "dist/2024-03-19/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz": "71b98f184c4b3f3a40c5ab7cf6bdae6947a39c2a7e36e590750a37806cd98a2f", - "dist/2024-03-19/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz": "44510c19128801a465c70fbb4d1fa0250edd7c1ff0a67f1c374f1d921e1a4bb8", - "dist/2024-03-19/rustc-nightly-x86_64-unknown-linux-musl.tar.gz": "897728aae12523d33bad792c4275512383ae5cff008860406882ebeb273cca5a", - "dist/2024-03-19/rustc-nightly-x86_64-unknown-linux-musl.tar.xz": "b027abf370ef289d6b2e615dcafac3eda20c147dd2ac4a3c113e8689f6936655", - "dist/2024-03-19/rustc-nightly-x86_64-unknown-netbsd.tar.gz": "97360bb700ee986b0a36ac4ed4f0fbcf3c875907bb6cfdbe4bfa0274893109f5", - "dist/2024-03-19/rustc-nightly-x86_64-unknown-netbsd.tar.xz": "e8414dc178f2d1939b2d6411beda7bc6f8e9b7f500ccb30fc8a8659ddc0f945f", - "dist/2024-03-19/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "8515050a52addca9d5c0ea8b9f4e5c536d32ed275fd0922cbe567fbf7d5adcb6", - "dist/2024-03-19/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "97c68112bd8f4cd67eef50c994dd13967482ac1e55170dfd11d8505c582c689d", - "dist/2024-03-19/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "b3ff60427dfa13e3c9d4965e0f197ac2a0625fe64cb1e23ec46604adbafdc847", - "dist/2024-03-19/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "848938bd1436276ba813104cde9d969cbcd79d295eb045ced1d82080cdbae29f", - "dist/2024-03-19/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "063f25121c6a8055228763240f178b7f1e9b55f20b305b8e2ebc1b0a080e432d", - "dist/2024-03-19/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "89ab3a28357f3926fa4880010d0ec6b6fce06476050f42c71416c60528490f7b", - "dist/2024-03-19/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "6ece90be16f59b3a5871d8cee8638e18c233eb0e59253875e71bd16ee4c7eb76", - "dist/2024-03-19/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "7272af79200e1da8ab80b2e4408501ef8a54c24ba44420aaab0fb03653933ad6", - "dist/2024-03-19/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "7ba3404ab333e43dbacfda6d8860d800721a7f894c672d3ea88cb88127128c90", - "dist/2024-03-19/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "bd4087d9e70c0246c0606015c1e6d6b974c068118e50e2720c7ac75a6d338709", - "dist/2024-03-19/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "f87c7036539d18881cc0ad5647b523dd07cd29cd38c36665aacbdb37de316231", - "dist/2024-03-19/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "cd1b05cde5ccfc389df6d146f467a18455f22c7f23e508537c8de11b8d7aea4f", - "dist/2024-03-19/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "66b0bdfb271448861ccc403d7549b49316c5cda81bbdaa396ff66c01dfb052df", - "dist/2024-03-19/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "40e3df123160c8948ed06c8228df90de1368d286f9849a0a14de0725167dc8dc", - "dist/2024-03-19/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "da09c72f472b6bdbf7e794d84990153936ad1c7d275daa75b506ab72444b51a0", - "dist/2024-03-19/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "c9e2ea2216c4f7737919c63ed0e5ca362f6c3c9f227f1b3e6a243a870f229a52", - "dist/2024-03-19/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "ba468a1251b4bdb685cf5437222ccea45ba1f4d1b25ca65b82a9fae4ba93d6d9", - "dist/2024-03-19/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "64781d2017662c9973a22d322c92b242703a90895cefa584035b0d80ac966541", - "dist/2024-03-19/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "595fcdf3cf5b2511ec828936119334516d535c4dea95f60a04eaf1724a90a276", - "dist/2024-03-19/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "42f2537e87adc2cadee67e5dc1fd7fee4c7bf4347f88501752080a65b9e7fd89", - "dist/2024-03-19/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz": "3ecbee26e0b0cc43189dbd8d69a563bf71292974d0c5d313528a32012f38fb56", - "dist/2024-03-19/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz": "7a0918c6ad0dcdddac757c7f4580fa57ca188ff2edbf7eac07ce01626666bc95", - "dist/2024-03-19/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "08197220ca270180ff4d7f484000f6b7a52800e932937238cbf1f47ce3f1080f", - "dist/2024-03-19/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "dc7f03fa39872e59fab5f4d663ed092409849c62c8e4c958c6cd4ed59bc05902", - "dist/2024-03-19/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "c7744b4c88a5ac7ddbaa1b61b66b39f2799863c50b6e18c18874d5774d11fe53", - "dist/2024-03-19/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "0ed8aa4704e7d665843ea1ac532b1631cbf449180331d880466fc69483d4cd23", - "dist/2024-03-19/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "e67d83663cb54168fded400385a5cdf8b74c6483d91fd16d03846a6411ab1afb", - "dist/2024-03-19/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "fe4c2401281c07d1c3ed335575bd192ac57396973a3676226d57e5de32a63e3d", - "dist/2024-03-19/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "39c4739ef0281bb1eeade5c8f7360ee8dde5a8a7ae148b0f263ba650d092cced", - "dist/2024-03-19/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "ea26063a71a4403a4aa49098a96a29b48aab5f9b9177e57b1790b92ed749ae1b", - "dist/2024-03-19/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "49591c34bcb82d6cc5c08c662c4c89aca07b406fa1b48b78c7dbcb63cbe6fb5c", - "dist/2024-03-19/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "df664d781e8104015c506178df751ba7130c677f050cae695428fbb6180b1af8", - "dist/2024-03-19/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "ff20c34ab85505c1957a677eb8123622c98f5e19e87cfa38eae76232e200242b", - "dist/2024-03-19/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "c4e8b76738bbfddf94defb88e9b0c0d0c488d9a5868f2be629322c041391b43c", - "dist/2024-03-19/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "8e0367ab0700e916956db6041e1c6a35b0c6fbd1127a17f9482691a103dc8d70", - "dist/2024-03-19/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "1aad45bb09a907effb39378acf5c57c741d7b0e29eec957d8be31eb1bf47ab23", - "dist/2024-03-19/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "f5fa93652040ba991c429d11c5e9ae2e76aa6f21f6850a777f2ba1b065e943fe", - "dist/2024-03-19/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "7d448e8ae9090467197d9bfc7ac3d8f7ab81cfdfd0be140afdbbbc6c3cf65295", - "dist/2024-03-19/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "8ea5bc3f374b5b63432151541715ab41d00f265e6cc8e57c61e175304363ca5e", - "dist/2024-03-19/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "666deba3f55f30e302642b3e2d3c86bdce12626ae78bb7134c7d90b1c7179592", - "dist/2024-03-19/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "edf75305baace32ab2955131357e30c73c736d823d6426125e5fde213c8f4c61", - "dist/2024-03-19/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "5b3ebd05d571474002c032aa2fedc788650d374b388eff9f6c00cf5bcdd10c08", - "dist/2024-03-19/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "e795bb7cfde3d71f9e964dbc9efd930251eb3209686d5c9348f24deecb01fcde", - "dist/2024-03-19/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "8e1c06e91fe7cd1ffa80f043b8342c611d8f923cc9b563fda0155855d8799660", - "dist/2024-03-19/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "a8a51ce3eceed87d192701abb699dc60dd3c28c86622b9aa3dae833feb8207ef", - "dist/2024-03-19/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "389cd5d4c0decb87eb24b9ce88d5e5f33a7292153e2eb37ca2a106e4f8a4e256", - "dist/2024-03-19/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "cbbdca68aa3ff10fb28d431ddd08b56bb4f0a0f85ebaf7c094b9740c8e2d1aa2", - "dist/2024-03-19/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "e1c1793bfd102241338f801ba8c28f83d15fafef09046b231e30d1ac42b5e372" + "dist/2024-04-29/cargo-beta-aarch64-apple-darwin.tar.gz": "5a8c5e48a88e7c7b41eb720d60fbd2e879b97639c7ff83710526e8e6caaf8afb", + "dist/2024-04-29/cargo-beta-aarch64-apple-darwin.tar.xz": "0d237535ae8d435d99104fa5b9dbf41878e2304bb0f2eb574bf17dd685caadc2", + "dist/2024-04-29/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "c56733bb6198af0a9b0df9a44ef979150e00de33b70853c239cccfcce23c328f", + "dist/2024-04-29/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "7da5f887151215ddec640684077d98551fe2aed75a3ece2c73b20698754a70bb", + "dist/2024-04-29/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "73851e304a539d41bedc0d8a5d98800c8279ae623d3e58e863f8c1f8b458b01c", + "dist/2024-04-29/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "db9c28841344b0154756e19a21795ef6e0c4e27c7844be9996824f1039edaa81", + "dist/2024-04-29/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "a706c8c7e37b9e80d7faa000c5d179a772746eef071387fb2879fdeab1f1f891", + "dist/2024-04-29/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "2060634afe1b4a19bae874c6ce3cf4256e613af26e06104b45da5bd71cfb133c", + "dist/2024-04-29/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "7af61e74faea669fdd41793e4b88eb6a37bfacf845af364ee02bb7cf08c612c7", + "dist/2024-04-29/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "4759fb3e3d89ead605c4eeba23be5cb9b3ac98086a9de20f8dbfdfa9282ee486", + "dist/2024-04-29/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "4cab18df2d94702e8b551357373bcae60d1023e644148f0f82e8971023362121", + "dist/2024-04-29/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "7de4f0d72b4e5770376ede82b02d6bcfd450788a40375fad34d75524c941d72c", + "dist/2024-04-29/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "6401391a426cf33d6c58f07e7b2828b178720cb4f2b8577ae932b5f5b7d6744e", + "dist/2024-04-29/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "c3f6729bc769325046f0f62c51b5bed30068c37dc2a36a6283e50565d8cb7d5c", + "dist/2024-04-29/cargo-beta-i686-pc-windows-gnu.tar.gz": "d116c97c1242220c7972b63010aee1ed36bf5353e84a06d3561cd5fe9d7dae84", + "dist/2024-04-29/cargo-beta-i686-pc-windows-gnu.tar.xz": "65eba577f7775b3eef36e7f000b5007264392b20a7759f8ed567f3a45b2877db", + "dist/2024-04-29/cargo-beta-i686-pc-windows-msvc.tar.gz": "d418a3371b3631328bde2b1e0c3159700f12424e83b1d8ece1349fea90f9e403", + "dist/2024-04-29/cargo-beta-i686-pc-windows-msvc.tar.xz": "23ae73c776fdb0795944656d743444e3b4c440f45084028206c1aec52333b1ba", + "dist/2024-04-29/cargo-beta-i686-unknown-linux-gnu.tar.gz": "b6bbdeb7c8bfac2e8a083adb4782caf5321799f47acb4eaf81da32bd11730e9c", + "dist/2024-04-29/cargo-beta-i686-unknown-linux-gnu.tar.xz": "6b409691da6ddb8c04409667b2c3d9d6429c6b5bf53ad18177248406a5f06cb9", + "dist/2024-04-29/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz": "24cd888d14a788e8fb5b886735f3c07a028a8681df48a777b2bb971c62a175ae", + "dist/2024-04-29/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz": "e8eece6412936fe4dc863a5e19e6766fbb20e81da0069ad7831465e638db23da", + "dist/2024-04-29/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "8f007a2aa02e35c5ddb2152cc7589092a0e3083211c6aa23e676e3a3ad5a4b8d", + "dist/2024-04-29/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "3e423e693dd0813f5d87d9eded94894076258ece56684f3598321cd013aeef3c", + "dist/2024-04-29/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "2eec5e45e389a52b526a5cf683d56a9df92004f6095936b16cd8d7d63722cc6c", + "dist/2024-04-29/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "64c5135cbff9d4fa9575074c55e79d85f72cb1783498a72e1f77865b9b2d1ba3", + "dist/2024-04-29/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "d64552a80ca386728e42f00d7f1c700b5e30e5a6939f32ffa15a7ce715d4c8e9", + "dist/2024-04-29/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "fe91adce8ba35bf06251448b5214ed112556dc8814de92e66bc5dc51193c442f", + "dist/2024-04-29/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "77aafa8b63a4bf4475e82cd777646be5254e1f62d44b2a8fbd40066fdd7020d3", + "dist/2024-04-29/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "c38f0b4adcc8e48f70b475636bbd5851406bba296d66df12e1ba54888a4bf21a", + "dist/2024-04-29/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "c05df24d7e8dff26c01055ad40f9e81e6fcb3ae634ecc1f7cc43c3108677fa0e", + "dist/2024-04-29/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "47e8f4ec4d996600e60ddc49daeeb43d4c21e0583a86c12395c16eddc7db76ee", + "dist/2024-04-29/cargo-beta-x86_64-apple-darwin.tar.gz": "f024bd225b77160dc2fabde78002c8deac5cbb9a35345340964c3b988b0d1791", + "dist/2024-04-29/cargo-beta-x86_64-apple-darwin.tar.xz": "96c9e44bd9f0c85c793e3dd6043cc4f89fbeeab5ddf0fdb5daefca8f690bce05", + "dist/2024-04-29/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "517889f222b62150fe16bcfd3a0eb5f353956b0084d85713480197bff4558145", + "dist/2024-04-29/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "a6653ea4aec51569c1300c044d8bf2517a1f5111f710d12cd352190425b8f317", + "dist/2024-04-29/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "4cb5b5054dffe6721efbbf29192a67e59cda69ea4ab4791aaec6f314eefa5a5e", + "dist/2024-04-29/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "08bc45be22e9e4f615d1c9e70500046c8db89045f5d40dcde853c610591712a7", + "dist/2024-04-29/cargo-beta-x86_64-unknown-freebsd.tar.gz": "9661357ee8ea8973016fdbaa2de3cb98713136dcd25f07aa9f9d101180276815", + "dist/2024-04-29/cargo-beta-x86_64-unknown-freebsd.tar.xz": "7fab806227d1a3be817602abb121ac7e039ba0bbf81e0a1d47bdcccca74203c6", + "dist/2024-04-29/cargo-beta-x86_64-unknown-illumos.tar.gz": "4c79bb48cfe64bd38af7fe3660cd8bdc99ec90738a0d8fdf80843ecda910dab0", + "dist/2024-04-29/cargo-beta-x86_64-unknown-illumos.tar.xz": "0fb9edfdafde1820ccb25c22369cafb0e75e68795effeb615cb284a5837c75ba", + "dist/2024-04-29/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "c1902a072e61ab5ae9737a1092732e3972deee426424bc85fcf8702adffdd41d", + "dist/2024-04-29/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "d39ea1195dcc95e428bd540abd2db5b5d4c997a7661a41a4c0ca41cbdd18d27e", + "dist/2024-04-29/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "0edfdb6f6bb2a4a1a96a5e95cec897c444c936e6624bb4a530ffed4847b97445", + "dist/2024-04-29/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "70c264b7845febdee45d0c6e44b65d47ba7f367ef33ec906a9fd7f992ba7cc13", + "dist/2024-04-29/cargo-beta-x86_64-unknown-netbsd.tar.gz": "f1bd6417a54f3b53d572ce4af799242db7c11265c71201cc09c78d71be38c13a", + "dist/2024-04-29/cargo-beta-x86_64-unknown-netbsd.tar.xz": "53569810469c483785333759f86434706ee5368d5e18270ee13a17817ad57d40", + "dist/2024-04-29/clippy-beta-aarch64-apple-darwin.tar.gz": "7b693bde61a090854527a145455ff774314c65ec0cd47d25a19c76c6a166d96c", + "dist/2024-04-29/clippy-beta-aarch64-apple-darwin.tar.xz": "2494e9fdd8d342b6bc3e55eecfd555c43e3cca8421f3236df2d5a366288fec62", + "dist/2024-04-29/clippy-beta-aarch64-pc-windows-msvc.tar.gz": "90307f09c6fcb0c1fbe3ad1522a5381a17e2f69637c6d00f4a2cb5f3149bf736", + "dist/2024-04-29/clippy-beta-aarch64-pc-windows-msvc.tar.xz": "f7e0dec4a4862bd85d894252366152b3b6a7627e7e5a25ce323fa2db3bd87c2b", + "dist/2024-04-29/clippy-beta-aarch64-unknown-linux-gnu.tar.gz": "7c719e38f2a1030ae61985205df52f9a0c37b659463a5e2dea8e60e632de2d73", + "dist/2024-04-29/clippy-beta-aarch64-unknown-linux-gnu.tar.xz": "181ff4ae6adced6522a4c29869be3cc5dac8b961c7c88f2957cd31f831490807", + "dist/2024-04-29/clippy-beta-aarch64-unknown-linux-musl.tar.gz": "4e0e63e6f200386995e369a2673867d1bc3005d51d6a57c00ca80056dd85316b", + "dist/2024-04-29/clippy-beta-aarch64-unknown-linux-musl.tar.xz": "3d5b22a13aed6821482e60d9cc8571e2da9d95d82104284b77c56985a35a9c4e", + "dist/2024-04-29/clippy-beta-arm-unknown-linux-gnueabi.tar.gz": "9f788db76a5d55b3ecdd04a70b0e2be466959f76ae9fd3497ca2c503504e0c03", + "dist/2024-04-29/clippy-beta-arm-unknown-linux-gnueabi.tar.xz": "f4d8fc103807fba61d71d88b8e25a7016bfbd1a2905330f9a9fb3d7ba082713a", + "dist/2024-04-29/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz": "d61bec3d017dd0be43e48350190ad18c0a0269e43d964600b62e1f7fd4f84399", + "dist/2024-04-29/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz": "c00cbdc41a4da0c313a1a282b0158b059dd34f640b582cb7ca18e3d290ca8fa5", + "dist/2024-04-29/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz": "52143a530ca5274fbb760beecddff16f860ea787443d3dc708dda7c8f32ca9bd", + "dist/2024-04-29/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz": "c6d2dfeac6f40811bc9b4cec3c23f9c3bb46f761e006257b9313aa7c1a647b5a", + "dist/2024-04-29/clippy-beta-i686-pc-windows-gnu.tar.gz": "325d39e426b1907fa17d93c0752d3d73bd95750f4f967c2a84aab2c5dac8a588", + "dist/2024-04-29/clippy-beta-i686-pc-windows-gnu.tar.xz": "536f591d4da455302029384ed196932d71119ef0160ac5415617d6b777c51123", + "dist/2024-04-29/clippy-beta-i686-pc-windows-msvc.tar.gz": "c3684c9bf471669d444853bf484880d17e150ecb0e7505de90883382023e343b", + "dist/2024-04-29/clippy-beta-i686-pc-windows-msvc.tar.xz": "0b00e6132f73d5dc762e359b0005fceab0cf7b01337d8f4aa9eacfb4552f9245", + "dist/2024-04-29/clippy-beta-i686-unknown-linux-gnu.tar.gz": "c91c1eadfc4cbae360a0eecf11c32d2509b68aca86c7b1de3b102944f43e1511", + "dist/2024-04-29/clippy-beta-i686-unknown-linux-gnu.tar.xz": "6f7a5a287dd6226c203bb674ff02ec773e5d0813091b2af744b88ecd6997a304", + "dist/2024-04-29/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz": "58383f094995823ea6db6a87b9ad4b33bdae2264d29bab88ab71ec60ccab3b93", + "dist/2024-04-29/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz": "dbf4680a6fd4dca54acca5503a7fd94502b8e85819bc02346ae9cecd275e4514", + "dist/2024-04-29/clippy-beta-powerpc-unknown-linux-gnu.tar.gz": "e28eb32cda42654c0f0247aa8e15f01f73770b36f7626c8d6f1b7659accc56e6", + "dist/2024-04-29/clippy-beta-powerpc-unknown-linux-gnu.tar.xz": "fcc48a83b748e1e46f9daef40563f8e5abbb0e3f014a168b04f3c700c2ace2b8", + "dist/2024-04-29/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz": "b626faf3275fcd196cd627e8a36c67721bae16a56f61cd080c79d137b3ec7737", + "dist/2024-04-29/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz": "2c599d2dc719d69f67625f3c6573fcc4f1ea3266801557dd3892bdb7c761b4cf", + "dist/2024-04-29/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz": "0bc1f546fe0cef2b9516231ab608de68d55f72022fbc9ced5101b600e005f8c4", + "dist/2024-04-29/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz": "993294f2ae5202785ab242c1c6567df9c8ab1ef44ad35748c526b7fe854fb94e", + "dist/2024-04-29/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz": "210a4f0d208e0c8e13a57fb3b3e6c98ab5f620e4988d10a127ff1424ac1d5ca9", + "dist/2024-04-29/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz": "f10f7df41a13ee2ecdc25d60e697cba2342129a912ef20d8bfca5f611a9ec97f", + "dist/2024-04-29/clippy-beta-s390x-unknown-linux-gnu.tar.gz": "3e24d2af65f0c9667c9997ce091711b2be48e673de3707cddfd8cda455dfecc7", + "dist/2024-04-29/clippy-beta-s390x-unknown-linux-gnu.tar.xz": "0e7b8fbd0207489e38c78c2ae1aa0df4fcbdd84741aa50a86379e4d7ede286b1", + "dist/2024-04-29/clippy-beta-x86_64-apple-darwin.tar.gz": "9c0c47fd97ce72abcd6126315834c62aa7297fe09d447ee4cefa1eb46a116326", + "dist/2024-04-29/clippy-beta-x86_64-apple-darwin.tar.xz": "49dd65c5340fd804399edfa2402cf255fd9bfce1f4aa7fbb3c193c11bc03f8af", + "dist/2024-04-29/clippy-beta-x86_64-pc-windows-gnu.tar.gz": "6c1c3bdf097a1846ae08b098c555c0c5e9e9b646c744d6bb5a855789196b8bf6", + "dist/2024-04-29/clippy-beta-x86_64-pc-windows-gnu.tar.xz": "0a7319d1062f73af1c8f0efe6ad970d10d02259162c5bc84bb1f3a10f3911bcb", + "dist/2024-04-29/clippy-beta-x86_64-pc-windows-msvc.tar.gz": "52fef3f8a64fa58934a633bd4944e8ba9e15f2c2766d0f302dea1a6523864dab", + "dist/2024-04-29/clippy-beta-x86_64-pc-windows-msvc.tar.xz": "8fdbe7590e62ab68a2e463b14da2595e8c4592744f578a813f64d430ed7db4b6", + "dist/2024-04-29/clippy-beta-x86_64-unknown-freebsd.tar.gz": "509bf535622bd26385184ee0c17e4e27a5061a8aeebf5759f24bd578692b2f5d", + "dist/2024-04-29/clippy-beta-x86_64-unknown-freebsd.tar.xz": "2fcd10ada329ba7633616bebc584dca13f11c465e7cf513e76efeb0c3174486f", + "dist/2024-04-29/clippy-beta-x86_64-unknown-illumos.tar.gz": "ea8cea0d4a2379bcd0693f6174b25bc1f90a016dbe8280159cbb61d859806fb0", + "dist/2024-04-29/clippy-beta-x86_64-unknown-illumos.tar.xz": "5a243df8d1345db6bd18e4386ba628e6d302bce1cc572fb447cca4264fda3ee9", + "dist/2024-04-29/clippy-beta-x86_64-unknown-linux-gnu.tar.gz": "2ee560d3c1e306e103eb06d8e8033cd1489b3f6ff9df3bd8a95e25e977befa27", + "dist/2024-04-29/clippy-beta-x86_64-unknown-linux-gnu.tar.xz": "aaf6e54184a65ad6592bf03955a84ad12b561afd86064b1ac5fa03cf637052f8", + "dist/2024-04-29/clippy-beta-x86_64-unknown-linux-musl.tar.gz": "1b3877424a0a0eb507675a50e9d2c793f00ab85f6f12b1e27f871331070325b8", + "dist/2024-04-29/clippy-beta-x86_64-unknown-linux-musl.tar.xz": "6df5eaae5afb64557ba5c3a53ee3e56dab85455838a6044c7671c1180acfeaf9", + "dist/2024-04-29/clippy-beta-x86_64-unknown-netbsd.tar.gz": "1ac05ed7b607fff8b77ff203a663e9f4f2487779bc25e2dcd454cdf5b7583328", + "dist/2024-04-29/clippy-beta-x86_64-unknown-netbsd.tar.xz": "da502375b3cee8b254ab5999809f522692c2d1d90ea0544ad03c0ca514c65ef4", + "dist/2024-04-29/rust-std-beta-aarch64-apple-darwin.tar.gz": "2fdd35ca3b3e3d6f548f11c93337f5bf2e3c088bc78a79881e6f8e230b38b9a5", + "dist/2024-04-29/rust-std-beta-aarch64-apple-darwin.tar.xz": "bc16b3a1ab6ed69f0121a117c50cbcd201500dae4d72ad0dab148913d04cc529", + "dist/2024-04-29/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "9375c786703c17baae1c2066f8d972ac316bc840e478ecd1b94288a1d428324e", + "dist/2024-04-29/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "50d6818a8dd3ab7a3ddbbd7a062b538d9ff3ceb6eada031d1c22ab1dc7ba512c", + "dist/2024-04-29/rust-std-beta-aarch64-apple-ios.tar.gz": "56c3a01e8fd5c2ed75df811993b0b724709fb5473cc308ac09e7f5644468f751", + "dist/2024-04-29/rust-std-beta-aarch64-apple-ios.tar.xz": "3527d1f2c99c806479fb4b3801335dc921b514f171b82cd252cbbfc9ed30b163", + "dist/2024-04-29/rust-std-beta-aarch64-linux-android.tar.gz": "bf8cae7c66489f1aa27f1dea1b37f0d0ae514a6e21b93ff2dc6400dc88feca03", + "dist/2024-04-29/rust-std-beta-aarch64-linux-android.tar.xz": "46799f0bc1b3c13877f6cb732774cb3b33e0d8a081bfb56d0f877e79482aa1de", + "dist/2024-04-29/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz": "9f90fadab5104e1d415edf3b4edfaf7222f9f0d55f849851efdec74ffee16f8d", + "dist/2024-04-29/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz": "87ed6774202b18691bd6884df6944c7e9fe9c944b57a2837e7a7647518bf94e8", + "dist/2024-04-29/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "4a0692ad28f7f130b472ffa4aa766b745ba01fb75aa921f2da6622c9c68750df", + "dist/2024-04-29/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "a3d45962489a1e18a87e567cbbc8d3665f38809d0ad2ef15bcf0ff9fb9f470a4", + "dist/2024-04-29/rust-std-beta-aarch64-unknown-fuchsia.tar.gz": "c724f4eb135f73b9c79618f27a1ab35dc7b9d26ca62ed796accce68f9e747a66", + "dist/2024-04-29/rust-std-beta-aarch64-unknown-fuchsia.tar.xz": "8eab25782d16bcee75f86ecbb826346beb4a7525b220b45b3ba05a567c6d4391", + "dist/2024-04-29/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "33ab1f8410edf590570d7468dbe2ebb5a0907125bbc8d360a928dcb355f0d0e6", + "dist/2024-04-29/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "d3d870209a55ac96391affaa347c04f48cf98c089ac5056f340b8bb38bcc8e60", + "dist/2024-04-29/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "4d2bb72b898c30a2fc8d5d3333c2e99a8e30c15891fab641b6a519dc9f0cb611", + "dist/2024-04-29/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "fa343e6b6110fcd0c5dae4287ff1a799de5d7e4a805dbf4e9a034bbaed2bf269", + "dist/2024-04-29/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz": "f1ec4139783169fd83e1b0184518ed25d26cee7b21f196deecc74e83a1d78725", + "dist/2024-04-29/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz": "d100be2f6f0346c4b1f5b41aec0c13a47426bf4d49127f2341c8332903e4e782", + "dist/2024-04-29/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "bab6051e1071a58cd126580f6644decf16edb4473fe4be6a34791610d820a294", + "dist/2024-04-29/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "d9b68f06ff23629063e92dfc42aa3115a858238d368e4b52b35c1ea4491b1402", + "dist/2024-04-29/rust-std-beta-aarch64-unknown-none.tar.gz": "96804c2d9accd3242bdc22dad688b2ccee071952477b9c592f099377aee6c591", + "dist/2024-04-29/rust-std-beta-aarch64-unknown-none.tar.xz": "3fed6812d84bdaf787e85c37e23ba729b81a6d25a2b33fed75320e66e6641c89", + "dist/2024-04-29/rust-std-beta-aarch64-unknown-uefi.tar.gz": "8da5f301bff35fc067ec7cfb878ebfa5607af7dbc276a6b34a77404432c700d2", + "dist/2024-04-29/rust-std-beta-aarch64-unknown-uefi.tar.xz": "80d643189dc9af98b6410a01261ce6ad34b1325f3aebf3ff61fb43f1261b41ff", + "dist/2024-04-29/rust-std-beta-arm-linux-androideabi.tar.gz": "2e86b54b0d1f7fefead11d6383bdc80fe0a7b3ccf58381d2a731e6f1c62926de", + "dist/2024-04-29/rust-std-beta-arm-linux-androideabi.tar.xz": "9831a0270457cad2798b5ae4fe956c257c7e10ce5ad211793dc467577cdec29e", + "dist/2024-04-29/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "f96bc303c0c2be9cf589f00aa63b2cf3fb8585ca9dd8860fe525821bfa1fe19a", + "dist/2024-04-29/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "e57a053b1c2bb6fad93dfaffedce7f48fa292196fc8ba6fd2f0c74dc810a13a9", + "dist/2024-04-29/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "49b2cb2ba5296871b5fac5ad9a74a2891e8b78321078a455ba4a65e003bebd40", + "dist/2024-04-29/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "0f9c15d834a9d282a4018934759f7b48ef3d275e09679a68c5fd1b3f047d02e4", + "dist/2024-04-29/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "e59f92827241e670c1aa92b35235ad12340869d59327fb83084b5f4149acbe06", + "dist/2024-04-29/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "ad1cf96bb1fcceaa016e29e8ad34b4cfd711d2e0bd7cabb9cd7cc28abf64d894", + "dist/2024-04-29/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "14a6d318af85bb9fa5c229e45a88a32a71f44ed02cd90a24bb67921eb64dee41", + "dist/2024-04-29/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "ed6b48502ab9169818bceb300b4e6b4fd63366ad5808b047bf9988dae04c2729", + "dist/2024-04-29/rust-std-beta-armebv7r-none-eabi.tar.gz": "345e8a023be55e3b88a0c2677ea28c7bb4fcc5f3ab707638de76065c7592c2d5", + "dist/2024-04-29/rust-std-beta-armebv7r-none-eabi.tar.xz": "6d9b11d08f2d62611327a893b45ba07c36df11f077250496ab0881eb7ac84c65", + "dist/2024-04-29/rust-std-beta-armebv7r-none-eabihf.tar.gz": "a2ae1bf003a8a12b2ecb6bde9868a978820f184af523f0e4c3fc935edd509423", + "dist/2024-04-29/rust-std-beta-armebv7r-none-eabihf.tar.xz": "3d1dcf8308f9d4590b429f6abbf8f42f04496ab490ccf4ed8c9e381e6d886cae", + "dist/2024-04-29/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "a54106d27e4ce97463e7867ceff9dd22ba456f840ec23229e6909b37d48ad554", + "dist/2024-04-29/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "e6abfaa0905a00efeaee85b9f93793bab93e2cf4e172c9d829c5ba85006c688a", + "dist/2024-04-29/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "cbed18e5dc61fcecb2920affc3890c3b8ae46b7fe5a80b3288689e18d490f3f4", + "dist/2024-04-29/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "2b58bb0dd5cd2c5f7f93f4c6e9135090b931e0ffa27ff9efe2b8ff9fbbb7e48c", + "dist/2024-04-29/rust-std-beta-armv7-linux-androideabi.tar.gz": "6a371c2ececd349dfa76a02563069912fc91577ac4446d36c22f96723d7f5e9f", + "dist/2024-04-29/rust-std-beta-armv7-linux-androideabi.tar.xz": "9325daf41ddab02fa845971c10a5e0538a18c7bea14e66fa0f5f6fb16654c7ae", + "dist/2024-04-29/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "7f5ba76cfb7c85333c8dab76fb4ad3f12ddc254b95f9ee07fadb8e1270a4f767", + "dist/2024-04-29/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "f853b7f929b7a309ed6c08ff8c57d583ce0ccb19270674fb30e63a873834dc87", + "dist/2024-04-29/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "0680005d0a12498b687afc583d4f36bd67d0877cd9d3323bfd2df50d15c27afe", + "dist/2024-04-29/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "a494b78fcad01c83df9522d460ac2d35d2d00736a921381f2c611dc516edaa16", + "dist/2024-04-29/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "cfa555db31b5470e878b0f53d86617e7342e8bf018fe62cb0271dfe13db95f51", + "dist/2024-04-29/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "0a8ccd6d88cbe79a855111fbda45aa1a728de655b6927f3d429d901d2afc6503", + "dist/2024-04-29/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "eac53424001c884a540c42f0b68447349ec5d0601a030c060aaed76d54895728", + "dist/2024-04-29/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "42d78fca62361ff28db5bc43bb01cef7af5c6f4ab2110fe6170c3dce4707aab8", + "dist/2024-04-29/rust-std-beta-armv7-unknown-linux-ohos.tar.gz": "c88de9f2e667da73177fb9c9309d7f1f467e31c18e3ae50d722c71ec8dd876a4", + "dist/2024-04-29/rust-std-beta-armv7-unknown-linux-ohos.tar.xz": "24b3c04a42d511cdc8c6107b597be38981114f0574eced493d0e90fc748094bc", + "dist/2024-04-29/rust-std-beta-armv7a-none-eabi.tar.gz": "cd4ad182a098c61550265879ccc04733c39110827f7ef62eecfb8c120ae4ece8", + "dist/2024-04-29/rust-std-beta-armv7a-none-eabi.tar.xz": "8499a014dfdf448f474a58f148784c2eef245dc909587d876d2fb9ddc6a4ec3f", + "dist/2024-04-29/rust-std-beta-armv7r-none-eabi.tar.gz": "e8e1870e5b12b3d8643d712efb91eb86b2081284cada4a140c1526692ab183c4", + "dist/2024-04-29/rust-std-beta-armv7r-none-eabi.tar.xz": "d6029121eacc44bd4dcd9ef6dd3cd0d775cb6e9a3d99f3d62d746fcbf8981cab", + "dist/2024-04-29/rust-std-beta-armv7r-none-eabihf.tar.gz": "1e0fc42c3802e205130c01ca90f92d793c1c5427b34da66fe77b97cf67b4a5c1", + "dist/2024-04-29/rust-std-beta-armv7r-none-eabihf.tar.xz": "4c8cfdb11bb686111fa4842d13430c86d9d14ada30e9df334b3777fe899233e0", + "dist/2024-04-29/rust-std-beta-i586-pc-windows-msvc.tar.gz": "ff895c1b39b84587f10903f4be13d275b545e690da6761190d12c01acc25c6d8", + "dist/2024-04-29/rust-std-beta-i586-pc-windows-msvc.tar.xz": "fdcbcff7b740235bb16e44174fff9080a7c0a31be358c8abc41805c02c20c3b2", + "dist/2024-04-29/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "6b227f3b9001e148b66b7001f753a6f88fef9677e39d8fcf4d9c35fe8d345568", + "dist/2024-04-29/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "1e29297beb8de3778ba958731294823d9a93aac1e0d8833abc5aa99e2935965b", + "dist/2024-04-29/rust-std-beta-i586-unknown-linux-musl.tar.gz": "26481ad5f22a319830d42f69b1c0195bd65900ebe112e659432334b3468f3d0e", + "dist/2024-04-29/rust-std-beta-i586-unknown-linux-musl.tar.xz": "c8a837e0d9da8ad976fc1539541c085365aac9dd28b34e4a289d38a823d1b065", + "dist/2024-04-29/rust-std-beta-i686-linux-android.tar.gz": "f05e28a52f17e22f36ffc70018012a1fe6a07f4b461e774b36464f32bc8f8dea", + "dist/2024-04-29/rust-std-beta-i686-linux-android.tar.xz": "f9501b2691c51e54a6f4cc6fb72e41901eb551d3a7be5f82a94ce2d3e217828b", + "dist/2024-04-29/rust-std-beta-i686-pc-windows-gnu.tar.gz": "8d9a782d4f7450bca536aab45147c6ef08bc3847b43fdd171c6449e29762eda0", + "dist/2024-04-29/rust-std-beta-i686-pc-windows-gnu.tar.xz": "4008712e03fb6494eaba3d79051c5e3fdd93d4c52ae8d86cf8f344b5f051cbca", + "dist/2024-04-29/rust-std-beta-i686-pc-windows-gnullvm.tar.gz": "cfb23242e495834a3d0f7ffa3da4a0b206dcae35872b1455b11faeee5511ba5f", + "dist/2024-04-29/rust-std-beta-i686-pc-windows-gnullvm.tar.xz": "95415742c0171945ffc2b67c913ebd1330e29634af238f5ccc843a965340374a", + "dist/2024-04-29/rust-std-beta-i686-pc-windows-msvc.tar.gz": "e9354d69e39ecfac1d2928664d17d73f808256a4076b849171a9667705c0aa08", + "dist/2024-04-29/rust-std-beta-i686-pc-windows-msvc.tar.xz": "a34bb0a91170d84195f35ba52afa4c9be8a2f2706dbeea02bd6e8908e08ac65e", + "dist/2024-04-29/rust-std-beta-i686-unknown-freebsd.tar.gz": "d65f286de399ccc9e9acaf7a4dc4f885357c750231d54a144ba9a59181814f11", + "dist/2024-04-29/rust-std-beta-i686-unknown-freebsd.tar.xz": "4c93a7da70a69b2ebbac01df64af16344e523d16470b29e57237b1d0925f7721", + "dist/2024-04-29/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "1b978bfd1a9234be7ef197c8c98c5a6b625f6fbb7b0fca58695986768bdca176", + "dist/2024-04-29/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "98d4eb5b89a593c8c4f86244c9a7c737d9c18c0168aebe5923b8d9145adcf89a", + "dist/2024-04-29/rust-std-beta-i686-unknown-linux-musl.tar.gz": "dbf9b3c5b54b3eb0727f976f5632c5b0fcb2f90ac7453962d6cef20f7dae4284", + "dist/2024-04-29/rust-std-beta-i686-unknown-linux-musl.tar.xz": "f209ade093753342dda6e710ee832a538dbdaa08a24d606f9a2a1bc59b83da29", + "dist/2024-04-29/rust-std-beta-i686-unknown-uefi.tar.gz": "3c3ca7f34569b2c70c6b223754418a535dd7dfa087ab6e28ed2ec78d20065887", + "dist/2024-04-29/rust-std-beta-i686-unknown-uefi.tar.xz": "72a7cd0f430ab40d80e93f409b8e26a181010ab4bb75d151e829d51ccdcf8c62", + "dist/2024-04-29/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz": "b7dfa59bb05cf806c87854d6fce5ef0f160697052fdf6e5a0cad121499108608", + "dist/2024-04-29/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz": "88bc22f68bab3367cdfa91676418ce1ffc0ec002afb32aed7def880bdd4be402", + "dist/2024-04-29/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz": "d61019048b941064a99d19e46ff3236a88a2e8fcfb963cedd1d9d1c47963c170", + "dist/2024-04-29/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz": "7474bda08134c676d74afe5263317af3f271963d8ceaa5efbfa1b657f885c572", + "dist/2024-04-29/rust-std-beta-loongarch64-unknown-none.tar.gz": "e089c77d433d838ca02d7531d6f4a1770fb4a0568acbd96c8f43034d76f2990b", + "dist/2024-04-29/rust-std-beta-loongarch64-unknown-none.tar.xz": "364ae6c89c7a930098286e55193d2f5ee3d5ea80b7cca73046e41725f4a8a2f9", + "dist/2024-04-29/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "c17bfad87d16f3a8d26646525dc59a352718db9e7572acb583b68a18cfdc338a", + "dist/2024-04-29/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "f5c4ecef1c08d19ba6fddbd359a0ce94e46888021cae057fce969276026d086c", + "dist/2024-04-29/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "3e7e13b0d2e804d228e1e3a9dac0205d294ae29dcc37132f15fb1e218861eb39", + "dist/2024-04-29/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "ea31b7678e6f64c2f9c28a9af120be04ed6f2a25a496e40afbf6e9aa0dd20b60", + "dist/2024-04-29/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "f0e1b314c3d5ad1676c68c112581dce62fa06ad557cd5f61034e147b064ed270", + "dist/2024-04-29/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "8ab7bbea6e2f72df1286facc7d306d01809a4dd9f8901dfdec7e50b594658d49", + "dist/2024-04-29/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "48f6abda1c7dac185858744aa2cdc3513cdfb6552535282ee83cf9c5365573c7", + "dist/2024-04-29/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "d920d97f15b56ba6ea81e08b3c29dc7f44f5f30b7513c53446edf95843c332af", + "dist/2024-04-29/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "0a198a770f6e6043e923b0ab1a508fd8b190612d0370c33c8dd2c5f63b6f19dd", + "dist/2024-04-29/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "424a93313cfe2d85acf956be3d9ac71ea8e34ee61617a550ad6ff5360e1dff52", + "dist/2024-04-29/rust-std-beta-riscv32im-unknown-none-elf.tar.gz": "2e2b0a8e41f4ea774d665d6248cbc2fdbe3e582206efeb87d250786ebaad0b1a", + "dist/2024-04-29/rust-std-beta-riscv32im-unknown-none-elf.tar.xz": "2da372c091017b7096e473e5c7016a504d2e041e14173d2520086cb43e0a615a", + "dist/2024-04-29/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "69d3b21403181b2df14243816388169db2466477ec34bcca5693fb017703686c", + "dist/2024-04-29/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "281b9c20f8641a3d1b349e762b7f713fb0b91da0d21eec798e639e36a0ea3dab", + "dist/2024-04-29/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz": "dd9bfd3fd8446d35180fe781139dfb4e04dd658b112eb2a749e8f4aea14f0271", + "dist/2024-04-29/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz": "b1366375e0c5f53da581741dec91972b0c46d7d466052539207e8feaab0ba3ec", + "dist/2024-04-29/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "7c6650d8cf8abd51547010e8211af3ef3195099ef43a563460ad4780de20ba17", + "dist/2024-04-29/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "bab46f3c0078ce346de563bb7a248ca92f15dbdc73bf5a3bc520486118442320", + "dist/2024-04-29/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "01735b4ad5bc0a53087dd0ccaef2cf174b27e45bf4d2e3c15e64f7522f059c63", + "dist/2024-04-29/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "0bb272c2c235583ed3e9ec151b3bfc601f8cd07822c2fe47a1258b358be507f0", + "dist/2024-04-29/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "b2c7f8ee0efe6d0812e4b5dd0979f60f105b84d34d4f600ef75f2eacd954893d", + "dist/2024-04-29/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "0d5301fc553a6911af6643ab7f57b6438bf649ffcd050d486278c0c5fe38eeba", + "dist/2024-04-29/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "0d1d35ecb88ee717720ad8e74bd5b602fd6011fe321baddb939f3b161e9cd8c5", + "dist/2024-04-29/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "a5cf0b98596e68e6f72be2e83c61b8aaa19ead42f248ee2408a3b8f4e97a6657", + "dist/2024-04-29/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "629ed749cdae110668ad9ddbc5c61e99e8d400f3dd0981146c3820deadc360f6", + "dist/2024-04-29/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "192819438ed27a565cdb67b51d2f5caeb6ae258de86191d6922574327f132acd", + "dist/2024-04-29/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "84286f6cf6f00f3c92dc881f64a31e1ec5910102d8d3d4faf6fc7e2ddf1544a7", + "dist/2024-04-29/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "304b5f876b47dcbb7c3483c49295b822e8ba83234bb568ce67896ae4773ae2fa", + "dist/2024-04-29/rust-std-beta-sparcv9-sun-solaris.tar.gz": "25062159b859e21dda76ca22d4a31d3aba4fcdb0def78bc5b5cf9887c07c1be9", + "dist/2024-04-29/rust-std-beta-sparcv9-sun-solaris.tar.xz": "5d557ee86457f288462603fe53bcc2e092d84faee543659419fa68c1bd88f554", + "dist/2024-04-29/rust-std-beta-thumbv6m-none-eabi.tar.gz": "a9663048aad82ef832b2cf82fa9fb94be047f77e283e8aa3e2df6ad957d0782d", + "dist/2024-04-29/rust-std-beta-thumbv6m-none-eabi.tar.xz": "4c4b703a846b4123d09c1eace6322e82784a004b278f1f3b1ca1279e96207f18", + "dist/2024-04-29/rust-std-beta-thumbv7em-none-eabi.tar.gz": "32907c33f240abb1cb17ac438da42c5fa3932b270ad08fd6914775c5b59a02f5", + "dist/2024-04-29/rust-std-beta-thumbv7em-none-eabi.tar.xz": "112583227d2b6abfef6eeb78d980bf2efef392f3b66e433c4959a642d72ffc7b", + "dist/2024-04-29/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "7ba0084527a18479c4b6f6a0dba8ae23a0ed50e9fc5fbfce23cae1babb5a1e12", + "dist/2024-04-29/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "49eb4e2efe3a76713ce1fecacaf915717eeed8552912b92895c7fee068a85a36", + "dist/2024-04-29/rust-std-beta-thumbv7m-none-eabi.tar.gz": "518a532b52f2dad2825158614cd00b12aac6c6e1983a1ad53e2b0e26d1f1b845", + "dist/2024-04-29/rust-std-beta-thumbv7m-none-eabi.tar.xz": "2895e5796a29fd016462694d880e38eb191cb92c9bdb14414c1d6e63b23d3394", + "dist/2024-04-29/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "2af590c063344c4c3f65d704fa255232b5f5954872d03c4c55d48662cbe6bb17", + "dist/2024-04-29/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "a09df5f38183d9fe6116c807619f812410763ddedf06055bfe8040b5794104d3", + "dist/2024-04-29/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "eac22c4972bde3a57cf2ec4e31b43db3c4b7d961ae31475d8942e898c07640cc", + "dist/2024-04-29/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "104f2c6490e30cc47833edbd806c2efe6256d1194600b2278339612f94704d45", + "dist/2024-04-29/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "b3c9c9d7ce8c1db6f20e8ede542e67aacd6047c52882a5d06c4f96a40a7304d9", + "dist/2024-04-29/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "76bfb114bc7674792934a4892d2db41fdc8f5bd30c3aa96c43e8055199157476", + "dist/2024-04-29/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "1308335fe80dcafaba511ee589959d461145533de5f76118fee29a7e9a15841f", + "dist/2024-04-29/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "cb8acdb8920983c03b9495cf3506a3014384b4d2f6a53e7907924d38a0baf7f0", + "dist/2024-04-29/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "9dd2e5ce7534ab4fbb93ff652196e877f4e9eea3863920c3d34a05d9a3598c81", + "dist/2024-04-29/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "4b6e962facf7c54846965a8d6880e4a980804459151f2e22ac5af79bc79e26bb", + "dist/2024-04-29/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "731603392b6e3d36b3a4956928d084e293ef18c8b8593efa756e753a2a309709", + "dist/2024-04-29/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "8b681b3af47855eb63c4ffe06a2bc6bc4f365354ffbc171ce8cbd8c2a3588a07", + "dist/2024-04-29/rust-std-beta-wasm32-unknown-unknown.tar.gz": "7b87e59391493c3147c03794061111e25bdae669aea58190a951cdef111e75e0", + "dist/2024-04-29/rust-std-beta-wasm32-unknown-unknown.tar.xz": "d15eaadb101027906c2fce15b95a3f820bdbc4cf145b705bafc2ac5291289c3b", + "dist/2024-04-29/rust-std-beta-wasm32-wasi.tar.gz": "07390ec742b79ec11b2c3ec65f60efe5d7c616f50c33058fce346f6e9ad21af3", + "dist/2024-04-29/rust-std-beta-wasm32-wasi.tar.xz": "79e34d46621c298cadb98c00ce3b25d97474aec300d85255153b47e21b7bb744", + "dist/2024-04-29/rust-std-beta-wasm32-wasip1-threads.tar.gz": "b916dc9051b0278f820ea0b093db3ecae2e27de641ef67a9b508df75dc92c938", + "dist/2024-04-29/rust-std-beta-wasm32-wasip1-threads.tar.xz": "2867922a39da3b02ebdb93fb78b010695daf468f87485ad8ab79c7f3eeb18b11", + "dist/2024-04-29/rust-std-beta-wasm32-wasip1.tar.gz": "792b718c0a72e97ba85a17ba67ee09e55b85de829fe4021f828ce54ff8cb31e0", + "dist/2024-04-29/rust-std-beta-wasm32-wasip1.tar.xz": "abff86499119bddfeda9059004549941dbcd3d911702d4a9c198b94f60e60f4e", + "dist/2024-04-29/rust-std-beta-x86_64-apple-darwin.tar.gz": "0bcc7698efafb42a37f20815f5660e39829a42a2776304e7129d0a4ec0c7520b", + "dist/2024-04-29/rust-std-beta-x86_64-apple-darwin.tar.xz": "c437626e250b0d06c05dc828ab81d0d2c543ffce4b100567910508974ea50045", + "dist/2024-04-29/rust-std-beta-x86_64-apple-ios.tar.gz": "7c98c9f491bfc837111769a45c10ce2f1ef73c22377158ef9ae80b38034892c0", + "dist/2024-04-29/rust-std-beta-x86_64-apple-ios.tar.xz": "f4bda724e6e382e02ddf4e4e7a479120420666a5a1ad3c87a85d4d3c763f2cb2", + "dist/2024-04-29/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "01efbb2e48045318e18bfc7b6c190b461a219e81fc1cca6c855bf0c658aef556", + "dist/2024-04-29/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "9bff316c6d2fbb3c0889f9ffe4eae496b293fb3afaf8d597155e6badbf0c6a8e", + "dist/2024-04-29/rust-std-beta-x86_64-linux-android.tar.gz": "5da713547a8af2c86da7db5d8aa4c27188dea1089fded81ffbbeb0f78952a10f", + "dist/2024-04-29/rust-std-beta-x86_64-linux-android.tar.xz": "9d6a45d6af395360c63ce97bcfc2f9a2967c708afcd979f17fa447239703a92b", + "dist/2024-04-29/rust-std-beta-x86_64-pc-solaris.tar.gz": "d1a71110bee002c8edfbcc00e0f5eede5afa005b09944bb2cde469c658049e70", + "dist/2024-04-29/rust-std-beta-x86_64-pc-solaris.tar.xz": "6b8d18c83b9fffdddf9e55c807dc7d5784cc6d7ae90a57c29b87d707f0656964", + "dist/2024-04-29/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "28921ee14426f54aa09523547516437130654b2d9814120d286f209666c88533", + "dist/2024-04-29/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "7c3125cce30978ca2619e9aab150cb5b9b2535fbb6274d4ac1b1d4342c7b0220", + "dist/2024-04-29/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz": "ee5c237f092f8a4ba797c4c7769dfd4da81b5c86d2f4b88704d127642d222a22", + "dist/2024-04-29/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz": "30c84b04bd2d4d33abf1875cfee5f227ef6484edc67b3cc4c9c96d92c8406d6f", + "dist/2024-04-29/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "81274050e72c5a8ffdead83f7be62434f35a65517a1b3c6f7d9d14d0d59da710", + "dist/2024-04-29/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "215e20c78a2a4edf9b8368a29a09af5f4cf8d0edd1995de3bbf2eff01127cab7", + "dist/2024-04-29/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "340131cba121827a9753e19cb3a4b9ba2ebe30569fb20d7f9300b4dbe2a15cf4", + "dist/2024-04-29/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "69626178bc5309afc8a02c941bd77e70e1aa6917ffb6bf0d67a57d921b5c664a", + "dist/2024-04-29/rust-std-beta-x86_64-unknown-fuchsia.tar.gz": "22c6c90533dad3a731ad8a6696e6cdc1b15579e25c658fa2b094185e1893934f", + "dist/2024-04-29/rust-std-beta-x86_64-unknown-fuchsia.tar.xz": "30d7ef6684fa98e28037b69d4220cba40489c23e80fe7793c98b388dc161757d", + "dist/2024-04-29/rust-std-beta-x86_64-unknown-illumos.tar.gz": "9d7192d32eaa6b6ccb0f615da0f4cd80827ba6484eabeaf401d8217678f1e313", + "dist/2024-04-29/rust-std-beta-x86_64-unknown-illumos.tar.xz": "7a3fb35e0bb252d5f90773136d1417c26d5601beadb77d6da6f5ad3081977f07", + "dist/2024-04-29/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "e987635519c1edc8a1d147ca4a86283637e4dbd0a49736b01d605e45a3a14e8f", + "dist/2024-04-29/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "c3ab6b97dccc0038c68494b03b6d444d534e447226a2b2e140af54c94fca0b2d", + "dist/2024-04-29/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "72e8113687be8f947c50befb42b0957dd564f01693cf4d68d749a9e074032ada", + "dist/2024-04-29/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "867b24f33b19f40727c71818c8a002718d44d4cd4ceca44314331e19c1adc1a4", + "dist/2024-04-29/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "f9b0fd9605bd4e264f5303bd740d9a0195bc147132969965b221f9da0d7875bf", + "dist/2024-04-29/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "022dcf4887df41d776ba2666858b9aaab479758134a71f7c6b2172ed7c1a1752", + "dist/2024-04-29/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz": "b5ff4a0ecd7e0f71a9557b6096bb907e5cbc8982431f0d9b01d8e1a895d8b37e", + "dist/2024-04-29/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz": "e40d5bfb46aadf6faf849df548154db3f35f356f8b98037a056802a235922b8a", + "dist/2024-04-29/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "57cfb1fa472dd9c01fc0caf605a55b7248375d616acf84ec12f6430d5e07e2ee", + "dist/2024-04-29/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "e4121f060b917c811d971e85ce02495e83150ddcceb2204615edff24bd55bfa6", + "dist/2024-04-29/rust-std-beta-x86_64-unknown-none.tar.gz": "d63559803c8eb47e0d10d9f3a2284477b570a2536bb541762774271451e1f0ce", + "dist/2024-04-29/rust-std-beta-x86_64-unknown-none.tar.xz": "5388cf8ecaa234d507e505e8c6d433c5de8811b2717aa254e4caac9f4aa6cd97", + "dist/2024-04-29/rust-std-beta-x86_64-unknown-redox.tar.gz": "0f027163f37618df4330ecd82afece432b0a509ab20333d7b787c0d139ea89c2", + "dist/2024-04-29/rust-std-beta-x86_64-unknown-redox.tar.xz": "b1c722e894b145c2183183fa58762c64402fac077419dc7874f8b08eee665651", + "dist/2024-04-29/rust-std-beta-x86_64-unknown-uefi.tar.gz": "24e2ac0d44619ef9b76cb1af6178103d65ab12e2677b366e8aee0604798fe5f1", + "dist/2024-04-29/rust-std-beta-x86_64-unknown-uefi.tar.xz": "1d8a45f1bfe6650edc5ddfc8683190eff5a74384abcb2f73eb3d1e88d566ccfc", + "dist/2024-04-29/rustc-beta-aarch64-apple-darwin.tar.gz": "ea113c567692d54983ab6c376761651b6dcf9bedad5b5d822d28c0d0d0733cf2", + "dist/2024-04-29/rustc-beta-aarch64-apple-darwin.tar.xz": "e36363f1ea531d2fd563f471758e387de37a34e7ef6f4c12175979657333c5b4", + "dist/2024-04-29/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "52d77d540fc3f83d82f35f358ccd9055fb75453af3e3bee4b11636742559db13", + "dist/2024-04-29/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "843c56f5431c1feda85ceaeef0daf988e8ae020b3556326fb1f75ea7968bf2df", + "dist/2024-04-29/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "ba2fe37dda1a487a2c75151895f4f6e886e9476a992272ce26e9b5fd7adb11f9", + "dist/2024-04-29/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "ccb7be3935de1920509d2061d38f92f1fb8d2a5dd6cef392492242a929363fa9", + "dist/2024-04-29/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "40636e0936bd311803317825c5fb6b446cdb5536ada1db097b567df04a86d7dd", + "dist/2024-04-29/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "804ef68f24bc0ba5150177d8b8515daa54aa82fcb61472385ef1a1d897c5c3e1", + "dist/2024-04-29/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "a320c2869d1d2c92b698397d4467c8498cad9481f38d28ac810bd165399ca46b", + "dist/2024-04-29/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "7ce92211d87068d9c223806929adc34ca611a1321cd58b5bd81aabb0ec3ff085", + "dist/2024-04-29/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "79c16b902884301882d16be36fe75ecb32a8e49abde0038ce21cfbee883c2c3a", + "dist/2024-04-29/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "9384eb9bdbb585b414b6c04c592a79e90a0c0ebfeeb970e5e1b920cb638807cc", + "dist/2024-04-29/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "ff99de5b819a4fb9adce9386a309b9841bd33632eb7d5079415a6ca6fc86b9dd", + "dist/2024-04-29/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "55635cde13af11dd8cc007d2e0499bfee493bdfba87b6efd7b1fa4115f5728dc", + "dist/2024-04-29/rustc-beta-i686-pc-windows-gnu.tar.gz": "de82ac745275f069225b84574ed145afaf9f54abde5246592e49d5d1cf40cac1", + "dist/2024-04-29/rustc-beta-i686-pc-windows-gnu.tar.xz": "a8a7bf64d33c95a2f94265fba8dd9ac50bbb727f4bc3e79be5bf61212cb5d22b", + "dist/2024-04-29/rustc-beta-i686-pc-windows-msvc.tar.gz": "88967a99c993d6e0c3c7948308510644286ac826266dbd3d89aaa083100711db", + "dist/2024-04-29/rustc-beta-i686-pc-windows-msvc.tar.xz": "1804f75786482946258ff0e827274357c49e90a7f2f568add7353249f2ab78b9", + "dist/2024-04-29/rustc-beta-i686-unknown-linux-gnu.tar.gz": "3cb7e02c61d4a21d8289289b874b25e8b020c1d553e5af950160bffc14f51c18", + "dist/2024-04-29/rustc-beta-i686-unknown-linux-gnu.tar.xz": "2ad4b1311a0e39c359798375912faa91b4e13cd473bd59efd1e4f721777d254f", + "dist/2024-04-29/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz": "ab19efb741a127615b9022dedf1d895b53c69740cc3da745f9b9888bade9d98b", + "dist/2024-04-29/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz": "492cc11d54df410c2547890803930fc65950e6b81ced512e24bef56c3e70f3d2", + "dist/2024-04-29/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "c5a631a41f417336f3f65c85adefd1fb0bacc02465485f37d29fc1223c9f6cec", + "dist/2024-04-29/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "0701183b615d9eec9daea724d4cd8fa98dede2260cfb6b137d6cbf8ad6b29a4f", + "dist/2024-04-29/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "cb70e92d5275862b500614d79eaea3d19319b96798f4850cb19dea9a8038a651", + "dist/2024-04-29/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "908cbe562d82cca1bf176fdc99af867966ea423d244c4a50e14bad19f6878201", + "dist/2024-04-29/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "8580a3eb6d6df1774f4b6ca06dc1195c42b1e2a463488a5d851e99b0ca6d0249", + "dist/2024-04-29/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "2627948036e905f2e280663c56c86c172e2b0d057311ade7ca238953b7e0c36a", + "dist/2024-04-29/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "526e4f129fdb4b2c8f4317c57105a09ff03e71771d6d6bbbc9380917b5440d71", + "dist/2024-04-29/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "fd9dcf60838376478d7cc505ec7fc39f86f9d042646a3b836e9c06825927c7eb", + "dist/2024-04-29/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "664c1255a9435d1ad086329a3c215974b9302d481762240cc9d0328d9f1b8c9a", + "dist/2024-04-29/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "a585ce7684e4174f03adb09df17221e1729e8179dbc91b9a0f8813c3ecc0822d", + "dist/2024-04-29/rustc-beta-x86_64-apple-darwin.tar.gz": "59a1d91009b506a5bce3c276993cb8acfd71f73d01f9eaf4195b36114ac822c3", + "dist/2024-04-29/rustc-beta-x86_64-apple-darwin.tar.xz": "f86f3309cf2784b076f14e7da9e921c294a7701ea92d378c609061deccbc6bff", + "dist/2024-04-29/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "f5c074461409b33a9791325d4014e6861ad36f99b9e48e54ecceb73986450be1", + "dist/2024-04-29/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "045431eec6f839b1c40b5a75c5000f80bd6351274a59b29d962833495324ecb6", + "dist/2024-04-29/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "a3abfb68e60544170f47209bbf048f1374e5bb75901a529e2ac2f315758155f8", + "dist/2024-04-29/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "398c41a3219781c7cf1a907406506526b672abca6d3ab59c30556390a5f992c9", + "dist/2024-04-29/rustc-beta-x86_64-unknown-freebsd.tar.gz": "38895e615efd0bf75ca14b0ab0a085527cca64fae17631d1780a8f51acd26d17", + "dist/2024-04-29/rustc-beta-x86_64-unknown-freebsd.tar.xz": "786f40030dbe5e6897aafe4bda44770920b2010b93fc5ce86574774e531e2eff", + "dist/2024-04-29/rustc-beta-x86_64-unknown-illumos.tar.gz": "7003cab7650dae7e3d29032422a57782a2c146024c437a6466ae1dd2b61a6618", + "dist/2024-04-29/rustc-beta-x86_64-unknown-illumos.tar.xz": "bed3cc10203e8bd4d43b6245928c8a607acc5b6e633635caea45eb4eef4bda56", + "dist/2024-04-29/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "84cdea91c9f1e848ea17f554229ca80d18d093fc609641d8f003c4f2d4871866", + "dist/2024-04-29/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "a20fce7512f7c8cc6230a0f63f12855b04370d25e621183f71aa444c90c36b4b", + "dist/2024-04-29/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "87e0c484ade99efab57c655ef96dbabf7a02314540575b65a14372ab5496c36c", + "dist/2024-04-29/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "469757d8f35c9f4210aefd2ba660ee249e4409d47b908a6c68c1e650ee81ae67", + "dist/2024-04-29/rustc-beta-x86_64-unknown-netbsd.tar.gz": "4a38000480fe78fd5da7f9b71d36f296a6ae103254d932c4de6b902354e86bbf", + "dist/2024-04-29/rustc-beta-x86_64-unknown-netbsd.tar.xz": "45945d6af237fe4c91fde7db02ca19e99bac56a911b8db79be9b6ab8bb3934e1", + "dist/2024-04-29/rustc-nightly-aarch64-apple-darwin.tar.gz": "0b07375a9a6507fd4932a05b5aaf28ed349fe2040103f1cb69c8a2494437258f", + "dist/2024-04-29/rustc-nightly-aarch64-apple-darwin.tar.xz": "143bd7ed3ca7b913ddd0cea7cda8d1a0e4c29cc2ccbb7d29f0e45c2a87c3ec46", + "dist/2024-04-29/rustc-nightly-aarch64-pc-windows-msvc.tar.gz": "9404c111b91fd092367b88adbc37dce10a98c443bd8d9e13a860e1fb4e3af96e", + "dist/2024-04-29/rustc-nightly-aarch64-pc-windows-msvc.tar.xz": "f9f432907c276edcae5ad8ade0264f3c03109be02e791a814edc8ad3d229637a", + "dist/2024-04-29/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz": "33425c90427424f0b30fa2a6331a3b59c680f1c1bd0d8845d7e6bc1e2f80292d", + "dist/2024-04-29/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz": "03792890c64c72f30143849894b15f0eb3d6ad735fceede9092abd900ee733e4", + "dist/2024-04-29/rustc-nightly-aarch64-unknown-linux-musl.tar.gz": "cf6f2bffa0db1b4b9b8e95801bf415dcce413f902e26f4c1831dff1a00752b99", + "dist/2024-04-29/rustc-nightly-aarch64-unknown-linux-musl.tar.xz": "9192fdb668df8d4cab776623db7d01e35af42fea94098c1d4ba53190825d81a8", + "dist/2024-04-29/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz": "a174e7e08da2abc6b84499360670188f5cc61b6d055967e04bf602ff3d831f45", + "dist/2024-04-29/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz": "5a59811027586863852b15fc2b603e7e69b19841f4c10d2527ef1fc5b77d8af2", + "dist/2024-04-29/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz": "645bb5dd7a96bb9292b9956cb9705e9aed2408e47728f245564f1f7404ede783", + "dist/2024-04-29/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz": "1fe34911b082c3a5ca4f24656675c095d2cf56f8005be9ca2517d0ef7d0a2b37", + "dist/2024-04-29/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "f2d6403d81bb0afe2e14956828987a0bb044c95f2d9566e1d792dd922dad7914", + "dist/2024-04-29/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "d93fdafcbbfd50c88c3f4feb4c68b053882ccae02c45e1615aeeae5a86f4aa98", + "dist/2024-04-29/rustc-nightly-i686-pc-windows-gnu.tar.gz": "a9e997b03559b3dfa2a0eba6ed7a142d7651ea7f4ba4e788d9de807b50558e58", + "dist/2024-04-29/rustc-nightly-i686-pc-windows-gnu.tar.xz": "4412b5fbfab8c5b31e57cf8c4ce9a9d13cfc9c0a8174ea1fc8a7c05281e1cb54", + "dist/2024-04-29/rustc-nightly-i686-pc-windows-msvc.tar.gz": "1725c41500dbf6bea554f3d4acaba70167f0e89087aaa3eb3c0f8a99047c55c4", + "dist/2024-04-29/rustc-nightly-i686-pc-windows-msvc.tar.xz": "27db022494afebbe05605f134191e8b2e78bfdeaa638d4215174038ca9dd2fd7", + "dist/2024-04-29/rustc-nightly-i686-unknown-linux-gnu.tar.gz": "dc1a05d49b773dba06808c1c50653ecac506b3433f0f6dfa307109a7c621cc1a", + "dist/2024-04-29/rustc-nightly-i686-unknown-linux-gnu.tar.xz": "cc58ce3af8f5481ada4dc129079cd558664717526b2f7f9a02bde6bafb6f45ad", + "dist/2024-04-29/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz": "34cfe803126ae9218b17adfe833a55c697dfa50729ac83b642529f3682d12d15", + "dist/2024-04-29/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz": "c752dc8962656c09047151fd24166f3134fbeed85006b5d22496691079c7fb9c", + "dist/2024-04-29/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz": "386b086b8aad922050c813dd58bb79a52ef806b2d1413e2e9cc46d6e43b81d7c", + "dist/2024-04-29/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz": "d9eec9ab7c265444ac5f04d4ec9e77d4c0c3c2e34c5804db8abf5f94c8fd2272", + "dist/2024-04-29/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz": "91df129046443554bfb836d25886aa9807b917acbc9dcf30f6531cde7bf912fa", + "dist/2024-04-29/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz": "ca9b574b9f2e914b5a6d9e011aba805d1e6f9b687dc1a1868e88f0e4d9e4401c", + "dist/2024-04-29/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "8b44f96a1ccd6d501b0af3960edb2c1a6c93957676a1c2cdb831e614de398f8b", + "dist/2024-04-29/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "f8a10a6767b80bf24f73223b9e46e1b18b6bf6746ad2115eb8968a0e482f0e4e", + "dist/2024-04-29/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "a197208807503a9cfbc6df938d614a192da48884b2e4892f7b1d234579091be1", + "dist/2024-04-29/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "af3a1a33942bd8a3417593dc118abb1db0373f5410f54771713c05bb86724fed", + "dist/2024-04-29/rustc-nightly-s390x-unknown-linux-gnu.tar.gz": "5a3a3aa73b6a0f21c63b9a40bdbd0bb4dc59bd75add0a06e292ced791fad31be", + "dist/2024-04-29/rustc-nightly-s390x-unknown-linux-gnu.tar.xz": "6d7903f1c9fc95a23448717326d667dce59e54aaff821443d3cd9137cf3537fb", + "dist/2024-04-29/rustc-nightly-x86_64-apple-darwin.tar.gz": "64eede54da4bf88b0a42ecf7f7a4bf8002b5550e60a64e1e48244c7f5b04768c", + "dist/2024-04-29/rustc-nightly-x86_64-apple-darwin.tar.xz": "0a8f95e3bb0bebf9bcc8116b91bab3ba97cb6ff4021713586280aaceed9da030", + "dist/2024-04-29/rustc-nightly-x86_64-pc-windows-gnu.tar.gz": "58f9e0dd9c1aadde2dfd869528adadd4acc29ab0850236f3cee5f023d4211939", + "dist/2024-04-29/rustc-nightly-x86_64-pc-windows-gnu.tar.xz": "a211a962093e0d09358d51a6eb48da0966a02383c6b00c8acc077b5663d7d707", + "dist/2024-04-29/rustc-nightly-x86_64-pc-windows-msvc.tar.gz": "5631926874dc54204c319137a77a89de5e6f408de2a832109e2be71ea79f27d1", + "dist/2024-04-29/rustc-nightly-x86_64-pc-windows-msvc.tar.xz": "a8cf87bc663b5e3dbcc97b0eb58bb1b9b5b0100aacb47dc0c372fe1612517244", + "dist/2024-04-29/rustc-nightly-x86_64-unknown-freebsd.tar.gz": "1011f98197a9fe82d6095f4521934a06eea5f7e9719a6e4c9e3bf13d68f799ca", + "dist/2024-04-29/rustc-nightly-x86_64-unknown-freebsd.tar.xz": "79599b3f91f9372262e97a417f4e104ef5192c0f6f8df204aea9c8b3ee39430e", + "dist/2024-04-29/rustc-nightly-x86_64-unknown-illumos.tar.gz": "7179a453bdcb17e401c0af8f4ab86cb5a4752a8ec80b0cbdd4cf1854c7f36a35", + "dist/2024-04-29/rustc-nightly-x86_64-unknown-illumos.tar.xz": "d565fc366fdbc305fbfe59e72b971c58f201d69e03a9ffa667d2ca0735cdb7f3", + "dist/2024-04-29/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz": "ae6bd8e20560d48519290d78e3d21f84b983403ca1f8f466a85496276d7866da", + "dist/2024-04-29/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz": "c7c0f8f44b0275456a27952178caa04c32eb9a1507056ddc05926a0730e17359", + "dist/2024-04-29/rustc-nightly-x86_64-unknown-linux-musl.tar.gz": "3246797ddbc9118de819b13b005b83748338f3c825a7436ebd5aa79ca55539c0", + "dist/2024-04-29/rustc-nightly-x86_64-unknown-linux-musl.tar.xz": "c7e784e77dbabedad88d24d2ae6dc4abb68bc04b1cd6c9d45f6dc28b6d0e2edc", + "dist/2024-04-29/rustc-nightly-x86_64-unknown-netbsd.tar.gz": "c9452de4b3f15f0cf0b7d737b217b2cc7b88a96543bd8ce587ee14be1e21a90a", + "dist/2024-04-29/rustc-nightly-x86_64-unknown-netbsd.tar.xz": "de9b05278a5c69d53ccbb31223526ea2aa2275c0fb3f046d1c1b4d67c0b0c275", + "dist/2024-04-29/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "3734353a58dbf6c3831cc6b4ea606357140c191c89e8dfca1d7aa2f3fb8ac53d", + "dist/2024-04-29/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "e5e3a6e609fbfd537aa4acfefd3681d4b6c8029e2801a1ef23e8b09cf5a47bfe", + "dist/2024-04-29/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "22f54857e01d759301d099b67547cdc485596499088d0d749d38058c28e0f752", + "dist/2024-04-29/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "db48a9d45dc7c7aad4c9bb0d20789dd35fb6ef7a966948c44fbbae132de4c16b", + "dist/2024-04-29/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "fa5d1fb9f3627e7d59269a1f8008d780c685ea04975473f1808287134e7bc5a7", + "dist/2024-04-29/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "61ab625b47fa9097af90a79a1e75a2f2492a415f4009c9043cf453bd4128f031", + "dist/2024-04-29/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "cc79969341fc60991059d0e3f13a69489c1e0915ea5787a88b8605ed5b7f3cd0", + "dist/2024-04-29/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "bbdb75f922b4b1716b033d91c76c4c0aa53061d6e7fa53a9bf16fe076814bbb2", + "dist/2024-04-29/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "13ca68afc3f3970a37951504664b58035102e1ae06d10a744389603b2f7499f5", + "dist/2024-04-29/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "04b174aa724945b6359a555892506c6a742a7c427464e8206433bb3f9a65fc02", + "dist/2024-04-29/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "430333380a590a9de211c8d735989fedb89321cf9f5f9a0b1ef651ec8b598691", + "dist/2024-04-29/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "924713e648806945cd56e54d4c11dc74b65241c8dbf6cc7b401c5c93d0f7ffdb", + "dist/2024-04-29/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "bb6e5a8b5cc88099e613aa5f4d926165976d8e4a7fccbecf4ac3b0eb966d7a0f", + "dist/2024-04-29/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "34d5e970304e1734aacb26c095e926c27a07e1a41fe70db9fa2997bef97ad3ec", + "dist/2024-04-29/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "835447a1d9d60659e99903275f327641809fc0148f35149f980d1a17ff87cc9a", + "dist/2024-04-29/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "ddd84a7f900aa239f93711f7da71e57aaedeeba2c9c8a8f23608acc7e48613c0", + "dist/2024-04-29/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "02f0af2bdae167c6091099a9b54ceb150c22b0f20dc861587a02cac78deb0b39", + "dist/2024-04-29/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "822f78f39dcbe3282bf7888a8cdae04efe7b023ded026a7e7f430e4ff15e7942", + "dist/2024-04-29/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "68a6189652c11a2c142c5339e2f5fb09d5f3e85d860bff063f62d5d3a3d111bf", + "dist/2024-04-29/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "6740ea882effa2fb87dd72744c08888ce5ec59c9797c00369156b24847bb180e", + "dist/2024-04-29/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz": "0bb365e2d895ef3c39c4899a01187a23f9b7c5195c30bf845da3917f62f5eafd", + "dist/2024-04-29/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz": "2e54c9887bc6ed1eb09b9f69c8425da843ea12bf33248fa0ccdc0d14387c1c57", + "dist/2024-04-29/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "b0c0fe437921d17e2f50cbff87beeac067efa3d5211a241fb6f4c10b8ab500ac", + "dist/2024-04-29/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "64e7282c0cf4a714b11eed1d28be3a64ba0ccc6d899211a872a5a7809d514c08", + "dist/2024-04-29/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "100cfde057c81460b8cfde2047fe83ddde360a6df1ff178da5a968b17ecc9df8", + "dist/2024-04-29/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "38e8712e98fa0bc6962ab2fd2e3b96a2a5dcaa6c16161d8caf71131a1ca5031e", + "dist/2024-04-29/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "4dab52b50e19348fb39fdad39ab44189c27c10f80b5fbe2cc4723b644611fa87", + "dist/2024-04-29/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "36d1b2c9150fafc5976c296200ba3fac3e923df3e6f18032068200e2a887146c", + "dist/2024-04-29/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "7cb4a536320c23d305ce3bd3b7a954d951bf4d358ef3732be75b9b290c4818a5", + "dist/2024-04-29/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "ede1afc7dc5892ef6f780e987737e145c4b4d00495da8c2e9902182a3a174e20", + "dist/2024-04-29/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "e2d2d561cbfa0add0e5349682976216d3a7cff4094372c1ed26854bb4e4d93fd", + "dist/2024-04-29/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "e0380e65e83e4131f6aa7ee4e185689add4372b0c1653312e2ffd56072fdd0fe", + "dist/2024-04-29/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "73a140c7ed9c80f209ff976c63b0a34d625d651553c38692c91f048f4e0ae470", + "dist/2024-04-29/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "9946b7120465181e05916b8023bc075b32bd85cf45a3b1d8bfba2f94ac78d927", + "dist/2024-04-29/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "eda273f27714b1e45adcc2388149f48de0e32a9104db0b9d1a02f6d37de43fef", + "dist/2024-04-29/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "f2955a4b696d050c219a96c093162b42a2fab921f9f3cb7570f8462928306c6d", + "dist/2024-04-29/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "ec900cc2d3c6d45ef039653f4418f9b9a4a5fddd5d7e8077c3fb08b36c539a28", + "dist/2024-04-29/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "04e6999a3405acc79f5fdcafeeab52880e5eeeedd3909b5f3c57e7647c86ef99", + "dist/2024-04-29/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "0730c5ebd576fec5371085f9fac0adde9424e1d7626456ed33bc66351b0ad307", + "dist/2024-04-29/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "90cbd84b8d48f0235a1954166f5edd53dc3031532ec6dfcb364f9a9624c9ce11", + "dist/2024-04-29/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "5f5c62d321db27eb495f6ea312ef8bea0bf17a7a501a44e062986c416951700f", + "dist/2024-04-29/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "a3bf64e2f22436e4484fc818f69d2f750fddd05a96463fd4abfcf655edce36b9", + "dist/2024-04-29/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "a847a6f9c7a3ce71c7cd8d81bdfcfcd8e4d128aa28ba0dafea89b0cc37c6c36c", + "dist/2024-04-29/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "21fa794456566c64d08f629a385f89b3cfe9d9b69f317ae85fbe7425419108ff", + "dist/2024-04-29/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "b3f792f10a98993b4b55d1df951727a4422102d51b1145e51824268d48587ad0", + "dist/2024-04-29/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "d791f0ec3c004e7baa0381962bf8ca2f18a3c861152702de5301d0149260e7fa", + "dist/2024-04-29/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "9807b2887e976d29f0c04484f8459175b4f6b70ef000037cdc4dada48e3cbd74", + "dist/2024-04-29/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "019920d64778af62879e2146c2c13d9f6e2165a38bbfa1982694bfb48864d308" } } diff --git a/src/tools/cargo b/src/tools/cargo -Subproject b60a1555155111e962018007a6d0ef85207db46 +Subproject 05364cb2f61a2c2b091e061c1f42b207dfb5f81 diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index bd3a04e34ae..9c9ea114081 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -6,11 +6,62 @@ document. ## Unreleased / Beta / In Rust Nightly -[66c29b97...master](https://github.com/rust-lang/rust-clippy/compare/66c29b97...master) +[93f0a9a9...master](https://github.com/rust-lang/rust-clippy/compare/93f0a9a9...master) + +## Rust 1.78 + +Current stable, released 2024-05-02 + +[View all 112 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2024-01-26T05%3A46%3A23Z..2024-03-07T16%3A25%3A52Z+base%3Amaster) + +### New Lints + +* [`assigning_clones`] + [#12077](https://github.com/rust-lang/rust-clippy/pull/12077) +* [`mixed_attributes_style`] + [#12354](https://github.com/rust-lang/rust-clippy/pull/12354) +* [`empty_docs`] + [#12342](https://github.com/rust-lang/rust-clippy/pull/12342) +* [`unnecessary_get_then_check`] + [#12339](https://github.com/rust-lang/rust-clippy/pull/12339) +* [`multiple_bound_locations`] + [#12259](https://github.com/rust-lang/rust-clippy/pull/12259) +* [`unnecessary_clippy_cfg`] + [#12303](https://github.com/rust-lang/rust-clippy/pull/12303) +* [`deprecated_clippy_cfg_attr`] + [#12292](https://github.com/rust-lang/rust-clippy/pull/12292) +* [`manual_c_str_literals`] + [#11919](https://github.com/rust-lang/rust-clippy/pull/11919) +* [`ref_as_ptr`] + [#12087](https://github.com/rust-lang/rust-clippy/pull/12087) +* [`lint_groups_priority`] + [#11832](https://github.com/rust-lang/rust-clippy/pull/11832) +* [`unnecessary_result_map_or_else`] + [#12169](https://github.com/rust-lang/rust-clippy/pull/12169) +* [`to_string_trait_impl`] + [#12122](https://github.com/rust-lang/rust-clippy/pull/12122) +* [`incompatible_msrv`] + [#12160](https://github.com/rust-lang/rust-clippy/pull/12160) + +### Enhancements + +* [`thread_local_initializer_can_be_made_const`]: Now checks the [`msrv`] configuration + [#12405](https://github.com/rust-lang/rust-clippy/pull/12405) +* [`disallowed_macros`]: Code generated by derive macros can no longer allow this lint + [#12267](https://github.com/rust-lang/rust-clippy/pull/12267) +* [`wildcard_imports`]: Add configuration [`allowed-wildcard-imports`] to allow preconfigured wildcards + [#11979](https://github.com/rust-lang/rust-clippy/pull/11979) + +### ICE Fixes + +* [`ptr_as_ptr`]: No longer ICEs when the cast source is a function call to a local variable + [#12617](https://github.com/rust-lang/rust-clippy/pull/12617) +* [`cast_sign_loss`]: Avoids an infinite loop when casting two chained `.unwrap()` calls + [#12508](https://github.com/rust-lang/rust-clippy/pull/12508) ## Rust 1.77 -Current stable, released 2024-03-18 +Released 2024-03-18 [View all 93 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2023-12-16T18%3A20%3A00Z..2024-01-25T18%3A15%3A56Z+base%3Amaster) @@ -5891,6 +5942,7 @@ Released 2018-09-13 [`allow-print-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-print-in-tests [`allow-private-module-inception`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-private-module-inception [`allow-unwrap-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-unwrap-in-tests +[`allow-useless-vec-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-useless-vec-in-tests [`allowed-dotfiles`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-dotfiles [`allowed-duplicate-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-duplicate-crates [`allowed-idents-below-min-chars`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-idents-below-min-chars diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index 43f20ecedc2..b48f3ab3919 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.79" +version = "0.1.80" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" @@ -30,7 +30,7 @@ color-print = "0.3.4" anstream = "0.6.0" [dev-dependencies] -ui_test = "0.22.2" +ui_test = "0.23" regex = "1.5.5" toml = "0.7.3" walkdir = "2.3" diff --git a/src/tools/clippy/book/src/development/adding_lints.md b/src/tools/clippy/book/src/development/adding_lints.md index b80ac6370e7..415022612ca 100644 --- a/src/tools/clippy/book/src/development/adding_lints.md +++ b/src/tools/clippy/book/src/development/adding_lints.md @@ -299,10 +299,10 @@ This is good, because it makes writing this particular lint less complicated. We have to make this decision with every new Clippy lint. It boils down to using either [`EarlyLintPass`][early_lint_pass] or [`LateLintPass`][late_lint_pass]. -In short, the `LateLintPass` has access to type information while the -`EarlyLintPass` doesn't. If you don't need access to type information, use the -`EarlyLintPass`. The `EarlyLintPass` is also faster. However, linting speed -hasn't really been a concern with Clippy so far. +In short, the `EarlyLintPass` runs before type checking and +[HIR](https://rustc-dev-guide.rust-lang.org/hir.html) lowering and the `LateLintPass` +has access to type information. Consider using the `LateLintPass` unless you need +something specific from the `EarlyLintPass`. Since we don't need type information for checking the function name, we used `--pass=early` when running the new lint automation and all the imports were diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md index 7cefa685264..f6af9810ca1 100644 --- a/src/tools/clippy/book/src/lint_configuration.md +++ b/src/tools/clippy/book/src/lint_configuration.md @@ -132,6 +132,16 @@ Whether `unwrap` should be allowed in test functions or `#[cfg(test)]` * [`unwrap_used`](https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used) +## `allow-useless-vec-in-tests` +Whether `useless_vec` should ignore test functions or `#[cfg(test)]` + +**Default Value:** `false` + +--- +**Affected lints:** +* [`useless_vec`](https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec) + + ## `allowed-dotfiles` Additional dotfiles (files or directories starting with a dot) to allow @@ -506,13 +516,14 @@ The maximum byte size a `Future` can have, before it triggers the `clippy::large ## `ignore-interior-mutability` -A list of paths to types that should be treated like `Arc`, i.e. ignored but -for the generic parameters for determining interior mutability +A list of paths to types that should be treated as if they do not contain interior mutability **Default Value:** `["bytes::Bytes"]` --- **Affected lints:** +* [`borrow_interior_mutable_const`](https://rust-lang.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const) +* [`declare_interior_mutable_const`](https://rust-lang.github.io/rust-clippy/master/index.html#declare_interior_mutable_const) * [`ifs_same_cond`](https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond) * [`mutable_key_type`](https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type) diff --git a/src/tools/clippy/clippy_config/Cargo.toml b/src/tools/clippy/clippy_config/Cargo.toml index 8ba2ab56625..7f7dc9d6cfb 100644 --- a/src/tools/clippy/clippy_config/Cargo.toml +++ b/src/tools/clippy/clippy_config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_config" -version = "0.1.79" +version = "0.1.80" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs index 781282213cc..5cfcbdb57d7 100644 --- a/src/tools/clippy/clippy_config/src/conf.rs +++ b/src/tools/clippy/clippy_config/src/conf.rs @@ -463,14 +463,17 @@ define_Conf! { /// /// Whether print macros (ex. `println!`) should be allowed in test functions or `#[cfg(test)]` (allow_print_in_tests: bool = false), + /// Lint: USELESS_VEC. + /// + /// Whether `useless_vec` should ignore test functions or `#[cfg(test)]` + (allow_useless_vec_in_tests: bool = false), /// Lint: RESULT_LARGE_ERR. /// /// The maximum size of the `Err`-variant in a `Result` returned from a function (large_error_threshold: u64 = 128), - /// Lint: MUTABLE_KEY_TYPE, IFS_SAME_COND. + /// Lint: MUTABLE_KEY_TYPE, IFS_SAME_COND, BORROW_INTERIOR_MUTABLE_CONST, DECLARE_INTERIOR_MUTABLE_CONST. /// - /// A list of paths to types that should be treated like `Arc`, i.e. ignored but - /// for the generic parameters for determining interior mutability + /// A list of paths to types that should be treated as if they do not contain interior mutability (ignore_interior_mutability: Vec<String> = Vec::from(["bytes::Bytes".into()])), /// Lint: UNINLINED_FORMAT_ARGS. /// diff --git a/src/tools/clippy/clippy_config/src/msrvs.rs b/src/tools/clippy/clippy_config/src/msrvs.rs index 59dd5b334b8..14808440d48 100644 --- a/src/tools/clippy/clippy_config/src/msrvs.rs +++ b/src/tools/clippy/clippy_config/src/msrvs.rs @@ -23,7 +23,7 @@ msrv_aliases! { 1,70,0 { OPTION_RESULT_IS_VARIANT_AND, BINARY_HEAP_RETAIN } 1,68,0 { PATH_MAIN_SEPARATOR_STR } 1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS } - 1,63,0 { ASSIGNING_CLONES } + 1,63,0 { CLONE_INTO } 1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE } 1,59,0 { THREAD_LOCAL_INITIALIZER_CAN_BE_MADE_CONST } 1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY } diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml index 1d954607eee..5e3a119337c 100644 --- a/src/tools/clippy/clippy_lints/Cargo.toml +++ b/src/tools/clippy/clippy_lints/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_lints" -version = "0.1.79" +version = "0.1.80" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/src/tools/clippy/clippy_lints/src/assigning_clones.rs b/src/tools/clippy/clippy_lints/src/assigning_clones.rs index dc7f44af2b7..f0dafb1ae0d 100644 --- a/src/tools/clippy/clippy_lints/src/assigning_clones.rs +++ b/src/tools/clippy/clippy_lints/src/assigning_clones.rs @@ -45,7 +45,7 @@ declare_clippy_lint! { /// a.clone_from(&b); /// } /// ``` - #[clippy::version = "1.77.0"] + #[clippy::version = "1.78.0"] pub ASSIGNING_CLONES, perf, "assigning the result of cloning may be inefficient" @@ -153,7 +153,7 @@ fn extract_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option< fn is_ok_to_suggest<'tcx>(cx: &LateContext<'tcx>, lhs: &Expr<'tcx>, call: &CallCandidate<'tcx>, msrv: &Msrv) -> bool { // For calls to .to_owned we suggest using .clone_into(), which was only stablilized in 1.63. // If the current MSRV is below that, don't suggest the lint. - if !msrv.meets(msrvs::ASSIGNING_CLONES) && matches!(call.target, TargetTrait::ToOwned) { + if !msrv.meets(msrvs::CLONE_INTO) && matches!(call.target, TargetTrait::ToOwned) { return false; } diff --git a/src/tools/clippy/clippy_lints/src/box_default.rs b/src/tools/clippy/clippy_lints/src/box_default.rs index 4062212f408..8459f051d3d 100644 --- a/src/tools/clippy/clippy_lints/src/box_default.rs +++ b/src/tools/clippy/clippy_lints/src/box_default.rs @@ -121,9 +121,9 @@ fn given_type(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { if let Some(index) = args.iter().position(|arg| arg.hir_id == expr.hir_id) && let Some(sig) = expr_sig(cx, path) && let Some(input) = sig.input(index) - && !cx.typeck_results().expr_ty_adjusted(expr).boxed_ty().is_trait() + && let Some(input_ty) = input.no_bound_vars() { - input.no_bound_vars().is_some() + input_ty == cx.typeck_results().expr_ty_adjusted(expr) } else { false } diff --git a/src/tools/clippy/clippy_lints/src/cargo/mod.rs b/src/tools/clippy/clippy_lints/src/cargo/mod.rs index ca7fa4e5a41..593bc6c81ee 100644 --- a/src/tools/clippy/clippy_lints/src/cargo/mod.rs +++ b/src/tools/clippy/clippy_lints/src/cargo/mod.rs @@ -197,7 +197,7 @@ declare_clippy_lint! { /// pedantic = { level = "warn", priority = -1 } /// similar_names = "allow" /// ``` - #[clippy::version = "1.76.0"] + #[clippy::version = "1.78.0"] pub LINT_GROUPS_PRIORITY, correctness, "a lint group in `Cargo.toml` at the same priority as a lint" diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs index dbfa8e1ee91..7c5acd1a678 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs @@ -40,9 +40,14 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b get_constant_bits(cx, right).map_or(0, |b| b.saturating_sub(1)) }) }, - BinOpKind::Rem | BinOpKind::BitAnd => get_constant_bits(cx, right) + BinOpKind::Rem => get_constant_bits(cx, right) .unwrap_or(u64::MAX) .min(apply_reductions(cx, nbits, left, signed)), + BinOpKind::BitAnd => get_constant_bits(cx, right) + .unwrap_or(u64::MAX) + .min(get_constant_bits(cx, left).unwrap_or(u64::MAX)) + .min(apply_reductions(cx, nbits, right, signed)) + .min(apply_reductions(cx, nbits, left, signed)), BinOpKind::Shr => apply_reductions(cx, nbits, left, signed) .saturating_sub(constant_int(cx, right).map_or(0, |s| u64::try_from(s).unwrap_or_default())), _ => nbits, diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs index d14898a8196..bd2c96f01f6 100644 --- a/src/tools/clippy/clippy_lints/src/casts/mod.rs +++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs @@ -708,7 +708,7 @@ declare_clippy_lint! { /// let a_ref = &1; /// let a_ptr = std::ptr::from_ref(a_ref); /// ``` - #[clippy::version = "1.77.0"] + #[clippy::version = "1.78.0"] pub REF_AS_PTR, pedantic, "using `as` to cast a reference to pointer" diff --git a/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs b/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs index 6942ca53640..70856b80881 100644 --- a/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs +++ b/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs @@ -1,9 +1,9 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item}; -use clippy_utils::visitors::for_each_expr_with_closures; +use clippy_utils::visitors::{for_each_expr_with_closures, Visitable}; use clippy_utils::{get_enclosing_block, path_to_local_id}; use core::ops::ControlFlow; -use rustc_hir::{Block, ExprKind, HirId, LangItem, LetStmt, Node, PatKind}; +use rustc_hir::{Body, ExprKind, HirId, LangItem, LetStmt, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use rustc_span::symbol::sym; @@ -77,7 +77,7 @@ fn match_acceptable_type(cx: &LateContext<'_>, local: &LetStmt<'_>, collections: || is_type_lang_item(cx, ty, LangItem::String) } -fn has_no_read_access<'tcx>(cx: &LateContext<'tcx>, id: HirId, block: &'tcx Block<'tcx>) -> bool { +fn has_no_read_access<'tcx, T: Visitable<'tcx>>(cx: &LateContext<'tcx>, id: HirId, block: T) -> bool { let mut has_access = false; let mut has_read_access = false; @@ -109,11 +109,30 @@ fn has_no_read_access<'tcx>(cx: &LateContext<'tcx>, id: HirId, block: &'tcx Bloc // traits (identified as local, based on the orphan rule), pessimistically assume that they might // have side effects, so consider them a read. if let Node::Expr(parent) = cx.tcx.parent_hir_node(expr.hir_id) - && let ExprKind::MethodCall(_, receiver, _, _) = parent.kind + && let ExprKind::MethodCall(_, receiver, args, _) = parent.kind && path_to_local_id(receiver, id) && let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(parent.hir_id) && !method_def_id.is_local() { + // If this "official" method takes closures, + // it has read access if one of the closures has read access. + // + // items.retain(|item| send_item(item).is_ok()); + let is_read_in_closure_arg = args.iter().any(|arg| { + if let ExprKind::Closure(closure) = arg.kind + // To keep things simple, we only check the first param to see if its read. + && let Body { params: [param, ..], value } = cx.tcx.hir().body(closure.body) + { + !has_no_read_access(cx, param.hir_id, *value) + } else { + false + } + }); + if is_read_in_closure_arg { + has_read_access = true; + return ControlFlow::Break(()); + } + // The method call is a statement, so the return value is not used. That's not a read access: // // id.foo(args); diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs index acdcb54be27..ccf1d9d6f8c 100644 --- a/src/tools/clippy/clippy_lints/src/copies.rs +++ b/src/tools/clippy/clippy_lints/src/copies.rs @@ -1,15 +1,14 @@ use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_then}; use clippy_utils::source::{first_line_of_span, indent_of, reindent_multiline, snippet, snippet_opt}; -use clippy_utils::ty::{is_interior_mut_ty, needs_ordered_drop}; +use clippy_utils::ty::{needs_ordered_drop, InteriorMut}; use clippy_utils::visitors::for_each_expr; use clippy_utils::{ - capture_local_usage, def_path_def_ids, eq_expr_value, find_binding_init, get_enclosing_block, hash_expr, hash_stmt, - if_sequence, is_else_clause, is_lint_allowed, path_to_local, search_same, ContainsName, HirEqInterExpr, SpanlessEq, + capture_local_usage, eq_expr_value, find_binding_init, get_enclosing_block, hash_expr, hash_stmt, if_sequence, + is_else_clause, is_lint_allowed, path_to_local, search_same, ContainsName, HirEqInterExpr, SpanlessEq, }; use core::iter; use core::ops::ControlFlow; use rustc_errors::Applicability; -use rustc_hir::def_id::DefIdSet; use rustc_hir::{intravisit, BinOpKind, Block, Expr, ExprKind, HirId, HirIdSet, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; @@ -159,40 +158,36 @@ declare_clippy_lint! { "`if` statement with shared code in all blocks" } -pub struct CopyAndPaste { +pub struct CopyAndPaste<'tcx> { ignore_interior_mutability: Vec<String>, - ignored_ty_ids: DefIdSet, + interior_mut: InteriorMut<'tcx>, } -impl CopyAndPaste { +impl CopyAndPaste<'_> { pub fn new(ignore_interior_mutability: Vec<String>) -> Self { Self { ignore_interior_mutability, - ignored_ty_ids: DefIdSet::new(), + interior_mut: InteriorMut::default(), } } } -impl_lint_pass!(CopyAndPaste => [ +impl_lint_pass!(CopyAndPaste<'_> => [ IFS_SAME_COND, SAME_FUNCTIONS_IN_IF_CONDITION, IF_SAME_THEN_ELSE, BRANCHES_SHARING_CODE ]); -impl<'tcx> LateLintPass<'tcx> for CopyAndPaste { +impl<'tcx> LateLintPass<'tcx> for CopyAndPaste<'tcx> { fn check_crate(&mut self, cx: &LateContext<'tcx>) { - for ignored_ty in &self.ignore_interior_mutability { - let path: Vec<&str> = ignored_ty.split("::").collect(); - for id in def_path_def_ids(cx, path.as_slice()) { - self.ignored_ty_ids.insert(id); - } - } + self.interior_mut = InteriorMut::new(cx, &self.ignore_interior_mutability); } + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if !expr.span.from_expansion() && matches!(expr.kind, ExprKind::If(..)) && !is_else_clause(cx.tcx, expr) { let (conds, blocks) = if_sequence(expr); - lint_same_cond(cx, &conds, &self.ignored_ty_ids); + lint_same_cond(cx, &conds, &mut self.interior_mut); lint_same_fns_in_if_cond(cx, &conds); let all_same = !is_lint_allowed(cx, IF_SAME_THEN_ELSE, expr.hir_id) && lint_if_same_then_else(cx, &conds, &blocks); @@ -570,13 +565,14 @@ fn check_for_warn_of_moved_symbol(cx: &LateContext<'_>, symbols: &[(HirId, Symbo }) } -fn method_caller_is_mutable(cx: &LateContext<'_>, caller_expr: &Expr<'_>, ignored_ty_ids: &DefIdSet) -> bool { +fn method_caller_is_mutable<'tcx>( + cx: &LateContext<'tcx>, + caller_expr: &Expr<'_>, + interior_mut: &mut InteriorMut<'tcx>, +) -> bool { let caller_ty = cx.typeck_results().expr_ty(caller_expr); - // Check if given type has inner mutability and was not set to ignored by the configuration - let is_inner_mut_ty = is_interior_mut_ty(cx, caller_ty) - && !matches!(caller_ty.ty_adt_def(), Some(adt) if ignored_ty_ids.contains(&adt.did())); - is_inner_mut_ty + interior_mut.is_interior_mut_ty(cx, caller_ty) || caller_ty.is_mutable_ptr() // `find_binding_init` will return the binding iff its not mutable || path_to_local(caller_expr) @@ -585,7 +581,7 @@ fn method_caller_is_mutable(cx: &LateContext<'_>, caller_expr: &Expr<'_>, ignore } /// Implementation of `IFS_SAME_COND`. -fn lint_same_cond(cx: &LateContext<'_>, conds: &[&Expr<'_>], ignored_ty_ids: &DefIdSet) { +fn lint_same_cond<'tcx>(cx: &LateContext<'tcx>, conds: &[&Expr<'_>], interior_mut: &mut InteriorMut<'tcx>) { for (i, j) in search_same( conds, |e| hash_expr(cx, e), @@ -593,7 +589,7 @@ fn lint_same_cond(cx: &LateContext<'_>, conds: &[&Expr<'_>], ignored_ty_ids: &De // Ignore eq_expr side effects iff one of the expression kind is a method call // and the caller is not a mutable, including inner mutable type. if let ExprKind::MethodCall(_, caller, _, _) = lhs.kind { - if method_caller_is_mutable(cx, caller, ignored_ty_ids) { + if method_caller_is_mutable(cx, caller, interior_mut) { false } else { SpanlessEq::new(cx).eq_expr(lhs, rhs) diff --git a/src/tools/clippy/clippy_lints/src/dbg_macro.rs b/src/tools/clippy/clippy_lints/src/dbg_macro.rs index e2296767431..db593726604 100644 --- a/src/tools/clippy/clippy_lints/src/dbg_macro.rs +++ b/src/tools/clippy/clippy_lints/src/dbg_macro.rs @@ -1,10 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_in_test; use clippy_utils::macros::{macro_backtrace, MacroCall}; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::{is_in_cfg_test, is_in_test_function}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, HirId, Node}; +use rustc_hir::{Expr, ExprKind, Node}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; @@ -63,7 +63,7 @@ impl LateLintPass<'_> for DbgMacro { !in_external_macro(cx.sess(), macro_call.span) && self.checked_dbg_call_site.insert(macro_call.span) && // allows `dbg!` in test code if allow-dbg-in-test is set to true in clippy.toml - !(self.allow_dbg_in_tests && is_in_test(cx, expr.hir_id)) + !(self.allow_dbg_in_tests && is_in_test(cx.tcx, expr.hir_id)) { let mut applicability = Applicability::MachineApplicable; @@ -129,10 +129,6 @@ impl LateLintPass<'_> for DbgMacro { } } -fn is_in_test(cx: &LateContext<'_>, hir_id: HirId) -> bool { - is_in_test_function(cx.tcx, hir_id) || is_in_cfg_test(cx.tcx, hir_id) -} - fn first_dbg_macro_in_expansion(cx: &LateContext<'_>, span: Span) -> Option<MacroCall> { macro_backtrace(span).find(|mc| cx.tcx.is_diagnostic_item(sym::dbg_macro, mc.def_id)) } diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 89e2b344968..b936b28470b 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -9,8 +9,8 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_ty, Visitor}; use rustc_hir::{ - self as hir, BindingMode, Body, BodyId, BorrowKind, Expr, ExprKind, HirId, MatchSource, Mutability, Node, - Pat, PatKind, Path, QPath, TyKind, UnOp, + self as hir, BindingMode, Body, BodyId, BorrowKind, Expr, ExprKind, HirId, MatchSource, Mutability, Node, Pat, + PatKind, Path, QPath, TyKind, UnOp, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs index 80db617c639..003a9995c15 100644 --- a/src/tools/clippy/clippy_lints/src/format_args.rs +++ b/src/tools/clippy/clippy_lints/src/format_args.rs @@ -4,7 +4,7 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::is_diag_trait_item; use clippy_utils::macros::{ find_format_arg_expr, find_format_args, format_arg_removal_span, format_placeholder_format_span, is_assert_macro, - is_format_macro, is_panic, root_macro_call, root_macro_call_first_node, FormatParamUsage, MacroCall, + is_format_macro, is_panic, matching_root_macro_call, root_macro_call_first_node, FormatParamUsage, MacroCall, }; use clippy_utils::source::snippet_opt; use clippy_utils::ty::{implements_trait, is_type_lang_item}; @@ -271,9 +271,7 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> { let mut suggest_format = |spec| { let message = format!("for the {spec} to apply consider using `format!()`"); - if let Some(mac_call) = root_macro_call(arg_span) - && self.cx.tcx.is_diagnostic_item(sym::format_args_macro, mac_call.def_id) - { + if let Some(mac_call) = matching_root_macro_call(self.cx, arg_span, sym::format_args_macro) { diag.span_suggestion( self.cx.sess().source_map().span_until_char(mac_call.span, '!'), message, diff --git a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs index 7b97fc15caa..3bf8d618955 100644 --- a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs +++ b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs @@ -24,7 +24,7 @@ declare_clippy_lint! { /// /// ### Limitations /// This lint does not check for implied bounds transitively. Meaning that - /// it does't check for implied bounds from supertraits of supertraits + /// it doesn't check for implied bounds from supertraits of supertraits /// (e.g. `trait A {} trait B: A {} trait C: B {}`, then having an `fn() -> impl A + C`) /// /// ### Example diff --git a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs index a4c3b06046e..128461ce7bc 100644 --- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs +++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs @@ -93,12 +93,9 @@ fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> FxIndexMap<Hir let mut slices: FxIndexMap<HirId, SliceLintInformation> = FxIndexMap::default(); pat.walk_always(|pat| { // We'll just ignore mut and ref mut for simplicity sake right now - if let hir::PatKind::Binding( - hir::BindingMode(by_ref, hir::Mutability::Not), - value_hir_id, - ident, - sub_pat, - ) = pat.kind && by_ref != hir::ByRef::Yes(hir::Mutability::Mut) + if let hir::PatKind::Binding(hir::BindingMode(by_ref, hir::Mutability::Not), value_hir_id, ident, sub_pat) = + pat.kind + && by_ref != hir::ByRef::Yes(hir::Mutability::Mut) { // This block catches bindings with sub patterns. It would be hard to build a correct suggestion // for them and it's likely that the user knows what they are doing in such a case. diff --git a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs index afcb6745947..208d1bb6e68 100644 --- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs @@ -1,10 +1,13 @@ -use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::is_from_proc_macro; +use clippy_utils::macros::macro_backtrace; use clippy_utils::source::snippet; -use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node}; +use rustc_hir::{ArrayLen, Expr, ExprKind, Item, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, ConstKind}; use rustc_session::impl_lint_pass; +use rustc_span::{sym, Span}; declare_clippy_lint! { /// ### What it does @@ -25,20 +28,41 @@ declare_clippy_lint! { pub struct LargeStackArrays { maximum_allowed_size: u128, + prev_vec_macro_callsite: Option<Span>, } impl LargeStackArrays { #[must_use] pub fn new(maximum_allowed_size: u128) -> Self { - Self { maximum_allowed_size } + Self { + maximum_allowed_size, + prev_vec_macro_callsite: None, + } + } + + /// Check if the given span of an expr is already in a `vec!` call. + fn is_from_vec_macro(&mut self, cx: &LateContext<'_>, span: Span) -> bool { + // First, we check if this is span is within the last encountered `vec!` macro's root callsite. + self.prev_vec_macro_callsite + .is_some_and(|vec_mac| vec_mac.contains(span)) + || { + // Then, we try backtracking the macro expansions, to see if there's a `vec!` macro, + // and update the `prev_vec_macro_callsite`. + let res = macro_backtrace(span).any(|mac| cx.tcx.is_diagnostic_item(sym::vec_macro, mac.def_id)); + if res { + self.prev_vec_macro_callsite = Some(span.source_callsite()); + } + res + } } } impl_lint_pass!(LargeStackArrays => [LARGE_STACK_ARRAYS]); impl<'tcx> LateLintPass<'tcx> for LargeStackArrays { - fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { if let ExprKind::Repeat(_, _) | ExprKind::Array(_) = expr.kind + && !self.is_from_vec_macro(cx, expr.span) && let ty::Array(element_type, cst) = cx.typeck_results().expr_ty(expr).kind() && let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind() && let Ok(element_count) = element_count.try_to_target_usize(cx.tcx) @@ -54,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackArrays { }) && self.maximum_allowed_size < u128::from(element_count) * u128::from(element_size) { - span_lint_and_help( + span_lint_and_then( cx, LARGE_STACK_ARRAYS, expr.span, @@ -62,12 +86,33 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackArrays { "allocating a local array larger than {} bytes", self.maximum_allowed_size ), - None, - format!( - "consider allocating on the heap with `vec!{}.into_boxed_slice()`", - snippet(cx, expr.span, "[...]") - ), + |diag| { + if !might_be_expanded(cx, expr) { + diag.help(format!( + "consider allocating on the heap with `vec!{}.into_boxed_slice()`", + snippet(cx, expr.span, "[...]") + )); + } + }, ); } } } + +/// Only giving help messages if the expr does not contains macro expanded codes. +fn might_be_expanded<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> bool { + /// Check if the span of `ArrayLen` of a repeat expression is within the expr's span, + /// if not, meaning this repeat expr is definitely from some proc-macro. + /// + /// This is a fail-safe to a case where even the `is_from_proc_macro` is unable to determain the + /// correct result. + fn repeat_expr_might_be_expanded<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> bool { + let ExprKind::Repeat(_, ArrayLen::Body(anon_const)) = expr.kind else { + return false; + }; + let len_span = cx.tcx.def_span(anon_const.def_id); + !expr.span.contains(len_span) + } + + expr.span.from_expansion() || is_from_proc_macro(cx, expr) || repeat_expr_might_be_expanded(cx, expr) +} diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index e2aac58bf97..2c44c3881aa 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -535,6 +535,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { allow_print_in_tests, allow_private_module_inception, allow_unwrap_in_tests, + allow_useless_vec_in_tests, ref allowed_dotfiles, ref allowed_idents_below_min_chars, ref allowed_scripts, @@ -754,6 +755,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { too_large_for_stack, msrv: msrv(), span_to_lint_map: BTreeMap::new(), + allow_in_test: allow_useless_vec_in_tests, }) }); store.register_late_pass(|_| Box::new(panic_unimplemented::PanicUnimplemented)); diff --git a/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs b/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs index 31f0f1cfeba..40ccfec02be 100644 --- a/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs +++ b/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs @@ -1,11 +1,12 @@ use super::UNUSED_ENUMERATE_INDEX; use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then}; use clippy_utils::source::snippet; -use clippy_utils::{match_def_path, pat_is_wild, sugg}; +use clippy_utils::{pat_is_wild, sugg}; use rustc_hir::def::DefKind; use rustc_hir::{Expr, ExprKind, Pat, PatKind}; use rustc_lint::LateContext; use rustc_middle::ty; +use rustc_span::sym; /// Checks for the `UNUSED_ENUMERATE_INDEX` lint. /// @@ -16,9 +17,9 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>, arg: &Expr<'_ && let ty = cx.typeck_results().expr_ty(arg) && pat_is_wild(cx, &index.kind, body) && let ty::Adt(base, _) = *ty.kind() - && match_def_path(cx, base.did(), &clippy_utils::paths::CORE_ITER_ENUMERATE_STRUCT) + && cx.tcx.is_diagnostic_item(sym::Enumerate, base.did()) && let Some((DefKind::AssocFn, call_id)) = cx.typeck_results().type_dependent_def(arg.hir_id) - && match_def_path(cx, call_id, &clippy_utils::paths::CORE_ITER_ENUMERATE_METHOD) + && cx.tcx.is_diagnostic_item(sym::enumerate_method, call_id) { span_lint_and_then( cx, diff --git a/src/tools/clippy/clippy_lints/src/manual_assert.rs b/src/tools/clippy/clippy_lints/src/manual_assert.rs index 76edbe8b755..d76b94eba23 100644 --- a/src/tools/clippy/clippy_lints/src/manual_assert.rs +++ b/src/tools/clippy/clippy_lints/src/manual_assert.rs @@ -1,12 +1,11 @@ use crate::rustc_lint::LintContext; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::macros::root_macro_call; +use clippy_utils::macros::{is_panic, root_macro_call}; use clippy_utils::{is_else_clause, is_parent_stmt, peel_blocks_with_stmt, span_extract_comment, sugg}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; -use rustc_span::sym; declare_clippy_lint! { /// ### What it does @@ -42,7 +41,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAssert { && !expr.span.from_expansion() && let then = peel_blocks_with_stmt(then) && let Some(macro_call) = root_macro_call(then.span) - && cx.tcx.item_name(macro_call.def_id) == sym::panic + && is_panic(cx, macro_call.def_id) && !cx.tcx.sess.source_map().is_multiline(cond.span) && let Ok(panic_snippet) = cx.sess().source_map().span_to_snippet(macro_call.span) && let Some(panic_snippet) = panic_snippet.strip_suffix(')') diff --git a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs index 338a299740a..6f6ba1852a6 100644 --- a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs +++ b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs @@ -1,15 +1,15 @@ use clippy_config::msrvs::{self, Msrv}; -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::macros::root_macro_call; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::macros::matching_root_macro_call; use clippy_utils::sugg::Sugg; -use clippy_utils::{higher, in_constant}; +use clippy_utils::{higher, in_constant, path_to_local, peel_ref_operators}; use rustc_ast::ast::RangeLimits; use rustc_ast::LitKind::{Byte, Char}; use rustc_errors::Applicability; -use rustc_hir::{BorrowKind, Expr, ExprKind, PatKind, RangeEnd}; +use rustc_hir::{Expr, ExprKind, Node, Param, PatKind, RangeEnd}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; use rustc_session::impl_lint_pass; -use rustc_span::def_id::DefId; use rustc_span::{sym, Span}; declare_clippy_lint! { @@ -97,12 +97,10 @@ impl<'tcx> LateLintPass<'tcx> for ManualIsAsciiCheck { return; } - if let Some(macro_call) = root_macro_call(expr.span) - && is_matches_macro(cx, macro_call.def_id) - { + if let Some(macro_call) = matching_root_macro_call(cx, expr.span, sym::matches_macro) { if let ExprKind::Match(recv, [arm, ..], _) = expr.kind { let range = check_pat(&arm.pat.kind); - check_is_ascii(cx, macro_call.span, recv, &range); + check_is_ascii(cx, macro_call.span, recv, &range, None); } } else if let ExprKind::MethodCall(path, receiver, [arg], ..) = expr.kind && path.ident.name == sym!(contains) @@ -111,42 +109,67 @@ impl<'tcx> LateLintPass<'tcx> for ManualIsAsciiCheck { end: Some(end), limits: RangeLimits::Closed, }) = higher::Range::hir(receiver) + && !matches!(cx.typeck_results().expr_ty(arg).peel_refs().kind(), ty::Param(_)) { + let arg = peel_ref_operators(cx, arg); + let ty_sugg = get_ty_sugg(cx, arg, start); let range = check_range(start, end); - if let ExprKind::AddrOf(BorrowKind::Ref, _, e) = arg.kind { - check_is_ascii(cx, expr.span, e, &range); - } else { - check_is_ascii(cx, expr.span, arg, &range); - } + check_is_ascii(cx, expr.span, arg, &range, ty_sugg); } } extract_msrv_attr!(LateContext); } -fn check_is_ascii(cx: &LateContext<'_>, span: Span, recv: &Expr<'_>, range: &CharRange) { - if let Some(sugg) = match range { - CharRange::UpperChar => Some("is_ascii_uppercase"), - CharRange::LowerChar => Some("is_ascii_lowercase"), - CharRange::FullChar => Some("is_ascii_alphabetic"), - CharRange::Digit => Some("is_ascii_digit"), - CharRange::HexDigit => Some("is_ascii_hexdigit"), - CharRange::Otherwise | CharRange::LowerHexLetter | CharRange::UpperHexLetter => None, - } { - let default_snip = ".."; - let mut app = Applicability::MachineApplicable; - let recv = Sugg::hir_with_context(cx, recv, span.ctxt(), default_snip, &mut app).maybe_par(); +fn get_ty_sugg(cx: &LateContext<'_>, arg: &Expr<'_>, bound_expr: &Expr<'_>) -> Option<(Span, &'static str)> { + if let ExprKind::Lit(lit) = bound_expr.kind + && let local_hid = path_to_local(arg)? + && let Node::Param(Param { ty_span, span, .. }) = cx.tcx.parent_hir_node(local_hid) + // `ty_span` and `span` are the same for inferred type, thus a type suggestion must be given + && ty_span == span + { + let ty_str = match lit.node { + Char(_) => "char", + Byte(_) => "u8", + _ => return None, + }; + return Some((*ty_span, ty_str)); + } + None +} - span_lint_and_sugg( - cx, - MANUAL_IS_ASCII_CHECK, - span, - "manual check for common ascii range", - "try", - format!("{recv}.{sugg}()"), - app, - ); +fn check_is_ascii( + cx: &LateContext<'_>, + span: Span, + recv: &Expr<'_>, + range: &CharRange, + ty_sugg: Option<(Span, &'_ str)>, +) { + let sugg = match range { + CharRange::UpperChar => "is_ascii_uppercase", + CharRange::LowerChar => "is_ascii_lowercase", + CharRange::FullChar => "is_ascii_alphabetic", + CharRange::Digit => "is_ascii_digit", + CharRange::HexDigit => "is_ascii_hexdigit", + CharRange::Otherwise | CharRange::LowerHexLetter | CharRange::UpperHexLetter => return, + }; + let default_snip = ".."; + let mut app = Applicability::MachineApplicable; + let recv = Sugg::hir_with_context(cx, recv, span.ctxt(), default_snip, &mut app).maybe_par(); + let mut suggestion = vec![(span, format!("{recv}.{sugg}()"))]; + if let Some((ty_span, ty_str)) = ty_sugg { + suggestion.push((ty_span, format!("{recv}: {ty_str}"))); } + + span_lint_and_then( + cx, + MANUAL_IS_ASCII_CHECK, + span, + "manual check for common ascii range", + |diag| { + diag.multipart_suggestion("try", suggestion, app); + }, + ); } fn check_pat(pat_kind: &PatKind<'_>) -> CharRange { @@ -187,11 +210,3 @@ fn check_range(start: &Expr<'_>, end: &Expr<'_>) -> CharRange { CharRange::Otherwise } } - -fn is_matches_macro(cx: &LateContext<'_>, macro_def_id: DefId) -> bool { - if let Some(name) = cx.tcx.get_diagnostic_name(macro_def_id) { - return sym::matches_macro == name; - } - - false -} diff --git a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs index 6746920edc5..90cfdecc199 100644 --- a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs @@ -1,3 +1,4 @@ +use clippy_config::msrvs::Msrv; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::IfLetOrMatch; use clippy_utils::source::snippet; @@ -11,12 +12,12 @@ use rustc_hir::{Arm, Expr, HirId, Pat, PatKind}; use rustc_lint::LateContext; use rustc_span::Span; -use super::COLLAPSIBLE_MATCH; +use super::{pat_contains_disallowed_or, COLLAPSIBLE_MATCH}; -pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) { +pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], msrv: &Msrv) { if let Some(els_arm) = arms.iter().rfind(|arm| arm_is_wild_like(cx, arm)) { for arm in arms { - check_arm(cx, true, arm.pat, arm.body, arm.guard, Some(els_arm.body)); + check_arm(cx, true, arm.pat, arm.body, arm.guard, Some(els_arm.body), msrv); } } } @@ -26,8 +27,9 @@ pub(super) fn check_if_let<'tcx>( pat: &'tcx Pat<'_>, body: &'tcx Expr<'_>, else_expr: Option<&'tcx Expr<'_>>, + msrv: &Msrv, ) { - check_arm(cx, false, pat, body, None, else_expr); + check_arm(cx, false, pat, body, None, else_expr, msrv); } fn check_arm<'tcx>( @@ -37,6 +39,7 @@ fn check_arm<'tcx>( outer_then_body: &'tcx Expr<'tcx>, outer_guard: Option<&'tcx Expr<'tcx>>, outer_else_body: Option<&'tcx Expr<'tcx>>, + msrv: &Msrv, ) { let inner_expr = peel_blocks_with_stmt(outer_then_body); if let Some(inner) = IfLetOrMatch::parse(cx, inner_expr) @@ -57,7 +60,7 @@ fn check_arm<'tcx>( // match expression must be a local binding // match <local> { .. } && let Some(binding_id) = path_to_local(peel_ref_operators(cx, inner_scrutinee)) - && !pat_contains_or(inner_then_pat) + && !pat_contains_disallowed_or(inner_then_pat, msrv) // the binding must come from the pattern of the containing match arm // ..<local>.. => match <local> { .. } && let (Some(binding_span), is_innermost_parent_pat_struct) @@ -142,13 +145,3 @@ fn find_pat_binding_and_is_innermost_parent_pat_struct(pat: &Pat<'_>, hir_id: Hi }); (span, is_innermost_parent_pat_struct) } - -fn pat_contains_or(pat: &Pat<'_>) -> bool { - let mut result = false; - pat.walk(|p| { - let is_or = matches!(p.kind, PatKind::Or(_)); - result |= is_or; - !is_or - }); - result -} diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs index fae2c4e4af9..ee9f48d71ad 100644 --- a/src/tools/clippy/clippy_lints/src/matches/mod.rs +++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs @@ -27,7 +27,7 @@ mod wild_in_or_pats; use clippy_config::msrvs::{self, Msrv}; use clippy_utils::source::walk_span_to_context; use clippy_utils::{higher, in_constant, is_direct_expn_of, is_span_match, span_contains_cfg}; -use rustc_hir::{Arm, Expr, ExprKind, LetStmt, MatchSource, Pat}; +use rustc_hir::{Arm, Expr, ExprKind, LetStmt, MatchSource, Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; @@ -1040,7 +1040,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches { significant_drop_in_scrutinee::check(cx, expr, ex, arms, source); } - collapsible_match::check_match(cx, arms); + collapsible_match::check_match(cx, arms, &self.msrv); if !from_expansion { // These don't depend on a relationship between multiple arms match_wild_err_arm::check(cx, ex, arms); @@ -1066,7 +1066,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches { needless_match::check_match(cx, ex, arms, expr); match_on_vec_items::check(cx, ex); match_str_case_mismatch::check(cx, ex, arms); - redundant_guards::check(cx, arms); + redundant_guards::check(cx, arms, &self.msrv); if !in_constant(cx, expr.hir_id) { manual_unwrap_or::check(cx, expr, ex, arms); @@ -1083,7 +1083,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches { match_ref_pats::check(cx, ex, arms.iter().map(|el| el.pat), expr); } } else if let Some(if_let) = higher::IfLet::hir(cx, expr) { - collapsible_match::check_if_let(cx, if_let.let_pat, if_let.if_then, if_let.if_else); + collapsible_match::check_if_let(cx, if_let.let_pat, if_let.if_then, if_let.if_else, &self.msrv); if !from_expansion { if let Some(else_expr) = if_let.if_else { if self.msrv.meets(msrvs::MATCHES_MACRO) { @@ -1195,3 +1195,18 @@ fn contains_cfg_arm(cx: &LateContext<'_>, e: &Expr<'_>, scrutinee: &Expr<'_>, ar Err(()) => true, } } + +/// Checks if `pat` contains OR patterns that cannot be nested due to a too low MSRV. +fn pat_contains_disallowed_or(pat: &Pat<'_>, msrv: &Msrv) -> bool { + if msrv.meets(msrvs::OR_PATTERNS) { + return false; + } + + let mut result = false; + pat.walk(|p| { + let is_or = matches!(p.kind, PatKind::Or(_)); + result |= is_or; + !is_or + }); + result +} diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs index 50cbccc3968..a75cf37945f 100644 --- a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs +++ b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs @@ -1,40 +1,32 @@ +use clippy_config::msrvs::Msrv; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::macros::matching_root_macro_call; use clippy_utils::source::snippet; use clippy_utils::visitors::{for_each_expr, is_local_used}; use clippy_utils::{in_constant, path_to_local}; use rustc_ast::{BorrowKind, LitKind}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{Arm, BinOpKind, Expr, ExprKind, MatchSource, Node, Pat, PatKind, UnOp}; +use rustc_hir::{Arm, BinOpKind, Expr, ExprKind, MatchSource, Node, PatKind, UnOp}; use rustc_lint::LateContext; use rustc_span::symbol::Ident; -use rustc_span::{Span, Symbol}; +use rustc_span::{sym, Span, Symbol}; use std::borrow::Cow; use std::ops::ControlFlow; -use super::REDUNDANT_GUARDS; +use super::{pat_contains_disallowed_or, REDUNDANT_GUARDS}; -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>]) { +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>], msrv: &Msrv) { for outer_arm in arms { let Some(guard) = outer_arm.guard else { continue; }; // `Some(x) if matches!(x, y)` - if let ExprKind::Match( - scrutinee, - [ - arm, - Arm { - pat: Pat { - kind: PatKind::Wild, .. - }, - .. - }, - ], - MatchSource::Normal, - ) = guard.kind + if let ExprKind::Match(scrutinee, [arm, _], MatchSource::Normal) = guard.kind + && matching_root_macro_call(cx, guard.span, sym::matches_macro).is_some() && let Some(binding) = get_pat_binding(cx, scrutinee, outer_arm) + && !pat_contains_disallowed_or(arm.pat, msrv) { let pat_span = match (arm.pat.kind, binding.byref_ident) { (PatKind::Ref(pat, _), Some(_)) => pat.span, @@ -53,6 +45,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>]) { // `Some(x) if let Some(2) = x` else if let ExprKind::Let(let_expr) = guard.kind && let Some(binding) = get_pat_binding(cx, let_expr.init, outer_arm) + && !pat_contains_disallowed_or(let_expr.pat, msrv) { let pat_span = match (let_expr.pat.kind, binding.byref_ident) { (PatKind::Ref(pat, _), Some(_)) => pat.span, diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs index 37f72528140..69791414f72 100644 --- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs @@ -75,7 +75,7 @@ fn report_single_pattern( ) { let lint = if els.is_some() { SINGLE_MATCH_ELSE } else { SINGLE_MATCH }; let ctxt = expr.span.ctxt(); - let mut app = Applicability::HasPlaceholders; + let mut app = Applicability::MachineApplicable; let els_str = els.map_or(String::new(), |els| { format!(" else {}", expr_block(cx, els, ctxt, "..", Some(expr.span), &mut app)) }); diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs index 581e3b308c3..02a11257007 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; -use clippy_utils::macros::{is_panic, root_macro_call}; +use clippy_utils::macros::{is_panic, matching_root_macro_call, root_macro_call}; use clippy_utils::source::{indent_of, reindent_multiline, snippet}; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{higher, is_trait_method, path_to_local_id, peel_blocks, SpanlessEq}; @@ -247,8 +247,7 @@ impl<'tcx> OffendingFilterExpr<'tcx> { } else { None } - } else if let Some(macro_call) = root_macro_call(expr.span) - && cx.tcx.get_diagnostic_name(macro_call.def_id) == Some(sym::matches_macro) + } else if matching_root_macro_call(cx, expr.span, sym::matches_macro).is_some() // we know for a fact that the wildcard pattern is the second arm && let ExprKind::Match(scrutinee, [arm, _], _) = expr.kind && path_to_local_id(scrutinee, filter_param_id) diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs index 6d70989546a..03b4680c522 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs @@ -89,8 +89,7 @@ pub(super) fn check<'tcx>( } match it.kind { - PatKind::Binding(BindingMode(_, Mutability::Mut), _, _, _) - | PatKind::Ref(_, Mutability::Mut) => { + PatKind::Binding(BindingMode(_, Mutability::Mut), _, _, _) | PatKind::Ref(_, Mutability::Mut) => { to_be_discarded = true; false }, diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index 0939c028564..63545d6c503 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -1145,11 +1145,16 @@ declare_clippy_lint! { /// `str` as an argument, e.g., `_.split("x")`. /// /// ### Why is this bad? - /// Performing these methods using a `char` is faster than - /// using a `str`. + /// While this can make a perf difference on some systems, + /// benchmarks have proven inconclusive. But at least using a + /// char literal makes it clear that we are looking at a single + /// character. /// /// ### Known problems - /// Does not catch multi-byte unicode characters. + /// Does not catch multi-byte unicode characters. This is by + /// design, on many machines, splitting by a non-ascii char is + /// actually slower. Please do your own measurements instead of + /// relying solely on the results of this lint. /// /// ### Example /// ```rust,ignore @@ -1162,7 +1167,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "pre 1.29.0"] pub SINGLE_CHAR_PATTERN, - perf, + pedantic, "using a single-character str where a char could be used, e.g., `_.split(\"x\")`" } @@ -3988,7 +3993,7 @@ declare_clippy_lint! { /// let x: Result<u32, ()> = Ok(0); /// let y = x.unwrap_or_else(|err| handle_error(err)); /// ``` - #[clippy::version = "1.77.0"] + #[clippy::version = "1.78.0"] pub UNNECESSARY_RESULT_MAP_OR_ELSE, suspicious, "making no use of the \"map closure\" when calling `.map_or_else(|err| handle_error(err), |n| n)`" @@ -4022,7 +4027,7 @@ declare_clippy_lint! { /// needs_cstr(c"Hello"); /// unsafe { libc::puts(c"World".as_ptr()) } /// ``` - #[clippy::version = "1.76.0"] + #[clippy::version = "1.78.0"] pub MANUAL_C_STR_LITERALS, pedantic, r#"creating a `CStr` through functions when `c""` literals can be used"# diff --git a/src/tools/clippy/clippy_lints/src/methods/readonly_write_lock.rs b/src/tools/clippy/clippy_lints/src/methods/readonly_write_lock.rs index 9b0180d9369..774aaec1afd 100644 --- a/src/tools/clippy/clippy_lints/src/methods/readonly_write_lock.rs +++ b/src/tools/clippy/clippy_lints/src/methods/readonly_write_lock.rs @@ -4,7 +4,7 @@ use clippy_utils::mir::{enclosing_mir, visit_local_usage}; use clippy_utils::source::snippet; use clippy_utils::ty::is_type_diagnostic_item; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, Node}; +use rustc_hir::{Expr, ExprKind, Node, PatKind}; use rustc_lint::LateContext; use rustc_middle::mir::{Location, START_BLOCK}; use rustc_span::sym; @@ -25,6 +25,11 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, receiver && is_unwrap_call(cx, unwrap_call_expr) && let parent = cx.tcx.parent_hir_node(unwrap_call_expr.hir_id) && let Node::LetStmt(local) = parent + && let PatKind::Binding(.., ident, _) = local.pat.kind + // if the binding is prefixed with `_`, it typically means + // that this guard only exists to protect a section of code + // rather than the contained data + && !ident.as_str().starts_with('_') && let Some(mir) = enclosing_mir(cx.tcx, expr.hir_id) && let Some((local, _)) = mir .local_decls diff --git a/src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs b/src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs index 44a7ad394fa..20ec2b74d81 100644 --- a/src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs +++ b/src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs @@ -10,7 +10,7 @@ use super::SINGLE_CHAR_ADD_STR; /// lint for length-1 `str`s as argument for `insert_str` pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { let mut applicability = Applicability::MachineApplicable; - if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[1], &mut applicability) { + if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[1], &mut applicability, false) { let base_string_snippet = snippet_with_applicability(cx, receiver.span.source_callsite(), "_", &mut applicability); let pos_arg = snippet_with_applicability(cx, args[0].span, "..", &mut applicability); diff --git a/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs b/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs index 363b1f2b812..982a7901c45 100644 --- a/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs +++ b/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs @@ -8,7 +8,7 @@ use rustc_span::symbol::Symbol; use super::SINGLE_CHAR_PATTERN; -const PATTERN_METHODS: [(&str, usize); 24] = [ +const PATTERN_METHODS: [(&str, usize); 22] = [ ("contains", 0), ("starts_with", 0), ("ends_with", 0), @@ -27,8 +27,6 @@ const PATTERN_METHODS: [(&str, usize); 24] = [ ("rmatches", 0), ("match_indices", 0), ("rmatch_indices", 0), - ("strip_prefix", 0), - ("strip_suffix", 0), ("trim_start_matches", 0), ("trim_end_matches", 0), ("replace", 0), @@ -50,7 +48,7 @@ pub(super) fn check( && args.len() > pos && let arg = &args[pos] && let mut applicability = Applicability::MachineApplicable - && let Some(hint) = get_hint_if_single_char_arg(cx, arg, &mut applicability) + && let Some(hint) = get_hint_if_single_char_arg(cx, arg, &mut applicability, true) { span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs b/src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs index 0698bd6a0c5..97c13825bc1 100644 --- a/src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs +++ b/src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs @@ -10,7 +10,7 @@ use super::SINGLE_CHAR_ADD_STR; /// lint for length-1 `str`s as argument for `push_str` pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { let mut applicability = Applicability::MachineApplicable; - if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[0], &mut applicability) { + if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[0], &mut applicability, false) { let base_string_snippet = snippet_with_applicability(cx, receiver.span.source_callsite(), "..", &mut applicability); let sugg = format!("{base_string_snippet}.push({extension_string})"); diff --git a/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs b/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs index e5cc898612e..8b8a965b9f0 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_hir_and_then}; -use clippy_utils::paths::{CORE_ITER_ENUMERATE_METHOD, CORE_ITER_ENUMERATE_STRUCT}; use clippy_utils::source::{snippet, snippet_opt}; -use clippy_utils::{expr_or_init, is_trait_method, match_def_path, pat_is_wild}; +use clippy_utils::{expr_or_init, is_trait_method, pat_is_wild}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, FnDecl, PatKind, TyKind}; use rustc_lint::LateContext; @@ -42,7 +41,7 @@ pub(super) fn check(cx: &LateContext<'_>, call_expr: &Expr<'_>, recv: &Expr<'_>, let recv_ty = cx.typeck_results().expr_ty(recv); if let Some(recv_ty_defid) = recv_ty.ty_adt_def().map(AdtDef::did) // If we call a method on a `std::iter::Enumerate` instance - && match_def_path(cx, recv_ty_defid, &CORE_ITER_ENUMERATE_STRUCT) + && cx.tcx.is_diagnostic_item(sym::Enumerate, recv_ty_defid) // If we are calling a method of the `Iterator` trait && is_trait_method(cx, call_expr, sym::Iterator) // And the map argument is a closure @@ -75,10 +74,10 @@ pub(super) fn check(cx: &LateContext<'_>, call_expr: &Expr<'_>, recv: &Expr<'_>, && let ExprKind::MethodCall(_, enumerate_recv, _, enumerate_span) = recv_init_expr.kind && let Some(enumerate_defid) = cx.typeck_results().type_dependent_def_id(recv_init_expr.hir_id) // Make sure the method call is `std::iter::Iterator::enumerate`. - && match_def_path(cx, enumerate_defid, &CORE_ITER_ENUMERATE_METHOD) + && cx.tcx.is_diagnostic_item(sym::enumerate_method, enumerate_defid) { // Check if the tuple type was explicit. It may be the type system _needs_ the type of the element - // that would be explicited in the closure. + // that would be explicitly in the closure. let new_closure_param = match find_elem_explicit_type_span(closure.fn_decl) { // We have an explicit type. Get its snippet, that of the binding name, and do `binding: ty`. // Fallback to `..` if we fail getting either snippet. diff --git a/src/tools/clippy/clippy_lints/src/methods/utils.rs b/src/tools/clippy/clippy_lints/src/methods/utils.rs index ef00c812d51..c50f24f824a 100644 --- a/src/tools/clippy/clippy_lints/src/methods/utils.rs +++ b/src/tools/clippy/clippy_lints/src/methods/utils.rs @@ -52,11 +52,17 @@ pub(super) fn get_hint_if_single_char_arg( cx: &LateContext<'_>, arg: &Expr<'_>, applicability: &mut Applicability, + ascii_only: bool, ) -> Option<String> { if let ExprKind::Lit(lit) = &arg.kind && let ast::LitKind::Str(r, style) = lit.node && let string = r.as_str() - && string.chars().count() == 1 + && let len = if ascii_only { + string.len() + } else { + string.chars().count() + } + && len == 1 { let snip = snippet_with_applicability(cx, arg.span, string, applicability); let ch = if let ast::StrStyle::Raw(nhash) = style { diff --git a/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs b/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs index 191b32408ef..d608f3bf7b4 100644 --- a/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs +++ b/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs @@ -29,7 +29,7 @@ declare_clippy_lint! { /// F: Sized + std::fmt::Debug, /// {} /// ``` - #[clippy::version = "1.77.0"] + #[clippy::version = "1.78.0"] pub MULTIPLE_BOUND_LOCATIONS, suspicious, "defining generic bounds in multiple locations" diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs index 8c2f43c97f4..2eb534da092 100644 --- a/src/tools/clippy/clippy_lints/src/mut_key.rs +++ b/src/tools/clippy/clippy_lints/src/mut_key.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint; -use clippy_utils::ty::is_interior_mut_ty; -use clippy_utils::{def_path_def_ids, trait_ref_of_method}; -use rustc_data_structures::fx::FxHashSet; +use clippy_utils::trait_ref_of_method; +use clippy_utils::ty::InteriorMut; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, Ty}; @@ -23,27 +22,15 @@ declare_clippy_lint! { /// ### Known problems /// /// #### False Positives - /// It's correct to use a struct that contains interior mutability as a key, when its + /// It's correct to use a struct that contains interior mutability as a key when its /// implementation of `Hash` or `Ord` doesn't access any of the interior mutable types. /// However, this lint is unable to recognize this, so it will often cause false positives in - /// theses cases. The `bytes` crate is a great example of this. + /// these cases. /// /// #### False Negatives - /// For custom `struct`s/`enum`s, this lint is unable to check for interior mutability behind - /// indirection. For example, `struct BadKey<'a>(&'a Cell<usize>)` will be seen as immutable - /// and cause a false negative if its implementation of `Hash`/`Ord` accesses the `Cell`. - /// - /// This lint does check a few cases for indirection. Firstly, using some standard library - /// types (`Option`, `Result`, `Box`, `Rc`, `Arc`, `Vec`, `VecDeque`, `BTreeMap` and - /// `BTreeSet`) directly as keys (e.g. in `HashMap<Box<Cell<usize>>, ()>`) **will** trigger the - /// lint, because the impls of `Hash`/`Ord` for these types directly call `Hash`/`Ord` on their - /// contained type. - /// - /// Secondly, the implementations of `Hash` and `Ord` for raw pointers (`*const T` or `*mut T`) - /// apply only to the **address** of the contained value. Therefore, interior mutability - /// behind raw pointers (e.g. in `HashSet<*mut Cell<usize>>`) can't impact the value of `Hash` - /// or `Ord`, and therefore will not trigger this link. For more info, see issue - /// [#6745](https://github.com/rust-lang/rust-clippy/issues/6745). + /// This lint does not follow raw pointers (`*const T` or `*mut T`) as `Hash` and `Ord` + /// apply only to the **address** of the contained value. This can cause false negatives for + /// custom collections that use raw pointers internally. /// /// ### Example /// ```no_run @@ -51,13 +38,12 @@ declare_clippy_lint! { /// use std::collections::HashSet; /// use std::hash::{Hash, Hasher}; /// use std::sync::atomic::AtomicUsize; - ///# #[allow(unused)] /// /// struct Bad(AtomicUsize); /// impl PartialEq for Bad { /// fn eq(&self, rhs: &Self) -> bool { /// .. - /// ; unimplemented!(); + /// # ; true /// } /// } /// @@ -66,7 +52,7 @@ declare_clippy_lint! { /// impl Hash for Bad { /// fn hash<H: Hasher>(&self, h: &mut H) { /// .. - /// ; unimplemented!(); + /// # ; /// } /// } /// @@ -80,25 +66,16 @@ declare_clippy_lint! { "Check for mutable `Map`/`Set` key type" } -#[derive(Clone)] -pub struct MutableKeyType { +pub struct MutableKeyType<'tcx> { ignore_interior_mutability: Vec<String>, - ignore_mut_def_ids: FxHashSet<hir::def_id::DefId>, + interior_mut: InteriorMut<'tcx>, } -impl_lint_pass!(MutableKeyType => [ MUTABLE_KEY_TYPE ]); +impl_lint_pass!(MutableKeyType<'_> => [ MUTABLE_KEY_TYPE ]); -impl<'tcx> LateLintPass<'tcx> for MutableKeyType { +impl<'tcx> LateLintPass<'tcx> for MutableKeyType<'tcx> { fn check_crate(&mut self, cx: &LateContext<'tcx>) { - self.ignore_mut_def_ids.clear(); - let mut path = Vec::new(); - for ty in &self.ignore_interior_mutability { - path.extend(ty.split("::")); - for id in def_path_def_ids(cx, &path[..]) { - self.ignore_mut_def_ids.insert(id); - } - path.clear(); - } + self.interior_mut = InteriorMut::without_pointers(cx, &self.ignore_interior_mutability); } fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { @@ -121,7 +98,7 @@ impl<'tcx> LateLintPass<'tcx> for MutableKeyType { } } - fn check_local(&mut self, cx: &LateContext<'_>, local: &hir::LetStmt<'_>) { + fn check_local(&mut self, cx: &LateContext<'tcx>, local: &hir::LetStmt<'tcx>) { if let hir::PatKind::Wild = local.pat.kind { return; } @@ -129,15 +106,15 @@ impl<'tcx> LateLintPass<'tcx> for MutableKeyType { } } -impl MutableKeyType { +impl<'tcx> MutableKeyType<'tcx> { pub fn new(ignore_interior_mutability: Vec<String>) -> Self { Self { ignore_interior_mutability, - ignore_mut_def_ids: FxHashSet::default(), + interior_mut: InteriorMut::default(), } } - fn check_sig(&self, cx: &LateContext<'_>, fn_def_id: LocalDefId, decl: &hir::FnDecl<'_>) { + fn check_sig(&mut self, cx: &LateContext<'tcx>, fn_def_id: LocalDefId, decl: &hir::FnDecl<'tcx>) { let fn_sig = cx.tcx.fn_sig(fn_def_id).instantiate_identity(); for (hir_ty, ty) in iter::zip(decl.inputs, fn_sig.inputs().skip_binder()) { self.check_ty_(cx, hir_ty.span, *ty); @@ -151,7 +128,7 @@ impl MutableKeyType { // We want to lint 1. sets or maps with 2. not immutable key types and 3. no unerased // generics (because the compiler cannot ensure immutability for unknown types). - fn check_ty_<'tcx>(&self, cx: &LateContext<'tcx>, span: Span, ty: Ty<'tcx>) { + fn check_ty_(&mut self, cx: &LateContext<'tcx>, span: Span, ty: Ty<'tcx>) { let ty = ty.peel_refs(); if let ty::Adt(def, args) = ty.kind() { let is_keyed_type = [sym::HashMap, sym::BTreeMap, sym::HashSet, sym::BTreeSet] @@ -162,11 +139,7 @@ impl MutableKeyType { } let subst_ty = args.type_at(0); - // Determines if a type contains interior mutability which would affect its implementation of - // [`Hash`] or [`Ord`]. - if is_interior_mut_ty(cx, subst_ty) - && !matches!(subst_ty.ty_adt_def(), Some(adt) if self.ignore_mut_def_ids.contains(&adt.did())) - { + if self.interior_mut.is_interior_mut_ty(cx, subst_ty) { span_lint(cx, MUTABLE_KEY_TYPE, span, "mutable key type"); } } diff --git a/src/tools/clippy/clippy_lints/src/needless_for_each.rs b/src/tools/clippy/clippy_lints/src/needless_for_each.rs index 84a07df1bb0..630018238f4 100644 --- a/src/tools/clippy/clippy_lints/src/needless_for_each.rs +++ b/src/tools/clippy/clippy_lints/src/needless_for_each.rs @@ -1,6 +1,6 @@ use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, Visitor}; -use rustc_hir::{Closure, Expr, ExprKind, Stmt, StmtKind}; +use rustc_hir::{Block, BlockCheckMode, Closure, Expr, ExprKind, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use rustc_span::{sym, Span, Symbol}; @@ -35,6 +35,16 @@ declare_clippy_lint! { /// println!("{}", elem); /// } /// ``` + /// + /// ### Known Problems + /// When doing things such as: + /// ```ignore + /// let v = vec![0, 1, 2]; + /// v.iter().for_each(|elem| unsafe { + /// libc::printf(c"%d\n".as_ptr(), elem); + /// }); + /// ``` + /// This lint will not trigger. #[clippy::version = "1.53.0"] pub NEEDLESS_FOR_EACH, pedantic, @@ -68,7 +78,9 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessForEach { // e.g. `v.iter().for_each(f)` is simpler and clearer than using `for` loop. && let ExprKind::Closure(&Closure { body, .. }) = for_each_arg.kind && let body = cx.tcx.hir().body(body) - && let ExprKind::Block(..) = body.value.kind + // Skip the lint if the body is not safe, so as not to suggest `for … in … unsafe {}` + // and suggesting `for … in … { unsafe { } }` is a little ugly. + && let ExprKind::Block(Block { rules: BlockCheckMode::DefaultBlock, .. }, ..) = body.value.kind { let mut ret_collector = RetCollector::default(); ret_collector.visit_expr(body.value); diff --git a/src/tools/clippy/clippy_lints/src/needless_late_init.rs b/src/tools/clippy/clippy_lints/src/needless_late_init.rs index 0c0b1a73351..6605d1fa51a 100644 --- a/src/tools/clippy/clippy_lints/src/needless_late_init.rs +++ b/src/tools/clippy/clippy_lints/src/needless_late_init.rs @@ -6,8 +6,7 @@ use clippy_utils::visitors::{for_each_expr, for_each_expr_with_closures, is_loca use core::ops::ControlFlow; use rustc_errors::{Applicability, MultiSpan}; use rustc_hir::{ - BindingMode, Block, Expr, ExprKind, HirId, LetStmt, LocalSource, MatchSource, Node, Pat, PatKind, Stmt, - StmtKind, + BindingMode, Block, Expr, ExprKind, HirId, LetStmt, LocalSource, MatchSource, Node, Pat, PatKind, Stmt, StmtKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs index 30d3e86dc4e..9e47c3ad0b7 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs @@ -83,7 +83,9 @@ fn should_skip<'tcx>( } if is_self(arg) { - return true; + // Interestingly enough, `self` arguments make `is_from_proc_macro` return `true`, hence why + // we return early here. + return false; } if let PatKind::Binding(.., name, _) = arg.pat.kind { @@ -185,7 +187,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> { } // Collect variables mutably used and spans which will need dereferencings from the // function body. - let MutablyUsedVariablesCtxt { mutably_used_vars, .. } = { + let mutably_used_vars = { let mut ctx = MutablyUsedVariablesCtxt { mutably_used_vars: HirIdSet::default(), prev_bind: None, @@ -217,7 +219,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> { check_closures(&mut ctx, cx, &infcx, &mut checked_closures, async_closures); } } - ctx + ctx.generate_mutably_used_ids_from_aliases() }; for ((&input, &_), arg) in it { // Only take `&mut` arguments. @@ -309,12 +311,22 @@ struct MutablyUsedVariablesCtxt<'tcx> { } impl<'tcx> MutablyUsedVariablesCtxt<'tcx> { - fn add_mutably_used_var(&mut self, mut used_id: HirId) { - while let Some(id) = self.aliases.get(&used_id) { + fn add_mutably_used_var(&mut self, used_id: HirId) { + self.mutably_used_vars.insert(used_id); + } + + // Because the alias may come after the mutable use of a variable, we need to fill the map at + // the end. + fn generate_mutably_used_ids_from_aliases(mut self) -> HirIdSet { + let all_ids = self.mutably_used_vars.iter().copied().collect::<Vec<_>>(); + for mut used_id in all_ids { + while let Some(id) = self.aliases.get(&used_id) { + self.mutably_used_vars.insert(used_id); + used_id = *id; + } self.mutably_used_vars.insert(used_id); - used_id = *id; } - self.mutably_used_vars.insert(used_id); + self.mutably_used_vars } fn would_be_alias_cycle(&self, alias: HirId, mut target: HirId) -> bool { 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 53bcde68087..39d374d0d27 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 @@ -9,8 +9,8 @@ use rustc_ast::ast::Attribute; use rustc_errors::{Applicability, Diag}; use rustc_hir::intravisit::FnKind; use rustc_hir::{ - BindingMode, Body, FnDecl, GenericArg, HirId, HirIdSet, Impl, ItemKind, LangItem, Mutability, Node, PatKind, - QPath, TyKind, + BindingMode, Body, FnDecl, GenericArg, HirId, HirIdSet, Impl, ItemKind, LangItem, Mutability, Node, PatKind, QPath, + TyKind, }; use rustc_hir_typeck::expr_use_visitor as euv; use rustc_infer::infer::TyCtxtInferExt; diff --git a/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs b/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs index fd3985a5daf..932d6fe54d6 100644 --- a/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs +++ b/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs @@ -182,17 +182,17 @@ impl LateLintPass<'_> for NonCanonicalImpls { if block.stmts.is_empty() && let Some(expr) = block.expr - && let ExprKind::Call( - Expr { - kind: ExprKind::Path(some_path), - hir_id: some_hir_id, - .. - }, - [cmp_expr], - ) = expr.kind - && is_res_lang_ctor(cx, cx.qpath_res(some_path, *some_hir_id), LangItem::OptionSome) - // Fix #11178, allow `Self::cmp(self, ..)` too - && self_cmp_call(cx, cmp_expr, impl_item.owner_id.def_id, &mut needs_fully_qualified) + && expr_is_cmp(cx, &expr.kind, impl_item, &mut needs_fully_qualified) + { + } + // Fix #12683, allow [`needless_return`] here + else if block.expr.is_none() + && let Some(stmt) = block.stmts.first() + && let rustc_hir::StmtKind::Semi(Expr { + kind: ExprKind::Ret(Some(Expr { kind: ret_kind, .. })), + .. + }) = stmt.kind + && expr_is_cmp(cx, ret_kind, impl_item, &mut needs_fully_qualified) { } else { // If `Self` and `Rhs` are not the same type, bail. This makes creating a valid @@ -245,6 +245,30 @@ impl LateLintPass<'_> for NonCanonicalImpls { } } +/// Return true if `expr_kind` is a `cmp` call. +fn expr_is_cmp<'tcx>( + cx: &LateContext<'tcx>, + expr_kind: &'tcx ExprKind<'tcx>, + impl_item: &ImplItem<'_>, + needs_fully_qualified: &mut bool, +) -> bool { + if let ExprKind::Call( + Expr { + kind: ExprKind::Path(some_path), + hir_id: some_hir_id, + .. + }, + [cmp_expr], + ) = expr_kind + { + is_res_lang_ctor(cx, cx.qpath_res(some_path, *some_hir_id), LangItem::OptionSome) + // Fix #11178, allow `Self::cmp(self, ..)` too + && self_cmp_call(cx, cmp_expr, impl_item.owner_id.def_id, needs_fully_qualified) + } else { + false + } +} + /// Returns whether this is any of `self.cmp(..)`, `Self::cmp(self, ..)` or `Ord::cmp(self, ..)`. fn self_cmp_call<'tcx>( cx: &LateContext<'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 ff10a841aef..76d9cee18aa 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -5,9 +5,9 @@ use std::ptr; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::in_constant; use clippy_utils::macros::macro_backtrace; -use clippy_utils::{def_path_def_ids, in_constant}; -use rustc_data_structures::fx::FxHashSet; +use clippy_utils::ty::InteriorMut; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{ @@ -52,8 +52,8 @@ declare_clippy_lint! { /// There're other enums plus associated constants cases that the lint cannot handle. /// /// Types that have underlying or potential interior mutability trigger the lint whether - /// the interior mutable field is used or not. See issues - /// [#5812](https://github.com/rust-lang/rust-clippy/issues/5812) and + /// the interior mutable field is used or not. See issue + /// [#5812](https://github.com/rust-lang/rust-clippy/issues/5812) /// /// ### Example /// ```no_run @@ -170,42 +170,22 @@ fn lint(cx: &LateContext<'_>, source: Source) { }); } -#[derive(Clone)] -pub struct NonCopyConst { +pub struct NonCopyConst<'tcx> { ignore_interior_mutability: Vec<String>, - ignore_mut_def_ids: FxHashSet<DefId>, + interior_mut: InteriorMut<'tcx>, } -impl_lint_pass!(NonCopyConst => [DECLARE_INTERIOR_MUTABLE_CONST, BORROW_INTERIOR_MUTABLE_CONST]); +impl_lint_pass!(NonCopyConst<'_> => [DECLARE_INTERIOR_MUTABLE_CONST, BORROW_INTERIOR_MUTABLE_CONST]); -impl NonCopyConst { +impl<'tcx> NonCopyConst<'tcx> { pub fn new(ignore_interior_mutability: Vec<String>) -> Self { Self { ignore_interior_mutability, - ignore_mut_def_ids: FxHashSet::default(), + interior_mut: InteriorMut::default(), } } - fn is_ty_ignored(&self, ty: Ty<'_>) -> bool { - matches!(ty.ty_adt_def(), Some(adt) if self.ignore_mut_def_ids.contains(&adt.did())) - } - - fn is_unfrozen<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - // Ignore types whose layout is unknown since `is_freeze` reports every generic types as `!Freeze`, - // making it indistinguishable from `UnsafeCell`. i.e. it isn't a tool to prove a type is - // 'unfrozen'. However, this code causes a false negative in which - // a type contains a layout-unknown type, but also an unsafe cell like `const CELL: Cell<T>`. - // Yet, it's better than `ty.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_PROJECTION)` - // since it works when a pointer indirection involves (`Cell<*const T>`). - // Making up a `ParamEnv` where every generic params and assoc types are `Freeze`is another option; - // but I'm not sure whether it's a decent way, if possible. - cx.tcx.layout_of(cx.param_env.and(ty)).is_ok() && !ty.is_freeze(cx.tcx, cx.param_env) - } - - fn is_value_unfrozen_raw_inner<'tcx>(&self, cx: &LateContext<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> bool { - if self.is_ty_ignored(ty) { - return false; - } + fn is_value_unfrozen_raw_inner(cx: &LateContext<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> bool { match *ty.kind() { // the fact that we have to dig into every structs to search enums // leads us to the point checking `UnsafeCell` directly is the only option. @@ -216,8 +196,7 @@ impl NonCopyConst { ty::Array(ty, _) => val .unwrap_branch() .iter() - .any(|field| self.is_value_unfrozen_raw_inner(cx, *field, ty)), - ty::Adt(def, _) if def.is_union() => false, + .any(|field| Self::is_value_unfrozen_raw_inner(cx, *field, ty)), ty::Adt(def, args) if def.is_enum() => { let (&variant_index, fields) = val.unwrap_branch().split_first().unwrap(); let variant_index = VariantIdx::from_u32(variant_index.unwrap_leaf().try_to_u32().ok().unwrap()); @@ -230,24 +209,23 @@ impl NonCopyConst { .iter() .map(|field| field.ty(cx.tcx, args)), ) - .any(|(field, ty)| self.is_value_unfrozen_raw_inner(cx, field, ty)) + .any(|(field, ty)| Self::is_value_unfrozen_raw_inner(cx, field, ty)) }, ty::Adt(def, args) => val .unwrap_branch() .iter() .zip(def.non_enum_variant().fields.iter().map(|field| field.ty(cx.tcx, args))) - .any(|(field, ty)| self.is_value_unfrozen_raw_inner(cx, *field, ty)), + .any(|(field, ty)| Self::is_value_unfrozen_raw_inner(cx, *field, ty)), ty::Tuple(tys) => val .unwrap_branch() .iter() .zip(tys) - .any(|(field, ty)| self.is_value_unfrozen_raw_inner(cx, *field, ty)), + .any(|(field, ty)| Self::is_value_unfrozen_raw_inner(cx, *field, ty)), _ => false, } } - fn is_value_unfrozen_raw<'tcx>( - &self, + fn is_value_unfrozen_raw( cx: &LateContext<'tcx>, result: Result<Option<ty::ValTree<'tcx>>, ErrorHandled>, ty: Ty<'tcx>, @@ -277,11 +255,11 @@ impl NonCopyConst { // I chose this way because unfrozen enums as assoc consts are rare (or, hopefully, none). matches!(err, ErrorHandled::TooGeneric(..)) }, - |val| val.map_or(true, |val| self.is_value_unfrozen_raw_inner(cx, val, ty)), + |val| val.map_or(true, |val| Self::is_value_unfrozen_raw_inner(cx, val, ty)), ) } - fn is_value_unfrozen_poly<'tcx>(&self, cx: &LateContext<'tcx>, body_id: BodyId, ty: Ty<'tcx>) -> bool { + fn is_value_unfrozen_poly(cx: &LateContext<'tcx>, body_id: BodyId, ty: Ty<'tcx>) -> bool { let def_id = body_id.hir_id.owner.to_def_id(); let args = ty::GenericArgs::identity_for_item(cx.tcx, def_id); let instance = ty::Instance::new(def_id, args); @@ -291,17 +269,17 @@ impl NonCopyConst { }; let param_env = cx.tcx.param_env(def_id).with_reveal_all_normalized(cx.tcx); let result = cx.tcx.const_eval_global_id_for_typeck(param_env, cid, DUMMY_SP); - self.is_value_unfrozen_raw(cx, result, ty) + Self::is_value_unfrozen_raw(cx, result, ty) } - fn is_value_unfrozen_expr<'tcx>(&self, cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool { + fn is_value_unfrozen_expr(cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool { let args = cx.typeck_results().node_args(hir_id); let result = Self::const_eval_resolve(cx.tcx, cx.param_env, ty::UnevaluatedConst::new(def_id, args), DUMMY_SP); - self.is_value_unfrozen_raw(cx, result, ty) + Self::is_value_unfrozen_raw(cx, result, ty) } - pub fn const_eval_resolve<'tcx>( + pub fn const_eval_resolve( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ct: ty::UnevaluatedConst<'tcx>, @@ -321,26 +299,17 @@ impl NonCopyConst { } } -impl<'tcx> LateLintPass<'tcx> for NonCopyConst { +impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> { fn check_crate(&mut self, cx: &LateContext<'tcx>) { - self.ignore_mut_def_ids.clear(); - let mut path = Vec::new(); - for ty in &self.ignore_interior_mutability { - path.extend(ty.split("::")); - for id in def_path_def_ids(cx, &path[..]) { - self.ignore_mut_def_ids.insert(id); - } - path.clear(); - } + self.interior_mut = InteriorMut::new(cx, &self.ignore_interior_mutability); } fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx Item<'_>) { if let ItemKind::Const(.., body_id) = it.kind { let ty = cx.tcx.type_of(it.owner_id).instantiate_identity(); if !ignored_macro(cx, it) - && !self.is_ty_ignored(ty) - && Self::is_unfrozen(cx, ty) - && self.is_value_unfrozen_poly(cx, body_id, ty) + && self.interior_mut.is_interior_mut_ty(cx, ty) + && Self::is_value_unfrozen_poly(cx, body_id, ty) { lint(cx, Source::Item { item: it.span }); } @@ -354,7 +323,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { // Normalize assoc types because ones originated from generic params // bounded other traits could have their bound. let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty); - if !self.is_ty_ignored(ty) && Self::is_unfrozen(cx, normalized) + if self.interior_mut.is_interior_mut_ty(cx, normalized) // When there's no default value, lint it only according to its type; // in other words, lint consts whose value *could* be unfrozen, not definitely is. // This feels inconsistent with how the lint treats generic types, @@ -367,7 +336,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { // i.e. having an enum doesn't necessary mean a type has a frozen variant. // And, implementing it isn't a trivial task; it'll probably end up // re-implementing the trait predicate evaluation specific to `Freeze`. - && body_id_opt.map_or(true, |body_id| self.is_value_unfrozen_poly(cx, body_id, normalized)) + && body_id_opt.map_or(true, |body_id| Self::is_value_unfrozen_poly(cx, body_id, normalized)) { lint(cx, Source::Assoc { item: trait_item.span }); } @@ -409,8 +378,8 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { // e.g. `layout_of(...).is_err() || has_frozen_variant(...);` && let ty = cx.tcx.type_of(impl_item.owner_id).instantiate_identity() && let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty) - && !self.is_ty_ignored(ty) && Self::is_unfrozen(cx, normalized) - && self.is_value_unfrozen_poly(cx, *body_id, normalized) + && self.interior_mut.is_interior_mut_ty(cx, normalized) + && Self::is_value_unfrozen_poly(cx, *body_id, normalized) { lint(cx, Source::Assoc { item: impl_item.span }); } @@ -420,9 +389,8 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { // Normalize assoc types originated from generic params. let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty); - if !self.is_ty_ignored(ty) - && Self::is_unfrozen(cx, ty) - && self.is_value_unfrozen_poly(cx, *body_id, normalized) + if self.interior_mut.is_interior_mut_ty(cx, normalized) + && Self::is_value_unfrozen_poly(cx, *body_id, normalized) { lint(cx, Source::Assoc { item: impl_item.span }); } @@ -517,9 +485,8 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { cx.typeck_results().expr_ty(dereferenced_expr) }; - if !self.is_ty_ignored(ty) - && Self::is_unfrozen(cx, ty) - && self.is_value_unfrozen_expr(cx, expr.hir_id, item_def_id, ty) + if self.interior_mut.is_interior_mut_ty(cx, ty) + && Self::is_value_unfrozen_expr(cx, expr.hir_id, item_def_id, ty) { lint(cx, Source::Expr { expr: expr.span }); } diff --git a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs index 96ea063aa74..7d6f26cde3e 100644 --- a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs +++ b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs @@ -7,14 +7,13 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, Ty}; use rustc_session::impl_lint_pass; -use rustc_span::source_map::Spanned; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol}; use {rustc_ast as ast, rustc_hir as hir}; const HARD_CODED_ALLOWED_BINARY: &[[&str; 2]] = &[["f32", "f32"], ["f64", "f64"], ["std::string::String", "str"]]; const HARD_CODED_ALLOWED_UNARY: &[&str] = &["f32", "f64", "std::num::Saturating", "std::num::Wrapping"]; -const INTEGER_METHODS: &[Symbol] = &[ +const DISALLOWED_INT_METHODS: &[Symbol] = &[ sym::saturating_div, sym::wrapping_div, sym::wrapping_rem, @@ -27,8 +26,8 @@ pub struct ArithmeticSideEffects { allowed_unary: FxHashSet<String>, // Used to check whether expressions are constants, such as in enum discriminants and consts const_span: Option<Span>, + disallowed_int_methods: FxHashSet<Symbol>, expr_span: Option<Span>, - integer_methods: FxHashSet<Symbol>, } impl_lint_pass!(ArithmeticSideEffects => [ARITHMETIC_SIDE_EFFECTS]); @@ -53,8 +52,8 @@ impl ArithmeticSideEffects { allowed_binary, allowed_unary, const_span: None, + disallowed_int_methods: DISALLOWED_INT_METHODS.iter().copied().collect(), expr_span: None, - integer_methods: INTEGER_METHODS.iter().copied().collect(), } } @@ -91,10 +90,10 @@ impl ArithmeticSideEffects { fn has_specific_allowed_type_and_operation<'tcx>( cx: &LateContext<'tcx>, lhs_ty: Ty<'tcx>, - op: &Spanned<hir::BinOpKind>, + op: hir::BinOpKind, rhs_ty: Ty<'tcx>, ) -> bool { - let is_div_or_rem = matches!(op.node, hir::BinOpKind::Div | hir::BinOpKind::Rem); + let is_div_or_rem = matches!(op, hir::BinOpKind::Div | hir::BinOpKind::Rem); let is_non_zero_u = |cx: &LateContext<'tcx>, ty: Ty<'tcx>| { let tcx = cx.tcx; @@ -166,13 +165,35 @@ impl ArithmeticSideEffects { None } + /// Methods like `add_assign` are send to their `BinOps` references. + fn manage_sugar_methods<'tcx>( + &mut self, + cx: &LateContext<'tcx>, + expr: &'tcx hir::Expr<'_>, + lhs: &'tcx hir::Expr<'_>, + ps: &hir::PathSegment<'_>, + rhs: &'tcx hir::Expr<'_>, + ) { + if ps.ident.name == sym::add || ps.ident.name == sym::add_assign { + self.manage_bin_ops(cx, expr, hir::BinOpKind::Add, lhs, rhs); + } else if ps.ident.name == sym::div || ps.ident.name == sym::div_assign { + self.manage_bin_ops(cx, expr, hir::BinOpKind::Div, lhs, rhs); + } else if ps.ident.name == sym::mul || ps.ident.name == sym::mul_assign { + self.manage_bin_ops(cx, expr, hir::BinOpKind::Mul, lhs, rhs); + } else if ps.ident.name == sym::rem || ps.ident.name == sym::rem_assign { + self.manage_bin_ops(cx, expr, hir::BinOpKind::Rem, lhs, rhs); + } else if ps.ident.name == sym::sub || ps.ident.name == sym::sub_assign { + self.manage_bin_ops(cx, expr, hir::BinOpKind::Sub, lhs, rhs); + } + } + /// Manages when the lint should be triggered. Operations in constant environments, hard coded - /// types, custom allowed types and non-constant operations that won't overflow are ignored. + /// types, custom allowed types and non-constant operations that don't overflow are ignored. fn manage_bin_ops<'tcx>( &mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, - op: &Spanned<hir::BinOpKind>, + op: hir::BinOpKind, lhs: &'tcx hir::Expr<'_>, rhs: &'tcx hir::Expr<'_>, ) { @@ -180,7 +201,7 @@ impl ArithmeticSideEffects { return; } if !matches!( - op.node, + op, hir::BinOpKind::Add | hir::BinOpKind::Div | hir::BinOpKind::Mul @@ -204,7 +225,7 @@ impl ArithmeticSideEffects { return; } let has_valid_op = if Self::is_integral(lhs_ty) && Self::is_integral(rhs_ty) { - if let hir::BinOpKind::Shl | hir::BinOpKind::Shr = op.node { + if let hir::BinOpKind::Shl | hir::BinOpKind::Shr = op { // At least for integers, shifts are already handled by the CTFE return; } @@ -213,7 +234,7 @@ impl ArithmeticSideEffects { Self::literal_integer(cx, actual_rhs), ) { (None, None) => false, - (None, Some(n)) => match (&op.node, n) { + (None, Some(n)) => match (&op, n) { // Division and module are always valid if applied to non-zero integers (hir::BinOpKind::Div | hir::BinOpKind::Rem, local_n) if local_n != 0 => true, // Adding or subtracting zeros is always a no-op @@ -223,7 +244,7 @@ impl ArithmeticSideEffects { => true, _ => false, }, - (Some(n), None) => match (&op.node, n) { + (Some(n), None) => match (&op, n) { // Adding or subtracting zeros is always a no-op (hir::BinOpKind::Add | hir::BinOpKind::Sub, 0) // Multiplication by 1 or 0 will never overflow @@ -249,6 +270,7 @@ impl ArithmeticSideEffects { &mut self, args: &'tcx [hir::Expr<'_>], cx: &LateContext<'tcx>, + expr: &'tcx hir::Expr<'_>, ps: &'tcx hir::PathSegment<'_>, receiver: &'tcx hir::Expr<'_>, ) { @@ -262,7 +284,8 @@ impl ArithmeticSideEffects { if !Self::is_integral(instance_ty) { return; } - if !self.integer_methods.contains(&ps.ident.name) { + self.manage_sugar_methods(cx, expr, receiver, ps, arg); + if !self.disallowed_int_methods.contains(&ps.ident.name) { return; } let (actual_arg, _) = peel_hir_expr_refs(arg); @@ -310,10 +333,10 @@ impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects { } match &expr.kind { hir::ExprKind::AssignOp(op, lhs, rhs) | hir::ExprKind::Binary(op, lhs, rhs) => { - self.manage_bin_ops(cx, expr, op, lhs, rhs); + self.manage_bin_ops(cx, expr, op.node, lhs, rhs); }, hir::ExprKind::MethodCall(ps, receiver, args, _) => { - self.manage_method_call(args, cx, ps, receiver); + self.manage_method_call(args, cx, expr, ps, receiver); }, hir::ExprKind::Unary(un_op, un_expr) => { self.manage_unary_ops(cx, expr, un_expr, *un_op); diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index cc61ef9184c..2534e3c8468 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -11,9 +11,8 @@ use rustc_hir::def_id::DefId; use rustc_hir::hir_id::{HirId, HirIdMap}; use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::{ - self as hir, AnonConst, BinOpKind, BindingMode, Body, Expr, ExprKind, FnRetTy, FnSig, GenericArg, - ImplItemKind, ItemKind, Lifetime, Mutability, Node, Param, PatKind, QPath, TraitFn, TraitItem, TraitItemKind, - TyKind, Unsafety, + self as hir, AnonConst, BinOpKind, BindingMode, Body, Expr, ExprKind, FnRetTy, FnSig, GenericArg, ImplItemKind, + ItemKind, Lifetime, Mutability, Node, Param, PatKind, QPath, TraitFn, TraitItem, TraitItemKind, TyKind, Unsafety, }; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{Obligation, ObligationCause}; @@ -687,9 +686,7 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args: .filter_map(|(i, arg)| { let param = &body.params[arg.idx]; match param.pat.kind { - PatKind::Binding(BindingMode::NONE, id, _, None) - if !is_lint_allowed(cx, PTR_ARG, param.hir_id) => - { + PatKind::Binding(BindingMode::NONE, id, _, None) if !is_lint_allowed(cx, PTR_ARG, param.hir_id) => { Some((id, i)) }, _ => { diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index 4ad967589a5..1f1ce147ca2 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -14,8 +14,8 @@ use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::LangItem::{self, OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_hir::{ - BindingMode, Block, Body, ByRef, Expr, ExprKind, LetStmt, Mutability, Node, PatKind, PathSegment, QPath, - Stmt, StmtKind, + BindingMode, Block, Body, ByRef, Expr, ExprKind, LetStmt, Mutability, Node, PatKind, PathSegment, QPath, Stmt, + StmtKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; diff --git a/src/tools/clippy/clippy_lints/src/repeat_vec_with_capacity.rs b/src/tools/clippy/clippy_lints/src/repeat_vec_with_capacity.rs index a358881bf80..792d8fc88f0 100644 --- a/src/tools/clippy/clippy_lints/src/repeat_vec_with_capacity.rs +++ b/src/tools/clippy/clippy_lints/src/repeat_vec_with_capacity.rs @@ -1,7 +1,7 @@ use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::VecArgs; -use clippy_utils::macros::root_macro_call; +use clippy_utils::macros::matching_root_macro_call; use clippy_utils::source::snippet; use clippy_utils::{expr_or_init, fn_def_id, match_def_path, paths}; use rustc_errors::Applicability; @@ -65,8 +65,7 @@ fn emit_lint(cx: &LateContext<'_>, span: Span, kind: &str, note: &'static str, s /// Checks `vec![Vec::with_capacity(x); n]` fn check_vec_macro(cx: &LateContext<'_>, expr: &Expr<'_>) { - if let Some(mac_call) = root_macro_call(expr.span) - && cx.tcx.is_diagnostic_item(sym::vec_macro, mac_call.def_id) + if matching_root_macro_call(cx, expr.span, sym::vec_macro).is_some() && let Some(VecArgs::Repeat(repeat_expr, len_expr)) = VecArgs::hir(cx, expr) && fn_def_id(cx, repeat_expr).is_some_and(|did| match_def_path(cx, did, &paths::VEC_WITH_CAPACITY)) && !len_expr.span.from_expansion() diff --git a/src/tools/clippy/clippy_lints/src/size_of_ref.rs b/src/tools/clippy/clippy_lints/src/size_of_ref.rs index 14ca7a3f004..8d7f12af86e 100644 --- a/src/tools/clippy/clippy_lints/src/size_of_ref.rs +++ b/src/tools/clippy/clippy_lints/src/size_of_ref.rs @@ -28,7 +28,7 @@ declare_clippy_lint! { /// fn size(&self) -> usize { /// // Note that `&self` as an argument is a `&&Foo`: Because `self` /// // is already a reference, `&self` is a double-reference. - /// // The return value of `size_of_val()` therefor is the + /// // The return value of `size_of_val()` therefore is the /// // size of the reference-type, not the size of `self`. /// std::mem::size_of_val(&self) /// } diff --git a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs index 28c254537ab..b0e25c02265 100644 --- a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs +++ b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::macros::root_macro_call; +use clippy_utils::macros::matching_root_macro_call; use clippy_utils::sugg::Sugg; use clippy_utils::{ get_enclosing_block, is_expr_path_def_path, is_integer_literal, is_path_diagnostic_item, path_to_local, @@ -145,9 +145,7 @@ impl SlowVectorInit { // Generally don't warn if the vec initializer comes from an expansion, except for the vec! macro. // This lets us still warn on `vec![]`, while ignoring other kinds of macros that may output an // empty vec - if expr.span.from_expansion() - && root_macro_call(expr.span).map(|m| m.def_id) != cx.tcx.get_diagnostic_item(sym::vec_macro) - { + if expr.span.from_expansion() && matching_root_macro_call(cx, expr.span, sym::vec_macro).is_none() { return None; } diff --git a/src/tools/clippy/clippy_lints/src/thread_local_initializer_can_be_made_const.rs b/src/tools/clippy/clippy_lints/src/thread_local_initializer_can_be_made_const.rs index c1e24674e3e..4af3ee74d0e 100644 --- a/src/tools/clippy/clippy_lints/src/thread_local_initializer_can_be_made_const.rs +++ b/src/tools/clippy/clippy_lints/src/thread_local_initializer_can_be_made_const.rs @@ -1,13 +1,14 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::macros::macro_backtrace; use clippy_utils::qualify_min_const_fn::is_min_const_fn; use clippy_utils::source::snippet; use clippy_utils::{fn_has_unsatisfiable_preds, peel_blocks}; use rustc_errors::Applicability; -use rustc_hir::{intravisit, ExprKind}; +use rustc_hir::{intravisit, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; -use rustc_span::sym::thread_local_macro; +use rustc_span::sym::{self, thread_local_macro}; declare_clippy_lint! { /// ### What it does @@ -69,6 +70,26 @@ fn is_thread_local_initializer( ) } +fn is_unreachable(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + if let Some(macro_call) = macro_backtrace(expr.span).next() + && let Some(diag_name) = cx.tcx.get_diagnostic_name(macro_call.def_id) + { + return (matches!( + diag_name, + sym::core_panic_macro + | sym::std_panic_macro + | sym::core_panic_2015_macro + | sym::std_panic_2015_macro + | sym::core_panic_2021_macro + ) && !cx.tcx.hir().is_inside_const_context(expr.hir_id)) + || matches!( + diag_name, + sym::unimplemented_macro | sym::todo_macro | sym::unreachable_macro | sym::unreachable_2015_macro + ); + } + false +} + #[inline] fn initializer_can_be_made_const(cx: &LateContext<'_>, defid: rustc_span::def_id::DefId, msrv: &Msrv) -> bool { // Building MIR for `fn`s with unsatisfiable preds results in ICE. @@ -102,12 +123,17 @@ impl<'tcx> LateLintPass<'tcx> for ThreadLocalInitializerCanBeMadeConst { // for details on this issue, see: // https://github.com/rust-lang/rust-clippy/pull/12276 && !cx.tcx.is_const_fn(defid) - && initializer_can_be_made_const(cx, defid, &self.msrv) - // we know that the function is const-qualifiable, so now - // we need only to get the initializer expression to span-lint it. && let ExprKind::Block(block, _) = body.value.kind && let Some(unpeeled) = block.expr && let ret_expr = peel_blocks(unpeeled) + // A common pattern around threadlocal! is to make the value unreachable + // to force an initialization before usage + // https://github.com/rust-lang/rust-clippy/issues/12637 + // we ensure that this is reachable before we check in mir + && !is_unreachable(cx, ret_expr) + && initializer_can_be_made_const(cx, defid, &self.msrv) + // we know that the function is const-qualifiable, so now + // we need only to get the initializer expression to span-lint it. && let initializer_snippet = snippet(cx, ret_expr.span, "thread_local! { ... }") && initializer_snippet != "thread_local! { ... }" { diff --git a/src/tools/clippy/clippy_lints/src/to_string_trait_impl.rs b/src/tools/clippy/clippy_lints/src/to_string_trait_impl.rs index 59ae185c9de..0361836cdec 100644 --- a/src/tools/clippy/clippy_lints/src/to_string_trait_impl.rs +++ b/src/tools/clippy/clippy_lints/src/to_string_trait_impl.rs @@ -38,7 +38,7 @@ declare_clippy_lint! { /// } /// } /// ``` - #[clippy::version = "1.77.0"] + #[clippy::version = "1.78.0"] pub TO_STRING_TRAIT_IMPL, style, "check for direct implementations of `ToString`" diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs index 9468d367a92..c05cd9ed593 100644 --- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs +++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs @@ -237,6 +237,7 @@ impl TraitBounds { } } + #[allow(clippy::mutable_key_type)] fn check_type_repetition<'tcx>(&self, cx: &LateContext<'tcx>, gen: &'tcx Generics<'_>) { struct SpanlessTy<'cx, 'tcx> { ty: &'tcx Ty<'tcx>, diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index 0802cb2b7c7..5e45ab211ef 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -12,8 +12,8 @@ mod vec_box; use rustc_hir as hir; use rustc_hir::intravisit::FnKind; use rustc_hir::{ - Body, FnDecl, FnRetTy, GenericArg, ImplItem, ImplItemKind, Item, ItemKind, LetStmt, MutTy, QPath, TraitItem, - TraitItemKind, TyKind, + Body, FnDecl, FnRetTy, GenericArg, ImplItem, ImplItemKind, Item, ItemKind, LetStmt, MutTy, QPath, TraitFn, + TraitItem, TraitItemKind, TyKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; @@ -420,7 +420,13 @@ impl<'tcx> LateLintPass<'tcx> for Types { TraitItemKind::Const(ty, _) | TraitItemKind::Type(_, Some(ty)) => { self.check_ty(cx, ty, context); }, - TraitItemKind::Fn(ref sig, _) => self.check_fn_decl(cx, sig.decl, context), + TraitItemKind::Fn(ref sig, trait_method) => { + // Check only methods without body + // Methods with body are covered by check_fn. + if let TraitFn::Required(_) = trait_method { + self.check_fn_decl(cx, sig.decl, context); + } + }, TraitItemKind::Type(..) => (), } } diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 7f0769452c7..4448c9ae3df 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -7,8 +7,8 @@ use rustc_ast::LitIntType; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_hir::{ - ArrayLen, BindingMode, CaptureBy, Closure, ClosureKind, CoroutineKind, ExprKind, FnRetTy, HirId, Lit, - PatKind, QPath, StmtKind, TyKind, + ArrayLen, BindingMode, CaptureBy, Closure, ClosureKind, CoroutineKind, ExprKind, FnRetTy, HirId, Lit, PatKind, + QPath, StmtKind, TyKind, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::declare_lint_pass; diff --git a/src/tools/clippy/clippy_lints/src/vec.rs b/src/tools/clippy/clippy_lints/src/vec.rs index 27ead55bf39..9edf7579d48 100644 --- a/src/tools/clippy/clippy_lints/src/vec.rs +++ b/src/tools/clippy/clippy_lints/src/vec.rs @@ -7,7 +7,7 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::source::snippet_opt; use clippy_utils::ty::is_copy; use clippy_utils::visitors::for_each_local_use_after_expr; -use clippy_utils::{get_parent_expr, higher, is_trait_method}; +use clippy_utils::{get_parent_expr, higher, is_in_test, is_trait_method}; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, HirId, LetStmt, Mutability, Node, Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -22,6 +22,7 @@ pub struct UselessVec { pub too_large_for_stack: u64, pub msrv: Msrv, pub span_to_lint_map: BTreeMap<Span, Option<(HirId, SuggestedType, String, Applicability)>>, + pub allow_in_test: bool, } declare_clippy_lint! { @@ -57,6 +58,9 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { let Some(vec_args) = higher::VecArgs::hir(cx, expr.peel_borrows()) else { return; }; + if self.allow_in_test && is_in_test(cx.tcx, expr.hir_id) { + return; + }; // the parent callsite of this `vec!` expression, or span to the borrowed one such as `&vec!` let callsite = expr.span.parent_callsite().unwrap_or(expr.span); diff --git a/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs b/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs index c46f0298cc8..a599415a2dd 100644 --- a/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs +++ b/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs @@ -6,9 +6,7 @@ use clippy_utils::{get_parent_expr, path_to_local_id}; use core::ops::ControlFlow; use rustc_errors::Applicability; use rustc_hir::def::Res; -use rustc_hir::{ - BindingMode, Block, Expr, ExprKind, HirId, LetStmt, Mutability, PatKind, QPath, Stmt, StmtKind, UnOp, -}; +use rustc_hir::{BindingMode, Block, Expr, ExprKind, HirId, LetStmt, Mutability, PatKind, QPath, Stmt, StmtKind, UnOp}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml index d2bb719a517..ab883c25338 100644 --- a/src/tools/clippy/clippy_utils/Cargo.toml +++ b/src/tools/clippy/clippy_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_utils" -version = "0.1.79" +version = "0.1.80" edition = "2021" publish = false diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 0395eb1449b..529d20126b2 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -446,7 +446,18 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { use ForeignItemKind::*; match (l, r) { - (Static(lt, lm, le), Static(rt, rm, re)) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re), + ( + Static(box StaticForeignItem { + ty: lt, + mutability: lm, + expr: le, + }), + Static(box StaticForeignItem { + ty: rt, + mutability: rm, + expr: re, + }), + ) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re), ( Fn(box ast::Fn { defaultness: ld, diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 07c443acb05..c921168df29 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -224,7 +224,7 @@ impl HirEqInterExpr<'_, '_, '_> { }) } - pub fn eq_array_length(&mut self, left: ArrayLen, right: ArrayLen) -> bool { + pub fn eq_array_length(&mut self, left: ArrayLen<'_>, right: ArrayLen<'_>) -> bool { match (left, right) { (ArrayLen::Infer(..), ArrayLen::Infer(..)) => true, (ArrayLen::Body(l_ct), ArrayLen::Body(r_ct)) => self.eq_body(l_ct.body, r_ct.body), @@ -1116,7 +1116,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } } - pub fn hash_array_length(&mut self, length: ArrayLen) { + pub fn hash_array_length(&mut self, length: ArrayLen<'_>) { match length { ArrayLen::Infer(..) => {}, ArrayLen::Body(anon_const) => self.hash_body(anon_const.body), diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 5e242aea354..a49414a058b 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -2328,10 +2328,10 @@ pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<S /// /// Given functions `eq` and `hash` such that `eq(a, b) == true` /// implies `hash(a) == hash(b)` -pub fn search_same<T, Hash, Eq>(exprs: &[T], hash: Hash, eq: Eq) -> Vec<(&T, &T)> +pub fn search_same<T, Hash, Eq>(exprs: &[T], mut hash: Hash, mut eq: Eq) -> Vec<(&T, &T)> where - Hash: Fn(&T) -> u64, - Eq: Fn(&T, &T) -> bool, + Hash: FnMut(&T) -> u64, + Eq: FnMut(&T, &T) -> bool, { match exprs { [a, b] if eq(a, b) => return vec![(a, b)], @@ -2505,8 +2505,9 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl Fn(&[Sym /// Note: Add `//@compile-flags: --test` to UI tests with a `#[test]` function pub fn is_in_test_function(tcx: TyCtxt<'_>, id: HirId) -> bool { with_test_item_names(tcx, tcx.parent_module(id), |names| { - tcx.hir() - .parent_iter(id) + let node = tcx.hir_node(id); + once((id, node)) + .chain(tcx.hir().parent_iter(id)) // Since you can nest functions we need to collect all until we leave // function scope .any(|(_id, node)| { @@ -2547,6 +2548,11 @@ pub fn is_in_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool { .any(|parent_id| is_cfg_test(tcx, parent_id)) } +/// Checks if the node is in a `#[test]` function or has any parent node marked `#[cfg(test)]` +pub fn is_in_test(tcx: TyCtxt<'_>, hir_id: HirId) -> bool { + is_in_test_function(tcx, hir_id) || is_in_cfg_test(tcx, hir_id) +} + /// Checks if the item of any of its parents has `#[cfg(...)]` attribute applied. pub fn inherits_cfg(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { let hir = tcx.hir(); diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs index f166087dc3c..257dd76ab15 100644 --- a/src/tools/clippy/clippy_utils/src/macros.rs +++ b/src/tools/clippy/clippy_utils/src/macros.rs @@ -119,10 +119,20 @@ pub fn macro_backtrace(span: Span) -> impl Iterator<Item = MacroCall> { /// If the macro backtrace of `span` has a macro call at the root expansion /// (i.e. not a nested macro call), returns `Some` with the `MacroCall` +/// +/// If you only want to check whether the root macro has a specific name, +/// consider using [`matching_root_macro_call`] instead. pub fn root_macro_call(span: Span) -> Option<MacroCall> { macro_backtrace(span).last() } +/// A combination of [`root_macro_call`] and +/// [`is_diagnostic_item`](rustc_middle::ty::TyCtxt::is_diagnostic_item) that returns a `MacroCall` +/// at the root expansion if only it matches the given name. +pub fn matching_root_macro_call(cx: &LateContext<'_>, span: Span, name: Symbol) -> Option<MacroCall> { + root_macro_call(span).filter(|mc| cx.tcx.is_diagnostic_item(name, mc.def_id)) +} + /// Like [`root_macro_call`], but only returns `Some` if `node` is the "first node" /// produced by the macro call, as in [`first_node_in_macro`]. pub fn root_macro_call_first_node(cx: &LateContext<'_>, node: &impl HirNode) -> Option<MacroCall> { diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs index 456b8019e95..9bf068ee3cd 100644 --- a/src/tools/clippy/clippy_utils/src/paths.rs +++ b/src/tools/clippy/clippy_utils/src/paths.rs @@ -19,8 +19,6 @@ pub const BTREESET_ITER: [&str; 6] = ["alloc", "collections", "btree", "set", "B pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"]; pub const CORE_ITER_CLONED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "cloned"]; pub const CORE_ITER_COPIED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "copied"]; -pub const CORE_ITER_ENUMERATE_METHOD: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "enumerate"]; -pub const CORE_ITER_ENUMERATE_STRUCT: [&str; 5] = ["core", "iter", "adapters", "enumerate", "Enumerate"]; pub const CORE_ITER_FILTER: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "filter"]; pub const CORE_RESULT_OK_METHOD: [&str; 4] = ["core", "result", "Result", "ok"]; pub const CSTRING_AS_C_STR: [&str; 5] = ["alloc", "ffi", "c_str", "CString", "as_c_str"]; @@ -73,7 +71,6 @@ pub const REGEX_NEW: [&str; 3] = ["regex", "Regex", "new"]; pub const REGEX_SET_NEW: [&str; 3] = ["regex", "RegexSet", "new"]; pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"]; pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"]; -pub const SLICE_GET: [&str; 4] = ["core", "slice", "<impl [T]>", "get"]; pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "<impl [T]>", "into_vec"]; pub const SLICE_INTO: [&str; 4] = ["core", "slice", "<impl [T]>", "iter"]; pub const STD_IO_SEEK_FROM_CURRENT: [&str; 4] = ["std", "io", "SeekFrom", "Current"]; @@ -81,7 +78,6 @@ pub const STD_IO_SEEKFROM_START: [&str; 4] = ["std", "io", "SeekFrom", "Start"]; pub const STRING_AS_MUT_STR: [&str; 4] = ["alloc", "string", "String", "as_mut_str"]; pub const STRING_AS_STR: [&str; 4] = ["alloc", "string", "String", "as_str"]; pub const STRING_NEW: [&str; 4] = ["alloc", "string", "String", "new"]; -pub const STR_BYTES: [&str; 4] = ["core", "str", "<impl str>", "bytes"]; pub const STR_CHARS: [&str; 4] = ["core", "str", "<impl str>", "chars"]; pub const STR_ENDS_WITH: [&str; 4] = ["core", "str", "<impl str>", "ends_with"]; pub const STR_LEN: [&str; 4] = ["core", "str", "<impl str>", "len"]; @@ -108,7 +104,6 @@ pub const VEC_DEQUE_ITER: [&str; 5] = ["alloc", "collections", "vec_deque", "Vec pub const VEC_FROM_ELEM: [&str; 3] = ["alloc", "vec", "from_elem"]; pub const VEC_NEW: [&str; 4] = ["alloc", "vec", "Vec", "new"]; pub const VEC_WITH_CAPACITY: [&str; 4] = ["alloc", "vec", "Vec", "with_capacity"]; -pub const VEC_RESIZE: [&str; 4] = ["alloc", "vec", "Vec", "resize"]; pub const INSTANT_NOW: [&str; 4] = ["std", "time", "Instant", "now"]; pub const VEC_IS_EMPTY: [&str; 4] = ["alloc", "vec", "Vec", "is_empty"]; pub const VEC_POP: [&str; 4] = ["alloc", "vec", "Vec", "pop"]; diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index a06a82c5653..23750ed4d1b 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -29,9 +29,10 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _ use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; use rustc_trait_selection::traits::{Obligation, ObligationCause}; use std::assert_matches::debug_assert_matches; +use std::collections::hash_map::Entry; use std::iter; -use crate::{match_def_path, path_res}; +use crate::{def_path_def_ids, match_def_path, path_res}; mod type_certainty; pub use type_certainty::expr_type_is_certain; @@ -1198,47 +1199,88 @@ pub fn make_normalized_projection<'tcx>( helper(tcx, param_env, make_projection(tcx, container_id, assoc_ty, args)?) } -/// Check if given type has inner mutability such as [`std::cell::Cell`] or [`std::cell::RefCell`] -/// etc. -pub fn is_interior_mut_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - match *ty.kind() { - ty::Ref(_, inner_ty, mutbl) => mutbl == Mutability::Mut || is_interior_mut_ty(cx, inner_ty), - ty::Slice(inner_ty) => is_interior_mut_ty(cx, inner_ty), - ty::Array(inner_ty, size) => { - size.try_eval_target_usize(cx.tcx, cx.param_env) - .map_or(true, |u| u != 0) - && is_interior_mut_ty(cx, inner_ty) - }, - ty::Tuple(fields) => fields.iter().any(|ty| is_interior_mut_ty(cx, ty)), - ty::Adt(def, args) => { - // Special case for collections in `std` who's impl of `Hash` or `Ord` delegates to - // that of their type parameters. Note: we don't include `HashSet` and `HashMap` - // because they have no impl for `Hash` or `Ord`. - let def_id = def.did(); - let is_std_collection = [ - sym::Option, - sym::Result, - sym::LinkedList, - sym::Vec, - sym::VecDeque, - sym::BTreeMap, - sym::BTreeSet, - sym::Rc, - sym::Arc, - ] +/// Helper to check if given type has inner mutability such as [`std::cell::Cell`] or +/// [`std::cell::RefCell`]. +#[derive(Default, Debug)] +pub struct InteriorMut<'tcx> { + ignored_def_ids: FxHashSet<DefId>, + ignore_pointers: bool, + tys: FxHashMap<Ty<'tcx>, Option<bool>>, +} + +impl<'tcx> InteriorMut<'tcx> { + pub fn new(cx: &LateContext<'tcx>, ignore_interior_mutability: &[String]) -> Self { + let ignored_def_ids = ignore_interior_mutability .iter() - .any(|diag_item| cx.tcx.is_diagnostic_item(*diag_item, def_id)); - let is_box = Some(def_id) == cx.tcx.lang_items().owned_box(); - if is_std_collection || is_box { - // The type is mutable if any of its type parameters are - args.types().any(|ty| is_interior_mut_ty(cx, ty)) - } else { - !ty.has_escaping_bound_vars() - && cx.tcx.layout_of(cx.param_env.and(ty)).is_ok() - && !ty.is_freeze(cx.tcx, cx.param_env) - } - }, - _ => false, + .flat_map(|ignored_ty| { + let path: Vec<&str> = ignored_ty.split("::").collect(); + def_path_def_ids(cx, path.as_slice()) + }) + .collect(); + + Self { + ignored_def_ids, + ..Self::default() + } + } + + pub fn without_pointers(cx: &LateContext<'tcx>, ignore_interior_mutability: &[String]) -> Self { + Self { + ignore_pointers: true, + ..Self::new(cx, ignore_interior_mutability) + } + } + + /// Check if given type has inner mutability such as [`std::cell::Cell`] or + /// [`std::cell::RefCell`] etc. + pub fn is_interior_mut_ty(&mut self, cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { + match self.tys.entry(ty) { + Entry::Occupied(o) => return *o.get() == Some(true), + // Temporarily insert a `None` to break cycles + Entry::Vacant(v) => v.insert(None), + }; + + let interior_mut = match *ty.kind() { + ty::RawPtr(inner_ty, _) if !self.ignore_pointers => self.is_interior_mut_ty(cx, inner_ty), + ty::Ref(_, inner_ty, _) | ty::Slice(inner_ty) => self.is_interior_mut_ty(cx, inner_ty), + ty::Array(inner_ty, size) => { + size.try_eval_target_usize(cx.tcx, cx.param_env) + .map_or(true, |u| u != 0) + && self.is_interior_mut_ty(cx, inner_ty) + }, + ty::Tuple(fields) => fields.iter().any(|ty| self.is_interior_mut_ty(cx, ty)), + ty::Adt(def, _) if def.is_unsafe_cell() => true, + ty::Adt(def, args) => { + let is_std_collection = matches!( + cx.tcx.get_diagnostic_name(def.did()), + Some( + sym::LinkedList + | sym::Vec + | sym::VecDeque + | sym::BTreeMap + | sym::BTreeSet + | sym::HashMap + | sym::HashSet + | sym::Arc + | sym::Rc + ) + ); + + if is_std_collection || def.is_box() { + // Include the types from std collections that are behind pointers internally + args.types().any(|ty| self.is_interior_mut_ty(cx, ty)) + } else if self.ignored_def_ids.contains(&def.did()) || def.is_phantom_data() { + false + } else { + def.all_fields() + .any(|f| self.is_interior_mut_ty(cx, f.ty(cx.tcx, args))) + } + }, + _ => false, + }; + + self.tys.insert(ty, Some(interior_mut)); + interior_mut } } diff --git a/src/tools/clippy/declare_clippy_lint/Cargo.toml b/src/tools/clippy/declare_clippy_lint/Cargo.toml index 9a3a41e1d1e..c8c734c3a7c 100644 --- a/src/tools/clippy/declare_clippy_lint/Cargo.toml +++ b/src/tools/clippy/declare_clippy_lint/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "declare_clippy_lint" -version = "0.1.79" +version = "0.1.80" edition = "2021" publish = false diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain index 521c0d12983..055f305eb8e 100644 --- a/src/tools/clippy/rust-toolchain +++ b/src/tools/clippy/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2024-04-18" +channel = "nightly-2024-05-02" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs index 32a31f5e082..b06a11702ec 100644 --- a/src/tools/clippy/tests/compile-test.rs +++ b/src/tools/clippy/tests/compile-test.rs @@ -4,6 +4,7 @@ #![warn(rust_2018_idioms, unused_lifetimes)] #![allow(unused_extern_crates)] +use ui_test::custom_flags::rustfix::RustfixMode; use ui_test::spanned::Spanned; use ui_test::{status_emitter, Args, CommandBuilder, Config, Match, Mode, OutputConflictHandling}; @@ -122,10 +123,11 @@ fn base_config(test_dir: &str) -> (Config, Args) { out_dir: target_dir.join("ui_test"), ..Config::rustc(Path::new("tests").join(test_dir)) }; - config.comment_defaults.base().mode = Some(Spanned::dummy(Mode::Yolo { - rustfix: ui_test::RustfixMode::Everything, - })) - .into(); + config.comment_defaults.base().mode = Some(Spanned::dummy(Mode::Yolo)).into(); + config + .comment_defaults + .base() + .set_custom("rustfix", RustfixMode::Everything); config.comment_defaults.base().diagnostic_code_prefix = Some(Spanned::dummy("clippy::".into())).into(); config.with_args(&args); let current_exe_path = env::current_exe().unwrap(); @@ -235,13 +237,12 @@ fn run_ui_cargo() { .push(("RUSTFLAGS".into(), Some("-Dwarnings".into()))); // We need to do this while we still have a rustc in the `program` field. config.fill_host_and_target().unwrap(); - config.dependencies_crate_manifest_path = None; config.program.program.set_file_name(if cfg!(windows) { "cargo-clippy.exe" } else { "cargo-clippy" }); - config.comment_defaults.base().edition = Default::default(); + config.comment_defaults.base().custom.clear(); config .comment_defaults diff --git a/src/tools/clippy/tests/ui-toml/mut_key/mut_key.rs b/src/tools/clippy/tests/ui-toml/mut_key/mut_key.rs index 095e0d15448..3a8e3741e20 100644 --- a/src/tools/clippy/tests/ui-toml/mut_key/mut_key.rs +++ b/src/tools/clippy/tests/ui-toml/mut_key/mut_key.rs @@ -44,10 +44,18 @@ impl<T> Deref for Counted<T> { } } +#[derive(Hash, PartialEq, Eq)] +struct ContainsCounted { + inner: Counted<String>, +} + // This is not linted because `"mut_key::Counted"` is in // `arc_like_types` in `clippy.toml` fn should_not_take_this_arg(_v: HashSet<Counted<String>>) {} +fn indirect(_: HashMap<ContainsCounted, usize>) {} + fn main() { should_not_take_this_arg(HashSet::new()); + indirect(HashMap::new()); } diff --git a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index 24645b61fdb..722e9b3bc8d 100644 --- a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -11,6 +11,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect allow-print-in-tests allow-private-module-inception allow-unwrap-in-tests + allow-useless-vec-in-tests allowed-dotfiles allowed-duplicate-crates allowed-idents-below-min-chars @@ -91,6 +92,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect allow-print-in-tests allow-private-module-inception allow-unwrap-in-tests + allow-useless-vec-in-tests allowed-dotfiles allowed-duplicate-crates allowed-idents-below-min-chars @@ -171,6 +173,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni allow-print-in-tests allow-private-module-inception allow-unwrap-in-tests + allow-useless-vec-in-tests allowed-dotfiles allowed-duplicate-crates allowed-idents-below-min-chars diff --git a/src/tools/clippy/tests/ui-toml/useless_vec/clippy.toml b/src/tools/clippy/tests/ui-toml/useless_vec/clippy.toml new file mode 100644 index 00000000000..230ca2d0ab7 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/useless_vec/clippy.toml @@ -0,0 +1 @@ +allow-useless-vec-in-tests = true diff --git a/src/tools/clippy/tests/ui-toml/useless_vec/useless_vec.fixed b/src/tools/clippy/tests/ui-toml/useless_vec/useless_vec.fixed new file mode 100644 index 00000000000..08323a0dcc9 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/useless_vec/useless_vec.fixed @@ -0,0 +1,26 @@ +//@compile-flags: --test +#![warn(clippy::useless_vec)] +#![allow(clippy::unnecessary_operation, clippy::no_effect)] + +fn foo(_: &[u32]) {} + +fn main() { + foo(&[1_u32]); +} + +#[test] +pub fn in_test() { + foo(&vec![2_u32]); +} + +#[cfg(test)] +fn in_cfg_test() { + foo(&vec![3_u32]); +} + +#[cfg(test)] +mod mod1 { + fn in_cfg_test_mod() { + super::foo(&vec![4_u32]); + } +} diff --git a/src/tools/clippy/tests/ui-toml/useless_vec/useless_vec.rs b/src/tools/clippy/tests/ui-toml/useless_vec/useless_vec.rs new file mode 100644 index 00000000000..1f4b27c5342 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/useless_vec/useless_vec.rs @@ -0,0 +1,26 @@ +//@compile-flags: --test +#![warn(clippy::useless_vec)] +#![allow(clippy::unnecessary_operation, clippy::no_effect)] + +fn foo(_: &[u32]) {} + +fn main() { + foo(&vec![1_u32]); +} + +#[test] +pub fn in_test() { + foo(&vec![2_u32]); +} + +#[cfg(test)] +fn in_cfg_test() { + foo(&vec![3_u32]); +} + +#[cfg(test)] +mod mod1 { + fn in_cfg_test_mod() { + super::foo(&vec![4_u32]); + } +} diff --git a/src/tools/clippy/tests/ui-toml/useless_vec/useless_vec.stderr b/src/tools/clippy/tests/ui-toml/useless_vec/useless_vec.stderr new file mode 100644 index 00000000000..633110c3c8d --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/useless_vec/useless_vec.stderr @@ -0,0 +1,11 @@ +error: useless use of `vec!` + --> tests/ui-toml/useless_vec/useless_vec.rs:8:9 + | +LL | foo(&vec![1_u32]); + | ^^^^^^^^^^^^ help: you can use a slice directly: `&[1_u32]` + | + = note: `-D clippy::useless-vec` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::useless_vec)]` + +error: aborting due to 1 previous error + diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs index fdec14a1528..66d71f337f2 100644 --- a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs +++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs @@ -521,4 +521,14 @@ pub fn issue_11393() { example_rem(x, maybe_zero); } +pub fn issue_12318() { + use core::ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign}; + let mut one: i32 = 1; + one.add_assign(1); + one.div_assign(1); + one.mul_assign(1); + one.rem_assign(1); + one.sub_assign(1); +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr index 741c892a52c..8039c0bfa24 100644 --- a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr +++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr @@ -715,5 +715,17 @@ error: arithmetic operation that can potentially result in unexpected side-effec LL | x % maybe_zero | ^^^^^^^^^^^^^^ -error: aborting due to 119 previous errors +error: arithmetic operation that can potentially result in unexpected side-effects + --> tests/ui/arithmetic_side_effects.rs:527:5 + | +LL | one.add_assign(1); + | ^^^^^^^^^^^^^^^^^ + +error: arithmetic operation that can potentially result in unexpected side-effects + --> tests/ui/arithmetic_side_effects.rs:531:5 + | +LL | one.sub_assign(1); + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 121 previous errors diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs index 3303eb14567..6e6919cd295 100644 --- a/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs +++ b/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs @@ -9,6 +9,7 @@ use proc_macro::token_stream::IntoIter; use proc_macro::Delimiter::{self, Brace, Parenthesis}; use proc_macro::Spacing::{self, Alone, Joint}; use proc_macro::{Group, Ident, Literal, Punct, Span, TokenStream, TokenTree as TT}; +use syn::spanned::Spanned; type Result<T> = core::result::Result<T, TokenStream>; @@ -124,6 +125,22 @@ fn write_with_span(s: Span, mut input: IntoIter, out: &mut TokenStream) -> Resul Ok(()) } +/// Takes an array repeat expression such as `[0_u32; 2]`, and return the tokens with 10 times the +/// original size, which turns to `[0_u32; 20]`. +#[proc_macro] +pub fn make_it_big(input: TokenStream) -> TokenStream { + let mut expr_repeat = syn::parse_macro_input!(input as syn::ExprRepeat); + let len_span = expr_repeat.len.span(); + if let syn::Expr::Lit(expr_lit) = &mut *expr_repeat.len { + if let syn::Lit::Int(lit_int) = &expr_lit.lit { + let orig_val = lit_int.base10_parse::<usize>().expect("not a valid length parameter"); + let new_val = orig_val.saturating_mul(10); + expr_lit.lit = syn::parse_quote_spanned!( len_span => #new_val); + } + } + quote::quote!(#expr_repeat).into() +} + /// Within the item this attribute is attached to, an `inline!` macro is available which expands the /// contained tokens as though they came from a macro expansion. /// diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.rs b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.rs index 4da3833cbf5..5570e7cd6d2 100644 --- a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.rs +++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.rs @@ -158,7 +158,7 @@ trait BothOfCellAndGeneric<T> { const INDIRECT: Cell<*const T>; fn function() { - let _ = &Self::DIRECT; + let _ = &Self::DIRECT; //~ ERROR: interior mutability let _ = &Self::INDIRECT; //~ ERROR: interior mutability } } @@ -168,7 +168,7 @@ impl<T: ConstDefault> BothOfCellAndGeneric<T> for Vec<T> { const INDIRECT: Cell<*const T> = Cell::new(std::ptr::null()); fn function() { - let _ = &Self::DIRECT; + let _ = &Self::DIRECT; //~ ERROR: interior mutability let _ = &Self::INDIRECT; //~ ERROR: interior mutability } } diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.stderr b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.stderr index 582b744b49f..8602b46b0dc 100644 --- a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.stderr +++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.stderr @@ -76,6 +76,14 @@ LL | let _ = &Self::WRAPPED_SELF; = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed + --> tests/ui/borrow_interior_mutable_const/traits.rs:161:18 + | +LL | let _ = &Self::DIRECT; + | ^^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here + +error: a `const` item with interior mutability should not be borrowed --> tests/ui/borrow_interior_mutable_const/traits.rs:162:18 | LL | let _ = &Self::INDIRECT; @@ -84,6 +92,14 @@ LL | let _ = &Self::INDIRECT; = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed + --> tests/ui/borrow_interior_mutable_const/traits.rs:171:18 + | +LL | let _ = &Self::DIRECT; + | ^^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here + +error: a `const` item with interior mutability should not be borrowed --> tests/ui/borrow_interior_mutable_const/traits.rs:172:18 | LL | let _ = &Self::INDIRECT; @@ -123,5 +139,5 @@ LL | assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); | = help: assign this const to a local or static variable, and use the variable here -error: aborting due to 15 previous errors +error: aborting due to 17 previous errors diff --git a/src/tools/clippy/tests/ui/box_default.fixed b/src/tools/clippy/tests/ui/box_default.fixed index 6c2896b3aa0..1f2f57c2507 100644 --- a/src/tools/clippy/tests/ui/box_default.fixed +++ b/src/tools/clippy/tests/ui/box_default.fixed @@ -65,6 +65,8 @@ fn main() { // Would have a suggestion after https://github.com/rust-lang/rust/blob/fdd030127cc68afec44a8d3f6341525dd34e50ae/compiler/rustc_middle/src/ty/diagnostics.rs#L554-L563 let mut unnameable = Box::new(Option::default()); let _ = unnameable.insert(|| {}); + + let _ = Box::into_raw(Box::new(String::default())); } fn ret_ty_fn() -> Box<bool> { @@ -75,6 +77,16 @@ fn call_ty_fn(_b: Box<u8>) { issue_9621_dyn_trait(); } +struct X<T>(T); + +impl<T: Default> X<T> { + fn x(_: Box<T>) {} + + fn same_generic_param() { + Self::x(Box::default()); + } +} + use std::io::{Read, Result}; impl Read for ImplementsDefault { diff --git a/src/tools/clippy/tests/ui/box_default.rs b/src/tools/clippy/tests/ui/box_default.rs index e19a62a9022..addfebc24f5 100644 --- a/src/tools/clippy/tests/ui/box_default.rs +++ b/src/tools/clippy/tests/ui/box_default.rs @@ -65,6 +65,8 @@ fn main() { // Would have a suggestion after https://github.com/rust-lang/rust/blob/fdd030127cc68afec44a8d3f6341525dd34e50ae/compiler/rustc_middle/src/ty/diagnostics.rs#L554-L563 let mut unnameable = Box::new(Option::default()); let _ = unnameable.insert(|| {}); + + let _ = Box::into_raw(Box::new(String::default())); } fn ret_ty_fn() -> Box<bool> { @@ -75,6 +77,16 @@ fn call_ty_fn(_b: Box<u8>) { issue_9621_dyn_trait(); } +struct X<T>(T); + +impl<T: Default> X<T> { + fn x(_: Box<T>) {} + + fn same_generic_param() { + Self::x(Box::new(T::default())); + } +} + use std::io::{Read, Result}; impl Read for ImplementsDefault { diff --git a/src/tools/clippy/tests/ui/box_default.stderr b/src/tools/clippy/tests/ui/box_default.stderr index f172a875dce..39fd0d29bbf 100644 --- a/src/tools/clippy/tests/ui/box_default.stderr +++ b/src/tools/clippy/tests/ui/box_default.stderr @@ -55,5 +55,11 @@ error: `Box::new(_)` of default value LL | call_ty_fn(Box::new(u8::default())); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()` -error: aborting due to 9 previous errors +error: `Box::new(_)` of default value + --> tests/ui/box_default.rs:86:17 + | +LL | Self::x(Box::new(T::default())); + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()` + +error: aborting due to 10 previous errors diff --git a/src/tools/clippy/tests/ui/cast.rs b/src/tools/clippy/tests/ui/cast.rs index 215c008902d..453d62ce607 100644 --- a/src/tools/clippy/tests/ui/cast.rs +++ b/src/tools/clippy/tests/ui/cast.rs @@ -13,7 +13,8 @@ clippy::cast_abs_to_unsigned, clippy::no_effect, clippy::unnecessary_operation, - clippy::unnecessary_literal_unwrap + clippy::unnecessary_literal_unwrap, + clippy::identity_op )] fn main() { @@ -479,3 +480,21 @@ fn issue12506() -> usize { let bar: Result<Option<i64>, u32> = Ok(Some(10)); bar.unwrap().unwrap() as usize } + +fn issue12721() { + fn x() -> u64 { + u64::MAX + } + + // Don't lint. + (255 & 999999u64) as u8; + // Don't lint. + let _ = ((x() & 255) & 999999) as u8; + // Don't lint. + let _ = (999999 & (x() & 255)) as u8; + + (256 & 999999u64) as u8; + //~^ ERROR: casting `u64` to `u8` may truncate the value + (255 % 999999u64) as u8; + //~^ ERROR: casting `u64` to `u8` may truncate the value +} diff --git a/src/tools/clippy/tests/ui/cast.stderr b/src/tools/clippy/tests/ui/cast.stderr index 8b269c47176..43c0d8f4ed7 100644 --- a/src/tools/clippy/tests/ui/cast.stderr +++ b/src/tools/clippy/tests/ui/cast.stderr @@ -1,5 +1,5 @@ error: casting `i32` to `f32` causes a loss of precision (`i32` is 32 bits wide, but `f32`'s mantissa is only 23 bits wide) - --> tests/ui/cast.rs:22:5 + --> tests/ui/cast.rs:23:5 | LL | x0 as f32; | ^^^^^^^^^ @@ -8,37 +8,37 @@ LL | x0 as f32; = help: to override `-D warnings` add `#[allow(clippy::cast_precision_loss)]` error: casting `i64` to `f32` causes a loss of precision (`i64` is 64 bits wide, but `f32`'s mantissa is only 23 bits wide) - --> tests/ui/cast.rs:26:5 + --> tests/ui/cast.rs:27:5 | LL | x1 as f32; | ^^^^^^^^^ error: casting `i64` to `f64` causes a loss of precision (`i64` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide) - --> tests/ui/cast.rs:28:5 + --> tests/ui/cast.rs:29:5 | LL | x1 as f64; | ^^^^^^^^^ error: casting `u32` to `f32` causes a loss of precision (`u32` is 32 bits wide, but `f32`'s mantissa is only 23 bits wide) - --> tests/ui/cast.rs:31:5 + --> tests/ui/cast.rs:32:5 | LL | x2 as f32; | ^^^^^^^^^ error: casting `u64` to `f32` causes a loss of precision (`u64` is 64 bits wide, but `f32`'s mantissa is only 23 bits wide) - --> tests/ui/cast.rs:34:5 + --> tests/ui/cast.rs:35:5 | LL | x3 as f32; | ^^^^^^^^^ error: casting `u64` to `f64` causes a loss of precision (`u64` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide) - --> tests/ui/cast.rs:36:5 + --> tests/ui/cast.rs:37:5 | LL | x3 as f64; | ^^^^^^^^^ error: casting `f32` to `i32` may truncate the value - --> tests/ui/cast.rs:39:5 + --> tests/ui/cast.rs:40:5 | LL | 1f32 as i32; | ^^^^^^^^^^^ @@ -48,7 +48,7 @@ LL | 1f32 as i32; = help: to override `-D warnings` add `#[allow(clippy::cast_possible_truncation)]` error: casting `f32` to `u32` may truncate the value - --> tests/ui/cast.rs:41:5 + --> tests/ui/cast.rs:42:5 | LL | 1f32 as u32; | ^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | 1f32 as u32; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:41:5 + --> tests/ui/cast.rs:42:5 | LL | 1f32 as u32; | ^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | 1f32 as u32; = help: to override `-D warnings` add `#[allow(clippy::cast_sign_loss)]` error: casting `f64` to `f32` may truncate the value - --> tests/ui/cast.rs:45:5 + --> tests/ui/cast.rs:46:5 | LL | 1f64 as f32; | ^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL | 1f64 as f32; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `i32` to `i8` may truncate the value - --> tests/ui/cast.rs:47:5 + --> tests/ui/cast.rs:48:5 | LL | 1i32 as i8; | ^^^^^^^^^^ @@ -85,7 +85,7 @@ LL | i8::try_from(1i32); | ~~~~~~~~~~~~~~~~~~ error: casting `i32` to `u8` may truncate the value - --> tests/ui/cast.rs:49:5 + --> tests/ui/cast.rs:50:5 | LL | 1i32 as u8; | ^^^^^^^^^^ @@ -97,7 +97,7 @@ LL | u8::try_from(1i32); | ~~~~~~~~~~~~~~~~~~ error: casting `f64` to `isize` may truncate the value - --> tests/ui/cast.rs:51:5 + --> tests/ui/cast.rs:52:5 | LL | 1f64 as isize; | ^^^^^^^^^^^^^ @@ -105,7 +105,7 @@ LL | 1f64 as isize; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f64` to `usize` may truncate the value - --> tests/ui/cast.rs:53:5 + --> tests/ui/cast.rs:54:5 | LL | 1f64 as usize; | ^^^^^^^^^^^^^ @@ -113,13 +113,13 @@ LL | 1f64 as usize; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f64` to `usize` may lose the sign of the value - --> tests/ui/cast.rs:53:5 + --> tests/ui/cast.rs:54:5 | LL | 1f64 as usize; | ^^^^^^^^^^^^^ error: casting `u32` to `u16` may truncate the value - --> tests/ui/cast.rs:56:5 + --> tests/ui/cast.rs:57:5 | LL | 1f32 as u32 as u16; | ^^^^^^^^^^^^^^^^^^ @@ -131,7 +131,7 @@ LL | u16::try_from(1f32 as u32); | ~~~~~~~~~~~~~~~~~~~~~~~~~~ error: casting `f32` to `u32` may truncate the value - --> tests/ui/cast.rs:56:5 + --> tests/ui/cast.rs:57:5 | LL | 1f32 as u32 as u16; | ^^^^^^^^^^^ @@ -139,13 +139,13 @@ LL | 1f32 as u32 as u16; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:56:5 + --> tests/ui/cast.rs:57:5 | LL | 1f32 as u32 as u16; | ^^^^^^^^^^^ error: casting `i32` to `i8` may truncate the value - --> tests/ui/cast.rs:61:22 + --> tests/ui/cast.rs:62:22 | LL | let _x: i8 = 1i32 as _; | ^^^^^^^^^ @@ -157,7 +157,7 @@ LL | let _x: i8 = 1i32.try_into(); | ~~~~~~~~~~~~~~~ error: casting `f32` to `i32` may truncate the value - --> tests/ui/cast.rs:63:9 + --> tests/ui/cast.rs:64:9 | LL | 1f32 as i32; | ^^^^^^^^^^^ @@ -165,7 +165,7 @@ LL | 1f32 as i32; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f64` to `i32` may truncate the value - --> tests/ui/cast.rs:65:9 + --> tests/ui/cast.rs:66:9 | LL | 1f64 as i32; | ^^^^^^^^^^^ @@ -173,7 +173,7 @@ LL | 1f64 as i32; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f32` to `u8` may truncate the value - --> tests/ui/cast.rs:67:9 + --> tests/ui/cast.rs:68:9 | LL | 1f32 as u8; | ^^^^^^^^^^ @@ -181,13 +181,13 @@ LL | 1f32 as u8; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f32` to `u8` may lose the sign of the value - --> tests/ui/cast.rs:67:9 + --> tests/ui/cast.rs:68:9 | LL | 1f32 as u8; | ^^^^^^^^^^ error: casting `u8` to `i8` may wrap around the value - --> tests/ui/cast.rs:72:5 + --> tests/ui/cast.rs:73:5 | LL | 1u8 as i8; | ^^^^^^^^^ @@ -196,31 +196,31 @@ LL | 1u8 as i8; = help: to override `-D warnings` add `#[allow(clippy::cast_possible_wrap)]` error: casting `u16` to `i16` may wrap around the value - --> tests/ui/cast.rs:75:5 + --> tests/ui/cast.rs:76:5 | LL | 1u16 as i16; | ^^^^^^^^^^^ error: casting `u32` to `i32` may wrap around the value - --> tests/ui/cast.rs:77:5 + --> tests/ui/cast.rs:78:5 | LL | 1u32 as i32; | ^^^^^^^^^^^ error: casting `u64` to `i64` may wrap around the value - --> tests/ui/cast.rs:79:5 + --> tests/ui/cast.rs:80:5 | LL | 1u64 as i64; | ^^^^^^^^^^^ error: casting `usize` to `isize` may wrap around the value - --> tests/ui/cast.rs:81:5 + --> tests/ui/cast.rs:82:5 | LL | 1usize as isize; | ^^^^^^^^^^^^^^^ error: casting `usize` to `i8` may truncate the value - --> tests/ui/cast.rs:84:5 + --> tests/ui/cast.rs:85:5 | LL | 1usize as i8; | ^^^^^^^^^^^^ @@ -232,7 +232,7 @@ LL | i8::try_from(1usize); | ~~~~~~~~~~~~~~~~~~~~ error: casting `usize` to `i16` may truncate the value - --> tests/ui/cast.rs:87:5 + --> tests/ui/cast.rs:88:5 | LL | 1usize as i16; | ^^^^^^^^^^^^^ @@ -244,7 +244,7 @@ LL | i16::try_from(1usize); | ~~~~~~~~~~~~~~~~~~~~~ error: casting `usize` to `i16` may wrap around the value on targets with 16-bit wide pointers - --> tests/ui/cast.rs:87:5 + --> tests/ui/cast.rs:88:5 | LL | 1usize as i16; | ^^^^^^^^^^^^^ @@ -253,7 +253,7 @@ LL | 1usize as i16; = note: for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types error: casting `usize` to `i32` may truncate the value on targets with 64-bit wide pointers - --> tests/ui/cast.rs:92:5 + --> tests/ui/cast.rs:93:5 | LL | 1usize as i32; | ^^^^^^^^^^^^^ @@ -265,19 +265,19 @@ LL | i32::try_from(1usize); | ~~~~~~~~~~~~~~~~~~~~~ error: casting `usize` to `i32` may wrap around the value on targets with 32-bit wide pointers - --> tests/ui/cast.rs:92:5 + --> tests/ui/cast.rs:93:5 | LL | 1usize as i32; | ^^^^^^^^^^^^^ error: casting `usize` to `i64` may wrap around the value on targets with 64-bit wide pointers - --> tests/ui/cast.rs:96:5 + --> tests/ui/cast.rs:97:5 | LL | 1usize as i64; | ^^^^^^^^^^^^^ error: casting `u16` to `isize` may wrap around the value on targets with 16-bit wide pointers - --> tests/ui/cast.rs:101:5 + --> tests/ui/cast.rs:102:5 | LL | 1u16 as isize; | ^^^^^^^^^^^^^ @@ -286,13 +286,13 @@ LL | 1u16 as isize; = note: for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types error: casting `u32` to `isize` may wrap around the value on targets with 32-bit wide pointers - --> tests/ui/cast.rs:105:5 + --> tests/ui/cast.rs:106:5 | LL | 1u32 as isize; | ^^^^^^^^^^^^^ error: casting `u64` to `isize` may truncate the value on targets with 32-bit wide pointers - --> tests/ui/cast.rs:108:5 + --> tests/ui/cast.rs:109:5 | LL | 1u64 as isize; | ^^^^^^^^^^^^^ @@ -304,55 +304,55 @@ LL | isize::try_from(1u64); | ~~~~~~~~~~~~~~~~~~~~~ error: casting `u64` to `isize` may wrap around the value on targets with 64-bit wide pointers - --> tests/ui/cast.rs:108:5 + --> tests/ui/cast.rs:109:5 | LL | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:113:5 + --> tests/ui/cast.rs:114:5 | LL | -1i32 as u32; | ^^^^^^^^^^^^ error: casting `isize` to `usize` may lose the sign of the value - --> tests/ui/cast.rs:116:5 + --> tests/ui/cast.rs:117:5 | LL | -1isize as usize; | ^^^^^^^^^^^^^^^^ error: casting `i8` to `u8` may lose the sign of the value - --> tests/ui/cast.rs:127:5 + --> tests/ui/cast.rs:128:5 | LL | (i8::MIN).abs() as u8; | ^^^^^^^^^^^^^^^^^^^^^ error: casting `i64` to `u64` may lose the sign of the value - --> tests/ui/cast.rs:131:5 + --> tests/ui/cast.rs:132:5 | LL | (-1i64).abs() as u64; | ^^^^^^^^^^^^^^^^^^^^ error: casting `isize` to `usize` may lose the sign of the value - --> tests/ui/cast.rs:132:5 + --> tests/ui/cast.rs:133:5 | LL | (-1isize).abs() as usize; | ^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i64` to `u64` may lose the sign of the value - --> tests/ui/cast.rs:139:5 + --> tests/ui/cast.rs:140:5 | LL | (unsafe { (-1i64).checked_abs().unwrap_unchecked() }) as u64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i64` to `u64` may lose the sign of the value - --> tests/ui/cast.rs:154:5 + --> tests/ui/cast.rs:155:5 | LL | (unsafe { (-1i64).checked_isqrt().unwrap_unchecked() }) as u64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i64` to `i8` may truncate the value - --> tests/ui/cast.rs:205:5 + --> tests/ui/cast.rs:206:5 | LL | (-99999999999i64).min(1) as i8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -364,7 +364,7 @@ LL | i8::try_from((-99999999999i64).min(1)); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: casting `u64` to `u8` may truncate the value - --> tests/ui/cast.rs:219:5 + --> tests/ui/cast.rs:220:5 | LL | 999999u64.clamp(0, 256) as u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -376,7 +376,7 @@ LL | u8::try_from(999999u64.clamp(0, 256)); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: casting `main::E2` to `u8` may truncate the value - --> tests/ui/cast.rs:242:21 + --> tests/ui/cast.rs:243:21 | LL | let _ = self as u8; | ^^^^^^^^^^ @@ -388,7 +388,7 @@ LL | let _ = u8::try_from(self); | ~~~~~~~~~~~~~~~~~~ error: casting `main::E2::B` to `u8` will truncate the value - --> tests/ui/cast.rs:244:21 + --> tests/ui/cast.rs:245:21 | LL | let _ = Self::B as u8; | ^^^^^^^^^^^^^ @@ -397,7 +397,7 @@ LL | let _ = Self::B as u8; = help: to override `-D warnings` add `#[allow(clippy::cast_enum_truncation)]` error: casting `main::E5` to `i8` may truncate the value - --> tests/ui/cast.rs:286:21 + --> tests/ui/cast.rs:287:21 | LL | let _ = self as i8; | ^^^^^^^^^^ @@ -409,13 +409,13 @@ LL | let _ = i8::try_from(self); | ~~~~~~~~~~~~~~~~~~ error: casting `main::E5::A` to `i8` will truncate the value - --> tests/ui/cast.rs:288:21 + --> tests/ui/cast.rs:289:21 | LL | let _ = Self::A as i8; | ^^^^^^^^^^^^^ error: casting `main::E6` to `i16` may truncate the value - --> tests/ui/cast.rs:305:21 + --> tests/ui/cast.rs:306:21 | LL | let _ = self as i16; | ^^^^^^^^^^^ @@ -427,7 +427,7 @@ LL | let _ = i16::try_from(self); | ~~~~~~~~~~~~~~~~~~~ error: casting `main::E7` to `usize` may truncate the value on targets with 32-bit wide pointers - --> tests/ui/cast.rs:324:21 + --> tests/ui/cast.rs:325:21 | LL | let _ = self as usize; | ^^^^^^^^^^^^^ @@ -439,7 +439,7 @@ LL | let _ = usize::try_from(self); | ~~~~~~~~~~~~~~~~~~~~~ error: casting `main::E10` to `u16` may truncate the value - --> tests/ui/cast.rs:371:21 + --> tests/ui/cast.rs:372:21 | LL | let _ = self as u16; | ^^^^^^^^^^^ @@ -451,7 +451,7 @@ LL | let _ = u16::try_from(self); | ~~~~~~~~~~~~~~~~~~~ error: casting `u32` to `u8` may truncate the value - --> tests/ui/cast.rs:382:13 + --> tests/ui/cast.rs:383:13 | LL | let c = (q >> 16) as u8; | ^^^^^^^^^^^^^^^ @@ -463,7 +463,7 @@ LL | let c = u8::try_from(q >> 16); | ~~~~~~~~~~~~~~~~~~~~~ error: casting `u32` to `u8` may truncate the value - --> tests/ui/cast.rs:386:13 + --> tests/ui/cast.rs:387:13 | LL | let c = (q / 1000) as u8; | ^^^^^^^^^^^^^^^^ @@ -475,85 +475,85 @@ LL | let c = u8::try_from(q / 1000); | ~~~~~~~~~~~~~~~~~~~~~~ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:398:9 + --> tests/ui/cast.rs:399:9 | LL | (x * x) as u32; | ^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:403:32 + --> tests/ui/cast.rs:404:32 | LL | let _a = |x: i32| -> u32 { (x * x * x * x) as u32 }; | ^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:405:5 + --> tests/ui/cast.rs:406:5 | LL | (2_i32).checked_pow(3).unwrap() as u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:406:5 + --> tests/ui/cast.rs:407:5 | LL | (-2_i32).pow(3) as u32; | ^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:411:5 + --> tests/ui/cast.rs:412:5 | LL | (-5_i32 % 2) as u32; | ^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:413:5 + --> tests/ui/cast.rs:414:5 | LL | (-5_i32 % -2) as u32; | ^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:416:5 + --> tests/ui/cast.rs:417:5 | LL | (-2_i32 >> 1) as u32; | ^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:420:5 + --> tests/ui/cast.rs:421:5 | LL | (x * x) as u32; | ^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:421:5 + --> tests/ui/cast.rs:422:5 | LL | (x * x * x) as u32; | ^^^^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:425:5 + --> tests/ui/cast.rs:426:5 | LL | (y * y * y * y * -2) as u16; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:427:5 + --> tests/ui/cast.rs:428:5 | LL | (y * y * y / y * 2) as u16; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:428:5 + --> tests/ui/cast.rs:429:5 | LL | (y * y / y * 2) as u16; | ^^^^^^^^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:430:5 + --> tests/ui/cast.rs:431:5 | LL | (y / y * y * -2) as u16; | ^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `/` - --> tests/ui/cast.rs:430:6 + --> tests/ui/cast.rs:431:6 | LL | (y / y * y * -2) as u16; | ^^^^^ @@ -561,97 +561,97 @@ LL | (y / y * y * -2) as u16; = note: `#[deny(clippy::eq_op)]` on by default error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:433:5 + --> tests/ui/cast.rs:434:5 | LL | (y + y + y + -2) as u16; | ^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:435:5 + --> tests/ui/cast.rs:436:5 | LL | (y + y + y + 2) as u16; | ^^^^^^^^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:439:5 + --> tests/ui/cast.rs:440:5 | LL | (z + -2) as u16; | ^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:441:5 + --> tests/ui/cast.rs:442:5 | LL | (z + z + 2) as u16; | ^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:444:9 + --> tests/ui/cast.rs:445:9 | LL | (a * a * b * b * c * c) as u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:445:9 + --> tests/ui/cast.rs:446:9 | LL | (a * b * c) as u32; | ^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:447:9 + --> tests/ui/cast.rs:448:9 | LL | (a * -b * c) as u32; | ^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:449:9 + --> tests/ui/cast.rs:450:9 | LL | (a * b * c * c) as u32; | ^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:450:9 + --> tests/ui/cast.rs:451:9 | LL | (a * -2) as u32; | ^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:452:9 + --> tests/ui/cast.rs:453:9 | LL | (a * b * c * -2) as u32; | ^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:454:9 + --> tests/ui/cast.rs:455:9 | LL | (a / b) as u32; | ^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:455:9 + --> tests/ui/cast.rs:456:9 | LL | (a / b * c) as u32; | ^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:457:9 + --> tests/ui/cast.rs:458:9 | LL | (a / b + b * c) as u32; | ^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:459:9 + --> tests/ui/cast.rs:460:9 | LL | a.saturating_pow(3) as u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:461:9 + --> tests/ui/cast.rs:462:9 | LL | (a.abs() * b.pow(2) / c.abs()) as u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:469:21 + --> tests/ui/cast.rs:470:21 | LL | let _ = i32::MIN as u32; // cast_sign_loss | ^^^^^^^^^^^^^^^ @@ -662,7 +662,7 @@ LL | m!(); = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: casting `u32` to `u8` may truncate the value - --> tests/ui/cast.rs:470:21 + --> tests/ui/cast.rs:471:21 | LL | let _ = u32::MAX as u8; // cast_possible_truncation | ^^^^^^^^^^^^^^ @@ -678,7 +678,7 @@ LL | let _ = u8::try_from(u32::MAX); // cast_possible_truncation | ~~~~~~~~~~~~~~~~~~~~~~ error: casting `f64` to `f32` may truncate the value - --> tests/ui/cast.rs:471:21 + --> tests/ui/cast.rs:472:21 | LL | let _ = std::f64::consts::PI as f32; // cast_possible_truncation | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -690,7 +690,7 @@ LL | m!(); = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: casting `i64` to `usize` may truncate the value on targets with 32-bit wide pointers - --> tests/ui/cast.rs:480:5 + --> tests/ui/cast.rs:481:5 | LL | bar.unwrap().unwrap() as usize | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -702,10 +702,34 @@ LL | usize::try_from(bar.unwrap().unwrap()) | error: casting `i64` to `usize` may lose the sign of the value - --> tests/ui/cast.rs:480:5 + --> tests/ui/cast.rs:481:5 | LL | bar.unwrap().unwrap() as usize | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 90 previous errors +error: casting `u64` to `u8` may truncate the value + --> tests/ui/cast.rs:496:5 + | +LL | (256 & 999999u64) as u8; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... +help: ... or use `try_from` and handle the error accordingly + | +LL | u8::try_from(256 & 999999u64); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: casting `u64` to `u8` may truncate the value + --> tests/ui/cast.rs:498:5 + | +LL | (255 % 999999u64) as u8; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... +help: ... or use `try_from` and handle the error accordingly + | +LL | u8::try_from(255 % 999999u64); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 92 previous errors diff --git a/src/tools/clippy/tests/ui/collapsible_match.rs b/src/tools/clippy/tests/ui/collapsible_match.rs index 7501fd2b0bd..2264b560791 100644 --- a/src/tools/clippy/tests/ui/collapsible_match.rs +++ b/src/tools/clippy/tests/ui/collapsible_match.rs @@ -4,7 +4,8 @@ clippy::needless_return, clippy::no_effect, clippy::single_match, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::let_unit_value )] fn lint_cases(opt_opt: Option<Option<u32>>, res_opt: Result<Option<u32>, String>) { @@ -238,13 +239,22 @@ fn negative_cases(res_opt: Result<Option<u32>, String>, res_res: Result<Result<u }, _ => return, } - match make::<Option<E<u32>>>() { + #[clippy::msrv = "1.52.0"] + let _ = match make::<Option<E<u32>>>() { Some(val) => match val { E::A(val) | E::B(val) => foo(val), _ => return, }, _ => return, - } + }; + #[clippy::msrv = "1.53.0"] + let _ = match make::<Option<E<u32>>>() { + Some(val) => match val { + E::A(val) | E::B(val) => foo(val), + _ => return, + }, + _ => return, + }; if let Ok(val) = res_opt { if let Some(n) = val { let _ = || { diff --git a/src/tools/clippy/tests/ui/collapsible_match.stderr b/src/tools/clippy/tests/ui/collapsible_match.stderr index 46b484ab05c..01944baee79 100644 --- a/src/tools/clippy/tests/ui/collapsible_match.stderr +++ b/src/tools/clippy/tests/ui/collapsible_match.stderr @@ -1,5 +1,5 @@ error: this `match` can be collapsed into the outer `match` - --> tests/ui/collapsible_match.rs:13:20 + --> tests/ui/collapsible_match.rs:14:20 | LL | Ok(val) => match val { | ____________________^ @@ -10,7 +10,7 @@ LL | | }, | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> tests/ui/collapsible_match.rs:13:12 + --> tests/ui/collapsible_match.rs:14:12 | LL | Ok(val) => match val { | ^^^ replace this binding @@ -21,7 +21,7 @@ LL | Some(n) => foo(n), = help: to override `-D warnings` add `#[allow(clippy::collapsible_match)]` error: this `match` can be collapsed into the outer `match` - --> tests/ui/collapsible_match.rs:23:20 + --> tests/ui/collapsible_match.rs:24:20 | LL | Ok(val) => match val { | ____________________^ @@ -32,7 +32,7 @@ LL | | }, | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> tests/ui/collapsible_match.rs:23:12 + --> tests/ui/collapsible_match.rs:24:12 | LL | Ok(val) => match val { | ^^^ replace this binding @@ -41,7 +41,7 @@ LL | Some(n) => foo(n), | ^^^^^^^ with this pattern error: this `if let` can be collapsed into the outer `if let` - --> tests/ui/collapsible_match.rs:33:9 + --> tests/ui/collapsible_match.rs:34:9 | LL | / if let Some(n) = val { LL | | @@ -50,7 +50,7 @@ LL | | } | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> tests/ui/collapsible_match.rs:32:15 + --> tests/ui/collapsible_match.rs:33:15 | LL | if let Ok(val) = res_opt { | ^^^ replace this binding @@ -58,7 +58,7 @@ LL | if let Some(n) = val { | ^^^^^^^ with this pattern error: this `if let` can be collapsed into the outer `if let` - --> tests/ui/collapsible_match.rs:41:9 + --> tests/ui/collapsible_match.rs:42:9 | LL | / if let Some(n) = val { LL | | @@ -69,7 +69,7 @@ LL | | } | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> tests/ui/collapsible_match.rs:40:15 + --> tests/ui/collapsible_match.rs:41:15 | LL | if let Ok(val) = res_opt { | ^^^ replace this binding @@ -77,7 +77,7 @@ LL | if let Some(n) = val { | ^^^^^^^ with this pattern error: this `match` can be collapsed into the outer `if let` - --> tests/ui/collapsible_match.rs:53:9 + --> tests/ui/collapsible_match.rs:54:9 | LL | / match val { LL | | @@ -87,7 +87,7 @@ LL | | } | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> tests/ui/collapsible_match.rs:52:15 + --> tests/ui/collapsible_match.rs:53:15 | LL | if let Ok(val) = res_opt { | ^^^ replace this binding @@ -96,7 +96,7 @@ LL | Some(n) => foo(n), | ^^^^^^^ with this pattern error: this `if let` can be collapsed into the outer `match` - --> tests/ui/collapsible_match.rs:63:13 + --> tests/ui/collapsible_match.rs:64:13 | LL | / if let Some(n) = val { LL | | @@ -105,7 +105,7 @@ LL | | } | |_____________^ | help: the outer pattern can be modified to include the inner pattern - --> tests/ui/collapsible_match.rs:62:12 + --> tests/ui/collapsible_match.rs:63:12 | LL | Ok(val) => { | ^^^ replace this binding @@ -113,7 +113,7 @@ LL | if let Some(n) = val { | ^^^^^^^ with this pattern error: this `match` can be collapsed into the outer `if let` - --> tests/ui/collapsible_match.rs:73:9 + --> tests/ui/collapsible_match.rs:74:9 | LL | / match val { LL | | @@ -123,7 +123,7 @@ LL | | } | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> tests/ui/collapsible_match.rs:72:15 + --> tests/ui/collapsible_match.rs:73:15 | LL | if let Ok(val) = res_opt { | ^^^ replace this binding @@ -132,7 +132,7 @@ LL | Some(n) => foo(n), | ^^^^^^^ with this pattern error: this `if let` can be collapsed into the outer `match` - --> tests/ui/collapsible_match.rs:85:13 + --> tests/ui/collapsible_match.rs:86:13 | LL | / if let Some(n) = val { LL | | @@ -143,7 +143,7 @@ LL | | } | |_____________^ | help: the outer pattern can be modified to include the inner pattern - --> tests/ui/collapsible_match.rs:84:12 + --> tests/ui/collapsible_match.rs:85:12 | LL | Ok(val) => { | ^^^ replace this binding @@ -151,7 +151,7 @@ LL | if let Some(n) = val { | ^^^^^^^ with this pattern error: this `match` can be collapsed into the outer `match` - --> tests/ui/collapsible_match.rs:97:20 + --> tests/ui/collapsible_match.rs:98:20 | LL | Ok(val) => match val { | ____________________^ @@ -162,7 +162,7 @@ LL | | }, | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> tests/ui/collapsible_match.rs:97:12 + --> tests/ui/collapsible_match.rs:98:12 | LL | Ok(val) => match val { | ^^^ replace this binding @@ -171,7 +171,7 @@ LL | Some(n) => foo(n), | ^^^^^^^ with this pattern error: this `match` can be collapsed into the outer `match` - --> tests/ui/collapsible_match.rs:107:22 + --> tests/ui/collapsible_match.rs:108:22 | LL | Some(val) => match val { | ______________________^ @@ -182,7 +182,7 @@ LL | | }, | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> tests/ui/collapsible_match.rs:107:14 + --> tests/ui/collapsible_match.rs:108:14 | LL | Some(val) => match val { | ^^^ replace this binding @@ -190,8 +190,26 @@ LL | LL | Some(n) => foo(n), | ^^^^^^^ with this pattern +error: this `match` can be collapsed into the outer `match` + --> tests/ui/collapsible_match.rs:252:22 + | +LL | Some(val) => match val { + | ______________________^ +LL | | E::A(val) | E::B(val) => foo(val), +LL | | _ => return, +LL | | }, + | |_________^ + | +help: the outer pattern can be modified to include the inner pattern + --> tests/ui/collapsible_match.rs:252:14 + | +LL | Some(val) => match val { + | ^^^ replace this binding +LL | E::A(val) | E::B(val) => foo(val), + | ^^^^^^^^^^^^^^^^^^^^^ with this pattern + error: this `if let` can be collapsed into the outer `if let` - --> tests/ui/collapsible_match.rs:273:9 + --> tests/ui/collapsible_match.rs:283:9 | LL | / if let Some(u) = a { LL | | @@ -200,7 +218,7 @@ LL | | } | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> tests/ui/collapsible_match.rs:272:27 + --> tests/ui/collapsible_match.rs:282:27 | LL | if let Issue9647::A { a, .. } = x { | ^ replace this binding @@ -208,7 +226,7 @@ LL | if let Some(u) = a { | ^^^^^^^ with this pattern, prefixed by a: error: this `if let` can be collapsed into the outer `if let` - --> tests/ui/collapsible_match.rs:282:9 + --> tests/ui/collapsible_match.rs:292:9 | LL | / if let Some(u) = a { LL | | @@ -217,12 +235,12 @@ LL | | } | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> tests/ui/collapsible_match.rs:281:35 + --> tests/ui/collapsible_match.rs:291:35 | LL | if let Issue9647::A { a: Some(a), .. } = x { | ^ replace this binding LL | if let Some(u) = a { | ^^^^^^^ with this pattern -error: aborting due to 12 previous errors +error: aborting due to 13 previous errors diff --git a/src/tools/clippy/tests/ui/collection_is_never_read.rs b/src/tools/clippy/tests/ui/collection_is_never_read.rs index bd281f7870c..eeb10da3402 100644 --- a/src/tools/clippy/tests/ui/collection_is_never_read.rs +++ b/src/tools/clippy/tests/ui/collection_is_never_read.rs @@ -222,3 +222,17 @@ fn supported_types() { //~^ ERROR: collection is never read x.push_front(1); } + +fn issue11783() { + struct Sender; + impl Sender { + fn send(&self, msg: String) -> Result<(), ()> { + // pretend to send message + println!("{msg}"); + Ok(()) + } + } + + let mut users: Vec<Sender> = vec![]; + users.retain(|user| user.send("hello".to_string()).is_ok()); +} diff --git a/src/tools/clippy/tests/ui/crashes/ice-5238.rs b/src/tools/clippy/tests/ui/crashes/ice-5238.rs index fe03a39ad1b..ee2ae4f1a04 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-5238.rs +++ b/src/tools/clippy/tests/ui/crashes/ice-5238.rs @@ -3,7 +3,8 @@ #![feature(coroutines, coroutine_trait, stmt_expr_attributes)] fn main() { - let _ = #[coroutine] || { + let _ = #[coroutine] + || { yield; }; } diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.rs b/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.rs index adc53891ef5..490073f97fb 100644 --- a/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.rs +++ b/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.rs @@ -121,13 +121,12 @@ impl SelfType for AtomicUsize { // Even though a constant contains a generic type, if it also have an interior mutable type, // it should be linted at the definition site. trait BothOfCellAndGeneric<T> { - // this is a false negative in the current implementation. - const DIRECT: Cell<T>; + const DIRECT: Cell<T>; //~ ERROR: interior mutable const INDIRECT: Cell<*const T>; //~ ERROR: interior mutable } impl<T: ConstDefault> BothOfCellAndGeneric<T> for u64 { - const DIRECT: Cell<T> = Cell::new(T::DEFAULT); + const DIRECT: Cell<T> = Cell::new(T::DEFAULT); //~ ERROR: interior mutable const INDIRECT: Cell<*const T> = Cell::new(std::ptr::null()); } diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.stderr b/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.stderr index 328453efa24..1d1e9e2002f 100644 --- a/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.stderr +++ b/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.stderr @@ -55,22 +55,34 @@ LL | const WRAPPED_SELF: Option<Self> = Some(AtomicUsize::new(21)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable - --> tests/ui/declare_interior_mutable_const/traits.rs:126:5 + --> tests/ui/declare_interior_mutable_const/traits.rs:124:5 + | +LL | const DIRECT: Cell<T>; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: a `const` item should never be interior mutable + --> tests/ui/declare_interior_mutable_const/traits.rs:125:5 | LL | const INDIRECT: Cell<*const T>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable - --> tests/ui/declare_interior_mutable_const/traits.rs:142:5 + --> tests/ui/declare_interior_mutable_const/traits.rs:129:5 + | +LL | const DIRECT: Cell<T> = Cell::new(T::DEFAULT); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: a `const` item should never be interior mutable + --> tests/ui/declare_interior_mutable_const/traits.rs:141:5 | LL | const ATOMIC: AtomicUsize = AtomicUsize::new(18); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable - --> tests/ui/declare_interior_mutable_const/traits.rs:148:5 + --> tests/ui/declare_interior_mutable_const/traits.rs:147:5 | LL | const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 11 previous errors +error: aborting due to 13 previous errors diff --git a/src/tools/clippy/tests/ui/disallowed_names.rs b/src/tools/clippy/tests/ui/disallowed_names.rs index 9a701a2cbcf..13c883409bf 100644 --- a/src/tools/clippy/tests/ui/disallowed_names.rs +++ b/src/tools/clippy/tests/ui/disallowed_names.rs @@ -71,3 +71,8 @@ mod tests { } } } + +#[test] +fn test_with_disallowed_name() { + let foo = 0; +} diff --git a/src/tools/clippy/tests/ui/from_over_into.stderr b/src/tools/clippy/tests/ui/from_over_into.stderr index 0649a6cb0f3..f913ae0bb50 100644 --- a/src/tools/clippy/tests/ui/from_over_into.stderr +++ b/src/tools/clippy/tests/ui/from_over_into.stderr @@ -54,7 +54,7 @@ help: replace the `Into` implementation with `From<ExplicitPaths>` LL ~ impl core::convert::From<crate::ExplicitPaths> for bool { LL ~ fn from(mut val: crate::ExplicitPaths) -> Self { LL ~ let in_closure = || val.0; -LL | +LL | LL ~ val.0 = false; LL ~ val.0 | diff --git a/src/tools/clippy/tests/ui/large_stack_arrays.rs b/src/tools/clippy/tests/ui/large_stack_arrays.rs index d5c4f95f8c4..6bcaf481c9f 100644 --- a/src/tools/clippy/tests/ui/large_stack_arrays.rs +++ b/src/tools/clippy/tests/ui/large_stack_arrays.rs @@ -1,6 +1,9 @@ +//@aux-build:proc_macros.rs #![warn(clippy::large_stack_arrays)] #![allow(clippy::large_enum_variant)] +extern crate proc_macros; + #[derive(Clone, Copy)] struct S { pub data: [u64; 32], @@ -55,3 +58,48 @@ fn main() { [(); 20_000_000], ); } + +#[allow(clippy::useless_vec)] +fn issue_12586() { + macro_rules! dummy { + ($n:expr) => { + $n + }; + // Weird rule to test help messages. + ($a:expr => $b:expr) => { + [$a, $b, $a, $b] + //~^ ERROR: allocating a local array larger than 512000 bytes + }; + ($id:ident; $n:literal) => { + dummy!(::std::vec![$id;$n]) + }; + ($($id:expr),+ $(,)?) => { + ::std::vec![$($id),*] + } + } + macro_rules! create_then_move { + ($id:ident; $n:literal) => {{ + let _x_ = [$id; $n]; + //~^ ERROR: allocating a local array larger than 512000 bytes + _x_ + }}; + } + + let x = [0u32; 50_000]; + let y = vec![x, x, x, x, x]; + let y = vec![dummy![x, x, x, x, x]]; + let y = vec![dummy![[x, x, x, x, x]]]; + let y = dummy![x, x, x, x, x]; + let y = [x, x, dummy!(x), x, x]; + //~^ ERROR: allocating a local array larger than 512000 bytes + let y = dummy![x => x]; + let y = dummy![x;5]; + let y = dummy!(vec![dummy![x, x, x, x, x]]); + let y = dummy![[x, x, x, x, x]]; + //~^ ERROR: allocating a local array larger than 512000 bytes + + let y = proc_macros::make_it_big!([x; 1]); + //~^ ERROR: allocating a local array larger than 512000 bytes + let y = vec![proc_macros::make_it_big!([x; 10])]; + let y = vec![create_then_move![x; 5]; 5]; +} diff --git a/src/tools/clippy/tests/ui/large_stack_arrays.stderr b/src/tools/clippy/tests/ui/large_stack_arrays.stderr index 007ca61c2de..06294ee8b8c 100644 --- a/src/tools/clippy/tests/ui/large_stack_arrays.stderr +++ b/src/tools/clippy/tests/ui/large_stack_arrays.stderr @@ -1,5 +1,5 @@ error: allocating a local array larger than 512000 bytes - --> tests/ui/large_stack_arrays.rs:29:14 + --> tests/ui/large_stack_arrays.rs:32:14 | LL | let _x = [build(); 3]; | ^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | let _x = [build(); 3]; = help: to override `-D warnings` add `#[allow(clippy::large_stack_arrays)]` error: allocating a local array larger than 512000 bytes - --> tests/ui/large_stack_arrays.rs:32:14 + --> tests/ui/large_stack_arrays.rs:35:14 | LL | let _y = [build(), build(), build()]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | let _y = [build(), build(), build()]; = help: consider allocating on the heap with `vec![build(), build(), build()].into_boxed_slice()` error: allocating a local array larger than 512000 bytes - --> tests/ui/large_stack_arrays.rs:38:9 + --> tests/ui/large_stack_arrays.rs:41:9 | LL | [0u32; 20_000_000], | ^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | [0u32; 20_000_000], = help: consider allocating on the heap with `vec![0u32; 20_000_000].into_boxed_slice()` error: allocating a local array larger than 512000 bytes - --> tests/ui/large_stack_arrays.rs:40:9 + --> tests/ui/large_stack_arrays.rs:43:9 | LL | [S { data: [0; 32] }; 5000], | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | [S { data: [0; 32] }; 5000], = help: consider allocating on the heap with `vec![S { data: [0; 32] }; 5000].into_boxed_slice()` error: allocating a local array larger than 512000 bytes - --> tests/ui/large_stack_arrays.rs:42:9 + --> tests/ui/large_stack_arrays.rs:45:9 | LL | [Some(""); 20_000_000], | ^^^^^^^^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | [Some(""); 20_000_000], = help: consider allocating on the heap with `vec![Some(""); 20_000_000].into_boxed_slice()` error: allocating a local array larger than 512000 bytes - --> tests/ui/large_stack_arrays.rs:44:9 + --> tests/ui/large_stack_arrays.rs:47:9 | LL | [E::T(0); 5000], | ^^^^^^^^^^^^^^^ @@ -49,12 +49,56 @@ LL | [E::T(0); 5000], = help: consider allocating on the heap with `vec![E::T(0); 5000].into_boxed_slice()` error: allocating a local array larger than 512000 bytes - --> tests/ui/large_stack_arrays.rs:46:9 + --> tests/ui/large_stack_arrays.rs:49:9 | LL | [0u8; usize::MAX], | ^^^^^^^^^^^^^^^^^ | = help: consider allocating on the heap with `vec![0u8; usize::MAX].into_boxed_slice()` -error: aborting due to 7 previous errors +error: allocating a local array larger than 512000 bytes + --> tests/ui/large_stack_arrays.rs:93:13 + | +LL | let y = [x, x, dummy!(x), x, x]; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider allocating on the heap with `vec![x, x, dummy!(x), x, x].into_boxed_slice()` + +error: allocating a local array larger than 512000 bytes + --> tests/ui/large_stack_arrays.rs:70:13 + | +LL | [$a, $b, $a, $b] + | ^^^^^^^^^^^^^^^^ +... +LL | let y = dummy![x => x]; + | -------------- in this macro invocation + | + = note: this error originates in the macro `dummy` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: allocating a local array larger than 512000 bytes + --> tests/ui/large_stack_arrays.rs:98:20 + | +LL | let y = dummy![[x, x, x, x, x]]; + | ^^^^^^^^^^^^^^^ + | + = help: consider allocating on the heap with `vec![x, x, x, x, x].into_boxed_slice()` + +error: allocating a local array larger than 512000 bytes + --> tests/ui/large_stack_arrays.rs:101:39 + | +LL | let y = proc_macros::make_it_big!([x; 1]); + | ^^^^^^ + +error: allocating a local array larger than 512000 bytes + --> tests/ui/large_stack_arrays.rs:82:23 + | +LL | let _x_ = [$id; $n]; + | ^^^^^^^^^ +... +LL | let y = vec![create_then_move![x; 5]; 5]; + | ----------------------- in this macro invocation + | + = note: this error originates in the macro `create_then_move` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 12 previous errors diff --git a/src/tools/clippy/tests/ui/let_and_return.stderr b/src/tools/clippy/tests/ui/let_and_return.stderr index f614a5739a8..ff5962ec196 100644 --- a/src/tools/clippy/tests/ui/let_and_return.stderr +++ b/src/tools/clippy/tests/ui/let_and_return.stderr @@ -71,7 +71,7 @@ LL | result help: return the expression directly | LL ~ -LL | +LL | LL ~ (match self { LL + E::A(x) => x, LL + E::B(x) => x, diff --git a/src/tools/clippy/tests/ui/manual_is_ascii_check.fixed b/src/tools/clippy/tests/ui/manual_is_ascii_check.fixed index 9c4bd335ad8..a72caa3a37e 100644 --- a/src/tools/clippy/tests/ui/manual_is_ascii_check.fixed +++ b/src/tools/clippy/tests/ui/manual_is_ascii_check.fixed @@ -55,3 +55,30 @@ fn msrv_1_47() { const FOO: bool = 'x'.is_ascii_digit(); const BAR: bool = 'x'.is_ascii_hexdigit(); } + +#[allow(clippy::deref_addrof, clippy::needless_borrow)] +fn with_refs() { + let cool_letter = &&'g'; + cool_letter.is_ascii_digit(); + cool_letter.is_ascii_lowercase(); +} + +fn generics() { + fn a<U>(u: &U) -> bool + where + char: PartialOrd<U>, + U: PartialOrd<char> + ?Sized, + { + ('A'..='Z').contains(u) + } + + fn take_while<Item, F>(cond: F) + where + Item: Sized, + F: Fn(Item) -> bool, + { + } + take_while(|c: char| c.is_ascii_uppercase()); + take_while(|c: u8| c.is_ascii_uppercase()); + take_while(|c: char| c.is_ascii_uppercase()); +} diff --git a/src/tools/clippy/tests/ui/manual_is_ascii_check.rs b/src/tools/clippy/tests/ui/manual_is_ascii_check.rs index 785943cd24d..bb6e2a317da 100644 --- a/src/tools/clippy/tests/ui/manual_is_ascii_check.rs +++ b/src/tools/clippy/tests/ui/manual_is_ascii_check.rs @@ -55,3 +55,30 @@ fn msrv_1_47() { const FOO: bool = matches!('x', '0'..='9'); const BAR: bool = matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F'); } + +#[allow(clippy::deref_addrof, clippy::needless_borrow)] +fn with_refs() { + let cool_letter = &&'g'; + ('0'..='9').contains(&&cool_letter); + ('a'..='z').contains(*cool_letter); +} + +fn generics() { + fn a<U>(u: &U) -> bool + where + char: PartialOrd<U>, + U: PartialOrd<char> + ?Sized, + { + ('A'..='Z').contains(u) + } + + fn take_while<Item, F>(cond: F) + where + Item: Sized, + F: Fn(Item) -> bool, + { + } + take_while(|c| ('A'..='Z').contains(&c)); + take_while(|c| (b'A'..=b'Z').contains(&c)); + take_while(|c: char| ('A'..='Z').contains(&c)); +} diff --git a/src/tools/clippy/tests/ui/manual_is_ascii_check.stderr b/src/tools/clippy/tests/ui/manual_is_ascii_check.stderr index 3632077ec80..a93ccace28a 100644 --- a/src/tools/clippy/tests/ui/manual_is_ascii_check.stderr +++ b/src/tools/clippy/tests/ui/manual_is_ascii_check.stderr @@ -133,5 +133,45 @@ error: manual check for common ascii range LL | const BAR: bool = matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F'); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_hexdigit()` -error: aborting due to 22 previous errors +error: manual check for common ascii range + --> tests/ui/manual_is_ascii_check.rs:62:5 + | +LL | ('0'..='9').contains(&&cool_letter); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cool_letter.is_ascii_digit()` + +error: manual check for common ascii range + --> tests/ui/manual_is_ascii_check.rs:63:5 + | +LL | ('a'..='z').contains(*cool_letter); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cool_letter.is_ascii_lowercase()` + +error: manual check for common ascii range + --> tests/ui/manual_is_ascii_check.rs:81:20 + | +LL | take_while(|c| ('A'..='Z').contains(&c)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL | take_while(|c: char| c.is_ascii_uppercase()); + | ~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~ + +error: manual check for common ascii range + --> tests/ui/manual_is_ascii_check.rs:82:20 + | +LL | take_while(|c| (b'A'..=b'Z').contains(&c)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL | take_while(|c: u8| c.is_ascii_uppercase()); + | ~~~~~ ~~~~~~~~~~~~~~~~~~~~~~ + +error: manual check for common ascii range + --> tests/ui/manual_is_ascii_check.rs:83:26 + | +LL | take_while(|c: char| ('A'..='Z').contains(&c)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `c.is_ascii_uppercase()` + +error: aborting due to 27 previous errors diff --git a/src/tools/clippy/tests/ui/manual_strip.stderr b/src/tools/clippy/tests/ui/manual_strip.stderr index d2d4f765310..a70c988a054 100644 --- a/src/tools/clippy/tests/ui/manual_strip.stderr +++ b/src/tools/clippy/tests/ui/manual_strip.stderr @@ -17,7 +17,7 @@ LL ~ if let Some(<stripped>) = s.strip_prefix("ab") { LL ~ str::to_string(<stripped>); LL | LL ~ <stripped>.to_string(); -LL | +LL | LL ~ str::to_string(<stripped>); LL ~ <stripped>.to_string(); | @@ -39,7 +39,7 @@ LL ~ if let Some(<stripped>) = s.strip_suffix("bc") { LL ~ str::to_string(<stripped>); LL | LL ~ <stripped>.to_string(); -LL | +LL | LL ~ str::to_string(<stripped>); LL ~ <stripped>.to_string(); | diff --git a/src/tools/clippy/tests/ui/mistyped_literal_suffix.fixed b/src/tools/clippy/tests/ui/mistyped_literal_suffix.fixed index 861764a2aee..b84b3dc349e 100644 --- a/src/tools/clippy/tests/ui/mistyped_literal_suffix.fixed +++ b/src/tools/clippy/tests/ui/mistyped_literal_suffix.fixed @@ -32,7 +32,7 @@ fn main() { // testing that the suggestion actually fits in its type let fail30 = 127_i8; // should be i8 let fail31 = 240_u8; // should be u8 - let ok32 = 360_8; // doesnt fit in either, should be ignored + let ok32 = 360_8; // doesn't fit in either, should be ignored let fail33 = 0x1234_i16; let fail34 = 0xABCD_u16; let ok35 = 0x12345_16; diff --git a/src/tools/clippy/tests/ui/mistyped_literal_suffix.rs b/src/tools/clippy/tests/ui/mistyped_literal_suffix.rs index 4a15c335fd8..a47a736067a 100644 --- a/src/tools/clippy/tests/ui/mistyped_literal_suffix.rs +++ b/src/tools/clippy/tests/ui/mistyped_literal_suffix.rs @@ -32,7 +32,7 @@ fn main() { // testing that the suggestion actually fits in its type let fail30 = 127_8; // should be i8 let fail31 = 240_8; // should be u8 - let ok32 = 360_8; // doesnt fit in either, should be ignored + let ok32 = 360_8; // doesn't fit in either, should be ignored let fail33 = 0x1234_16; let fail34 = 0xABCD_16; let ok35 = 0x12345_16; diff --git a/src/tools/clippy/tests/ui/mut_key.rs b/src/tools/clippy/tests/ui/mut_key.rs index 2d70bfd4c77..81d8732b3b2 100644 --- a/src/tools/clippy/tests/ui/mut_key.rs +++ b/src/tools/clippy/tests/ui/mut_key.rs @@ -5,7 +5,7 @@ use std::rc::Rc; use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering::Relaxed; use std::sync::Arc; -//@no-rustfix + struct Key(AtomicUsize); impl Clone for Key { @@ -77,8 +77,6 @@ fn main() { //~^ ERROR: mutable key type let _map = HashMap::<&mut Cell<usize>, usize>::new(); //~^ ERROR: mutable key type - let _map = HashMap::<&mut usize, usize>::new(); - //~^ ERROR: mutable key type // Collection types from `std` who's impl of `Hash` or `Ord` delegate their type parameters let _map = HashMap::<Vec<Cell<usize>>, usize>::new(); //~^ ERROR: mutable key type @@ -92,8 +90,6 @@ fn main() { //~^ ERROR: mutable key type let _map = HashMap::<Option<Vec<Cell<usize>>>, usize>::new(); //~^ ERROR: mutable key type - let _map = HashMap::<Result<&mut usize, ()>, usize>::new(); - //~^ ERROR: mutable key type // Smart pointers from `std` who's impl of `Hash` or `Ord` delegate their type parameters let _map = HashMap::<Box<Cell<usize>>, usize>::new(); //~^ ERROR: mutable key type @@ -101,4 +97,8 @@ fn main() { //~^ ERROR: mutable key type let _map = HashMap::<Arc<Cell<usize>>, usize>::new(); //~^ ERROR: mutable key type + + // Not interior mutability + let _map = HashMap::<&mut usize, usize>::new(); + let _map = HashMap::<Result<&mut usize, ()>, usize>::new(); } diff --git a/src/tools/clippy/tests/ui/mut_key.stderr b/src/tools/clippy/tests/ui/mut_key.stderr index e54c3075d4f..5ad9aad2d0a 100644 --- a/src/tools/clippy/tests/ui/mut_key.stderr +++ b/src/tools/clippy/tests/ui/mut_key.stderr @@ -38,70 +38,58 @@ LL | let _map = HashMap::<&mut Cell<usize>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> tests/ui/mut_key.rs:80:5 - | -LL | let _map = HashMap::<&mut usize, usize>::new(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: mutable key type - --> tests/ui/mut_key.rs:83:5 + --> tests/ui/mut_key.rs:81:5 | LL | let _map = HashMap::<Vec<Cell<usize>>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> tests/ui/mut_key.rs:85:5 + --> tests/ui/mut_key.rs:83:5 | LL | let _map = HashMap::<BTreeMap<Cell<usize>, ()>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> tests/ui/mut_key.rs:87:5 + --> tests/ui/mut_key.rs:85:5 | LL | let _map = HashMap::<BTreeMap<(), Cell<usize>>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> tests/ui/mut_key.rs:89:5 + --> tests/ui/mut_key.rs:87:5 | LL | let _map = HashMap::<BTreeSet<Cell<usize>>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> tests/ui/mut_key.rs:91:5 + --> tests/ui/mut_key.rs:89:5 | LL | let _map = HashMap::<Option<Cell<usize>>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> tests/ui/mut_key.rs:93:5 + --> tests/ui/mut_key.rs:91:5 | LL | let _map = HashMap::<Option<Vec<Cell<usize>>>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> tests/ui/mut_key.rs:95:5 - | -LL | let _map = HashMap::<Result<&mut usize, ()>, usize>::new(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: mutable key type - --> tests/ui/mut_key.rs:98:5 + --> tests/ui/mut_key.rs:94:5 | LL | let _map = HashMap::<Box<Cell<usize>>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> tests/ui/mut_key.rs:100:5 + --> tests/ui/mut_key.rs:96:5 | LL | let _map = HashMap::<Rc<Cell<usize>>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> tests/ui/mut_key.rs:102:5 + --> tests/ui/mut_key.rs:98:5 | LL | let _map = HashMap::<Arc<Cell<usize>>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 17 previous errors +error: aborting due to 15 previous errors diff --git a/src/tools/clippy/tests/ui/needless_for_each_fixable.fixed b/src/tools/clippy/tests/ui/needless_for_each_fixable.fixed index 8c0e7ba7627..2362314290e 100644 --- a/src/tools/clippy/tests/ui/needless_for_each_fixable.fixed +++ b/src/tools/clippy/tests/ui/needless_for_each_fixable.fixed @@ -113,6 +113,10 @@ fn should_not_lint() { let _ = v.iter().for_each(|elem| { acc += elem; }); + // `for_each` has a closure with an unsafe block. + v.iter().for_each(|elem| unsafe { + acc += elem; + }); } fn main() {} diff --git a/src/tools/clippy/tests/ui/needless_for_each_fixable.rs b/src/tools/clippy/tests/ui/needless_for_each_fixable.rs index cdc903a636c..5b1186daa22 100644 --- a/src/tools/clippy/tests/ui/needless_for_each_fixable.rs +++ b/src/tools/clippy/tests/ui/needless_for_each_fixable.rs @@ -113,6 +113,10 @@ fn should_not_lint() { let _ = v.iter().for_each(|elem| { acc += elem; }); + // `for_each` has a closure with an unsafe block. + v.iter().for_each(|elem| unsafe { + acc += elem; + }); } fn main() {} diff --git a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs index a92197fb0af..3f5f55f4002 100644 --- a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs +++ b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs @@ -44,18 +44,13 @@ fn non_mut_ref(_: &Vec<u32>) {} struct Bar; impl Bar { - // Should not warn on `&mut self`. fn bar(&mut self) {} + //~^ ERROR: this argument is a mutable reference, but not used mutably fn mushroom(&self, vec: &mut Vec<i32>) -> usize { //~^ ERROR: this argument is a mutable reference, but not used mutably vec.len() } - - fn badger(&mut self, vec: &mut Vec<i32>) -> usize { - //~^ ERROR: this argument is a mutable reference, but not used mutably - vec.len() - } } trait Babar { @@ -307,6 +302,41 @@ fn filter_copy<T: Copy>(predicate: &mut impl FnMut(T) -> bool) -> impl FnMut(&T) move |&item| predicate(item) } +trait MutSelfTrait { + // Should not warn since it's a trait method. + fn mut_self(&mut self); +} + +struct MutSelf { + a: u32, +} + +impl MutSelf { + fn bar(&mut self) {} + //~^ ERROR: this argument is a mutable reference, but not used mutably + async fn foo(&mut self, u: &mut i32, v: &mut u32) { + //~^ ERROR: this argument is a mutable reference, but not used mutably + //~| ERROR: this argument is a mutable reference, but not used mutably + async { + *u += 1; + } + .await; + } + async fn foo2(&mut self, u: &mut i32, v: &mut u32) { + //~^ ERROR: this argument is a mutable reference, but not used mutably + async { + self.a += 1; + *u += 1; + } + .await; + } +} + +impl MutSelfTrait for MutSelf { + // Should not warn since it's a trait method. + fn mut_self(&mut self) {} +} + // `is_from_proc_macro` stress tests fn _empty_tup(x: &mut (())) {} fn _single_tup(x: &mut ((i32,))) {} diff --git a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr index 89dad3e60b1..21ca393dcb6 100644 --- a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr +++ b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr @@ -14,73 +14,73 @@ LL | fn foo6(s: &mut Vec<u32>) { | ^^^^^^^^^^^^^ help: consider changing to: `&Vec<u32>` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:50:29 + --> tests/ui/needless_pass_by_ref_mut.rs:47:12 | -LL | fn mushroom(&self, vec: &mut Vec<i32>) -> usize { - | ^^^^^^^^^^^^^ help: consider changing to: `&Vec<i32>` +LL | fn bar(&mut self) {} + | ^^^^^^^^^ help: consider changing to: `&self` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:55:31 + --> tests/ui/needless_pass_by_ref_mut.rs:50:29 | -LL | fn badger(&mut self, vec: &mut Vec<i32>) -> usize { - | ^^^^^^^^^^^^^ help: consider changing to: `&Vec<i32>` +LL | fn mushroom(&self, vec: &mut Vec<i32>) -> usize { + | ^^^^^^^^^^^^^ help: consider changing to: `&Vec<i32>` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:132:16 + --> tests/ui/needless_pass_by_ref_mut.rs:127:16 | LL | async fn a1(x: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:136:16 + --> tests/ui/needless_pass_by_ref_mut.rs:131:16 | LL | async fn a2(x: &mut i32, y: String) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:140:16 + --> tests/ui/needless_pass_by_ref_mut.rs:135:16 | LL | async fn a3(x: &mut i32, y: String, z: String) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:144:16 + --> tests/ui/needless_pass_by_ref_mut.rs:139:16 | LL | async fn a4(x: &mut i32, y: i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:148:24 + --> tests/ui/needless_pass_by_ref_mut.rs:143:24 | LL | async fn a5(x: i32, y: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:152:24 + --> tests/ui/needless_pass_by_ref_mut.rs:147:24 | LL | async fn a6(x: i32, y: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:156:32 + --> tests/ui/needless_pass_by_ref_mut.rs:151:32 | LL | async fn a7(x: i32, y: i32, z: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:160:24 + --> tests/ui/needless_pass_by_ref_mut.rs:155:24 | LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:160:45 + --> tests/ui/needless_pass_by_ref_mut.rs:155:45 | LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:194:16 + --> tests/ui/needless_pass_by_ref_mut.rs:189:16 | LL | fn cfg_warn(s: &mut u32) {} | ^^^^^^^^ help: consider changing to: `&u32` @@ -88,7 +88,7 @@ LL | fn cfg_warn(s: &mut u32) {} = note: this is cfg-gated and may require further changes error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:200:20 + --> tests/ui/needless_pass_by_ref_mut.rs:195:20 | LL | fn cfg_warn(s: &mut u32) {} | ^^^^^^^^ help: consider changing to: `&u32` @@ -96,19 +96,19 @@ LL | fn cfg_warn(s: &mut u32) {} = note: this is cfg-gated and may require further changes error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:214:39 + --> tests/ui/needless_pass_by_ref_mut.rs:209:39 | LL | async fn inner_async2(x: &mut i32, y: &mut u32) { | ^^^^^^^^ help: consider changing to: `&u32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:222:26 + --> tests/ui/needless_pass_by_ref_mut.rs:217:26 | LL | async fn inner_async3(x: &mut i32, y: &mut u32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:241:34 + --> tests/ui/needless_pass_by_ref_mut.rs:236:34 | LL | pub async fn call_in_closure1(n: &mut str) { | ^^^^^^^^ help: consider changing to: `&str` @@ -116,15 +116,7 @@ LL | pub async fn call_in_closure1(n: &mut str) { = warning: changing this function will impact semver compatibility error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:253:25 - | -LL | pub async fn closure(n: &mut usize) -> impl '_ + FnMut() { - | ^^^^^^^^^^ help: consider changing to: `&usize` - | - = warning: changing this function will impact semver compatibility - -error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:260:20 + --> tests/ui/needless_pass_by_ref_mut.rs:255:20 | LL | pub fn closure2(n: &mut usize) -> impl '_ + FnMut() -> usize { | ^^^^^^^^^^ help: consider changing to: `&usize` @@ -132,7 +124,7 @@ LL | pub fn closure2(n: &mut usize) -> impl '_ + FnMut() -> usize { = warning: changing this function will impact semver compatibility error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:271:26 + --> tests/ui/needless_pass_by_ref_mut.rs:266:26 | LL | pub async fn closure4(n: &mut usize) { | ^^^^^^^^^^ help: consider changing to: `&usize` @@ -140,64 +132,88 @@ LL | pub async fn closure4(n: &mut usize) { = warning: changing this function will impact semver compatibility error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:311:18 + --> tests/ui/needless_pass_by_ref_mut.rs:315:12 + | +LL | fn bar(&mut self) {} + | ^^^^^^^^^ help: consider changing to: `&self` + +error: this argument is a mutable reference, but not used mutably + --> tests/ui/needless_pass_by_ref_mut.rs:317:18 + | +LL | async fn foo(&mut self, u: &mut i32, v: &mut u32) { + | ^^^^^^^^^ help: consider changing to: `&self` + +error: this argument is a mutable reference, but not used mutably + --> tests/ui/needless_pass_by_ref_mut.rs:317:45 + | +LL | async fn foo(&mut self, u: &mut i32, v: &mut u32) { + | ^^^^^^^^ help: consider changing to: `&u32` + +error: this argument is a mutable reference, but not used mutably + --> tests/ui/needless_pass_by_ref_mut.rs:325:46 + | +LL | async fn foo2(&mut self, u: &mut i32, v: &mut u32) { + | ^^^^^^^^ help: consider changing to: `&u32` + +error: this argument is a mutable reference, but not used mutably + --> tests/ui/needless_pass_by_ref_mut.rs:341:18 | LL | fn _empty_tup(x: &mut (())) {} | ^^^^^^^^^ help: consider changing to: `&()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:312:19 + --> tests/ui/needless_pass_by_ref_mut.rs:342:19 | LL | fn _single_tup(x: &mut ((i32,))) {} | ^^^^^^^^^^^^^ help: consider changing to: `&(i32,)` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:313:18 + --> tests/ui/needless_pass_by_ref_mut.rs:343:18 | LL | fn _multi_tup(x: &mut ((i32, u32))) {} | ^^^^^^^^^^^^^^^^^ help: consider changing to: `&(i32, u32)` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:314:11 + --> tests/ui/needless_pass_by_ref_mut.rs:344:11 | LL | fn _fn(x: &mut (fn())) {} | ^^^^^^^^^^^ help: consider changing to: `&fn()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:316:23 + --> tests/ui/needless_pass_by_ref_mut.rs:346:23 | LL | fn _extern_rust_fn(x: &mut extern "Rust" fn()) {} | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&extern "Rust" fn()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:317:20 + --> tests/ui/needless_pass_by_ref_mut.rs:347:20 | LL | fn _extern_c_fn(x: &mut extern "C" fn()) {} | ^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&extern "C" fn()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:318:18 + --> tests/ui/needless_pass_by_ref_mut.rs:348:18 | LL | fn _unsafe_fn(x: &mut unsafe fn()) {} | ^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe fn()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:319:25 + --> tests/ui/needless_pass_by_ref_mut.rs:349:25 | LL | fn _unsafe_extern_fn(x: &mut unsafe extern "C" fn()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe extern "C" fn()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:320:20 + --> tests/ui/needless_pass_by_ref_mut.rs:350:20 | LL | fn _fn_with_arg(x: &mut unsafe extern "C" fn(i32)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe extern "C" fn(i32)` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:321:20 + --> tests/ui/needless_pass_by_ref_mut.rs:351:20 | LL | fn _fn_with_ret(x: &mut unsafe extern "C" fn() -> (i32)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe extern "C" fn() -> (i32)` -error: aborting due to 31 previous errors +error: aborting due to 34 previous errors diff --git a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut2.fixed b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut2.fixed new file mode 100644 index 00000000000..3c2576213cd --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut2.fixed @@ -0,0 +1,24 @@ +// If both `inner_async3` and `inner_async4` are present, aliases are declared after +// they're used in `inner_async4` for some reasons... This test ensures that no +// only `v` is marked as not used mutably in `inner_async4`. + +#![allow(clippy::redundant_closure_call)] +#![warn(clippy::needless_pass_by_ref_mut)] + +pub async fn inner_async3(x: &i32, y: &mut u32) { + //~^ ERROR: this argument is a mutable reference, but not used mutably + async { + *y += 1; + } + .await; +} + +pub async fn inner_async4(u: &mut i32, v: &u32) { + //~^ ERROR: this argument is a mutable reference, but not used mutably + async { + *u += 1; + } + .await; +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut2.rs b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut2.rs new file mode 100644 index 00000000000..34b0b564deb --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut2.rs @@ -0,0 +1,24 @@ +// If both `inner_async3` and `inner_async4` are present, aliases are declared after +// they're used in `inner_async4` for some reasons... This test ensures that no +// only `v` is marked as not used mutably in `inner_async4`. + +#![allow(clippy::redundant_closure_call)] +#![warn(clippy::needless_pass_by_ref_mut)] + +pub async fn inner_async3(x: &mut i32, y: &mut u32) { + //~^ ERROR: this argument is a mutable reference, but not used mutably + async { + *y += 1; + } + .await; +} + +pub async fn inner_async4(u: &mut i32, v: &mut u32) { + //~^ ERROR: this argument is a mutable reference, but not used mutably + async { + *u += 1; + } + .await; +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut2.stderr b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut2.stderr new file mode 100644 index 00000000000..c8753603225 --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut2.stderr @@ -0,0 +1,20 @@ +error: this argument is a mutable reference, but not used mutably + --> tests/ui/needless_pass_by_ref_mut2.rs:8:30 + | +LL | pub async fn inner_async3(x: &mut i32, y: &mut u32) { + | ^^^^^^^^ help: consider changing to: `&i32` + | + = warning: changing this function will impact semver compatibility + = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_ref_mut)]` + +error: this argument is a mutable reference, but not used mutably + --> tests/ui/needless_pass_by_ref_mut2.rs:16:43 + | +LL | pub async fn inner_async4(u: &mut i32, v: &mut u32) { + | ^^^^^^^^ help: consider changing to: `&u32` + | + = warning: changing this function will impact semver compatibility + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/non_canonical_partial_ord_impl.fixed b/src/tools/clippy/tests/ui/non_canonical_partial_ord_impl.fixed index db55cc094e3..d444a753697 100644 --- a/src/tools/clippy/tests/ui/non_canonical_partial_ord_impl.fixed +++ b/src/tools/clippy/tests/ui/non_canonical_partial_ord_impl.fixed @@ -142,3 +142,21 @@ impl PartialOrd for H { Some(Ord::cmp(self, other)) } } + +// #12683, do not lint + +#[derive(Eq, PartialEq)] +struct I(u32); + +impl Ord for I { + fn cmp(&self, other: &Self) -> Ordering { + todo!(); + } +} + +impl PartialOrd for I { + #[allow(clippy::needless_return)] + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + return Some(self.cmp(other)); + } +} diff --git a/src/tools/clippy/tests/ui/non_canonical_partial_ord_impl.rs b/src/tools/clippy/tests/ui/non_canonical_partial_ord_impl.rs index 52f4b85b917..dc6c4354604 100644 --- a/src/tools/clippy/tests/ui/non_canonical_partial_ord_impl.rs +++ b/src/tools/clippy/tests/ui/non_canonical_partial_ord_impl.rs @@ -146,3 +146,21 @@ impl PartialOrd for H { Some(Ord::cmp(self, other)) } } + +// #12683, do not lint + +#[derive(Eq, PartialEq)] +struct I(u32); + +impl Ord for I { + fn cmp(&self, other: &Self) -> Ordering { + todo!(); + } +} + +impl PartialOrd for I { + #[allow(clippy::needless_return)] + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + return Some(self.cmp(other)); + } +} diff --git a/src/tools/clippy/tests/ui/readonly_write_lock.fixed b/src/tools/clippy/tests/ui/readonly_write_lock.fixed index 76f4a43ae53..4db13482ac7 100644 --- a/src/tools/clippy/tests/ui/readonly_write_lock.fixed +++ b/src/tools/clippy/tests/ui/readonly_write_lock.fixed @@ -43,3 +43,7 @@ fn main() { *writer1 = *writer2; } } + +fn issue12733(rw: &RwLock<()>) { + let _write_guard = rw.write().unwrap(); +} diff --git a/src/tools/clippy/tests/ui/readonly_write_lock.rs b/src/tools/clippy/tests/ui/readonly_write_lock.rs index 3d1d3855fe1..66ba1b2d696 100644 --- a/src/tools/clippy/tests/ui/readonly_write_lock.rs +++ b/src/tools/clippy/tests/ui/readonly_write_lock.rs @@ -43,3 +43,7 @@ fn main() { *writer1 = *writer2; } } + +fn issue12733(rw: &RwLock<()>) { + let _write_guard = rw.write().unwrap(); +} diff --git a/src/tools/clippy/tests/ui/redundant_guards.fixed b/src/tools/clippy/tests/ui/redundant_guards.fixed index ded91e08376..ed4b1c21915 100644 --- a/src/tools/clippy/tests/ui/redundant_guards.fixed +++ b/src/tools/clippy/tests/ui/redundant_guards.fixed @@ -136,6 +136,18 @@ fn f(s: Option<std::ffi::OsString>) { } } +fn not_matches() { + match Some(42) { + // The pattern + guard is not equivalent to `Some(42)` because of the `panic!` + Some(v) + if match v { + 42 => true, + _ => panic!(), + } => {}, + _ => {}, + } +} + struct S { a: usize, } diff --git a/src/tools/clippy/tests/ui/redundant_guards.rs b/src/tools/clippy/tests/ui/redundant_guards.rs index 2aaa2ace398..adbc4ed16cd 100644 --- a/src/tools/clippy/tests/ui/redundant_guards.rs +++ b/src/tools/clippy/tests/ui/redundant_guards.rs @@ -136,6 +136,18 @@ fn f(s: Option<std::ffi::OsString>) { } } +fn not_matches() { + match Some(42) { + // The pattern + guard is not equivalent to `Some(42)` because of the `panic!` + Some(v) + if match v { + 42 => true, + _ => panic!(), + } => {}, + _ => {}, + } +} + struct S { a: usize, } diff --git a/src/tools/clippy/tests/ui/redundant_guards.stderr b/src/tools/clippy/tests/ui/redundant_guards.stderr index 01ca91fcd09..fd12e083282 100644 --- a/src/tools/clippy/tests/ui/redundant_guards.stderr +++ b/src/tools/clippy/tests/ui/redundant_guards.stderr @@ -132,7 +132,7 @@ LL + 1 => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:174:28 + --> tests/ui/redundant_guards.rs:186:28 | LL | Some(ref x) if x == &1 => {}, | ^^^^^^^ @@ -144,7 +144,7 @@ LL + Some(1) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:175:28 + --> tests/ui/redundant_guards.rs:187:28 | LL | Some(ref x) if &1 == x => {}, | ^^^^^^^ @@ -156,7 +156,7 @@ LL + Some(1) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:176:28 + --> tests/ui/redundant_guards.rs:188:28 | LL | Some(ref x) if let &2 = x => {}, | ^^^^^^^^^^ @@ -168,7 +168,7 @@ LL + Some(2) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:177:28 + --> tests/ui/redundant_guards.rs:189:28 | LL | Some(ref x) if matches!(x, &3) => {}, | ^^^^^^^^^^^^^^^ @@ -180,7 +180,7 @@ LL + Some(3) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:197:32 + --> tests/ui/redundant_guards.rs:209:32 | LL | B { ref c, .. } if c == &1 => {}, | ^^^^^^^ @@ -192,7 +192,7 @@ LL + B { c: 1, .. } => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:198:32 + --> tests/ui/redundant_guards.rs:210:32 | LL | B { ref c, .. } if &1 == c => {}, | ^^^^^^^ @@ -204,7 +204,7 @@ LL + B { c: 1, .. } => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:199:32 + --> tests/ui/redundant_guards.rs:211:32 | LL | B { ref c, .. } if let &1 = c => {}, | ^^^^^^^^^^ @@ -216,7 +216,7 @@ LL + B { c: 1, .. } => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:200:32 + --> tests/ui/redundant_guards.rs:212:32 | LL | B { ref c, .. } if matches!(c, &1) => {}, | ^^^^^^^^^^^^^^^ @@ -228,7 +228,7 @@ LL + B { c: 1, .. } => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:210:26 + --> tests/ui/redundant_guards.rs:222:26 | LL | Some(Some(x)) if x.is_empty() => {}, | ^^^^^^^^^^^^ @@ -240,7 +240,7 @@ LL + Some(Some("")) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:221:26 + --> tests/ui/redundant_guards.rs:233:26 | LL | Some(Some(x)) if x.is_empty() => {}, | ^^^^^^^^^^^^ @@ -252,7 +252,7 @@ LL + Some(Some([])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:226:26 + --> tests/ui/redundant_guards.rs:238:26 | LL | Some(Some(x)) if x.is_empty() => {}, | ^^^^^^^^^^^^ @@ -264,7 +264,7 @@ LL + Some(Some([])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:237:26 + --> tests/ui/redundant_guards.rs:249:26 | LL | Some(Some(x)) if x.starts_with(&[]) => {}, | ^^^^^^^^^^^^^^^^^^ @@ -276,7 +276,7 @@ LL + Some(Some([..])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:242:26 + --> tests/ui/redundant_guards.rs:254:26 | LL | Some(Some(x)) if x.starts_with(&[1]) => {}, | ^^^^^^^^^^^^^^^^^^^ @@ -288,7 +288,7 @@ LL + Some(Some([1, ..])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:247:26 + --> tests/ui/redundant_guards.rs:259:26 | LL | Some(Some(x)) if x.starts_with(&[1, 2]) => {}, | ^^^^^^^^^^^^^^^^^^^^^^ @@ -300,7 +300,7 @@ LL + Some(Some([1, 2, ..])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:252:26 + --> tests/ui/redundant_guards.rs:264:26 | LL | Some(Some(x)) if x.ends_with(&[1, 2]) => {}, | ^^^^^^^^^^^^^^^^^^^^ @@ -312,7 +312,7 @@ LL + Some(Some([.., 1, 2])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:274:18 + --> tests/ui/redundant_guards.rs:286:18 | LL | y if y.is_empty() => {}, | ^^^^^^^^^^^^ @@ -324,7 +324,7 @@ LL + "" => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:293:22 + --> tests/ui/redundant_guards.rs:305:22 | LL | y if y.is_empty() => {}, | ^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/redundant_locals.rs b/src/tools/clippy/tests/ui/redundant_locals.rs index e9d77182a91..d21aa240b2d 100644 --- a/src/tools/clippy/tests/ui/redundant_locals.rs +++ b/src/tools/clippy/tests/ui/redundant_locals.rs @@ -191,14 +191,20 @@ fn issue12225() { let v4 = v4; dbg!(&v4); }); - assert_static(#[coroutine] static || { - let v5 = v5; - yield; - }); - assert_static(#[coroutine] || { - let v6 = v6; - yield; - }); + assert_static( + #[coroutine] + static || { + let v5 = v5; + yield; + }, + ); + assert_static( + #[coroutine] + || { + let v6 = v6; + yield; + }, + ); fn foo(a: &str, b: &str) {} diff --git a/src/tools/clippy/tests/ui/result_map_unit_fn_unfixable.stderr b/src/tools/clippy/tests/ui/result_map_unit_fn_unfixable.stderr index fa2ac7a1b37..d69c86c70e2 100644 --- a/src/tools/clippy/tests/ui/result_map_unit_fn_unfixable.stderr +++ b/src/tools/clippy/tests/ui/result_map_unit_fn_unfixable.stderr @@ -27,7 +27,7 @@ LL | || do_nothing(value) LL | || }); | ||______^- help: try: `if let Ok(value) = x.field { ... }` | |______| - | + | error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` --> tests/ui/result_map_unit_fn_unfixable.rs:37:5 diff --git a/src/tools/clippy/tests/ui/single_char_pattern.fixed b/src/tools/clippy/tests/ui/single_char_pattern.fixed index 9573fdbcfde..a18d6319f89 100644 --- a/src/tools/clippy/tests/ui/single_char_pattern.fixed +++ b/src/tools/clippy/tests/ui/single_char_pattern.fixed @@ -1,5 +1,5 @@ #![allow(clippy::needless_raw_strings, clippy::needless_raw_string_hashes, unused_must_use)] - +#![warn(clippy::single_char_pattern)] use std::collections::HashSet; fn main() { @@ -10,9 +10,9 @@ fn main() { let y = "x"; x.split(y); - x.split('ß'); - x.split('â„'); - x.split('💣'); + x.split("ß"); + x.split("â„"); + x.split("💣"); // Can't use this lint for unicode code points which don't fit in a char x.split("â¤ï¸"); x.split_inclusive('x'); @@ -34,8 +34,6 @@ fn main() { x.rmatch_indices('x'); x.trim_start_matches('x'); x.trim_end_matches('x'); - x.strip_prefix('x'); - x.strip_suffix('x'); x.replace('x', "y"); x.replacen('x', "y", 3); // Make sure we escape characters correctly. @@ -64,4 +62,8 @@ fn main() { // Must escape backslash in raw strings when converting to char #8060 x.split('\\'); x.split('\\'); + + // should not warn, the char versions are actually slower in some cases + x.strip_prefix("x"); + x.strip_suffix("x"); } diff --git a/src/tools/clippy/tests/ui/single_char_pattern.rs b/src/tools/clippy/tests/ui/single_char_pattern.rs index 8a04480dbc6..b52e6fb2fdf 100644 --- a/src/tools/clippy/tests/ui/single_char_pattern.rs +++ b/src/tools/clippy/tests/ui/single_char_pattern.rs @@ -1,5 +1,5 @@ #![allow(clippy::needless_raw_strings, clippy::needless_raw_string_hashes, unused_must_use)] - +#![warn(clippy::single_char_pattern)] use std::collections::HashSet; fn main() { @@ -34,8 +34,6 @@ fn main() { x.rmatch_indices("x"); x.trim_start_matches("x"); x.trim_end_matches("x"); - x.strip_prefix("x"); - x.strip_suffix("x"); x.replace("x", "y"); x.replacen("x", "y", 3); // Make sure we escape characters correctly. @@ -64,4 +62,8 @@ fn main() { // Must escape backslash in raw strings when converting to char #8060 x.split(r#"\"#); x.split(r"\"); + + // should not warn, the char versions are actually slower in some cases + x.strip_prefix("x"); + x.strip_suffix("x"); } diff --git a/src/tools/clippy/tests/ui/single_char_pattern.stderr b/src/tools/clippy/tests/ui/single_char_pattern.stderr index 5a2ec6c764b..b2deed23cbd 100644 --- a/src/tools/clippy/tests/ui/single_char_pattern.stderr +++ b/src/tools/clippy/tests/ui/single_char_pattern.stderr @@ -8,24 +8,6 @@ LL | x.split("x"); = help: to override `-D warnings` add `#[allow(clippy::single_char_pattern)]` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:13:13 - | -LL | x.split("ß"); - | ^^^ help: consider using a `char`: `'ß'` - -error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:14:13 - | -LL | x.split("â„"); - | ^^^ help: consider using a `char`: `'â„'` - -error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:15:13 - | -LL | x.split("💣"); - | ^^^^ help: consider using a `char`: `'💣'` - -error: single-character string constant used as pattern --> tests/ui/single_char_pattern.rs:18:23 | LL | x.split_inclusive("x"); @@ -140,106 +122,94 @@ LL | x.trim_end_matches("x"); | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:37:20 - | -LL | x.strip_prefix("x"); - | ^^^ help: consider using a `char`: `'x'` - -error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:38:20 - | -LL | x.strip_suffix("x"); - | ^^^ help: consider using a `char`: `'x'` - -error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:39:15 + --> tests/ui/single_char_pattern.rs:37:15 | LL | x.replace("x", "y"); | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:40:16 + --> tests/ui/single_char_pattern.rs:38:16 | LL | x.replacen("x", "y", 3); | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:42:13 + --> tests/ui/single_char_pattern.rs:40:13 | LL | x.split("\n"); | ^^^^ help: consider using a `char`: `'\n'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:43:13 + --> tests/ui/single_char_pattern.rs:41:13 | LL | x.split("'"); | ^^^ help: consider using a `char`: `'\''` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:44:13 + --> tests/ui/single_char_pattern.rs:42:13 | LL | x.split("\'"); | ^^^^ help: consider using a `char`: `'\''` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:46:13 + --> tests/ui/single_char_pattern.rs:44:13 | LL | x.split("\""); | ^^^^ help: consider using a `char`: `'"'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:51:31 + --> tests/ui/single_char_pattern.rs:49:31 | LL | x.replace(';', ",").split(","); // issue #2978 | ^^^ help: consider using a `char`: `','` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:52:19 + --> tests/ui/single_char_pattern.rs:50:19 | LL | x.starts_with("\x03"); // issue #2996 | ^^^^^^ help: consider using a `char`: `'\x03'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:59:13 + --> tests/ui/single_char_pattern.rs:57:13 | LL | x.split(r"a"); | ^^^^ help: consider using a `char`: `'a'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:60:13 + --> tests/ui/single_char_pattern.rs:58:13 | LL | x.split(r#"a"#); | ^^^^^^ help: consider using a `char`: `'a'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:61:13 + --> tests/ui/single_char_pattern.rs:59:13 | LL | x.split(r###"a"###); | ^^^^^^^^^^ help: consider using a `char`: `'a'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:62:13 + --> tests/ui/single_char_pattern.rs:60:13 | LL | x.split(r###"'"###); | ^^^^^^^^^^ help: consider using a `char`: `'\''` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:63:13 + --> tests/ui/single_char_pattern.rs:61:13 | LL | x.split(r###"#"###); | ^^^^^^^^^^ help: consider using a `char`: `'#'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:65:13 + --> tests/ui/single_char_pattern.rs:63:13 | LL | x.split(r#"\"#); | ^^^^^^ help: consider using a `char`: `'\\'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:66:13 + --> tests/ui/single_char_pattern.rs:64:13 | LL | x.split(r"\"); | ^^^^ help: consider using a `char`: `'\\'` -error: aborting due to 40 previous errors +error: aborting due to 35 previous errors diff --git a/src/tools/clippy/tests/ui/suspicious_doc_comments.stderr b/src/tools/clippy/tests/ui/suspicious_doc_comments.stderr index b54309b44d5..f12053b1595 100644 --- a/src/tools/clippy/tests/ui/suspicious_doc_comments.stderr +++ b/src/tools/clippy/tests/ui/suspicious_doc_comments.stderr @@ -85,7 +85,7 @@ LL | | ///! b help: use an inner doc comment to document the parent module or crate | LL ~ //! a -LL | +LL | LL ~ //! b | diff --git a/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.fixed b/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.fixed index a6ed59d49c5..4c9bd0bd863 100644 --- a/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.fixed +++ b/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.fixed @@ -1,6 +1,6 @@ #![warn(clippy::thread_local_initializer_can_be_made_const)] -use std::cell::RefCell; +use std::cell::{Cell, RefCell}; fn main() { // lint and suggest const @@ -36,6 +36,37 @@ fn main() { } } +fn issue_12637() { + /// The set methods on LocalKey<Cell<T>> and LocalKey<RefCell<T>> are + /// guaranteed to bypass the thread_local's initialization expression. + /// See rust-lang/rust#92122. Thus, = panic!() is a useful idiom for + /// forcing the use of set on each thread before it accesses the thread local in any other + /// manner. + thread_local! { + static STATE_12637_PANIC: Cell<usize> = panic!(); + } + STATE_12637_PANIC.set(9); + println!("{}", STATE_12637_PANIC.get()); + + thread_local! { + static STATE_12637_TODO: Cell<usize> = todo!(); + } + STATE_12637_TODO.set(9); + println!("{}", STATE_12637_TODO.get()); + + thread_local! { + static STATE_12637_UNIMPLEMENTED: Cell<usize> = unimplemented!(); + } + STATE_12637_UNIMPLEMENTED.set(9); + println!("{}", STATE_12637_UNIMPLEMENTED.get()); + + thread_local! { + static STATE_12637_UNREACHABLE: Cell<usize> = unreachable!(); + } + STATE_12637_UNREACHABLE.set(9); + println!("{}", STATE_12637_UNREACHABLE.get()); +} + #[clippy::msrv = "1.58"] fn f() { thread_local! { diff --git a/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.rs b/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.rs index 3f0159c5806..eb336f0dd19 100644 --- a/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.rs +++ b/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.rs @@ -1,6 +1,6 @@ #![warn(clippy::thread_local_initializer_can_be_made_const)] -use std::cell::RefCell; +use std::cell::{Cell, RefCell}; fn main() { // lint and suggest const @@ -36,6 +36,37 @@ fn main() { } } +fn issue_12637() { + /// The set methods on LocalKey<Cell<T>> and LocalKey<RefCell<T>> are + /// guaranteed to bypass the thread_local's initialization expression. + /// See rust-lang/rust#92122. Thus, = panic!() is a useful idiom for + /// forcing the use of set on each thread before it accesses the thread local in any other + /// manner. + thread_local! { + static STATE_12637_PANIC: Cell<usize> = panic!(); + } + STATE_12637_PANIC.set(9); + println!("{}", STATE_12637_PANIC.get()); + + thread_local! { + static STATE_12637_TODO: Cell<usize> = todo!(); + } + STATE_12637_TODO.set(9); + println!("{}", STATE_12637_TODO.get()); + + thread_local! { + static STATE_12637_UNIMPLEMENTED: Cell<usize> = unimplemented!(); + } + STATE_12637_UNIMPLEMENTED.set(9); + println!("{}", STATE_12637_UNIMPLEMENTED.get()); + + thread_local! { + static STATE_12637_UNREACHABLE: Cell<usize> = unreachable!(); + } + STATE_12637_UNREACHABLE.set(9); + println!("{}", STATE_12637_UNREACHABLE.get()); +} + #[clippy::msrv = "1.58"] fn f() { thread_local! { diff --git a/src/tools/clippy/tests/ui/type_complexity.rs b/src/tools/clippy/tests/ui/type_complexity.rs index b057dc4e89f..be28ee2da0c 100644 --- a/src/tools/clippy/tests/ui/type_complexity.rs +++ b/src/tools/clippy/tests/ui/type_complexity.rs @@ -1,5 +1,3 @@ -//@compile-flags: -Zdeduplicate-diagnostics=yes - #![warn(clippy::all)] #![allow(unused, clippy::needless_pass_by_value, clippy::vec_box, clippy::useless_vec)] #![feature(associated_type_defaults)] diff --git a/src/tools/clippy/tests/ui/type_complexity.stderr b/src/tools/clippy/tests/ui/type_complexity.stderr index bfbab8647e8..9e27899e4f9 100644 --- a/src/tools/clippy/tests/ui/type_complexity.stderr +++ b/src/tools/clippy/tests/ui/type_complexity.stderr @@ -1,5 +1,5 @@ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:9:12 + --> tests/ui/type_complexity.rs:7:12 | LL | const CST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,85 +8,85 @@ LL | const CST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); = help: to override `-D warnings` add `#[allow(clippy::type_complexity)]` error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:12:12 + --> tests/ui/type_complexity.rs:10:12 | LL | static ST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:16:8 + --> tests/ui/type_complexity.rs:14:8 | LL | f: Vec<Vec<Box<(u32, u32, u32, u32)>>>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:20:11 + --> tests/ui/type_complexity.rs:18:11 | LL | struct Ts(Vec<Vec<Box<(u32, u32, u32, u32)>>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:24:11 + --> tests/ui/type_complexity.rs:22:11 | LL | Tuple(Vec<Vec<Box<(u32, u32, u32, u32)>>>), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:26:17 + --> tests/ui/type_complexity.rs:24:17 | LL | Struct { f: Vec<Vec<Box<(u32, u32, u32, u32)>>> }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:31:14 + --> tests/ui/type_complexity.rs:29:14 | LL | const A: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:33:30 + --> tests/ui/type_complexity.rs:31:30 | LL | fn impl_method(&self, p: Vec<Vec<Box<(u32, u32, u32, u32)>>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:38:14 + --> tests/ui/type_complexity.rs:36:14 | LL | const A: Vec<Vec<Box<(u32, u32, u32, u32)>>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:40:14 + --> tests/ui/type_complexity.rs:38:14 | LL | type B = Vec<Vec<Box<(u32, u32, u32, u32)>>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:42:25 + --> tests/ui/type_complexity.rs:40:25 | LL | fn method(&self, p: Vec<Vec<Box<(u32, u32, u32, u32)>>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:44:29 + --> tests/ui/type_complexity.rs:42:29 | LL | fn def_method(&self, p: Vec<Vec<Box<(u32, u32, u32, u32)>>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:57:15 + --> tests/ui/type_complexity.rs:55:15 | LL | fn test1() -> Vec<Vec<Box<(u32, u32, u32, u32)>>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:62:14 + --> tests/ui/type_complexity.rs:60:14 | LL | fn test2(_x: Vec<Vec<Box<(u32, u32, u32, u32)>>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:66:13 + --> tests/ui/type_complexity.rs:64:13 | LL | let _y: Vec<Vec<Box<(u32, u32, u32, u32)>>> = vec![]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/type_id_on_box_unfixable.rs b/src/tools/clippy/tests/ui/type_id_on_box_unfixable.rs index f6d09834adb..67e398e604b 100644 --- a/src/tools/clippy/tests/ui/type_id_on_box_unfixable.rs +++ b/src/tools/clippy/tests/ui/type_id_on_box_unfixable.rs @@ -19,7 +19,7 @@ where impl<T> NormalTrait for T {} fn main() { - // (currently we don't look deeper than one level into the supertrait hierachy, but we probably + // (currently we don't look deeper than one level into the supertrait hierarchy, but we probably // could) let b: Box<dyn AnySubSubTrait> = Box::new(1); let _ = b.type_id(); diff --git a/src/tools/clippy/triagebot.toml b/src/tools/clippy/triagebot.toml index 901977da25b..4d66b728b76 100644 --- a/src/tools/clippy/triagebot.toml +++ b/src/tools/clippy/triagebot.toml @@ -20,7 +20,6 @@ new_pr = true [assign] contributing_url = "https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md" users_on_vacation = [ - "y21", "matthiaskrgr", "giraffate", "Centri3", diff --git a/src/tools/clippy/util/gh-pages/script.js b/src/tools/clippy/util/gh-pages/script.js index f59245e556c..c63edd5bf70 100644 --- a/src/tools/clippy/util/gh-pages/script.js +++ b/src/tools/clippy/util/gh-pages/script.js @@ -415,7 +415,7 @@ let terms = searchStr.split(" "); let docsLowerCase = lint.docs.toLowerCase(); for (index = 0; index < terms.length; index++) { - // This is more likely and will therefor be checked first + // This is more likely and will therefore be checked first if (docsLowerCase.indexOf(terms[index]) !== -1) { continue; } diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 34e65c7d61f..42159b147d5 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -208,6 +208,8 @@ pub struct TestProps { pub llvm_cov_flags: Vec<String>, /// Extra flags to pass to LLVM's `filecheck` tool, in tests that use it. pub filecheck_flags: Vec<String>, + /// Don't automatically insert any `--check-cfg` args + pub no_auto_check_cfg: bool, } mod directives { @@ -249,6 +251,7 @@ mod directives { pub const COMPARE_OUTPUT_LINES_BY_SUBSET: &'static str = "compare-output-lines-by-subset"; pub const LLVM_COV_FLAGS: &'static str = "llvm-cov-flags"; pub const FILECHECK_FLAGS: &'static str = "filecheck-flags"; + pub const NO_AUTO_CHECK_CFG: &'static str = "no-auto-check-cfg"; // This isn't a real directive, just one that is probably mistyped often pub const INCORRECT_COMPILER_FLAGS: &'static str = "compiler-flags"; } @@ -304,6 +307,7 @@ impl TestProps { remap_src_base: false, llvm_cov_flags: vec![], filecheck_flags: vec![], + no_auto_check_cfg: false, } } @@ -567,6 +571,8 @@ impl TestProps { if let Some(flags) = config.parse_name_value_directive(ln, FILECHECK_FLAGS) { self.filecheck_flags.extend(split_flags(&flags)); } + + config.set_name_directive(ln, NO_AUTO_CHECK_CFG, &mut self.no_auto_check_cfg); }, ); @@ -860,6 +866,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "needs-unwind", "needs-wasmtime", "needs-xray", + "no-auto-check-cfg", "no-prefer-dynamic", "normalize-stderr-32bit", "normalize-stderr-64bit", diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index db154932d5b..7bc7e4b8680 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -120,16 +120,6 @@ pub(super) fn handle_needs( ignore_reason: "ignored on targets without Rust's LLDB", }, Need { - name: "needs-i686-dlltool", - condition: cache.i686_dlltool, - ignore_reason: "ignored when dlltool for i686 is not present", - }, - Need { - name: "needs-x86_64-dlltool", - condition: cache.x86_64_dlltool, - ignore_reason: "ignored when dlltool for x86_64 is not present", - }, - Need { name: "needs-dlltool", condition: cache.dlltool, ignore_reason: "ignored when dlltool for the current architecture is not present", @@ -218,27 +208,11 @@ pub(super) struct CachedNeedsConditions { profiler_support: bool, xray: bool, rust_lld: bool, - i686_dlltool: bool, - x86_64_dlltool: bool, dlltool: bool, } impl CachedNeedsConditions { pub(super) fn load(config: &Config) -> Self { - let path = std::env::var_os("PATH").expect("missing PATH environment variable"); - let path = std::env::split_paths(&path).collect::<Vec<_>>(); - - // On Windows, dlltool.exe is used for all architectures. - #[cfg(windows)] - let dlltool = path.iter().any(|dir| dir.join("dlltool.exe").is_file()); - - // For non-Windows, there are architecture specific dlltool binaries. - #[cfg(not(windows))] - let i686_dlltool = path.iter().any(|dir| dir.join("i686-w64-mingw32-dlltool").is_file()); - #[cfg(not(windows))] - let x86_64_dlltool = - path.iter().any(|dir| dir.join("x86_64-w64-mingw32-dlltool").is_file()); - let target = &&*config.target; let sanitizers = &config.target_cfg().sanitizers; Self { @@ -278,26 +252,30 @@ impl CachedNeedsConditions { .join(if config.host.contains("windows") { "rust-lld.exe" } else { "rust-lld" }) .exists(), - #[cfg(windows)] - i686_dlltool: dlltool, - #[cfg(windows)] - x86_64_dlltool: dlltool, - #[cfg(windows)] - dlltool, - - // For non-Windows, there are architecture specific dlltool binaries. - #[cfg(not(windows))] - i686_dlltool, - #[cfg(not(windows))] - x86_64_dlltool, - #[cfg(not(windows))] - dlltool: if config.matches_arch("x86") { - i686_dlltool - } else if config.matches_arch("x86_64") { - x86_64_dlltool - } else { - false - }, + dlltool: find_dlltool(&config), } } } + +fn find_dlltool(config: &Config) -> bool { + let path = std::env::var_os("PATH").expect("missing PATH environment variable"); + let path = std::env::split_paths(&path).collect::<Vec<_>>(); + + // dlltool is used ony by GNU based `*-*-windows-gnu` + if !(config.matches_os("windows") && config.matches_env("gnu") && config.matches_abi("")) { + return false; + } + + // On Windows, dlltool.exe is used for all architectures. + // For non-Windows, there are architecture specific dlltool binaries. + let dlltool_found = if cfg!(windows) { + path.iter().any(|dir| dir.join("dlltool.exe").is_file()) + } else if config.matches_arch("i686") { + path.iter().any(|dir| dir.join("i686-w64-mingw32-dlltool").is_file()) + } else if config.matches_arch("x86_64") { + path.iter().any(|dir| dir.join("x86_64-w64-mingw32-dlltool").is_file()) + } else { + false + }; + dlltool_found +} diff --git a/src/tools/compiletest/src/raise_fd_limit.rs b/src/tools/compiletest/src/raise_fd_limit.rs index a4235381beb..218bea68a21 100644 --- a/src/tools/compiletest/src/raise_fd_limit.rs +++ b/src/tools/compiletest/src/raise_fd_limit.rs @@ -4,7 +4,7 @@ /// on the number of cores available. /// /// This fixes issue #7772. -#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "visionos"))] +#[cfg(target_vendor = "apple")] #[allow(non_camel_case_types)] pub unsafe fn raise_fd_limit() { use std::cmp; @@ -50,5 +50,5 @@ pub unsafe fn raise_fd_limit() { } } -#[cfg(not(any(target_os = "macos", target_os = "ios")))] +#[cfg(not(target_vendor = "apple"))] pub unsafe fn raise_fd_limit() {} diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index b0f84b1162f..1d69ed59859 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1028,12 +1028,31 @@ impl<'test> TestCx<'test> { } fn set_revision_flags(&self, cmd: &mut Command) { + // Normalize revisions to be lowercase and replace `-`s with `_`s. + // Otherwise the `--cfg` flag is not valid. + let normalize_revision = |revision: &str| revision.to_lowercase().replace("-", "_"); + if let Some(revision) = self.revision { - // Normalize revisions to be lowercase and replace `-`s with `_`s. - // Otherwise the `--cfg` flag is not valid. - let normalized_revision = revision.to_lowercase().replace("-", "_"); + let normalized_revision = normalize_revision(revision); cmd.args(&["--cfg", &normalized_revision]); } + + if !self.props.no_auto_check_cfg { + let mut check_cfg = String::with_capacity(25); + + // Generate `cfg(FALSE, REV1, ..., REVN)` (for all possible revisions) + // + // For compatibility reason we consider the `FALSE` cfg to be expected + // since it is extensively used in the testsuite. + check_cfg.push_str("cfg(FALSE"); + for revision in &self.props.revisions { + check_cfg.push_str(","); + check_cfg.push_str(&normalize_revision(&revision)); + } + check_cfg.push_str(")"); + + cmd.args(&["--check-cfg", &check_cfg]); + } } fn typecheck_source(&self, src: String) -> ProcRes { @@ -2140,6 +2159,7 @@ impl<'test> TestCx<'test> { if !self.props.aux_bins.is_empty() { let aux_bin_dir = self.aux_bin_output_dir_name(); + remove_and_create_dir_all(&aux_dir); remove_and_create_dir_all(&aux_bin_dir); } @@ -3824,6 +3844,7 @@ impl<'test> TestCx<'test> { .arg(format!("-Ldependency={}", &support_lib_deps_deps.to_string_lossy())) .arg("--extern") .arg(format!("run_make_support={}", &support_lib_path.to_string_lossy())) + .arg("--edition=2021") .arg(&self.testpaths.file.join("rmake.rs")) .env("TARGET", &self.config.target) .env("PYTHON", &self.config.python) diff --git a/src/tools/expand-yaml-anchors/Cargo.toml b/src/tools/expand-yaml-anchors/Cargo.toml deleted file mode 100644 index 9a25b6c1f1c..00000000000 --- a/src/tools/expand-yaml-anchors/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "expand-yaml-anchors" -version = "0.1.0" -edition = "2021" - -[dependencies] -yaml-rust = "0.4.3" -yaml-merge-keys = "0.4.0" diff --git a/src/tools/expand-yaml-anchors/src/main.rs b/src/tools/expand-yaml-anchors/src/main.rs deleted file mode 100644 index 60651734b9e..00000000000 --- a/src/tools/expand-yaml-anchors/src/main.rs +++ /dev/null @@ -1,198 +0,0 @@ -use std::error::Error; -use std::path::{Path, PathBuf}; -use yaml_rust::{Yaml, YamlEmitter, YamlLoader}; - -/// List of files to expand. The first tuple element is the source -/// file, while the second tuple element is the destination file. -#[rustfmt::skip] -static TO_EXPAND: &[(&str, &str)] = &[ - ("src/ci/github-actions/ci.yml", ".github/workflows/ci.yml"), -]; - -/// Name of a special key that will be removed from all the maps in expanded configuration files. -/// This key can then be used to contain shared anchors. -static REMOVE_MAP_KEY: &str = "x--expand-yaml-anchors--remove"; - -/// Message that will be included at the top of all the expanded files. {source} will be replaced -/// with the source filename relative to the base path. -static HEADER_MESSAGE: &str = "\ -############################################################# -# WARNING: automatically generated file, DO NOT CHANGE! # -############################################################# - -# This file was automatically generated by the expand-yaml-anchors tool. The -# source file that generated this one is: -# -# {source} -# -# Once you make changes to that file you need to run: -# -# ./x.py run src/tools/expand-yaml-anchors/ -# -# The CI build will fail if the tool is not run after changes to this file. - -"; - -enum Mode { - Check, - Generate, -} - -struct App { - mode: Mode, - base: PathBuf, -} - -impl App { - fn from_args() -> Result<Self, Box<dyn Error>> { - // Parse CLI arguments - let args = std::env::args().skip(1).collect::<Vec<_>>(); - let (mode, base) = match args.iter().map(|s| s.as_str()).collect::<Vec<_>>().as_slice() { - ["generate", ref base] => (Mode::Generate, PathBuf::from(base)), - ["check", ref base] => (Mode::Check, PathBuf::from(base)), - _ => { - eprintln!("usage: expand-yaml-anchors <generate|check> <base-dir>"); - std::process::exit(1); - } - }; - - Ok(App { mode, base }) - } - - fn run(&self) -> Result<(), Box<dyn Error>> { - for (source, dest) in TO_EXPAND { - let source = self.base.join(source); - let dest_path = self.base.join(dest); - - self.expand(&source, &dest_path).with_context(|| match self.mode { - Mode::Generate => format!( - "failed to expand {} into {}", - self.path(&source), - self.path(&dest_path) - ), - Mode::Check => format!( - "{} is not up to date; please run \ - `x.py run src/tools/expand-yaml-anchors`.", - self.path(&dest_path) - ), - })?; - } - Ok(()) - } - - fn expand(&self, source: &Path, dest: &Path) -> Result<(), Box<dyn Error>> { - let content = std::fs::read_to_string(source) - .with_context(|| format!("failed to read {}", self.path(source)))?; - - let mut buf = - HEADER_MESSAGE.replace("{source}", &self.path(source).to_string().replace("\\", "/")); - - let documents = YamlLoader::load_from_str(&content) - .with_context(|| format!("failed to parse {}", self.path(source)))?; - for mut document in documents.into_iter() { - document = yaml_merge_keys::merge_keys(document) - .with_context(|| format!("failed to expand {}", self.path(source)))?; - document = filter_document(document); - - YamlEmitter::new(&mut buf).dump(&document).map_err(|err| WithContext { - context: "failed to serialize the expanded yaml".into(), - source: Box::new(err), - })?; - buf.push('\n'); - } - - match self.mode { - Mode::Check => { - let old = std::fs::read_to_string(dest) - .with_context(|| format!("failed to read {}", self.path(dest)))?; - if old != buf { - return Err(Box::new(StrError(format!( - "{} and {} are different", - self.path(source), - self.path(dest), - )))); - } - } - Mode::Generate => { - std::fs::write(dest, buf.as_bytes()) - .with_context(|| format!("failed to write to {}", self.path(dest)))?; - } - } - Ok(()) - } - - fn path<'a>(&self, path: &'a Path) -> impl std::fmt::Display + 'a { - path.strip_prefix(&self.base).unwrap_or(path).display() - } -} - -fn filter_document(document: Yaml) -> Yaml { - match document { - Yaml::Hash(map) => Yaml::Hash( - map.into_iter() - .filter(|(key, _)| { - if let Yaml::String(string) = &key { string != REMOVE_MAP_KEY } else { true } - }) - .map(|(key, value)| (filter_document(key), filter_document(value))) - .collect(), - ), - Yaml::Array(vec) => Yaml::Array(vec.into_iter().map(filter_document).collect()), - other => other, - } -} - -fn main() { - if let Err(err) = App::from_args().and_then(|app| app.run()) { - eprintln!("error: {}", err); - - let mut source = err.as_ref() as &dyn Error; - while let Some(err) = source.source() { - eprintln!("caused by: {}", err); - source = err; - } - - std::process::exit(1); - } -} - -#[derive(Debug)] -struct StrError(String); - -impl Error for StrError {} - -impl std::fmt::Display for StrError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - std::fmt::Display::fmt(&self.0, f) - } -} - -#[derive(Debug)] -struct WithContext { - context: String, - source: Box<dyn Error>, -} - -impl std::fmt::Display for WithContext { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.context) - } -} - -impl Error for WithContext { - fn source(&self) -> Option<&(dyn Error + 'static)> { - Some(self.source.as_ref()) - } -} - -pub(crate) trait ResultExt<T> { - fn with_context<F: FnOnce() -> String>(self, f: F) -> Result<T, Box<dyn Error>>; -} - -impl<T, E: Into<Box<dyn Error>>> ResultExt<T> for Result<T, E> { - fn with_context<F: FnOnce() -> String>(self, f: F) -> Result<T, Box<dyn Error>> { - match self { - Ok(ok) => Ok(ok), - Err(err) => Err(WithContext { source: err.into(), context: f() }.into()), - } - } -} diff --git a/src/tools/jsondocck/Cargo.toml b/src/tools/jsondocck/Cargo.toml index 6326a9b1e79..e1eb6d05665 100644 --- a/src/tools/jsondocck/Cargo.toml +++ b/src/tools/jsondocck/Cargo.toml @@ -10,4 +10,3 @@ regex = "1.4" shlex = "1.0" serde_json = "1.0" fs-err = "2.5.0" -once_cell = "1.0" diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs index e3d05ec8315..688b403bf0e 100644 --- a/src/tools/jsondocck/src/main.rs +++ b/src/tools/jsondocck/src/main.rs @@ -1,8 +1,8 @@ use jsonpath_lib::select; -use once_cell::sync::Lazy; use regex::{Regex, RegexBuilder}; use serde_json::Value; use std::borrow::Cow; +use std::sync::OnceLock; use std::{env, fmt, fs}; mod cache; @@ -95,7 +95,8 @@ impl fmt::Display for CommandKind { } } -static LINE_PATTERN: Lazy<Regex> = Lazy::new(|| { +static LINE_PATTERN: OnceLock<Regex> = OnceLock::new(); +fn line_pattern() -> Regex { RegexBuilder::new( r#" \s(?P<invalid>!?)@(?P<negated>!?) @@ -107,7 +108,7 @@ static LINE_PATTERN: Lazy<Regex> = Lazy::new(|| { .unicode(true) .build() .unwrap() -}); +} fn print_err(msg: &str, lineno: usize) { eprintln!("Invalid command: {} on line {}", msg, lineno) @@ -123,7 +124,7 @@ fn get_commands(template: &str) -> Result<Vec<Command>, ()> { for (lineno, line) in file.split('\n').enumerate() { let lineno = lineno + 1; - let cap = match LINE_PATTERN.captures(line) { + let cap = match LINE_PATTERN.get_or_init(line_pattern).captures(line) { Some(c) => c, None => continue, }; diff --git a/src/tools/linkchecker/Cargo.toml b/src/tools/linkchecker/Cargo.toml index 318a69ab835..05049aabc7d 100644 --- a/src/tools/linkchecker/Cargo.toml +++ b/src/tools/linkchecker/Cargo.toml @@ -9,5 +9,4 @@ path = "main.rs" [dependencies] regex = "1" -once_cell = "1" html5ever = "0.26.0" diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index f49c6e79f13..32f935de730 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -18,8 +18,6 @@ use html5ever::tendril::ByteTendril; use html5ever::tokenizer::{ BufferQueue, TagToken, Token, TokenSink, TokenSinkResult, Tokenizer, TokenizerOpts, }; -use once_cell::sync::Lazy; -use regex::Regex; use std::cell::RefCell; use std::collections::{HashMap, HashSet}; use std::env; @@ -69,8 +67,12 @@ const INTRA_DOC_LINK_EXCEPTIONS: &[(&str, &[&str])] = &[ ]; -static BROKEN_INTRA_DOC_LINK: Lazy<Regex> = - Lazy::new(|| Regex::new(r#"\[<code>(.*)</code>\]"#).unwrap()); +macro_rules! static_regex { + ($re:literal) => {{ + static RE: ::std::sync::OnceLock<::regex::Regex> = ::std::sync::OnceLock::new(); + RE.get_or_init(|| ::regex::Regex::new($re).unwrap()) + }}; +} macro_rules! t { ($e:expr) => { @@ -373,7 +375,7 @@ impl Checker { // Search for intra-doc links that rustdoc didn't warn about // NOTE: only looks at one line at a time; in practice this should find most links for (i, line) in source.lines().enumerate() { - for broken_link in BROKEN_INTRA_DOC_LINK.captures_iter(line) { + for broken_link in static_regex!(r#"\[<code>(.*)</code>\]"#).captures_iter(line) { if is_intra_doc_exception(file, &broken_link[1]) { report.intra_doc_exceptions += 1; } else { diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml index b00dae784d2..ac8b4b37e92 100644 --- a/src/tools/miri/Cargo.toml +++ b/src/tools/miri/Cargo.toml @@ -46,7 +46,6 @@ colored = "2" ui_test = "0.21.1" rustc_version = "0.4" regex = "1.5.5" -lazy_static = "1.4.0" tempfile = "3" [package.metadata.rust-analyzer] diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index 2242768a568..97c5e9a0eac 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -387,7 +387,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>( let main_ptr = ecx.fn_ptr(FnVal::Instance(entry_instance)); // Always using DEFAULT is okay since we don't support signals in Miri anyway. - // (This means we are effectively ignoring `#[unix_sigpipe]`.) + // (This means we are effectively ignoring `-Zon-broken-pipe`.) let sigpipe = rustc_session::config::sigpipe::DEFAULT; ecx.call_function( diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 44727e01ea2..3b1d7687d02 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -89,10 +89,13 @@ mod shims; // Establish a "crate-wide prelude": we often import `crate::*`. // Make all those symbols available in the same place as our own. +#[doc(no_inline)] pub use rustc_const_eval::interpret::*; // Resolve ambiguity. +#[doc(no_inline)] pub use rustc_const_eval::interpret::{self, AllocMap, PlaceTy, Provenance as _}; +pub use crate::shims::EmulateItemResult; pub use crate::shims::env::{EnvVars, EvalContextExt as _}; pub use crate::shims::foreign_items::{DynSym, EvalContextExt as _}; pub use crate::shims::intrinsics::EvalContextExt as _; diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 8b286871774..51b96bff5fe 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -380,7 +380,7 @@ impl<'mir, 'tcx: 'mir> PrimitiveLayouts<'tcx> { let mut_raw_ptr = Ty::new_mut_ptr(tcx, tcx.types.unit); let const_raw_ptr = Ty::new_imm_ptr(tcx, tcx.types.unit); Ok(Self { - unit: layout_cx.layout_of(Ty::new_unit(tcx))?, + unit: layout_cx.layout_of(tcx.types.unit)?, i8: layout_cx.layout_of(tcx.types.i8)?, i16: layout_cx.layout_of(tcx.types.i16)?, i32: layout_cx.layout_of(tcx.types.i32)?, @@ -986,7 +986,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { dest: &MPlaceTy<'tcx, Provenance>, ret: Option<mir::BasicBlock>, unwind: mir::UnwindAction, - ) -> InterpResult<'tcx> { + ) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> { ecx.call_intrinsic(instance, args, dest, ret, unwind) } diff --git a/src/tools/miri/src/shims/alloc.rs b/src/tools/miri/src/shims/alloc.rs index b5ae06c2a49..79531598c00 100644 --- a/src/tools/miri/src/shims/alloc.rs +++ b/src/tools/miri/src/shims/alloc.rs @@ -4,7 +4,6 @@ use rustc_ast::expand::allocator::AllocatorKind; use rustc_target::abi::{Align, Size}; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; /// Check some basic requirements for this allocation request: /// non-zero size, power-of-two alignment. @@ -55,12 +54,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn emulate_allocator( &mut self, default: impl FnOnce(&mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); let Some(allocator_kind) = this.tcx.allocator_kind(()) else { // in real code, this symbol does not exist without an allocator - return Ok(EmulateForeignItemResult::NotSupported); + return Ok(EmulateItemResult::NotSupported); }; match allocator_kind { @@ -70,11 +69,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // and not execute any Miri shim. Somewhat unintuitively doing so is done // by returning `NotSupported`, which triggers the `lookup_exported_symbol` // fallback case in `emulate_foreign_item`. - return Ok(EmulateForeignItemResult::NotSupported); + return Ok(EmulateItemResult::NotSupported); } AllocatorKind::Default => { default(this)?; - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } } diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 636361148a4..8a38c6c11a8 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -28,16 +28,6 @@ impl DynSym { } } -/// Returned by `emulate_foreign_item_inner`. -pub enum EmulateForeignItemResult { - /// The caller is expected to jump to the return block. - NeedsJumping, - /// Jumping has already been taken care of. - AlreadyJumped, - /// The item is not supported. - NotSupported, -} - impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// Emulates calling a foreign item, failing if the item is not supported. @@ -58,84 +48,47 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_mut(); let tcx = this.tcx.tcx; - // First: functions that diverge. - let ret = match ret { - None => - match link_name.as_str() { - "miri_start_unwind" => { - // `check_shim` happens inside `handle_miri_start_unwind`. - this.handle_miri_start_unwind(abi, link_name, args, unwind)?; - return Ok(None); - } - // This matches calls to the foreign item `panic_impl`. - // The implementation is provided by the function with the `#[panic_handler]` attribute. - "panic_impl" => { - // We don't use `check_shim` here because we are just forwarding to the lang - // item. Argument count checking will be performed when the returned `Body` is - // called. - this.check_abi_and_shim_symbol_clash(abi, Abi::Rust, link_name)?; - let panic_impl_id = tcx.lang_items().panic_impl().unwrap(); - let panic_impl_instance = ty::Instance::mono(tcx, panic_impl_id); - return Ok(Some(( - this.load_mir(panic_impl_instance.def, None)?, - panic_impl_instance, - ))); - } - "__rust_alloc_error_handler" => { - // Forward to the right symbol that implements this function. - let Some(handler_kind) = this.tcx.alloc_error_handler_kind(()) else { - // in real code, this symbol does not exist without an allocator - throw_unsup_format!( - "`__rust_alloc_error_handler` cannot be called when no alloc error handler is set" - ); - }; - let name = alloc_error_handler_name(handler_kind); - let handler = this - .lookup_exported_symbol(Symbol::intern(name))? - .expect("missing alloc error handler symbol"); - return Ok(Some(handler)); - } - #[rustfmt::skip] - | "exit" - | "ExitProcess" - => { - let exp_abi = if link_name.as_str() == "exit" { - Abi::C { unwind: false } - } else { - Abi::System { unwind: false } - }; - let [code] = this.check_shim(abi, exp_abi, link_name, args)?; - // it's really u32 for ExitProcess, but we have to put it into the `Exit` variant anyway - let code = this.read_scalar(code)?.to_i32()?; - throw_machine_stop!(TerminationInfo::Exit { code: code.into(), leak_check: false }); - } - "abort" => { - let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - throw_machine_stop!(TerminationInfo::Abort( - "the program aborted execution".to_owned() - )) - } - _ => { - if let Some(body) = this.lookup_exported_symbol(link_name)? { - return Ok(Some(body)); - } - this.handle_unsupported(format!( - "can't call (diverging) foreign function: {link_name}" - ))?; - return Ok(None); - } - }, - Some(p) => p, - }; + // Some shims forward to other MIR bodies. + match link_name.as_str() { + // This matches calls to the foreign item `panic_impl`. + // The implementation is provided by the function with the `#[panic_handler]` attribute. + "panic_impl" => { + // We don't use `check_shim` here because we are just forwarding to the lang + // item. Argument count checking will be performed when the returned `Body` is + // called. + this.check_abi_and_shim_symbol_clash(abi, Abi::Rust, link_name)?; + let panic_impl_id = tcx.lang_items().panic_impl().unwrap(); + let panic_impl_instance = ty::Instance::mono(tcx, panic_impl_id); + return Ok(Some(( + this.load_mir(panic_impl_instance.def, None)?, + panic_impl_instance, + ))); + } + "__rust_alloc_error_handler" => { + // Forward to the right symbol that implements this function. + let Some(handler_kind) = this.tcx.alloc_error_handler_kind(()) else { + // in real code, this symbol does not exist without an allocator + throw_unsup_format!( + "`__rust_alloc_error_handler` cannot be called when no alloc error handler is set" + ); + }; + let name = alloc_error_handler_name(handler_kind); + let handler = this + .lookup_exported_symbol(Symbol::intern(name))? + .expect("missing alloc error handler symbol"); + return Ok(Some(handler)); + } + _ => {} + } - // Second: functions that return immediately. - match this.emulate_foreign_item_inner(link_name, abi, args, dest)? { - EmulateForeignItemResult::NeedsJumping => { + // The rest either implements the logic, or falls back to `lookup_exported_symbol`. + match this.emulate_foreign_item_inner(link_name, abi, args, dest, unwind)? { + EmulateItemResult::NeedsJumping => { trace!("{:?}", this.dump_place(&dest.clone().into())); - this.go_to_block(ret); + this.return_to_block(ret)?; } - EmulateForeignItemResult::AlreadyJumped => (), - EmulateForeignItemResult::NotSupported => { + EmulateItemResult::AlreadyJumped => (), + EmulateItemResult::NotSupported => { if let Some(body) = this.lookup_exported_symbol(link_name)? { return Ok(Some(body)); } @@ -243,7 +196,8 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + unwind: mir::UnwindAction, + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); // First deal with any external C functions in linked .so file. @@ -254,7 +208,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // by the specified `.so` file; we should continue and check if it corresponds to // a provided shim. if this.call_external_c_fct(link_name, dest, args)? { - return Ok(EmulateForeignItemResult::NeedsJumping); + return Ok(EmulateItemResult::NeedsJumping); } } @@ -298,6 +252,11 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // shim, add it to the corresponding submodule. match link_name.as_str() { // Miri-specific extern functions + "miri_start_unwind" => { + // `check_shim` happens inside `handle_miri_start_unwind`. + this.handle_miri_start_unwind(abi, link_name, args, unwind)?; + return Ok(EmulateItemResult::AlreadyJumped); + } "miri_run_provenance_gc" => { let [] = this.check_shim(abi, Abi::Rust, link_name, args)?; this.run_provenance_gc(); @@ -362,29 +321,24 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Return value: 0 on success, otherwise the size it would have needed. this.write_int(if success { 0 } else { needed_size }, dest)?; } - // Obtains the size of a Miri backtrace. See the README for details. "miri_backtrace_size" => { this.handle_miri_backtrace_size(abi, link_name, args, dest)?; } - // Obtains a Miri backtrace. See the README for details. "miri_get_backtrace" => { // `check_shim` happens inside `handle_miri_get_backtrace`. this.handle_miri_get_backtrace(abi, link_name, args, dest)?; } - // Resolves a Miri backtrace frame. See the README for details. "miri_resolve_frame" => { // `check_shim` happens inside `handle_miri_resolve_frame`. this.handle_miri_resolve_frame(abi, link_name, args, dest)?; } - // Writes the function and file names of a Miri backtrace frame into a user provided buffer. See the README for details. "miri_resolve_frame_names" => { this.handle_miri_resolve_frame_names(abi, link_name, args)?; } - // Writes some bytes to the interpreter's stdout/stderr. See the // README for details. "miri_write_to_stdout" | "miri_write_to_stderr" => { @@ -398,7 +352,6 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { _ => unreachable!(), }; } - // Promises that a pointer has a given symbolic alignment. "miri_promise_symbolic_alignment" => { use rustc_target::abi::AlignFromBytesError; @@ -442,6 +395,25 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } + // Aborting the process. + "exit" | "ExitProcess" => { + let exp_abi = if link_name.as_str() == "exit" { + Abi::C { unwind: false } + } else { + Abi::System { unwind: false } + }; + let [code] = this.check_shim(abi, exp_abi, link_name, args)?; + // it's really u32 for ExitProcess, but we have to put it into the `Exit` variant anyway + let code = this.read_scalar(code)?.to_i32()?; + throw_machine_stop!(TerminationInfo::Exit { code: code.into(), leak_check: false }); + } + "abort" => { + let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + throw_machine_stop!(TerminationInfo::Abort( + "the program aborted execution".to_owned() + )) + } + // Standard C allocation "malloc" => { let [size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -504,7 +476,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "__rust_alloc" => return this.emulate_allocator(default), "miri_alloc" => { default(this)?; - return Ok(EmulateForeignItemResult::NeedsJumping); + return Ok(EmulateItemResult::NeedsJumping); } _ => unreachable!(), } @@ -564,7 +536,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } "miri_dealloc" => { default(this)?; - return Ok(EmulateForeignItemResult::NeedsJumping); + return Ok(EmulateItemResult::NeedsJumping); } _ => unreachable!(), } @@ -966,11 +938,11 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_inner( this, link_name, abi, args, dest, ), - _ => Ok(EmulateForeignItemResult::NotSupported), + _ => Ok(EmulateItemResult::NotSupported), }, }; // We only fall through to here if we did *not* hit the `_` arm above, // i.e., if we actually emulated the function with one of the shims. - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/intrinsics/atomic.rs b/src/tools/miri/src/shims/intrinsics/atomic.rs index 865886a7fc1..40f6b8a64ef 100644 --- a/src/tools/miri/src/shims/intrinsics/atomic.rs +++ b/src/tools/miri/src/shims/intrinsics/atomic.rs @@ -14,12 +14,13 @@ pub enum AtomicOp { impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// Calls the atomic intrinsic `intrinsic`; the `atomic_` prefix has already been removed. + /// Returns `Ok(true)` if the intrinsic was handled. fn emulate_atomic_intrinsic( &mut self, intrinsic_name: &str, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); let intrinsic_structure: Vec<_> = intrinsic_name.split('_').collect(); @@ -113,9 +114,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.atomic_rmw_op(args, dest, AtomicOp::Max, rw_ord(ord)?)?; } - _ => throw_unsup_format!("unimplemented intrinsic: `atomic_{intrinsic_name}`"), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(()) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs index d16d5d99e9c..974943432aa 100644 --- a/src/tools/miri/src/shims/intrinsics/mod.rs +++ b/src/tools/miri/src/shims/intrinsics/mod.rs @@ -10,6 +10,7 @@ use rustc_middle::{ mir, ty::{self, FloatTy}, }; +use rustc_span::{sym, Symbol}; use rustc_target::abi::Size; use crate::*; @@ -26,54 +27,60 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { dest: &MPlaceTy<'tcx, Provenance>, ret: Option<mir::BasicBlock>, _unwind: mir::UnwindAction, - ) -> InterpResult<'tcx> { + ) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> { let this = self.eval_context_mut(); // See if the core engine can handle this intrinsic. if this.emulate_intrinsic(instance, args, dest, ret)? { - return Ok(()); + return Ok(None); } let intrinsic_name = this.tcx.item_name(instance.def_id()); let intrinsic_name = intrinsic_name.as_str(); - // Handle intrinsics without return place. - match intrinsic_name { - "abort" => { - throw_machine_stop!(TerminationInfo::Abort( - "the program aborted execution".to_owned() - )) + match this.emulate_intrinsic_by_name(intrinsic_name, instance.args, args, dest, ret)? { + EmulateItemResult::NotSupported => { + // We haven't handled the intrinsic, let's see if we can use a fallback body. + if this.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden { + throw_unsup_format!("unimplemented intrinsic: `{intrinsic_name}`") + } + let intrinsic_fallback_checks_ub = Symbol::intern("intrinsic_fallback_checks_ub"); + if this + .tcx + .get_attrs_by_path( + instance.def_id(), + &[sym::miri, intrinsic_fallback_checks_ub], + ) + .next() + .is_none() + { + throw_unsup_format!( + "miri can only use intrinsic fallback bodies that check UB. After verifying that `{intrinsic_name}` does so, add the `#[miri::intrinsic_fallback_checks_ub]` attribute to it; also ping @rust-lang/miri when you do that" + ); + } + Ok(Some(ty::Instance { + def: ty::InstanceDef::Item(instance.def_id()), + args: instance.args, + })) } - _ => {} - } - - // All remaining supported intrinsics have a return place. - let ret = match ret { - None => throw_unsup_format!("unimplemented (diverging) intrinsic: `{intrinsic_name}`"), - Some(p) => p, - }; - - // Some intrinsics are special and need the "ret". - match intrinsic_name { - "catch_unwind" => return this.handle_catch_unwind(args, dest, ret), - _ => {} + EmulateItemResult::NeedsJumping => { + trace!("{:?}", this.dump_place(&dest.clone().into())); + this.return_to_block(ret)?; + Ok(None) + } + EmulateItemResult::AlreadyJumped => Ok(None), } - - // The rest jumps to `ret` immediately. - this.emulate_intrinsic_by_name(intrinsic_name, instance.args, args, dest)?; - - trace!("{:?}", this.dump_place(&dest.clone().into())); - this.go_to_block(ret); - Ok(()) } /// Emulates a Miri-supported intrinsic (not supported by the core engine). + /// Returns `Ok(true)` if the intrinsic was handled. fn emulate_intrinsic_by_name( &mut self, intrinsic_name: &str, generic_args: ty::GenericArgsRef<'tcx>, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx> { + ret: Option<mir::BasicBlock>, + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); if let Some(name) = intrinsic_name.strip_prefix("atomic_") { @@ -84,22 +91,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } match intrinsic_name { - // Miri overwriting CTFE intrinsics. - "ptr_guaranteed_cmp" => { - let [left, right] = check_arg_count(args)?; - let left = this.read_immediate(left)?; - let right = this.read_immediate(right)?; - let val = this.wrapping_binary_op(mir::BinOp::Eq, &left, &right)?; - // We're type punning a bool as an u8 here. - this.write_scalar(val.to_scalar(), dest)?; - } - "const_allocate" => { - // For now, for compatibility with the run-time implementation of this, we just return null. - // See <https://github.com/rust-lang/rust/issues/93935>. - this.write_null(dest)?; + "abort" => { + throw_machine_stop!(TerminationInfo::Abort( + "the program aborted execution".to_owned() + )); } - "const_deallocate" => { - // complete NOP + "catch_unwind" => { + this.handle_catch_unwind(args, dest, ret)?; + // THis pushed a stack frame, don't jump to `ret`. + return Ok(EmulateItemResult::AlreadyJumped); } // Raw memory accesses @@ -425,9 +425,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { throw_machine_stop!(TerminationInfo::Abort(format!("trace/breakpoint trap"))) } - name => throw_unsup_format!("unimplemented intrinsic: `{name}`"), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(()) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs index 9a0671430d4..c7de587443a 100644 --- a/src/tools/miri/src/shims/intrinsics/simd.rs +++ b/src/tools/miri/src/shims/intrinsics/simd.rs @@ -16,13 +16,14 @@ pub(crate) enum MinMax { impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// Calls the simd intrinsic `intrinsic`; the `simd_` prefix has already been removed. + /// Returns `Ok(true)` if the intrinsic was handled. fn emulate_simd_intrinsic( &mut self, intrinsic_name: &str, generic_args: ty::GenericArgsRef<'tcx>, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); match intrinsic_name { #[rustfmt::skip] @@ -743,9 +744,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } - name => throw_unsup_format!("unimplemented intrinsic: `simd_{name}`"), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(()) + Ok(EmulateItemResult::NeedsJumping) } fn fminmax_op( diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs index 85c9a202f7d..975efe29b4b 100644 --- a/src/tools/miri/src/shims/mod.rs +++ b/src/tools/miri/src/shims/mod.rs @@ -16,3 +16,13 @@ pub mod os_str; pub mod panic; pub mod time; pub mod tls; + +/// What needs to be done after emulating an item (a shim or an intrinsic) is done. +pub enum EmulateItemResult { + /// The caller is expected to jump to the return block. + NeedsJumping, + /// Jumping has already been taken care of. + AlreadyJumped, + /// The item is not supported. + NotSupported, +} diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs index bb31ef733cf..4444d297469 100644 --- a/src/tools/miri/src/shims/panic.rs +++ b/src/tools/miri/src/shims/panic.rs @@ -30,7 +30,7 @@ pub struct CatchUnwindData<'tcx> { /// The return place from the original call to `try`. dest: MPlaceTy<'tcx, Provenance>, /// The return block from the original call to `try`. - ret: mir::BasicBlock, + ret: Option<mir::BasicBlock>, } impl VisitProvenance for CatchUnwindData<'_> { @@ -73,7 +73,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { &mut self, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ret: mir::BasicBlock, + ret: Option<mir::BasicBlock>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); @@ -103,7 +103,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { &[data.into()], None, // Directly return to caller. - StackPopCleanup::Goto { ret: Some(ret), unwind: mir::UnwindAction::Continue }, + StackPopCleanup::Goto { ret, unwind: mir::UnwindAction::Continue }, )?; // We ourselves will return `0`, eventually (will be overwritten if we catch a panic). @@ -155,7 +155,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { None, // Directly return to caller of `try`. StackPopCleanup::Goto { - ret: Some(catch_unwind.ret), + ret: catch_unwind.ret, unwind: mir::UnwindAction::Continue, }, )?; diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index bd299aaa125..7f6a3ba0887 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -9,7 +9,6 @@ use rustc_target::spec::abi::Abi; use crate::shims::alloc::EvalContextExt as _; use crate::shims::unix::*; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; use shims::unix::freebsd::foreign_items as freebsd; use shims::unix::linux::foreign_items as linux; @@ -43,7 +42,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. @@ -750,11 +749,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "freebsd" => freebsd::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), "linux" => linux::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), "macos" => macos::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), - _ => Ok(EmulateForeignItemResult::NotSupported), + _ => Ok(EmulateItemResult::NotSupported), }; } }; - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs index ffb583123d4..1e0e7d16320 100644 --- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs @@ -3,7 +3,6 @@ use rustc_target::spec::abi::Abi; use crate::shims::unix::*; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; pub fn is_dyn_sym(_name: &str) -> bool { false @@ -17,7 +16,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); match link_name.as_str() { // Threading @@ -97,8 +96,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 497e8bee70e..dd4ec8cfaa7 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -5,7 +5,6 @@ use crate::machine::SIGRTMAX; use crate::machine::SIGRTMIN; use crate::shims::unix::*; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; use shims::unix::linux::epoll::EvalContextExt as _; use shims::unix::linux::eventfd::EvalContextExt as _; use shims::unix::linux::mem::EvalContextExt as _; @@ -23,7 +22,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. @@ -156,7 +155,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } id => { this.handle_unsupported(format!("can't execute syscall with ID {id}"))?; - return Ok(EmulateForeignItemResult::AlreadyJumped); + return Ok(EmulateItemResult::AlreadyJumped); } } } @@ -204,10 +203,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_null(dest)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), }; - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index 66a8dce753f..912623b7225 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -3,7 +3,6 @@ use rustc_target::spec::abi::Abi; use crate::shims::unix::*; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; pub fn is_dyn_sym(_name: &str) -> bool { false @@ -17,7 +16,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. @@ -175,9 +174,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_scalar(res, dest)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), }; - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index e8ae80261c6..08aee04254b 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -12,7 +12,6 @@ use crate::shims::alloc::EvalContextExt as _; use crate::shims::os_str::bytes_to_os_str; use crate::shims::windows::*; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; use shims::windows::handle::{Handle, PseudoHandle}; fn is_dyn_sym(name: &str) -> bool { @@ -86,7 +85,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. @@ -721,9 +720,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_null(dest)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/aesni.rs b/src/tools/miri/src/shims/x86/aesni.rs index 6c090d877ea..8dc3748a12d 100644 --- a/src/tools/miri/src/shims/x86/aesni.rs +++ b/src/tools/miri/src/shims/x86/aesni.rs @@ -4,7 +4,6 @@ use rustc_span::Symbol; use rustc_target::spec::abi::Abi; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -16,7 +15,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "aes")?; // Prefix should have already been checked. @@ -126,9 +125,9 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: } // TODO: Implement the `llvm.x86.aesni.aeskeygenassist` when possible // with an external crate. - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/avx.rs b/src/tools/miri/src/shims/x86/avx.rs index 41c20d768f7..86ef180a448 100644 --- a/src/tools/miri/src/shims/x86/avx.rs +++ b/src/tools/miri/src/shims/x86/avx.rs @@ -11,7 +11,6 @@ use super::{ FloatBinOp, FloatUnaryOp, }; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -23,7 +22,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "avx")?; // Prefix should have already been checked. @@ -343,8 +342,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this.write_scalar(Scalar::from_i32(res.into()), dest)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/avx2.rs b/src/tools/miri/src/shims/x86/avx2.rs index bbf53f9f1e5..6e3468c0189 100644 --- a/src/tools/miri/src/shims/x86/avx2.rs +++ b/src/tools/miri/src/shims/x86/avx2.rs @@ -9,7 +9,6 @@ use super::{ packuswb, pmulhrsw, psign, shift_simd_by_scalar, shift_simd_by_simd, ShiftOp, }; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -21,7 +20,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "avx2")?; // Prefix should have already been checked. @@ -437,8 +436,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: shift_simd_by_simd(this, left, right, which, dest)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs index cf4d6a04bec..2ab2ae85905 100644 --- a/src/tools/miri/src/shims/x86/mod.rs +++ b/src/tools/miri/src/shims/x86/mod.rs @@ -10,7 +10,6 @@ use rustc_target::spec::abi::Abi; use crate::*; use helpers::bool_to_simd_element; -use shims::foreign_items::EmulateForeignItemResult; mod aesni; mod avx; @@ -31,7 +30,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); // Prefix should have already been checked. let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.").unwrap(); @@ -43,7 +42,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: // https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/addcarry-u32-addcarry-u64.html "addcarry.32" | "addcarry.64" => { if unprefixed_name == "addcarry.64" && this.tcx.sess.target.arch != "x86_64" { - return Ok(EmulateForeignItemResult::NotSupported); + return Ok(EmulateItemResult::NotSupported); } let [c_in, a, b] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?; @@ -69,7 +68,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: // https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/subborrow-u32-subborrow-u64.html "subborrow.32" | "subborrow.64" => { if unprefixed_name == "subborrow.64" && this.tcx.sess.target.arch != "x86_64" { - return Ok(EmulateForeignItemResult::NotSupported); + return Ok(EmulateItemResult::NotSupported); } let [b_in, a, b] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?; @@ -143,9 +142,9 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: ); } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/sse.rs b/src/tools/miri/src/shims/x86/sse.rs index 17608837319..ea967a8cf72 100644 --- a/src/tools/miri/src/shims/x86/sse.rs +++ b/src/tools/miri/src/shims/x86/sse.rs @@ -8,7 +8,6 @@ use super::{ FloatUnaryOp, }; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -20,7 +19,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "sse")?; // Prefix should have already been checked. @@ -211,8 +210,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this.copy_op(&this.project_index(&left, i)?, &this.project_index(&dest, i)?)?; } } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/sse2.rs b/src/tools/miri/src/shims/x86/sse2.rs index c9ed751d36c..31fa66a496f 100644 --- a/src/tools/miri/src/shims/x86/sse2.rs +++ b/src/tools/miri/src/shims/x86/sse2.rs @@ -7,7 +7,6 @@ use super::{ packuswb, shift_simd_by_scalar, FloatBinOp, ShiftOp, }; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -19,7 +18,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "sse2")?; // Prefix should have already been checked. @@ -387,8 +386,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this.copy_op(&this.project_index(&left, i)?, &this.project_index(&dest, i)?)?; } } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/sse3.rs b/src/tools/miri/src/shims/x86/sse3.rs index 5ac30dca79a..8de339eb9e5 100644 --- a/src/tools/miri/src/shims/x86/sse3.rs +++ b/src/tools/miri/src/shims/x86/sse3.rs @@ -4,7 +4,6 @@ use rustc_target::spec::abi::Abi; use super::horizontal_bin_op; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -16,7 +15,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "sse3")?; // Prefix should have already been checked. @@ -50,8 +49,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this.mem_copy(src_ptr, dest.ptr(), dest.layout.size, /*nonoverlapping*/ true)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/sse41.rs b/src/tools/miri/src/shims/x86/sse41.rs index 19bc27421d3..011a7a16c68 100644 --- a/src/tools/miri/src/shims/x86/sse41.rs +++ b/src/tools/miri/src/shims/x86/sse41.rs @@ -3,7 +3,6 @@ use rustc_target::spec::abi::Abi; use super::{conditional_dot_product, mpsadbw, packusdw, round_all, round_first, test_bits_masked}; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -15,7 +14,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "sse4.1")?; // Prefix should have already been checked. @@ -175,8 +174,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this.write_scalar(Scalar::from_i32(res.into()), dest)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/ssse3.rs b/src/tools/miri/src/shims/x86/ssse3.rs index 4f8e52dbb7d..d30de430088 100644 --- a/src/tools/miri/src/shims/x86/ssse3.rs +++ b/src/tools/miri/src/shims/x86/ssse3.rs @@ -4,7 +4,6 @@ use rustc_target::spec::abi::Abi; use super::{horizontal_bin_op, int_abs, pmulhrsw, psign}; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -16,7 +15,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "ssse3")?; // Prefix should have already been checked. @@ -136,8 +135,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: psign(this, left, right, dest)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/tests/fail/intrinsic_fallback_checks_ub.rs b/src/tools/miri/tests/fail/intrinsic_fallback_checks_ub.rs new file mode 100644 index 00000000000..93c9d3d7814 --- /dev/null +++ b/src/tools/miri/tests/fail/intrinsic_fallback_checks_ub.rs @@ -0,0 +1,14 @@ +#![feature(rustc_attrs, effects)] + +#[rustc_intrinsic] +#[rustc_nounwind] +#[rustc_do_not_const_check] +#[inline] +pub const fn ptr_guaranteed_cmp<T>(ptr: *const T, other: *const T) -> u8 { + (ptr == other) as u8 +} + +fn main() { + ptr_guaranteed_cmp::<()>(std::ptr::null(), std::ptr::null()); + //~^ ERROR: can only use intrinsic fallback bodies that check UB. +} diff --git a/src/tools/miri/tests/fail/intrinsic_fallback_checks_ub.stderr b/src/tools/miri/tests/fail/intrinsic_fallback_checks_ub.stderr new file mode 100644 index 00000000000..b37e05c62f9 --- /dev/null +++ b/src/tools/miri/tests/fail/intrinsic_fallback_checks_ub.stderr @@ -0,0 +1,14 @@ +error: unsupported operation: miri can only use intrinsic fallback bodies that check UB. After verifying that `ptr_guaranteed_cmp` does so, add the `#[miri::intrinsic_fallback_checks_ub]` attribute to it; also ping @rust-lang/miri when you do that + --> $DIR/intrinsic_fallback_checks_ub.rs:LL:CC + | +LL | ptr_guaranteed_cmp::<()>(std::ptr::null(), std::ptr::null()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ miri can only use intrinsic fallback bodies that check UB. After verifying that `ptr_guaranteed_cmp` does so, add the `#[miri::intrinsic_fallback_checks_ub]` attribute to it; also ping @rust-lang/miri when you do that + | + = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support + = note: BACKTRACE: + = note: inside `main` at $DIR/intrinsic_fallback_checks_ub.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/ui.rs b/src/tools/miri/tests/ui.rs index ace0da01253..efeefbe29fb 100644 --- a/src/tools/miri/tests/ui.rs +++ b/src/tools/miri/tests/ui.rs @@ -1,6 +1,7 @@ use std::ffi::OsString; use std::num::NonZeroUsize; use std::path::{Path, PathBuf}; +use std::sync::OnceLock; use std::{env, process::Command}; use colored::*; @@ -67,8 +68,8 @@ fn miri_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) -> let mut config = Config { target: Some(target.to_owned()), - stderr_filters: STDERR.clone(), - stdout_filters: STDOUT.clone(), + stderr_filters: stderr_filters().into(), + stdout_filters: stdout_filters().into(), mode, program, out_dir: PathBuf::from(std::env::var_os("CARGO_TARGET_DIR").unwrap()).join("ui"), @@ -174,15 +175,18 @@ fn run_tests( } macro_rules! regexes { - ($name:ident: $($regex:expr => $replacement:expr,)*) => {lazy_static::lazy_static! { - static ref $name: Vec<(Match, &'static [u8])> = vec![ - $((Regex::new($regex).unwrap().into(), $replacement.as_bytes()),)* - ]; - }}; + ($name:ident: $($regex:expr => $replacement:expr,)*) => { + fn $name() -> &'static [(Match, &'static [u8])] { + static S: OnceLock<Vec<(Match, &'static [u8])>> = OnceLock::new(); + S.get_or_init(|| vec![ + $((Regex::new($regex).unwrap().into(), $replacement.as_bytes()),)* + ]) + } + }; } regexes! { - STDOUT: + stdout_filters: // Windows file paths r"\\" => "/", // erase borrow tags @@ -191,7 +195,7 @@ regexes! { } regexes! { - STDERR: + stderr_filters: // erase line and column info r"\.rs:[0-9]+:[0-9]+(: [0-9]+:[0-9]+)?" => ".rs:LL:CC", // erase alloc ids diff --git a/src/tools/run-make-support/Cargo.toml b/src/tools/run-make-support/Cargo.toml index 61a24c97e77..cf4ae4b16cd 100644 --- a/src/tools/run-make-support/Cargo.toml +++ b/src/tools/run-make-support/Cargo.toml @@ -8,3 +8,4 @@ object = "0.34.0" similar = "2.5.0" wasmparser = "0.118.2" regex = "1.8" # 1.8 to avoid memchr 2.6.0, as 2.5.0 is pinned in the workspace +gimli = "0.28.1" diff --git a/src/tools/run-make-support/src/cc.rs b/src/tools/run-make-support/src/cc.rs index a2d51902652..4082639f618 100644 --- a/src/tools/run-make-support/src/cc.rs +++ b/src/tools/run-make-support/src/cc.rs @@ -71,6 +71,11 @@ impl Cc { self } + + /// Get the [`Output`][::std::process::Output] of the finished process. + pub fn output(&mut self) -> ::std::process::Output { + self.cmd.output().expect("failed to get output of finished process") + } } /// `EXTRACFLAGS` @@ -161,8 +166,9 @@ pub fn extra_cxx_flags() -> Vec<&'static str> { if is_windows() { if is_msvc() { vec![] } else { vec!["-lstdc++"] } } else { - match uname() { - n if n.contains("Darwin") => vec!["-lc++"], + match &uname()[..] { + "Darwin" => vec!["-lc++"], + "FreeBSD" | "SunOS" | "OpenBSD" => vec![], _ => vec!["-lstdc++"], } } diff --git a/src/tools/run-make-support/src/clang.rs b/src/tools/run-make-support/src/clang.rs index ed9f8383dc3..c30ba29ed76 100644 --- a/src/tools/run-make-support/src/clang.rs +++ b/src/tools/run-make-support/src/clang.rs @@ -70,4 +70,9 @@ impl Clang { self.cmd.arg(format!("-fuse-ld={ld}")); self } + + /// Get the [`Output`][::std::process::Output] of the finished process. + pub fn output(&mut self) -> ::std::process::Output { + self.cmd.output().expect("failed to get output of finished process") + } } diff --git a/src/tools/run-make-support/src/diff/mod.rs b/src/tools/run-make-support/src/diff/mod.rs index 54532c6e35b..332126939c0 100644 --- a/src/tools/run-make-support/src/diff/mod.rs +++ b/src/tools/run-make-support/src/diff/mod.rs @@ -1,3 +1,4 @@ +use regex::Regex; use similar::TextDiff; use std::path::Path; @@ -14,12 +15,19 @@ pub struct Diff { expected_name: Option<String>, actual: Option<String>, actual_name: Option<String>, + normalizers: Vec<(String, String)>, } impl Diff { /// Construct a bare `diff` invocation. pub fn new() -> Self { - Self { expected: None, expected_name: None, actual: None, actual_name: None } + Self { + expected: None, + expected_name: None, + actual: None, + actual_name: None, + normalizers: Vec::new(), + } } /// Specify the expected output for the diff from a file. @@ -58,15 +66,29 @@ impl Diff { self } + /// Specify a regex that should replace text in the "actual" text that will be compared. + pub fn normalize<R: Into<String>, I: Into<String>>( + &mut self, + regex: R, + replacement: I, + ) -> &mut Self { + self.normalizers.push((regex.into(), replacement.into())); + self + } + /// Executes the diff process, prints any differences to the standard error. #[track_caller] pub fn run(&self) { let expected = self.expected.as_ref().expect("expected text not set"); - let actual = self.actual.as_ref().expect("actual text not set"); + let mut actual = self.actual.as_ref().expect("actual text not set").to_string(); let expected_name = self.expected_name.as_ref().unwrap(); let actual_name = self.actual_name.as_ref().unwrap(); + for (regex, replacement) in &self.normalizers { + let re = Regex::new(regex).expect("bad regex in custom normalization rule"); + actual = re.replace_all(&actual, replacement).into_owned(); + } - let output = TextDiff::from_lines(expected, actual) + let output = TextDiff::from_lines(expected, &actual) .unified_diff() .header(expected_name, actual_name) .to_string(); diff --git a/src/tools/run-make-support/src/diff/tests.rs b/src/tools/run-make-support/src/diff/tests.rs index e6d72544b7e..286548bef61 100644 --- a/src/tools/run-make-support/src/diff/tests.rs +++ b/src/tools/run-make-support/src/diff/tests.rs @@ -36,4 +36,26 @@ test failed: `EXPECTED_TEXT` is different from `ACTUAL_TEXT` assert_eq!(output.downcast_ref::<String>().unwrap(), expected_output); } + + #[test] + fn test_normalize() { + let expected = " +running 2 tests +.. + +test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME +"; + let actual = " +running 2 tests +.. + +test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s +"; + + diff() + .expected_text("EXPECTED_TEXT", expected) + .actual_text("ACTUAL_TEXT", actual) + .normalize(r#"finished in \d+\.\d+s"#, "finished in $$TIME") + .run(); + } } diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 76e8838d27c..d040b05f20e 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -15,6 +15,7 @@ use std::env; use std::path::{Path, PathBuf}; use std::process::{Command, Output}; +pub use gimli; pub use object; pub use regex; pub use wasmparser; @@ -143,7 +144,7 @@ pub fn set_host_rpath(cmd: &mut Command) { } /// Implement common helpers for command wrappers. This assumes that the command wrapper is a struct -/// containing a `cmd: Command` field. The provided helpers are: +/// containing a `cmd: Command` field and a `output` function. The provided helpers are: /// /// 1. Generic argument acceptors: `arg` and `args` (delegated to [`Command`]). These are intended /// to be *fallback* argument acceptors, when specific helpers don't make sense. Prefer to add @@ -159,7 +160,12 @@ pub fn set_host_rpath(cmd: &mut Command) { /// Example usage: /// /// ```ignore (illustrative) -/// struct CommandWrapper { cmd: Command } +/// struct CommandWrapper { cmd: Command } // <- required `cmd` field +/// +/// impl CommandWrapper { +/// /// Get the [`Output`][::std::process::Output] of the finished process. +/// pub fn output(&mut self) -> Output { /* ... */ } // <- required `output()` method +/// } /// /// crate::impl_common_helpers!(CommandWrapper); /// @@ -230,18 +236,13 @@ macro_rules! impl_common_helpers { self } - /// Get the [`Output`][::std::process::Output] of the finished process. - pub fn output(&mut self) -> ::std::process::Output { - self.cmd.output().expect("failed to get output of finished process") - } - /// Run the constructed command and assert that it is successfully run. #[track_caller] pub fn run(&mut self) -> ::std::process::Output { let caller_location = ::std::panic::Location::caller(); let caller_line_number = caller_location.line(); - let output = self.cmd.output().unwrap(); + let output = self.output(); if !output.status.success() { handle_failed_output(&self.cmd, output, caller_line_number); } @@ -254,12 +255,18 @@ macro_rules! impl_common_helpers { let caller_location = ::std::panic::Location::caller(); let caller_line_number = caller_location.line(); - let output = self.cmd.output().unwrap(); + let output = self.output(); if output.status.success() { handle_failed_output(&self.cmd, output, caller_line_number); } output } + + /// Set the path where the command will be run. + pub fn current_dir<P: AsRef<Path>>(&mut self, path: P) -> &mut Self { + self.cmd.current_dir(path); + self + } } }; } diff --git a/src/tools/run-make-support/src/llvm_readobj.rs b/src/tools/run-make-support/src/llvm_readobj.rs index 32ea07e932e..4e1f2b002f3 100644 --- a/src/tools/run-make-support/src/llvm_readobj.rs +++ b/src/tools/run-make-support/src/llvm_readobj.rs @@ -41,4 +41,10 @@ impl LlvmReadobj { self.cmd.arg("--file-header"); self } + + /// Get the [`Output`][::std::process::Output] of the finished process. + #[track_caller] + pub fn output(&mut self) -> ::std::process::Output { + self.cmd.output().expect("failed to get output of finished process") + } } diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs index ddaae3236c2..37539528ab3 100644 --- a/src/tools/run-make-support/src/rustc.rs +++ b/src/tools/run-make-support/src/rustc.rs @@ -1,7 +1,8 @@ use std::env; use std::ffi::OsString; +use std::io::Write; use std::path::Path; -use std::process::{Command, Output}; +use std::process::{Command, Output, Stdio}; use crate::{handle_failed_output, set_host_rpath, tmp_dir}; @@ -19,6 +20,7 @@ pub fn aux_build() -> Rustc { #[derive(Debug)] pub struct Rustc { cmd: Command, + stdin: Option<Box<[u8]>>, } crate::impl_common_helpers!(Rustc); @@ -37,14 +39,14 @@ impl Rustc { /// Construct a new `rustc` invocation. pub fn new() -> Self { let cmd = setup_common(); - Self { cmd } + Self { cmd, stdin: None } } /// Construct a new `rustc` invocation with `aux_build` preset (setting `--crate-type=lib`). pub fn new_aux_build() -> Self { let mut cmd = setup_common(); cmd.arg("--crate-type=lib"); - Self { cmd } + Self { cmd, stdin: None } } // Argument provider methods @@ -161,12 +163,40 @@ impl Rustc { self } + /// Specify a stdin input + pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self { + self.stdin = Some(input.as_ref().to_vec().into_boxed_slice()); + self + } + + /// Get the [`Output`][::std::process::Output] of the finished process. + #[track_caller] + pub fn output(&mut self) -> ::std::process::Output { + // let's make sure we piped all the input and outputs + self.cmd.stdin(Stdio::piped()); + self.cmd.stdout(Stdio::piped()); + self.cmd.stderr(Stdio::piped()); + + if let Some(input) = &self.stdin { + let mut child = self.cmd.spawn().unwrap(); + + { + let mut stdin = child.stdin.take().unwrap(); + stdin.write_all(input.as_ref()).unwrap(); + } + + child.wait_with_output().expect("failed to get output of finished process") + } else { + self.cmd.output().expect("failed to get output of finished process") + } + } + #[track_caller] pub fn run_fail_assert_exit_code(&mut self, code: i32) -> Output { let caller_location = std::panic::Location::caller(); let caller_line_number = caller_location.line(); - let output = self.cmd.output().unwrap(); + let output = self.output(); if output.status.code().unwrap() != code { handle_failed_output(&self.cmd, output, caller_line_number); } diff --git a/src/tools/run-make-support/src/rustdoc.rs b/src/tools/run-make-support/src/rustdoc.rs index 1054ac83c10..c2c4f2e68e2 100644 --- a/src/tools/run-make-support/src/rustdoc.rs +++ b/src/tools/run-make-support/src/rustdoc.rs @@ -1,6 +1,7 @@ use std::env; +use std::io::Write; use std::path::Path; -use std::process::{Command, Output}; +use std::process::{Command, Output, Stdio}; use crate::{handle_failed_output, set_host_rpath}; @@ -17,6 +18,7 @@ pub fn rustdoc() -> Rustdoc { #[derive(Debug)] pub struct Rustdoc { cmd: Command, + stdin: Option<Box<[u8]>>, } crate::impl_common_helpers!(Rustdoc); @@ -32,7 +34,7 @@ impl Rustdoc { /// Construct a bare `rustdoc` invocation. pub fn bare() -> Self { let cmd = setup_common(); - Self { cmd } + Self { cmd, stdin: None } } /// Construct a `rustdoc` invocation with `-L $(TARGET_RPATH_DIR)` set. @@ -40,7 +42,7 @@ impl Rustdoc { let mut cmd = setup_common(); let target_rpath_dir = env::var_os("TARGET_RPATH_DIR").unwrap(); cmd.arg(format!("-L{}", target_rpath_dir.to_string_lossy())); - Self { cmd } + Self { cmd, stdin: None } } /// Specify path to the input file. @@ -62,12 +64,41 @@ impl Rustdoc { self } + /// Specify a stdin input + pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self { + self.cmd.stdin(Stdio::piped()); + self.stdin = Some(input.as_ref().to_vec().into_boxed_slice()); + self + } + + /// Get the [`Output`][::std::process::Output] of the finished process. + #[track_caller] + pub fn output(&mut self) -> ::std::process::Output { + // let's make sure we piped all the input and outputs + self.cmd.stdin(Stdio::piped()); + self.cmd.stdout(Stdio::piped()); + self.cmd.stderr(Stdio::piped()); + + if let Some(input) = &self.stdin { + let mut child = self.cmd.spawn().unwrap(); + + { + let mut stdin = child.stdin.take().unwrap(); + stdin.write_all(input.as_ref()).unwrap(); + } + + child.wait_with_output().expect("failed to get output of finished process") + } else { + self.cmd.output().expect("failed to get output of finished process") + } + } + #[track_caller] pub fn run_fail_assert_exit_code(&mut self, code: i32) -> Output { let caller_location = std::panic::Location::caller(); let caller_line_number = caller_location.line(); - let output = self.cmd.output().unwrap(); + let output = self.output(); if output.status.code().unwrap() != code { handle_failed_output(&self.cmd, output, caller_line_number); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr/builtin.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr/builtin.rs index 55b9a1dfdcb..1fba2e2e4d3 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr/builtin.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr/builtin.rs @@ -207,7 +207,6 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ ), // Entry point: - gated!(unix_sigpipe, Normal, template!(Word, NameValueStr: "inherit|sig_ign|sig_dfl"), ErrorFollowing, experimental!(unix_sigpipe)), ungated!(start, Normal, template!(Word), WarnFollowing), ungated!(no_start, CrateLevel, template!(Word), WarnFollowing), ungated!(no_main, CrateLevel, template!(Word), WarnFollowing), diff --git a/src/tools/rustdoc/main.rs b/src/tools/rustdoc/main.rs index b81f46d1211..5b499a1fa1f 100644 --- a/src/tools/rustdoc/main.rs +++ b/src/tools/rustdoc/main.rs @@ -1,6 +1,3 @@ -#![feature(unix_sigpipe)] - -#[unix_sigpipe = "sig_dfl"] fn main() { rustdoc::main() } diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index f6f51fbd8ea..e196d1817f3 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -3325,11 +3325,11 @@ impl Rewrite for ast::ForeignItem { .map(|(s, _, _)| format!("{};", s)) } } - ast::ForeignItemKind::Static(ref ty, mutability, _) => { + ast::ForeignItemKind::Static(ref static_foreign_item) => { // FIXME(#21): we're dropping potential comments in between the // function kw here. let vis = format_visibility(context, &self.vis); - let mut_str = format_mutability(mutability); + let mut_str = format_mutability(static_foreign_item.mutability); let prefix = format!( "{}static {}{}:", vis, @@ -3340,7 +3340,7 @@ impl Rewrite for ast::ForeignItem { rewrite_assign_rhs( context, prefix, - &**ty, + &static_foreign_item.ty, &RhsAssignKind::Ty, shape.sub_width(1)?, ) diff --git a/src/tools/suggest-tests/Cargo.toml b/src/tools/suggest-tests/Cargo.toml index f4f4d548bb7..7c048d53a50 100644 --- a/src/tools/suggest-tests/Cargo.toml +++ b/src/tools/suggest-tests/Cargo.toml @@ -6,4 +6,3 @@ edition = "2021" [dependencies] glob = "0.3.0" build_helper = { version = "0.1.0", path = "../build_helper" } -once_cell = "1.17.1" diff --git a/src/tools/suggest-tests/src/lib.rs b/src/tools/suggest-tests/src/lib.rs index 1c1d9d0333d..8932403ac9f 100644 --- a/src/tools/suggest-tests/src/lib.rs +++ b/src/tools/suggest-tests/src/lib.rs @@ -5,7 +5,7 @@ use std::{ use dynamic_suggestions::DYNAMIC_SUGGESTIONS; use glob::Pattern; -use static_suggestions::STATIC_SUGGESTIONS; +use static_suggestions::static_suggestions; mod dynamic_suggestions; mod static_suggestions; @@ -33,7 +33,7 @@ pub fn get_suggestions<T: AsRef<str>>(modified_files: &[T]) -> Vec<Suggestion> { let mut suggestions = Vec::new(); // static suggestions - for (globs, sugs) in STATIC_SUGGESTIONS.iter() { + for (globs, sugs) in static_suggestions().iter() { let globs = globs .iter() .map(|glob| Pattern::new(glob).expect("Found invalid glob pattern!")) diff --git a/src/tools/suggest-tests/src/static_suggestions.rs b/src/tools/suggest-tests/src/static_suggestions.rs index fbd265ea42a..a34a4b16ec1 100644 --- a/src/tools/suggest-tests/src/static_suggestions.rs +++ b/src/tools/suggest-tests/src/static_suggestions.rs @@ -1,10 +1,14 @@ use crate::{sug, Suggestion}; +use std::sync::OnceLock; // FIXME: perhaps this could use `std::lazy` when it is stablizied macro_rules! static_suggestions { ($( [ $( $glob:expr ),* $(,)? ] => [ $( $suggestion:expr ),* $(,)? ] ),* $(,)? ) => { - pub(crate) const STATIC_SUGGESTIONS: ::once_cell::unsync::Lazy<Vec<(Vec<&'static str>, Vec<Suggestion>)>> - = ::once_cell::unsync::Lazy::new(|| vec![ $( (vec![ $($glob),* ], vec![ $($suggestion),* ]) ),*]); + pub(crate) fn static_suggestions() -> &'static [(Vec<&'static str>, Vec<Suggestion>)] + { + static S: OnceLock<Vec<(Vec<&'static str>, Vec<Suggestion>)>> = OnceLock::new(); + S.get_or_init(|| vec![ $( (vec![ $($glob),* ], vec![ $($suggestion),* ]) ),*]) + } } } diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml index 96866e74248..63963b0bd1c 100644 --- a/src/tools/tidy/Cargo.toml +++ b/src/tools/tidy/Cargo.toml @@ -8,7 +8,6 @@ autobins = false cargo_metadata = "0.15" regex = "1" miropt-test-tools = { path = "../miropt-test-tools" } -lazy_static = "1" walkdir = "2" ignore = "0.4.18" semver = "1.0" diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 1b560ee352c..d4d6c1460ce 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -44,7 +44,6 @@ run-make/dep-graph/Makefile run-make/dep-info-doesnt-run-much/Makefile run-make/dep-info-spaces/Makefile run-make/dep-info/Makefile -run-make/doctests-keep-binaries/Makefile run-make/doctests-runtool/Makefile run-make/dump-ice-to-disk/Makefile run-make/dump-mono-stats/Makefile @@ -219,7 +218,6 @@ run-make/prefer-rlib/Makefile run-make/pretty-print-to-file/Makefile run-make/pretty-print-with-dep-file/Makefile run-make/print-calling-conventions/Makefile -run-make/print-cfg/Makefile run-make/print-target-list/Makefile run-make/profile/Makefile run-make/prune-link-args/Makefile @@ -236,7 +234,6 @@ run-make/relocation-model/Makefile run-make/relro-levels/Makefile run-make/remap-path-prefix-dwarf/Makefile run-make/remap-path-prefix/Makefile -run-make/repr128-dwarf/Makefile run-make/reproducible-build-2/Makefile run-make/reproducible-build/Makefile run-make/resolve-rename/Makefile @@ -248,7 +245,6 @@ run-make/rlib-format-packed-bundled-libs-3/Makefile run-make/rlib-format-packed-bundled-libs/Makefile run-make/rmeta-preferred/Makefile run-make/rustc-macro-dep-files/Makefile -run-make/rustdoc-determinism/Makefile run-make/rustdoc-error-lines/Makefile run-make/rustdoc-io-error/Makefile run-make/rustdoc-map-file/Makefile @@ -290,7 +286,6 @@ run-make/static-unwinding/Makefile run-make/staticlib-blank-lib/Makefile run-make/staticlib-dylib-linkage/Makefile run-make/std-core-cycle/Makefile -run-make/stdin-non-utf8/Makefile run-make/suspicious-library/Makefile run-make/symbol-mangling-hashed/Makefile run-make/symbol-visibility/Makefile diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index d673ce7a736..3e84bf3c34b 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -17,8 +17,6 @@ use std::fs; use std::num::NonZeroU32; use std::path::{Path, PathBuf}; -use regex::Regex; - #[cfg(test)] mod tests; @@ -251,16 +249,10 @@ fn format_features<'a>( } fn find_attr_val<'a>(line: &'a str, attr: &str) -> Option<&'a str> { - lazy_static::lazy_static! { - static ref ISSUE: Regex = Regex::new(r#"issue\s*=\s*"([^"]*)""#).unwrap(); - static ref FEATURE: Regex = Regex::new(r#"feature\s*=\s*"([^"]*)""#).unwrap(); - static ref SINCE: Regex = Regex::new(r#"since\s*=\s*"([^"]*)""#).unwrap(); - } - let r = match attr { - "issue" => &*ISSUE, - "feature" => &*FEATURE, - "since" => &*SINCE, + "issue" => static_regex!(r#"issue\s*=\s*"([^"]*)""#), + "feature" => static_regex!(r#"feature\s*=\s*"([^"]*)""#), + "since" => static_regex!(r#"since\s*=\s*"([^"]*)""#), _ => unimplemented!("{attr} not handled"), }; @@ -528,11 +520,8 @@ fn map_lib_features( }}; } - lazy_static::lazy_static! { - static ref COMMENT_LINE: Regex = Regex::new(r"^\s*//").unwrap(); - } // exclude commented out lines - if COMMENT_LINE.is_match(line) { + if static_regex!(r"^\s*//").is_match(line) { continue; } diff --git a/src/tools/tidy/src/fluent_alphabetical.rs b/src/tools/tidy/src/fluent_alphabetical.rs index 9803b6eab2d..a85367984de 100644 --- a/src/tools/tidy/src/fluent_alphabetical.rs +++ b/src/tools/tidy/src/fluent_alphabetical.rs @@ -6,8 +6,8 @@ use std::{fs::OpenOptions, io::Write, path::Path}; use regex::Regex; -lazy_static::lazy_static! { - static ref MESSAGE: Regex = Regex::new(r#"(?m)^([a-zA-Z0-9_]+)\s*=\s*"#).unwrap(); +fn message() -> &'static Regex { + static_regex!(r#"(?m)^([a-zA-Z0-9_]+)\s*=\s*"#) } fn filter_fluent(path: &Path) -> bool { @@ -20,7 +20,7 @@ fn check_alphabetic( bad: &mut bool, all_defined_msgs: &mut HashMap<String, String>, ) { - let mut matches = MESSAGE.captures_iter(fluent).peekable(); + let mut matches = message().captures_iter(fluent).peekable(); while let Some(m) = matches.next() { let name = m.get(1).unwrap(); if let Some(defined_filename) = all_defined_msgs.get(name.as_str()) { @@ -60,7 +60,7 @@ fn sort_messages( let mut chunks = vec![]; let mut cur = String::new(); for line in fluent.lines() { - if let Some(name) = MESSAGE.find(line) { + if let Some(name) = message().find(line) { if let Some(defined_filename) = all_defined_msgs.get(name.as_str()) { tidy_error!( bad, diff --git a/src/tools/tidy/src/fluent_used.rs b/src/tools/tidy/src/fluent_used.rs index b73e79cb38d..8b6c6c18813 100644 --- a/src/tools/tidy/src/fluent_used.rs +++ b/src/tools/tidy/src/fluent_used.rs @@ -1,14 +1,9 @@ //! Checks that all Fluent messages appear at least twice use crate::walk::{filter_dirs, walk}; -use regex::Regex; use std::collections::HashMap; use std::path::Path; -lazy_static::lazy_static! { - static ref WORD: Regex = Regex::new(r"\w+").unwrap(); -} - fn filter_used_messages( contents: &str, msgs_not_appeared_yet: &mut HashMap<String, String>, @@ -17,7 +12,7 @@ fn filter_used_messages( // we don't just check messages never appear in Rust files, // because messages can be used as parts of other fluent messages in Fluent files, // so we do checking messages appear only once in all Rust and Fluent files. - let mut matches = WORD.find_iter(contents); + let mut matches = static_regex!(r"\w+").find_iter(contents); while let Some(name) = matches.next() { if let Some((name, filename)) = msgs_not_appeared_yet.remove_entry(name.as_str()) { // if one msg appears for the first time, diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index 23f303276aa..c15081a56d1 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -5,6 +5,13 @@ use termcolor::WriteColor; +macro_rules! static_regex { + ($re:literal) => {{ + static RE: ::std::sync::OnceLock<::regex::Regex> = ::std::sync::OnceLock::new(); + RE.get_or_init(|| ::regex::Regex::new($re).unwrap()) + }}; +} + /// A helper macro to `unwrap` a result except also print out details like: /// /// * The expression that failed diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index a1445ce5896..9cabab582d0 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -18,7 +18,7 @@ // ignore-tidy-dbg use crate::walk::{filter_dirs, walk}; -use regex::{Regex, RegexSet}; +use regex::RegexSet; use rustc_hash::FxHashMap; use std::{ffi::OsStr, path::Path}; @@ -178,20 +178,14 @@ fn should_ignore(line: &str) -> bool { // Matches test annotations like `//~ ERROR text`. // This mirrors the regex in src/tools/compiletest/src/runtest.rs, please // update both if either are changed. - lazy_static::lazy_static! { - static ref ANNOTATION_RE: Regex = Regex::new("\\s*//(\\[.*\\])?~.*").unwrap(); - } + static_regex!("\\s*//(\\[.*\\])?~.*").is_match(line) + || ANNOTATIONS_TO_IGNORE.iter().any(|a| line.contains(a)) + // For `ui_test`-style UI test directives, also ignore // - `//@[rev] compile-flags` // - `//@[rev] normalize-stderr-test` - lazy_static::lazy_static! { - static ref UI_TEST_LONG_DIRECTIVES_RE: Regex = - Regex::new("\\s*//@(\\[.*\\]) (compile-flags|normalize-stderr-test|error-pattern).*") - .unwrap(); - } - ANNOTATION_RE.is_match(line) - || ANNOTATIONS_TO_IGNORE.iter().any(|a| line.contains(a)) - || UI_TEST_LONG_DIRECTIVES_RE.is_match(line) + || static_regex!("\\s*//@(\\[.*\\]) (compile-flags|normalize-stderr-test|error-pattern).*") + .is_match(line) } /// Returns `true` if `line` is allowed to be longer than the normal limit. @@ -226,6 +220,7 @@ fn contains_ignore_directive(can_contain: bool, contents: &str, check: &str) -> if contents.contains(&format!("// ignore-tidy-{check}")) || contents.contains(&format!("# ignore-tidy-{check}")) || contents.contains(&format!("/* ignore-tidy-{check} */")) + || contents.contains(&format!("<!-- ignore-tidy-{check} -->")) { Directive::Ignore(false) } else { @@ -352,7 +347,8 @@ pub fn check(path: &Path, bad: &mut bool) { let can_contain = contents.contains("// ignore-tidy-") || contents.contains("# ignore-tidy-") - || contents.contains("/* ignore-tidy-"); + || contents.contains("/* ignore-tidy-") + || contents.contains("<!-- ignore-tidy-"); // Enable testing ICE's that require specific (untidy) // file formats easily eg. `issue-1234-ignore-tidy.rs` if filename.contains("ignore-tidy") { diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index f9985a75703..94a0eee154d 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -2,8 +2,6 @@ //! - the number of entries in each directory must be less than `ENTRY_LIMIT` //! - there are no stray `.stderr` files use ignore::Walk; -use lazy_static::lazy_static; -use regex::Regex; use std::collections::{BTreeSet, HashMap}; use std::ffi::OsStr; use std::fs; @@ -182,12 +180,8 @@ pub fn check(root_path: &Path, bless: bool, bad: &mut bool) { } if ext == "rs" { - lazy_static! { - static ref ISSUE_NAME_REGEX: Regex = - Regex::new(r"^issues?[-_]?(\d{3,})").unwrap(); - } - - if let Some(test_name) = ISSUE_NAME_REGEX.captures(testname) { + if let Some(test_name) = static_regex!(r"^issues?[-_]?(\d{3,})").captures(testname) + { // these paths are always relative to the passed `path` and always UTF8 let stripped_path = file_path .strip_prefix(path) diff --git a/tests/assembly/manual-eq-efficient.rs b/tests/assembly/manual-eq-efficient.rs new file mode 100644 index 00000000000..817ce94f476 --- /dev/null +++ b/tests/assembly/manual-eq-efficient.rs @@ -0,0 +1,22 @@ +// Regression test for #106269 +//@ assembly-output: emit-asm +//@ compile-flags: --crate-type=lib -O -C llvm-args=-x86-asm-syntax=intel +//@ only-x86_64 +//@ ignore-sgx + +pub struct S { + a: u8, + b: u8, + c: u8, + d: u8, +} + +// CHECK-LABEL: manual_eq: +#[no_mangle] +pub fn manual_eq(s1: &S, s2: &S) -> bool { + // CHECK: mov [[REG:[a-z0-9]+]], dword ptr [{{[a-z0-9]+}}] + // CHECK-NEXT: cmp [[REG]], dword ptr [{{[a-z0-9]+}}] + // CHECK-NEXT: sete al + // CHECK: ret + s1.a == s2.a && s1.b == s2.b && s1.c == s2.c && s1.d == s2.d +} diff --git a/tests/assembly/simd-intrinsic-mask-reduce.rs b/tests/assembly/simd-intrinsic-mask-reduce.rs index 763401755fa..72c3f6376e8 100644 --- a/tests/assembly/simd-intrinsic-mask-reduce.rs +++ b/tests/assembly/simd-intrinsic-mask-reduce.rs @@ -1,6 +1,8 @@ // verify that simd mask reductions do not introduce additional bit shift operations //@ revisions: x86 aarch64 //@ [x86] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +// Set the base cpu explicitly, in case the default has been changed. +//@ [x86] compile-flags: -C target-cpu=x86-64 //@ [x86] needs-llvm-components: x86 //@ [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu //@ [aarch64] needs-llvm-components: aarch64 diff --git a/tests/assembly/x86_64-floating-point-clamp.rs b/tests/assembly/x86_64-floating-point-clamp.rs index 4a72a7f44fa..c05afadff64 100644 --- a/tests/assembly/x86_64-floating-point-clamp.rs +++ b/tests/assembly/x86_64-floating-point-clamp.rs @@ -2,7 +2,8 @@ // so check to make sure that's what it's actually emitting. //@ assembly-output: emit-asm -//@ compile-flags: --crate-type=lib -O -C llvm-args=-x86-asm-syntax=intel +// Set the base cpu explicitly, in case the default has been changed. +//@ compile-flags: --crate-type=lib -O -C llvm-args=-x86-asm-syntax=intel -C target-cpu=x86-64 //@ only-x86_64 //@ ignore-sgx diff --git a/tests/codegen/enum/enum-match.rs b/tests/codegen/enum/enum-match.rs index f1c40f6695b..ced26c0a434 100644 --- a/tests/codegen/enum/enum-match.rs +++ b/tests/codegen/enum/enum-match.rs @@ -11,7 +11,7 @@ pub enum Enum0 { B, } -// CHECK: define noundef i8 @match0{{.*}} +// CHECK: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match0{{.*}} // CHECK-NEXT: start: // CHECK-NEXT: %1 = icmp eq i8 %0, 2 // CHECK-NEXT: %2 = and i8 %0, 1 @@ -32,7 +32,7 @@ pub enum Enum1 { C, } -// CHECK: define noundef i8 @match1{{.*}} +// CHECK: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match1{{.*}} // CHECK-NEXT: start: // CHECK-NEXT: %1 = add i8 %0, -2 // CHECK-NEXT: %2 = zext i8 %1 to i64 @@ -91,7 +91,7 @@ pub enum Enum2 { E, } -// CHECK: define noundef i8 @match2{{.*}} +// CHECK: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match2{{.*}} // CHECK-NEXT: start: // CHECK-NEXT: %1 = add i8 %0, 2 // CHECK-NEXT: %2 = zext i8 %1 to i64 diff --git a/tests/codegen/instrument-coverage/instrument-coverage-off.rs b/tests/codegen/instrument-coverage/instrument-coverage-off.rs index fda3c541a25..616e3295e5b 100644 --- a/tests/codegen/instrument-coverage/instrument-coverage-off.rs +++ b/tests/codegen/instrument-coverage/instrument-coverage-off.rs @@ -1,22 +1,19 @@ // Test that `-Cinstrument-coverage=off` does not add coverage instrumentation to LLVM IR. -//@ needs-profiler-support -//@ revisions: n no off false zero +//@ revisions: n no off false_ zero //@ [n] compile-flags: -Cinstrument-coverage=n //@ [no] compile-flags: -Cinstrument-coverage=no //@ [off] compile-flags: -Cinstrument-coverage=off -//@ [false] compile-flags: -Cinstrument-coverage=false +//@ [false_] compile-flags: -Cinstrument-coverage=false //@ [zero] compile-flags: -Cinstrument-coverage=0 // CHECK-NOT: __llvm_profile_filename // CHECK-NOT: __llvm_coverage_mapping -#![crate_type="lib"] +#![crate_type = "lib"] #[inline(never)] -fn some_function() { - -} +fn some_function() {} pub fn some_other_function() { some_function(); diff --git a/tests/codegen/instrument-coverage/instrument-coverage.rs b/tests/codegen/instrument-coverage/instrument-coverage.rs index f7d96ea3467..d638a544d5a 100644 --- a/tests/codegen/instrument-coverage/instrument-coverage.rs +++ b/tests/codegen/instrument-coverage/instrument-coverage.rs @@ -1,12 +1,12 @@ // Test that `-Cinstrument-coverage` creates expected __llvm_profile_filename symbol in LLVM IR. //@ needs-profiler-support -//@ revisions: default y yes on true all +//@ revisions: default y yes on true_ all //@ [default] compile-flags: -Cinstrument-coverage //@ [y] compile-flags: -Cinstrument-coverage=y //@ [yes] compile-flags: -Cinstrument-coverage=yes //@ [on] compile-flags: -Cinstrument-coverage=on -//@ [true] compile-flags: -Cinstrument-coverage=true +//@ [true_] compile-flags: -Cinstrument-coverage=true //@ [all] compile-flags: -Cinstrument-coverage=all // CHECK: @__llvm_profile_filename = {{.*}}"default_%m_%p.profraw\00"{{.*}} diff --git a/tests/codegen/ptr-read-metadata.rs b/tests/codegen/ptr-read-metadata.rs index 4c623dee5e1..e3565c962f7 100644 --- a/tests/codegen/ptr-read-metadata.rs +++ b/tests/codegen/ptr-read-metadata.rs @@ -47,7 +47,7 @@ pub unsafe fn read_byte_assume_init(p: &MaybeUninit<u8>) -> u8 { p.assume_init_read() } -// CHECK-LABEL: define {{(dso_local )?}}noundef i32 @copy_char( +// CHECK-LABEL: define {{(dso_local )?}}noundef {{(range\(.*\) )?}}i32 @copy_char( #[no_mangle] pub unsafe fn copy_char(p: *const char) -> char { // CHECK-NOT: load @@ -58,7 +58,7 @@ pub unsafe fn copy_char(p: *const char) -> char { *p } -// CHECK-LABEL: define {{(dso_local )?}}noundef i32 @read_char( +// CHECK-LABEL: define {{(dso_local )?}}noundef {{(range\(.*\) )?}}i32 @read_char( #[no_mangle] pub unsafe fn read_char(p: *const char) -> char { // CHECK-NOT: load @@ -80,7 +80,7 @@ pub unsafe fn read_char_maybe_uninit(p: *const MaybeUninit<char>) -> MaybeUninit p.read() } -// CHECK-LABEL: define {{(dso_local )?}}noundef i32 @read_char_assume_init( +// CHECK-LABEL: define {{(dso_local )?}}noundef {{(range\(.*\) )?}}i32 @read_char_assume_init( #[no_mangle] pub unsafe fn read_char_assume_init(p: &MaybeUninit<char>) -> char { // CHECK-NOT: load diff --git a/tests/codegen/target-feature-inline-closure.rs b/tests/codegen/target-feature-inline-closure.rs index 88bd413a870..d973bd93e31 100644 --- a/tests/codegen/target-feature-inline-closure.rs +++ b/tests/codegen/target-feature-inline-closure.rs @@ -1,5 +1,6 @@ //@ only-x86_64 -//@ compile-flags: -Copt-level=3 +// Set the base cpu explicitly, in case the default has been changed. +//@ compile-flags: -Copt-level=3 -Ctarget-cpu=x86-64 #![crate_type = "lib"] #![feature(target_feature_11)] diff --git a/tests/coverage/issue-83601.cov-map b/tests/coverage/issue-83601.cov-map index f2447e3c92c..ddb4407881a 100644 --- a/tests/coverage/issue-83601.cov-map +++ b/tests/coverage/issue-83601.cov-map @@ -1,12 +1,12 @@ Function name: issue_83601::main -Raw bytes (21): 0x[01, 01, 01, 05, 09, 03, 01, 06, 01, 02, 1c, 05, 03, 09, 01, 1c, 02, 02, 05, 03, 02] +Raw bytes (21): 0x[01, 01, 01, 05, 00, 03, 01, 06, 01, 02, 1c, 05, 03, 09, 01, 1c, 02, 02, 05, 03, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 -- expression 0 operands: lhs = Counter(1), rhs = Counter(2) +- expression 0 operands: lhs = Counter(1), rhs = Zero Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 6, 1) to (start + 2, 28) - Code(Counter(1)) at (prev + 3, 9) to (start + 1, 28) - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 3, 2) - = (c1 - c2) + = (c1 - Zero) diff --git a/tests/coverage/issue-84561.cov-map b/tests/coverage/issue-84561.cov-map index a81884ea942..ab66a2fffce 100644 --- a/tests/coverage/issue-84561.cov-map +++ b/tests/coverage/issue-84561.cov-map @@ -77,22 +77,22 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 167, 9) to (start + 2, 10) Function name: issue_84561::test3 -Raw bytes (436): 0x[01, 01, 41, 05, 09, 0d, 00, 15, 19, 12, 00, 15, 19, 21, 00, 1e, 00, 21, 00, 31, 00, 3d, 41, 2e, 45, 3d, 41, 42, 49, 45, 00, 3f, 51, 42, 49, 45, 00, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 92, 01, 55, 51, 00, 8f, 01, 5d, 92, 01, 55, 51, 00, 87, 01, 61, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 82, 01, 65, 87, 01, 61, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 75, f6, 01, fb, 01, 79, 00, fe, 01, 82, 02, 00, 69, 6d, 00, fe, 01, 82, 02, 00, 69, 6d, 69, 6d, 82, 02, 00, 69, 6d, fb, 01, 79, 00, fe, 01, 82, 02, 00, 69, 6d, f3, 01, 7d, 75, f6, 01, fb, 01, 79, 00, fe, 01, 82, 02, 00, 69, 6d, ee, 01, 00, f3, 01, 7d, 75, f6, 01, fb, 01, 79, 00, fe, 01, 82, 02, 00, 69, 6d, 33, 01, 08, 01, 03, 1c, 05, 04, 09, 01, 1c, 02, 02, 05, 04, 1f, 0d, 05, 05, 00, 1f, 06, 01, 05, 00, 1f, 15, 01, 09, 01, 1c, 12, 02, 05, 00, 1f, 0e, 01, 05, 00, 0f, 00, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 00, 03, 20, 00, 30, 00, 00, 33, 00, 41, 00, 00, 4b, 00, 5a, 1e, 01, 05, 00, 0f, 00, 05, 09, 03, 10, 00, 05, 0d, 00, 1b, 00, 02, 0d, 00, 1c, 1a, 04, 09, 05, 06, 31, 06, 05, 03, 06, 22, 04, 05, 03, 06, 3d, 04, 09, 04, 06, 2e, 05, 08, 00, 0f, 45, 01, 09, 03, 0a, 2a, 05, 09, 03, 0a, 3f, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 00, 03, 0d, 00, 1d, 3a, 03, 09, 00, 13, 00, 03, 0d, 00, 1d, 87, 01, 03, 05, 00, 0f, 8f, 01, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 8a, 01, 02, 0d, 00, 13, 82, 01, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 7e, 02, 0d, 00, 13, f3, 01, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 03, 0e, 75, 04, 0d, 00, 13, fb, 01, 02, 0d, 00, 17, 82, 02, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, fe, 01, 02, 15, 00, 1b, f6, 01, 04, 0d, 00, 13, 7d, 03, 09, 00, 19, ee, 01, 02, 05, 00, 0f, ea, 01, 03, 09, 00, 22, 00, 02, 05, 00, 0f, 00, 03, 09, 00, 2c, 00, 02, 01, 00, 02] +Raw bytes (436): 0x[01, 01, 41, 05, 00, 0d, 00, 15, 00, 12, 00, 15, 00, 21, 00, 1e, 00, 21, 00, 31, 00, 3d, 00, 2e, 45, 3d, 00, 42, 49, 45, 00, 3f, 51, 42, 49, 45, 00, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 92, 01, 55, 51, 00, 8f, 01, 5d, 92, 01, 55, 51, 00, 87, 01, 61, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 82, 01, 65, 87, 01, 61, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 75, f6, 01, fb, 01, 79, 00, fe, 01, 82, 02, 00, 69, 6d, 00, fe, 01, 82, 02, 00, 69, 6d, 69, 6d, 82, 02, 00, 69, 6d, fb, 01, 79, 00, fe, 01, 82, 02, 00, 69, 6d, f3, 01, 7d, 75, f6, 01, fb, 01, 79, 00, fe, 01, 82, 02, 00, 69, 6d, ee, 01, 00, f3, 01, 7d, 75, f6, 01, fb, 01, 79, 00, fe, 01, 82, 02, 00, 69, 6d, 33, 01, 08, 01, 03, 1c, 05, 04, 09, 01, 1c, 02, 02, 05, 04, 1f, 0d, 05, 05, 00, 1f, 06, 01, 05, 00, 1f, 15, 01, 09, 01, 1c, 12, 02, 05, 00, 1f, 0e, 01, 05, 00, 0f, 00, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 00, 03, 20, 00, 30, 00, 00, 33, 00, 41, 00, 00, 4b, 00, 5a, 1e, 01, 05, 00, 0f, 00, 05, 09, 03, 10, 00, 05, 0d, 00, 1b, 00, 02, 0d, 00, 1c, 1a, 04, 09, 05, 06, 31, 06, 05, 03, 06, 22, 04, 05, 03, 06, 3d, 04, 09, 04, 06, 2e, 05, 08, 00, 0f, 45, 01, 09, 03, 0a, 2a, 05, 09, 03, 0a, 3f, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 00, 03, 0d, 00, 1d, 3a, 03, 09, 00, 13, 00, 03, 0d, 00, 1d, 87, 01, 03, 05, 00, 0f, 8f, 01, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 8a, 01, 02, 0d, 00, 13, 82, 01, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 7e, 02, 0d, 00, 13, f3, 01, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 03, 0e, 75, 04, 0d, 00, 13, fb, 01, 02, 0d, 00, 17, 82, 02, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, fe, 01, 02, 15, 00, 1b, f6, 01, 04, 0d, 00, 13, 7d, 03, 09, 00, 19, ee, 01, 02, 05, 00, 0f, ea, 01, 03, 09, 00, 22, 00, 02, 05, 00, 0f, 00, 03, 09, 00, 2c, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 65 -- expression 0 operands: lhs = Counter(1), rhs = Counter(2) +- expression 0 operands: lhs = Counter(1), rhs = Zero - expression 1 operands: lhs = Counter(3), rhs = Zero -- expression 2 operands: lhs = Counter(5), rhs = Counter(6) +- expression 2 operands: lhs = Counter(5), rhs = Zero - expression 3 operands: lhs = Expression(4, Sub), rhs = Zero -- expression 4 operands: lhs = Counter(5), rhs = Counter(6) +- expression 4 operands: lhs = Counter(5), rhs = Zero - expression 5 operands: lhs = Counter(8), rhs = Zero - expression 6 operands: lhs = Expression(7, Sub), rhs = Zero - expression 7 operands: lhs = Counter(8), rhs = Zero - expression 8 operands: lhs = Counter(12), rhs = Zero -- expression 9 operands: lhs = Counter(15), rhs = Counter(16) +- expression 9 operands: lhs = Counter(15), rhs = Zero - expression 10 operands: lhs = Expression(11, Sub), rhs = Counter(17) -- expression 11 operands: lhs = Counter(15), rhs = Counter(16) +- expression 11 operands: lhs = Counter(15), rhs = Zero - expression 12 operands: lhs = Expression(16, Sub), rhs = Counter(18) - expression 13 operands: lhs = Counter(17), rhs = Zero - expression 14 operands: lhs = Expression(15, Add), rhs = Counter(20) @@ -150,15 +150,15 @@ Number of file 0 mappings: 51 - Code(Counter(0)) at (prev + 8, 1) to (start + 3, 28) - Code(Counter(1)) at (prev + 4, 9) to (start + 1, 28) - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 4, 31) - = (c1 - c2) + = (c1 - Zero) - Code(Counter(3)) at (prev + 5, 5) to (start + 0, 31) - Code(Expression(1, Sub)) at (prev + 1, 5) to (start + 0, 31) = (c3 - Zero) - Code(Counter(5)) at (prev + 1, 9) to (start + 1, 28) - Code(Expression(4, Sub)) at (prev + 2, 5) to (start + 0, 31) - = (c5 - c6) + = (c5 - Zero) - Code(Expression(3, Sub)) at (prev + 1, 5) to (start + 0, 15) - = ((c5 - c6) - Zero) + = ((c5 - Zero) - Zero) - Code(Zero) at (prev + 0, 32) to (start + 0, 48) - Code(Counter(8)) at (prev + 1, 5) to (start + 3, 15) - Code(Zero) at (prev + 3, 32) to (start + 0, 48) @@ -176,10 +176,10 @@ Number of file 0 mappings: 51 = (c12 - Zero) - Code(Counter(15)) at (prev + 4, 9) to (start + 4, 6) - Code(Expression(11, Sub)) at (prev + 5, 8) to (start + 0, 15) - = (c15 - c16) + = (c15 - Zero) - Code(Counter(17)) at (prev + 1, 9) to (start + 3, 10) - Code(Expression(10, Sub)) at (prev + 5, 9) to (start + 3, 10) - = ((c15 - c16) - c17) + = ((c15 - Zero) - c17) - Code(Expression(15, Add)) at (prev + 5, 8) to (start + 0, 15) = ((c17 - Zero) + c18) - Code(Counter(20)) at (prev + 1, 9) to (start + 0, 19) diff --git a/tests/coverage/mcdc_nested_if.cov-map b/tests/coverage/mcdc_nested_if.cov-map new file mode 100644 index 00000000000..2f35ffad8a9 --- /dev/null +++ b/tests/coverage/mcdc_nested_if.cov-map @@ -0,0 +1,201 @@ +Function name: mcdc_nested_if::doubly_nested_if_in_condition +Raw bytes (168): 0x[01, 01, 0e, 01, 05, 05, 11, 05, 11, 26, 19, 05, 11, 19, 1d, 19, 1d, 1d, 22, 26, 19, 05, 11, 11, 15, 09, 02, 0d, 37, 09, 02, 14, 01, 0f, 01, 01, 09, 28, 02, 02, 01, 08, 00, 4e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4e, 05, 00, 10, 00, 11, 28, 01, 02, 00, 10, 00, 36, 30, 11, 26, 01, 00, 02, 00, 10, 00, 11, 30, 15, 21, 02, 00, 00, 00, 15, 00, 36, 26, 00, 18, 00, 19, 28, 00, 02, 00, 18, 00, 1e, 30, 19, 22, 01, 02, 00, 00, 18, 00, 19, 19, 00, 1d, 00, 1e, 30, 1a, 1d, 02, 00, 00, 00, 1d, 00, 1e, 1a, 00, 21, 00, 25, 1f, 00, 2f, 00, 34, 2b, 00, 39, 00, 3e, 21, 00, 48, 00, 4c, 0d, 00, 4f, 02, 06, 37, 02, 0c, 02, 06, 33, 03, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 14 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Counter(4) +- expression 2 operands: lhs = Counter(1), rhs = Counter(4) +- expression 3 operands: lhs = Expression(9, Sub), rhs = Counter(6) +- expression 4 operands: lhs = Counter(1), rhs = Counter(4) +- expression 5 operands: lhs = Counter(6), rhs = Counter(7) +- expression 6 operands: lhs = Counter(6), rhs = Counter(7) +- expression 7 operands: lhs = Counter(7), rhs = Expression(8, Sub) +- expression 8 operands: lhs = Expression(9, Sub), rhs = Counter(6) +- expression 9 operands: lhs = Counter(1), rhs = Counter(4) +- expression 10 operands: lhs = Counter(4), rhs = Counter(5) +- expression 11 operands: lhs = Counter(2), rhs = Expression(0, Sub) +- expression 12 operands: lhs = Counter(3), rhs = Expression(13, Add) +- expression 13 operands: lhs = Counter(2), rhs = Expression(0, Sub) +Number of file 0 mappings: 20 +- Code(Counter(0)) at (prev + 15, 1) to (start + 1, 9) +- MCDCDecision { bitmap_idx: 2, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 78) +- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) + true = c1 + false = (c0 - c1) +- MCDCBranch { true: Counter(3), false: Counter(2), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 78) + true = c3 + false = c2 +- Code(Counter(1)) at (prev + 0, 16) to (start + 0, 17) +- MCDCDecision { bitmap_idx: 1, conditions_num: 2 } at (prev + 0, 16) to (start + 0, 54) +- MCDCBranch { true: Counter(4), false: Expression(9, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 16) to (start + 0, 17) + true = c4 + false = (c1 - c4) +- MCDCBranch { true: Counter(5), false: Counter(8), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 21) to (start + 0, 54) + true = c5 + false = c8 +- Code(Expression(9, Sub)) at (prev + 0, 24) to (start + 0, 25) + = (c1 - c4) +- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 0, 24) to (start + 0, 30) +- MCDCBranch { true: Counter(6), false: Expression(8, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 24) to (start + 0, 25) + true = c6 + false = ((c1 - c4) - c6) +- Code(Counter(6)) at (prev + 0, 29) to (start + 0, 30) +- MCDCBranch { true: Expression(6, Sub), false: Counter(7), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 29) to (start + 0, 30) + true = (c6 - c7) + false = c7 +- Code(Expression(6, Sub)) at (prev + 0, 33) to (start + 0, 37) + = (c6 - c7) +- Code(Expression(7, Add)) at (prev + 0, 47) to (start + 0, 52) + = (c7 + ((c1 - c4) - c6)) +- Code(Expression(10, Add)) at (prev + 0, 57) to (start + 0, 62) + = (c4 + c5) +- Code(Counter(8)) at (prev + 0, 72) to (start + 0, 76) +- Code(Counter(3)) at (prev + 0, 79) to (start + 2, 6) +- Code(Expression(13, Add)) at (prev + 2, 12) to (start + 2, 6) + = (c2 + (c0 - c1)) +- Code(Expression(12, Add)) at (prev + 3, 1) to (start + 0, 2) + = (c3 + (c2 + (c0 - c1))) + +Function name: mcdc_nested_if::nested_if_in_condition +Raw bytes (120): 0x[01, 01, 0b, 01, 05, 05, 11, 05, 11, 1e, 15, 05, 11, 11, 15, 1e, 15, 05, 11, 09, 02, 0d, 2b, 09, 02, 0e, 01, 07, 01, 01, 09, 28, 01, 02, 01, 08, 00, 2e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 2e, 05, 00, 10, 00, 11, 28, 00, 02, 00, 10, 00, 16, 30, 11, 1e, 01, 00, 02, 00, 10, 00, 11, 1e, 00, 15, 00, 16, 30, 15, 1a, 02, 00, 00, 00, 15, 00, 16, 17, 00, 19, 00, 1d, 1a, 00, 27, 00, 2c, 0d, 00, 2f, 02, 06, 2b, 02, 0c, 02, 06, 27, 03, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 11 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Counter(4) +- expression 2 operands: lhs = Counter(1), rhs = Counter(4) +- expression 3 operands: lhs = Expression(7, Sub), rhs = Counter(5) +- expression 4 operands: lhs = Counter(1), rhs = Counter(4) +- expression 5 operands: lhs = Counter(4), rhs = Counter(5) +- expression 6 operands: lhs = Expression(7, Sub), rhs = Counter(5) +- expression 7 operands: lhs = Counter(1), rhs = Counter(4) +- expression 8 operands: lhs = Counter(2), rhs = Expression(0, Sub) +- expression 9 operands: lhs = Counter(3), rhs = Expression(10, Add) +- expression 10 operands: lhs = Counter(2), rhs = Expression(0, Sub) +Number of file 0 mappings: 14 +- Code(Counter(0)) at (prev + 7, 1) to (start + 1, 9) +- MCDCDecision { bitmap_idx: 1, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 46) +- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) + true = c1 + false = (c0 - c1) +- MCDCBranch { true: Counter(3), false: Counter(2), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 46) + true = c3 + false = c2 +- Code(Counter(1)) at (prev + 0, 16) to (start + 0, 17) +- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 0, 16) to (start + 0, 22) +- MCDCBranch { true: Counter(4), false: Expression(7, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 16) to (start + 0, 17) + true = c4 + false = (c1 - c4) +- Code(Expression(7, Sub)) at (prev + 0, 21) to (start + 0, 22) + = (c1 - c4) +- MCDCBranch { true: Counter(5), false: Expression(6, Sub), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 21) to (start + 0, 22) + true = c5 + false = ((c1 - c4) - c5) +- Code(Expression(5, Add)) at (prev + 0, 25) to (start + 0, 29) + = (c4 + c5) +- Code(Expression(6, Sub)) at (prev + 0, 39) to (start + 0, 44) + = ((c1 - c4) - c5) +- Code(Counter(3)) at (prev + 0, 47) to (start + 2, 6) +- Code(Expression(10, Add)) at (prev + 2, 12) to (start + 2, 6) + = (c2 + (c0 - c1)) +- Code(Expression(9, Add)) at (prev + 3, 1) to (start + 0, 2) + = (c3 + (c2 + (c0 - c1))) + +Function name: mcdc_nested_if::nested_in_then_block_in_condition +Raw bytes (176): 0x[01, 01, 12, 01, 05, 05, 11, 05, 11, 3a, 15, 05, 11, 11, 15, 33, 19, 11, 15, 19, 1d, 19, 1d, 1d, 2e, 33, 19, 11, 15, 3a, 15, 05, 11, 09, 02, 0d, 47, 09, 02, 14, 01, 22, 01, 01, 09, 28, 02, 02, 01, 08, 00, 4b, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4b, 05, 00, 10, 00, 11, 28, 00, 02, 00, 10, 00, 16, 30, 11, 3a, 01, 00, 02, 00, 10, 00, 11, 3a, 00, 15, 00, 16, 30, 15, 36, 02, 00, 00, 00, 15, 00, 16, 33, 00, 1c, 00, 1d, 28, 01, 02, 00, 1c, 00, 22, 30, 19, 2e, 01, 02, 00, 00, 1c, 00, 1d, 19, 00, 21, 00, 22, 30, 26, 1d, 02, 00, 00, 00, 21, 00, 22, 26, 00, 25, 00, 29, 2b, 00, 33, 00, 38, 36, 00, 44, 00, 49, 0d, 00, 4c, 02, 06, 47, 02, 0c, 02, 06, 43, 03, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 18 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Counter(4) +- expression 2 operands: lhs = Counter(1), rhs = Counter(4) +- expression 3 operands: lhs = Expression(14, Sub), rhs = Counter(5) +- expression 4 operands: lhs = Counter(1), rhs = Counter(4) +- expression 5 operands: lhs = Counter(4), rhs = Counter(5) +- expression 6 operands: lhs = Expression(12, Add), rhs = Counter(6) +- expression 7 operands: lhs = Counter(4), rhs = Counter(5) +- expression 8 operands: lhs = Counter(6), rhs = Counter(7) +- expression 9 operands: lhs = Counter(6), rhs = Counter(7) +- expression 10 operands: lhs = Counter(7), rhs = Expression(11, Sub) +- expression 11 operands: lhs = Expression(12, Add), rhs = Counter(6) +- expression 12 operands: lhs = Counter(4), rhs = Counter(5) +- expression 13 operands: lhs = Expression(14, Sub), rhs = Counter(5) +- expression 14 operands: lhs = Counter(1), rhs = Counter(4) +- expression 15 operands: lhs = Counter(2), rhs = Expression(0, Sub) +- expression 16 operands: lhs = Counter(3), rhs = Expression(17, Add) +- expression 17 operands: lhs = Counter(2), rhs = Expression(0, Sub) +Number of file 0 mappings: 20 +- Code(Counter(0)) at (prev + 34, 1) to (start + 1, 9) +- MCDCDecision { bitmap_idx: 2, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 75) +- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) + true = c1 + false = (c0 - c1) +- MCDCBranch { true: Counter(3), false: Counter(2), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 75) + true = c3 + false = c2 +- Code(Counter(1)) at (prev + 0, 16) to (start + 0, 17) +- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 0, 16) to (start + 0, 22) +- MCDCBranch { true: Counter(4), false: Expression(14, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 16) to (start + 0, 17) + true = c4 + false = (c1 - c4) +- Code(Expression(14, Sub)) at (prev + 0, 21) to (start + 0, 22) + = (c1 - c4) +- MCDCBranch { true: Counter(5), false: Expression(13, Sub), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 21) to (start + 0, 22) + true = c5 + false = ((c1 - c4) - c5) +- Code(Expression(12, Add)) at (prev + 0, 28) to (start + 0, 29) + = (c4 + c5) +- MCDCDecision { bitmap_idx: 1, conditions_num: 2 } at (prev + 0, 28) to (start + 0, 34) +- MCDCBranch { true: Counter(6), false: Expression(11, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 28) to (start + 0, 29) + true = c6 + false = ((c4 + c5) - c6) +- Code(Counter(6)) at (prev + 0, 33) to (start + 0, 34) +- MCDCBranch { true: Expression(9, Sub), false: Counter(7), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 33) to (start + 0, 34) + true = (c6 - c7) + false = c7 +- Code(Expression(9, Sub)) at (prev + 0, 37) to (start + 0, 41) + = (c6 - c7) +- Code(Expression(10, Add)) at (prev + 0, 51) to (start + 0, 56) + = (c7 + ((c4 + c5) - c6)) +- Code(Expression(13, Sub)) at (prev + 0, 68) to (start + 0, 73) + = ((c1 - c4) - c5) +- Code(Counter(3)) at (prev + 0, 76) to (start + 2, 6) +- Code(Expression(17, Add)) at (prev + 2, 12) to (start + 2, 6) + = (c2 + (c0 - c1)) +- Code(Expression(16, Add)) at (prev + 3, 1) to (start + 0, 2) + = (c3 + (c2 + (c0 - c1))) + +Function name: mcdc_nested_if::nested_single_condition_decision +Raw bytes (85): 0x[01, 01, 06, 01, 05, 05, 11, 05, 11, 09, 02, 0d, 17, 09, 02, 0b, 01, 17, 01, 04, 09, 28, 00, 02, 04, 08, 00, 29, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 29, 05, 00, 10, 00, 11, 20, 11, 0a, 00, 10, 00, 11, 11, 00, 14, 00, 19, 0a, 00, 23, 00, 27, 0d, 00, 2a, 02, 06, 17, 02, 0c, 02, 06, 13, 03, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 6 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Counter(4) +- expression 2 operands: lhs = Counter(1), rhs = Counter(4) +- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub) +- expression 4 operands: lhs = Counter(3), rhs = Expression(5, Add) +- expression 5 operands: lhs = Counter(2), rhs = Expression(0, Sub) +Number of file 0 mappings: 11 +- Code(Counter(0)) at (prev + 23, 1) to (start + 4, 9) +- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 4, 8) to (start + 0, 41) +- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) + true = c1 + false = (c0 - c1) +- MCDCBranch { true: Counter(3), false: Counter(2), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 41) + true = c3 + false = c2 +- Code(Counter(1)) at (prev + 0, 16) to (start + 0, 17) +- Branch { true: Counter(4), false: Expression(2, Sub) } at (prev + 0, 16) to (start + 0, 17) + true = c4 + false = (c1 - c4) +- Code(Counter(4)) at (prev + 0, 20) to (start + 0, 25) +- Code(Expression(2, Sub)) at (prev + 0, 35) to (start + 0, 39) + = (c1 - c4) +- Code(Counter(3)) at (prev + 0, 42) to (start + 2, 6) +- Code(Expression(5, Add)) at (prev + 2, 12) to (start + 2, 6) + = (c2 + (c0 - c1)) +- Code(Expression(4, Add)) at (prev + 3, 1) to (start + 0, 2) + = (c3 + (c2 + (c0 - c1))) + diff --git a/tests/coverage/mcdc_nested_if.coverage b/tests/coverage/mcdc_nested_if.coverage new file mode 100644 index 00000000000..19529cd6aa4 --- /dev/null +++ b/tests/coverage/mcdc_nested_if.coverage @@ -0,0 +1,235 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2021 + LL| |//@ min-llvm-version: 18 + LL| |//@ compile-flags: -Zcoverage-options=mcdc + LL| |//@ llvm-cov-flags: --show-mcdc + LL| | + LL| 4|fn nested_if_in_condition(a: bool, b: bool, c: bool) { + LL| 4| if a && if b || c { true } else { false } { + ^3 ^2 ^2 ^1 + ------------------ + |---> MC/DC Decision Region (LL:8) to (LL:46) + | + | Number of Conditions: 2 + | Condition C1 --> (LL:8) + | Condition C2 --> (LL:13) + | + | Executed MC/DC Test Vectors: + | + | C1, C2 Result + | 1 { F, - = F } + | 2 { T, F = F } + | 3 { T, T = T } + | + | C1-Pair: covered: (1,3) + | C2-Pair: covered: (2,3) + | MC/DC Coverage for Decision: 100.00% + | + |---> MC/DC Decision Region (LL:16) to (LL:22) + | + | Number of Conditions: 2 + | Condition C1 --> (LL:16) + | Condition C2 --> (LL:21) + | + | Executed MC/DC Test Vectors: + | + | C1, C2 Result + | 1 { F, F = F } + | 2 { T, - = T } + | 3 { F, T = T } + | + | C1-Pair: covered: (1,2) + | C2-Pair: covered: (1,3) + | MC/DC Coverage for Decision: 100.00% + | + ------------------ + LL| 2| say("yes"); + LL| 2| } else { + LL| 2| say("no"); + LL| 2| } + LL| 4|} + LL| | + LL| 4|fn doubly_nested_if_in_condition(a: bool, b: bool, c: bool, d: bool) { + LL| 4| if a && if b || if c && d { true } else { false } { false } else { true } { + ^3 ^2 ^1 ^1 ^1 ^2 ^1 + ------------------ + |---> MC/DC Decision Region (LL:8) to (LL:78) + | + | Number of Conditions: 2 + | Condition C1 --> (LL:8) + | Condition C2 --> (LL:13) + | + | Executed MC/DC Test Vectors: + | + | C1, C2 Result + | 1 { F, - = F } + | 2 { T, F = F } + | 3 { T, T = T } + | + | C1-Pair: covered: (1,3) + | C2-Pair: covered: (2,3) + | MC/DC Coverage for Decision: 100.00% + | + |---> MC/DC Decision Region (LL:16) to (LL:54) + | + | Number of Conditions: 2 + | Condition C1 --> (LL:16) + | Condition C2 --> (LL:21) + | + | Executed MC/DC Test Vectors: + | + | C1, C2 Result + | 1 { F, F = F } + | 2 { T, - = T } + | 3 { F, T = T } + | + | C1-Pair: covered: (1,2) + | C2-Pair: covered: (1,3) + | MC/DC Coverage for Decision: 100.00% + | + |---> MC/DC Decision Region (LL:24) to (LL:30) + | + | Number of Conditions: 2 + | Condition C1 --> (LL:24) + | Condition C2 --> (LL:29) + | + | Executed MC/DC Test Vectors: + | + | C1, C2 Result + | 1 { F, - = F } + | 2 { T, T = T } + | + | C1-Pair: covered: (1,2) + | C2-Pair: not covered + | MC/DC Coverage for Decision: 50.00% + | + ------------------ + LL| 1| say("yes"); + LL| 3| } else { + LL| 3| say("no"); + LL| 3| } + LL| 4|} + LL| | + LL| 3|fn nested_single_condition_decision(a: bool, b: bool) { + LL| 3| // Decision with only 1 decision should not be instrumented by MCDC because + LL| 3| // branch-coverage is equivalent to MCDC coverage in this case, and we don't + LL| 3| // want to waste bitmap space for this. + LL| 3| if a && if b { false } else { true } { + ^2 ^1 ^1 + ------------------ + |---> MC/DC Decision Region (LL:8) to (LL:41) + | + | Number of Conditions: 2 + | Condition C1 --> (LL:8) + | Condition C2 --> (LL:13) + | + | Executed MC/DC Test Vectors: + | + | C1, C2 Result + | 1 { F, - = F } + | 2 { T, F = F } + | 3 { T, T = T } + | + | C1-Pair: covered: (1,3) + | C2-Pair: covered: (2,3) + | MC/DC Coverage for Decision: 100.00% + | + ------------------ + LL| 1| say("yes"); + LL| 2| } else { + LL| 2| say("no"); + LL| 2| } + LL| 3|} + LL| | + LL| 7|fn nested_in_then_block_in_condition(a: bool, b: bool, c: bool, d: bool, e: bool) { + LL| 7| if a && if b || c { if d && e { true } else { false } } else { false } { + ^6 ^5 ^5 ^2 ^1 ^4 ^1 + ------------------ + |---> MC/DC Decision Region (LL:8) to (LL:75) + | + | Number of Conditions: 2 + | Condition C1 --> (LL:8) + | Condition C2 --> (LL:13) + | + | Executed MC/DC Test Vectors: + | + | C1, C2 Result + | 1 { F, - = F } + | 2 { T, F = F } + | 3 { T, T = T } + | + | C1-Pair: covered: (1,3) + | C2-Pair: covered: (2,3) + | MC/DC Coverage for Decision: 100.00% + | + |---> MC/DC Decision Region (LL:16) to (LL:22) + | + | Number of Conditions: 2 + | Condition C1 --> (LL:16) + | Condition C2 --> (LL:21) + | + | Executed MC/DC Test Vectors: + | + | C1, C2 Result + | 1 { F, F = F } + | 2 { T, - = T } + | 3 { F, T = T } + | + | C1-Pair: covered: (1,2) + | C2-Pair: covered: (1,3) + | MC/DC Coverage for Decision: 100.00% + | + |---> MC/DC Decision Region (LL:28) to (LL:34) + | + | Number of Conditions: 2 + | Condition C1 --> (LL:28) + | Condition C2 --> (LL:33) + | + | Executed MC/DC Test Vectors: + | + | C1, C2 Result + | 1 { F, - = F } + | 2 { T, F = F } + | 3 { T, T = T } + | + | C1-Pair: covered: (1,3) + | C2-Pair: covered: (2,3) + | MC/DC Coverage for Decision: 100.00% + | + ------------------ + LL| 1| say("yes"); + LL| 6| } else { + LL| 6| say("no"); + LL| 6| } + LL| 7|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | nested_if_in_condition(true, false, false); + LL| | nested_if_in_condition(true, true, true); + LL| | nested_if_in_condition(true, false, true); + LL| | nested_if_in_condition(false, true, true); + LL| | + LL| | doubly_nested_if_in_condition(true, false, false, true); + LL| | doubly_nested_if_in_condition(true, true, true, true); + LL| | doubly_nested_if_in_condition(true, false, true, true); + LL| | doubly_nested_if_in_condition(false, true, true, true); + LL| | + LL| | nested_single_condition_decision(true, true); + LL| | nested_single_condition_decision(true, false); + LL| | nested_single_condition_decision(false, false); + LL| | + LL| | nested_in_then_block_in_condition(false, false, false, false, false); + LL| | nested_in_then_block_in_condition(true, false, false, false, false); + LL| | nested_in_then_block_in_condition(true, true, false, false, false); + LL| | nested_in_then_block_in_condition(true, false, true, false, false); + LL| | nested_in_then_block_in_condition(true, false, true, true, false); + LL| | nested_in_then_block_in_condition(true, false, true, false, true); + LL| | nested_in_then_block_in_condition(true, false, true, true, true); + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |fn say(message: &str) { + LL| | core::hint::black_box(message); + LL| |} + diff --git a/tests/coverage/mcdc_nested_if.rs b/tests/coverage/mcdc_nested_if.rs new file mode 100644 index 00000000000..3d869771f75 --- /dev/null +++ b/tests/coverage/mcdc_nested_if.rs @@ -0,0 +1,70 @@ +#![feature(coverage_attribute)] +//@ edition: 2021 +//@ min-llvm-version: 18 +//@ compile-flags: -Zcoverage-options=mcdc +//@ llvm-cov-flags: --show-mcdc + +fn nested_if_in_condition(a: bool, b: bool, c: bool) { + if a && if b || c { true } else { false } { + say("yes"); + } else { + say("no"); + } +} + +fn doubly_nested_if_in_condition(a: bool, b: bool, c: bool, d: bool) { + if a && if b || if c && d { true } else { false } { false } else { true } { + say("yes"); + } else { + say("no"); + } +} + +fn nested_single_condition_decision(a: bool, b: bool) { + // Decision with only 1 decision should not be instrumented by MCDC because + // branch-coverage is equivalent to MCDC coverage in this case, and we don't + // want to waste bitmap space for this. + if a && if b { false } else { true } { + say("yes"); + } else { + say("no"); + } +} + +fn nested_in_then_block_in_condition(a: bool, b: bool, c: bool, d: bool, e: bool) { + if a && if b || c { if d && e { true } else { false } } else { false } { + say("yes"); + } else { + say("no"); + } +} + +#[coverage(off)] +fn main() { + nested_if_in_condition(true, false, false); + nested_if_in_condition(true, true, true); + nested_if_in_condition(true, false, true); + nested_if_in_condition(false, true, true); + + doubly_nested_if_in_condition(true, false, false, true); + doubly_nested_if_in_condition(true, true, true, true); + doubly_nested_if_in_condition(true, false, true, true); + doubly_nested_if_in_condition(false, true, true, true); + + nested_single_condition_decision(true, true); + nested_single_condition_decision(true, false); + nested_single_condition_decision(false, false); + + nested_in_then_block_in_condition(false, false, false, false, false); + nested_in_then_block_in_condition(true, false, false, false, false); + nested_in_then_block_in_condition(true, true, false, false, false); + nested_in_then_block_in_condition(true, false, true, false, false); + nested_in_then_block_in_condition(true, false, true, true, false); + nested_in_then_block_in_condition(true, false, true, false, true); + nested_in_then_block_in_condition(true, false, true, true, true); +} + +#[coverage(off)] +fn say(message: &str) { + core::hint::black_box(message); +} diff --git a/tests/crashes/109812.rs b/tests/crashes/109812.rs new file mode 100644 index 00000000000..c29b8746521 --- /dev/null +++ b/tests/crashes/109812.rs @@ -0,0 +1,22 @@ +//@ known-bug: #109812 + +#![warn(rust_2021_incompatible_closure_captures)] + +enum Either { + One(X), + Two(X), +} + +struct X(Y); + +struct Y; + +fn move_into_fnmut() { + let x = X(Y); + + consume_fnmut(|| { + let Either::Two(ref mut _t) = x; + + let X(mut _t) = x; + }); +} diff --git a/tests/crashes/111883.rs b/tests/crashes/111883.rs deleted file mode 100644 index fa72b28c228..00000000000 --- a/tests/crashes/111883.rs +++ /dev/null @@ -1,40 +0,0 @@ -//@ known-bug: #111883 -#![crate_type = "lib"] -#![feature(arbitrary_self_types, no_core, lang_items)] -#![no_core] - -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} -#[lang = "receiver"] -trait Receiver {} -#[lang = "dispatch_from_dyn"] -trait DispatchFromDyn<T> {} -impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {} -#[lang = "unsize"] -trait Unsize<T: ?Sized> {} -#[lang = "coerce_unsized"] -pub trait CoerceUnsized<T: ?Sized> {} -impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} - -#[lang = "drop_in_place"] -fn drop_in_place_fn<T>(a: &dyn Trait2<T>) {} - -pub trait Trait1 { - fn foo(&self); -} - -pub struct Type1; - -impl Trait1 for Type1 { - fn foo(&self) {} -} - -pub trait Trait2<T> {} - -pub fn bar1() { - let a = Type1; - let b = &a as &dyn Trait1; - b.foo(); -} diff --git a/tests/crashes/123710.rs b/tests/crashes/123710.rs deleted file mode 100644 index f171fa7cebb..00000000000 --- a/tests/crashes/123710.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ known-bug: #123710 - -#[repr(packed)] -#[repr(u32)] -enum E { - A, - B, - C, -} - -fn main() { - union InvalidTag { - int: u32, - e: E, - } - let _invalid_tag = InvalidTag { int: 4 }; -} diff --git a/tests/mir-opt/const_prop/offset_of.concrete.GVN.panic-abort.diff b/tests/mir-opt/const_prop/offset_of.concrete.GVN.panic-abort.diff index 5d94797905d..77a2c5bcccc 100644 --- a/tests/mir-opt/const_prop/offset_of.concrete.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/offset_of.concrete.GVN.panic-abort.diff @@ -4,33 +4,26 @@ fn concrete() -> () { let mut _0: (); let _1: usize; - let mut _2: usize; - let mut _4: usize; - let mut _6: usize; - let mut _8: usize; - let mut _10: usize; - let mut _12: usize; - let mut _14: usize; scope 1 { debug x => _1; - let _3: usize; + let _2: usize; scope 2 { - debug y => _3; - let _5: usize; + debug y => _2; + let _3: usize; scope 3 { - debug z0 => _5; - let _7: usize; + debug z0 => _3; + let _4: usize; scope 4 { - debug z1 => _7; - let _9: usize; + debug z1 => _4; + let _5: usize; scope 5 { - debug eA0 => _9; - let _11: usize; + debug eA0 => _5; + let _6: usize; scope 6 { - debug eA1 => _11; - let _13: usize; + debug eA1 => _6; + let _7: usize; scope 7 { - debug eC => _13; + debug eC => _7; } } } @@ -41,82 +34,33 @@ bb0: { StorageLive(_1); +- _1 = OffsetOf(Alpha, [(0, 0)]); ++ _1 = const 4_usize; StorageLive(_2); -- _2 = OffsetOf(Alpha, [(0, 0)]); -- _1 = must_use::<usize>(move _2) -> [return: bb1, unwind unreachable]; -+ _2 = const 4_usize; -+ _1 = must_use::<usize>(const 4_usize) -> [return: bb1, unwind unreachable]; - } - - bb1: { - StorageDead(_2); +- _2 = OffsetOf(Alpha, [(0, 1)]); ++ _2 = const 0_usize; StorageLive(_3); +- _3 = OffsetOf(Alpha, [(0, 2), (0, 0)]); ++ _3 = const 2_usize; StorageLive(_4); -- _4 = OffsetOf(Alpha, [(0, 1)]); -- _3 = must_use::<usize>(move _4) -> [return: bb2, unwind unreachable]; -+ _4 = const 0_usize; -+ _3 = must_use::<usize>(const 0_usize) -> [return: bb2, unwind unreachable]; - } - - bb2: { - StorageDead(_4); +- _4 = OffsetOf(Alpha, [(0, 2), (0, 1)]); ++ _4 = const 3_usize; StorageLive(_5); +- _5 = OffsetOf(Epsilon, [(0, 0)]); ++ _5 = const 1_usize; StorageLive(_6); -- _6 = OffsetOf(Alpha, [(0, 2), (0, 0)]); -- _5 = must_use::<usize>(move _6) -> [return: bb3, unwind unreachable]; +- _6 = OffsetOf(Epsilon, [(0, 1)]); + _6 = const 2_usize; -+ _5 = must_use::<usize>(const 2_usize) -> [return: bb3, unwind unreachable]; - } - - bb3: { - StorageDead(_6); StorageLive(_7); - StorageLive(_8); -- _8 = OffsetOf(Alpha, [(0, 2), (0, 1)]); -- _7 = must_use::<usize>(move _8) -> [return: bb4, unwind unreachable]; -+ _8 = const 3_usize; -+ _7 = must_use::<usize>(const 3_usize) -> [return: bb4, unwind unreachable]; - } - - bb4: { - StorageDead(_8); - StorageLive(_9); - StorageLive(_10); -- _10 = OffsetOf(Epsilon, [(0, 0)]); -- _9 = must_use::<usize>(move _10) -> [return: bb5, unwind unreachable]; -+ _10 = const 1_usize; -+ _9 = must_use::<usize>(const 1_usize) -> [return: bb5, unwind unreachable]; - } - - bb5: { - StorageDead(_10); - StorageLive(_11); - StorageLive(_12); -- _12 = OffsetOf(Epsilon, [(0, 1)]); -- _11 = must_use::<usize>(move _12) -> [return: bb6, unwind unreachable]; -+ _12 = const 2_usize; -+ _11 = must_use::<usize>(const 2_usize) -> [return: bb6, unwind unreachable]; - } - - bb6: { - StorageDead(_12); - StorageLive(_13); - StorageLive(_14); -- _14 = OffsetOf(Epsilon, [(2, 0)]); -- _13 = must_use::<usize>(move _14) -> [return: bb7, unwind unreachable]; -+ _14 = const 4_usize; -+ _13 = must_use::<usize>(const 4_usize) -> [return: bb7, unwind unreachable]; - } - - bb7: { - StorageDead(_14); +- _7 = OffsetOf(Epsilon, [(2, 0)]); ++ _7 = const 4_usize; _0 = const (); - StorageDead(_13); - StorageDead(_11); - StorageDead(_9); StorageDead(_7); + StorageDead(_6); StorageDead(_5); + StorageDead(_4); StorageDead(_3); + StorageDead(_2); StorageDead(_1); return; } diff --git a/tests/mir-opt/const_prop/offset_of.concrete.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/offset_of.concrete.GVN.panic-unwind.diff index 4d890742ee9..77a2c5bcccc 100644 --- a/tests/mir-opt/const_prop/offset_of.concrete.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/offset_of.concrete.GVN.panic-unwind.diff @@ -4,33 +4,26 @@ fn concrete() -> () { let mut _0: (); let _1: usize; - let mut _2: usize; - let mut _4: usize; - let mut _6: usize; - let mut _8: usize; - let mut _10: usize; - let mut _12: usize; - let mut _14: usize; scope 1 { debug x => _1; - let _3: usize; + let _2: usize; scope 2 { - debug y => _3; - let _5: usize; + debug y => _2; + let _3: usize; scope 3 { - debug z0 => _5; - let _7: usize; + debug z0 => _3; + let _4: usize; scope 4 { - debug z1 => _7; - let _9: usize; + debug z1 => _4; + let _5: usize; scope 5 { - debug eA0 => _9; - let _11: usize; + debug eA0 => _5; + let _6: usize; scope 6 { - debug eA1 => _11; - let _13: usize; + debug eA1 => _6; + let _7: usize; scope 7 { - debug eC => _13; + debug eC => _7; } } } @@ -41,82 +34,33 @@ bb0: { StorageLive(_1); +- _1 = OffsetOf(Alpha, [(0, 0)]); ++ _1 = const 4_usize; StorageLive(_2); -- _2 = OffsetOf(Alpha, [(0, 0)]); -- _1 = must_use::<usize>(move _2) -> [return: bb1, unwind continue]; -+ _2 = const 4_usize; -+ _1 = must_use::<usize>(const 4_usize) -> [return: bb1, unwind continue]; - } - - bb1: { - StorageDead(_2); +- _2 = OffsetOf(Alpha, [(0, 1)]); ++ _2 = const 0_usize; StorageLive(_3); +- _3 = OffsetOf(Alpha, [(0, 2), (0, 0)]); ++ _3 = const 2_usize; StorageLive(_4); -- _4 = OffsetOf(Alpha, [(0, 1)]); -- _3 = must_use::<usize>(move _4) -> [return: bb2, unwind continue]; -+ _4 = const 0_usize; -+ _3 = must_use::<usize>(const 0_usize) -> [return: bb2, unwind continue]; - } - - bb2: { - StorageDead(_4); +- _4 = OffsetOf(Alpha, [(0, 2), (0, 1)]); ++ _4 = const 3_usize; StorageLive(_5); +- _5 = OffsetOf(Epsilon, [(0, 0)]); ++ _5 = const 1_usize; StorageLive(_6); -- _6 = OffsetOf(Alpha, [(0, 2), (0, 0)]); -- _5 = must_use::<usize>(move _6) -> [return: bb3, unwind continue]; +- _6 = OffsetOf(Epsilon, [(0, 1)]); + _6 = const 2_usize; -+ _5 = must_use::<usize>(const 2_usize) -> [return: bb3, unwind continue]; - } - - bb3: { - StorageDead(_6); StorageLive(_7); - StorageLive(_8); -- _8 = OffsetOf(Alpha, [(0, 2), (0, 1)]); -- _7 = must_use::<usize>(move _8) -> [return: bb4, unwind continue]; -+ _8 = const 3_usize; -+ _7 = must_use::<usize>(const 3_usize) -> [return: bb4, unwind continue]; - } - - bb4: { - StorageDead(_8); - StorageLive(_9); - StorageLive(_10); -- _10 = OffsetOf(Epsilon, [(0, 0)]); -- _9 = must_use::<usize>(move _10) -> [return: bb5, unwind continue]; -+ _10 = const 1_usize; -+ _9 = must_use::<usize>(const 1_usize) -> [return: bb5, unwind continue]; - } - - bb5: { - StorageDead(_10); - StorageLive(_11); - StorageLive(_12); -- _12 = OffsetOf(Epsilon, [(0, 1)]); -- _11 = must_use::<usize>(move _12) -> [return: bb6, unwind continue]; -+ _12 = const 2_usize; -+ _11 = must_use::<usize>(const 2_usize) -> [return: bb6, unwind continue]; - } - - bb6: { - StorageDead(_12); - StorageLive(_13); - StorageLive(_14); -- _14 = OffsetOf(Epsilon, [(2, 0)]); -- _13 = must_use::<usize>(move _14) -> [return: bb7, unwind continue]; -+ _14 = const 4_usize; -+ _13 = must_use::<usize>(const 4_usize) -> [return: bb7, unwind continue]; - } - - bb7: { - StorageDead(_14); +- _7 = OffsetOf(Epsilon, [(2, 0)]); ++ _7 = const 4_usize; _0 = const (); - StorageDead(_13); - StorageDead(_11); - StorageDead(_9); StorageDead(_7); + StorageDead(_6); StorageDead(_5); + StorageDead(_4); StorageDead(_3); + StorageDead(_2); StorageDead(_1); return; } diff --git a/tests/mir-opt/const_prop/offset_of.generic.GVN.panic-abort.diff b/tests/mir-opt/const_prop/offset_of.generic.GVN.panic-abort.diff index 025241dd1bf..130c31eff8c 100644 --- a/tests/mir-opt/const_prop/offset_of.generic.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/offset_of.generic.GVN.panic-abort.diff @@ -4,33 +4,26 @@ fn generic() -> () { let mut _0: (); let _1: usize; - let mut _2: usize; - let mut _4: usize; - let mut _6: usize; - let mut _8: usize; - let mut _10: usize; - let mut _12: usize; - let mut _14: usize; scope 1 { debug gx => _1; - let _3: usize; + let _2: usize; scope 2 { - debug gy => _3; - let _5: usize; + debug gy => _2; + let _3: usize; scope 3 { - debug dx => _5; - let _7: usize; + debug dx => _3; + let _4: usize; scope 4 { - debug dy => _7; - let _9: usize; + debug dy => _4; + let _5: usize; scope 5 { - debug zA0 => _9; - let _11: usize; + debug zA0 => _5; + let _6: usize; scope 6 { - debug zA1 => _11; - let _13: usize; + debug zA1 => _6; + let _7: usize; scope 7 { - debug zB => _13; + debug zB => _7; } } } @@ -41,72 +34,28 @@ bb0: { StorageLive(_1); + _1 = OffsetOf(Gamma<T>, [(0, 0)]); StorageLive(_2); - _2 = OffsetOf(Gamma<T>, [(0, 0)]); - _1 = must_use::<usize>(move _2) -> [return: bb1, unwind unreachable]; - } - - bb1: { - StorageDead(_2); + _2 = OffsetOf(Gamma<T>, [(0, 1)]); StorageLive(_3); +- _3 = OffsetOf(Delta<T>, [(0, 1)]); ++ _3 = const 0_usize; StorageLive(_4); - _4 = OffsetOf(Gamma<T>, [(0, 1)]); - _3 = must_use::<usize>(move _4) -> [return: bb2, unwind unreachable]; - } - - bb2: { - StorageDead(_4); +- _4 = OffsetOf(Delta<T>, [(0, 2)]); ++ _4 = const 2_usize; StorageLive(_5); + _5 = OffsetOf(Zeta<T>, [(0, 0)]); StorageLive(_6); -- _6 = OffsetOf(Delta<T>, [(0, 1)]); -- _5 = must_use::<usize>(move _6) -> [return: bb3, unwind unreachable]; -+ _6 = const 0_usize; -+ _5 = must_use::<usize>(const 0_usize) -> [return: bb3, unwind unreachable]; - } - - bb3: { - StorageDead(_6); + _6 = OffsetOf(Zeta<T>, [(0, 1)]); StorageLive(_7); - StorageLive(_8); -- _8 = OffsetOf(Delta<T>, [(0, 2)]); -- _7 = must_use::<usize>(move _8) -> [return: bb4, unwind unreachable]; -+ _8 = const 2_usize; -+ _7 = must_use::<usize>(const 2_usize) -> [return: bb4, unwind unreachable]; - } - - bb4: { - StorageDead(_8); - StorageLive(_9); - StorageLive(_10); - _10 = OffsetOf(Zeta<T>, [(0, 0)]); - _9 = must_use::<usize>(move _10) -> [return: bb5, unwind unreachable]; - } - - bb5: { - StorageDead(_10); - StorageLive(_11); - StorageLive(_12); - _12 = OffsetOf(Zeta<T>, [(0, 1)]); - _11 = must_use::<usize>(move _12) -> [return: bb6, unwind unreachable]; - } - - bb6: { - StorageDead(_12); - StorageLive(_13); - StorageLive(_14); - _14 = OffsetOf(Zeta<T>, [(1, 0)]); - _13 = must_use::<usize>(move _14) -> [return: bb7, unwind unreachable]; - } - - bb7: { - StorageDead(_14); + _7 = OffsetOf(Zeta<T>, [(1, 0)]); _0 = const (); - StorageDead(_13); - StorageDead(_11); - StorageDead(_9); StorageDead(_7); + StorageDead(_6); StorageDead(_5); + StorageDead(_4); StorageDead(_3); + StorageDead(_2); StorageDead(_1); return; } diff --git a/tests/mir-opt/const_prop/offset_of.generic.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/offset_of.generic.GVN.panic-unwind.diff index 27f2b2f7355..130c31eff8c 100644 --- a/tests/mir-opt/const_prop/offset_of.generic.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/offset_of.generic.GVN.panic-unwind.diff @@ -4,33 +4,26 @@ fn generic() -> () { let mut _0: (); let _1: usize; - let mut _2: usize; - let mut _4: usize; - let mut _6: usize; - let mut _8: usize; - let mut _10: usize; - let mut _12: usize; - let mut _14: usize; scope 1 { debug gx => _1; - let _3: usize; + let _2: usize; scope 2 { - debug gy => _3; - let _5: usize; + debug gy => _2; + let _3: usize; scope 3 { - debug dx => _5; - let _7: usize; + debug dx => _3; + let _4: usize; scope 4 { - debug dy => _7; - let _9: usize; + debug dy => _4; + let _5: usize; scope 5 { - debug zA0 => _9; - let _11: usize; + debug zA0 => _5; + let _6: usize; scope 6 { - debug zA1 => _11; - let _13: usize; + debug zA1 => _6; + let _7: usize; scope 7 { - debug zB => _13; + debug zB => _7; } } } @@ -41,72 +34,28 @@ bb0: { StorageLive(_1); + _1 = OffsetOf(Gamma<T>, [(0, 0)]); StorageLive(_2); - _2 = OffsetOf(Gamma<T>, [(0, 0)]); - _1 = must_use::<usize>(move _2) -> [return: bb1, unwind continue]; - } - - bb1: { - StorageDead(_2); + _2 = OffsetOf(Gamma<T>, [(0, 1)]); StorageLive(_3); +- _3 = OffsetOf(Delta<T>, [(0, 1)]); ++ _3 = const 0_usize; StorageLive(_4); - _4 = OffsetOf(Gamma<T>, [(0, 1)]); - _3 = must_use::<usize>(move _4) -> [return: bb2, unwind continue]; - } - - bb2: { - StorageDead(_4); +- _4 = OffsetOf(Delta<T>, [(0, 2)]); ++ _4 = const 2_usize; StorageLive(_5); + _5 = OffsetOf(Zeta<T>, [(0, 0)]); StorageLive(_6); -- _6 = OffsetOf(Delta<T>, [(0, 1)]); -- _5 = must_use::<usize>(move _6) -> [return: bb3, unwind continue]; -+ _6 = const 0_usize; -+ _5 = must_use::<usize>(const 0_usize) -> [return: bb3, unwind continue]; - } - - bb3: { - StorageDead(_6); + _6 = OffsetOf(Zeta<T>, [(0, 1)]); StorageLive(_7); - StorageLive(_8); -- _8 = OffsetOf(Delta<T>, [(0, 2)]); -- _7 = must_use::<usize>(move _8) -> [return: bb4, unwind continue]; -+ _8 = const 2_usize; -+ _7 = must_use::<usize>(const 2_usize) -> [return: bb4, unwind continue]; - } - - bb4: { - StorageDead(_8); - StorageLive(_9); - StorageLive(_10); - _10 = OffsetOf(Zeta<T>, [(0, 0)]); - _9 = must_use::<usize>(move _10) -> [return: bb5, unwind continue]; - } - - bb5: { - StorageDead(_10); - StorageLive(_11); - StorageLive(_12); - _12 = OffsetOf(Zeta<T>, [(0, 1)]); - _11 = must_use::<usize>(move _12) -> [return: bb6, unwind continue]; - } - - bb6: { - StorageDead(_12); - StorageLive(_13); - StorageLive(_14); - _14 = OffsetOf(Zeta<T>, [(1, 0)]); - _13 = must_use::<usize>(move _14) -> [return: bb7, unwind continue]; - } - - bb7: { - StorageDead(_14); + _7 = OffsetOf(Zeta<T>, [(1, 0)]); _0 = const (); - StorageDead(_13); - StorageDead(_11); - StorageDead(_9); StorageDead(_7); + StorageDead(_6); StorageDead(_5); + StorageDead(_4); StorageDead(_3); + StorageDead(_2); StorageDead(_1); return; } diff --git a/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-abort.diff new file mode 100644 index 00000000000..897592a0e2f --- /dev/null +++ b/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-abort.diff @@ -0,0 +1,24 @@ +- // MIR for `borrowed` before CopyProp ++ // MIR for `borrowed` after CopyProp + + fn borrowed(_1: T) -> bool { + let mut _0: bool; + let mut _2: T; + let mut _3: &T; + + bb0: { +- _2 = _1; + _3 = &_1; + _0 = opaque::<&T>(_3) -> [return: bb1, unwind unreachable]; + } + + bb1: { +- _0 = opaque::<T>(_2) -> [return: bb2, unwind unreachable]; ++ _0 = opaque::<T>(_1) -> [return: bb2, unwind unreachable]; + } + + bb2: { + return; + } + } + diff --git a/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-unwind.diff new file mode 100644 index 00000000000..33c05af91a1 --- /dev/null +++ b/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-unwind.diff @@ -0,0 +1,24 @@ +- // MIR for `borrowed` before CopyProp ++ // MIR for `borrowed` after CopyProp + + fn borrowed(_1: T) -> bool { + let mut _0: bool; + let mut _2: T; + let mut _3: &T; + + bb0: { +- _2 = _1; + _3 = &_1; + _0 = opaque::<&T>(_3) -> [return: bb1, unwind continue]; + } + + bb1: { +- _0 = opaque::<T>(_2) -> [return: bb2, unwind continue]; ++ _0 = opaque::<T>(_1) -> [return: bb2, unwind continue]; + } + + bb2: { + return; + } + } + diff --git a/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/borrowed_local.compare_address.CopyProp.panic-abort.diff index 46534076c29..3d6b5dffba4 100644 --- a/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/borrowed_local.compare_address.CopyProp.panic-abort.diff @@ -1,7 +1,7 @@ -- // MIR for `f` before CopyProp -+ // MIR for `f` after CopyProp +- // MIR for `compare_address` before CopyProp ++ // MIR for `compare_address` after CopyProp - fn f() -> bool { + fn compare_address() -> bool { let mut _0: bool; let mut _1: u8; let mut _2: &u8; diff --git a/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/borrowed_local.compare_address.CopyProp.panic-unwind.diff index b702e3b7d1e..0f29d2681de 100644 --- a/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/borrowed_local.compare_address.CopyProp.panic-unwind.diff @@ -1,7 +1,7 @@ -- // MIR for `f` before CopyProp -+ // MIR for `f` after CopyProp +- // MIR for `compare_address` before CopyProp ++ // MIR for `compare_address` after CopyProp - fn f() -> bool { + fn compare_address() -> bool { let mut _0: bool; let mut _1: u8; let mut _2: &u8; diff --git a/tests/mir-opt/copy-prop/borrowed_local.non_freeze.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/borrowed_local.non_freeze.CopyProp.panic-abort.diff new file mode 100644 index 00000000000..af2aeb0dcab --- /dev/null +++ b/tests/mir-opt/copy-prop/borrowed_local.non_freeze.CopyProp.panic-abort.diff @@ -0,0 +1,23 @@ +- // MIR for `non_freeze` before CopyProp ++ // MIR for `non_freeze` after CopyProp + + fn non_freeze(_1: T) -> bool { + let mut _0: bool; + let mut _2: T; + let mut _3: &T; + + bb0: { + _2 = _1; + _3 = &_1; + _0 = opaque::<&T>(_3) -> [return: bb1, unwind unreachable]; + } + + bb1: { + _0 = opaque::<T>(_2) -> [return: bb2, unwind unreachable]; + } + + bb2: { + return; + } + } + diff --git a/tests/mir-opt/copy-prop/borrowed_local.non_freeze.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/borrowed_local.non_freeze.CopyProp.panic-unwind.diff new file mode 100644 index 00000000000..040ed0aec16 --- /dev/null +++ b/tests/mir-opt/copy-prop/borrowed_local.non_freeze.CopyProp.panic-unwind.diff @@ -0,0 +1,23 @@ +- // MIR for `non_freeze` before CopyProp ++ // MIR for `non_freeze` after CopyProp + + fn non_freeze(_1: T) -> bool { + let mut _0: bool; + let mut _2: T; + let mut _3: &T; + + bb0: { + _2 = _1; + _3 = &_1; + _0 = opaque::<&T>(_3) -> [return: bb1, unwind continue]; + } + + bb1: { + _0 = opaque::<T>(_2) -> [return: bb2, unwind continue]; + } + + bb2: { + return; + } + } + diff --git a/tests/mir-opt/copy-prop/borrowed_local.rs b/tests/mir-opt/copy-prop/borrowed_local.rs index 74ac6281a89..512287dd176 100644 --- a/tests/mir-opt/copy-prop/borrowed_local.rs +++ b/tests/mir-opt/copy-prop/borrowed_local.rs @@ -1,10 +1,10 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY //@ test-mir-pass: CopyProp -#![feature(custom_mir, core_intrinsics)] +#![feature(custom_mir, core_intrinsics, freeze)] #![allow(unused_assignments)] extern crate core; +use core::marker::Freeze; use core::intrinsics::mir::*; fn opaque(_: impl Sized) -> bool { true } @@ -14,7 +14,16 @@ fn cmp_ref(a: &u8, b: &u8) -> bool { } #[custom_mir(dialect = "analysis", phase = "post-cleanup")] -fn f() -> bool { +fn compare_address() -> bool { + // CHECK-LABEL: fn compare_address( + // CHECK: bb0: { + // CHECK-NEXT: _1 = const 5_u8; + // CHECK-NEXT: _2 = &_1; + // CHECK-NEXT: _3 = _1; + // CHECK-NEXT: _4 = &_3; + // CHECK-NEXT: _0 = cmp_ref(_2, _4) + // CHECK: bb1: { + // CHECK-NEXT: _0 = opaque::<u8>(_3) mir!( { let a = 5_u8; @@ -34,8 +43,60 @@ fn f() -> bool { ) } +/// Generic type `T` is `Freeze`, so shared borrows are immutable. +#[custom_mir(dialect = "analysis", phase = "post-cleanup")] +fn borrowed<T: Copy + Freeze>(x: T) -> bool { + // CHECK-LABEL: fn borrowed( + // CHECK: bb0: { + // CHECK-NEXT: _3 = &_1; + // CHECK-NEXT: _0 = opaque::<&T>(_3) + // CHECK: bb1: { + // CHECK-NEXT: _0 = opaque::<T>(_1) + mir!( + { + let a = x; + let r1 = &x; + Call(RET = opaque(r1), ReturnTo(next), UnwindContinue()) + } + next = { + Call(RET = opaque(a), ReturnTo(ret), UnwindContinue()) + } + ret = { + Return() + } + ) +} + +/// Generic type `T` is not known to be `Freeze`, so shared borrows may be mutable. +#[custom_mir(dialect = "analysis", phase = "post-cleanup")] +fn non_freeze<T: Copy>(x: T) -> bool { + // CHECK-LABEL: fn non_freeze( + // CHECK: bb0: { + // CHECK-NEXT: _2 = _1; + // CHECK-NEXT: _3 = &_1; + // CHECK-NEXT: _0 = opaque::<&T>(_3) + // CHECK: bb1: { + // CHECK-NEXT: _0 = opaque::<T>(_2) + mir!( + { + let a = x; + let r1 = &x; + Call(RET = opaque(r1), ReturnTo(next), UnwindContinue()) + } + next = { + Call(RET = opaque(a), ReturnTo(ret), UnwindContinue()) + } + ret = { + Return() + } + ) +} + fn main() { - assert!(!f()); + assert!(!compare_address()); + non_freeze(5); } -// EMIT_MIR borrowed_local.f.CopyProp.diff +// EMIT_MIR borrowed_local.compare_address.CopyProp.diff +// EMIT_MIR borrowed_local.borrowed.CopyProp.diff +// EMIT_MIR borrowed_local.non_freeze.CopyProp.diff diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.concrete.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/offset_of.concrete.DataflowConstProp.panic-abort.diff index f8f89175033..92691d0f807 100644 --- a/tests/mir-opt/dataflow-const-prop/offset_of.concrete.DataflowConstProp.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/offset_of.concrete.DataflowConstProp.panic-abort.diff @@ -4,21 +4,17 @@ fn concrete() -> () { let mut _0: (); let _1: usize; - let mut _2: usize; - let mut _4: usize; - let mut _6: usize; - let mut _8: usize; scope 1 { debug x => _1; - let _3: usize; + let _2: usize; scope 2 { - debug y => _3; - let _5: usize; + debug y => _2; + let _3: usize; scope 3 { - debug z0 => _5; - let _7: usize; + debug z0 => _3; + let _4: usize; scope 4 { - debug z1 => _7; + debug z1 => _4; } } } @@ -26,49 +22,21 @@ bb0: { StorageLive(_1); +- _1 = OffsetOf(Alpha, [(0, 0)]); ++ _1 = const 4_usize; StorageLive(_2); -- _2 = OffsetOf(Alpha, [(0, 0)]); -- _1 = must_use::<usize>(move _2) -> [return: bb1, unwind unreachable]; -+ _2 = const 4_usize; -+ _1 = must_use::<usize>(const 4_usize) -> [return: bb1, unwind unreachable]; - } - - bb1: { - StorageDead(_2); +- _2 = OffsetOf(Alpha, [(0, 1)]); ++ _2 = const 0_usize; StorageLive(_3); +- _3 = OffsetOf(Alpha, [(0, 2), (0, 0)]); ++ _3 = const 2_usize; StorageLive(_4); -- _4 = OffsetOf(Alpha, [(0, 1)]); -- _3 = must_use::<usize>(move _4) -> [return: bb2, unwind unreachable]; -+ _4 = const 0_usize; -+ _3 = must_use::<usize>(const 0_usize) -> [return: bb2, unwind unreachable]; - } - - bb2: { - StorageDead(_4); - StorageLive(_5); - StorageLive(_6); -- _6 = OffsetOf(Alpha, [(0, 2), (0, 0)]); -- _5 = must_use::<usize>(move _6) -> [return: bb3, unwind unreachable]; -+ _6 = const 2_usize; -+ _5 = must_use::<usize>(const 2_usize) -> [return: bb3, unwind unreachable]; - } - - bb3: { - StorageDead(_6); - StorageLive(_7); - StorageLive(_8); -- _8 = OffsetOf(Alpha, [(0, 2), (0, 1)]); -- _7 = must_use::<usize>(move _8) -> [return: bb4, unwind unreachable]; -+ _8 = const 3_usize; -+ _7 = must_use::<usize>(const 3_usize) -> [return: bb4, unwind unreachable]; - } - - bb4: { - StorageDead(_8); +- _4 = OffsetOf(Alpha, [(0, 2), (0, 1)]); ++ _4 = const 3_usize; _0 = const (); - StorageDead(_7); - StorageDead(_5); + StorageDead(_4); StorageDead(_3); + StorageDead(_2); StorageDead(_1); return; } diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.concrete.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/offset_of.concrete.DataflowConstProp.panic-unwind.diff index d4f8cb66704..92691d0f807 100644 --- a/tests/mir-opt/dataflow-const-prop/offset_of.concrete.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/offset_of.concrete.DataflowConstProp.panic-unwind.diff @@ -4,21 +4,17 @@ fn concrete() -> () { let mut _0: (); let _1: usize; - let mut _2: usize; - let mut _4: usize; - let mut _6: usize; - let mut _8: usize; scope 1 { debug x => _1; - let _3: usize; + let _2: usize; scope 2 { - debug y => _3; - let _5: usize; + debug y => _2; + let _3: usize; scope 3 { - debug z0 => _5; - let _7: usize; + debug z0 => _3; + let _4: usize; scope 4 { - debug z1 => _7; + debug z1 => _4; } } } @@ -26,49 +22,21 @@ bb0: { StorageLive(_1); +- _1 = OffsetOf(Alpha, [(0, 0)]); ++ _1 = const 4_usize; StorageLive(_2); -- _2 = OffsetOf(Alpha, [(0, 0)]); -- _1 = must_use::<usize>(move _2) -> [return: bb1, unwind continue]; -+ _2 = const 4_usize; -+ _1 = must_use::<usize>(const 4_usize) -> [return: bb1, unwind continue]; - } - - bb1: { - StorageDead(_2); +- _2 = OffsetOf(Alpha, [(0, 1)]); ++ _2 = const 0_usize; StorageLive(_3); +- _3 = OffsetOf(Alpha, [(0, 2), (0, 0)]); ++ _3 = const 2_usize; StorageLive(_4); -- _4 = OffsetOf(Alpha, [(0, 1)]); -- _3 = must_use::<usize>(move _4) -> [return: bb2, unwind continue]; -+ _4 = const 0_usize; -+ _3 = must_use::<usize>(const 0_usize) -> [return: bb2, unwind continue]; - } - - bb2: { - StorageDead(_4); - StorageLive(_5); - StorageLive(_6); -- _6 = OffsetOf(Alpha, [(0, 2), (0, 0)]); -- _5 = must_use::<usize>(move _6) -> [return: bb3, unwind continue]; -+ _6 = const 2_usize; -+ _5 = must_use::<usize>(const 2_usize) -> [return: bb3, unwind continue]; - } - - bb3: { - StorageDead(_6); - StorageLive(_7); - StorageLive(_8); -- _8 = OffsetOf(Alpha, [(0, 2), (0, 1)]); -- _7 = must_use::<usize>(move _8) -> [return: bb4, unwind continue]; -+ _8 = const 3_usize; -+ _7 = must_use::<usize>(const 3_usize) -> [return: bb4, unwind continue]; - } - - bb4: { - StorageDead(_8); +- _4 = OffsetOf(Alpha, [(0, 2), (0, 1)]); ++ _4 = const 3_usize; _0 = const (); - StorageDead(_7); - StorageDead(_5); + StorageDead(_4); StorageDead(_3); + StorageDead(_2); StorageDead(_1); return; } diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.generic.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/offset_of.generic.DataflowConstProp.panic-abort.diff index 7f166e4fa35..c6908166def 100644 --- a/tests/mir-opt/dataflow-const-prop/offset_of.generic.DataflowConstProp.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/offset_of.generic.DataflowConstProp.panic-abort.diff @@ -4,21 +4,17 @@ fn generic() -> () { let mut _0: (); let _1: usize; - let mut _2: usize; - let mut _4: usize; - let mut _6: usize; - let mut _8: usize; scope 1 { debug gx => _1; - let _3: usize; + let _2: usize; scope 2 { - debug gy => _3; - let _5: usize; + debug gy => _2; + let _3: usize; scope 3 { - debug dx => _5; - let _7: usize; + debug dx => _3; + let _4: usize; scope 4 { - debug dy => _7; + debug dy => _4; } } } @@ -26,45 +22,19 @@ bb0: { StorageLive(_1); + _1 = OffsetOf(Gamma<T>, [(0, 0)]); StorageLive(_2); - _2 = OffsetOf(Gamma<T>, [(0, 0)]); - _1 = must_use::<usize>(move _2) -> [return: bb1, unwind unreachable]; - } - - bb1: { - StorageDead(_2); + _2 = OffsetOf(Gamma<T>, [(0, 1)]); StorageLive(_3); +- _3 = OffsetOf(Delta<T>, [(0, 1)]); ++ _3 = const 0_usize; StorageLive(_4); - _4 = OffsetOf(Gamma<T>, [(0, 1)]); - _3 = must_use::<usize>(move _4) -> [return: bb2, unwind unreachable]; - } - - bb2: { - StorageDead(_4); - StorageLive(_5); - StorageLive(_6); -- _6 = OffsetOf(Delta<T>, [(0, 1)]); -- _5 = must_use::<usize>(move _6) -> [return: bb3, unwind unreachable]; -+ _6 = const 0_usize; -+ _5 = must_use::<usize>(const 0_usize) -> [return: bb3, unwind unreachable]; - } - - bb3: { - StorageDead(_6); - StorageLive(_7); - StorageLive(_8); -- _8 = OffsetOf(Delta<T>, [(0, 2)]); -- _7 = must_use::<usize>(move _8) -> [return: bb4, unwind unreachable]; -+ _8 = const 2_usize; -+ _7 = must_use::<usize>(const 2_usize) -> [return: bb4, unwind unreachable]; - } - - bb4: { - StorageDead(_8); +- _4 = OffsetOf(Delta<T>, [(0, 2)]); ++ _4 = const 2_usize; _0 = const (); - StorageDead(_7); - StorageDead(_5); + StorageDead(_4); StorageDead(_3); + StorageDead(_2); StorageDead(_1); return; } diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.generic.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/offset_of.generic.DataflowConstProp.panic-unwind.diff index 38ad6f79801..c6908166def 100644 --- a/tests/mir-opt/dataflow-const-prop/offset_of.generic.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/offset_of.generic.DataflowConstProp.panic-unwind.diff @@ -4,21 +4,17 @@ fn generic() -> () { let mut _0: (); let _1: usize; - let mut _2: usize; - let mut _4: usize; - let mut _6: usize; - let mut _8: usize; scope 1 { debug gx => _1; - let _3: usize; + let _2: usize; scope 2 { - debug gy => _3; - let _5: usize; + debug gy => _2; + let _3: usize; scope 3 { - debug dx => _5; - let _7: usize; + debug dx => _3; + let _4: usize; scope 4 { - debug dy => _7; + debug dy => _4; } } } @@ -26,45 +22,19 @@ bb0: { StorageLive(_1); + _1 = OffsetOf(Gamma<T>, [(0, 0)]); StorageLive(_2); - _2 = OffsetOf(Gamma<T>, [(0, 0)]); - _1 = must_use::<usize>(move _2) -> [return: bb1, unwind continue]; - } - - bb1: { - StorageDead(_2); + _2 = OffsetOf(Gamma<T>, [(0, 1)]); StorageLive(_3); +- _3 = OffsetOf(Delta<T>, [(0, 1)]); ++ _3 = const 0_usize; StorageLive(_4); - _4 = OffsetOf(Gamma<T>, [(0, 1)]); - _3 = must_use::<usize>(move _4) -> [return: bb2, unwind continue]; - } - - bb2: { - StorageDead(_4); - StorageLive(_5); - StorageLive(_6); -- _6 = OffsetOf(Delta<T>, [(0, 1)]); -- _5 = must_use::<usize>(move _6) -> [return: bb3, unwind continue]; -+ _6 = const 0_usize; -+ _5 = must_use::<usize>(const 0_usize) -> [return: bb3, unwind continue]; - } - - bb3: { - StorageDead(_6); - StorageLive(_7); - StorageLive(_8); -- _8 = OffsetOf(Delta<T>, [(0, 2)]); -- _7 = must_use::<usize>(move _8) -> [return: bb4, unwind continue]; -+ _8 = const 2_usize; -+ _7 = must_use::<usize>(const 2_usize) -> [return: bb4, unwind continue]; - } - - bb4: { - StorageDead(_8); +- _4 = OffsetOf(Delta<T>, [(0, 2)]); ++ _4 = const 2_usize; _0 = const (); - StorageDead(_7); - StorageDead(_5); + StorageDead(_4); StorageDead(_3); + StorageDead(_2); StorageDead(_1); return; } diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.rs b/tests/mir-opt/dataflow-const-prop/offset_of.rs index cd4e1f6990d..12396b31ed0 100644 --- a/tests/mir-opt/dataflow-const-prop/offset_of.rs +++ b/tests/mir-opt/dataflow-const-prop/offset_of.rs @@ -36,16 +36,16 @@ fn concrete() { // CHECK: debug z0 => [[z0:_.*]]; // CHECK: debug z1 => [[z1:_.*]]; - // CHECK: [[x]] = must_use::<usize>(const 4_usize) -> {{.*}} + // CHECK: [[x]] = const 4_usize let x = offset_of!(Alpha, x); - // CHECK: [[y]] = must_use::<usize>(const 0_usize) -> {{.*}} + // CHECK: [[y]] = const 0_usize let y = offset_of!(Alpha, y); - // CHECK: [[z0]] = must_use::<usize>(const 2_usize) -> {{.*}} + // CHECK: [[z0]] = const 2_usize let z0 = offset_of!(Alpha, z.0); - // CHECK: [[z1]] = must_use::<usize>(const 3_usize) -> {{.*}} + // CHECK: [[z1]] = const 3_usize let z1 = offset_of!(Alpha, z.1); } @@ -58,16 +58,16 @@ fn generic<T>() { // CHECK: debug dx => [[dx:_.*]]; // CHECK: debug dy => [[dy:_.*]]; - // CHECK: [[gx]] = must_use::<usize>(move {{_.*}}) -> {{.*}} + // CHECK: [[gx]] = OffsetOf(Gamma<T>, [(0, 0)]); let gx = offset_of!(Gamma<T>, x); - // CHECK: [[gy]] = must_use::<usize>(move {{_.*}}) -> {{.*}} + // CHECK: [[gy]] = OffsetOf(Gamma<T>, [(0, 1)]); let gy = offset_of!(Gamma<T>, y); - // CHECK: [[dx]] = must_use::<usize>(const 0_usize) -> {{.*}} + // CHECK: [[dx]] = const 0_usize let dx = offset_of!(Delta<T>, x); - // CHECK: [[dy]] = must_use::<usize>(const 2_usize) -> {{.*}} + // CHECK: [[dy]] = const 2_usize let dy = offset_of!(Delta<T>, y); } diff --git a/tests/mir-opt/gvn.borrowed.GVN.panic-abort.diff b/tests/mir-opt/gvn.borrowed.GVN.panic-abort.diff new file mode 100644 index 00000000000..9520bd382ee --- /dev/null +++ b/tests/mir-opt/gvn.borrowed.GVN.panic-abort.diff @@ -0,0 +1,29 @@ +- // MIR for `borrowed` before GVN ++ // MIR for `borrowed` after GVN + + fn borrowed(_1: T) -> () { + let mut _0: (); + let mut _2: T; + let mut _3: &T; + + bb0: { + _2 = _1; + _3 = &_1; + _0 = opaque::<&T>(_3) -> [return: bb1, unwind unreachable]; + } + + bb1: { +- _0 = opaque::<T>(_2) -> [return: bb2, unwind unreachable]; ++ _0 = opaque::<T>(_1) -> [return: bb2, unwind unreachable]; + } + + bb2: { +- _0 = opaque::<T>((*_3)) -> [return: bb3, unwind unreachable]; ++ _0 = opaque::<T>(_1) -> [return: bb3, unwind unreachable]; + } + + bb3: { + return; + } + } + diff --git a/tests/mir-opt/gvn.borrowed.GVN.panic-unwind.diff b/tests/mir-opt/gvn.borrowed.GVN.panic-unwind.diff new file mode 100644 index 00000000000..4f5d76d5644 --- /dev/null +++ b/tests/mir-opt/gvn.borrowed.GVN.panic-unwind.diff @@ -0,0 +1,29 @@ +- // MIR for `borrowed` before GVN ++ // MIR for `borrowed` after GVN + + fn borrowed(_1: T) -> () { + let mut _0: (); + let mut _2: T; + let mut _3: &T; + + bb0: { + _2 = _1; + _3 = &_1; + _0 = opaque::<&T>(_3) -> [return: bb1, unwind continue]; + } + + bb1: { +- _0 = opaque::<T>(_2) -> [return: bb2, unwind continue]; ++ _0 = opaque::<T>(_1) -> [return: bb2, unwind continue]; + } + + bb2: { +- _0 = opaque::<T>((*_3)) -> [return: bb3, unwind continue]; ++ _0 = opaque::<T>(_1) -> [return: bb3, unwind continue]; + } + + bb3: { + return; + } + } + diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff index 02bf95840da..68cb4d55e7b 100644 --- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff @@ -8,10 +8,10 @@ let mut _3: fn(u8) -> u8; let _5: (); let mut _6: fn(u8) -> u8; - let mut _9: {closure@$DIR/gvn.rs:610:19: 610:21}; + let mut _9: {closure@$DIR/gvn.rs:612:19: 612:21}; let _10: (); let mut _11: fn(); - let mut _13: {closure@$DIR/gvn.rs:610:19: 610:21}; + let mut _13: {closure@$DIR/gvn.rs:612:19: 612:21}; let _14: (); let mut _15: fn(); scope 1 { @@ -19,7 +19,7 @@ let _4: fn(u8) -> u8; scope 2 { debug g => _4; - let _7: {closure@$DIR/gvn.rs:610:19: 610:21}; + let _7: {closure@$DIR/gvn.rs:612:19: 612:21}; scope 3 { debug closure => _7; let _8: fn(); @@ -62,16 +62,16 @@ StorageDead(_6); StorageDead(_5); - StorageLive(_7); -- _7 = {closure@$DIR/gvn.rs:610:19: 610:21}; +- _7 = {closure@$DIR/gvn.rs:612:19: 612:21}; - StorageLive(_8); + nop; -+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21}; ++ _7 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21}; + nop; StorageLive(_9); - _9 = _7; - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Normal))); -+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); ++ _9 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21}; ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); StorageDead(_9); StorageLive(_10); StorageLive(_11); @@ -88,8 +88,8 @@ StorageLive(_13); - _13 = _7; - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Normal))); -+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); ++ _13 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21}; ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); StorageDead(_13); StorageLive(_14); StorageLive(_15); diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff index c5dcc8a8ec9..fa184348b3b 100644 --- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff @@ -8,10 +8,10 @@ let mut _3: fn(u8) -> u8; let _5: (); let mut _6: fn(u8) -> u8; - let mut _9: {closure@$DIR/gvn.rs:610:19: 610:21}; + let mut _9: {closure@$DIR/gvn.rs:612:19: 612:21}; let _10: (); let mut _11: fn(); - let mut _13: {closure@$DIR/gvn.rs:610:19: 610:21}; + let mut _13: {closure@$DIR/gvn.rs:612:19: 612:21}; let _14: (); let mut _15: fn(); scope 1 { @@ -19,7 +19,7 @@ let _4: fn(u8) -> u8; scope 2 { debug g => _4; - let _7: {closure@$DIR/gvn.rs:610:19: 610:21}; + let _7: {closure@$DIR/gvn.rs:612:19: 612:21}; scope 3 { debug closure => _7; let _8: fn(); @@ -62,16 +62,16 @@ StorageDead(_6); StorageDead(_5); - StorageLive(_7); -- _7 = {closure@$DIR/gvn.rs:610:19: 610:21}; +- _7 = {closure@$DIR/gvn.rs:612:19: 612:21}; - StorageLive(_8); + nop; -+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21}; ++ _7 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21}; + nop; StorageLive(_9); - _9 = _7; - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Normal))); -+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); ++ _9 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21}; ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); StorageDead(_9); StorageLive(_10); StorageLive(_11); @@ -88,8 +88,8 @@ StorageLive(_13); - _13 = _7; - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Normal))); -+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); ++ _13 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21}; ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); StorageDead(_13); StorageLive(_14); StorageLive(_15); diff --git a/tests/mir-opt/gvn.non_freeze.GVN.panic-abort.diff b/tests/mir-opt/gvn.non_freeze.GVN.panic-abort.diff new file mode 100644 index 00000000000..7b6ed096118 --- /dev/null +++ b/tests/mir-opt/gvn.non_freeze.GVN.panic-abort.diff @@ -0,0 +1,27 @@ +- // MIR for `non_freeze` before GVN ++ // MIR for `non_freeze` after GVN + + fn non_freeze(_1: T) -> () { + let mut _0: (); + let mut _2: T; + let mut _3: &T; + + bb0: { + _2 = _1; + _3 = &_1; + _0 = opaque::<&T>(_3) -> [return: bb1, unwind unreachable]; + } + + bb1: { + _0 = opaque::<T>(_2) -> [return: bb2, unwind unreachable]; + } + + bb2: { + _0 = opaque::<T>((*_3)) -> [return: bb3, unwind unreachable]; + } + + bb3: { + return; + } + } + diff --git a/tests/mir-opt/gvn.non_freeze.GVN.panic-unwind.diff b/tests/mir-opt/gvn.non_freeze.GVN.panic-unwind.diff new file mode 100644 index 00000000000..641a2f4609a --- /dev/null +++ b/tests/mir-opt/gvn.non_freeze.GVN.panic-unwind.diff @@ -0,0 +1,27 @@ +- // MIR for `non_freeze` before GVN ++ // MIR for `non_freeze` after GVN + + fn non_freeze(_1: T) -> () { + let mut _0: (); + let mut _2: T; + let mut _3: &T; + + bb0: { + _2 = _1; + _3 = &_1; + _0 = opaque::<&T>(_3) -> [return: bb1, unwind continue]; + } + + bb1: { + _0 = opaque::<T>(_2) -> [return: bb2, unwind continue]; + } + + bb2: { + _0 = opaque::<T>((*_3)) -> [return: bb3, unwind continue]; + } + + bb3: { + return; + } + } + diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index 0484710f00e..9be30515283 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -6,9 +6,11 @@ #![feature(rustc_attrs)] #![feature(custom_mir)] #![feature(core_intrinsics)] +#![feature(freeze)] #![allow(unconditional_panic)] use std::intrinsics::mir::*; +use std::marker::Freeze; use std::mem::transmute; struct S<T>(T); @@ -720,6 +722,65 @@ fn wide_ptr_integer() { opaque(a >= b); } +#[custom_mir(dialect = "analysis", phase = "post-cleanup")] +fn borrowed<T: Copy + Freeze>(x: T) { + // CHECK-LABEL: fn borrowed( + // CHECK: bb0: { + // CHECK-NEXT: _2 = _1; + // CHECK-NEXT: _3 = &_1; + // CHECK-NEXT: _0 = opaque::<&T>(_3) + // CHECK: bb1: { + // CHECK-NEXT: _0 = opaque::<T>(_1) + // CHECK: bb2: { + // CHECK-NEXT: _0 = opaque::<T>(_1) + mir!( + { + let a = x; + let r1 = &x; + Call(RET = opaque(r1), ReturnTo(next), UnwindContinue()) + } + next = { + Call(RET = opaque(a), ReturnTo(deref), UnwindContinue()) + } + deref = { + Call(RET = opaque(*r1), ReturnTo(ret), UnwindContinue()) + } + ret = { + Return() + } + ) +} + +/// Generic type `T` is not known to be `Freeze`, so shared borrows may be mutable. +#[custom_mir(dialect = "analysis", phase = "post-cleanup")] +fn non_freeze<T: Copy>(x: T) { + // CHECK-LABEL: fn non_freeze( + // CHECK: bb0: { + // CHECK-NEXT: _2 = _1; + // CHECK-NEXT: _3 = &_1; + // CHECK-NEXT: _0 = opaque::<&T>(_3) + // CHECK: bb1: { + // CHECK-NEXT: _0 = opaque::<T>(_2) + // CHECK: bb2: { + // CHECK-NEXT: _0 = opaque::<T>((*_3)) + mir!( + { + let a = x; + let r1 = &x; + Call(RET = opaque(r1), ReturnTo(next), UnwindContinue()) + } + next = { + Call(RET = opaque(a), ReturnTo(deref), UnwindContinue()) + } + deref = { + Call(RET = opaque(*r1), ReturnTo(ret), UnwindContinue()) + } + ret = { + Return() + } + ) +} + fn main() { subexpression_elimination(2, 4, 5); wrap_unwrap(5); @@ -742,6 +803,8 @@ fn main() { constant_index_overflow(&[5, 3]); wide_ptr_provenance(); wide_ptr_integer(); + borrowed(5); + non_freeze(5); } #[inline(never)] @@ -773,3 +836,5 @@ fn identity<T>(x: T) -> T { // EMIT_MIR gvn.wide_ptr_provenance.GVN.diff // EMIT_MIR gvn.wide_ptr_same_provenance.GVN.diff // EMIT_MIR gvn.wide_ptr_integer.GVN.diff +// EMIT_MIR gvn.borrowed.GVN.diff +// EMIT_MIR gvn.non_freeze.GVN.diff diff --git a/tests/mir-opt/gvn.slices.GVN.panic-abort.diff b/tests/mir-opt/gvn.slices.GVN.panic-abort.diff index 2389d98b5b3..fb67e3d5994 100644 --- a/tests/mir-opt/gvn.slices.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.slices.GVN.panic-abort.diff @@ -111,8 +111,9 @@ StorageLive(_7); StorageLive(_8); - StorageLive(_9); +- StorageLive(_10); ++ nop; + nop; - StorageLive(_10); StorageLive(_11); _11 = &(*_1); _10 = core::str::<impl str>::as_ptr(move _11) -> [return: bb3, unwind unreachable]; @@ -122,8 +123,9 @@ StorageDead(_11); _9 = &_10; - StorageLive(_12); +- StorageLive(_13); ++ nop; + nop; - StorageLive(_13); StorageLive(_14); - _14 = &(*_4); + _14 = &(*_1); @@ -148,11 +150,12 @@ StorageLive(_17); StorageLive(_18); - _18 = (*_15); -+ _18 = (*_9); ++ _18 = _10; StorageLive(_19); - _19 = (*_16); -+ _19 = (*_12); - _17 = Eq(move _18, move _19); +- _17 = Eq(move _18, move _19); ++ _19 = _13; ++ _17 = Eq(_10, _13); switchInt(move _17) -> [0: bb6, otherwise: bb5]; } @@ -163,8 +166,10 @@ StorageDead(_17); StorageDead(_16); StorageDead(_15); - StorageDead(_13); - StorageDead(_10); +- StorageDead(_13); +- StorageDead(_10); ++ nop; ++ nop; StorageDead(_8); StorageDead(_7); - StorageLive(_29); @@ -213,8 +218,9 @@ StorageLive(_33); StorageLive(_34); - StorageLive(_35); +- StorageLive(_36); ++ nop; + nop; - StorageLive(_36); StorageLive(_37); _37 = &(*_1); _36 = core::str::<impl str>::as_ptr(move _37) -> [return: bb8, unwind unreachable]; @@ -224,8 +230,9 @@ StorageDead(_37); _35 = &_36; - StorageLive(_38); +- StorageLive(_39); ++ nop; + nop; - StorageLive(_39); StorageLive(_40); _40 = &(*_29); _39 = core::slice::<impl [u8]>::as_ptr(move _40) -> [return: bb9, unwind unreachable]; @@ -249,11 +256,12 @@ StorageLive(_43); StorageLive(_44); - _44 = (*_41); -+ _44 = (*_35); ++ _44 = _36; StorageLive(_45); - _45 = (*_42); -+ _45 = (*_38); - _43 = Eq(move _44, move _45); +- _43 = Eq(move _44, move _45); ++ _45 = _39; ++ _43 = Eq(_36, _39); switchInt(move _43) -> [0: bb11, otherwise: bb10]; } @@ -264,8 +272,10 @@ StorageDead(_43); StorageDead(_42); StorageDead(_41); - StorageDead(_39); - StorageDead(_36); +- StorageDead(_39); +- StorageDead(_36); ++ nop; ++ nop; StorageDead(_34); StorageDead(_33); _0 = const (); diff --git a/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff b/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff index 50715d748e7..ae3013b011e 100644 --- a/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff @@ -111,8 +111,9 @@ StorageLive(_7); StorageLive(_8); - StorageLive(_9); +- StorageLive(_10); ++ nop; + nop; - StorageLive(_10); StorageLive(_11); _11 = &(*_1); _10 = core::str::<impl str>::as_ptr(move _11) -> [return: bb3, unwind continue]; @@ -122,8 +123,9 @@ StorageDead(_11); _9 = &_10; - StorageLive(_12); +- StorageLive(_13); ++ nop; + nop; - StorageLive(_13); StorageLive(_14); - _14 = &(*_4); + _14 = &(*_1); @@ -148,11 +150,12 @@ StorageLive(_17); StorageLive(_18); - _18 = (*_15); -+ _18 = (*_9); ++ _18 = _10; StorageLive(_19); - _19 = (*_16); -+ _19 = (*_12); - _17 = Eq(move _18, move _19); +- _17 = Eq(move _18, move _19); ++ _19 = _13; ++ _17 = Eq(_10, _13); switchInt(move _17) -> [0: bb6, otherwise: bb5]; } @@ -163,8 +166,10 @@ StorageDead(_17); StorageDead(_16); StorageDead(_15); - StorageDead(_13); - StorageDead(_10); +- StorageDead(_13); +- StorageDead(_10); ++ nop; ++ nop; StorageDead(_8); StorageDead(_7); - StorageLive(_29); @@ -213,8 +218,9 @@ StorageLive(_33); StorageLive(_34); - StorageLive(_35); +- StorageLive(_36); ++ nop; + nop; - StorageLive(_36); StorageLive(_37); _37 = &(*_1); _36 = core::str::<impl str>::as_ptr(move _37) -> [return: bb8, unwind continue]; @@ -224,8 +230,9 @@ StorageDead(_37); _35 = &_36; - StorageLive(_38); +- StorageLive(_39); ++ nop; + nop; - StorageLive(_39); StorageLive(_40); _40 = &(*_29); _39 = core::slice::<impl [u8]>::as_ptr(move _40) -> [return: bb9, unwind continue]; @@ -249,11 +256,12 @@ StorageLive(_43); StorageLive(_44); - _44 = (*_41); -+ _44 = (*_35); ++ _44 = _36; StorageLive(_45); - _45 = (*_42); -+ _45 = (*_38); - _43 = Eq(move _44, move _45); +- _43 = Eq(move _44, move _45); ++ _45 = _39; ++ _43 = Eq(_36, _39); switchInt(move _43) -> [0: bb11, otherwise: bb10]; } @@ -264,8 +272,10 @@ StorageDead(_43); StorageDead(_42); StorageDead(_41); - StorageDead(_39); - StorageDead(_36); +- StorageDead(_39); +- StorageDead(_36); ++ nop; ++ nop; StorageDead(_34); StorageDead(_33); _0 = const (); diff --git a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff index c5ee0d9c44d..626367766d7 100644 --- a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff @@ -17,7 +17,8 @@ StorageLive(_3); _5 = const f::promoted[0]; _3 = &(*_5); - _2 = ((*_3).1: E); +- _2 = ((*_3).1: E); ++ _2 = ((*_5).1: E); StorageLive(_1); - _1 = ((_2 as A).1: u32); + _1 = const 0_u32; diff --git a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff index c5ee0d9c44d..626367766d7 100644 --- a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff @@ -17,7 +17,8 @@ StorageLive(_3); _5 = const f::promoted[0]; _3 = &(*_5); - _2 = ((*_3).1: E); +- _2 = ((*_3).1: E); ++ _2 = ((*_5).1: E); StorageLive(_1); - _1 = ((_2 as A).1: u32); + _1 = const 0_u32; diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir index 65cac0a81ef..dfa13230254 100644 --- a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir @@ -10,18 +10,18 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 let mut _8: &&usize; let _9: &usize; let mut _10: &&usize; - let mut _15: bool; + let mut _13: bool; + let mut _14: &&usize; + let _15: &usize; let mut _16: &&usize; - let _17: &usize; - let mut _18: &&usize; + let mut _19: bool; + let mut _20: &&usize; + let _21: &usize; + let mut _22: &&usize; let mut _23: bool; let mut _24: &&usize; let _25: &usize; let mut _26: &&usize; - let mut _31: bool; - let mut _32: &&usize; - let _33: &usize; - let mut _34: &&usize; scope 1 { debug a => _4; debug b => _5; @@ -30,208 +30,145 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 scope 2 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) { debug self => _8; debug other => _10; - let mut _11: &usize; - let mut _12: &usize; scope 3 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) { - debug self => _11; - debug other => _12; - let mut _13: usize; - let mut _14: usize; + debug self => _4; + debug other => _9; + let mut _11: usize; + let mut _12: usize; } } scope 4 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) { - debug self => _16; - debug other => _18; - let mut _19: &usize; - let mut _20: &usize; + debug self => _14; + debug other => _16; scope 5 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) { - debug self => _19; - debug other => _20; - let mut _21: usize; - let mut _22: usize; + debug self => _7; + debug other => _15; + let mut _17: usize; + let mut _18: usize; } } scope 6 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) { - debug self => _24; - debug other => _26; - let mut _27: &usize; - let mut _28: &usize; + debug self => _20; + debug other => _22; scope 7 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) { - debug self => _27; - debug other => _28; - let mut _29: usize; - let mut _30: usize; + debug self => _6; + debug other => _21; } } scope 8 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) { - debug self => _32; - debug other => _34; - let mut _35: &usize; - let mut _36: &usize; + debug self => _24; + debug other => _26; scope 9 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) { - debug self => _35; - debug other => _36; - let mut _37: usize; - let mut _38: usize; + debug self => _5; + debug other => _25; + let mut _27: usize; + let mut _28: usize; } } } bb0: { - StorageLive(_4); _3 = (*_2); _4 = &((*_3).0: usize); - StorageLive(_5); _5 = &((*_3).1: usize); - StorageLive(_6); _6 = &((*_3).2: usize); - StorageLive(_7); _7 = &((*_3).3: usize); - StorageLive(_15); + StorageLive(_13); StorageLive(_8); _8 = &_4; StorageLive(_10); - StorageLive(_9); - _9 = _6; + _9 = &((*_3).2: usize); _10 = &_9; - StorageLive(_11); - StorageLive(_12); - _11 = _4; - _12 = _9; - StorageLive(_13); - _13 = (*_11); - StorageLive(_14); - _14 = (*_12); - _15 = Le(move _13, move _14); - StorageDead(_14); - StorageDead(_13); - StorageDead(_12); - StorageDead(_11); - switchInt(move _15) -> [0: bb1, otherwise: bb2]; + _11 = ((*_3).0: usize); + _12 = ((*_3).2: usize); + _13 = Le(_11, _12); + switchInt(move _13) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageDead(_9); StorageDead(_10); StorageDead(_8); goto -> bb4; } bb2: { - StorageDead(_9); StorageDead(_10); StorageDead(_8); - StorageLive(_23); + StorageLive(_19); + StorageLive(_14); + _14 = &_7; StorageLive(_16); - _16 = &_7; - StorageLive(_18); + _15 = &((*_3).1: usize); + _16 = &_15; StorageLive(_17); - _17 = _5; - _18 = &_17; - StorageLive(_19); - StorageLive(_20); - _19 = _7; - _20 = _17; - StorageLive(_21); - _21 = (*_19); - StorageLive(_22); - _22 = (*_20); - _23 = Le(move _21, move _22); - StorageDead(_22); - StorageDead(_21); - StorageDead(_20); - StorageDead(_19); - switchInt(move _23) -> [0: bb3, otherwise: bb8]; + _17 = ((*_3).3: usize); + StorageLive(_18); + _18 = ((*_3).1: usize); + _19 = Le(move _17, move _18); + StorageDead(_18); + StorageDead(_17); + switchInt(move _19) -> [0: bb3, otherwise: bb8]; } bb3: { - StorageDead(_17); - StorageDead(_18); StorageDead(_16); + StorageDead(_14); goto -> bb4; } bb4: { - StorageLive(_31); - StorageLive(_24); - _24 = &_6; - StorageLive(_26); - StorageLive(_25); - _25 = _4; - _26 = &_25; - StorageLive(_27); - StorageLive(_28); - _27 = _6; - _28 = _25; - StorageLive(_29); - _29 = (*_27); - StorageLive(_30); - _30 = (*_28); - _31 = Le(move _29, move _30); - StorageDead(_30); - StorageDead(_29); - StorageDead(_28); - StorageDead(_27); - switchInt(move _31) -> [0: bb5, otherwise: bb6]; + StorageLive(_23); + StorageLive(_20); + _20 = &_6; + StorageLive(_22); + _21 = &((*_3).0: usize); + _22 = &_21; + _23 = Le(_12, _11); + switchInt(move _23) -> [0: bb5, otherwise: bb6]; } bb5: { - StorageDead(_25); - StorageDead(_26); - StorageDead(_24); + StorageDead(_22); + StorageDead(_20); _0 = const false; goto -> bb7; } bb6: { - StorageDead(_25); + StorageDead(_22); + StorageDead(_20); + StorageLive(_24); + _24 = &_5; + StorageLive(_26); + _25 = &((*_3).3: usize); + _26 = &_25; + StorageLive(_27); + _27 = ((*_3).1: usize); + StorageLive(_28); + _28 = ((*_3).3: usize); + _0 = Le(move _27, move _28); + StorageDead(_28); + StorageDead(_27); StorageDead(_26); StorageDead(_24); - StorageLive(_32); - _32 = &_5; - StorageLive(_34); - StorageLive(_33); - _33 = _7; - _34 = &_33; - StorageLive(_35); - StorageLive(_36); - _35 = _5; - _36 = _33; - StorageLive(_37); - _37 = (*_35); - StorageLive(_38); - _38 = (*_36); - _0 = Le(move _37, move _38); - StorageDead(_38); - StorageDead(_37); - StorageDead(_36); - StorageDead(_35); - StorageDead(_33); - StorageDead(_34); - StorageDead(_32); goto -> bb7; } bb7: { - StorageDead(_31); + StorageDead(_23); goto -> bb9; } bb8: { - StorageDead(_17); - StorageDead(_18); StorageDead(_16); + StorageDead(_14); _0 = const true; goto -> bb9; } bb9: { - StorageDead(_23); - StorageDead(_15); - StorageDead(_7); - StorageDead(_6); - StorageDead(_5); - StorageDead(_4); + StorageDead(_19); + StorageDead(_13); return; } } diff --git a/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff index 1be2ce8d0bb..0dfe8781c18 100644 --- a/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff @@ -247,7 +247,8 @@ StorageLive(_21); _21 = &_20; StorageLive(_22); - _22 = (*_20); +- _22 = (*_20); ++ _22 = _19; StorageLive(_23); StorageLive(_24); _24 = _21; @@ -394,7 +395,8 @@ StorageLive(_62); _62 = &_61; StorageLive(_63); - _63 = (*_61); +- _63 = (*_61); ++ _63 = _60; StorageLive(_64); StorageLive(_65); _65 = (); diff --git a/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff index 1e6a168f756..21486a8616a 100644 --- a/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff @@ -260,7 +260,8 @@ StorageLive(_20); _20 = &_19; StorageLive(_21); - _21 = (*_19); +- _21 = (*_19); ++ _21 = _18; StorageLive(_22); StorageLive(_23); _23 = _20; @@ -429,7 +430,8 @@ StorageLive(_67); _67 = &_66; StorageLive(_68); - _68 = (*_66); +- _68 = (*_66); ++ _68 = _65; StorageLive(_69); StorageLive(_70); _70 = (); diff --git a/tests/mir-opt/reference_prop.rs b/tests/mir-opt/reference_prop.rs index 2dda771ba7d..e0b0d699420 100644 --- a/tests/mir-opt/reference_prop.rs +++ b/tests/mir-opt/reference_prop.rs @@ -49,7 +49,7 @@ fn reference_propagation<'a, T: Copy>(single: &'a T, mut multiple: &'a T) { // CHECK: [[a:_.*]] = const 5_usize; // CHECK: [[b:_.*]] = &[[a]]; // CHECK: [[d:_.*]] = &[[b]]; - // CHECK: [[c:_.*]] = (*[[b]]); + // CHECK: [[c:_.*]] = [[a]]; let a = 5_usize; let b = &a; @@ -138,8 +138,7 @@ fn reference_propagation<'a, T: Copy>(single: &'a T, mut multiple: &'a T) { // CHECK: [[a:_.*]] = const 5_usize; // CHECK: [[b:_.*]] = &[[a]]; // CHECK: [[d:_.*]] = &[[b]]; - // FIXME this could be [[a]] - // CHECK: [[c:_.*]] = (*[[b]]); + // CHECK: [[c:_.*]] = [[a]]; let a = 5_usize; let b = &a; @@ -363,7 +362,7 @@ fn reference_propagation_const_ptr<T: Copy>(single: *const T, mut multiple: *con // CHECK: [[a:_.*]] = const 5_usize; // CHECK: [[b:_.*]] = &raw const [[a]]; // CHECK: [[d:_.*]] = &[[b]]; - // CHECK: [[c:_.*]] = (*[[b]]); + // CHECK: [[c:_.*]] = [[a]]; let a = 5_usize; let b = &raw const a; @@ -467,8 +466,7 @@ fn reference_propagation_const_ptr<T: Copy>(single: *const T, mut multiple: *con // CHECK: [[a:_.*]] = const 5_usize; // CHECK: [[b:_.*]] = &raw const [[a]]; // CHECK: [[d:_.*]] = &[[b]]; - // FIXME this could be [[a]] - // CHECK: [[c:_.*]] = (*[[b]]); + // CHECK: [[c:_.*]] = [[a]]; let a = 5_usize; let b = &raw const a; diff --git a/tests/pretty/postfix-match/precedence.pp b/tests/pretty/postfix-match/precedence.pp new file mode 100644 index 00000000000..967aa7bc39e --- /dev/null +++ b/tests/pretty/postfix-match/precedence.pp @@ -0,0 +1,34 @@ +#![feature(prelude_import)] +#![no_std] +#![feature(postfix_match)] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +use std::ops::Add; + +//@ pretty-mode:expanded +//@ pp-exact:precedence.pp + +macro_rules! repro { ($e:expr) => { $e.match { _ => {} } }; } + +struct Struct {} + +impl Add<Struct> for usize { + type Output = (); + fn add(self, _: Struct) -> () { () } +} +pub fn main() { + let a; + ( + { 1 } + 1).match { + _ => {} + }; + (4 as usize).match { _ => {} }; + (return).match { _ => {} }; + (a = 42).match { _ => {} }; + (|| {}).match { _ => {} }; + (42..101).match { _ => {} }; + (1 + Struct {}).match { _ => {} }; +} diff --git a/tests/pretty/postfix-match/precedence.rs b/tests/pretty/postfix-match/precedence.rs new file mode 100644 index 00000000000..ee947e161dd --- /dev/null +++ b/tests/pretty/postfix-match/precedence.rs @@ -0,0 +1,34 @@ +#![feature(postfix_match)] + +use std::ops::Add; + +//@ pretty-mode:expanded +//@ pp-exact:precedence.pp + +macro_rules! repro { + ($e:expr) => { + $e.match { + _ => {} + } + }; +} + +struct Struct {} + +impl Add<Struct> for usize { + type Output = (); + fn add(self, _: Struct) -> () { + () + } +} +pub fn main() { + let a; + + repro!({ 1 } + 1); + repro!(4 as usize); + repro!(return); + repro!(a = 42); + repro!(|| {}); + repro!(42..101); + repro!(1 + Struct {}); +} diff --git a/tests/pretty/postfix-match.rs b/tests/pretty/postfix-match/simple-matches.rs index 5bb54e15275..5bb54e15275 100644 --- a/tests/pretty/postfix-match.rs +++ b/tests/pretty/postfix-match/simple-matches.rs diff --git a/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs b/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs index 1204260a2f4..4b7ce4e57d5 100644 --- a/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs +++ b/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs @@ -3,11 +3,9 @@ // Check that the `CURRENT_RUSTC_VERSION` placeholder is correctly replaced by the current // `rustc` version and the `since` property in feature stability gating is properly respected. -extern crate run_make_support; - use std::path::PathBuf; -use run_make_support::{rustc, aux_build}; +use run_make_support::{aux_build, rustc}; fn main() { aux_build().input("stable.rs").emit("metadata").run(); @@ -15,11 +13,7 @@ fn main() { let mut stable_path = PathBuf::from(env!("TMPDIR")); stable_path.push("libstable.rmeta"); - let output = rustc() - .input("main.rs") - .emit("metadata") - .extern_("stable", &stable_path) - .output(); + let output = rustc().input("main.rs").emit("metadata").extern_("stable", &stable_path).output(); let stderr = String::from_utf8_lossy(&output.stderr); let version = include_str!(concat!(env!("S"), "/src/version")); diff --git a/tests/run-make/a-b-a-linker-guard/rmake.rs b/tests/run-make/a-b-a-linker-guard/rmake.rs index ffc1b2000b9..ee6d655bc76 100644 --- a/tests/run-make/a-b-a-linker-guard/rmake.rs +++ b/tests/run-make/a-b-a-linker-guard/rmake.rs @@ -3,8 +3,6 @@ // Test that if we build `b` against a version of `a` that has one set of types, it will not run // with a dylib that has a different set of types. -extern crate run_make_support; - use run_make_support::{run, run_fail, rustc}; fn main() { diff --git a/tests/run-make/arguments-non-c-like-enum/rmake.rs b/tests/run-make/arguments-non-c-like-enum/rmake.rs index 624a7fb2251..13230206ca8 100644 --- a/tests/run-make/arguments-non-c-like-enum/rmake.rs +++ b/tests/run-make/arguments-non-c-like-enum/rmake.rs @@ -1,8 +1,6 @@ //! Check that non-trivial `repr(C)` enum in Rust has valid C layout. //@ ignore-cross-compile -extern crate run_make_support; - use run_make_support::{cc, extra_c_flags, extra_cxx_flags, run, rustc, static_lib}; pub fn main() { diff --git a/tests/run-make/artifact-incr-cache-no-obj/rmake.rs b/tests/run-make/artifact-incr-cache-no-obj/rmake.rs index de55de2a1ee..6613698ae1d 100644 --- a/tests/run-make/artifact-incr-cache-no-obj/rmake.rs +++ b/tests/run-make/artifact-incr-cache-no-obj/rmake.rs @@ -5,8 +5,6 @@ // // Fixes: rust-lang/rust#123234 -extern crate run_make_support; - use run_make_support::{rustc, tmp_dir}; fn main() { diff --git a/tests/run-make/artifact-incr-cache/rmake.rs b/tests/run-make/artifact-incr-cache/rmake.rs index bb651368081..106f363eb8d 100644 --- a/tests/run-make/artifact-incr-cache/rmake.rs +++ b/tests/run-make/artifact-incr-cache/rmake.rs @@ -7,8 +7,6 @@ // Also see discussion at // <https://internals.rust-lang.org/t/interaction-between-incremental-compilation-and-emit/20551> -extern crate run_make_support; - use run_make_support::{rustc, tmp_dir}; fn main() { diff --git a/tests/run-make/compiler-builtins/rmake.rs b/tests/run-make/compiler-builtins/rmake.rs index 97ff12877f1..f5da50ebb04 100644 --- a/tests/run-make/compiler-builtins/rmake.rs +++ b/tests/run-make/compiler-builtins/rmake.rs @@ -14,8 +14,6 @@ #![deny(warnings)] -extern crate run_make_support; - use run_make_support::object; use run_make_support::object::read::archive::ArchiveFile; use run_make_support::object::read::Object; @@ -51,22 +49,22 @@ fn main() { let bootstrap_cargo = std::env::var("BOOTSTRAP_CARGO").unwrap(); let mut cmd = std::process::Command::new(bootstrap_cargo); cmd.args([ - "build", - "--manifest-path", - manifest_path.to_str().unwrap(), - "-Zbuild-std=core", - "--target", - &target, - ]) - .env_clear() - .env("PATH", path) - .env("RUSTC", rustc) - .env("RUSTFLAGS", "-Copt-level=0 -Cdebug-assertions=yes") - .env("CARGO_TARGET_DIR", &target_dir) - .env("RUSTC_BOOTSTRAP", "1") - // Visual Studio 2022 requires that the LIB env var be set so it can - // find the Windows SDK. - .env("LIB", std::env::var("LIB").unwrap_or_default()); + "build", + "--manifest-path", + manifest_path.to_str().unwrap(), + "-Zbuild-std=core", + "--target", + &target, + ]) + .env_clear() + .env("PATH", path) + .env("RUSTC", rustc) + .env("RUSTFLAGS", "-Copt-level=0 -Cdebug-assertions=yes") + .env("CARGO_TARGET_DIR", &target_dir) + .env("RUSTC_BOOTSTRAP", "1") + // Visual Studio 2022 requires that the LIB env var be set so it can + // find the Windows SDK. + .env("LIB", std::env::var("LIB").unwrap_or_default()); set_host_rpath(&mut cmd); let status = cmd.status().unwrap(); diff --git a/tests/run-make/core-no-fp-fmt-parse/rmake.rs b/tests/run-make/core-no-fp-fmt-parse/rmake.rs index 2748d4359c3..e3484888ca5 100644 --- a/tests/run-make/core-no-fp-fmt-parse/rmake.rs +++ b/tests/run-make/core-no-fp-fmt-parse/rmake.rs @@ -1,8 +1,6 @@ // This test checks that the core library of Rust can be compiled without enabling // support for formatting and parsing floating-point numbers. -extern crate run_make_support; - use run_make_support::rustc; use std::path::PathBuf; diff --git a/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs b/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs index b534a99f8cf..61f32762d8b 100644 --- a/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs +++ b/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs @@ -2,7 +2,6 @@ //! which requires extra `target-abi` metadata to be emitted. //@ needs-matching-clang //@ needs-llvm-components riscv -extern crate run_make_support; use run_make_support::{bin_name, clang, llvm_readobj, rustc, tmp_dir}; use std::{ diff --git a/tests/run-make/doctests-keep-binaries/Makefile b/tests/run-make/doctests-keep-binaries/Makefile deleted file mode 100644 index 2c647851ad0..00000000000 --- a/tests/run-make/doctests-keep-binaries/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -# Check that valid binaries are persisted by running them, regardless of whether the --run or --no-run option is used. - -MY_SRC_DIR := ${CURDIR} - -all: run no_run test_run_directory - -run: - mkdir -p $(TMPDIR)/doctests - $(RUSTC) --crate-type rlib t.rs - $(RUSTDOC) -Zunstable-options --test --persist-doctests $(TMPDIR)/doctests --extern t=$(TMPDIR)/libt.rlib t.rs - $(TMPDIR)/doctests/t_rs_2_0/rust_out - $(TMPDIR)/doctests/t_rs_8_0/rust_out - rm -rf $(TMPDIR)/doctests - -no_run: - mkdir -p $(TMPDIR)/doctests - $(RUSTC) --crate-type rlib t.rs - $(RUSTDOC) -Zunstable-options --test --persist-doctests $(TMPDIR)/doctests --extern t=$(TMPDIR)/libt.rlib t.rs --no-run - $(TMPDIR)/doctests/t_rs_2_0/rust_out - $(TMPDIR)/doctests/t_rs_8_0/rust_out - rm -rf $(TMPDIR)/doctests - -# Behavior with --test-run-directory with relative paths. -test_run_directory: - mkdir -p $(TMPDIR)/doctests - mkdir -p $(TMPDIR)/rundir - $(RUSTC) --crate-type rlib t.rs - ( cd $(TMPDIR); \ - $(RUSTDOC) -Zunstable-options --test --persist-doctests doctests --test-run-directory rundir --extern t=libt.rlib $(MY_SRC_DIR)/t.rs ) - rm -rf $(TMPDIR)/doctests $(TMPDIR)/rundir diff --git a/tests/run-make/doctests-keep-binaries/rmake.rs b/tests/run-make/doctests-keep-binaries/rmake.rs new file mode 100644 index 00000000000..ad0c2764df7 --- /dev/null +++ b/tests/run-make/doctests-keep-binaries/rmake.rs @@ -0,0 +1,68 @@ +// Check that valid binaries are persisted by running them, regardless of whether the +// --run or --no-run option is used. + +use run_make_support::{run, rustc, rustdoc, tmp_dir}; +use std::fs::{create_dir, remove_dir_all}; +use std::path::Path; + +fn setup_test_env<F: FnOnce(&Path, &Path)>(callback: F) { + let out_dir = tmp_dir().join("doctests"); + create_dir(&out_dir).expect("failed to create doctests folder"); + rustc().input("t.rs").crate_type("rlib").run(); + callback(&out_dir, &tmp_dir().join("libt.rlib")); + remove_dir_all(out_dir); +} + +fn check_generated_binaries() { + run("doctests/t_rs_2_0/rust_out"); + run("doctests/t_rs_8_0/rust_out"); +} + +fn main() { + setup_test_env(|out_dir, extern_path| { + rustdoc() + .input("t.rs") + .arg("-Zunstable-options") + .arg("--test") + .arg("--persist-doctests") + .arg(out_dir) + .arg("--extern") + .arg(format!("t={}", extern_path.display())) + .run(); + check_generated_binaries(); + }); + setup_test_env(|out_dir, extern_path| { + rustdoc() + .input("t.rs") + .arg("-Zunstable-options") + .arg("--test") + .arg("--persist-doctests") + .arg(out_dir) + .arg("--extern") + .arg(format!("t={}", extern_path.display())) + .arg("--no-run") + .run(); + check_generated_binaries(); + }); + // Behavior with --test-run-directory with relative paths. + setup_test_env(|_out_dir, extern_path| { + let run_dir = "rundir"; + let run_dir_path = tmp_dir().join("rundir"); + create_dir(&run_dir_path).expect("failed to create rundir folder"); + + rustdoc() + .current_dir(tmp_dir()) + .input(std::env::current_dir().unwrap().join("t.rs")) + .arg("-Zunstable-options") + .arg("--test") + .arg("--persist-doctests") + .arg("doctests") + .arg("--test-run-directory") + .arg(run_dir) + .arg("--extern") + .arg("t=libt.rlib") + .run(); + + remove_dir_all(run_dir_path); + }); +} diff --git a/tests/run-make/exit-code/rmake.rs b/tests/run-make/exit-code/rmake.rs index f387626287e..b1143153d0a 100644 --- a/tests/run-make/exit-code/rmake.rs +++ b/tests/run-make/exit-code/rmake.rs @@ -1,21 +1,13 @@ // Test that we exit with the correct exit code for successful / unsuccessful / ICE compilations -extern crate run_make_support; - use run_make_support::{rustc, rustdoc, tmp_dir}; fn main() { - rustc() - .arg("success.rs") - .run(); + rustc().arg("success.rs").run(); - rustc() - .arg("--invalid-arg-foo") - .run_fail_assert_exit_code(1); + rustc().arg("--invalid-arg-foo").run_fail_assert_exit_code(1); - rustc() - .arg("compile-error.rs") - .run_fail_assert_exit_code(1); + rustc().arg("compile-error.rs").run_fail_assert_exit_code(1); rustc() .env("RUSTC_ICE", "0") @@ -23,21 +15,11 @@ fn main() { .arg("compile-error.rs") .run_fail_assert_exit_code(101); - rustdoc() - .arg("success.rs") - .arg("-o") - .arg(tmp_dir().join("exit-code")) - .run(); + rustdoc().arg("success.rs").arg("-o").arg(tmp_dir().join("exit-code")).run(); - rustdoc() - .arg("--invalid-arg-foo") - .run_fail_assert_exit_code(1); + rustdoc().arg("--invalid-arg-foo").run_fail_assert_exit_code(1); - rustdoc() - .arg("compile-error.rs") - .run_fail_assert_exit_code(1); + rustdoc().arg("compile-error.rs").run_fail_assert_exit_code(1); - rustdoc() - .arg("lint-failure.rs") - .run_fail_assert_exit_code(1); + rustdoc().arg("lint-failure.rs").run_fail_assert_exit_code(1); } diff --git a/tests/run-make/issue-107495-archive-permissions/rmake.rs b/tests/run-make/issue-107495-archive-permissions/rmake.rs index 40deabe15b7..db25e9b033c 100644 --- a/tests/run-make/issue-107495-archive-permissions/rmake.rs +++ b/tests/run-make/issue-107495-archive-permissions/rmake.rs @@ -2,7 +2,6 @@ #[cfg(unix)] extern crate libc; -extern crate run_make_support; use run_make_support::{aux_build, tmp_dir}; use std::fs; diff --git a/tests/run-make/no-input-file/rmake.rs b/tests/run-make/no-input-file/rmake.rs index 26df7e80dfb..15e582311f0 100644 --- a/tests/run-make/no-input-file/rmake.rs +++ b/tests/run-make/no-input-file/rmake.rs @@ -1,5 +1,3 @@ -extern crate run_make_support; - use run_make_support::{diff, rustc}; fn main() { diff --git a/tests/run-make/non-unicode-env/rmake.rs b/tests/run-make/non-unicode-env/rmake.rs index ba4aa1609b5..a4843a52efd 100644 --- a/tests/run-make/non-unicode-env/rmake.rs +++ b/tests/run-make/non-unicode-env/rmake.rs @@ -1,5 +1,3 @@ -extern crate run_make_support; - use run_make_support::rustc; fn main() { diff --git a/tests/run-make/non-unicode-in-incremental-dir/rmake.rs b/tests/run-make/non-unicode-in-incremental-dir/rmake.rs index 129e424f27a..40152e0411d 100644 --- a/tests/run-make/non-unicode-in-incremental-dir/rmake.rs +++ b/tests/run-make/non-unicode-in-incremental-dir/rmake.rs @@ -1,5 +1,3 @@ -extern crate run_make_support; - use run_make_support::{rustc, tmp_dir}; fn main() { diff --git a/tests/run-make/print-cfg/Makefile b/tests/run-make/print-cfg/Makefile deleted file mode 100644 index 6b153e5b54e..00000000000 --- a/tests/run-make/print-cfg/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -# needs-llvm-components: x86 arm - -include ../tools.mk - -all: default output_to_file - $(RUSTC) --target x86_64-pc-windows-gnu --print cfg | $(CGREP) windows - $(RUSTC) --target x86_64-pc-windows-gnu --print cfg | $(CGREP) x86_64 - $(RUSTC) --target i686-pc-windows-msvc --print cfg | $(CGREP) msvc - $(RUSTC) --target i686-apple-darwin --print cfg | $(CGREP) macos - $(RUSTC) --target i686-unknown-linux-gnu --print cfg | $(CGREP) gnu - $(RUSTC) --target arm-unknown-linux-gnueabihf --print cfg | $(CGREP) target_abi= - $(RUSTC) --target arm-unknown-linux-gnueabihf --print cfg | $(CGREP) eabihf - -output_to_file: - # Backend-independent, printed by rustc_driver_impl/src/lib.rs - $(RUSTC) --target x86_64-pc-windows-gnu --print cfg=$(TMPDIR)/cfg.txt - $(CGREP) windows < $(TMPDIR)/cfg.txt - - # Printed from CodegenBackend trait impl in rustc_codegen_llvm/src/lib.rs - $(RUSTC) --print relocation-models=$(TMPDIR)/relocation-models.txt - $(CGREP) dynamic-no-pic < $(TMPDIR)/relocation-models.txt - - # Printed by compiler/rustc_codegen_llvm/src/llvm_util.rs - $(RUSTC) --target wasm32-unknown-unknown --print target-features=$(TMPDIR)/target-features.txt - $(CGREP) reference-types < $(TMPDIR)/target-features.txt - - # Printed by C++ code in rustc_llvm/llvm-wrapper/PassWrapper.cpp - $(RUSTC) --target wasm32-unknown-unknown --print target-cpus=$(TMPDIR)/target-cpus.txt - $(CGREP) generic < $(TMPDIR)/target-cpus.txt - -ifdef IS_WINDOWS -default: - $(RUSTC) --print cfg | $(CGREP) windows -else -default: - $(RUSTC) --print cfg | $(CGREP) unix -endif diff --git a/tests/run-make/print-cfg/rmake.rs b/tests/run-make/print-cfg/rmake.rs new file mode 100644 index 00000000000..6e72c16f1f9 --- /dev/null +++ b/tests/run-make/print-cfg/rmake.rs @@ -0,0 +1,104 @@ +//! This checks the output of `--print=cfg` +//! +//! Specifically it checks that output is correctly formatted +//! (ie. no duplicated cfgs, values are between "", names are not). +//! +//! It also checks that some targets have the correct set cfgs. + +use std::collections::HashSet; +use std::ffi::OsString; +use std::io::BufRead; +use std::iter::FromIterator; + +use run_make_support::{rustc, tmp_dir}; + +struct PrintCfg { + target: &'static str, + includes: &'static [&'static str], + disallow: &'static [&'static str], +} + +fn main() { + check(PrintCfg { + target: "x86_64-pc-windows-gnu", + includes: &["windows", "target_arch=\"x86_64\""], + disallow: &["unix"], + }); + check(PrintCfg { + target: "i686-pc-windows-msvc", + includes: &["windows", "target_env=\"msvc\""], + disallow: &["unix"], + }); + check(PrintCfg { + target: "i686-apple-darwin", + includes: &["unix", "target_os=\"macos\"", "target_vendor=\"apple\""], + disallow: &["windows"], + }); + check(PrintCfg { + target: "i686-unknown-linux-gnu", + includes: &["unix", "target_env=\"gnu\""], + disallow: &["windows"], + }); + check(PrintCfg { + target: "arm-unknown-linux-gnueabihf", + includes: &["unix", "target_abi=\"eabihf\""], + disallow: &["windows"], + }); +} + +fn check(PrintCfg { target, includes, disallow }: PrintCfg) { + fn check_(output: &str, includes: &[&str], disallow: &[&str]) { + let mut found = HashSet::<String>::new(); + let mut recorded = HashSet::<String>::new(); + + for l in output.lines() { + assert!(l == l.trim()); + if let Some((left, right)) = l.split_once('=') { + assert!(right.starts_with("\"")); + assert!(right.ends_with("\"")); + assert!(!left.contains("\"")); + } else { + assert!(!l.contains("\"")); + } + + assert!(recorded.insert(l.to_string()), "duplicated: {}", &l); + assert!(!disallow.contains(&l), "found disallowed: {}", &l); + if includes.contains(&l) { + assert!(found.insert(l.to_string()), "duplicated (includes): {}", &l); + } + } + + let should_found = HashSet::<String>::from_iter(includes.iter().map(|s| s.to_string())); + let diff: Vec<_> = should_found.difference(&found).collect(); + + assert!( + diff.is_empty(), + "expected: {:?}, found: {:?} (~ {:?})", + &should_found, + &found, + &diff + ); + } + + // --print=cfg + { + let output = rustc().target(target).print("cfg").run(); + + let stdout = String::from_utf8(output.stdout).unwrap(); + + check_(&stdout, includes, disallow); + } + + // --print=cfg=PATH + { + let tmp_path = tmp_dir().join(format!("{target}.cfg")); + let mut print_arg = OsString::from("--print=cfg="); + print_arg.push(tmp_path.as_os_str()); + + let output = rustc().target(target).arg(print_arg).run(); + + let output = std::fs::read_to_string(&tmp_path).unwrap(); + + check_(&output, includes, disallow); + } +} diff --git a/tests/run-make/print-native-static-libs/rmake.rs b/tests/run-make/print-native-static-libs/rmake.rs index fc8701777d1..edb85d568c6 100644 --- a/tests/run-make/print-native-static-libs/rmake.rs +++ b/tests/run-make/print-native-static-libs/rmake.rs @@ -12,19 +12,13 @@ //@ ignore-cross-compile //@ ignore-wasm -extern crate run_make_support; - use std::io::BufRead; -use run_make_support::{rustc, is_msvc}; +use run_make_support::{is_msvc, rustc}; fn main() { // build supporting crate - rustc() - .input("bar.rs") - .crate_type("rlib") - .arg("-lbar_cli") - .run(); + rustc().input("bar.rs").crate_type("rlib").arg("-lbar_cli").run(); // build main crate as staticlib let output = rustc() @@ -39,7 +33,9 @@ fn main() { for l in output.stderr.lines() { let l = l.expect("utf-8 string"); - let Some(args) = l.strip_prefix("note: native-static-libs:") else { continue; }; + let Some(args) = l.strip_prefix("note: native-static-libs:") else { + continue; + }; assert!(!found_note); found_note = true; @@ -55,11 +51,11 @@ fn main() { ); let found = $args.contains(&&*lib); assert!(found, "unable to find lib `{}` in those linker args: {:?}", lib, $args); - }} + }}; } assert_contains_lib!("glib-2.0" in args); // in bar.rs - assert_contains_lib!("systemd" in args); // in foo.rs + assert_contains_lib!("systemd" in args); // in foo.rs assert_contains_lib!("bar_cli" in args); assert_contains_lib!("foo_cli" in args); diff --git a/tests/run-make/print-to-output/rmake.rs b/tests/run-make/print-to-output/rmake.rs new file mode 100644 index 00000000000..1763cd378d2 --- /dev/null +++ b/tests/run-make/print-to-output/rmake.rs @@ -0,0 +1,62 @@ +//! This checks the output of some `--print` options when +//! output to a file (instead of stdout) + +use std::ffi::OsString; + +use run_make_support::{rustc, target, tmp_dir}; + +struct Option<'a> { + target: &'a str, + option: &'static str, + includes: &'static [&'static str], +} + +fn main() { + // Printed from CodegenBackend trait impl in rustc_codegen_llvm/src/lib.rs + check(Option { target: &target(), option: "relocation-models", includes: &["dynamic-no-pic"] }); + + // Printed by compiler/rustc_codegen_llvm/src/llvm_util.rs + check(Option { + target: "wasm32-unknown-unknown", + option: "target-features", + includes: &["reference-types"], + }); + + // Printed by C++ code in rustc_llvm/llvm-wrapper/PassWrapper.cpp + check(Option { + target: "wasm32-unknown-unknown", + option: "target-cpus", + includes: &["generic"], + }); +} + +fn check(args: Option) { + fn check_(output: &str, includes: &[&str]) { + for i in includes { + assert!(output.contains(i), "output doesn't contains: {}", i); + } + } + + // --print={option} + let stdout = { + let output = rustc().target(args.target).print(args.option).run(); + + String::from_utf8(output.stdout).unwrap() + }; + + // --print={option}=PATH + let output = { + let tmp_path = tmp_dir().join(format!("{}.txt", args.option)); + let mut print_arg = OsString::from(format!("--print={}=", args.option)); + print_arg.push(tmp_path.as_os_str()); + + let _output = rustc().target(args.target).arg(print_arg).run(); + + std::fs::read_to_string(&tmp_path).unwrap() + }; + + check_(&stdout, args.includes); + check_(&output, args.includes); + + assert_eq!(&stdout, &output); +} diff --git a/tests/run-make/raw-dylib-cross-compilation/Makefile b/tests/run-make/raw-dylib-cross-compilation/Makefile index a8f97edd689..2524f8500e1 100644 --- a/tests/run-make/raw-dylib-cross-compilation/Makefile +++ b/tests/run-make/raw-dylib-cross-compilation/Makefile @@ -1,8 +1,6 @@ # Tests that raw-dylib cross compilation works correctly -# only-gnu -# needs-i686-dlltool -# needs-x86_64-dlltool +# needs-dlltool # i686 dlltool.exe can't product x64 binaries. # ignore-i686-pc-windows-gnu diff --git a/tests/run-make/repr128-dwarf/Makefile b/tests/run-make/repr128-dwarf/Makefile deleted file mode 100644 index 3f933042724..00000000000 --- a/tests/run-make/repr128-dwarf/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# ignore-windows -# This test should be replaced with one in tests/debuginfo once GDB or LLDB support 128-bit -# enums. - -include ../tools.mk - -all: - $(RUSTC) -Cdebuginfo=2 lib.rs -o $(TMPDIR)/repr128.rlib - "$(LLVM_BIN_DIR)"/llvm-dwarfdump -n U128A $(TMPDIR)/repr128.rlib | $(CGREP) "DW_AT_const_value (<0x10> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 )" - "$(LLVM_BIN_DIR)"/llvm-dwarfdump -n U128B $(TMPDIR)/repr128.rlib | $(CGREP) "DW_AT_const_value (<0x10> 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 )" - "$(LLVM_BIN_DIR)"/llvm-dwarfdump -n U128C $(TMPDIR)/repr128.rlib | $(CGREP) "DW_AT_const_value (<0x10> 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 )" - "$(LLVM_BIN_DIR)"/llvm-dwarfdump -n U128D $(TMPDIR)/repr128.rlib | $(CGREP) "DW_AT_const_value (<0x10> ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff )" - "$(LLVM_BIN_DIR)"/llvm-dwarfdump -n I128A $(TMPDIR)/repr128.rlib | $(CGREP) "DW_AT_const_value (<0x10> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 )" - "$(LLVM_BIN_DIR)"/llvm-dwarfdump -n I128B $(TMPDIR)/repr128.rlib | $(CGREP) "DW_AT_const_value (<0x10> ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff )" - "$(LLVM_BIN_DIR)"/llvm-dwarfdump -n I128C $(TMPDIR)/repr128.rlib | $(CGREP) "DW_AT_const_value (<0x10> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 )" - "$(LLVM_BIN_DIR)"/llvm-dwarfdump -n I128D $(TMPDIR)/repr128.rlib | $(CGREP) "DW_AT_const_value (<0x10> ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 7f )" diff --git a/tests/run-make/repr128-dwarf/lib.rs b/tests/run-make/repr128-dwarf/main.rs index 63675441d4b..57923a8386d 100644 --- a/tests/run-make/repr128-dwarf/lib.rs +++ b/tests/run-make/repr128-dwarf/main.rs @@ -1,4 +1,3 @@ -#![crate_type = "lib"] #![feature(repr128)] // Use .to_le() to ensure that the bytes are in the same order on both little- and big-endian @@ -21,3 +20,7 @@ pub enum I128Enum { } pub fn f(_: U128Enum, _: I128Enum) {} + +fn main() { + f(U128Enum::U128A, I128Enum::I128A); +} diff --git a/tests/run-make/repr128-dwarf/rmake.rs b/tests/run-make/repr128-dwarf/rmake.rs new file mode 100644 index 00000000000..d734b2add79 --- /dev/null +++ b/tests/run-make/repr128-dwarf/rmake.rs @@ -0,0 +1,73 @@ +//@ ignore-windows +// This test should be replaced with one in tests/debuginfo once GDB or LLDB support 128-bit enums. + +use gimli::{AttributeValue, Dwarf, EndianRcSlice, Reader, RunTimeEndian}; +use object::{Object, ObjectSection}; +use run_make_support::{gimli, object, rustc, tmp_dir}; +use std::borrow::Cow; +use std::collections::HashMap; +use std::rc::Rc; + +fn main() { + let output = tmp_dir().join("repr128"); + rustc().input("main.rs").arg("-o").arg(&output).arg("-Cdebuginfo=2").run(); + // Mach-O uses packed debug info + let dsym_location = output + .with_extension("dSYM") + .join("Contents") + .join("Resources") + .join("DWARF") + .join("repr128"); + let output = + std::fs::read(if dsym_location.try_exists().unwrap() { dsym_location } else { output }) + .unwrap(); + let obj = object::File::parse(output.as_slice()).unwrap(); + let endian = if obj.is_little_endian() { RunTimeEndian::Little } else { RunTimeEndian::Big }; + let dwarf = gimli::Dwarf::load(|section| -> Result<_, ()> { + let data = obj.section_by_name(section.name()).map(|s| s.uncompressed_data().unwrap()); + Ok(EndianRcSlice::new(Rc::from(data.unwrap_or_default().as_ref()), endian)) + }) + .unwrap(); + let mut iter = dwarf.units(); + let mut still_to_find = HashMap::from([ + ("U128A", 0_u128), + ("U128B", 1_u128), + ("U128C", u64::MAX as u128 + 1), + ("U128D", u128::MAX), + ("I128A", 0_i128 as u128), + ("I128B", (-1_i128) as u128), + ("I128C", i128::MIN as u128), + ("I128D", i128::MAX as u128), + ]); + while let Some(header) = iter.next().unwrap() { + let unit = dwarf.unit(header).unwrap(); + let mut cursor = unit.entries(); + while let Some((_, entry)) = cursor.next_dfs().unwrap() { + if entry.tag() == gimli::constants::DW_TAG_enumerator { + let name = dwarf + .attr_string( + &unit, + entry.attr(gimli::constants::DW_AT_name).unwrap().unwrap().value(), + ) + .unwrap(); + let name = name.to_string().unwrap(); + if let Some(expected) = still_to_find.remove(name.as_ref()) { + match entry.attr(gimli::constants::DW_AT_const_value).unwrap().unwrap().value() + { + AttributeValue::Block(value) => { + assert_eq!( + value.to_slice().unwrap(), + expected.to_le_bytes().as_slice(), + "{name}" + ); + } + value => panic!("{name}: unexpected DW_AT_const_value of {value:?}"), + } + } + } + } + } + if !still_to_find.is_empty() { + panic!("Didn't find debug entries for {still_to_find:?}"); + } +} diff --git a/tests/run-make/rust-lld-custom-target/rmake.rs b/tests/run-make/rust-lld-custom-target/rmake.rs index b5341725e36..9bdb69f47d8 100644 --- a/tests/run-make/rust-lld-custom-target/rmake.rs +++ b/tests/run-make/rust-lld-custom-target/rmake.rs @@ -8,8 +8,6 @@ //@ needs-rust-lld //@ only-x86_64-unknown-linux-gnu -extern crate run_make_support; - use run_make_support::regex::Regex; use run_make_support::rustc; use std::process::Output; diff --git a/tests/run-make/rust-lld/rmake.rs b/tests/run-make/rust-lld/rmake.rs index acb6d74aaa8..feeb82e709e 100644 --- a/tests/run-make/rust-lld/rmake.rs +++ b/tests/run-make/rust-lld/rmake.rs @@ -5,8 +5,6 @@ //@ ignore-msvc //@ ignore-s390x lld does not yet support s390x as target -extern crate run_make_support; - use run_make_support::regex::Regex; use run_make_support::rustc; use std::process::Output; diff --git a/tests/run-make/rustdoc-determinism/Makefile b/tests/run-make/rustdoc-determinism/Makefile deleted file mode 100644 index a3ef1690671..00000000000 --- a/tests/run-make/rustdoc-determinism/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -include ../tools.mk - -# Assert that the search index is generated deterministically, regardless of the -# order that crates are documented in. - -# ignore-windows -# Uses `diff`. - -all: - $(RUSTDOC) foo.rs -o $(TMPDIR)/foo_first - $(RUSTDOC) bar.rs -o $(TMPDIR)/foo_first - - $(RUSTDOC) bar.rs -o $(TMPDIR)/bar_first - $(RUSTDOC) foo.rs -o $(TMPDIR)/bar_first - - diff $(TMPDIR)/foo_first/search-index.js $(TMPDIR)/bar_first/search-index.js diff --git a/tests/run-make/rustdoc-determinism/rmake.rs b/tests/run-make/rustdoc-determinism/rmake.rs new file mode 100644 index 00000000000..38ae75199fd --- /dev/null +++ b/tests/run-make/rustdoc-determinism/rmake.rs @@ -0,0 +1,18 @@ +use run_make_support::{diff, rustc, rustdoc, tmp_dir}; + +/// Assert that the search index is generated deterministically, regardless of the +/// order that crates are documented in. +fn main() { + let dir_first = tmp_dir().join("first"); + rustdoc().out_dir(&dir_first).input("foo.rs").run(); + rustdoc().out_dir(&dir_first).input("bar.rs").run(); + + let dir_second = tmp_dir().join("second"); + rustdoc().out_dir(&dir_second).input("bar.rs").run(); + rustdoc().out_dir(&dir_second).input("foo.rs").run(); + + diff() + .expected_file(dir_first.join("search-index.js")) + .actual_file(dir_second.join("search-index.js")) + .run(); +} diff --git a/tests/run-make/rustdoc-test-args/rmake.rs b/tests/run-make/rustdoc-test-args/rmake.rs index c8edfb6370e..66f3f7cf131 100644 --- a/tests/run-make/rustdoc-test-args/rmake.rs +++ b/tests/run-make/rustdoc-test-args/rmake.rs @@ -1,5 +1,3 @@ -extern crate run_make_support; - use run_make_support::{rustdoc, tmp_dir}; use std::path::Path; use std::{fs, iter}; diff --git a/tests/run-make/stdin-non-utf8/Makefile b/tests/run-make/stdin-non-utf8/Makefile deleted file mode 100644 index 709d4cf1408..00000000000 --- a/tests/run-make/stdin-non-utf8/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -include ../tools.mk - -all: - cp non-utf8 $(TMPDIR)/non-utf.rs - cat $(TMPDIR)/non-utf.rs | $(RUSTC) - 2>&1 \ - | $(CGREP) "error: couldn't read from stdin, as it did not contain valid UTF-8" diff --git a/tests/run-make/stdin-non-utf8/non-utf8 b/tests/run-make/stdin-non-utf8/non-utf8 deleted file mode 100644 index bc87051a852..00000000000 --- a/tests/run-make/stdin-non-utf8/non-utf8 +++ /dev/null @@ -1 +0,0 @@ -Ò diff --git a/tests/run-make/stdin-rustc/rmake.rs b/tests/run-make/stdin-rustc/rmake.rs new file mode 100644 index 00000000000..c07a6df4d84 --- /dev/null +++ b/tests/run-make/stdin-rustc/rmake.rs @@ -0,0 +1,26 @@ +//! This test checks rustc `-` (stdin) support + +use run_make_support::{is_windows, rustc, tmp_dir}; + +const HELLO_WORLD: &str = r#" +fn main() { + println!("Hello world!"); +} +"#; + +const NOT_UTF8: &[u8] = &[0xff, 0xff, 0xff]; + +fn main() { + let out_dir = tmp_dir(); + + // echo $HELLO_WORLD | rustc - + rustc().arg("-").stdin(HELLO_WORLD).run(); + assert!( + out_dir.join(if !is_windows() { "rust_out" } else { "rust_out.exe" }).try_exists().unwrap() + ); + + // echo $NOT_UTF8 | rustc - + let output = rustc().arg("-").stdin(NOT_UTF8).run_fail(); + let stderr = String::from_utf8(output.stderr).unwrap(); + assert!(stderr.contains("error: couldn't read from stdin, as it did not contain valid UTF-8")); +} diff --git a/tests/run-make/wasm-abi/rmake.rs b/tests/run-make/wasm-abi/rmake.rs index d83332f6e03..a2dcafbbe0f 100644 --- a/tests/run-make/wasm-abi/rmake.rs +++ b/tests/run-make/wasm-abi/rmake.rs @@ -1,8 +1,6 @@ //@ only-wasm32-wasip1 //@ needs-wasmtime -extern crate run_make_support; - use run_make_support::{rustc, tmp_dir}; use std::path::Path; use std::process::Command; diff --git a/tests/run-make/wasm-custom-section/rmake.rs b/tests/run-make/wasm-custom-section/rmake.rs index 825fcf71514..0303ca05ca6 100644 --- a/tests/run-make/wasm-custom-section/rmake.rs +++ b/tests/run-make/wasm-custom-section/rmake.rs @@ -1,5 +1,4 @@ //@ only-wasm32-wasip1 -extern crate run_make_support; use run_make_support::{rustc, tmp_dir, wasmparser}; use std::collections::HashMap; diff --git a/tests/run-make/wasm-custom-sections-opt/rmake.rs b/tests/run-make/wasm-custom-sections-opt/rmake.rs index 634683adc22..50916b1bf81 100644 --- a/tests/run-make/wasm-custom-sections-opt/rmake.rs +++ b/tests/run-make/wasm-custom-sections-opt/rmake.rs @@ -1,7 +1,6 @@ //@ only-wasm32-wasip1 -extern crate run_make_support; -use run_make_support::{tmp_dir, wasmparser, rustc}; +use run_make_support::{rustc, tmp_dir, wasmparser}; use std::collections::HashMap; use std::path::Path; diff --git a/tests/run-make/wasm-export-all-symbols/rmake.rs b/tests/run-make/wasm-export-all-symbols/rmake.rs index 400d6db5651..f4c51bc4ab4 100644 --- a/tests/run-make/wasm-export-all-symbols/rmake.rs +++ b/tests/run-make/wasm-export-all-symbols/rmake.rs @@ -1,8 +1,6 @@ //@ only-wasm32-wasip1 -extern crate run_make_support; - -use run_make_support::{tmp_dir, wasmparser, rustc}; +use run_make_support::{rustc, tmp_dir, wasmparser}; use std::collections::HashMap; use std::path::Path; use wasmparser::ExternalKind::*; diff --git a/tests/run-make/wasm-import-module/rmake.rs b/tests/run-make/wasm-import-module/rmake.rs index 1b814e9ccce..6eed229e907 100644 --- a/tests/run-make/wasm-import-module/rmake.rs +++ b/tests/run-make/wasm-import-module/rmake.rs @@ -1,19 +1,12 @@ //@ only-wasm32-wasip1 -extern crate run_make_support; - -use run_make_support::{tmp_dir, wasmparser, rustc}; +use run_make_support::{rustc, tmp_dir, wasmparser}; use std::collections::HashMap; use wasmparser::TypeRef::Func; fn main() { rustc().input("foo.rs").target("wasm32-wasip1").run(); - rustc() - .input("bar.rs") - .target("wasm32-wasip1") - .arg("-Clto") - .opt() - .run(); + rustc().input("bar.rs").target("wasm32-wasip1").arg("-Clto").opt().run(); let file = std::fs::read(&tmp_dir().join("bar.wasm")).unwrap(); diff --git a/tests/run-make/wasm-panic-small/rmake.rs b/tests/run-make/wasm-panic-small/rmake.rs index bffa311d93a..373b966401c 100644 --- a/tests/run-make/wasm-panic-small/rmake.rs +++ b/tests/run-make/wasm-panic-small/rmake.rs @@ -1,8 +1,6 @@ //@ only-wasm32-wasip1 #![deny(warnings)] -extern crate run_make_support; - use run_make_support::{rustc, tmp_dir}; fn main() { diff --git a/tests/run-make/wasm-spurious-import/rmake.rs b/tests/run-make/wasm-spurious-import/rmake.rs index 8f716061d28..458c7bfccb7 100644 --- a/tests/run-make/wasm-spurious-import/rmake.rs +++ b/tests/run-make/wasm-spurious-import/rmake.rs @@ -1,7 +1,5 @@ //@ only-wasm32-wasip1 -extern crate run_make_support; - use run_make_support::{rustc, tmp_dir, wasmparser}; use std::collections::HashMap; diff --git a/tests/run-make/wasm-stringify-ints-small/rmake.rs b/tests/run-make/wasm-stringify-ints-small/rmake.rs index 5efbfee8d38..9fac0c0c215 100644 --- a/tests/run-make/wasm-stringify-ints-small/rmake.rs +++ b/tests/run-make/wasm-stringify-ints-small/rmake.rs @@ -1,8 +1,6 @@ //@ only-wasm32-wasip1 #![deny(warnings)] -extern crate run_make_support; - use run_make_support::{rustc, tmp_dir}; fn main() { diff --git a/tests/run-make/wasm-symbols-different-module/rmake.rs b/tests/run-make/wasm-symbols-different-module/rmake.rs index 88bd16a404c..521d2c31ee6 100644 --- a/tests/run-make/wasm-symbols-different-module/rmake.rs +++ b/tests/run-make/wasm-symbols-different-module/rmake.rs @@ -1,5 +1,4 @@ //@ only-wasm32-wasip1 -extern crate run_make_support; use run_make_support::{rustc, tmp_dir, wasmparser}; use std::collections::{HashMap, HashSet}; diff --git a/tests/run-make/wasm-symbols-not-exported/rmake.rs b/tests/run-make/wasm-symbols-not-exported/rmake.rs index c9207f70ae5..1b020b67a38 100644 --- a/tests/run-make/wasm-symbols-not-exported/rmake.rs +++ b/tests/run-make/wasm-symbols-not-exported/rmake.rs @@ -1,5 +1,4 @@ //@ only-wasm32-wasip1 -extern crate run_make_support; use run_make_support::{rustc, tmp_dir, wasmparser}; use std::path::Path; diff --git a/tests/run-make/wasm-symbols-not-imported/rmake.rs b/tests/run-make/wasm-symbols-not-imported/rmake.rs index 4d41dc7c0aa..a653ab61b2c 100644 --- a/tests/run-make/wasm-symbols-not-imported/rmake.rs +++ b/tests/run-make/wasm-symbols-not-imported/rmake.rs @@ -1,5 +1,4 @@ //@ only-wasm32-wasip1 -extern crate run_make_support; use run_make_support::{rustc, tmp_dir, wasmparser}; use std::path::Path; diff --git a/tests/rustdoc-ui/argfile/commandline-argfile.rs b/tests/rustdoc-ui/argfile/commandline-argfile.rs index b0b314f53ce..d5a1cd0a5ed 100644 --- a/tests/rustdoc-ui/argfile/commandline-argfile.rs +++ b/tests/rustdoc-ui/argfile/commandline-argfile.rs @@ -1,7 +1,8 @@ // Check to see if we can get parameters from an @argsfile file // //@ check-pass -//@ compile-flags: --cfg cmdline_set @{{src-base}}/argfile/commandline-argfile.args +//@ compile-flags: --cfg cmdline_set --check-cfg=cfg(cmdline_set,unbroken) +//@ compile-flags: @{{src-base}}/argfile/commandline-argfile.args #[cfg(not(cmdline_set))] compile_error!("cmdline_set not set"); @@ -9,5 +10,4 @@ compile_error!("cmdline_set not set"); #[cfg(not(unbroken))] compile_error!("unbroken not set"); -fn main() { -} +fn main() {} diff --git a/tests/rustdoc-ui/doctest/non_local_defs.rs b/tests/rustdoc-ui/doctest/non_local_defs.rs new file mode 100644 index 00000000000..aa166c343b2 --- /dev/null +++ b/tests/rustdoc-ui/doctest/non_local_defs.rs @@ -0,0 +1,10 @@ +//@ check-pass +//@ compile-flags:--test --test-args --test-threads=1 --nocapture -Zunstable-options +//@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stderr-test: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" + +//! ``` +//! #[macro_export] +//! macro_rules! a_macro { () => {} } +//! ``` diff --git a/tests/rustdoc-ui/doctest/non_local_defs.stderr b/tests/rustdoc-ui/doctest/non_local_defs.stderr new file mode 100644 index 00000000000..39a25de1aae --- /dev/null +++ b/tests/rustdoc-ui/doctest/non_local_defs.stderr @@ -0,0 +1,14 @@ +warning: non-local `macro_rules!` definition, they should be avoided as they go against expectation + --> $DIR/non_local_defs.rs:9:1 + | +LL | macro_rules! a_macro { () => {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: remove the `#[macro_export]` or make this doc-test a standalone test with its own `fn main() { ... }` + = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute + = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module + = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> + = note: `#[warn(non_local_definitions)]` on by default + +warning: 1 warning emitted + diff --git a/tests/rustdoc-ui/doctest/non_local_defs.stdout b/tests/rustdoc-ui/doctest/non_local_defs.stdout new file mode 100644 index 00000000000..bee195fcdd7 --- /dev/null +++ b/tests/rustdoc-ui/doctest/non_local_defs.stdout @@ -0,0 +1,6 @@ + +running 1 test +test $DIR/non_local_defs.rs - (line 7) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/rustdoc/resolve-ice-124363.rs b/tests/rustdoc/resolve-ice-124363.rs new file mode 100644 index 00000000000..111916cc590 --- /dev/null +++ b/tests/rustdoc/resolve-ice-124363.rs @@ -0,0 +1,7 @@ +/** +*/ +pub mod A { + #![doc = "{ + Foo { }, + }"] +} diff --git a/tests/ui/argfile/commandline-argfile.rs b/tests/ui/argfile/commandline-argfile.rs index 387a8d033b3..b7f1e8ed6aa 100644 --- a/tests/ui/argfile/commandline-argfile.rs +++ b/tests/ui/argfile/commandline-argfile.rs @@ -1,7 +1,8 @@ // Check to see if we can get parameters from an @argsfile file // //@ build-pass -//@ compile-flags: --cfg cmdline_set @{{src-base}}/argfile/commandline-argfile.args +//@ compile-flags: --cfg cmdline_set --check-cfg=cfg(cmdline_set,unbroken) +//@ compile-flags: @{{src-base}}/argfile/commandline-argfile.args #[cfg(not(cmdline_set))] compile_error!("cmdline_set not set"); @@ -9,5 +10,4 @@ compile_error!("cmdline_set not set"); #[cfg(not(unbroken))] compile_error!("unbroken not set"); -fn main() { -} +fn main() {} diff --git a/tests/ui/asm/x86_64/target-feature-attr.rs b/tests/ui/asm/x86_64/target-feature-attr.rs index 820be132ef7..6bb277ac165 100644 --- a/tests/ui/asm/x86_64/target-feature-attr.rs +++ b/tests/ui/asm/x86_64/target-feature-attr.rs @@ -1,4 +1,6 @@ //@ only-x86_64 +// Set the base cpu explicitly, in case the default has been changed. +//@ compile-flags: -C target-cpu=x86-64 #![feature(avx512_target_feature)] diff --git a/tests/ui/asm/x86_64/target-feature-attr.stderr b/tests/ui/asm/x86_64/target-feature-attr.stderr index c852726ee7f..0cd571ac8cc 100644 --- a/tests/ui/asm/x86_64/target-feature-attr.stderr +++ b/tests/ui/asm/x86_64/target-feature-attr.stderr @@ -1,23 +1,23 @@ error: register class `ymm_reg` requires the `avx` target feature - --> $DIR/target-feature-attr.rs:18:40 + --> $DIR/target-feature-attr.rs:20:40 | LL | asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x); | ^^^^^^^^^^^^^ error: register class `ymm_reg` requires the `avx` target feature - --> $DIR/target-feature-attr.rs:18:55 + --> $DIR/target-feature-attr.rs:20:55 | LL | asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x); | ^^^^^^^^^^^^^ error: register class `ymm_reg` requires the `avx` target feature - --> $DIR/target-feature-attr.rs:18:70 + --> $DIR/target-feature-attr.rs:20:70 | LL | asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x); | ^^^^^^^^^^^^^^^^^^ error: register class `kreg` requires at least one of the following target features: avx512bw, avx512f - --> $DIR/target-feature-attr.rs:33:23 + --> $DIR/target-feature-attr.rs:35:23 | LL | asm!("/* {0} */", in(kreg) x); | ^^^^^^^^^^ diff --git a/tests/ui/async-await/inference_var_self_argument.rs b/tests/ui/async-await/inference_var_self_argument.rs index f4bb8884b05..4d5ac4abb19 100644 --- a/tests/ui/async-await/inference_var_self_argument.rs +++ b/tests/ui/async-await/inference_var_self_argument.rs @@ -4,7 +4,7 @@ trait Foo { async fn foo(self: &dyn Foo) { //~^ ERROR: `Foo` cannot be made into an object - //~| ERROR invalid `self` parameter type: &dyn Foo + //~| ERROR invalid `self` parameter type: `&dyn Foo` todo!() } } diff --git a/tests/ui/async-await/inference_var_self_argument.stderr b/tests/ui/async-await/inference_var_self_argument.stderr index 8a8c1ea03f1..f94ae2a27c3 100644 --- a/tests/ui/async-await/inference_var_self_argument.stderr +++ b/tests/ui/async-await/inference_var_self_argument.stderr @@ -13,7 +13,7 @@ LL | async fn foo(self: &dyn Foo) { | ^^^ ...because method `foo` is `async` = help: consider moving `foo` to another trait -error[E0307]: invalid `self` parameter type: &dyn Foo +error[E0307]: invalid `self` parameter type: `&dyn Foo` --> $DIR/inference_var_self_argument.rs:5:24 | LL | async fn foo(self: &dyn Foo) { diff --git a/tests/ui/async-await/issue-66312.stderr b/tests/ui/async-await/issue-66312.stderr index 2875af8a97e..702e0b375e5 100644 --- a/tests/ui/async-await/issue-66312.stderr +++ b/tests/ui/async-await/issue-66312.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | if x.is_some() { | ^^^^^^^^^^^ expected `bool`, found `()` -error[E0307]: invalid `self` parameter type: T +error[E0307]: invalid `self` parameter type: `T` --> $DIR/issue-66312.rs:4:22 | LL | fn is_some(self: T); diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-bare.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-bare.rs deleted file mode 100644 index 5d95fc70e78..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-bare.rs +++ /dev/null @@ -1,4 +0,0 @@ -#![feature(unix_sigpipe)] - -#[unix_sigpipe] //~ error: malformed `unix_sigpipe` attribute input -fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-bare.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-bare.stderr deleted file mode 100644 index c1b4470d54a..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-bare.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: malformed `unix_sigpipe` attribute input - --> $DIR/unix_sigpipe-bare.rs:3:1 - | -LL | #[unix_sigpipe] - | ^^^^^^^^^^^^^^^ help: must be of the form: `#[unix_sigpipe = "inherit|sig_ign|sig_dfl"]` - -error: aborting due to 1 previous error - diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.rs deleted file mode 100644 index f5fa177f29c..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.rs +++ /dev/null @@ -1,4 +0,0 @@ -#![feature(unix_sigpipe)] -#![unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute cannot be used at crate level - -fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr deleted file mode 100644 index fdfa3018086..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error: `unix_sigpipe` attribute cannot be used at crate level - --> $DIR/unix_sigpipe-crate.rs:2:1 - | -LL | #![unix_sigpipe = "sig_dfl"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | fn main() {} - | ---- the inner attribute doesn't annotate this function - | -help: perhaps you meant to use an outer attribute - | -LL - #![unix_sigpipe = "sig_dfl"] -LL + #[unix_sigpipe = "sig_dfl"] - | - -error: aborting due to 1 previous error - diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-different-duplicates.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-different-duplicates.rs deleted file mode 100644 index 294cb38526b..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-different-duplicates.rs +++ /dev/null @@ -1,5 +0,0 @@ -#![feature(unix_sigpipe)] - -#[unix_sigpipe = "sig_ign"] -#[unix_sigpipe = "inherit"] //~ error: multiple `unix_sigpipe` attributes -fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-different-duplicates.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-different-duplicates.stderr deleted file mode 100644 index c2a3b9f45f9..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-different-duplicates.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: multiple `unix_sigpipe` attributes - --> $DIR/unix_sigpipe-different-duplicates.rs:4:1 - | -LL | #[unix_sigpipe = "inherit"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute - | -note: attribute also specified here - --> $DIR/unix_sigpipe-different-duplicates.rs:3:1 - | -LL | #[unix_sigpipe = "sig_ign"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.rs deleted file mode 100644 index eccb23021b6..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.rs +++ /dev/null @@ -1,5 +0,0 @@ -#![feature(unix_sigpipe)] - -#[unix_sigpipe = "inherit"] -#[unix_sigpipe = "inherit"] //~ error: multiple `unix_sigpipe` attributes -fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.stderr deleted file mode 100644 index c86e54a1e53..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: multiple `unix_sigpipe` attributes - --> $DIR/unix_sigpipe-duplicates.rs:4:1 - | -LL | #[unix_sigpipe = "inherit"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute - | -note: attribute also specified here - --> $DIR/unix_sigpipe-duplicates.rs:3:1 - | -LL | #[unix_sigpipe = "inherit"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-ident-list.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-ident-list.rs deleted file mode 100644 index 462ae24a884..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-ident-list.rs +++ /dev/null @@ -1,4 +0,0 @@ -#![feature(unix_sigpipe)] - -#[unix_sigpipe(sig_dfl)] //~ error: malformed `unix_sigpipe` attribute input -fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-ident-list.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-ident-list.stderr deleted file mode 100644 index a020f21e6ca..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-ident-list.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: malformed `unix_sigpipe` attribute input - --> $DIR/unix_sigpipe-ident-list.rs:3:1 - | -LL | #[unix_sigpipe(sig_dfl)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[unix_sigpipe = "inherit|sig_ign|sig_dfl"]` - -error: aborting due to 1 previous error - diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.rs deleted file mode 100644 index 16731a4ba2c..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![feature(unix_sigpipe)] - -#[unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()` -fn f() {} - -fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.stderr deleted file mode 100644 index fcdd5db8f29..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: `unix_sigpipe` attribute can only be used on `fn main()` - --> $DIR/unix_sigpipe-non-main-fn.rs:3:1 - | -LL | #[unix_sigpipe = "sig_dfl"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.rs deleted file mode 100644 index a2435258620..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![feature(unix_sigpipe)] - -mod m { - #[unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute can only be used on root `fn main()` - fn main() {} -} - -fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.stderr deleted file mode 100644 index 98afb62fdb4..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: `unix_sigpipe` attribute can only be used on root `fn main()` - --> $DIR/unix_sigpipe-non-root-main.rs:4:5 - | -LL | #[unix_sigpipe = "sig_dfl"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.rs deleted file mode 100644 index 945b820f9e0..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![feature(start)] -#![feature(unix_sigpipe)] - -#[start] -#[unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()` -fn custom_start(argc: isize, argv: *const *const u8) -> isize { 0 } diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.stderr deleted file mode 100644 index 3d56b3655c9..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: `unix_sigpipe` attribute can only be used on `fn main()` - --> $DIR/unix_sigpipe-start.rs:5:1 - | -LL | #[unix_sigpipe = "sig_dfl"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.rs deleted file mode 100644 index 22326835623..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.rs +++ /dev/null @@ -1,4 +0,0 @@ -#![feature(unix_sigpipe)] - -#[unix_sigpipe("sig_dfl")] //~ error: malformed `unix_sigpipe` attribute input -fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.stderr deleted file mode 100644 index b62c086e360..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: malformed `unix_sigpipe` attribute input - --> $DIR/unix_sigpipe-str-list.rs:3:1 - | -LL | #[unix_sigpipe("sig_dfl")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[unix_sigpipe = "inherit|sig_ign|sig_dfl"]` - -error: aborting due to 1 previous error - diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.rs deleted file mode 100644 index 662779c0821..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![feature(unix_sigpipe)] - -#[unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()` -struct S; - -fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.stderr deleted file mode 100644 index a8fc51bdbc4..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: `unix_sigpipe` attribute can only be used on `fn main()` - --> $DIR/unix_sigpipe-struct.rs:3:1 - | -LL | #[unix_sigpipe = "sig_dfl"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.rs deleted file mode 100644 index 4ec25de00ec..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.rs +++ /dev/null @@ -1,4 +0,0 @@ -#![feature(unix_sigpipe)] - -#[unix_sigpipe = "wrong"] //~ error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl` -fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.stderr deleted file mode 100644 index d750443e4a9..00000000000 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl` - --> $DIR/unix_sigpipe-wrong.rs:3:1 - | -LL | #[unix_sigpipe = "wrong"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/cfg/cfg-in-crate-1.rs b/tests/ui/cfg/cfg-in-crate-1.rs index 07e1c3727f9..4339ce00477 100644 --- a/tests/ui/cfg/cfg-in-crate-1.rs +++ b/tests/ui/cfg/cfg-in-crate-1.rs @@ -1,5 +1,6 @@ //@ run-pass -//@ compile-flags: --cfg bar -D warnings +//@ compile-flags: --cfg bar --check-cfg=cfg(bar) -D warnings + #![cfg(bar)] fn main() {} diff --git a/tests/ui/cfg/cfg-macros-foo.rs b/tests/ui/cfg/cfg-macros-foo.rs index 7cdf2df5c8f..4f6ec583db2 100644 --- a/tests/ui/cfg/cfg-macros-foo.rs +++ b/tests/ui/cfg/cfg-macros-foo.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ compile-flags: --cfg foo +//@ compile-flags: --cfg foo --check-cfg=cfg(foo) // check that cfg correctly chooses between the macro impls (see also // cfg-macros-notfoo.rs) diff --git a/tests/ui/cfg/cfg-path-error.rs b/tests/ui/cfg/cfg-path-error.rs index 1e52922d079..9db1f190bdc 100644 --- a/tests/ui/cfg/cfg-path-error.rs +++ b/tests/ui/cfg/cfg-path-error.rs @@ -1,5 +1,7 @@ //@ check-fail +#![allow(unexpected_cfgs)] // invalid cfgs + #[cfg(any(foo, foo::bar))] //~^ERROR `cfg` predicate key must be an identifier fn foo1() {} diff --git a/tests/ui/cfg/cfg-path-error.stderr b/tests/ui/cfg/cfg-path-error.stderr index 84b44b2b0c2..4f68fa32a9a 100644 --- a/tests/ui/cfg/cfg-path-error.stderr +++ b/tests/ui/cfg/cfg-path-error.stderr @@ -1,23 +1,23 @@ error: `cfg` predicate key must be an identifier - --> $DIR/cfg-path-error.rs:3:16 + --> $DIR/cfg-path-error.rs:5:16 | LL | #[cfg(any(foo, foo::bar))] | ^^^^^^^^ error: `cfg` predicate key must be an identifier - --> $DIR/cfg-path-error.rs:7:11 + --> $DIR/cfg-path-error.rs:9:11 | LL | #[cfg(any(foo::bar, foo))] | ^^^^^^^^ error: `cfg` predicate key must be an identifier - --> $DIR/cfg-path-error.rs:11:16 + --> $DIR/cfg-path-error.rs:13:16 | LL | #[cfg(all(foo, foo::bar))] | ^^^^^^^^ error: `cfg` predicate key must be an identifier - --> $DIR/cfg-path-error.rs:15:11 + --> $DIR/cfg-path-error.rs:17:11 | LL | #[cfg(all(foo::bar, foo))] | ^^^^^^^^ diff --git a/tests/ui/cfg/cfg_attr.rs b/tests/ui/cfg/cfg_attr.rs index 4bd024ef5f4..ba4adafd3a5 100644 --- a/tests/ui/cfg/cfg_attr.rs +++ b/tests/ui/cfg/cfg_attr.rs @@ -1,6 +1,8 @@ //@ run-pass //@ compile-flags:--cfg set1 --cfg set2 -#![allow(dead_code)] + +#![allow(dead_code, unexpected_cfgs)] + use std::fmt::Debug; struct NotDebugable; diff --git a/tests/ui/cfg/cfgs-on-items.rs b/tests/ui/cfg/cfgs-on-items.rs index b3b38cfadb5..8992a8fca9c 100644 --- a/tests/ui/cfg/cfgs-on-items.rs +++ b/tests/ui/cfg/cfgs-on-items.rs @@ -1,8 +1,7 @@ //@ run-pass -//@ compile-flags: --cfg fooA --cfg fooB +//@ compile-flags: --cfg fooA --cfg fooB --check-cfg=cfg(fooA,fooB,fooC,bar) // fooA AND !bar - #[cfg(all(fooA, not(bar)))] fn foo1() -> isize { 1 } diff --git a/tests/ui/cfg/diagnostics-not-a-def.rs b/tests/ui/cfg/diagnostics-not-a-def.rs index 72939471226..1912cf9f616 100644 --- a/tests/ui/cfg/diagnostics-not-a-def.rs +++ b/tests/ui/cfg/diagnostics-not-a-def.rs @@ -1,4 +1,7 @@ +#![feature(lint_reasons)] + pub mod inner { + #[expect(unexpected_cfgs)] pub fn i_am_here() { #[cfg(feature = "another one that doesn't exist")] loop {} diff --git a/tests/ui/cfg/diagnostics-not-a-def.stderr b/tests/ui/cfg/diagnostics-not-a-def.stderr index 6941f850e5f..89bbf574871 100644 --- a/tests/ui/cfg/diagnostics-not-a-def.stderr +++ b/tests/ui/cfg/diagnostics-not-a-def.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find function `i_am_not` in module `inner` - --> $DIR/diagnostics-not-a-def.rs:11:12 + --> $DIR/diagnostics-not-a-def.rs:14:12 | LL | inner::i_am_not(); | ^^^^^^^^ not found in `inner` diff --git a/tests/ui/cfg/diagnostics-same-crate.rs b/tests/ui/cfg/diagnostics-same-crate.rs index d9ff8d61e92..b2a0fb58dd6 100644 --- a/tests/ui/cfg/diagnostics-same-crate.rs +++ b/tests/ui/cfg/diagnostics-same-crate.rs @@ -1,3 +1,5 @@ +#![allow(unexpected_cfgs)] // since we want to recognize them as unexpected + pub mod inner { #[cfg(FALSE)] pub fn uwu() {} diff --git a/tests/ui/cfg/diagnostics-same-crate.stderr b/tests/ui/cfg/diagnostics-same-crate.stderr index 83a44587238..86421736b8c 100644 --- a/tests/ui/cfg/diagnostics-same-crate.stderr +++ b/tests/ui/cfg/diagnostics-same-crate.stderr @@ -1,72 +1,72 @@ error[E0432]: unresolved import `super::inner::doesnt_exist` - --> $DIR/diagnostics-same-crate.rs:28:9 + --> $DIR/diagnostics-same-crate.rs:30:9 | LL | use super::inner::doesnt_exist; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ no `doesnt_exist` in `inner` | note: found an item that was configured out - --> $DIR/diagnostics-same-crate.rs:7:13 + --> $DIR/diagnostics-same-crate.rs:9:13 | LL | pub mod doesnt_exist { | ^^^^^^^^^^^^ error[E0432]: unresolved import `super::inner::doesnt_exist` - --> $DIR/diagnostics-same-crate.rs:31:23 + --> $DIR/diagnostics-same-crate.rs:33:23 | LL | use super::inner::doesnt_exist::hi; | ^^^^^^^^^^^^ could not find `doesnt_exist` in `inner` | note: found an item that was configured out - --> $DIR/diagnostics-same-crate.rs:7:13 + --> $DIR/diagnostics-same-crate.rs:9:13 | LL | pub mod doesnt_exist { | ^^^^^^^^^^^^ error[E0433]: failed to resolve: could not find `doesnt_exist` in `inner` - --> $DIR/diagnostics-same-crate.rs:50:12 + --> $DIR/diagnostics-same-crate.rs:52:12 | LL | inner::doesnt_exist::hello(); | ^^^^^^^^^^^^ could not find `doesnt_exist` in `inner` | note: found an item that was configured out - --> $DIR/diagnostics-same-crate.rs:7:13 + --> $DIR/diagnostics-same-crate.rs:9:13 | LL | pub mod doesnt_exist { | ^^^^^^^^^^^^ error[E0425]: cannot find function `uwu` in module `inner` - --> $DIR/diagnostics-same-crate.rs:45:12 + --> $DIR/diagnostics-same-crate.rs:47:12 | LL | inner::uwu(); | ^^^ not found in `inner` | note: found an item that was configured out - --> $DIR/diagnostics-same-crate.rs:3:12 + --> $DIR/diagnostics-same-crate.rs:5:12 | LL | pub fn uwu() {} | ^^^ error[E0425]: cannot find function `meow` in module `inner::right` - --> $DIR/diagnostics-same-crate.rs:54:19 + --> $DIR/diagnostics-same-crate.rs:56:19 | LL | inner::right::meow(); | ^^^^ not found in `inner::right` | note: found an item that was configured out - --> $DIR/diagnostics-same-crate.rs:22:16 + --> $DIR/diagnostics-same-crate.rs:24:16 | LL | pub fn meow() {} | ^^^^ = note: the item is gated behind the `what-a-cool-feature` feature error[E0425]: cannot find function `uwu` in this scope - --> $DIR/diagnostics-same-crate.rs:41:5 + --> $DIR/diagnostics-same-crate.rs:43:5 | LL | uwu(); | ^^^ not found in this scope error[E0425]: cannot find function `vanished` in this scope - --> $DIR/diagnostics-same-crate.rs:61:5 + --> $DIR/diagnostics-same-crate.rs:63:5 | LL | vanished(); | ^^^^^^^^ not found in this scope diff --git a/tests/ui/cfg/expanded-cfg.rs b/tests/ui/cfg/expanded-cfg.rs index 75860146e74..ecafa40cadc 100644 --- a/tests/ui/cfg/expanded-cfg.rs +++ b/tests/ui/cfg/expanded-cfg.rs @@ -1,5 +1,7 @@ //@ check-pass +#![allow(unexpected_cfgs)] // since we different cfgs + macro_rules! mac { {} => { #[cfg(attr)] diff --git a/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.rs b/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.rs index 96e326e02ad..3ced3a630e3 100644 --- a/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.rs +++ b/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.rs @@ -1,5 +1,5 @@ //@ check-fail -//@ compile-flags:--cfg foo +//@ compile-flags:--cfg foo --check-cfg=cfg(foo) #![cfg_attr(foo, crate_type="bin")] //~^ERROR `crate_type` within diff --git a/tests/ui/check-cfg/allow-at-crate-level.rs b/tests/ui/check-cfg/allow-at-crate-level.rs index 03b4676ad5f..9dc2416a3a9 100644 --- a/tests/ui/check-cfg/allow-at-crate-level.rs +++ b/tests/ui/check-cfg/allow-at-crate-level.rs @@ -1,6 +1,7 @@ // This test check that #![allow(unexpected_cfgs)] works with --cfg // //@ check-pass +//@ no-auto-check-cfg //@ compile-flags: --cfg=unexpected --check-cfg=cfg() #![allow(unexpected_cfgs)] diff --git a/tests/ui/check-cfg/allow-macro-cfg.rs b/tests/ui/check-cfg/allow-macro-cfg.rs index 3db6e18d77a..b3c706d6d2b 100644 --- a/tests/ui/check-cfg/allow-macro-cfg.rs +++ b/tests/ui/check-cfg/allow-macro-cfg.rs @@ -1,6 +1,7 @@ // This test check that local #[allow(unexpected_cfgs)] works // //@ check-pass +//@ no-auto-check-cfg //@ compile-flags: --check-cfg=cfg() #[allow(unexpected_cfgs)] diff --git a/tests/ui/check-cfg/allow-same-level.rs b/tests/ui/check-cfg/allow-same-level.rs index e932ece6ee7..ff724174cea 100644 --- a/tests/ui/check-cfg/allow-same-level.rs +++ b/tests/ui/check-cfg/allow-same-level.rs @@ -1,6 +1,7 @@ // This test check that #[allow(unexpected_cfgs)] doesn't work if put on the same level // //@ check-pass +//@ no-auto-check-cfg //@ compile-flags: --check-cfg=cfg() #[allow(unexpected_cfgs)] diff --git a/tests/ui/check-cfg/allow-same-level.stderr b/tests/ui/check-cfg/allow-same-level.stderr index 349f41cb142..99e81d3bba6 100644 --- a/tests/ui/check-cfg/allow-same-level.stderr +++ b/tests/ui/check-cfg/allow-same-level.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `FALSE` - --> $DIR/allow-same-level.rs:7:7 + --> $DIR/allow-same-level.rs:8:7 | LL | #[cfg(FALSE)] | ^^^^^ diff --git a/tests/ui/check-cfg/allow-top-level.rs b/tests/ui/check-cfg/allow-top-level.rs index 0f88543d847..cf94ed5da42 100644 --- a/tests/ui/check-cfg/allow-top-level.rs +++ b/tests/ui/check-cfg/allow-top-level.rs @@ -1,6 +1,7 @@ // This test check that a top-level #![allow(unexpected_cfgs)] works // //@ check-pass +//@ no-auto-check-cfg //@ compile-flags: --check-cfg=cfg() #![allow(unexpected_cfgs)] diff --git a/tests/ui/check-cfg/allow-upper-level.rs b/tests/ui/check-cfg/allow-upper-level.rs index d03d0cab37b..2e6664c30d3 100644 --- a/tests/ui/check-cfg/allow-upper-level.rs +++ b/tests/ui/check-cfg/allow-upper-level.rs @@ -1,6 +1,7 @@ // This test check that #[allow(unexpected_cfgs)] work if put on an upper level // //@ check-pass +//@ no-auto-check-cfg //@ compile-flags: --check-cfg=cfg() #[allow(unexpected_cfgs)] diff --git a/tests/ui/check-cfg/cargo-feature.none.stderr b/tests/ui/check-cfg/cargo-feature.none.stderr index 0b914c2bc35..09a1c950267 100644 --- a/tests/ui/check-cfg/cargo-feature.none.stderr +++ b/tests/ui/check-cfg/cargo-feature.none.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `serde` - --> $DIR/cargo-feature.rs:13:7 + --> $DIR/cargo-feature.rs:14:7 | LL | #[cfg(feature = "serde")] | ^^^^^^^^^^^^^^^^^ help: remove the condition @@ -10,7 +10,7 @@ LL | #[cfg(feature = "serde")] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: (none) - --> $DIR/cargo-feature.rs:17:7 + --> $DIR/cargo-feature.rs:18:7 | LL | #[cfg(feature)] | ^^^^^^^ help: remove the condition @@ -20,7 +20,7 @@ LL | #[cfg(feature)] = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `tokio_unstable` - --> $DIR/cargo-feature.rs:21:7 + --> $DIR/cargo-feature.rs:22:7 | LL | #[cfg(tokio_unstable)] | ^^^^^^^^^^^^^^ @@ -30,7 +30,7 @@ LL | #[cfg(tokio_unstable)] = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `CONFIG_NVME` - --> $DIR/cargo-feature.rs:25:7 + --> $DIR/cargo-feature.rs:26:7 | LL | #[cfg(CONFIG_NVME = "m")] | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/check-cfg/cargo-feature.rs b/tests/ui/check-cfg/cargo-feature.rs index ced0d381d2d..13faf7f2820 100644 --- a/tests/ui/check-cfg/cargo-feature.rs +++ b/tests/ui/check-cfg/cargo-feature.rs @@ -3,6 +3,7 @@ // list of all the expected names // //@ check-pass +//@ no-auto-check-cfg //@ revisions: some none //@ rustc-env:CARGO_CRATE_NAME=foo //@ [none]compile-flags: --check-cfg=cfg(feature,values()) diff --git a/tests/ui/check-cfg/cargo-feature.some.stderr b/tests/ui/check-cfg/cargo-feature.some.stderr index 1a4ef89efc1..4db9c66fc86 100644 --- a/tests/ui/check-cfg/cargo-feature.some.stderr +++ b/tests/ui/check-cfg/cargo-feature.some.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `serde` - --> $DIR/cargo-feature.rs:13:7 + --> $DIR/cargo-feature.rs:14:7 | LL | #[cfg(feature = "serde")] | ^^^^^^^^^^^^^^^^^ @@ -10,7 +10,7 @@ LL | #[cfg(feature = "serde")] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: (none) - --> $DIR/cargo-feature.rs:17:7 + --> $DIR/cargo-feature.rs:18:7 | LL | #[cfg(feature)] | ^^^^^^^- help: specify a config value: `= "bitcode"` @@ -20,7 +20,7 @@ LL | #[cfg(feature)] = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `tokio_unstable` - --> $DIR/cargo-feature.rs:21:7 + --> $DIR/cargo-feature.rs:22:7 | LL | #[cfg(tokio_unstable)] | ^^^^^^^^^^^^^^ @@ -30,7 +30,7 @@ LL | #[cfg(tokio_unstable)] = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `m` - --> $DIR/cargo-feature.rs:25:7 + --> $DIR/cargo-feature.rs:26:7 | LL | #[cfg(CONFIG_NVME = "m")] | ^^^^^^^^^^^^^^--- diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.rs b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.rs index 79d4e45c13b..dd82ccd2c51 100644 --- a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.rs +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.rs @@ -2,6 +2,7 @@ // This test checks we won't suggest more than 3 span suggestions for cfg names // //@ check-pass +//@ no-auto-check-cfg //@ compile-flags: --check-cfg=cfg(foo,values("value")) --check-cfg=cfg(bar,values("value")) --check-cfg=cfg(bee,values("value")) --check-cfg=cfg(cow,values("value")) #[cfg(value)] diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr index 23ae4c55e42..f1393c55819 100644 --- a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `value` - --> $DIR/cfg-value-for-cfg-name-duplicate.rs:7:7 + --> $DIR/cfg-value-for-cfg-name-duplicate.rs:8:7 | LL | #[cfg(value)] | ^^^^^ diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.rs b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.rs index f2fd050bb75..3a94b6a6072 100644 --- a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.rs +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.rs @@ -2,6 +2,7 @@ // This test checks that when a single cfg has a value for user's specified name // //@ check-pass +//@ no-auto-check-cfg //@ compile-flags: --check-cfg=cfg(foo,values("my_value")) --check-cfg=cfg(bar,values("my_value")) #[cfg(my_value)] diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr index b5faaf6029c..3d4f430c2bb 100644 --- a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `my_value` - --> $DIR/cfg-value-for-cfg-name-multiple.rs:7:7 + --> $DIR/cfg-value-for-cfg-name-multiple.rs:8:7 | LL | #[cfg(my_value)] | ^^^^^^^^ diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name.rs b/tests/ui/check-cfg/cfg-value-for-cfg-name.rs index e8f9095655b..50f2fbab603 100644 --- a/tests/ui/check-cfg/cfg-value-for-cfg-name.rs +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name.rs @@ -3,6 +3,7 @@ // suggest to use `#[cfg(target_os = "linux")]` instead of `#[cfg(linux)]` // //@ check-pass +//@ no-auto-check-cfg //@ compile-flags: --check-cfg=cfg() #[cfg(linux)] diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr index 01586a6c71d..142d10076e9 100644 --- a/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `linux` - --> $DIR/cfg-value-for-cfg-name.rs:8:7 + --> $DIR/cfg-value-for-cfg-name.rs:9:7 | LL | #[cfg(linux)] | ^^^^^ help: found config with similar value: `target_os = "linux"` @@ -10,7 +10,7 @@ LL | #[cfg(linux)] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition name: `linux` - --> $DIR/cfg-value-for-cfg-name.rs:13:7 + --> $DIR/cfg-value-for-cfg-name.rs:14:7 | LL | #[cfg(linux = "os-name")] | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/check-cfg/compact-names.rs b/tests/ui/check-cfg/compact-names.rs index ddbd20b99b2..931afdf986f 100644 --- a/tests/ui/check-cfg/compact-names.rs +++ b/tests/ui/check-cfg/compact-names.rs @@ -1,6 +1,7 @@ // This test check that we correctly emit an warning for compact cfg // //@ check-pass +//@ no-auto-check-cfg //@ compile-flags: --check-cfg=cfg() #![feature(cfg_target_compact)] diff --git a/tests/ui/check-cfg/compact-names.stderr b/tests/ui/check-cfg/compact-names.stderr index 929501b420a..dd19f606620 100644 --- a/tests/ui/check-cfg/compact-names.stderr +++ b/tests/ui/check-cfg/compact-names.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `target_architecture` - --> $DIR/compact-names.rs:11:28 + --> $DIR/compact-names.rs:12:28 | LL | #[cfg(target(os = "linux", architecture = "arm"))] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/check-cfg/compact-values.rs b/tests/ui/check-cfg/compact-values.rs index bda4686ebd7..f13c23f6895 100644 --- a/tests/ui/check-cfg/compact-values.rs +++ b/tests/ui/check-cfg/compact-values.rs @@ -1,6 +1,7 @@ // This test check that we correctly emit an warning for compact cfg // //@ check-pass +//@ no-auto-check-cfg //@ compile-flags: --check-cfg=cfg() #![feature(cfg_target_compact)] diff --git a/tests/ui/check-cfg/compact-values.stderr b/tests/ui/check-cfg/compact-values.stderr index 45d084c46bf..4fe921dd24b 100644 --- a/tests/ui/check-cfg/compact-values.stderr +++ b/tests/ui/check-cfg/compact-values.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `X` - --> $DIR/compact-values.rs:11:28 + --> $DIR/compact-values.rs:12:28 | LL | #[cfg(target(os = "linux", pointer_width = "X"))] | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/check-cfg/concat-values.rs b/tests/ui/check-cfg/concat-values.rs index c546590a2c1..6cbc5d6074c 100644 --- a/tests/ui/check-cfg/concat-values.rs +++ b/tests/ui/check-cfg/concat-values.rs @@ -1,4 +1,5 @@ //@ check-pass +//@ no-auto-check-cfg //@ compile-flags: --check-cfg=cfg(my_cfg,values("foo")) --check-cfg=cfg(my_cfg,values("bar")) //@ compile-flags: --check-cfg=cfg(my_cfg,values()) diff --git a/tests/ui/check-cfg/concat-values.stderr b/tests/ui/check-cfg/concat-values.stderr index ca8b58f73e5..a508c397661 100644 --- a/tests/ui/check-cfg/concat-values.stderr +++ b/tests/ui/check-cfg/concat-values.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: (none) - --> $DIR/concat-values.rs:5:7 + --> $DIR/concat-values.rs:6:7 | LL | #[cfg(my_cfg)] | ^^^^^^ @@ -10,7 +10,7 @@ LL | #[cfg(my_cfg)] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `unk` - --> $DIR/concat-values.rs:9:7 + --> $DIR/concat-values.rs:10:7 | LL | #[cfg(my_cfg = "unk")] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/check-cfg/diagnotics.cargo.stderr b/tests/ui/check-cfg/diagnotics.cargo.stderr index 05c52bf59fa..16417fe0105 100644 --- a/tests/ui/check-cfg/diagnotics.cargo.stderr +++ b/tests/ui/check-cfg/diagnotics.cargo.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `featur` - --> $DIR/diagnotics.rs:7:7 + --> $DIR/diagnotics.rs:8:7 | LL | #[cfg(featur)] | ^^^^^^ help: there is a config with a similar name: `feature` @@ -9,7 +9,7 @@ LL | #[cfg(featur)] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition name: `featur` - --> $DIR/diagnotics.rs:11:7 + --> $DIR/diagnotics.rs:12:7 | LL | #[cfg(featur = "foo")] | ^^^^^^^^^^^^^^ @@ -21,7 +21,7 @@ LL | #[cfg(feature = "foo")] | ~~~~~~~ warning: unexpected `cfg` condition name: `featur` - --> $DIR/diagnotics.rs:15:7 + --> $DIR/diagnotics.rs:16:7 | LL | #[cfg(featur = "fo")] | ^^^^^^^^^^^^^ @@ -34,7 +34,7 @@ LL | #[cfg(feature = "foo")] | ~~~~~~~~~~~~~~~ warning: unexpected `cfg` condition name: `no_value` - --> $DIR/diagnotics.rs:22:7 + --> $DIR/diagnotics.rs:23:7 | LL | #[cfg(no_value)] | ^^^^^^^^ help: there is a config with a similar name: `no_values` @@ -43,7 +43,7 @@ LL | #[cfg(no_value)] = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `no_value` - --> $DIR/diagnotics.rs:26:7 + --> $DIR/diagnotics.rs:27:7 | LL | #[cfg(no_value = "foo")] | ^^^^^^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | #[cfg(no_values)] | ~~~~~~~~~ warning: unexpected `cfg` condition value: `bar` - --> $DIR/diagnotics.rs:30:7 + --> $DIR/diagnotics.rs:31:7 | LL | #[cfg(no_values = "bar")] | ^^^^^^^^^-------- diff --git a/tests/ui/check-cfg/diagnotics.rs b/tests/ui/check-cfg/diagnotics.rs index cccd6f9bbc3..b8268ec5606 100644 --- a/tests/ui/check-cfg/diagnotics.rs +++ b/tests/ui/check-cfg/diagnotics.rs @@ -1,4 +1,5 @@ //@ check-pass +//@ no-auto-check-cfg //@ revisions: cargo rustc //@ [rustc]unset-rustc-env:CARGO_CRATE_NAME //@ [cargo]rustc-env:CARGO_CRATE_NAME=foo diff --git a/tests/ui/check-cfg/diagnotics.rustc.stderr b/tests/ui/check-cfg/diagnotics.rustc.stderr index 0a938d2143e..0bd6ce156bb 100644 --- a/tests/ui/check-cfg/diagnotics.rustc.stderr +++ b/tests/ui/check-cfg/diagnotics.rustc.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `featur` - --> $DIR/diagnotics.rs:7:7 + --> $DIR/diagnotics.rs:8:7 | LL | #[cfg(featur)] | ^^^^^^ help: there is a config with a similar name: `feature` @@ -10,7 +10,7 @@ LL | #[cfg(featur)] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition name: `featur` - --> $DIR/diagnotics.rs:11:7 + --> $DIR/diagnotics.rs:12:7 | LL | #[cfg(featur = "foo")] | ^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | #[cfg(feature = "foo")] | ~~~~~~~ warning: unexpected `cfg` condition name: `featur` - --> $DIR/diagnotics.rs:15:7 + --> $DIR/diagnotics.rs:16:7 | LL | #[cfg(featur = "fo")] | ^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL | #[cfg(feature = "foo")] | ~~~~~~~~~~~~~~~ warning: unexpected `cfg` condition name: `no_value` - --> $DIR/diagnotics.rs:22:7 + --> $DIR/diagnotics.rs:23:7 | LL | #[cfg(no_value)] | ^^^^^^^^ help: there is a config with a similar name: `no_values` @@ -46,7 +46,7 @@ LL | #[cfg(no_value)] = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `no_value` - --> $DIR/diagnotics.rs:26:7 + --> $DIR/diagnotics.rs:27:7 | LL | #[cfg(no_value = "foo")] | ^^^^^^^^^^^^^^^^ @@ -59,7 +59,7 @@ LL | #[cfg(no_values)] | ~~~~~~~~~ warning: unexpected `cfg` condition value: `bar` - --> $DIR/diagnotics.rs:30:7 + --> $DIR/diagnotics.rs:31:7 | LL | #[cfg(no_values = "bar")] | ^^^^^^^^^-------- diff --git a/tests/ui/check-cfg/empty-values.rs b/tests/ui/check-cfg/empty-values.rs index cad2d351b96..cf7a7d7d1c0 100644 --- a/tests/ui/check-cfg/empty-values.rs +++ b/tests/ui/check-cfg/empty-values.rs @@ -1,6 +1,7 @@ // Check that we detect unexpected value when none are allowed // //@ check-pass +//@ no-auto-check-cfg //@ compile-flags: --check-cfg=cfg(foo,values()) #[cfg(foo = "foo")] diff --git a/tests/ui/check-cfg/empty-values.stderr b/tests/ui/check-cfg/empty-values.stderr index 1f773b10316..7f57a4ba593 100644 --- a/tests/ui/check-cfg/empty-values.stderr +++ b/tests/ui/check-cfg/empty-values.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `foo` - --> $DIR/empty-values.rs:6:7 + --> $DIR/empty-values.rs:7:7 | LL | #[cfg(foo = "foo")] | ^^^^^^^^^^^ help: remove the condition @@ -10,7 +10,7 @@ LL | #[cfg(foo = "foo")] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: (none) - --> $DIR/empty-values.rs:10:7 + --> $DIR/empty-values.rs:11:7 | LL | #[cfg(foo)] | ^^^ help: remove the condition diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr index 9537d4f5172..91afe766c8d 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `unknown_key` - --> $DIR/exhaustive-names-values.rs:9:7 + --> $DIR/exhaustive-names-values.rs:10:7 | LL | #[cfg(unknown_key = "value")] | ^^^^^^^^^^^^^^^^^^^^^ @@ -10,7 +10,7 @@ LL | #[cfg(unknown_key = "value")] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `value` - --> $DIR/exhaustive-names-values.rs:13:7 + --> $DIR/exhaustive-names-values.rs:14:7 | LL | #[cfg(test = "value")] | ^^^^---------- @@ -21,7 +21,7 @@ LL | #[cfg(test = "value")] = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `feature` - --> $DIR/exhaustive-names-values.rs:17:7 + --> $DIR/exhaustive-names-values.rs:18:7 | LL | #[cfg(feature = "unk")] | ^^^^^^^^^^^^^^^ @@ -30,7 +30,7 @@ LL | #[cfg(feature = "unk")] = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `feature` - --> $DIR/exhaustive-names-values.rs:24:7 + --> $DIR/exhaustive-names-values.rs:25:7 | LL | #[cfg(feature = "std")] | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr index d63d8627953..93b0621e224 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `unknown_key` - --> $DIR/exhaustive-names-values.rs:9:7 + --> $DIR/exhaustive-names-values.rs:10:7 | LL | #[cfg(unknown_key = "value")] | ^^^^^^^^^^^^^^^^^^^^^ @@ -10,7 +10,7 @@ LL | #[cfg(unknown_key = "value")] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `value` - --> $DIR/exhaustive-names-values.rs:13:7 + --> $DIR/exhaustive-names-values.rs:14:7 | LL | #[cfg(test = "value")] | ^^^^---------- @@ -21,7 +21,7 @@ LL | #[cfg(test = "value")] = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `unk` - --> $DIR/exhaustive-names-values.rs:17:7 + --> $DIR/exhaustive-names-values.rs:18:7 | LL | #[cfg(feature = "unk")] | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/check-cfg/exhaustive-names-values.full.stderr b/tests/ui/check-cfg/exhaustive-names-values.full.stderr index d63d8627953..93b0621e224 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.full.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.full.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `unknown_key` - --> $DIR/exhaustive-names-values.rs:9:7 + --> $DIR/exhaustive-names-values.rs:10:7 | LL | #[cfg(unknown_key = "value")] | ^^^^^^^^^^^^^^^^^^^^^ @@ -10,7 +10,7 @@ LL | #[cfg(unknown_key = "value")] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `value` - --> $DIR/exhaustive-names-values.rs:13:7 + --> $DIR/exhaustive-names-values.rs:14:7 | LL | #[cfg(test = "value")] | ^^^^---------- @@ -21,7 +21,7 @@ LL | #[cfg(test = "value")] = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `unk` - --> $DIR/exhaustive-names-values.rs:17:7 + --> $DIR/exhaustive-names-values.rs:18:7 | LL | #[cfg(feature = "unk")] | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/check-cfg/exhaustive-names-values.rs b/tests/ui/check-cfg/exhaustive-names-values.rs index f6c3e1f575a..a6190f15dbb 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.rs +++ b/tests/ui/check-cfg/exhaustive-names-values.rs @@ -1,6 +1,7 @@ // Check warning for unexpected cfg in the code. // //@ check-pass +//@ no-auto-check-cfg //@ revisions: empty_cfg feature full //@ [empty_cfg]compile-flags: --check-cfg=cfg() //@ [feature]compile-flags: --check-cfg=cfg(feature,values("std")) diff --git a/tests/ui/check-cfg/exhaustive-names.rs b/tests/ui/check-cfg/exhaustive-names.rs index 23bde4dff55..5d77cc10ca4 100644 --- a/tests/ui/check-cfg/exhaustive-names.rs +++ b/tests/ui/check-cfg/exhaustive-names.rs @@ -1,6 +1,7 @@ // Check warning for unexpected cfg // //@ check-pass +//@ no-auto-check-cfg //@ compile-flags: --check-cfg=cfg() #[cfg(unknown_key = "value")] diff --git a/tests/ui/check-cfg/exhaustive-names.stderr b/tests/ui/check-cfg/exhaustive-names.stderr index c42adec94b2..f4eb5a640ae 100644 --- a/tests/ui/check-cfg/exhaustive-names.stderr +++ b/tests/ui/check-cfg/exhaustive-names.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `unknown_key` - --> $DIR/exhaustive-names.rs:6:7 + --> $DIR/exhaustive-names.rs:7:7 | LL | #[cfg(unknown_key = "value")] | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr index 63ba2c68625..a3c0f36aee8 100644 --- a/tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr +++ b/tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `value` - --> $DIR/exhaustive-values.rs:8:7 + --> $DIR/exhaustive-values.rs:9:7 | LL | #[cfg(test = "value")] | ^^^^---------- diff --git a/tests/ui/check-cfg/exhaustive-values.rs b/tests/ui/check-cfg/exhaustive-values.rs index 029b2ff2c69..b4ce2ac98dc 100644 --- a/tests/ui/check-cfg/exhaustive-values.rs +++ b/tests/ui/check-cfg/exhaustive-values.rs @@ -1,6 +1,7 @@ // Check warning for unexpected cfg value // //@ check-pass +//@ no-auto-check-cfg //@ revisions: empty_cfg without_names //@ [empty_cfg]compile-flags: --check-cfg=cfg() //@ [without_names]compile-flags: --check-cfg=cfg(any()) diff --git a/tests/ui/check-cfg/exhaustive-values.without_names.stderr b/tests/ui/check-cfg/exhaustive-values.without_names.stderr index 63ba2c68625..a3c0f36aee8 100644 --- a/tests/ui/check-cfg/exhaustive-values.without_names.stderr +++ b/tests/ui/check-cfg/exhaustive-values.without_names.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `value` - --> $DIR/exhaustive-values.rs:8:7 + --> $DIR/exhaustive-values.rs:9:7 | LL | #[cfg(test = "value")] | ^^^^---------- diff --git a/tests/ui/check-cfg/invalid-arguments.rs b/tests/ui/check-cfg/invalid-arguments.rs index 84087a16e80..c0b58ede97f 100644 --- a/tests/ui/check-cfg/invalid-arguments.rs +++ b/tests/ui/check-cfg/invalid-arguments.rs @@ -1,6 +1,7 @@ // Check that invalid --check-cfg are rejected // //@ check-fail +//@ no-auto-check-cfg //@ revisions: anything_else //@ revisions: string_for_name_1 string_for_name_2 multiple_any multiple_values //@ revisions: multiple_values_any not_empty_any not_empty_values_any diff --git a/tests/ui/check-cfg/mix.rs b/tests/ui/check-cfg/mix.rs index ab8a180bc6f..ac244f4fc09 100644 --- a/tests/ui/check-cfg/mix.rs +++ b/tests/ui/check-cfg/mix.rs @@ -3,6 +3,7 @@ // we correctly lint on the `cfg!` macro and `cfg_attr` attribute. // //@ check-pass +//@ no-auto-check-cfg //@ compile-flags: --cfg feature="bar" --cfg unknown_name //@ compile-flags: --check-cfg=cfg(feature,values("foo")) diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index 557fdcbf38d..1ccdd10d123 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `widnows` - --> $DIR/mix.rs:12:7 + --> $DIR/mix.rs:13:7 | LL | #[cfg(widnows)] | ^^^^^^^ help: there is a config with a similar name: `windows` @@ -9,7 +9,7 @@ LL | #[cfg(widnows)] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: (none) - --> $DIR/mix.rs:16:7 + --> $DIR/mix.rs:17:7 | LL | #[cfg(feature)] | ^^^^^^^- help: specify a config value: `= "foo"` @@ -19,7 +19,7 @@ LL | #[cfg(feature)] = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `bar` - --> $DIR/mix.rs:23:7 + --> $DIR/mix.rs:24:7 | LL | #[cfg(feature = "bar")] | ^^^^^^^^^^^^^^^ @@ -29,7 +29,7 @@ LL | #[cfg(feature = "bar")] = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:27:7 + --> $DIR/mix.rs:28:7 | LL | #[cfg(feature = "zebra")] | ^^^^^^^^^^^^^^^^^ @@ -39,7 +39,7 @@ LL | #[cfg(feature = "zebra")] = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `uu` - --> $DIR/mix.rs:31:12 + --> $DIR/mix.rs:32:12 | LL | #[cfg_attr(uu, test)] | ^^ @@ -49,7 +49,7 @@ LL | #[cfg_attr(uu, test)] = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `widnows` - --> $DIR/mix.rs:40:10 + --> $DIR/mix.rs:41:10 | LL | cfg!(widnows); | ^^^^^^^ help: there is a config with a similar name: `windows` @@ -58,7 +58,7 @@ LL | cfg!(widnows); = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `bar` - --> $DIR/mix.rs:43:10 + --> $DIR/mix.rs:44:10 | LL | cfg!(feature = "bar"); | ^^^^^^^^^^^^^^^ @@ -68,7 +68,7 @@ LL | cfg!(feature = "bar"); = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:45:10 + --> $DIR/mix.rs:46:10 | LL | cfg!(feature = "zebra"); | ^^^^^^^^^^^^^^^^^ @@ -78,7 +78,7 @@ LL | cfg!(feature = "zebra"); = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:47:10 + --> $DIR/mix.rs:48:10 | LL | cfg!(xxx = "foo"); | ^^^^^^^^^^^ @@ -87,7 +87,7 @@ LL | cfg!(xxx = "foo"); = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:49:10 + --> $DIR/mix.rs:50:10 | LL | cfg!(xxx); | ^^^ @@ -96,7 +96,7 @@ LL | cfg!(xxx); = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:51:14 + --> $DIR/mix.rs:52:14 | LL | cfg!(any(xxx, windows)); | ^^^ @@ -105,7 +105,7 @@ LL | cfg!(any(xxx, windows)); = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `bad` - --> $DIR/mix.rs:53:14 + --> $DIR/mix.rs:54:14 | LL | cfg!(any(feature = "bad", windows)); | ^^^^^^^^^^^^^^^ @@ -115,7 +115,7 @@ LL | cfg!(any(feature = "bad", windows)); = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:55:23 + --> $DIR/mix.rs:56:23 | LL | cfg!(any(windows, xxx)); | ^^^ @@ -124,7 +124,7 @@ LL | cfg!(any(windows, xxx)); = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:57:20 + --> $DIR/mix.rs:58:20 | LL | cfg!(all(unix, xxx)); | ^^^ @@ -133,7 +133,7 @@ LL | cfg!(all(unix, xxx)); = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `aa` - --> $DIR/mix.rs:59:14 + --> $DIR/mix.rs:60:14 | LL | cfg!(all(aa, bb)); | ^^ @@ -142,7 +142,7 @@ LL | cfg!(all(aa, bb)); = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `bb` - --> $DIR/mix.rs:59:18 + --> $DIR/mix.rs:60:18 | LL | cfg!(all(aa, bb)); | ^^ @@ -151,7 +151,7 @@ LL | cfg!(all(aa, bb)); = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `aa` - --> $DIR/mix.rs:62:14 + --> $DIR/mix.rs:63:14 | LL | cfg!(any(aa, bb)); | ^^ @@ -160,7 +160,7 @@ LL | cfg!(any(aa, bb)); = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `bb` - --> $DIR/mix.rs:62:18 + --> $DIR/mix.rs:63:18 | LL | cfg!(any(aa, bb)); | ^^ @@ -169,7 +169,7 @@ LL | cfg!(any(aa, bb)); = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:65:20 + --> $DIR/mix.rs:66:20 | LL | cfg!(any(unix, feature = "zebra")); | ^^^^^^^^^^^^^^^^^ @@ -179,7 +179,7 @@ LL | cfg!(any(unix, feature = "zebra")); = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:67:14 + --> $DIR/mix.rs:68:14 | LL | cfg!(any(xxx, feature = "zebra")); | ^^^ @@ -188,7 +188,7 @@ LL | cfg!(any(xxx, feature = "zebra")); = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:67:19 + --> $DIR/mix.rs:68:19 | LL | cfg!(any(xxx, feature = "zebra")); | ^^^^^^^^^^^^^^^^^ @@ -198,7 +198,7 @@ LL | cfg!(any(xxx, feature = "zebra")); = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:70:14 + --> $DIR/mix.rs:71:14 | LL | cfg!(any(xxx, unix, xxx)); | ^^^ @@ -207,7 +207,7 @@ LL | cfg!(any(xxx, unix, xxx)); = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:70:25 + --> $DIR/mix.rs:71:25 | LL | cfg!(any(xxx, unix, xxx)); | ^^^ @@ -216,7 +216,7 @@ LL | cfg!(any(xxx, unix, xxx)); = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:73:14 + --> $DIR/mix.rs:74:14 | LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); | ^^^^^^^^^^^^^^^^^ @@ -226,7 +226,7 @@ LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:73:33 + --> $DIR/mix.rs:74:33 | LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); | ^^^^^^^^^^^^^^^^^ @@ -236,7 +236,7 @@ LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:73:52 + --> $DIR/mix.rs:74:52 | LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); | ^^^^^^^^^^^^^^^^^ @@ -246,7 +246,7 @@ LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:77:10 + --> $DIR/mix.rs:78:10 | LL | cfg!(target_feature = "zebra"); | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/check-cfg/no-expected-values.empty.stderr b/tests/ui/check-cfg/no-expected-values.empty.stderr index 0f181cc2ab1..9c7d970f35e 100644 --- a/tests/ui/check-cfg/no-expected-values.empty.stderr +++ b/tests/ui/check-cfg/no-expected-values.empty.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `foo` - --> $DIR/no-expected-values.rs:10:7 + --> $DIR/no-expected-values.rs:11:7 | LL | #[cfg(feature = "foo")] | ^^^^^^^-------- @@ -12,7 +12,7 @@ LL | #[cfg(feature = "foo")] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `foo` - --> $DIR/no-expected-values.rs:14:7 + --> $DIR/no-expected-values.rs:15:7 | LL | #[cfg(test = "foo")] | ^^^^-------- diff --git a/tests/ui/check-cfg/no-expected-values.mixed.stderr b/tests/ui/check-cfg/no-expected-values.mixed.stderr index 0f181cc2ab1..9c7d970f35e 100644 --- a/tests/ui/check-cfg/no-expected-values.mixed.stderr +++ b/tests/ui/check-cfg/no-expected-values.mixed.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `foo` - --> $DIR/no-expected-values.rs:10:7 + --> $DIR/no-expected-values.rs:11:7 | LL | #[cfg(feature = "foo")] | ^^^^^^^-------- @@ -12,7 +12,7 @@ LL | #[cfg(feature = "foo")] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `foo` - --> $DIR/no-expected-values.rs:14:7 + --> $DIR/no-expected-values.rs:15:7 | LL | #[cfg(test = "foo")] | ^^^^-------- diff --git a/tests/ui/check-cfg/no-expected-values.rs b/tests/ui/check-cfg/no-expected-values.rs index 42e7f45fa7a..58e0e0a10e2 100644 --- a/tests/ui/check-cfg/no-expected-values.rs +++ b/tests/ui/check-cfg/no-expected-values.rs @@ -1,6 +1,7 @@ // Check that we detect unexpected value when none are allowed // //@ check-pass +//@ no-auto-check-cfg //@ revisions: simple mixed empty //@ compile-flags: --check-cfg=cfg(values,simple,mixed,empty) //@ [simple]compile-flags: --check-cfg=cfg(test) --check-cfg=cfg(feature) diff --git a/tests/ui/check-cfg/no-expected-values.simple.stderr b/tests/ui/check-cfg/no-expected-values.simple.stderr index 0f181cc2ab1..9c7d970f35e 100644 --- a/tests/ui/check-cfg/no-expected-values.simple.stderr +++ b/tests/ui/check-cfg/no-expected-values.simple.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `foo` - --> $DIR/no-expected-values.rs:10:7 + --> $DIR/no-expected-values.rs:11:7 | LL | #[cfg(feature = "foo")] | ^^^^^^^-------- @@ -12,7 +12,7 @@ LL | #[cfg(feature = "foo")] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `foo` - --> $DIR/no-expected-values.rs:14:7 + --> $DIR/no-expected-values.rs:15:7 | LL | #[cfg(test = "foo")] | ^^^^-------- diff --git a/tests/ui/check-cfg/order-independant.rs b/tests/ui/check-cfg/order-independant.rs index 671d2e764d3..6acd1a41bab 100644 --- a/tests/ui/check-cfg/order-independant.rs +++ b/tests/ui/check-cfg/order-independant.rs @@ -1,5 +1,6 @@ //@ check-pass // +//@ no-auto-check-cfg //@ revisions: values_before values_after //@ compile-flags: --check-cfg=cfg(values_before,values_after) //@ [values_before]compile-flags: --check-cfg=cfg(a,values("b")) --check-cfg=cfg(a) diff --git a/tests/ui/check-cfg/order-independant.values_after.stderr b/tests/ui/check-cfg/order-independant.values_after.stderr index 7e18df8e1c2..69c3aa32020 100644 --- a/tests/ui/check-cfg/order-independant.values_after.stderr +++ b/tests/ui/check-cfg/order-independant.values_after.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `unk` - --> $DIR/order-independant.rs:11:7 + --> $DIR/order-independant.rs:12:7 | LL | #[cfg(a = "unk")] | ^^^^^^^^^ diff --git a/tests/ui/check-cfg/order-independant.values_before.stderr b/tests/ui/check-cfg/order-independant.values_before.stderr index 7e18df8e1c2..69c3aa32020 100644 --- a/tests/ui/check-cfg/order-independant.values_before.stderr +++ b/tests/ui/check-cfg/order-independant.values_before.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `unk` - --> $DIR/order-independant.rs:11:7 + --> $DIR/order-independant.rs:12:7 | LL | #[cfg(a = "unk")] | ^^^^^^^^^ diff --git a/tests/ui/check-cfg/stmt-no-ice.rs b/tests/ui/check-cfg/stmt-no-ice.rs index 866a5836db0..edd9febbe37 100644 --- a/tests/ui/check-cfg/stmt-no-ice.rs +++ b/tests/ui/check-cfg/stmt-no-ice.rs @@ -1,6 +1,7 @@ // This test checks that there is no ICE with this code // //@ check-pass +//@ no-auto-check-cfg //@ compile-flags:--check-cfg=cfg() fn main() { diff --git a/tests/ui/check-cfg/stmt-no-ice.stderr b/tests/ui/check-cfg/stmt-no-ice.stderr index e686cdddc1c..a6c72b0e6bf 100644 --- a/tests/ui/check-cfg/stmt-no-ice.stderr +++ b/tests/ui/check-cfg/stmt-no-ice.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `crossbeam_loom` - --> $DIR/stmt-no-ice.rs:7:11 + --> $DIR/stmt-no-ice.rs:8:11 | LL | #[cfg(crossbeam_loom)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/check-cfg/unexpected-cfg-name.rs b/tests/ui/check-cfg/unexpected-cfg-name.rs index 365c29d10fb..8178df8b87c 100644 --- a/tests/ui/check-cfg/unexpected-cfg-name.rs +++ b/tests/ui/check-cfg/unexpected-cfg-name.rs @@ -1,6 +1,7 @@ // Check warning for unexpected configuration name // //@ check-pass +//@ no-auto-check-cfg //@ compile-flags: --check-cfg=cfg() #[cfg(widnows)] diff --git a/tests/ui/check-cfg/unexpected-cfg-name.stderr b/tests/ui/check-cfg/unexpected-cfg-name.stderr index 0b265078aa5..c652c8e27bc 100644 --- a/tests/ui/check-cfg/unexpected-cfg-name.stderr +++ b/tests/ui/check-cfg/unexpected-cfg-name.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `widnows` - --> $DIR/unexpected-cfg-name.rs:6:7 + --> $DIR/unexpected-cfg-name.rs:7:7 | LL | #[cfg(widnows)] | ^^^^^^^ help: there is a config with a similar name: `windows` diff --git a/tests/ui/check-cfg/unexpected-cfg-value.rs b/tests/ui/check-cfg/unexpected-cfg-value.rs index 583cf40c485..b6efcaac44c 100644 --- a/tests/ui/check-cfg/unexpected-cfg-value.rs +++ b/tests/ui/check-cfg/unexpected-cfg-value.rs @@ -1,6 +1,7 @@ // Check for unexpected configuration value in the code. // //@ check-pass +//@ no-auto-check-cfg //@ compile-flags: --cfg=feature="rand" //@ compile-flags: --check-cfg=cfg(feature,values("serde","full")) diff --git a/tests/ui/check-cfg/unexpected-cfg-value.stderr b/tests/ui/check-cfg/unexpected-cfg-value.stderr index c3001208492..efcf65bb707 100644 --- a/tests/ui/check-cfg/unexpected-cfg-value.stderr +++ b/tests/ui/check-cfg/unexpected-cfg-value.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `sedre` - --> $DIR/unexpected-cfg-value.rs:7:7 + --> $DIR/unexpected-cfg-value.rs:8:7 | LL | #[cfg(feature = "sedre")] | ^^^^^^^^^^------- @@ -12,7 +12,7 @@ LL | #[cfg(feature = "sedre")] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `rand` - --> $DIR/unexpected-cfg-value.rs:14:7 + --> $DIR/unexpected-cfg-value.rs:15:7 | LL | #[cfg(feature = "rand")] | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/check-cfg/unknown-values.rs b/tests/ui/check-cfg/unknown-values.rs index 7b2b00fe9d4..ef0590d76d2 100644 --- a/tests/ui/check-cfg/unknown-values.rs +++ b/tests/ui/check-cfg/unknown-values.rs @@ -1,6 +1,7 @@ // Check that no warning is emitted for unknown cfg value // //@ check-pass +//@ no-auto-check-cfg //@ revisions: simple mixed with_values //@ compile-flags: --check-cfg=cfg(simple,mixed,with_values) //@ [simple]compile-flags: --check-cfg=cfg(foo,values(any())) diff --git a/tests/ui/check-cfg/values-none.explicit.stderr b/tests/ui/check-cfg/values-none.explicit.stderr index f75cc08f551..000eabdb22e 100644 --- a/tests/ui/check-cfg/values-none.explicit.stderr +++ b/tests/ui/check-cfg/values-none.explicit.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `too` - --> $DIR/values-none.rs:10:7 + --> $DIR/values-none.rs:11:7 | LL | #[cfg(foo = "too")] | ^^^-------- @@ -12,7 +12,7 @@ LL | #[cfg(foo = "too")] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `bar` - --> $DIR/values-none.rs:15:7 + --> $DIR/values-none.rs:16:7 | LL | #[cfg(foo = "bar")] | ^^^-------- diff --git a/tests/ui/check-cfg/values-none.implicit.stderr b/tests/ui/check-cfg/values-none.implicit.stderr index f75cc08f551..000eabdb22e 100644 --- a/tests/ui/check-cfg/values-none.implicit.stderr +++ b/tests/ui/check-cfg/values-none.implicit.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `too` - --> $DIR/values-none.rs:10:7 + --> $DIR/values-none.rs:11:7 | LL | #[cfg(foo = "too")] | ^^^-------- @@ -12,7 +12,7 @@ LL | #[cfg(foo = "too")] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `bar` - --> $DIR/values-none.rs:15:7 + --> $DIR/values-none.rs:16:7 | LL | #[cfg(foo = "bar")] | ^^^-------- diff --git a/tests/ui/check-cfg/values-none.rs b/tests/ui/check-cfg/values-none.rs index bd9c0255b7d..6856d2f33af 100644 --- a/tests/ui/check-cfg/values-none.rs +++ b/tests/ui/check-cfg/values-none.rs @@ -1,5 +1,6 @@ //@ check-pass // +//@ no-auto-check-cfg //@ revisions: explicit implicit //@ [explicit]compile-flags: --check-cfg=cfg(foo,values(none())) //@ [implicit]compile-flags: --check-cfg=cfg(foo) diff --git a/tests/ui/check-cfg/values-target-json.rs b/tests/ui/check-cfg/values-target-json.rs index f3a27043e67..b52decdf6c0 100644 --- a/tests/ui/check-cfg/values-target-json.rs +++ b/tests/ui/check-cfg/values-target-json.rs @@ -1,6 +1,7 @@ // This test checks that we don't lint values defined by a custom target (target json) // //@ check-pass +//@ no-auto-check-cfg //@ needs-llvm-components: x86 //@ compile-flags: --crate-type=lib --check-cfg=cfg() --target={{src-base}}/check-cfg/my-awesome-platform.json diff --git a/tests/ui/check-cfg/well-known-names.rs b/tests/ui/check-cfg/well-known-names.rs index c277b84d9bd..b84710ca839 100644 --- a/tests/ui/check-cfg/well-known-names.rs +++ b/tests/ui/check-cfg/well-known-names.rs @@ -1,6 +1,7 @@ // This test checks that we lint on non well known names and that we don't lint on well known names // //@ check-pass +//@ no-auto-check-cfg //@ compile-flags: --check-cfg=cfg() #[cfg(target_oz = "linux")] diff --git a/tests/ui/check-cfg/well-known-names.stderr b/tests/ui/check-cfg/well-known-names.stderr index b2db777e8a8..2f07174b905 100644 --- a/tests/ui/check-cfg/well-known-names.stderr +++ b/tests/ui/check-cfg/well-known-names.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `target_oz` - --> $DIR/well-known-names.rs:6:7 + --> $DIR/well-known-names.rs:7:7 | LL | #[cfg(target_oz = "linux")] | ^^^^^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL | #[cfg(target_os = "linux")] | ~~~~~~~~~ warning: unexpected `cfg` condition name: `features` - --> $DIR/well-known-names.rs:13:7 + --> $DIR/well-known-names.rs:14:7 | LL | #[cfg(features = "foo")] | ^^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | #[cfg(features = "foo")] = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `feature` - --> $DIR/well-known-names.rs:17:7 + --> $DIR/well-known-names.rs:18:7 | LL | #[cfg(feature = "foo")] | ^^^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | #[cfg(feature = "foo")] = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `uniw` - --> $DIR/well-known-names.rs:21:7 + --> $DIR/well-known-names.rs:22:7 | LL | #[cfg(uniw)] | ^^^^ help: there is a config with a similar name: `unix` diff --git a/tests/ui/check-cfg/well-known-values.rs b/tests/ui/check-cfg/well-known-values.rs index 4c010a62d21..b821f8092dd 100644 --- a/tests/ui/check-cfg/well-known-values.rs +++ b/tests/ui/check-cfg/well-known-values.rs @@ -5,6 +5,7 @@ // values since the suggestion shows them. // //@ check-pass +//@ no-auto-check-cfg //@ compile-flags: --check-cfg=cfg() //@ compile-flags: -Zcheck-cfg-all-expected diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 1863032c386..cd5cdf3df3c 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:27:5 + --> $DIR/well-known-values.rs:28:5 | LL | clippy = "_UNEXPECTED_VALUE", | ^^^^^^---------------------- @@ -11,7 +11,7 @@ LL | clippy = "_UNEXPECTED_VALUE", = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:29:5 + --> $DIR/well-known-values.rs:30:5 | LL | debug_assertions = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^---------------------- @@ -22,7 +22,7 @@ LL | debug_assertions = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:31:5 + --> $DIR/well-known-values.rs:32:5 | LL | doc = "_UNEXPECTED_VALUE", | ^^^---------------------- @@ -33,7 +33,7 @@ LL | doc = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:33:5 + --> $DIR/well-known-values.rs:34:5 | LL | doctest = "_UNEXPECTED_VALUE", | ^^^^^^^---------------------- @@ -44,7 +44,7 @@ LL | doctest = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:35:5 + --> $DIR/well-known-values.rs:36:5 | LL | miri = "_UNEXPECTED_VALUE", | ^^^^---------------------- @@ -55,7 +55,7 @@ LL | miri = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:37:5 + --> $DIR/well-known-values.rs:38:5 | LL | overflow_checks = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^---------------------- @@ -66,7 +66,7 @@ LL | overflow_checks = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:39:5 + --> $DIR/well-known-values.rs:40:5 | LL | panic = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -75,7 +75,7 @@ LL | panic = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:41:5 + --> $DIR/well-known-values.rs:42:5 | LL | proc_macro = "_UNEXPECTED_VALUE", | ^^^^^^^^^^---------------------- @@ -86,7 +86,7 @@ LL | proc_macro = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:43:5 + --> $DIR/well-known-values.rs:44:5 | LL | relocation_model = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -95,7 +95,7 @@ LL | relocation_model = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:45:5 + --> $DIR/well-known-values.rs:46:5 | LL | sanitize = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -104,7 +104,7 @@ LL | sanitize = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:47:5 + --> $DIR/well-known-values.rs:48:5 | LL | target_abi = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -113,7 +113,7 @@ LL | target_abi = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:49:5 + --> $DIR/well-known-values.rs:50:5 | LL | target_arch = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -122,7 +122,7 @@ LL | target_arch = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:51:5 + --> $DIR/well-known-values.rs:52:5 | LL | target_endian = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -131,7 +131,7 @@ LL | target_endian = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:53:5 + --> $DIR/well-known-values.rs:54:5 | LL | target_env = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -140,7 +140,7 @@ LL | target_env = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:55:5 + --> $DIR/well-known-values.rs:56:5 | LL | target_family = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -149,7 +149,7 @@ LL | target_family = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:57:5 + --> $DIR/well-known-values.rs:58:5 | LL | target_feature = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -158,7 +158,7 @@ LL | target_feature = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:59:5 + --> $DIR/well-known-values.rs:60:5 | LL | target_has_atomic = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -167,7 +167,7 @@ LL | target_has_atomic = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:61:5 + --> $DIR/well-known-values.rs:62:5 | LL | target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -176,7 +176,7 @@ LL | target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:63:5 + --> $DIR/well-known-values.rs:64:5 | LL | target_has_atomic_load_store = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -185,7 +185,7 @@ LL | target_has_atomic_load_store = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:65:5 + --> $DIR/well-known-values.rs:66:5 | LL | target_os = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -194,7 +194,7 @@ LL | target_os = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:67:5 + --> $DIR/well-known-values.rs:68:5 | LL | target_pointer_width = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -203,7 +203,7 @@ LL | target_pointer_width = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:69:5 + --> $DIR/well-known-values.rs:70:5 | LL | target_thread_local = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^---------------------- @@ -214,7 +214,7 @@ LL | target_thread_local = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:71:5 + --> $DIR/well-known-values.rs:72:5 | LL | target_vendor = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -223,7 +223,7 @@ LL | target_vendor = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:73:5 + --> $DIR/well-known-values.rs:74:5 | LL | test = "_UNEXPECTED_VALUE", | ^^^^---------------------- @@ -234,7 +234,7 @@ LL | test = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:75:5 + --> $DIR/well-known-values.rs:76:5 | LL | ub_checks = "_UNEXPECTED_VALUE", | ^^^^^^^^^---------------------- @@ -245,7 +245,7 @@ LL | ub_checks = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:77:5 + --> $DIR/well-known-values.rs:78:5 | LL | unix = "_UNEXPECTED_VALUE", | ^^^^---------------------- @@ -256,7 +256,7 @@ LL | unix = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:79:5 + --> $DIR/well-known-values.rs:80:5 | LL | windows = "_UNEXPECTED_VALUE", | ^^^^^^^---------------------- @@ -267,7 +267,7 @@ LL | windows = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `linuz` - --> $DIR/well-known-values.rs:85:7 + --> $DIR/well-known-values.rs:86:7 | LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux` | ^^^^^^^^^^^^------- diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.svg b/tests/ui/codemap_tests/huge_multispan_highlight.svg index f1e96583ff0..7b6dbb17c6f 100644 --- a/tests/ui/codemap_tests/huge_multispan_highlight.svg +++ b/tests/ui/codemap_tests/huge_multispan_highlight.svg @@ -27,11 +27,11 @@ </tspan> <tspan x="10px" y="82px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> let _ = match true {</tspan> </tspan> - <tspan x="10px" y="100px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">----------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">`match` arms have incompatible types</tspan> + <tspan x="10px" y="100px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">----------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">`match` arms have incompatible types</tspan> </tspan> <tspan x="10px" y="118px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> true => (</tspan> </tspan> - <tspan x="10px" y="136px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">_________________-</tspan> + <tspan x="10px" y="136px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">_________________-</tspan> </tspan> <tspan x="10px" y="154px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> // last line shown in multispan header</tspan> </tspan> @@ -41,11 +41,11 @@ </tspan> <tspan x="10px" y="208px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> ),</tspan> </tspan> - <tspan x="10px" y="226px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan class="fg-ansi256-012 bold">|_________-</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">this is found to be of type `()`</tspan> + <tspan x="10px" y="226px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|_________-</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">this is found to be of type `()`</tspan> </tspan> <tspan x="10px" y="244px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> false => "</tspan> </tspan> - <tspan x="10px" y="262px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">__________________^</tspan> + <tspan x="10px" y="262px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">__________________^</tspan> </tspan> <tspan x="10px" y="280px"><tspan class="fg-ansi256-012 bold">...</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan> </tspan> @@ -53,7 +53,7 @@ </tspan> <tspan x="10px" y="316px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> ",</tspan> </tspan> - <tspan x="10px" y="334px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan class="fg-ansi256-009 bold">|_________^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected `()`, found `&str`</tspan> + <tspan x="10px" y="334px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|_________^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected `()`, found `&str`</tspan> </tspan> <tspan x="10px" y="352px"> </tspan> @@ -65,11 +65,11 @@ </tspan> <tspan x="10px" y="424px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> let _ = match true {</tspan> </tspan> - <tspan x="10px" y="442px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">----------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">`match` arms have incompatible types</tspan> + <tspan x="10px" y="442px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">----------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">`match` arms have incompatible types</tspan> </tspan> <tspan x="10px" y="460px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> true => (</tspan> </tspan> - <tspan x="10px" y="478px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">_________________-</tspan> + <tspan x="10px" y="478px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">_________________-</tspan> </tspan> <tspan x="10px" y="496px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan> </tspan> @@ -81,11 +81,11 @@ </tspan> <tspan x="10px" y="568px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> ),</tspan> </tspan> - <tspan x="10px" y="586px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan class="fg-ansi256-012 bold">|_________-</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">this is found to be of type `{integer}`</tspan> + <tspan x="10px" y="586px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|_________-</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">this is found to be of type `{integer}`</tspan> </tspan> <tspan x="10px" y="604px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> false => "</tspan> </tspan> - <tspan x="10px" y="622px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">__________________^</tspan> + <tspan x="10px" y="622px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">__________________^</tspan> </tspan> <tspan x="10px" y="640px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan> </tspan> @@ -99,7 +99,7 @@ </tspan> <tspan x="10px" y="730px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> ",</tspan> </tspan> - <tspan x="10px" y="748px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan class="fg-ansi256-009 bold">|_________^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected integer, found `&str`</tspan> + <tspan x="10px" y="748px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|_________^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected integer, found `&str`</tspan> </tspan> <tspan x="10px" y="766px"> </tspan> diff --git a/tests/ui/coercion/mut-mut-wont-coerce.rs b/tests/ui/coercion/mut-mut-wont-coerce.rs new file mode 100644 index 00000000000..e99566461a2 --- /dev/null +++ b/tests/ui/coercion/mut-mut-wont-coerce.rs @@ -0,0 +1,43 @@ +// Documents that Rust currently does not permit the coercion &mut &mut T -> *mut *mut T +// Making this compile was a feature request in rust-lang/rust#34117 but this is currently +// "working as intended". Allowing "deep pointer coercion" seems footgun-prone, and would +// require proceeding carefully. +use std::ops::{Deref, DerefMut}; + +struct Foo(i32); + +struct SmartPtr<T>(*mut T); + +impl<T> SmartPtr<T> { + fn get_addr(&mut self) -> &mut *mut T { + &mut self.0 + } +} + +impl<T> Deref for SmartPtr<T> { + type Target = T; + fn deref(&self) -> &T { + unsafe { &*self.0 } + } +} +impl<T> DerefMut for SmartPtr<T> { + fn deref_mut(&mut self) -> &mut T { + unsafe { &mut *self.0 } + } +} + +/// Puts a Foo into the pointer provided by the caller +fn make_foo(_: *mut *mut Foo) { + unimplemented!() +} + +fn main() { + let mut result: SmartPtr<Foo> = SmartPtr(std::ptr::null_mut()); + make_foo(&mut &mut *result); //~ mismatched types + //~^ expected `*mut *mut Foo`, found `&mut &mut Foo` + make_foo(out(&mut result)); // works, but makes one wonder why above coercion cannot happen +} + +fn out<T>(ptr: &mut SmartPtr<T>) -> &mut *mut T { + ptr.get_addr() +} diff --git a/tests/ui/coercion/mut-mut-wont-coerce.stderr b/tests/ui/coercion/mut-mut-wont-coerce.stderr new file mode 100644 index 00000000000..5daf9cbd3d3 --- /dev/null +++ b/tests/ui/coercion/mut-mut-wont-coerce.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/mut-mut-wont-coerce.rs:36:14 + | +LL | make_foo(&mut &mut *result); + | -------- ^^^^^^^^^^^^^^^^^ expected `*mut *mut Foo`, found `&mut &mut Foo` + | | + | arguments to this function are incorrect + | + = note: expected raw pointer `*mut *mut Foo` + found mutable reference `&mut &mut Foo` +note: function defined here + --> $DIR/mut-mut-wont-coerce.rs:30:4 + | +LL | fn make_foo(_: *mut *mut Foo) { + | ^^^^^^^^ ---------------- + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coherence/auxiliary/parametrized-trait.rs b/tests/ui/coherence/auxiliary/parametrized-trait.rs new file mode 100644 index 00000000000..88a3d5cd52d --- /dev/null +++ b/tests/ui/coherence/auxiliary/parametrized-trait.rs @@ -0,0 +1,2 @@ +pub trait Trait0<T, U, V> {} +pub trait Trait1<T, U> {} diff --git a/tests/ui/coherence/auxiliary/trait-with-assoc-ty.rs b/tests/ui/coherence/auxiliary/trait-with-assoc-ty.rs new file mode 100644 index 00000000000..d49538de580 --- /dev/null +++ b/tests/ui/coherence/auxiliary/trait-with-assoc-ty.rs @@ -0,0 +1,3 @@ +pub trait Trait { + type Assoc; +} diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr new file mode 100644 index 00000000000..2ffb6000ec8 --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr @@ -0,0 +1,19 @@ +error[E0119]: conflicting implementations of trait `Trait` for type `Box<_>` + --> $DIR/coherence-overlap-unnormalizable-projection-0.rs:27:1 + | +LL | / impl<T> Trait for T +LL | | where +LL | | T: 'static, +LL | | for<'a> T: WithAssoc<'a>, +LL | | for<'a> <T as WithAssoc<'a>>::Assoc: WhereBound, + | |____________________________________________________- first implementation here +... +LL | impl<T> Trait for Box<T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` + | + = note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>` + = note: downstream crates may implement trait `WhereBound` for type `<std::boxed::Box<_> as WithAssoc<'a>>::Assoc` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.next.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.next.stderr new file mode 100644 index 00000000000..99abdf65abd --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.next.stderr @@ -0,0 +1,18 @@ +error[E0119]: conflicting implementations of trait `Trait` for type `Box<_>` + --> $DIR/coherence-overlap-unnormalizable-projection-0.rs:27:1 + | +LL | / impl<T> Trait for T +LL | | where +LL | | T: 'static, +LL | | for<'a> T: WithAssoc<'a>, +LL | | for<'a> <T as WithAssoc<'a>>::Assoc: WhereBound, + | |____________________________________________________- first implementation here +... +LL | impl<T> Trait for Box<T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` + | + = note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.rs b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.rs new file mode 100644 index 00000000000..b8b6d8846ef --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.rs @@ -0,0 +1,42 @@ +// Regression test for soundness issue #114061: +// "Coherence incorrectly considers `unnormalizable_projection: Trait` to not hold even if it could" +#![crate_type = "lib"] + +//@ revisions: classic next +//@[next] compile-flags: -Znext-solver + +trait WhereBound {} +impl WhereBound for () {} + + +pub trait WithAssoc<'a> { + type Assoc; +} + +// These two impls of `Trait` overlap: + +pub trait Trait {} +impl<T> Trait for T +where + T: 'static, + for<'a> T: WithAssoc<'a>, + for<'a> <T as WithAssoc<'a>>::Assoc: WhereBound, +{ +} + +impl<T> Trait for Box<T> {} //~ ERROR conflicting implementations of trait `Trait` for type `Box<_>` + +// A downstream crate could write: +// +// use upstream::*; +// +// struct Local; +// impl WithAssoc<'_> for Box<Local> { +// type Assoc = (); +// } +// +// fn impls_trait<T: Trait>() {} +// +// fn main() { +// impls_trait::<Box<Local>>(); +// } diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr new file mode 100644 index 00000000000..49b236f9d2a --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr @@ -0,0 +1,19 @@ +error[E0119]: conflicting implementations of trait `Trait` for type `Box<_>` + --> $DIR/coherence-overlap-unnormalizable-projection-1.rs:26:1 + | +LL | / impl<T> Trait for T +LL | | where +LL | | T: 'static, +LL | | for<'a> T: WithAssoc<'a>, +LL | | for<'a> Box<<T as WithAssoc<'a>>::Assoc>: WhereBound, + | |_________________________________________________________- first implementation here +... +LL | impl<T> Trait for Box<T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` + | + = note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>` + = note: downstream crates may implement trait `WhereBound` for type `std::boxed::Box<<std::boxed::Box<_> as WithAssoc<'a>>::Assoc>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.next.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.next.stderr new file mode 100644 index 00000000000..49b236f9d2a --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.next.stderr @@ -0,0 +1,19 @@ +error[E0119]: conflicting implementations of trait `Trait` for type `Box<_>` + --> $DIR/coherence-overlap-unnormalizable-projection-1.rs:26:1 + | +LL | / impl<T> Trait for T +LL | | where +LL | | T: 'static, +LL | | for<'a> T: WithAssoc<'a>, +LL | | for<'a> Box<<T as WithAssoc<'a>>::Assoc>: WhereBound, + | |_________________________________________________________- first implementation here +... +LL | impl<T> Trait for Box<T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` + | + = note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>` + = note: downstream crates may implement trait `WhereBound` for type `std::boxed::Box<<std::boxed::Box<_> as WithAssoc<'a>>::Assoc>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.rs b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.rs new file mode 100644 index 00000000000..8eeadb3dc75 --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.rs @@ -0,0 +1,44 @@ +// Regression test for soundness issue #114061: +// "Coherence incorrectly considers `unnormalizable_projection: Trait` to not hold even if it could" +#![crate_type = "lib"] + +//@ revisions: classic next +//@[next] compile-flags: -Znext-solver + +pub trait WhereBound {} +impl WhereBound for () {} + +pub trait WithAssoc<'a> { + type Assoc; +} + +// These two impls of `Trait` overlap: + +pub trait Trait {} +impl<T> Trait for T +where + T: 'static, + for<'a> T: WithAssoc<'a>, + for<'a> Box<<T as WithAssoc<'a>>::Assoc>: WhereBound, +{ +} + +impl<T> Trait for Box<T> {} //~ ERROR conflicting implementations of trait `Trait` for type `Box<_>` + +// A downstream crate could write: +// +// +// use upstream::*; +// +// struct Local; +// impl WithAssoc<'_> for Box<Local> { +// type Assoc = Local; +// } +// +// impl WhereBound for Box<Local> {} +// +// fn impls_trait<T: Trait>() {} +// +// fn main() { +// impls_trait::<Box<Local>>(); +// } diff --git a/tests/ui/coherence/occurs-check/opaques.next.stderr b/tests/ui/coherence/occurs-check/opaques.next.stderr index a5182eb5d9c..f6c5255a186 100644 --- a/tests/ui/coherence/occurs-check/opaques.next.stderr +++ b/tests/ui/coherence/occurs-check/opaques.next.stderr @@ -11,7 +11,7 @@ error[E0282]: type annotations needed --> $DIR/opaques.rs:13:20 | LL | pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> { - | ^ cannot infer type for struct `Container<T, T>` + | ^ cannot infer type for associated type `<T as Trait<T>>::Assoc` error: aborting due to 2 previous errors diff --git a/tests/ui/coherence/orphan-check-projections-covering.rs b/tests/ui/coherence/orphan-check-projections-covering.rs new file mode 100644 index 00000000000..ae1917ec161 --- /dev/null +++ b/tests/ui/coherence/orphan-check-projections-covering.rs @@ -0,0 +1,25 @@ +// Projections cover type parameters if they normalize to a (local) type that covers them. +// This ensures that we don't perform an overly strict check on +// projections like in closed PR #100555 which did a syntactic +// check for type parameters in projections without normalizing +// first which would've lead to real-word regressions. + +//@ check-pass +//@ revisions: classic next +//@[next] compile-flags: -Znext-solver + +//@ aux-crate:foreign=parametrized-trait.rs +//@ edition:2021 + +trait Project { type Output; } + +impl<T> Project for Wrapper<T> { + type Output = Local; +} + +struct Wrapper<T>(T); +struct Local; + +impl<T> foreign::Trait1<Local, T> for <Wrapper<T> as Project>::Output {} + +fn main() {} diff --git a/tests/ui/coherence/orphan-check-projections-nested.rs b/tests/ui/coherence/orphan-check-projections-nested.rs new file mode 100644 index 00000000000..ec244a8005b --- /dev/null +++ b/tests/ui/coherence/orphan-check-projections-nested.rs @@ -0,0 +1,23 @@ +// This used to ICE in an earlier iteration of #117164. Minimized from crate `proqnt`. + +//@ check-pass +//@ revisions: classic next +//@[next] compile-flags: -Znext-solver +//@ aux-crate:dep=trait-with-assoc-ty.rs +//@ edition: 2021 + +pub(crate) trait Trait<T> { + type Assoc; +} + +pub(crate) struct Type<T, U, V>(T, U, V); + +impl<T, U> dep::Trait for Type<T, <<T as dep::Trait>::Assoc as Trait<U>>::Assoc, U> +where + T: dep::Trait, + <T as dep::Trait>::Assoc: Trait<U>, +{ + type Assoc = U; +} + +fn main() {} diff --git a/tests/ui/coherence/orphan-check-projections-not-covering-ambiguity.classic.stderr b/tests/ui/coherence/orphan-check-projections-not-covering-ambiguity.classic.stderr new file mode 100644 index 00000000000..d83a56c0bd0 --- /dev/null +++ b/tests/ui/coherence/orphan-check-projections-not-covering-ambiguity.classic.stderr @@ -0,0 +1,15 @@ +warning[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/orphan-check-projections-not-covering-ambiguity.rs:25:6 + | +LL | impl<T> foreign::Trait1<Local, T> for <T as Project>::Output {} + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = 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 #124559 <https://github.com/rust-lang/rust/issues/124559> + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last + = note: `#[warn(uncovered_param_in_projection)]` on by default + +warning: 1 warning emitted + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/orphan-check-projections-not-covering-ambiguity.next.stderr b/tests/ui/coherence/orphan-check-projections-not-covering-ambiguity.next.stderr new file mode 100644 index 00000000000..d83a56c0bd0 --- /dev/null +++ b/tests/ui/coherence/orphan-check-projections-not-covering-ambiguity.next.stderr @@ -0,0 +1,15 @@ +warning[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/orphan-check-projections-not-covering-ambiguity.rs:25:6 + | +LL | impl<T> foreign::Trait1<Local, T> for <T as Project>::Output {} + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = 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 #124559 <https://github.com/rust-lang/rust/issues/124559> + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last + = note: `#[warn(uncovered_param_in_projection)]` on by default + +warning: 1 warning emitted + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/orphan-check-projections-not-covering-ambiguity.rs b/tests/ui/coherence/orphan-check-projections-not-covering-ambiguity.rs new file mode 100644 index 00000000000..227d8535232 --- /dev/null +++ b/tests/ui/coherence/orphan-check-projections-not-covering-ambiguity.rs @@ -0,0 +1,29 @@ +// This test demonstrates a limitation of the trait solver. +// Basically, one might think that `T` was covered by the projection since the +// latter appears to normalize to a local type. However, since we instantiate the +// constituent types of the self type of impls with fresh infer vars and try to +// normalize them during orphan checking, we wind up trying to normalize a +// projection whose self type is an infer var which unconditionally fails due to +// ambiguity. + +//@ revisions: classic next +//@[next] compile-flags: -Znext-solver + +//@ check-pass +//@ compile-flags: --crate-type=lib +//@ aux-crate:foreign=parametrized-trait.rs +//@ edition:2021 + +trait Project { type Output; } + +impl<T> Project for T { + type Output = Local; +} + +struct Local; + +impl<T> foreign::Trait1<Local, T> for <T as Project>::Output {} +//~^ WARNING type parameter `T` must be covered by another type +//~| WARNING this was previously accepted by the compiler + +fn main() {} diff --git a/tests/ui/coherence/orphan-check-projections-not-covering-multiple-params.classic.stderr b/tests/ui/coherence/orphan-check-projections-not-covering-multiple-params.classic.stderr new file mode 100644 index 00000000000..8964fefedd4 --- /dev/null +++ b/tests/ui/coherence/orphan-check-projections-not-covering-multiple-params.classic.stderr @@ -0,0 +1,26 @@ +warning[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`LocalTy`) + --> $DIR/orphan-check-projections-not-covering-multiple-params.rs:17:6 + | +LL | impl<T, U> foreign::Trait0<LocalTy, T, U> for <() as Trait<T, U>>::Assoc {} + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`LocalTy`) + | + = 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 #124559 <https://github.com/rust-lang/rust/issues/124559> + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last + = note: `#[warn(uncovered_param_in_projection)]` on by default + +warning[E0210]: type parameter `U` must be covered by another type when it appears before the first local type (`LocalTy`) + --> $DIR/orphan-check-projections-not-covering-multiple-params.rs:17:9 + | +LL | impl<T, U> foreign::Trait0<LocalTy, T, U> for <() as Trait<T, U>>::Assoc {} + | ^ type parameter `U` must be covered by another type when it appears before the first local type (`LocalTy`) + | + = 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 #124559 <https://github.com/rust-lang/rust/issues/124559> + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last + +warning: 2 warnings emitted + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/orphan-check-projections-not-covering-multiple-params.next.stderr b/tests/ui/coherence/orphan-check-projections-not-covering-multiple-params.next.stderr new file mode 100644 index 00000000000..8964fefedd4 --- /dev/null +++ b/tests/ui/coherence/orphan-check-projections-not-covering-multiple-params.next.stderr @@ -0,0 +1,26 @@ +warning[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`LocalTy`) + --> $DIR/orphan-check-projections-not-covering-multiple-params.rs:17:6 + | +LL | impl<T, U> foreign::Trait0<LocalTy, T, U> for <() as Trait<T, U>>::Assoc {} + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`LocalTy`) + | + = 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 #124559 <https://github.com/rust-lang/rust/issues/124559> + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last + = note: `#[warn(uncovered_param_in_projection)]` on by default + +warning[E0210]: type parameter `U` must be covered by another type when it appears before the first local type (`LocalTy`) + --> $DIR/orphan-check-projections-not-covering-multiple-params.rs:17:9 + | +LL | impl<T, U> foreign::Trait0<LocalTy, T, U> for <() as Trait<T, U>>::Assoc {} + | ^ type parameter `U` must be covered by another type when it appears before the first local type (`LocalTy`) + | + = 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 #124559 <https://github.com/rust-lang/rust/issues/124559> + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last + +warning: 2 warnings emitted + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/orphan-check-projections-not-covering-multiple-params.rs b/tests/ui/coherence/orphan-check-projections-not-covering-multiple-params.rs new file mode 100644 index 00000000000..c5340e85405 --- /dev/null +++ b/tests/ui/coherence/orphan-check-projections-not-covering-multiple-params.rs @@ -0,0 +1,24 @@ +//@ revisions: classic next +//@[next] compile-flags: -Znext-solver + +//@ check-pass +//@ compile-flags: --crate-type=lib +//@ aux-crate:foreign=parametrized-trait.rs +//@ edition:2021 + +trait Trait<T, U> { type Assoc; } + +impl<T, U> Trait<T, U> for () { + type Assoc = LocalTy; +} + +struct LocalTy; + +impl<T, U> foreign::Trait0<LocalTy, T, U> for <() as Trait<T, U>>::Assoc {} +//~^ WARNING type parameter `T` must be covered by another type +//~| WARNING this was previously accepted by the compiler +//~| WARNING type parameter `U` must be covered by another type +//~| WARNING this was previously accepted by the compiler + + +fn main() {} diff --git a/tests/ui/coherence/orphan-check-projections-not-covering.classic.stderr b/tests/ui/coherence/orphan-check-projections-not-covering.classic.stderr new file mode 100644 index 00000000000..28b8c3f4a94 --- /dev/null +++ b/tests/ui/coherence/orphan-check-projections-not-covering.classic.stderr @@ -0,0 +1,37 @@ +warning[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/orphan-check-projections-not-covering.rs:22:6 + | +LL | impl<T> foreign::Trait0<Local, T, ()> for <T as Identity>::Output {} + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = 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 #124559 <https://github.com/rust-lang/rust/issues/124559> + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last + = note: `#[warn(uncovered_param_in_projection)]` on by default + +warning[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/orphan-check-projections-not-covering.rs:27:6 + | +LL | impl<T> foreign::Trait0<<T as Identity>::Output, Local, T> for Option<T> {} + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = 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 #124559 <https://github.com/rust-lang/rust/issues/124559> + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last + +warning[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/orphan-check-projections-not-covering.rs:40:6 + | +LL | impl<T: Deferred> foreign::Trait1<Local, T> for <T as Deferred>::Output {} + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = 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 #124559 <https://github.com/rust-lang/rust/issues/124559> + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last + +warning: 3 warnings emitted + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/orphan-check-projections-not-covering.next.stderr b/tests/ui/coherence/orphan-check-projections-not-covering.next.stderr new file mode 100644 index 00000000000..28b8c3f4a94 --- /dev/null +++ b/tests/ui/coherence/orphan-check-projections-not-covering.next.stderr @@ -0,0 +1,37 @@ +warning[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/orphan-check-projections-not-covering.rs:22:6 + | +LL | impl<T> foreign::Trait0<Local, T, ()> for <T as Identity>::Output {} + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = 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 #124559 <https://github.com/rust-lang/rust/issues/124559> + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last + = note: `#[warn(uncovered_param_in_projection)]` on by default + +warning[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/orphan-check-projections-not-covering.rs:27:6 + | +LL | impl<T> foreign::Trait0<<T as Identity>::Output, Local, T> for Option<T> {} + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = 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 #124559 <https://github.com/rust-lang/rust/issues/124559> + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last + +warning[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/orphan-check-projections-not-covering.rs:40:6 + | +LL | impl<T: Deferred> foreign::Trait1<Local, T> for <T as Deferred>::Output {} + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = 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 #124559 <https://github.com/rust-lang/rust/issues/124559> + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last + +warning: 3 warnings emitted + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/orphan-check-projections-not-covering.rs b/tests/ui/coherence/orphan-check-projections-not-covering.rs new file mode 100644 index 00000000000..8c2a9a17e2b --- /dev/null +++ b/tests/ui/coherence/orphan-check-projections-not-covering.rs @@ -0,0 +1,42 @@ +// Regression test for issue #99554. +// Projections might not cover type parameters. + +//@ revisions: classic next +//@[next] compile-flags: -Znext-solver + +//@ check-pass +//@ compile-flags: --crate-type=lib +//@ aux-crate:foreign=parametrized-trait.rs +//@ edition:2021 + +trait Identity { + type Output; +} + +impl<T> Identity for T { + type Output = T; +} + +struct Local; + +impl<T> foreign::Trait0<Local, T, ()> for <T as Identity>::Output {} +//~^ WARNING type parameter `T` must be covered by another type +//~| WARNING this was previously accepted by the compiler + + +impl<T> foreign::Trait0<<T as Identity>::Output, Local, T> for Option<T> {} +//~^ WARNING type parameter `T` must be covered by another type +//~| WARNING this was previously accepted by the compiler + +pub trait Deferred { + type Output; +} + +// A downstream user could implement +// +// impl<T> Deferred for Type<T> { type Output = T; } +// struct Type<T>(T); +// +impl<T: Deferred> foreign::Trait1<Local, T> for <T as Deferred>::Output {} +//~^ WARNING type parameter `T` must be covered by another type +//~| WARNING this was previously accepted by the compiler diff --git a/tests/ui/coherence/orphan-check-projections-unsat-bounds.classic.stderr b/tests/ui/coherence/orphan-check-projections-unsat-bounds.classic.stderr new file mode 100644 index 00000000000..0346a9d665c --- /dev/null +++ b/tests/ui/coherence/orphan-check-projections-unsat-bounds.classic.stderr @@ -0,0 +1,15 @@ +warning[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`LocalTy`) + --> $DIR/orphan-check-projections-unsat-bounds.rs:28:6 + | +LL | impl<T> foreign::Trait1<LocalTy, T> for <Wrapper<T> as Discard>::Output + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`LocalTy`) + | + = 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 #124559 <https://github.com/rust-lang/rust/issues/124559> + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last + = note: `#[warn(uncovered_param_in_projection)]` on by default + +warning: 1 warning emitted + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/orphan-check-projections-unsat-bounds.next.stderr b/tests/ui/coherence/orphan-check-projections-unsat-bounds.next.stderr new file mode 100644 index 00000000000..0346a9d665c --- /dev/null +++ b/tests/ui/coherence/orphan-check-projections-unsat-bounds.next.stderr @@ -0,0 +1,15 @@ +warning[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`LocalTy`) + --> $DIR/orphan-check-projections-unsat-bounds.rs:28:6 + | +LL | impl<T> foreign::Trait1<LocalTy, T> for <Wrapper<T> as Discard>::Output + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`LocalTy`) + | + = 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 #124559 <https://github.com/rust-lang/rust/issues/124559> + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last + = note: `#[warn(uncovered_param_in_projection)]` on by default + +warning: 1 warning emitted + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/orphan-check-projections-unsat-bounds.rs b/tests/ui/coherence/orphan-check-projections-unsat-bounds.rs new file mode 100644 index 00000000000..bc52673a016 --- /dev/null +++ b/tests/ui/coherence/orphan-check-projections-unsat-bounds.rs @@ -0,0 +1,35 @@ +// This used to ICE in an earlier iteration of #117164. +// The normalization performed during orphan checking happens inside an empty ParamEnv and +// with type parameters mapped to fresh infer vars. Therefore it may fail for example due to +// unsatisfied bounds while normalization outside of orphan checking succeeds. + +//@ revisions: classic next +//@[next] compile-flags: -Znext-solver + +//@ check-pass +//@ aux-crate:foreign=parametrized-trait.rs +//@ edition:2021 + +struct Wrapper<T>(T); + +trait Bound {} + +trait Discard { type Output; } + +impl<T> Discard for Wrapper<T> +where + Wrapper<T>: Bound +{ + type Output = LocalTy; +} + +struct LocalTy; + +impl<T> foreign::Trait1<LocalTy, T> for <Wrapper<T> as Discard>::Output +//~^ WARNING type parameter `T` must be covered by another type +//~| WARNING this was previously accepted by the compiler +where + Wrapper<T>: Bound +{} + +fn main() {} diff --git a/tests/ui/coherence/orphan-check-weak-aliases-covering.rs b/tests/ui/coherence/orphan-check-weak-aliases-covering.rs new file mode 100644 index 00000000000..a8b9e905c70 --- /dev/null +++ b/tests/ui/coherence/orphan-check-weak-aliases-covering.rs @@ -0,0 +1,20 @@ +// Weak aliases cover type parameters if they normalize to a (local) type that covers them. + +//@ check-pass +//@ revisions: classic next +//@[next] compile-flags: -Znext-solver + +//@ aux-crate:foreign=parametrized-trait.rs +//@ edition:2021 + +#![feature(lazy_type_alias)] +#![allow(incomplete_features)] + +type Alias<T> = LocalWrapper<T>; + +struct Local; +struct LocalWrapper<T>(T); + +impl<T> foreign::Trait1<Local, T> for Alias<T> {} + +fn main() {} diff --git a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.classic.stderr b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.classic.stderr new file mode 100644 index 00000000000..276833fa171 --- /dev/null +++ b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.classic.stderr @@ -0,0 +1,12 @@ +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/orphan-check-weak-aliases-not-covering.rs:16:6 + | +LL | impl<T> foreign::Trait1<Local, T> for Identity<T> {} + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.next.stderr b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.next.stderr new file mode 100644 index 00000000000..276833fa171 --- /dev/null +++ b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.next.stderr @@ -0,0 +1,12 @@ +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/orphan-check-weak-aliases-not-covering.rs:16:6 + | +LL | impl<T> foreign::Trait1<Local, T> for Identity<T> {} + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.rs b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.rs new file mode 100644 index 00000000000..9ebc45a8829 --- /dev/null +++ b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.rs @@ -0,0 +1,19 @@ +// Weak aliases might not cover type parameters. + +//@ revisions: classic next +//@[next] compile-flags: -Znext-solver + +//@ aux-crate:foreign=parametrized-trait.rs +//@ edition:2021 + +#![feature(lazy_type_alias)] +#![allow(incomplete_features)] + +type Identity<T> = T; + +struct Local; + +impl<T> foreign::Trait1<Local, T> for Identity<T> {} +//~^ ERROR type parameter `T` must be covered by another type + +fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-attr-cfg-2.rs b/tests/ui/conditional-compilation/cfg-attr-cfg-2.rs index ae0afc7dfa7..c801bbccedd 100644 --- a/tests/ui/conditional-compilation/cfg-attr-cfg-2.rs +++ b/tests/ui/conditional-compilation/cfg-attr-cfg-2.rs @@ -1,6 +1,5 @@ -// //@ error-pattern: `main` function not found -//@ compile-flags: --cfg foo +//@ compile-flags: --cfg foo --check-cfg=cfg(foo,bar) // main is conditionally compiled, but the conditional compilation // is conditional too! diff --git a/tests/ui/conditional-compilation/cfg-attr-cfg-2.stderr b/tests/ui/conditional-compilation/cfg-attr-cfg-2.stderr index 5f7fea0965f..64595241dc7 100644 --- a/tests/ui/conditional-compilation/cfg-attr-cfg-2.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-cfg-2.stderr @@ -1,5 +1,5 @@ error[E0601]: `main` function not found in crate `cfg_attr_cfg_2` - --> $DIR/cfg-attr-cfg-2.rs:9:14 + --> $DIR/cfg-attr-cfg-2.rs:8:14 | LL | fn main() { } | ^ consider adding a `main` function to `$DIR/cfg-attr-cfg-2.rs` diff --git a/tests/ui/conditional-compilation/cfg-attr-crate-2.rs b/tests/ui/conditional-compilation/cfg-attr-crate-2.rs index 710dbd8e818..4b7d1c45234 100644 --- a/tests/ui/conditional-compilation/cfg-attr-crate-2.rs +++ b/tests/ui/conditional-compilation/cfg-attr-crate-2.rs @@ -1,6 +1,6 @@ // https://github.com/rust-lang/rust/issues/21833#issuecomment-72353044 -//@ compile-flags: --cfg broken +//@ compile-flags: --cfg broken --check-cfg=cfg(broken) #![crate_type = "lib"] #![cfg_attr(broken, no_core)] //~ ERROR the `#[no_core]` attribute is an experimental feature diff --git a/tests/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs b/tests/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs index de2c7557a6d..d881634abc3 100644 --- a/tests/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs +++ b/tests/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --cfg broken +//@ compile-flags: --cfg broken --check-cfg=cfg(broken) #![crate_type = "lib"] #![cfg_attr(broken, no_core, no_std)] diff --git a/tests/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs b/tests/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs index e222b79c9d8..6cac52983b5 100644 --- a/tests/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs +++ b/tests/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --cfg broken +//@ compile-flags: --cfg broken --check-cfg=cfg(broken) #![crate_type = "lib"] #![cfg_attr(broken, no_std, no_core)] diff --git a/tests/ui/conditional-compilation/cfg-generic-params.rs b/tests/ui/conditional-compilation/cfg-generic-params.rs index 2a83be21498..4bb8f8ae94f 100644 --- a/tests/ui/conditional-compilation/cfg-generic-params.rs +++ b/tests/ui/conditional-compilation/cfg-generic-params.rs @@ -1,4 +1,4 @@ -//@ compile-flags:--cfg yes +//@ compile-flags:--cfg yes --check-cfg=cfg(yes,no) fn f_lt<#[cfg(yes)] 'a: 'a, #[cfg(FALSE)] T>() {} fn f_ty<#[cfg(FALSE)] 'a: 'a, #[cfg(yes)] T>() {} diff --git a/tests/ui/conditional-compilation/test-cfg.rs b/tests/ui/conditional-compilation/test-cfg.rs index 7c6c692072d..adbbc309be4 100644 --- a/tests/ui/conditional-compilation/test-cfg.rs +++ b/tests/ui/conditional-compilation/test-cfg.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --cfg foo +//@ compile-flags: --cfg foo --check-cfg=cfg(foo,bar) #[cfg(all(foo, bar))] // foo AND bar fn foo() {} diff --git a/tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.rs b/tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.rs new file mode 100644 index 00000000000..05bd0d91168 --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.rs @@ -0,0 +1,13 @@ +//@ edition:2021 +// issues rust-lang/rust#111911 +// test for ICE opaque type with non-universal region substs + +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +pub async fn foo<const X: &'static str>() {} +//~^ ERROR const parameter `X` is part of concrete type but not used in parameter list for the `impl Trait` type alias +//~| ERROR const parameter `X` is part of concrete type but not used in parameter list for the `impl Trait` type alias +fn bar<const N: &'static u8>() -> impl Sized {} + +pub fn main() {} diff --git a/tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.stderr b/tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.stderr new file mode 100644 index 00000000000..1bdb9cd9501 --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.stderr @@ -0,0 +1,16 @@ +error: const parameter `X` is part of concrete type but not used in parameter list for the `impl Trait` type alias + --> $DIR/opaque_type_with_non-universal_region_substs_ice-111911.rs:8:43 + | +LL | pub async fn foo<const X: &'static str>() {} + | ^^ + +error: const parameter `X` is part of concrete type but not used in parameter list for the `impl Trait` type alias + --> $DIR/opaque_type_with_non-universal_region_substs_ice-111911.rs:8:43 + | +LL | pub async fn foo<const X: &'static str>() {} + | ^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.rs b/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.rs new file mode 100644 index 00000000000..68b8b489816 --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.rs @@ -0,0 +1,32 @@ +// ICE Inconsistent rustc_transmute::is_transmutable(...) result, got Yes +// issue: rust-lang/rust#110969 +#![feature(adt_const_params, generic_const_exprs, transmutability)] +#![allow(incomplete_features, unstable_features)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + + pub fn is_transmutable<Src, Dst, Context, const ASSUME: std::mem::Assume>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME>, + //~^ ERROR trait takes at most 2 generic arguments but 3 generic arguments were supplied + { + } +} + +fn via_associated_const() { + struct Context; + #[repr(C)] + struct Src; + #[repr(C)] + struct Dst; + + trait Trait { + const FALSE: bool = assert::is_transmutable::<Src, Dst, Context, {}>(); + //~^ ERROR mismatched types + //~| ERROR `Src` cannot be safely transmuted into `Dst` + //~| ERROR mismatched types + } +} + +pub fn main() {} diff --git a/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.stderr b/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.stderr new file mode 100644 index 00000000000..1dbacaee3c2 --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.stderr @@ -0,0 +1,39 @@ +error[E0107]: trait takes at most 2 generic arguments but 3 generic arguments were supplied + --> $DIR/transmutable-ice-110969.rs:11:14 + | +LL | Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME>, + | ^^^^^^^^^^^^^^^^^^^^^ ------ help: remove this generic argument + | | + | expected at most 2 generic arguments + +error[E0308]: mismatched types + --> $DIR/transmutable-ice-110969.rs:25:74 + | +LL | const FALSE: bool = assert::is_transmutable::<Src, Dst, Context, {}>(); + | ^^ expected `Assume`, found `()` + +error[E0277]: `Src` cannot be safely transmuted into `Dst` + --> $DIR/transmutable-ice-110969.rs:25:60 + | +LL | const FALSE: bool = assert::is_transmutable::<Src, Dst, Context, {}>(); + | ^^^ `Dst` may carry safety invariants + | +note: required by a bound in `is_transmutable` + --> $DIR/transmutable-ice-110969.rs:11:14 + | +LL | pub fn is_transmutable<Src, Dst, Context, const ASSUME: std::mem::Assume>() + | --------------- required by a bound in this function +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0308]: mismatched types + --> $DIR/transmutable-ice-110969.rs:25:29 + | +LL | const FALSE: bool = assert::is_transmutable::<Src, Dst, Context, {}>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0107, E0277, E0308. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs new file mode 100644 index 00000000000..4bea3ad87f5 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs @@ -0,0 +1,23 @@ +// issue: rust-lang/rust#113776 +// ice: expected type of closure body to be a closure or coroutine +//@ edition: 2021 +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +use core::ops::SubAssign; + +fn f<T>( + data: &[(); { + let f: F = async { 1 }; + //~^ ERROR cannot find type `F` in this scope + + 1 + }], +) -> impl Iterator<Item = SubAssign> { +//~^ ERROR the type parameter `Rhs` must be explicitly specified +//~| ERROR `()` is not an iterator +//~| ERROR trait objects must include the `dyn` keyword +//~| ERROR the type parameter `Rhs` must be explicitly specified [E0393] +} + +pub fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr new file mode 100644 index 00000000000..be79450a3ce --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr @@ -0,0 +1,68 @@ +error[E0412]: cannot find type `F` in this scope + --> $DIR/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs:11:17 + | +LL | let f: F = async { 1 }; + | ^ + --> $SRC_DIR/core/src/ops/function.rs:LL:COL + | + = note: similarly named trait `Fn` defined here + | +help: a trait with a similar name exists + | +LL | let f: Fn = async { 1 }; + | ~~ +help: you might be missing a type parameter + | +LL | fn f<T, F>( + | +++ + +error[E0393]: the type parameter `Rhs` must be explicitly specified + --> $DIR/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs:16:27 + | +LL | ) -> impl Iterator<Item = SubAssign> { + | ^^^^^^^^^ help: set the type parameter to the desired type: `SubAssign<Rhs>` + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + | + = note: type parameter `Rhs` must be specified for this + | + = note: because of the default `Self` reference, type parameters must be specified on object types + +error[E0393]: the type parameter `Rhs` must be explicitly specified + --> $DIR/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs:16:27 + | +LL | ) -> impl Iterator<Item = SubAssign> { + | ^^^^^^^^^ help: set the type parameter to the desired type: `SubAssign<Rhs>` + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + | + = note: type parameter `Rhs` must be specified for this + | + = note: because of the default `Self` reference, type parameters must be specified on object types + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: `()` is not an iterator + --> $DIR/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs:16:6 + | +LL | ) -> impl Iterator<Item = SubAssign> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator + | + = help: the trait `Iterator` is not implemented for `()` + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs:16:27 + | +LL | ) -> impl Iterator<Item = SubAssign> { + | ^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL | ) -> impl Iterator<Item = dyn SubAssign> { + | +++ +help: you might have meant to write a bound here + | +LL | ) -> impl Iterator<Item: SubAssign> { + | ~ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0277, E0393, E0412, E0782. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/generic_const_exprs/failed-to-resolve-instance-ice-111667.rs b/tests/ui/const-generics/generic_const_exprs/failed-to-resolve-instance-ice-111667.rs new file mode 100644 index 00000000000..c547b54e16b --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/failed-to-resolve-instance-ice-111667.rs @@ -0,0 +1,18 @@ +// issue rust-lang/rust#111667 +// ICE failed to resolve instance for <[f32; 2] as CrossProduct .. +//@ check-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait CrossProduct<'a, T, R> { + fn cross(&'a self, t: &'a T) -> R; +} + +impl<'a, T, U, const N: usize> CrossProduct<'a, [U; N], [(&'a T, &'a U); N * N]> for [T; N] { + fn cross(&'a self, us: &'a [U; N]) -> [(&'a T, &'a U); N * N] { + std::array::from_fn(|i| (&self[i / N], &us[i % N])) + } +} + +pub fn main() {} diff --git a/tests/ui/consts/const-eval/const_fn_target_feature.rs b/tests/ui/consts/const-eval/const_fn_target_feature.rs index b56b68a5795..ee669abb51e 100644 --- a/tests/ui/consts/const-eval/const_fn_target_feature.rs +++ b/tests/ui/consts/const-eval/const_fn_target_feature.rs @@ -1,5 +1,6 @@ //@ only-x86_64 -//@ compile-flags:-C target-feature=+ssse3 +// Set the base cpu explicitly, in case the default has been changed. +//@ compile-flags: -C target-cpu=x86-64 -C target-feature=+ssse3 #![crate_type = "lib"] diff --git a/tests/ui/consts/const-eval/const_fn_target_feature.stderr b/tests/ui/consts/const-eval/const_fn_target_feature.stderr index 0c7c69b794a..d3a00b57ebb 100644 --- a/tests/ui/consts/const-eval/const_fn_target_feature.stderr +++ b/tests/ui/consts/const-eval/const_fn_target_feature.stderr @@ -1,5 +1,5 @@ error[E0080]: evaluation of constant value failed - --> $DIR/const_fn_target_feature.rs:10:24 + --> $DIR/const_fn_target_feature.rs:11:24 | LL | const B: () = unsafe { avx2_fn() }; | ^^^^^^^^^ calling a function that requires unavailable target features: avx2 diff --git a/tests/ui/error-emitter/highlighting.svg b/tests/ui/error-emitter/highlighting.svg index 1d82a97888a..be92c00c19b 100644 --- a/tests/ui/error-emitter/highlighting.svg +++ b/tests/ui/error-emitter/highlighting.svg @@ -29,11 +29,11 @@ </tspan> <tspan x="10px" y="82px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> query(wrapped_fn);</tspan> </tspan> - <tspan x="10px" y="100px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">-----</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">one type is more general than the other</tspan> + <tspan x="10px" y="100px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">-----</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">one type is more general than the other</tspan> </tspan> - <tspan x="10px" y="118px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan> + <tspan x="10px" y="118px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan> </tspan> - <tspan x="10px" y="136px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">arguments to this function are incorrect</tspan> + <tspan x="10px" y="136px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">arguments to this function are incorrect</tspan> </tspan> <tspan x="10px" y="154px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan> </tspan> @@ -49,13 +49,13 @@ </tspan> <tspan x="10px" y="262px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> fn query(_: fn(Box<(dyn Any + Send + '_)>) -> Pin<Box<(</tspan> </tspan> - <tspan x="10px" y="280px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">____</tspan><tspan class="fg-ansi256-010 bold">^^^^^</tspan><tspan class="fg-ansi256-012 bold">_-</tspan> + <tspan x="10px" y="280px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">____</tspan><tspan class="fg-ansi256-010 bold">^^^^^</tspan><tspan class="fg-ansi256-012 bold">_-</tspan> </tspan> <tspan x="10px" y="298px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> dyn Future<Output = Result<Box<(dyn Any + 'static)>, String>> + Send + 'static</tspan> </tspan> <tspan x="10px" y="316px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> )>>) {}</tspan> </tspan> - <tspan x="10px" y="334px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan class="fg-ansi256-012 bold">|___-</tspan> + <tspan x="10px" y="334px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|___-</tspan> </tspan> <tspan x="10px" y="352px"> </tspan> diff --git a/tests/ui/error-emitter/highlighting.windows.svg b/tests/ui/error-emitter/highlighting.windows.svg index 88143f725a5..152245da9dd 100644 --- a/tests/ui/error-emitter/highlighting.windows.svg +++ b/tests/ui/error-emitter/highlighting.windows.svg @@ -30,11 +30,11 @@ </tspan> <tspan x="10px" y="82px"><tspan class="fg-ansi256-014 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan> query(wrapped_fn);</tspan> </tspan> - <tspan x="10px" y="100px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">| </tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">-----</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">one type is more general than the other</tspan> + <tspan x="10px" y="100px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">-----</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">one type is more general than the other</tspan> </tspan> - <tspan x="10px" y="118px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">| </tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan> + <tspan x="10px" y="118px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan> </tspan> - <tspan x="10px" y="136px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">| </tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">arguments to this function are incorrect</tspan> + <tspan x="10px" y="136px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">arguments to this function are incorrect</tspan> </tspan> <tspan x="10px" y="154px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan> </tspan> @@ -50,13 +50,13 @@ </tspan> <tspan x="10px" y="262px"><tspan class="fg-ansi256-014 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan> fn query(_: fn(Box<(dyn Any + Send + '_)>) -> Pin<Box<(</tspan> </tspan> - <tspan x="10px" y="280px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">| </tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">____</tspan><tspan class="fg-ansi256-010 bold">^^^^^</tspan><tspan class="fg-ansi256-014 bold">_-</tspan> + <tspan x="10px" y="280px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">____</tspan><tspan class="fg-ansi256-010 bold">^^^^^</tspan><tspan class="fg-ansi256-014 bold">_-</tspan> </tspan> <tspan x="10px" y="298px"><tspan class="fg-ansi256-014 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan> dyn Future<Output = Result<Box<(dyn Any + 'static)>, String>> + Send + 'static</tspan> </tspan> <tspan x="10px" y="316px"><tspan class="fg-ansi256-014 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan> )>>) {}</tspan> </tspan> - <tspan x="10px" y="334px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">| </tspan><tspan class="fg-ansi256-014 bold">|___-</tspan> + <tspan x="10px" y="334px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">|___-</tspan> </tspan> <tspan x="10px" y="352px"> </tspan> diff --git a/tests/ui/error-emitter/multiline-multipart-suggestion.svg b/tests/ui/error-emitter/multiline-multipart-suggestion.svg index 26210fade74..c0fb98555ad 100644 --- a/tests/ui/error-emitter/multiline-multipart-suggestion.svg +++ b/tests/ui/error-emitter/multiline-multipart-suggestion.svg @@ -29,7 +29,7 @@ </tspan> <tspan x="10px" y="82px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> fn short(foo_bar: &Vec<&i32>) -> &i32 {</tspan> </tspan> - <tspan x="10px" y="100px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">----------</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected named lifetime parameter</tspan> + <tspan x="10px" y="100px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">----------</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected named lifetime parameter</tspan> </tspan> <tspan x="10px" y="118px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan> </tspan> @@ -53,13 +53,13 @@ </tspan> <tspan x="10px" y="298px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> foo_bar: &Vec<&i32>,</tspan> </tspan> - <tspan x="10px" y="316px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">----------</tspan> + <tspan x="10px" y="316px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">----------</tspan> </tspan> <tspan x="10px" y="334px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> something_very_long_so_that_the_line_will_wrap_around__________: i32,</tspan> </tspan> <tspan x="10px" y="352px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> ) -> &i32 {</tspan> </tspan> - <tspan x="10px" y="370px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected named lifetime parameter</tspan> + <tspan x="10px" y="370px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected named lifetime parameter</tspan> </tspan> <tspan x="10px" y="388px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan> </tspan> @@ -73,7 +73,7 @@ </tspan> <tspan x="10px" y="478px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-010">~ </tspan><tspan> foo_bar: &</tspan><tspan class="fg-ansi256-010">'a </tspan><tspan>Vec<&</tspan><tspan class="fg-ansi256-010">'a </tspan><tspan>i32>,</tspan> </tspan> - <tspan x="10px" y="496px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan> something_very_long_so_that_the_line_will_wrap_around__________: i32,</tspan> + <tspan x="10px" y="496px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> something_very_long_so_that_the_line_will_wrap_around__________: i32,</tspan> </tspan> <tspan x="10px" y="514px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-010">~ </tspan><tspan>) -> &</tspan><tspan class="fg-ansi256-010">'a </tspan><tspan>i32 {</tspan> </tspan> @@ -89,7 +89,7 @@ </tspan> <tspan x="10px" y="622px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> foo_bar: &Vec<&i32>) -> &i32 {</tspan> </tspan> - <tspan x="10px" y="640px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">----------</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected named lifetime parameter</tspan> + <tspan x="10px" y="640px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">----------</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected named lifetime parameter</tspan> </tspan> <tspan x="10px" y="658px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan> </tspan> diff --git a/tests/ui/error-emitter/multiline-multipart-suggestion.windows.svg b/tests/ui/error-emitter/multiline-multipart-suggestion.windows.svg index 3fa9cc18f0d..61b544001f0 100644 --- a/tests/ui/error-emitter/multiline-multipart-suggestion.windows.svg +++ b/tests/ui/error-emitter/multiline-multipart-suggestion.windows.svg @@ -29,7 +29,7 @@ </tspan> <tspan x="10px" y="82px"><tspan class="fg-ansi256-014 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan> fn short(foo_bar: &Vec<&i32>) -> &i32 {</tspan> </tspan> - <tspan x="10px" y="100px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">| </tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">----------</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected named lifetime parameter</tspan> + <tspan x="10px" y="100px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">----------</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected named lifetime parameter</tspan> </tspan> <tspan x="10px" y="118px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan> </tspan> @@ -53,13 +53,13 @@ </tspan> <tspan x="10px" y="298px"><tspan class="fg-ansi256-014 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan> foo_bar: &Vec<&i32>,</tspan> </tspan> - <tspan x="10px" y="316px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">| </tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">----------</tspan> + <tspan x="10px" y="316px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">----------</tspan> </tspan> <tspan x="10px" y="334px"><tspan class="fg-ansi256-014 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan> something_very_long_so_that_the_line_will_wrap_around__________: i32,</tspan> </tspan> <tspan x="10px" y="352px"><tspan class="fg-ansi256-014 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan> ) -> &i32 {</tspan> </tspan> - <tspan x="10px" y="370px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">| </tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected named lifetime parameter</tspan> + <tspan x="10px" y="370px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected named lifetime parameter</tspan> </tspan> <tspan x="10px" y="388px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan> </tspan> @@ -73,7 +73,7 @@ </tspan> <tspan x="10px" y="478px"><tspan class="fg-ansi256-014 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-010">~ </tspan><tspan> foo_bar: &</tspan><tspan class="fg-ansi256-010">'a </tspan><tspan>Vec<&</tspan><tspan class="fg-ansi256-010">'a </tspan><tspan>i32>,</tspan> </tspan> - <tspan x="10px" y="496px"><tspan class="fg-ansi256-014 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">| </tspan><tspan> something_very_long_so_that_the_line_will_wrap_around__________: i32,</tspan> + <tspan x="10px" y="496px"><tspan class="fg-ansi256-014 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan> something_very_long_so_that_the_line_will_wrap_around__________: i32,</tspan> </tspan> <tspan x="10px" y="514px"><tspan class="fg-ansi256-014 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-010">~ </tspan><tspan>) -> &</tspan><tspan class="fg-ansi256-010">'a </tspan><tspan>i32 {</tspan> </tspan> @@ -89,7 +89,7 @@ </tspan> <tspan x="10px" y="622px"><tspan class="fg-ansi256-014 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan> foo_bar: &Vec<&i32>) -> &i32 {</tspan> </tspan> - <tspan x="10px" y="640px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">| </tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">----------</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected named lifetime parameter</tspan> + <tspan x="10px" y="640px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">----------</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected named lifetime parameter</tspan> </tspan> <tspan x="10px" y="658px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan> </tspan> diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-compact.rs b/tests/ui/feature-gates/feature-gate-cfg-target-compact.rs index df81b7d2297..e9dd81cea1b 100644 --- a/tests/ui/feature-gates/feature-gate-cfg-target-compact.rs +++ b/tests/ui/feature-gates/feature-gate-cfg-target-compact.rs @@ -1,13 +1,13 @@ -#[cfg(target(os = "x"))] //~ ERROR compact `cfg(target(..))` is experimental +#[cfg(target(os = "linux"))] //~ ERROR compact `cfg(target(..))` is experimental struct Foo(u64, u64); -#[cfg_attr(target(os = "x"), x)] //~ ERROR compact `cfg(target(..))` is experimental +#[cfg_attr(target(os = "linux"), non_exhaustive)] //~ ERROR compact `cfg(target(..))` is experimental struct Bar(u64, u64); -#[cfg(not(any(all(target(os = "x")))))] //~ ERROR compact `cfg(target(..))` is experimental +#[cfg(not(any(all(target(os = "linux")))))] //~ ERROR compact `cfg(target(..))` is experimental fn foo() {} fn main() { - cfg!(target(os = "x")); + cfg!(target(os = "linux")); //~^ ERROR compact `cfg(target(..))` is experimental and subject to change } diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-compact.stderr b/tests/ui/feature-gates/feature-gate-cfg-target-compact.stderr index 1fd59651957..75c5ab37a4d 100644 --- a/tests/ui/feature-gates/feature-gate-cfg-target-compact.stderr +++ b/tests/ui/feature-gates/feature-gate-cfg-target-compact.stderr @@ -1,8 +1,8 @@ error[E0658]: compact `cfg(target(..))` is experimental and subject to change --> $DIR/feature-gate-cfg-target-compact.rs:1:7 | -LL | #[cfg(target(os = "x"))] - | ^^^^^^^^^^^^^^^^ +LL | #[cfg(target(os = "linux"))] + | ^^^^^^^^^^^^^^^^^^^^ | = note: see issue #96901 <https://github.com/rust-lang/rust/issues/96901> for more information = help: add `#![feature(cfg_target_compact)]` to the crate attributes to enable @@ -11,8 +11,8 @@ LL | #[cfg(target(os = "x"))] error[E0658]: compact `cfg(target(..))` is experimental and subject to change --> $DIR/feature-gate-cfg-target-compact.rs:4:12 | -LL | #[cfg_attr(target(os = "x"), x)] - | ^^^^^^^^^^^^^^^^ +LL | #[cfg_attr(target(os = "linux"), non_exhaustive)] + | ^^^^^^^^^^^^^^^^^^^^ | = note: see issue #96901 <https://github.com/rust-lang/rust/issues/96901> for more information = help: add `#![feature(cfg_target_compact)]` to the crate attributes to enable @@ -21,8 +21,8 @@ LL | #[cfg_attr(target(os = "x"), x)] error[E0658]: compact `cfg(target(..))` is experimental and subject to change --> $DIR/feature-gate-cfg-target-compact.rs:7:19 | -LL | #[cfg(not(any(all(target(os = "x")))))] - | ^^^^^^^^^^^^^^^^ +LL | #[cfg(not(any(all(target(os = "linux")))))] + | ^^^^^^^^^^^^^^^^^^^^ | = note: see issue #96901 <https://github.com/rust-lang/rust/issues/96901> for more information = help: add `#![feature(cfg_target_compact)]` to the crate attributes to enable @@ -31,8 +31,8 @@ LL | #[cfg(not(any(all(target(os = "x")))))] error[E0658]: compact `cfg(target(..))` is experimental and subject to change --> $DIR/feature-gate-cfg-target-compact.rs:11:10 | -LL | cfg!(target(os = "x")); - | ^^^^^^^^^^^^^^^^ +LL | cfg!(target(os = "linux")); + | ^^^^^^^^^^^^^^^^^^^^ | = note: see issue #96901 <https://github.com/rust-lang/rust/issues/96901> for more information = help: add `#![feature(cfg_target_compact)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.rs b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.rs index 83366ea02b0..eea6a21ce27 100644 --- a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.rs +++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.rs @@ -3,7 +3,7 @@ use std::cell::Cell; trait Trait{ - fn cell(self: Cell<&Self>); //~ ERROR invalid `self` parameter type: Cell<&Self> + fn cell(self: Cell<&Self>); //~ ERROR invalid `self` parameter type: `Cell<&Self>` } fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr index e727b69ffce..2150effc3b7 100644 --- a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr +++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr @@ -1,4 +1,4 @@ -error[E0307]: invalid `self` parameter type: Cell<&Self> +error[E0307]: invalid `self` parameter type: `Cell<&Self>` --> $DIR/feature-gate-dispatch-from-dyn-cell.rs:6:19 | LL | fn cell(self: Cell<&Self>); diff --git a/tests/ui/feature-gates/feature-gate-unix_sigpipe.rs b/tests/ui/feature-gates/feature-gate-unix_sigpipe.rs deleted file mode 100644 index 46dc3f6cc17..00000000000 --- a/tests/ui/feature-gates/feature-gate-unix_sigpipe.rs +++ /dev/null @@ -1,4 +0,0 @@ -#![crate_type = "bin"] - -#[unix_sigpipe = "inherit"] //~ the `#[unix_sigpipe]` attribute is an experimental feature -fn main () {} diff --git a/tests/ui/feature-gates/feature-gate-unix_sigpipe.stderr b/tests/ui/feature-gates/feature-gate-unix_sigpipe.stderr deleted file mode 100644 index 88c18e72683..00000000000 --- a/tests/ui/feature-gates/feature-gate-unix_sigpipe.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: the `#[unix_sigpipe]` attribute is an experimental feature - --> $DIR/feature-gate-unix_sigpipe.rs:3:1 - | -LL | #[unix_sigpipe = "inherit"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #97889 <https://github.com/rust-lang/rust/issues/97889> for more information - = help: add `#![feature(unix_sigpipe)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/for/issue-20605.next.stderr b/tests/ui/for/issue-20605.next.stderr index 0669999cb82..6855e17df9a 100644 --- a/tests/ui/for/issue-20605.next.stderr +++ b/tests/ui/for/issue-20605.next.stderr @@ -2,9 +2,14 @@ error[E0277]: `dyn Iterator<Item = &'a mut u8>` is not an iterator --> $DIR/issue-20605.rs:6:17 | LL | for item in *things { *item = 0 } - | ^^^^^^^ `dyn Iterator<Item = &'a mut u8>` is not an iterator + | ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator<Item = &'a mut u8>` | - = help: the trait `IntoIterator` is not implemented for `dyn Iterator<Item = &'a mut u8>` + = note: the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied + = note: required for `dyn Iterator<Item = &'a mut u8>` to implement `IntoIterator` +help: consider mutably borrowing here + | +LL | for item in &mut *things { *item = 0 } + | ++++ error: the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed --> $DIR/issue-20605.rs:6:17 diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.next.stderr b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.next.stderr index 8a8118dea85..5be683cd319 100644 --- a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.next.stderr +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.next.stderr @@ -23,7 +23,20 @@ error[E0283]: type annotations needed LL | impls_indirect_leak::<Box<_>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls_indirect_leak` | - = note: cannot satisfy `for<'a> Box<_>: IndirectLeak<'a>` +note: multiple `impl`s satisfying `for<'a> Box<_>: Leak<'a>` found + --> $DIR/leak-check-in-selection-3.rs:9:1 + | +LL | impl Leak<'_> for Box<u32> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl Leak<'static> for Box<u16> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required for `Box<_>` to implement `for<'a> IndirectLeak<'a>` + --> $DIR/leak-check-in-selection-3.rs:23:23 + | +LL | impl<'a, T: Leak<'a>> IndirectLeak<'a> for T {} + | -------- ^^^^^^^^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here note: required by a bound in `impls_indirect_leak` --> $DIR/leak-check-in-selection-3.rs:25:27 | diff --git a/tests/ui/impl-trait/future-no-bound-vars-ice-112347.rs b/tests/ui/impl-trait/future-no-bound-vars-ice-112347.rs new file mode 100644 index 00000000000..dc4dc9e220d --- /dev/null +++ b/tests/ui/impl-trait/future-no-bound-vars-ice-112347.rs @@ -0,0 +1,29 @@ +// issue: rust-lang/rust#112347 +// ICE future has no bound vars +//@ edition:2021 +//@ check-pass + +#![feature(type_alias_impl_trait)] + +use std::future::Future; + +type Fut<'a> = impl Future<Output = ()> + 'a; + +fn foo<'a>(_: &()) -> Fut<'_> { + async {} +} + +trait Test { + fn hello(); +} + +impl Test for () +where + for<'a> Fut<'a>: Future<Output = ()>, +{ + fn hello() {} +} + +fn main() { + <()>::hello(); +} diff --git a/tests/ui/imports/extern-prelude-extern-crate-cfg.rs b/tests/ui/imports/extern-prelude-extern-crate-cfg.rs index 346d63dabe7..49b90e43915 100644 --- a/tests/ui/imports/extern-prelude-extern-crate-cfg.rs +++ b/tests/ui/imports/extern-prelude-extern-crate-cfg.rs @@ -1,5 +1,5 @@ //@ build-pass (FIXME(62277): could be check-pass?) -//@ compile-flags:--cfg my_feature +//@ compile-flags:--cfg my_feature --check-cfg=cfg(my_feature) #![no_std] diff --git a/tests/ui/imports/issue-59764.stderr b/tests/ui/imports/issue-59764.stderr index fe58eb97b8d..293c2a60d80 100644 --- a/tests/ui/imports/issue-59764.stderr +++ b/tests/ui/imports/issue-59764.stderr @@ -208,9 +208,9 @@ LL | makro as foobar} help: a macro with this name exists at the root of the crate | LL ~ issue_59764::{makro as foobar, -LL | +LL | ... -LL | +LL | LL ~ foo::{baz} | diff --git a/tests/ui/instrument-coverage/coverage-options.bad.stderr b/tests/ui/instrument-coverage/coverage-options.bad.stderr index f6e5421f878..9e2c19e90d5 100644 --- a/tests/ui/instrument-coverage/coverage-options.bad.stderr +++ b/tests/ui/instrument-coverage/coverage-options.bad.stderr @@ -1,2 +1,2 @@ -error: incorrect value `bad` for unstable option `coverage-options` - either `no-branch`, `branch` or `mcdc` was expected +error: incorrect value `bad` for unstable option `coverage-options` - `block` | `branch` | `mcdc` was expected diff --git a/tests/ui/instrument-coverage/coverage-options.rs b/tests/ui/instrument-coverage/coverage-options.rs index 50c01ed29b5..332da32e435 100644 --- a/tests/ui/instrument-coverage/coverage-options.rs +++ b/tests/ui/instrument-coverage/coverage-options.rs @@ -1,20 +1,17 @@ //@ needs-profiler-support -//@ revisions: branch no-branch bad +//@ revisions: block branch bad //@ compile-flags -Cinstrument-coverage +//@ [block] check-pass +//@ [block] compile-flags: -Zcoverage-options=block + //@ [branch] check-pass //@ [branch] compile-flags: -Zcoverage-options=branch -//@ [no-branch] check-pass -//@ [no-branch] compile-flags: -Zcoverage-options=no-branch - //@ [mcdc] check-pass //@ [mcdc] compile-flags: -Zcoverage-options=mcdc //@ [bad] check-fail //@ [bad] compile-flags: -Zcoverage-options=bad -//@ [conflict] check-fail -//@ [conflict] compile-flags: -Zcoverage-options=no-branch,mcdc - fn main() {} diff --git a/tests/ui/instrument-coverage/on-values.rs b/tests/ui/instrument-coverage/on-values.rs index 36643c40525..a6793b2c304 100644 --- a/tests/ui/instrument-coverage/on-values.rs +++ b/tests/ui/instrument-coverage/on-values.rs @@ -1,11 +1,11 @@ //@ check-pass //@ needs-profiler-support -//@ revisions: default y yes on true all +//@ revisions: default y yes on true_ all //@ [default] compile-flags: -Cinstrument-coverage //@ [y] compile-flags: -Cinstrument-coverage=y //@ [yes] compile-flags: -Cinstrument-coverage=yes //@ [on] compile-flags: -Cinstrument-coverage=on -//@ [true] compile-flags: -Cinstrument-coverage=true +//@ [true_] compile-flags: -Cinstrument-coverage=true //@ [all] compile-flags: -Cinstrument-coverage=all fn main() {} diff --git a/tests/ui/issues/issue-11085.rs b/tests/ui/issues/issue-11085.rs index 300be10226c..f646ba35cbf 100644 --- a/tests/ui/issues/issue-11085.rs +++ b/tests/ui/issues/issue-11085.rs @@ -1,9 +1,8 @@ //@ run-pass -#![allow(dead_code)] -//@ compile-flags: --cfg foo - //@ pretty-expanded FIXME #23616 +#![allow(dead_code)] + struct Foo { #[cfg(FALSE)] bar: baz, @@ -11,7 +10,7 @@ struct Foo { } struct Foo2 { - #[cfg(foo)] + #[cfg(all())] foo: isize, } diff --git a/tests/ui/issues/issue-22644.stderr b/tests/ui/issues/issue-22644.stderr index 0799e9ef11b..7d8a0ff170a 100644 --- a/tests/ui/issues/issue-22644.stderr +++ b/tests/ui/issues/issue-22644.stderr @@ -63,9 +63,9 @@ LL | 5); help: try comparing the cast value | LL ~ println!("{}", (a -LL | +LL | ... -LL | +LL | LL ~ usize) | diff --git a/tests/ui/issues/issue-24434.rs b/tests/ui/issues/issue-24434.rs index 4cf1f8b50f7..991084c2740 100644 --- a/tests/ui/issues/issue-24434.rs +++ b/tests/ui/issues/issue-24434.rs @@ -1,7 +1,6 @@ //@ check-pass -//@ compile-flags:--cfg set1 -#![cfg_attr(set1, feature(rustc_attrs))] +#![cfg_attr(all(), feature(rustc_attrs))] #![rustc_dummy] fn main() {} diff --git a/tests/ui/issues/issue-43250.stderr b/tests/ui/issues/issue-43250.stderr index f729c5cf10c..e74342b85ad 100644 --- a/tests/ui/issues/issue-43250.stderr +++ b/tests/ui/issues/issue-43250.stderr @@ -3,12 +3,16 @@ error: arbitrary expressions aren't allowed in patterns | LL | m!(y); | ^ + | + = note: the `expr` fragment specifier forces the metavariable's content to be an expression error: arbitrary expressions aren't allowed in patterns --> $DIR/issue-43250.rs:11:8 | LL | m!(C); | ^ + | + = note: the `expr` fragment specifier forces the metavariable's content to be an expression error: aborting due to 2 previous errors diff --git a/tests/ui/issues/issue-56806.stderr b/tests/ui/issues/issue-56806.stderr index f3d4c2fef94..ec50d863758 100644 --- a/tests/ui/issues/issue-56806.stderr +++ b/tests/ui/issues/issue-56806.stderr @@ -1,4 +1,4 @@ -error[E0307]: invalid `self` parameter type: Box<(dyn Trait + 'static)> +error[E0307]: invalid `self` parameter type: `Box<(dyn Trait + 'static)>` --> $DIR/issue-56806.rs:2:34 | LL | fn dyn_instead_of_self(self: Box<dyn Trait>); diff --git a/tests/ui/lint/ice-const-prop-unions-known-panics-lint-123710.rs b/tests/ui/lint/ice-const-prop-unions-known-panics-lint-123710.rs new file mode 100644 index 00000000000..2b93d0f8a60 --- /dev/null +++ b/tests/ui/lint/ice-const-prop-unions-known-panics-lint-123710.rs @@ -0,0 +1,22 @@ +// Regression test for issue 123710. +// Tests that the we do not ICE in KnownPanicsLint +// when a union contains an enum with an repr(packed), +// which is a repr not supported for enums + +#[repr(packed)] +//~^ ERROR attribute should be applied to a struct or union +#[repr(u32)] +enum E { + A, + B, + C, +} + +fn main() { + union InvalidTag { + int: u32, + e: E, +//~^ ERROR field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union + } + let _invalid_tag = InvalidTag { int: 4 }; +} diff --git a/tests/ui/lint/ice-const-prop-unions-known-panics-lint-123710.stderr b/tests/ui/lint/ice-const-prop-unions-known-panics-lint-123710.stderr new file mode 100644 index 00000000000..44dde6120e8 --- /dev/null +++ b/tests/ui/lint/ice-const-prop-unions-known-panics-lint-123710.stderr @@ -0,0 +1,29 @@ +error[E0517]: attribute should be applied to a struct or union + --> $DIR/ice-const-prop-unions-known-panics-lint-123710.rs:6:8 + | +LL | #[repr(packed)] + | ^^^^^^ +... +LL | / enum E { +LL | | A, +LL | | B, +LL | | C, +LL | | } + | |_- not a struct or union + +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union + --> $DIR/ice-const-prop-unions-known-panics-lint-123710.rs:18:9 + | +LL | e: E, + | ^^^^ + | + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` + | +LL | e: std::mem::ManuallyDrop<E>, + | +++++++++++++++++++++++ + + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0517, E0740. +For more information about an error, try `rustc --explain E0517`. diff --git a/tests/ui/lint/non-local-defs/module_as_local.rs b/tests/ui/lint/non-local-defs/module_as_local.rs new file mode 100644 index 00000000000..bb215026c7d --- /dev/null +++ b/tests/ui/lint/non-local-defs/module_as_local.rs @@ -0,0 +1,38 @@ +//! This test checks that module are treated as if they were local +//! +//! https://github.com/rust-lang/rust/issues/124396 + +//@ check-pass + +trait JoinTo {} + +fn simple_one() { + mod posts { + #[allow(non_camel_case_types)] + pub struct table {} + } + + impl JoinTo for posts::table {} +} + +fn simple_two() { + mod posts { + pub mod posts { + #[allow(non_camel_case_types)] + pub struct table {} + } + } + + impl JoinTo for posts::posts::table {} +} + +struct Global; +fn trait_() { + mod posts { + pub trait AdjecentTo {} + } + + impl posts::AdjecentTo for Global {} +} + +fn main() {} diff --git a/tests/ui/lint/use_suggestion_json.stderr b/tests/ui/lint/use_suggestion_json.stderr index 16fb1682d4a..acc36550642 100644 --- a/tests/ui/lint/use_suggestion_json.stderr +++ b/tests/ui/lint/use_suggestion_json.stderr @@ -384,7 +384,7 @@ mod foo { \u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0m$DIR/use_suggestion_json.rs:12:12\u001b[0m \u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m \u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m let x: Iter;\u001b[0m -\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9m^^^^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9mnot found in this scope\u001b[0m +\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9m^^^^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9mnot found in this scope\u001b[0m \u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m \u001b[0m\u001b[1m\u001b[38;5;14mhelp\u001b[0m\u001b[0m: consider importing one of these items\u001b[0m \u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m diff --git a/tests/ui/lowering/expr-in-pat-issue-99380.rs b/tests/ui/lowering/expr-in-pat-issue-99380.rs new file mode 100644 index 00000000000..1d4a047f717 --- /dev/null +++ b/tests/ui/lowering/expr-in-pat-issue-99380.rs @@ -0,0 +1,11 @@ +macro_rules! foo { + ($p:expr) => { + if let $p = Some(42) { + return; + } + }; +} + +fn main() { + foo!(Some(3)); //~ ERROR arbitrary expressions aren't allowed in patterns +} diff --git a/tests/ui/lowering/expr-in-pat-issue-99380.stderr b/tests/ui/lowering/expr-in-pat-issue-99380.stderr new file mode 100644 index 00000000000..29438c9b063 --- /dev/null +++ b/tests/ui/lowering/expr-in-pat-issue-99380.stderr @@ -0,0 +1,10 @@ +error: arbitrary expressions aren't allowed in patterns + --> $DIR/expr-in-pat-issue-99380.rs:10:10 + | +LL | foo!(Some(3)); + | ^^^^^^^ + | + = note: the `expr` fragment specifier forces the metavariable's content to be an expression + +error: aborting due to 1 previous error + diff --git a/tests/ui/macros/issue-118048.stderr b/tests/ui/macros/issue-118048.stderr index 6acf78f63b2..4dc5ef71fec 100644 --- a/tests/ui/macros/issue-118048.stderr +++ b/tests/ui/macros/issue-118048.stderr @@ -12,7 +12,7 @@ help: use type parameters instead LL ~ fn foo<T>(_: $ty, _: $ty) {} LL | } LL | } -LL | +LL | LL ~ foo!(T); | diff --git a/tests/ui/macros/macro-comma-support-rpass.rs b/tests/ui/macros/macro-comma-support-rpass.rs index 724bd5af2dc..5a4bac70b1c 100644 --- a/tests/ui/macros/macro-comma-support-rpass.rs +++ b/tests/ui/macros/macro-comma-support-rpass.rs @@ -51,6 +51,7 @@ fn assert_ne() { } #[test] +#[allow(unexpected_cfgs)] fn cfg() { let _ = cfg!(pants); let _ = cfg!(pants,); diff --git a/tests/ui/macros/macro-meta-items.rs b/tests/ui/macros/macro-meta-items.rs index 10c57fba244..35ef10fef5a 100644 --- a/tests/ui/macros/macro-meta-items.rs +++ b/tests/ui/macros/macro-meta-items.rs @@ -1,6 +1,7 @@ //@ run-pass +//@ compile-flags: --cfg foo --check-cfg=cfg(foo) + #![allow(dead_code)] -//@ compile-flags: --cfg foo macro_rules! compiles_fine { ($at:meta) => { @@ -16,7 +17,7 @@ macro_rules! emit { } // item -compiles_fine!(bar); +compiles_fine!(FALSE); emit!(foo); fn foo() { @@ -25,7 +26,7 @@ fn foo() { pub fn main() { // statement - compiles_fine!(baz); - emit!(baz); + compiles_fine!(FALSE); + emit!(FALSE); println!("{}", MISTYPED); } diff --git a/tests/ui/macros/macro-with-attrs1.rs b/tests/ui/macros/macro-with-attrs1.rs index cfd5691fe94..a3030e744db 100644 --- a/tests/ui/macros/macro-with-attrs1.rs +++ b/tests/ui/macros/macro-with-attrs1.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ compile-flags: --cfg foo +//@ compile-flags: --cfg foo --check-cfg=cfg(foo) #[cfg(foo)] diff --git a/tests/ui/macros/syntax-extension-cfg.rs b/tests/ui/macros/syntax-extension-cfg.rs index 56d869f3dc1..6e7f3e2ed5d 100644 --- a/tests/ui/macros/syntax-extension-cfg.rs +++ b/tests/ui/macros/syntax-extension-cfg.rs @@ -1,6 +1,6 @@ //@ run-pass //@ compile-flags: --cfg foo --cfg qux="foo" - +//@ compile-flags: --check-cfg=cfg(foo) --check-cfg=cfg(qux,values("foo")) pub fn main() { // check @@ -14,11 +14,11 @@ pub fn main() { if cfg!(not(all(foo, qux="foo"))) { panic!() } if cfg!(all(not(all(foo, qux="foo")))) { panic!() } - if cfg!(not_a_cfg) { panic!() } - if cfg!(all(not_a_cfg, foo, qux="foo")) { panic!() } - if cfg!(all(not_a_cfg, foo, qux="foo")) { panic!() } - if ! cfg!(any(not_a_cfg, foo)) { panic!() } + if cfg!(FALSE) { panic!() } + if cfg!(all(FALSE, foo, qux="foo")) { panic!() } + if cfg!(all(FALSE, foo, qux="foo")) { panic!() } + if ! cfg!(any(FALSE, foo)) { panic!() } - if ! cfg!(not(not_a_cfg)) { panic!() } - if ! cfg!(all(not(not_a_cfg), foo, qux="foo")) { panic!() } + if ! cfg!(not(FALSE)) { panic!() } + if ! cfg!(all(not(FALSE), foo, qux="foo")) { panic!() } } diff --git a/tests/ui/macros/vec-macro-in-pattern.stderr b/tests/ui/macros/vec-macro-in-pattern.stderr index 447f5dcf864..1a446b8c3ed 100644 --- a/tests/ui/macros/vec-macro-in-pattern.stderr +++ b/tests/ui/macros/vec-macro-in-pattern.stderr @@ -4,6 +4,7 @@ error: arbitrary expressions aren't allowed in patterns LL | Some(vec![43]) => {} | ^^^^^^^^ | + = note: the `expr` fragment specifier forces the metavariable's content to be an expression = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/match/expr_before_ident_pat.stderr b/tests/ui/match/expr_before_ident_pat.stderr index 57a2d2b26cf..1657c51545c 100644 --- a/tests/ui/match/expr_before_ident_pat.stderr +++ b/tests/ui/match/expr_before_ident_pat.stderr @@ -9,6 +9,8 @@ error: arbitrary expressions aren't allowed in patterns | LL | funny!(a, a); | ^ + | + = note: the `expr` fragment specifier forces the metavariable's content to be an expression error: aborting due to 2 previous errors diff --git a/tests/ui/methods/method-call-err-msg.stderr b/tests/ui/methods/method-call-err-msg.stderr index 7d9b38fb29b..5a76449e9f9 100644 --- a/tests/ui/methods/method-call-err-msg.stderr +++ b/tests/ui/methods/method-call-err-msg.stderr @@ -55,7 +55,7 @@ LL | / y.zero() LL | | .take() | | -^^^^ `Foo` is not an iterator | |______| - | + | | = note: the following trait bounds were not satisfied: `Foo: Iterator` diff --git a/tests/ui/methods/method-lookup-order.rs b/tests/ui/methods/method-lookup-order.rs index 08ad6483d08..f794e5a7241 100644 --- a/tests/ui/methods/method-lookup-order.rs +++ b/tests/ui/methods/method-lookup-order.rs @@ -18,6 +18,9 @@ //@ revisions: b00001 b00010 b00011 b00100 b00101 b00110 b00111 b01000 b01001 b01100 b01101 b10000 b10001 b10010 b10011 b10101 b10111 b11000 b11001 b11101 +//@ compile-flags: --check-cfg=cfg(inherent_mut,bar_for_foo,mutbar_for_foo) +//@ compile-flags: --check-cfg=cfg(valbar_for_et_foo,valbar_for_etmut_foo) + //@[b00001]compile-flags: --cfg inherent_mut //@[b00010]compile-flags: --cfg bar_for_foo //@[b00011]compile-flags: --cfg inherent_mut --cfg bar_for_foo diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs new file mode 100644 index 00000000000..0ae498c134f --- /dev/null +++ b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs @@ -0,0 +1,141 @@ +//@ check-pass +use std::{marker, mem, ptr}; + +fn main() {} + +fn _zero() { + if false { + unsafe { mem::zeroed() } + //~^ warn: never type fallback affects this call to an `unsafe` function + } else { + return; + }; + + // no ; -> type is inferred without fallback + if true { unsafe { mem::zeroed() } } else { return } +} + +fn _trans() { + if false { + unsafe { + struct Zst; + core::mem::transmute(Zst) + //~^ warn: never type fallback affects this call to an `unsafe` function + } + } else { + return; + }; +} + +fn _union() { + if false { + union Union<T: Copy> { + a: (), + b: T, + } + + unsafe { Union { a: () }.b } + //~^ warn: never type fallback affects this union access + } else { + return; + }; +} + +fn _deref() { + if false { + unsafe { *ptr::from_ref(&()).cast() } + //~^ warn: never type fallback affects this raw pointer dereference + } else { + return; + }; +} + +fn _only_generics() { + if false { + unsafe fn internally_create<T>(_: Option<T>) { + let _ = mem::zeroed::<T>(); + } + + // We need the option (and unwrap later) to call a function in a way, + // which makes it affected by the fallback, but without having it return anything + let x = None; + + unsafe { internally_create(x) } + //~^ warn: never type fallback affects this call to an `unsafe` function + + x.unwrap() + } else { + return; + }; +} + +fn _stored_function() { + if false { + let zeroed = mem::zeroed; + //~^ warn: never type fallback affects this `unsafe` function + + unsafe { zeroed() } + //~^ warn: never type fallback affects this call to an `unsafe` function + } else { + return; + }; +} + +fn _only_generics_stored_function() { + if false { + unsafe fn internally_create<T>(_: Option<T>) { + let _ = mem::zeroed::<T>(); + } + + let x = None; + let f = internally_create; + //~^ warn: never type fallback affects this `unsafe` function + + unsafe { f(x) } + + x.unwrap() + } else { + return; + }; +} + +fn _method() { + struct S<T>(marker::PhantomData<T>); + + impl<T> S<T> { + #[allow(unused)] // FIXME: the unused lint is probably incorrect here + unsafe fn create_out_of_thin_air(&self) -> T { + todo!() + } + } + + if false { + unsafe { + S(marker::PhantomData).create_out_of_thin_air() + //~^ warn: never type fallback affects this call to an `unsafe` method + } + } else { + return; + }; +} + +// Minimization of the famous `objc` crate issue +fn _objc() { + pub unsafe fn send_message<R>() -> Result<R, ()> { + Ok(unsafe { core::mem::zeroed() }) + } + + macro_rules! msg_send { + () => { + match send_message::<_ /* ?0 */>() { + //~^ warn: never type fallback affects this call to an `unsafe` function + Ok(x) => x, + Err(_) => loop {}, + } + }; + } + + unsafe { + msg_send!(); + } +} diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.stderr b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.stderr new file mode 100644 index 00000000000..84c9385fd13 --- /dev/null +++ b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.stderr @@ -0,0 +1,87 @@ +warning: never type fallback affects this call to an `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:8:18 + | +LL | unsafe { mem::zeroed() } + | ^^^^^^^^^^^^^ + | + = help: specify the type explicitly + = note: `#[warn(never_type_fallback_flowing_into_unsafe)]` on by default + +warning: never type fallback affects this call to an `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:22:13 + | +LL | core::mem::transmute(Zst) + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: specify the type explicitly + +warning: never type fallback affects this union access + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:37:18 + | +LL | unsafe { Union { a: () }.b } + | ^^^^^^^^^^^^^^^^^ + | + = help: specify the type explicitly + +warning: never type fallback affects this raw pointer dereference + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:46:18 + | +LL | unsafe { *ptr::from_ref(&()).cast() } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: specify the type explicitly + +warning: never type fallback affects this call to an `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:63:18 + | +LL | unsafe { internally_create(x) } + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: specify the type explicitly + +warning: never type fallback affects this call to an `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:77:18 + | +LL | unsafe { zeroed() } + | ^^^^^^^^ + | + = help: specify the type explicitly + +warning: never type fallback affects this `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:74:22 + | +LL | let zeroed = mem::zeroed; + | ^^^^^^^^^^^ + | + = help: specify the type explicitly + +warning: never type fallback affects this `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:91:17 + | +LL | let f = internally_create; + | ^^^^^^^^^^^^^^^^^ + | + = help: specify the type explicitly + +warning: never type fallback affects this call to an `unsafe` method + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:114:13 + | +LL | S(marker::PhantomData).create_out_of_thin_air() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: specify the type explicitly + +warning: never type fallback affects this call to an `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:130:19 + | +LL | match send_message::<_ /* ?0 */>() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | msg_send!(); + | ----------- in this macro invocation + | + = help: specify the type explicitly + = note: this warning originates in the macro `msg_send` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 10 warnings emitted + diff --git a/tests/ui/offset-of/offset-of-dst-field.stderr b/tests/ui/offset-of/offset-of-dst-field.stderr index 753ba809e7d..adfd16c6f2b 100644 --- a/tests/ui/offset-of/offset-of-dst-field.stderr +++ b/tests/ui/offset-of/offset-of-dst-field.stderr @@ -34,20 +34,6 @@ LL | offset_of!((u8, dyn Trait), 1); = help: the trait `Sized` is not implemented for `dyn Trait` = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/offset-of-dst-field.rs:44:5 - | -LL | offset_of!(Delta<Alpha>, z); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: within `Alpha`, the trait `Sized` is not implemented for `[u8]`, which is required by `Alpha: Sized` -note: required because it appears within the type `Alpha` - --> $DIR/offset-of-dst-field.rs:5:8 - | -LL | struct Alpha { - | ^^^^^ - = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) - error[E0277]: the size for values of type `Extern` cannot be known at compilation time --> $DIR/offset-of-dst-field.rs:45:5 | @@ -66,6 +52,20 @@ LL | offset_of!(Delta<dyn Trait>, z); = help: the trait `Sized` is not implemented for `dyn Trait` = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/offset-of-dst-field.rs:44:5 + | +LL | offset_of!(Delta<Alpha>, z); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `Alpha`, the trait `Sized` is not implemented for `[u8]`, which is required by `Alpha: Sized` +note: required because it appears within the type `Alpha` + --> $DIR/offset-of-dst-field.rs:5:8 + | +LL | struct Alpha { + | ^^^^^ + = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) + error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/offset-of-dst-field.rs:50:5 | diff --git a/tests/ui/offset-of/offset-of-must-use.rs b/tests/ui/offset-of/offset-of-must-use.rs index f0c242891d8..87918b8ff95 100644 --- a/tests/ui/offset-of/offset-of-must-use.rs +++ b/tests/ui/offset-of/offset-of-must-use.rs @@ -4,5 +4,5 @@ fn main() { core::mem::offset_of!((String,), 0); - //~^ WARN unused return value of `must_use` that must be used + //~^ WARN unused `offset_of` call that must be used } diff --git a/tests/ui/offset-of/offset-of-must-use.stderr b/tests/ui/offset-of/offset-of-must-use.stderr index b6d88e098d0..9f0e37a59f4 100644 --- a/tests/ui/offset-of/offset-of-must-use.stderr +++ b/tests/ui/offset-of/offset-of-must-use.stderr @@ -1,8 +1,8 @@ -warning: unused return value of `must_use` that must be used +warning: unused `offset_of` call that must be used --> $DIR/offset-of-must-use.rs:6:5 | LL | core::mem::offset_of!((String,), 0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `offset_of` call produces a value | note: the lint level is defined here --> $DIR/offset-of-must-use.rs:3:9 diff --git a/tests/ui/offset-of/offset-of-temporaries.rs b/tests/ui/offset-of/offset-of-temporaries.rs new file mode 100644 index 00000000000..951a8ee2b50 --- /dev/null +++ b/tests/ui/offset-of/offset-of-temporaries.rs @@ -0,0 +1,23 @@ +//@ build-pass + +//! Regression test #124478. + +use std::mem::offset_of; + +struct S { + v: u8, + w: u16, +} + +impl S { + fn return_static_slice() -> &'static [usize] { + &[offset_of!(Self, v), offset_of!(Self, w)] + } + fn use_reference() -> usize { + let r = &offset_of!(Self, v); + *r * 6 + } +} + +fn main() { +} diff --git a/tests/ui/parser/attribute/attr-unquoted-ident.fixed b/tests/ui/parser/attribute/attr-unquoted-ident.fixed index 636508b5615..bc861ef69fb 100644 --- a/tests/ui/parser/attribute/attr-unquoted-ident.fixed +++ b/tests/ui/parser/attribute/attr-unquoted-ident.fixed @@ -1,6 +1,8 @@ //@ compile-flags: -Zdeduplicate-diagnostics=yes //@ run-rustfix +#![allow(unexpected_cfgs)] + fn main() { #[cfg(key="foo")] //~^ ERROR expected unsuffixed literal, found `foo` diff --git a/tests/ui/parser/attribute/attr-unquoted-ident.rs b/tests/ui/parser/attribute/attr-unquoted-ident.rs index 9b9a9f78403..8bdb8605ebb 100644 --- a/tests/ui/parser/attribute/attr-unquoted-ident.rs +++ b/tests/ui/parser/attribute/attr-unquoted-ident.rs @@ -1,6 +1,8 @@ //@ compile-flags: -Zdeduplicate-diagnostics=yes //@ run-rustfix +#![allow(unexpected_cfgs)] + fn main() { #[cfg(key=foo)] //~^ ERROR expected unsuffixed literal, found `foo` diff --git a/tests/ui/parser/attribute/attr-unquoted-ident.stderr b/tests/ui/parser/attribute/attr-unquoted-ident.stderr index bc028f39be6..99484a51110 100644 --- a/tests/ui/parser/attribute/attr-unquoted-ident.stderr +++ b/tests/ui/parser/attribute/attr-unquoted-ident.stderr @@ -1,5 +1,5 @@ error: expected unsuffixed literal, found `foo` - --> $DIR/attr-unquoted-ident.rs:5:15 + --> $DIR/attr-unquoted-ident.rs:7:15 | LL | #[cfg(key=foo)] | ^^^ @@ -10,7 +10,7 @@ LL | #[cfg(key="foo")] | + + error: expected unsuffixed literal, found `foo` - --> $DIR/attr-unquoted-ident.rs:11:15 + --> $DIR/attr-unquoted-ident.rs:13:15 | LL | #[cfg(key=foo bar baz)] | ^^^ diff --git a/tests/ui/pattern/issue-92074-macro-ice.stderr b/tests/ui/pattern/issue-92074-macro-ice.stderr index b340afff010..025592116e5 100644 --- a/tests/ui/pattern/issue-92074-macro-ice.stderr +++ b/tests/ui/pattern/issue-92074-macro-ice.stderr @@ -7,6 +7,7 @@ LL | () => { force_expr!(Vec::new()) } LL | assert!(matches!(x, En::A(make_vec!()))); | ----------- in this macro invocation | + = note: the `expr` fragment specifier forces the metavariable's content to be an expression = note: this error originates in the macro `make_vec` (in Nightly builds, run with -Z macro-backtrace for more info) error: arbitrary expressions aren't allowed in patterns @@ -18,6 +19,7 @@ LL | () => { force_pat!(get_usize(), get_usize()) } LL | assert!(matches!(5, make_pat!())); | ----------- in this macro invocation | + = note: the `expr` fragment specifier forces the metavariable's content to be an expression = note: this error originates in the macro `make_pat` (in Nightly builds, run with -Z macro-backtrace for more info) error: arbitrary expressions aren't allowed in patterns @@ -29,6 +31,7 @@ LL | () => { force_pat!(get_usize(), get_usize()) } LL | assert!(matches!(5, make_pat!())); | ----------- in this macro invocation | + = note: the `expr` fragment specifier forces the metavariable's content to be an expression = note: this error originates in the macro `make_pat` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/tests/ui/process/println-with-broken-pipe.rs b/tests/ui/process/println-with-broken-pipe.rs index 1df8c765cbd..798db3c0f8c 100644 --- a/tests/ui/process/println-with-broken-pipe.rs +++ b/tests/ui/process/println-with-broken-pipe.rs @@ -6,16 +6,14 @@ //@ ignore-horizon //@ ignore-android //@ normalize-stderr-test ".rs:\d+:\d+" -> ".rs:LL:CC" +//@ compile-flags: -Zon-broken-pipe=error // Test what the error message looks like when `println!()` panics because of // `std::io::ErrorKind::BrokenPipe` -#![feature(unix_sigpipe)] - use std::env; use std::process::{Command, Stdio}; -#[unix_sigpipe = "sig_ign"] fn main() { let mut args = env::args(); let me = args.next().unwrap(); diff --git a/tests/ui/regions/regions-refcell.rs b/tests/ui/regions/regions-refcell.rs index 29eb5161a6c..c27ffe6b6a8 100644 --- a/tests/ui/regions/regions-refcell.rs +++ b/tests/ui/regions/regions-refcell.rs @@ -3,6 +3,7 @@ // attempting to bootstrap librustc with new destructor lifetime // semantics. +#![allow(unexpected_cfgs)] // for the cfg-as-descriptions use std::collections::HashMap; use std::cell::RefCell; diff --git a/tests/ui/resolve/suggest-import-without-clobbering-attrs.fixed b/tests/ui/resolve/suggest-import-without-clobbering-attrs.fixed index d05c0f05806..607c9af4927 100644 --- a/tests/ui/resolve/suggest-import-without-clobbering-attrs.fixed +++ b/tests/ui/resolve/suggest-import-without-clobbering-attrs.fixed @@ -1,8 +1,8 @@ //@ run-rustfix -//@ compile-flags: --cfg=whatever -Aunused +//@ compile-flags: -Aunused use y::z; -#[cfg(whatever)] +#[cfg(all())] use y::Whatever; mod y { diff --git a/tests/ui/resolve/suggest-import-without-clobbering-attrs.rs b/tests/ui/resolve/suggest-import-without-clobbering-attrs.rs index 0be2e558e42..6cc53fb1086 100644 --- a/tests/ui/resolve/suggest-import-without-clobbering-attrs.rs +++ b/tests/ui/resolve/suggest-import-without-clobbering-attrs.rs @@ -1,7 +1,7 @@ //@ run-rustfix -//@ compile-flags: --cfg=whatever -Aunused +//@ compile-flags: -Aunused -#[cfg(whatever)] +#[cfg(all())] use y::Whatever; mod y { diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs index c73b8d7e4d2..de002ef71d7 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs @@ -1,4 +1,6 @@ //@ only-x86_64 +// Set the base cpu explicitly, in case the default has been changed. +//@ compile-flags: -C target-cpu=x86-64 #![feature(target_feature_11)] diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr index d9d7e297f8e..aa660db3867 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr @@ -1,5 +1,5 @@ error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:25:5 + --> $DIR/safe-calls.rs:27:5 | LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` @@ -8,7 +8,7 @@ LL | sse2(); = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:27:5 + --> $DIR/safe-calls.rs:29:5 | LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` @@ -16,7 +16,7 @@ LL | avx_bmi2(); = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:29:5 + --> $DIR/safe-calls.rs:31:5 | LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` @@ -24,7 +24,7 @@ LL | Quux.avx_bmi2(); = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:35:5 + --> $DIR/safe-calls.rs:37:5 | LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` @@ -32,7 +32,7 @@ LL | avx_bmi2(); = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:37:5 + --> $DIR/safe-calls.rs:39:5 | LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` @@ -40,7 +40,7 @@ LL | Quux.avx_bmi2(); = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:43:5 + --> $DIR/safe-calls.rs:45:5 | LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` @@ -49,7 +49,7 @@ LL | sse2(); = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:45:5 + --> $DIR/safe-calls.rs:47:5 | LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` @@ -57,7 +57,7 @@ LL | avx_bmi2(); = help: in order for the call to be safe, the context requires the following additional target feature: bmi2 error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:47:5 + --> $DIR/safe-calls.rs:49:5 | LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` @@ -65,7 +65,7 @@ LL | Quux.avx_bmi2(); = help: in order for the call to be safe, the context requires the following additional target feature: bmi2 error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:54:5 + --> $DIR/safe-calls.rs:56:5 | LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` @@ -74,7 +74,7 @@ LL | sse2(); = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:58:15 + --> $DIR/safe-calls.rs:60:15 | LL | const _: () = sse2(); | ^^^^^^ call to function with `#[target_feature]` @@ -83,7 +83,7 @@ LL | const _: () = sse2(); = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` error[E0133]: call to function `sse2_and_fxsr` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:61:15 + --> $DIR/safe-calls.rs:63:15 | LL | const _: () = sse2_and_fxsr(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` @@ -92,7 +92,7 @@ LL | const _: () = sse2_and_fxsr(); = note: the fxsr and sse2 target features being enabled in the build configuration does not remove the requirement to list them in `#[target_feature]` error: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe block (error E0133) - --> $DIR/safe-calls.rs:68:5 + --> $DIR/safe-calls.rs:70:5 | LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` @@ -101,12 +101,12 @@ LL | sse2(); = help: in order for the call to be safe, the context requires the following additional target feature: sse2 = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` note: an unsafe function restricts its caller, but its body is safe by default - --> $DIR/safe-calls.rs:67:1 + --> $DIR/safe-calls.rs:69:1 | LL | unsafe fn needs_unsafe_block() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: the lint level is defined here - --> $DIR/safe-calls.rs:64:8 + --> $DIR/safe-calls.rs:66:8 | LL | #[deny(unsafe_op_in_unsafe_fn)] | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-allowed.rs b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-allowed.rs index e35f743d96a..4b8d2406784 100644 --- a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-allowed.rs +++ b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-allowed.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: --cfg something +//@ compile-flags: --cfg something --check-cfg=cfg(nothing,something) #![deny(unused_mut)] diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.rs b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.rs index babeaf67eb2..e7a5d59958b 100644 --- a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.rs +++ b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --cfg something +//@ compile-flags: --cfg something --check-cfg=cfg(nothing,something) //@ edition:2018 #![feature(async_closure)] diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs b/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs index 5ff3cd25e67..402efaf5027 100644 --- a/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs +++ b/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs @@ -1,7 +1,5 @@ // Tests that dlltool failing to generate an import library will raise an error. -//@ only-gnu -//@ only-windows //@ needs-dlltool //@ compile-flags: --crate-type lib --emit link //@ normalize-stderr-test: "[^ ']*/dlltool.exe" -> "$$DLLTOOL" diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.rs b/tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.rs index ac6a2998a47..bcf6dda7a44 100644 --- a/tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.rs +++ b/tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.rs @@ -1,7 +1,6 @@ // Tests that failing to run dlltool will raise an error. -//@ only-gnu -//@ only-windows +//@ needs-dlltool //@ compile-flags: --crate-type lib --emit link -Cdlltool=does_not_exit.exe #[link(name = "foo", kind = "raw-dylib")] extern "C" { diff --git a/tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_dfl.rs b/tests/ui/runtime/on-broken-pipe/auxiliary/assert-inherit-sig_dfl.rs index 7f95fa7ebbe..b179e484524 100644 --- a/tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_dfl.rs +++ b/tests/ui/runtime/on-broken-pipe/auxiliary/assert-inherit-sig_dfl.rs @@ -1,8 +1,6 @@ //@ aux-crate: sigpipe_utils=sigpipe-utils.rs +//@ compile-flags: -Zon-broken-pipe=inherit -#![feature(unix_sigpipe)] - -#[unix_sigpipe = "inherit"] fn main() { sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default); } diff --git a/tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_ign.rs b/tests/ui/runtime/on-broken-pipe/auxiliary/assert-inherit-sig_ign.rs index d96e8b8ef84..5ea435521ec 100644 --- a/tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_ign.rs +++ b/tests/ui/runtime/on-broken-pipe/auxiliary/assert-inherit-sig_ign.rs @@ -1,8 +1,6 @@ //@ aux-crate: sigpipe_utils=sigpipe-utils.rs +//@ compile-flags: -Zon-broken-pipe=inherit -#![feature(unix_sigpipe)] - -#[unix_sigpipe = "inherit"] fn main() { sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Ignore); } diff --git a/tests/ui/attributes/unix_sigpipe/auxiliary/assert-sigpipe-disposition.rs b/tests/ui/runtime/on-broken-pipe/auxiliary/assert-sigpipe-disposition.rs index 117f6134b4e..117f6134b4e 100644 --- a/tests/ui/attributes/unix_sigpipe/auxiliary/assert-sigpipe-disposition.rs +++ b/tests/ui/runtime/on-broken-pipe/auxiliary/assert-sigpipe-disposition.rs diff --git a/tests/ui/attributes/unix_sigpipe/auxiliary/sigpipe-utils.rs b/tests/ui/runtime/on-broken-pipe/auxiliary/sigpipe-utils.rs index 3d93d50ca3f..3d93d50ca3f 100644 --- a/tests/ui/attributes/unix_sigpipe/auxiliary/sigpipe-utils.rs +++ b/tests/ui/runtime/on-broken-pipe/auxiliary/sigpipe-utils.rs diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-and-child-processes.rs b/tests/ui/runtime/on-broken-pipe/child-processes.rs index 9d1bd9f9607..0da2347481b 100644 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-and-child-processes.rs +++ b/tests/ui/runtime/on-broken-pipe/child-processes.rs @@ -1,25 +1,20 @@ -//@ revisions: default sig_dfl sig_ign inherit +//@ revisions: default error kill inherit //@ ignore-cross-compile because aux-bin does not yet support it //@ only-unix because SIGPIPE is a unix thing //@ run-pass //@ aux-bin:assert-sigpipe-disposition.rs //@ aux-crate:sigpipe_utils=sigpipe-utils.rs +//@ [kill] compile-flags: -Zunstable-options -Zon-broken-pipe=kill +//@ [error] compile-flags: -Zunstable-options -Zon-broken-pipe=error +//@ [inherit] compile-flags: -Zunstable-options -Zon-broken-pipe=inherit // Checks the signal disposition of `SIGPIPE` in child processes, and in our own -// process for robustness. Without any `unix_sigpipe` attribute, `SIG_IGN` is -// the default. But there is a difference in how `SIGPIPE` is treated in child -// processes with and without the attribute. Search for -// `unix_sigpipe_attr_specified()` in the code base to learn more. - -#![cfg_attr(any(sig_dfl, sig_ign, inherit), feature(unix_sigpipe))] +// process for robustness. extern crate sigpipe_utils; use sigpipe_utils::*; -#[cfg_attr(sig_dfl, unix_sigpipe = "sig_dfl")] -#[cfg_attr(sig_ign, unix_sigpipe = "sig_ign")] -#[cfg_attr(inherit, unix_sigpipe = "inherit")] fn main() { // By default we get SIG_IGN but the child gets SIG_DFL through an explicit // reset before exec: @@ -27,18 +22,18 @@ fn main() { #[cfg(default)] let (we_expect, child_expects) = (SignalHandler::Ignore, "SIG_DFL"); - // With #[unix_sigpipe = "sig_dfl"] we get SIG_DFL and the child does too - // without any special code running before exec. - #[cfg(sig_dfl)] + // We get SIG_DFL and the child does too without any special code running + // before exec. + #[cfg(kill)] let (we_expect, child_expects) = (SignalHandler::Default, "SIG_DFL"); - // With #[unix_sigpipe = "sig_ign"] we get SIG_IGN and the child does too - // without any special code running before exec. - #[cfg(sig_ign)] + // We get SIG_IGN and the child does too without any special code running + // before exec. + #[cfg(error)] let (we_expect, child_expects) = (SignalHandler::Ignore, "SIG_IGN"); - // With #[unix_sigpipe = "inherit"] we get SIG_DFL and the child does too - // without any special code running before exec. + // We get SIG_DFL and the child does too without any special code running + // before exec. #[cfg(inherit)] let (we_expect, child_expects) = (SignalHandler::Default, "SIG_DFL"); diff --git a/tests/ui/runtime/on-broken-pipe/default.rs b/tests/ui/runtime/on-broken-pipe/default.rs new file mode 100644 index 00000000000..c10d1cfacc0 --- /dev/null +++ b/tests/ui/runtime/on-broken-pipe/default.rs @@ -0,0 +1,4 @@ +//@ compile-flags: -Zon-broken-pipe=default +//@ check-fail + +fn main() {} diff --git a/tests/ui/runtime/on-broken-pipe/default.stderr b/tests/ui/runtime/on-broken-pipe/default.stderr new file mode 100644 index 00000000000..b90d7566cbb --- /dev/null +++ b/tests/ui/runtime/on-broken-pipe/default.stderr @@ -0,0 +1,2 @@ +error: incorrect value `default` for unstable option `on-broken-pipe` - either `kill`, `error`, or `inherit` was expected + diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-not-used.rs b/tests/ui/runtime/on-broken-pipe/error.rs index b0044f5e919..ab2036c2f41 100644 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-not-used.rs +++ b/tests/ui/runtime/on-broken-pipe/error.rs @@ -1,12 +1,10 @@ -//@ revisions: with_feature without_feature //@ run-pass //@ aux-build:sigpipe-utils.rs - -#![cfg_attr(with_feature, feature(unix_sigpipe))] +//@ compile-flags: -Zon-broken-pipe=error fn main() { extern crate sigpipe_utils; - // SIGPIPE shall be ignored since #[unix_sigpipe = "..."] is not used + // `-Zon-broken-pipe=error` is active, so we expect SIGPIPE to be ignored. sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Ignore); } diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-inherit.rs b/tests/ui/runtime/on-broken-pipe/inherit.rs index 694fa460e9b..64909b73528 100644 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-inherit.rs +++ b/tests/ui/runtime/on-broken-pipe/inherit.rs @@ -3,20 +3,20 @@ //@ aux-bin: assert-inherit-sig_dfl.rs //@ aux-bin: assert-inherit-sig_ign.rs //@ run-pass +//@ compile-flags: -Zon-broken-pipe=kill -#![feature(rustc_private, unix_sigpipe)] +#![feature(rustc_private)] extern crate libc; -// By default the Rust runtime resets SIGPIPE to SIG_DFL before exec:ing child -// processes so opt-out of that with `#[unix_sigpipe = "sig_dfl"]`. See +// By default the Rust runtime resets SIGPIPE to SIG_DFL before exec'ing child +// processes so opt-out of that with `-Zon-broken-pipe=kill`. See // https://github.com/rust-lang/rust/blob/bf4de3a874753bbee3323081c8b0c133444fed2d/library/std/src/sys/pal/unix/process/process_unix.rs#L359-L384 -#[unix_sigpipe = "sig_dfl"] fn main() { - // First expect SIG_DFL in a child process with #[unix_sigpipe = "inherit"]. + // First expect SIG_DFL in a child process with -`Zon-broken-pipe=inherit`. assert_inherit_sigpipe_disposition("auxiliary/bin/assert-inherit-sig_dfl"); - // With SIG_IGN we expect #[unix_sigpipe = "inherit"] to also get SIG_IGN. + // With SIG_IGN we expect `-Zon-broken-pipe=inherit` to also get SIG_IGN. unsafe { libc::signal(libc::SIGPIPE, libc::SIG_IGN); } diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-sig_dfl.rs b/tests/ui/runtime/on-broken-pipe/kill.rs index 30f2a9b1430..5dace6f1c6f 100644 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-sig_dfl.rs +++ b/tests/ui/runtime/on-broken-pipe/kill.rs @@ -1,13 +1,11 @@ //@ run-pass //@ aux-build:sigpipe-utils.rs +//@ compile-flags: -Zon-broken-pipe=kill -#![feature(unix_sigpipe)] - -#[unix_sigpipe = "sig_dfl"] fn main() { extern crate sigpipe_utils; - // #[unix_sigpipe = "sig_dfl"] is active, so SIGPIPE shall NOT be ignored, instead + // `-Zon-broken-pipe=kill` is active, so SIGPIPE shall NOT be ignored, instead // the default handler shall be installed sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default); } diff --git a/tests/ui/runtime/on-broken-pipe/no-flag-arg.rs b/tests/ui/runtime/on-broken-pipe/no-flag-arg.rs new file mode 100644 index 00000000000..2273291bfa7 --- /dev/null +++ b/tests/ui/runtime/on-broken-pipe/no-flag-arg.rs @@ -0,0 +1,4 @@ +//@ compile-flags: -Zon-broken-pipe +//@ check-fail + +fn main() {} diff --git a/tests/ui/runtime/on-broken-pipe/no-flag-arg.stderr b/tests/ui/runtime/on-broken-pipe/no-flag-arg.stderr new file mode 100644 index 00000000000..3d3e12d303c --- /dev/null +++ b/tests/ui/runtime/on-broken-pipe/no-flag-arg.stderr @@ -0,0 +1,2 @@ +error: unstable option `on-broken-pipe` requires either `kill`, `error`, or `inherit` (Z on-broken-pipe=<value>) + diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-sig_ign.rs b/tests/ui/runtime/on-broken-pipe/not-used.rs index ccd6c678660..e31236f2b3d 100644 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-sig_ign.rs +++ b/tests/ui/runtime/on-broken-pipe/not-used.rs @@ -1,13 +1,9 @@ //@ run-pass //@ aux-build:sigpipe-utils.rs -#![feature(unix_sigpipe)] - -#[unix_sigpipe = "sig_ign"] fn main() { extern crate sigpipe_utils; - // #[unix_sigpipe = "sig_ign"] is active, so the legacy behavior of ignoring - // SIGPIPE shall be in effect + // SIGPIPE shall be ignored since `-Zon-broken-pipe` is not used sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Ignore); } diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-rustc_main.rs b/tests/ui/runtime/on-broken-pipe/with-rustc_main.rs index 02a3f48f3b3..c1731200038 100644 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-rustc_main.rs +++ b/tests/ui/runtime/on-broken-pipe/with-rustc_main.rs @@ -1,15 +1,14 @@ //@ run-pass //@ aux-build:sigpipe-utils.rs +//@ compile-flags: -Zon-broken-pipe=kill -#![feature(unix_sigpipe)] #![feature(rustc_attrs)] -#[unix_sigpipe = "sig_dfl"] #[rustc_main] fn rustc_main() { extern crate sigpipe_utils; - // #[unix_sigpipe = "sig_dfl"] is active, so SIGPIPE handler shall be + // `-Zon-broken-pipe=kill` is active, so SIGPIPE handler shall be // SIG_DFL. Note that we have a #[rustc_main], but it should still work. sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default); } diff --git a/tests/ui/runtime/on-broken-pipe/wrong-flag-arg.rs b/tests/ui/runtime/on-broken-pipe/wrong-flag-arg.rs new file mode 100644 index 00000000000..14d0ac56b5a --- /dev/null +++ b/tests/ui/runtime/on-broken-pipe/wrong-flag-arg.rs @@ -0,0 +1,4 @@ +//@ compile-flags: -Zon-broken-pipe=wrong +//@ check-fail + +fn main() {} diff --git a/tests/ui/runtime/on-broken-pipe/wrong-flag-arg.stderr b/tests/ui/runtime/on-broken-pipe/wrong-flag-arg.stderr new file mode 100644 index 00000000000..3635418c845 --- /dev/null +++ b/tests/ui/runtime/on-broken-pipe/wrong-flag-arg.stderr @@ -0,0 +1,2 @@ +error: incorrect value `wrong` for unstable option `on-broken-pipe` - either `kill`, `error`, or `inherit` was expected + diff --git a/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.fixed b/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.fixed index f4506dd929e..878d1dc72cc 100644 --- a/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.fixed +++ b/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.fixed @@ -4,7 +4,7 @@ //@ edition:2018 #![deny(rust_2018_idioms)] -#![allow(dead_code)] +#![allow(dead_code, unexpected_cfgs)] // The suggestion span should include the attribute. diff --git a/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.rs b/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.rs index 4f1cb71dc51..573942bd095 100644 --- a/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.rs +++ b/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.rs @@ -4,7 +4,7 @@ //@ edition:2018 #![deny(rust_2018_idioms)] -#![allow(dead_code)] +#![allow(dead_code, unexpected_cfgs)] // The suggestion span should include the attribute. diff --git a/tests/ui/self/arbitrary-self-opaque.rs b/tests/ui/self/arbitrary-self-opaque.rs index 99357dde3e1..3331b037b05 100644 --- a/tests/ui/self/arbitrary-self-opaque.rs +++ b/tests/ui/self/arbitrary-self-opaque.rs @@ -6,7 +6,7 @@ type Bar = impl Sized; impl Foo { fn foo(self: Bar) {} - //~^ ERROR: invalid `self` parameter type: Bar + //~^ ERROR: invalid `self` parameter type: `Bar` } fn main() {} diff --git a/tests/ui/self/arbitrary-self-opaque.stderr b/tests/ui/self/arbitrary-self-opaque.stderr index 6b5db8d8493..0cbe22afac3 100644 --- a/tests/ui/self/arbitrary-self-opaque.stderr +++ b/tests/ui/self/arbitrary-self-opaque.stderr @@ -6,7 +6,7 @@ LL | type Bar = impl Sized; | = note: `Bar` must be used in combination with a concrete type within the same module -error[E0307]: invalid `self` parameter type: Bar +error[E0307]: invalid `self` parameter type: `Bar` --> $DIR/arbitrary-self-opaque.rs:8:18 | LL | fn foo(self: Bar) {} diff --git a/tests/ui/shell-argfiles/shell-argfiles-via-argfile.rs b/tests/ui/shell-argfiles/shell-argfiles-via-argfile.rs index b907fd3bbc7..2c07542bd75 100644 --- a/tests/ui/shell-argfiles/shell-argfiles-via-argfile.rs +++ b/tests/ui/shell-argfiles/shell-argfiles-via-argfile.rs @@ -1,6 +1,7 @@ // Check to see if we can get parameters from an @argsfile file // //@ build-pass +//@ no-auto-check-cfg //@ compile-flags: @{{src-base}}/shell-argfiles/shell-argfiles-via-argfile.args @shell:{{src-base}}/shell-argfiles/shell-argfiles-via-argfile-shell.args #[cfg(not(shell_args_set))] diff --git a/tests/ui/shell-argfiles/shell-argfiles.args b/tests/ui/shell-argfiles/shell-argfiles.args index e5bb4b807ec..6c596b0bbc0 100644 --- a/tests/ui/shell-argfiles/shell-argfiles.args +++ b/tests/ui/shell-argfiles/shell-argfiles.args @@ -1,3 +1,4 @@ --cfg unquoted_set '--cfg' 'single_quoted_set' "--cfg" "double_quoted_set" +--check-cfg 'cfg(cmdline_set, unquoted_set, single_quoted_set, double_quoted_set)' diff --git a/tests/ui/span/issue-27522.stderr b/tests/ui/span/issue-27522.stderr index c2de1562841..c57a100bbe2 100644 --- a/tests/ui/span/issue-27522.stderr +++ b/tests/ui/span/issue-27522.stderr @@ -1,4 +1,4 @@ -error[E0307]: invalid `self` parameter type: &SomeType +error[E0307]: invalid `self` parameter type: `&SomeType` --> $DIR/issue-27522.rs:6:22 | LL | fn handler(self: &SomeType); diff --git a/tests/ui/span/suggestion-raw-68962.rs b/tests/ui/span/suggestion-raw-68962.rs new file mode 100644 index 00000000000..0b581308f66 --- /dev/null +++ b/tests/ui/span/suggestion-raw-68962.rs @@ -0,0 +1,11 @@ +fn r#fn() {} + +fn main() { + let r#final = 1; + + // Should correctly suggest variable defined using raw identifier. + fina; //~ ERROR cannot find value + + // Should correctly suggest function defined using raw identifier. + f(); //~ ERROR cannot find function +} diff --git a/tests/ui/span/suggestion-raw-68962.stderr b/tests/ui/span/suggestion-raw-68962.stderr new file mode 100644 index 00000000000..2e25f5cbdf5 --- /dev/null +++ b/tests/ui/span/suggestion-raw-68962.stderr @@ -0,0 +1,18 @@ +error[E0425]: cannot find value `fina` in this scope + --> $DIR/suggestion-raw-68962.rs:7:5 + | +LL | fina; + | ^^^^ help: a local variable with a similar name exists: `r#final` + +error[E0425]: cannot find function `f` in this scope + --> $DIR/suggestion-raw-68962.rs:10:5 + | +LL | fn r#fn() {} + | --------- similarly named function `r#fn` defined here +... +LL | f(); + | ^ help: a function with a similar name exists: `r#fn` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/specialization/specialization-overlap-projection.stderr b/tests/ui/specialization/specialization-overlap-projection.current.stderr index 708c0817fd9..a69826fa96b 100644 --- a/tests/ui/specialization/specialization-overlap-projection.stderr +++ b/tests/ui/specialization/specialization-overlap-projection.current.stderr @@ -1,5 +1,5 @@ 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 + --> $DIR/specialization-overlap-projection.rs:10:12 | LL | #![feature(specialization)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/specialization/specialization-overlap-projection.next.stderr b/tests/ui/specialization/specialization-overlap-projection.next.stderr new file mode 100644 index 00000000000..ab040193fa4 --- /dev/null +++ b/tests/ui/specialization/specialization-overlap-projection.next.stderr @@ -0,0 +1,49 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-overlap-projection.rs:10:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0119]: conflicting implementations of trait `Foo` for type `u32` + --> $DIR/specialization-overlap-projection.rs:28:1 + | +LL | impl Foo for u32 {} + | ---------------- first implementation here +LL | impl Foo for <u8 as Assoc>::Output {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` + +error[E0119]: conflicting implementations of trait `Foo` for type `u32` + --> $DIR/specialization-overlap-projection.rs:30:1 + | +LL | impl Foo for u32 {} + | ---------------- first implementation here +... +LL | impl Foo for <u16 as Assoc>::Output {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` + +error[E0282]: type annotations needed + --> $DIR/specialization-overlap-projection.rs:17:27 + | +LL | default type Output = bool; + | ^^^^ cannot infer type for associated type `<T as Assoc>::Output` + +error[E0282]: type annotations needed + --> $DIR/specialization-overlap-projection.rs:21:35 + | +LL | impl Assoc for u8 { type Output = u8; } + | ^^ cannot infer type for associated type `<u8 as Assoc>::Output` + +error[E0282]: type annotations needed + --> $DIR/specialization-overlap-projection.rs:23:36 + | +LL | impl Assoc for u16 { type Output = u16; } + | ^^^ cannot infer type for associated type `<u16 as Assoc>::Output` + +error: aborting due to 5 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0119, E0282. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/specialization/specialization-overlap-projection.rs b/tests/ui/specialization/specialization-overlap-projection.rs index 66951b9d50c..78e75f623c4 100644 --- a/tests/ui/specialization/specialization-overlap-projection.rs +++ b/tests/ui/specialization/specialization-overlap-projection.rs @@ -1,4 +1,7 @@ -//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[current] check-pass // Test that impls on projected self types can resolve overlap, even when the // projections involve specialization, so long as the associated type is @@ -12,14 +15,19 @@ trait Assoc { impl<T> Assoc for T { default type Output = bool; + //[next]~^ ERROR type annotations needed } impl Assoc for u8 { type Output = u8; } +//[next]~^ ERROR type annotations needed impl Assoc for u16 { type Output = u16; } +//[next]~^ ERROR type annotations needed trait Foo {} impl Foo for u32 {} impl Foo for <u8 as Assoc>::Output {} +//[next]~^ ERROR conflicting implementations of trait `Foo` for type `u32` impl Foo for <u16 as Assoc>::Output {} +//[next]~^ ERROR conflicting implementations of trait `Foo` for type `u32` fn main() {} diff --git a/tests/ui/sse2.rs b/tests/ui/sse2.rs index fa6d79713b4..9ed6f6fefbd 100644 --- a/tests/ui/sse2.rs +++ b/tests/ui/sse2.rs @@ -2,6 +2,7 @@ #![allow(stable_features)] #![feature(cfg_target_feature)] +#![feature(lint_reasons)] use std::env; @@ -19,7 +20,8 @@ fn main() { assert!(cfg!(target_feature = "sse2"), "SSE2 was not detected as available on an x86 platform"); } - // check a negative case too -- allowed on x86, but not enabled by default - assert!(cfg!(not(target_feature = "avx2")), - "AVX2 shouldn't be detected as available by default on any platform"); + // check a negative case too -- certainly not enabled by default + #[expect(unexpected_cfgs)] + { assert!(cfg!(not(target_feature = "ferris_wheel")), + "🎡 shouldn't be detected as available by default on any platform") }; } diff --git a/tests/ui/statics/nested_struct.rs b/tests/ui/statics/nested_struct.rs index f5819f50789..6745e102962 100644 --- a/tests/ui/statics/nested_struct.rs +++ b/tests/ui/statics/nested_struct.rs @@ -9,7 +9,7 @@ pub struct Lint { pub name: &'static str, pub desc: &'static str, pub report_in_external_macro: bool, - pub is_loaded: bool, + pub is_externally_loaded: bool, pub crate_level_only: bool, } @@ -17,7 +17,7 @@ static FOO: &Lint = &Lint { name: &"foo", desc: "desc", report_in_external_macro: false, - is_loaded: true, + is_externally_loaded: true, crate_level_only: false, }; diff --git a/tests/ui/stats/hir-stats.stderr b/tests/ui/stats/hir-stats.stderr index dc24833c267..a3d0d47d407 100644 --- a/tests/ui/stats/hir-stats.stderr +++ b/tests/ui/stats/hir-stats.stderr @@ -11,15 +11,15 @@ ast-stats-1 Attribute 64 ( 1.0%) 2 32 ast-stats-1 - Normal 32 ( 0.5%) 1 ast-stats-1 - DocComment 32 ( 0.5%) 1 ast-stats-1 Local 80 ( 1.2%) 1 80 -ast-stats-1 Arm 96 ( 1.4%) 2 48 -ast-stats-1 ForeignItem 96 ( 1.4%) 1 96 -ast-stats-1 - Fn 96 ( 1.4%) 1 +ast-stats-1 ForeignItem 88 ( 1.3%) 1 88 +ast-stats-1 - Fn 88 ( 1.3%) 1 +ast-stats-1 Arm 96 ( 1.5%) 2 48 ast-stats-1 FnDecl 120 ( 1.8%) 5 24 ast-stats-1 FieldDef 160 ( 2.4%) 2 80 ast-stats-1 Stmt 160 ( 2.4%) 5 32 ast-stats-1 - Let 32 ( 0.5%) 1 ast-stats-1 - MacCall 32 ( 0.5%) 1 -ast-stats-1 - Expr 96 ( 1.4%) 3 +ast-stats-1 - Expr 96 ( 1.5%) 3 ast-stats-1 Param 160 ( 2.4%) 4 40 ast-stats-1 Block 192 ( 2.9%) 6 32 ast-stats-1 Variant 208 ( 3.1%) 2 104 @@ -28,7 +28,7 @@ ast-stats-1 - Trait 352 ( 5.3%) 4 ast-stats-1 AssocItem 352 ( 5.3%) 4 88 ast-stats-1 - Type 176 ( 2.7%) 2 ast-stats-1 - Fn 176 ( 2.7%) 2 -ast-stats-1 GenericParam 480 ( 7.2%) 5 96 +ast-stats-1 GenericParam 480 ( 7.3%) 5 96 ast-stats-1 Pat 504 ( 7.6%) 7 72 ast-stats-1 - Struct 72 ( 1.1%) 1 ast-stats-1 - Wild 72 ( 1.1%) 1 @@ -53,7 +53,7 @@ ast-stats-1 - Impl 136 ( 2.1%) 1 ast-stats-1 - Fn 272 ( 4.1%) 2 ast-stats-1 - Use 408 ( 6.2%) 3 ast-stats-1 ---------------------------------------------------------------- -ast-stats-1 Total 6_624 +ast-stats-1 Total 6_616 ast-stats-1 ast-stats-2 POST EXPANSION AST STATS ast-stats-2 Name Accumulated Size Count Item Size @@ -65,9 +65,9 @@ ast-stats-2 ExprField 48 ( 0.7%) 1 48 ast-stats-2 WherePredicate 56 ( 0.8%) 1 56 ast-stats-2 - BoundPredicate 56 ( 0.8%) 1 ast-stats-2 Local 80 ( 1.1%) 1 80 +ast-stats-2 ForeignItem 88 ( 1.2%) 1 88 +ast-stats-2 - Fn 88 ( 1.2%) 1 ast-stats-2 Arm 96 ( 1.3%) 2 48 -ast-stats-2 ForeignItem 96 ( 1.3%) 1 96 -ast-stats-2 - Fn 96 ( 1.3%) 1 ast-stats-2 InlineAsm 120 ( 1.7%) 1 120 ast-stats-2 FnDecl 120 ( 1.7%) 5 24 ast-stats-2 Attribute 128 ( 1.8%) 4 32 @@ -86,7 +86,7 @@ ast-stats-2 - Trait 352 ( 4.9%) 4 ast-stats-2 AssocItem 352 ( 4.9%) 4 88 ast-stats-2 - Type 176 ( 2.4%) 2 ast-stats-2 - Fn 176 ( 2.4%) 2 -ast-stats-2 GenericParam 480 ( 6.6%) 5 96 +ast-stats-2 GenericParam 480 ( 6.7%) 5 96 ast-stats-2 Pat 504 ( 7.0%) 7 72 ast-stats-2 - Struct 72 ( 1.0%) 1 ast-stats-2 - Wild 72 ( 1.0%) 1 @@ -113,7 +113,7 @@ ast-stats-2 - Impl 136 ( 1.9%) 1 ast-stats-2 - Fn 272 ( 3.8%) 2 ast-stats-2 - Use 544 ( 7.5%) 4 ast-stats-2 ---------------------------------------------------------------- -ast-stats-2 Total 7_224 +ast-stats-2 Total 7_216 ast-stats-2 hir-stats HIR STATS hir-stats Name Accumulated Size Count Item Size @@ -129,6 +129,9 @@ hir-stats Body 72 ( 0.8%) 3 24 hir-stats InlineAsm 72 ( 0.8%) 1 72 hir-stats ImplItemRef 72 ( 0.8%) 2 36 hir-stats Arm 80 ( 0.9%) 2 40 +hir-stats GenericArg 96 ( 1.1%) 4 24 +hir-stats - Type 24 ( 0.3%) 1 +hir-stats - Lifetime 72 ( 0.8%) 3 hir-stats FieldDef 96 ( 1.1%) 2 48 hir-stats Stmt 96 ( 1.1%) 3 32 hir-stats - Let 32 ( 0.4%) 1 @@ -136,43 +139,40 @@ hir-stats - Semi 32 ( 0.4%) 1 hir-stats - Expr 32 ( 0.4%) 1 hir-stats FnDecl 120 ( 1.3%) 3 40 hir-stats Attribute 128 ( 1.4%) 4 32 -hir-stats GenericArg 128 ( 1.4%) 4 32 -hir-stats - Type 32 ( 0.4%) 1 -hir-stats - Lifetime 96 ( 1.1%) 3 +hir-stats Variant 144 ( 1.6%) 2 72 hir-stats GenericArgs 144 ( 1.6%) 3 48 -hir-stats Variant 176 ( 1.9%) 2 88 hir-stats GenericBound 192 ( 2.1%) 4 48 hir-stats - Trait 192 ( 2.1%) 4 hir-stats WherePredicate 192 ( 2.1%) 3 64 hir-stats - BoundPredicate 192 ( 2.1%) 3 hir-stats Block 288 ( 3.2%) 6 48 +hir-stats GenericParam 360 ( 4.0%) 5 72 hir-stats Pat 360 ( 4.0%) 5 72 hir-stats - Wild 72 ( 0.8%) 1 hir-stats - Struct 72 ( 0.8%) 1 hir-stats - Binding 216 ( 2.4%) 3 -hir-stats GenericParam 400 ( 4.4%) 5 80 hir-stats Generics 560 ( 6.2%) 10 56 -hir-stats Ty 720 ( 7.9%) 15 48 +hir-stats Ty 720 ( 8.0%) 15 48 hir-stats - Ptr 48 ( 0.5%) 1 hir-stats - Ref 48 ( 0.5%) 1 hir-stats - Path 624 ( 6.9%) 13 -hir-stats Expr 768 ( 8.4%) 12 64 +hir-stats Expr 768 ( 8.5%) 12 64 hir-stats - Path 64 ( 0.7%) 1 hir-stats - Struct 64 ( 0.7%) 1 hir-stats - Match 64 ( 0.7%) 1 hir-stats - InlineAsm 64 ( 0.7%) 1 hir-stats - Lit 128 ( 1.4%) 2 -hir-stats - Block 384 ( 4.2%) 6 -hir-stats Item 968 (10.6%) 11 88 +hir-stats - Block 384 ( 4.3%) 6 +hir-stats Item 968 (10.8%) 11 88 hir-stats - Trait 88 ( 1.0%) 1 hir-stats - Enum 88 ( 1.0%) 1 hir-stats - ExternCrate 88 ( 1.0%) 1 hir-stats - ForeignMod 88 ( 1.0%) 1 hir-stats - Impl 88 ( 1.0%) 1 -hir-stats - Fn 176 ( 1.9%) 2 +hir-stats - Fn 176 ( 2.0%) 2 hir-stats - Use 352 ( 3.9%) 4 -hir-stats Path 1_240 (13.6%) 31 40 -hir-stats PathSegment 1_920 (21.1%) 40 48 +hir-stats Path 1_240 (13.8%) 31 40 +hir-stats PathSegment 1_920 (21.4%) 40 48 hir-stats ---------------------------------------------------------------- -hir-stats Total 9_096 +hir-stats Total 8_992 hir-stats diff --git a/tests/ui/str/str-escape.stderr b/tests/ui/str/str-escape.stderr index 00fe5444e1a..c4aee2a110a 100644 --- a/tests/ui/str/str-escape.stderr +++ b/tests/ui/str/str-escape.stderr @@ -15,7 +15,7 @@ LL | let s = c"foo\ LL | |  bar | | ^ whitespace symbol '\u{a0}' is not skipped | |___| - | + | warning: whitespace symbol '\u{c}' is not skipped --> $DIR/str-escape.rs:26:16 @@ -25,7 +25,7 @@ LL | let s = b"a\ LL | | b"; | | ^- whitespace symbol '\u{c}' is not skipped | |____| - | + | warning: 3 warnings emitted diff --git a/tests/ui/structs-enums/struct-rec/issue-17431-2.stderr b/tests/ui/structs-enums/struct-rec/issue-17431-2.stderr index cdf51632acd..e818409366d 100644 --- a/tests/ui/structs-enums/struct-rec/issue-17431-2.stderr +++ b/tests/ui/structs-enums/struct-rec/issue-17431-2.stderr @@ -11,7 +11,7 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle | LL ~ struct Baz { q: Option<Box<Foo>> } LL | -LL | +LL | LL ~ struct Foo { q: Option<Box<Baz>> } | diff --git a/tests/ui/structs-enums/struct-rec/mutual-struct-recursion.stderr b/tests/ui/structs-enums/struct-rec/mutual-struct-recursion.stderr index 881bc281936..afe523939ac 100644 --- a/tests/ui/structs-enums/struct-rec/mutual-struct-recursion.stderr +++ b/tests/ui/structs-enums/struct-rec/mutual-struct-recursion.stderr @@ -16,7 +16,7 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle | LL ~ y: Box<B<T>>, LL | } -LL | +LL | LL | struct B<T> { LL ~ z: Box<A<T>> | @@ -39,7 +39,7 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle | LL ~ y: Option<Option<Box<D<T>>>>, LL | } -LL | +LL | LL | struct D<T> { LL ~ z: Option<Option<Box<C<T>>>>, | diff --git a/tests/ui/suggestions/issue-99240-2.stderr b/tests/ui/suggestions/issue-99240-2.stderr index 00bffee6529..5b86bc9880f 100644 --- a/tests/ui/suggestions/issue-99240-2.stderr +++ b/tests/ui/suggestions/issue-99240-2.stderr @@ -8,7 +8,7 @@ LL | // Alias:: LL | || Unit(); | ||________^_- call expression requires function | |________| - | + | | help: `Alias::Unit` is a unit enum variant, and does not take parentheses to be constructed | diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr b/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr index c0dc71df06e..abbf56cfac8 100644 --- a/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr +++ b/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr @@ -26,7 +26,7 @@ help: consider changing method `bar`'s `self` parameter to be `&self` LL | fn bar(self: &Self) {} | ~~~~~ -error[E0307]: invalid `self` parameter type: () +error[E0307]: invalid `self` parameter type: `()` --> $DIR/object-unsafe-trait-should-use-where-sized.rs:6:18 | LL | fn bar(self: ()) {} diff --git a/tests/ui/target-feature/no-llvm-leaks.rs b/tests/ui/target-feature/no-llvm-leaks.rs index b4a391e184e..73cec0a4496 100644 --- a/tests/ui/target-feature/no-llvm-leaks.rs +++ b/tests/ui/target-feature/no-llvm-leaks.rs @@ -6,7 +6,7 @@ //@ build-pass #![no_core] #![crate_type = "rlib"] -#![feature(intrinsics, rustc_attrs, no_core, lang_items, staged_api)] +#![feature(intrinsics, rustc_attrs, no_core, lang_items, staged_api, lint_reasons)] #![stable(feature = "test", since = "1.0.0")] // Supporting minimal rust core code @@ -43,22 +43,30 @@ macro_rules! assert { #[cfg(target_arch = "aarch64")] fn check_aarch64() { - // This checks that the rustc feature name is used, not the LLVM feature. + // These checks that the rustc feature name is used, not the LLVM feature. + assert!(cfg!(target_feature = "neon")); - assert!(cfg!(not(target_feature = "fp-armv8"))); + // #[expect(unexpected_cfgs)] except that 32-bit arm actually use fp-armv8 + { assert!(cfg!(not(target_feature = "fp-armv8"))); } + assert!(cfg!(target_feature = "fhm")); - assert!(cfg!(not(target_feature = "fp16fml"))); + #[expect(unexpected_cfgs)] + { assert!(cfg!(not(target_feature = "fp16fml"))); } + assert!(cfg!(target_feature = "fp16")); - assert!(cfg!(not(target_feature = "fullfp16"))); + #[expect(unexpected_cfgs)] + { assert!(cfg!(not(target_feature = "fullfp16"))); } } #[cfg(target_arch = "x86_64")] fn check_x86_64() { // This checks that the rustc feature name is used, not the LLVM feature. assert!(cfg!(target_feature = "rdrand")); - assert!(cfg!(not(target_feature = "rdrnd"))); + #[expect(unexpected_cfgs)] + { assert!(cfg!(not(target_feature = "rdrnd"))); } // Likewise: We enable LLVM's crc32 feature with SSE4.2, but Rust says it's just SSE4.2 assert!(cfg!(target_feature = "sse4.2")); - assert!(cfg!(not(target_feature = "crc32"))); + #[expect(unexpected_cfgs)] + { assert!(cfg!(not(target_feature = "crc32"))); } } diff --git a/tests/ui/traits/dyn-any-prefer-vtable.rs b/tests/ui/traits/dyn-any-prefer-vtable.rs new file mode 100644 index 00000000000..ca9d655239d --- /dev/null +++ b/tests/ui/traits/dyn-any-prefer-vtable.rs @@ -0,0 +1,9 @@ +//@ run-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +fn main() { + let x: &dyn std::any::Any = &1i32; + assert_eq!(x.type_id(), std::any::TypeId::of::<i32>()); +} diff --git a/tests/ui/traits/issue-78372.rs b/tests/ui/traits/issue-78372.rs index 143325c097c..b97835bbc57 100644 --- a/tests/ui/traits/issue-78372.rs +++ b/tests/ui/traits/issue-78372.rs @@ -6,7 +6,7 @@ impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {} //~ ERROR cannot find type `U` //~| ERROR the trait `DispatchFromDyn` may only be implemented for a coercion between structures trait Foo: X<u32> {} trait X<T> { - fn foo(self: Smaht<Self, T>); //~ ERROR: invalid `self` + fn foo(self: Smaht<Self, T>); //~ ERROR: invalid `self` parameter type } trait Marker {} impl Marker for dyn Foo {} diff --git a/tests/ui/traits/issue-78372.stderr b/tests/ui/traits/issue-78372.stderr index edb07957c44..58a4c229e5e 100644 --- a/tests/ui/traits/issue-78372.stderr +++ b/tests/ui/traits/issue-78372.stderr @@ -79,7 +79,7 @@ LL | trait X<T> { LL | fn foo(self: Smaht<Self, T>); | ^^^^^^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on -error[E0307]: invalid `self` parameter type: Smaht<Self, T> +error[E0307]: invalid `self` parameter type: `Smaht<Self, T>` --> $DIR/issue-78372.rs:9:18 | LL | fn foo(self: Smaht<Self, T>); diff --git a/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr b/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr index ac05dfb2d46..562d7ccf9fe 100644 --- a/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr +++ b/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr @@ -1,18 +1,26 @@ -error[E0277]: `impl Future<Output = ()>` cannot be sent between threads safely +error: future cannot be sent between threads safely --> $DIR/auto-with-drop_tracking_mir.rs:25:13 | LL | is_send(foo()); - | ------- ^^^^^ `impl Future<Output = ()>` cannot be sent between threads safely - | | - | required by a bound introduced by this call + | ^^^^^ future returned by `foo` is not `Send` | - = help: the trait `Send` is not implemented for `impl Future<Output = ()>` + = help: the trait `Sync` is not implemented for `impl Future<Output = ()>`, which is required by `impl Future<Output = ()>: Send` +note: future is not `Send` as this value is used across an await + --> $DIR/auto-with-drop_tracking_mir.rs:16:11 + | +LL | let x = &NotSync; + | - has type `&NotSync` which is not `Send` +LL | bar().await; + | ^^^^^ await occurs here, with `x` maybe used later note: required by a bound in `is_send` --> $DIR/auto-with-drop_tracking_mir.rs:24:24 | LL | fn is_send(_: impl Send) {} | ^^^^ required by this bound in `is_send` +help: consider dereferencing here + | +LL | is_send(*foo()); + | + error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.rs b/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.rs index c82c1793119..17741161b31 100644 --- a/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.rs +++ b/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.rs @@ -23,5 +23,5 @@ async fn bar() {} fn main() { fn is_send(_: impl Send) {} is_send(foo()); - //[fail]~^ ERROR `impl Future<Output = ()>` cannot be sent between threads safely + //[fail]~^ ERROR future cannot be sent between threads safely } diff --git a/tests/ui/traits/next-solver/builtin-fn-must-return-sized.rs b/tests/ui/traits/next-solver/builtin-fn-must-return-sized.rs index ccb10bab6c1..f8926b24e3f 100644 --- a/tests/ui/traits/next-solver/builtin-fn-must-return-sized.rs +++ b/tests/ui/traits/next-solver/builtin-fn-must-return-sized.rs @@ -13,5 +13,5 @@ fn foo<F: Fn<T>, T: Tuple>(f: Option<F>, t: T) { fn main() { foo::<fn() -> str, _>(None, ()); - //~^ expected a `Fn<_>` closure, found `fn() -> str` + //~^ the size for values of type `str` cannot be known at compilation time } diff --git a/tests/ui/traits/next-solver/builtin-fn-must-return-sized.stderr b/tests/ui/traits/next-solver/builtin-fn-must-return-sized.stderr index 08047852f20..b487ceef1d4 100644 --- a/tests/ui/traits/next-solver/builtin-fn-must-return-sized.stderr +++ b/tests/ui/traits/next-solver/builtin-fn-must-return-sized.stderr @@ -1,10 +1,11 @@ -error[E0277]: expected a `Fn<_>` closure, found `fn() -> str` +error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/builtin-fn-must-return-sized.rs:15:11 | LL | foo::<fn() -> str, _>(None, ()); - | ^^^^^^^^^^^ expected an `Fn<_>` closure, found `fn() -> str` + | ^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: the trait `Fn<_>` is not implemented for `fn() -> str` + = help: within `fn() -> str`, the trait `Sized` is not implemented for `str`, which is required by `fn() -> str: Fn<_>` + = note: required because it appears within the type `fn() -> str` note: required by a bound in `foo` --> $DIR/builtin-fn-must-return-sized.rs:10:11 | diff --git a/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr b/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr index 57cba790b55..6e68646fbe4 100644 --- a/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr +++ b/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr @@ -1,12 +1,12 @@ -error[E0119]: conflicting implementations of trait `Trait` for type `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>` +error[E0119]: conflicting implementations of trait `Trait` for type `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>>` --> $DIR/coherence-fulfill-overflow.rs:12:1 | LL | impl<T: ?Sized + TwoW> Trait for W<T> {} | ------------------------------------- first implementation here LL | impl<T: ?Sized + TwoW> Trait for T {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>>` | - = note: overflow evaluating the requirement `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>: TwoW` + = note: overflow evaluating the requirement `W<W<W<W<_>>>>: TwoW` = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`coherence_fulfill_overflow`) error: aborting due to 1 previous error diff --git a/tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.stderr b/tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.stderr index 8d7d8cee08a..df25150c21f 100644 --- a/tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.stderr +++ b/tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.stderr @@ -1,9 +1,16 @@ -error[E0275]: overflow evaluating the requirement `W<_>: Trait` +error[E0275]: overflow evaluating the requirement `_: Sized` --> $DIR/fixpoint-exponential-growth.rs:33:13 | LL | impls::<W<_>>(); | ^^^^ | +note: required for `W<(W<_>, W<_>)>` to implement `Trait` + --> $DIR/fixpoint-exponential-growth.rs:23:12 + | +LL | impl<T, U> Trait for W<(W<T>, W<U>)> + | - ^^^^^ ^^^^^^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here note: required by a bound in `impls` --> $DIR/fixpoint-exponential-growth.rs:30:13 | diff --git a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs index 7eea81ce03c..bc9bb6ce2d7 100644 --- a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs +++ b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs @@ -61,7 +61,7 @@ where // entering the cycle from `A` fails, but would work if we were to use the cache // result of `B<X>`. impls_trait::<A<X>, _, _, _>(); - //~^ ERROR the trait bound `A<X>: Trait<_, _, _>` is not satisfied + //~^ ERROR the trait bound `X: IncompleteGuidance<_, _>` is not satisfied } fn main() { diff --git a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr index d4932191791..78116ebba82 100644 --- a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr +++ b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr @@ -1,10 +1,21 @@ -error[E0277]: the trait bound `A<X>: Trait<_, _, _>` is not satisfied +error[E0277]: the trait bound `X: IncompleteGuidance<_, _>` is not satisfied --> $DIR/incompleteness-unstable-result.rs:63:19 | LL | impls_trait::<A<X>, _, _, _>(); - | ^^^^ the trait `Trait<_, _, _>` is not implemented for `A<X>` + | ^^^^ the trait `IncompleteGuidance<_, _>` is not implemented for `X`, which is required by `A<X>: Trait<_, _, _>` | - = help: the trait `Trait<U, V, D>` is implemented for `A<T>` + = help: the following other types implement trait `IncompleteGuidance<T, V>`: + <T as IncompleteGuidance<U, i16>> + <T as IncompleteGuidance<U, i8>> + <T as IncompleteGuidance<U, u8>> +note: required for `A<X>` to implement `Trait<_, _, u8>` + --> $DIR/incompleteness-unstable-result.rs:32:50 + | +LL | impl<T: ?Sized, U: ?Sized, V: ?Sized, D: ?Sized> Trait<U, V, D> for A<T> + | ^^^^^^^^^^^^^^ ^^^^ +LL | where +LL | T: IncompleteGuidance<U, V>, + | ------------------------ unsatisfied trait bound introduced here note: required by a bound in `impls_trait` --> $DIR/incompleteness-unstable-result.rs:51:28 | diff --git a/tests/ui/traits/next-solver/cycles/double-cycle-inductive-coinductive.stderr b/tests/ui/traits/next-solver/cycles/double-cycle-inductive-coinductive.stderr index 7cedb4d36c9..86c71ad92ff 100644 --- a/tests/ui/traits/next-solver/cycles/double-cycle-inductive-coinductive.stderr +++ b/tests/ui/traits/next-solver/cycles/double-cycle-inductive-coinductive.stderr @@ -1,21 +1,53 @@ -error[E0275]: overflow evaluating the requirement `(): Trait` +error[E0275]: overflow evaluating the requirement `(): Inductive` --> $DIR/double-cycle-inductive-coinductive.rs:32:19 | LL | impls_trait::<()>(); | ^^ | +note: required for `()` to implement `Trait` + --> $DIR/double-cycle-inductive-coinductive.rs:9:34 + | +LL | impl<T: Inductive + Coinductive> Trait for T {} + | --------- ^^^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required for `()` to implement `Inductive` + --> $DIR/double-cycle-inductive-coinductive.rs:12:16 + | +LL | impl<T: Trait> Inductive for T {} + | ----- ^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + = note: 7 redundant requirements hidden + = note: required for `()` to implement `Trait` note: required by a bound in `impls_trait` --> $DIR/double-cycle-inductive-coinductive.rs:17:19 | LL | fn impls_trait<T: Trait>() {} | ^^^^^ required by this bound in `impls_trait` -error[E0275]: overflow evaluating the requirement `(): TraitRev` +error[E0275]: overflow evaluating the requirement `(): CoinductiveRev` --> $DIR/double-cycle-inductive-coinductive.rs:35:23 | LL | impls_trait_rev::<()>(); | ^^ | +note: required for `()` to implement `TraitRev` + --> $DIR/double-cycle-inductive-coinductive.rs:21:40 + | +LL | impl<T: CoinductiveRev + InductiveRev> TraitRev for T {} + | -------------- ^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required for `()` to implement `CoinductiveRev` + --> $DIR/double-cycle-inductive-coinductive.rs:27:19 + | +LL | impl<T: TraitRev> CoinductiveRev for T {} + | -------- ^^^^^^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + = note: 7 redundant requirements hidden + = note: required for `()` to implement `TraitRev` note: required by a bound in `impls_trait_rev` --> $DIR/double-cycle-inductive-coinductive.rs:29:23 | diff --git a/tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.stderr b/tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.stderr index a2a5c028cf8..ea46c0fea97 100644 --- a/tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.stderr +++ b/tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.stderr @@ -1,9 +1,19 @@ -error[E0275]: overflow evaluating the requirement `W<_>: Trait` +error[E0275]: overflow evaluating the requirement `W<W<_>>: Trait` --> $DIR/inductive-fixpoint-hang.rs:31:19 | LL | impls_trait::<W<_>>(); | ^^^^ | +note: required for `W<W<W<_>>>` to implement `Trait` + --> $DIR/inductive-fixpoint-hang.rs:22:17 + | +LL | impl<T: ?Sized> Trait for W<W<T>> + | ^^^^^ ^^^^^^^ +LL | where +LL | W<T>: Trait, + | ----- unsatisfied trait bound introduced here + = note: 8 redundant requirements hidden + = note: required for `W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>` to implement `Trait` note: required by a bound in `impls_trait` --> $DIR/inductive-fixpoint-hang.rs:28:19 | diff --git a/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.rs b/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.rs index 78683372580..9d0ea51b1b2 100644 --- a/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.rs +++ b/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.rs @@ -39,7 +39,7 @@ fn impls_ar<T: AR>() {} fn main() { impls_a::<()>(); - //~^ ERROR overflow evaluating the requirement `(): A` + //~^ ERROR overflow evaluating the requirement `(): B` impls_ar::<()>(); //~^ ERROR overflow evaluating the requirement `(): AR` diff --git a/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.stderr b/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.stderr index e9cc6bc6c81..fe02d3c407c 100644 --- a/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.stderr +++ b/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.stderr @@ -1,9 +1,25 @@ -error[E0275]: overflow evaluating the requirement `(): A` +error[E0275]: overflow evaluating the requirement `(): B` --> $DIR/inductive-not-on-stack.rs:41:15 | LL | impls_a::<()>(); | ^^ | +note: required for `()` to implement `A` + --> $DIR/inductive-not-on-stack.rs:21:16 + | +LL | impl<T: B + C> A for T {} + | - ^ ^ + | | + | unsatisfied trait bound introduced here +note: required for `()` to implement `B` + --> $DIR/inductive-not-on-stack.rs:22:12 + | +LL | impl<T: A> B for T {} + | - ^ ^ + | | + | unsatisfied trait bound introduced here + = note: 7 redundant requirements hidden + = note: required for `()` to implement `A` note: required by a bound in `impls_a` --> $DIR/inductive-not-on-stack.rs:25:15 | @@ -16,6 +32,29 @@ error[E0275]: overflow evaluating the requirement `(): AR` LL | impls_ar::<()>(); | ^^ | +note: required for `()` to implement `BR` + --> $DIR/inductive-not-on-stack.rs:35:13 + | +LL | impl<T: AR> BR for T {} + | -- ^^ ^ + | | + | unsatisfied trait bound introduced here +note: required for `()` to implement `CR` + --> $DIR/inductive-not-on-stack.rs:36:13 + | +LL | impl<T: BR> CR for T {} + | -- ^^ ^ + | | + | unsatisfied trait bound introduced here +note: required for `()` to implement `AR` + --> $DIR/inductive-not-on-stack.rs:34:18 + | +LL | impl<T: CR + BR> AR for T {} + | -- ^^ ^ + | | + | unsatisfied trait bound introduced here + = note: 6 redundant requirements hidden + = note: required for `()` to implement `AR` note: required by a bound in `impls_ar` --> $DIR/inductive-not-on-stack.rs:38:16 | diff --git a/tests/ui/traits/next-solver/cycles/mixed-cycles-1.rs b/tests/ui/traits/next-solver/cycles/mixed-cycles-1.rs index 6d75d241864..b90a354be1b 100644 --- a/tests/ui/traits/next-solver/cycles/mixed-cycles-1.rs +++ b/tests/ui/traits/next-solver/cycles/mixed-cycles-1.rs @@ -35,5 +35,5 @@ fn impls_a<T: A>() {} fn main() { impls_a::<()>(); - //~^ ERROR overflow evaluating the requirement `(): A` + //~^ ERROR overflow evaluating the requirement `(): CInd` } diff --git a/tests/ui/traits/next-solver/cycles/mixed-cycles-1.stderr b/tests/ui/traits/next-solver/cycles/mixed-cycles-1.stderr index 17544eb1da5..03e61dbf99c 100644 --- a/tests/ui/traits/next-solver/cycles/mixed-cycles-1.stderr +++ b/tests/ui/traits/next-solver/cycles/mixed-cycles-1.stderr @@ -1,9 +1,46 @@ -error[E0275]: overflow evaluating the requirement `(): A` +error[E0275]: overflow evaluating the requirement `(): CInd` --> $DIR/mixed-cycles-1.rs:37:15 | LL | impls_a::<()>(); | ^^ | +note: required for `()` to implement `B` + --> $DIR/mixed-cycles-1.rs:31:28 + | +LL | impl<T: ?Sized + CInd + C> B for T {} + | ---- ^ ^ + | | + | unsatisfied trait bound introduced here +note: required for `()` to implement `C` + --> $DIR/mixed-cycles-1.rs:32:25 + | +LL | impl<T: ?Sized + B + A> C for T {} + | - ^ ^ + | | + | unsatisfied trait bound introduced here +note: required for `()` to implement `CInd` + --> $DIR/mixed-cycles-1.rs:28:21 + | +LL | impl<T: ?Sized + C> CInd for T {} + | - ^^^^ ^ + | | + | unsatisfied trait bound introduced here + = note: 4 redundant requirements hidden + = note: required for `()` to implement `B` +note: required for `()` to implement `BInd` + --> $DIR/mixed-cycles-1.rs:23:21 + | +LL | impl<T: ?Sized + B> BInd for T {} + | - ^^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required for `()` to implement `A` + --> $DIR/mixed-cycles-1.rs:30:28 + | +LL | impl<T: ?Sized + BInd + C> A for T {} + | ---- ^ ^ + | | + | unsatisfied trait bound introduced here note: required by a bound in `impls_a` --> $DIR/mixed-cycles-1.rs:34:15 | diff --git a/tests/ui/traits/next-solver/cycles/mixed-cycles-2.rs b/tests/ui/traits/next-solver/cycles/mixed-cycles-2.rs index c939a6e5ef2..a3ffcaafb37 100644 --- a/tests/ui/traits/next-solver/cycles/mixed-cycles-2.rs +++ b/tests/ui/traits/next-solver/cycles/mixed-cycles-2.rs @@ -28,5 +28,5 @@ fn impls_a<T: A>() {} fn main() { impls_a::<()>(); - //~^ ERROR overflow evaluating the requirement `(): A` + //~^ ERROR overflow evaluating the requirement `(): BInd` } diff --git a/tests/ui/traits/next-solver/cycles/mixed-cycles-2.stderr b/tests/ui/traits/next-solver/cycles/mixed-cycles-2.stderr index a9be1016c74..892426abe82 100644 --- a/tests/ui/traits/next-solver/cycles/mixed-cycles-2.stderr +++ b/tests/ui/traits/next-solver/cycles/mixed-cycles-2.stderr @@ -1,9 +1,32 @@ -error[E0275]: overflow evaluating the requirement `(): A` +error[E0275]: overflow evaluating the requirement `(): BInd` --> $DIR/mixed-cycles-2.rs:30:15 | LL | impls_a::<()>(); | ^^ | +note: required for `()` to implement `B` + --> $DIR/mixed-cycles-2.rs:25:24 + | +LL | impl<T: ?Sized + BInd> B for T {} + | ---- ^ ^ + | | + | unsatisfied trait bound introduced here +note: required for `()` to implement `BInd` + --> $DIR/mixed-cycles-2.rs:22:21 + | +LL | impl<T: ?Sized + B> BInd for T {} + | - ^^^^ ^ + | | + | unsatisfied trait bound introduced here + = note: 6 redundant requirements hidden + = note: required for `()` to implement `BInd` +note: required for `()` to implement `A` + --> $DIR/mixed-cycles-2.rs:24:28 + | +LL | impl<T: ?Sized + BInd + B> A for T {} + | ---- ^ ^ + | | + | unsatisfied trait bound introduced here note: required by a bound in `impls_a` --> $DIR/mixed-cycles-2.rs:27:15 | diff --git a/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.rs b/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.rs index ce7a380f07a..d11150ca55a 100644 --- a/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.rs +++ b/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.rs @@ -25,7 +25,7 @@ fn foo<T: Foo>() { // // https://github.com/rust-lang/trait-system-refactor-initiative/issues/76 require_bar::<T>(); - //~^ ERROR the trait bound `T: Bar` is not satisfied + //~^ ERROR type mismatch resolving `<T as Foo>::Assoc == i32` } fn main() {} diff --git a/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr b/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr index 2785357e792..3ef0afa38bf 100644 --- a/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr +++ b/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr @@ -1,19 +1,25 @@ -error[E0277]: the trait bound `T: Bar` is not satisfied +error[E0271]: type mismatch resolving `<T as Foo>::Assoc == i32` --> $DIR/param-candidate-shadows-project.rs:27:19 | LL | require_bar::<T>(); - | ^ the trait `Bar` is not implemented for `T` + | ^ type mismatch resolving `<T as Foo>::Assoc == i32` | +note: types differ + --> $DIR/param-candidate-shadows-project.rs:10:18 + | +LL | type Assoc = i32; + | ^^^ +note: required for `T` to implement `Bar` + --> $DIR/param-candidate-shadows-project.rs:13:9 + | +LL | impl<T> Bar for T where T: Foo<Assoc = i32> {} + | ^^^ ^ ----------- unsatisfied trait bound introduced here note: required by a bound in `require_bar` --> $DIR/param-candidate-shadows-project.rs:15:19 | LL | fn require_bar<T: Bar>() {} | ^^^ required by this bound in `require_bar` -help: consider further restricting this bound - | -LL | fn foo<T: Foo + Bar>() { - | +++++ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/more-object-bound.rs b/tests/ui/traits/next-solver/more-object-bound.rs index 511111af83f..3d3fdc926f6 100644 --- a/tests/ui/traits/next-solver/more-object-bound.rs +++ b/tests/ui/traits/next-solver/more-object-bound.rs @@ -10,7 +10,7 @@ trait Trait: SuperTrait<A = <Self as SuperTrait>::B> {} fn transmute<A, B>(x: A) -> B { foo::<A, B, dyn Trait<A = A, B = B>>(x) - //~^ ERROR the trait bound `dyn Trait<A = A, B = B>: Trait` is not satisfied + //~^ ERROR type mismatch resolving `<dyn Trait<A = A, B = B> as SuperTrait>::A == B` } fn foo<A, B, T: ?Sized>(x: T::A) -> B diff --git a/tests/ui/traits/next-solver/more-object-bound.stderr b/tests/ui/traits/next-solver/more-object-bound.stderr index 1b776d7198e..8cc2a51ee2b 100644 --- a/tests/ui/traits/next-solver/more-object-bound.stderr +++ b/tests/ui/traits/next-solver/more-object-bound.stderr @@ -1,9 +1,10 @@ -error[E0277]: the trait bound `dyn Trait<A = A, B = B>: Trait` is not satisfied +error[E0271]: type mismatch resolving `<dyn Trait<A = A, B = B> as SuperTrait>::A == B` --> $DIR/more-object-bound.rs:12:5 | LL | foo::<A, B, dyn Trait<A = A, B = B>>(x) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `dyn Trait<A = A, B = B>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ | + = note: required because it appears within the type `dyn Trait<A = A, B = B>` note: required by a bound in `foo` --> $DIR/more-object-bound.rs:18:8 | @@ -12,11 +13,7 @@ LL | fn foo<A, B, T: ?Sized>(x: T::A) -> B LL | where LL | T: Trait<B = B>, | ^^^^^^^^^^^^ required by this bound in `foo` -help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement - | -LL | fn transmute<A, B>(x: A) -> B where dyn Trait<A = A, B = B>: Trait { - | ++++++++++++++++++++++++++++++++++++ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs index 40d68dbaffd..12ea1bf142a 100644 --- a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs +++ b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs @@ -24,7 +24,7 @@ fn needs_bar<T: Bar>() {} fn foo<T: Foo<Assoc = i32> + Foo<Assoc = u32>>() { needs_bar::<T>(); - //~^ ERROR type annotations needed: cannot satisfy `T: Bar` + //~^ ERROR type annotations needed: cannot satisfy `<T as Foo>::Assoc == i32` } fn main() {} diff --git a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr index dfff9f11b87..21f3fbfeb87 100644 --- a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr +++ b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr @@ -1,11 +1,14 @@ -error[E0283]: type annotations needed: cannot satisfy `T: Bar` +error[E0284]: type annotations needed: cannot satisfy `<T as Foo>::Assoc == i32` --> $DIR/two-projection-param-candidates-are-ambiguous.rs:26:17 | LL | needs_bar::<T>(); - | ^ + | ^ cannot satisfy `<T as Foo>::Assoc == i32` | - = note: cannot satisfy `T: Bar` - = help: the trait `Bar` is implemented for `T` +note: required for `T` to implement `Bar` + --> $DIR/two-projection-param-candidates-are-ambiguous.rs:21:9 + | +LL | impl<T> Bar for T where T: Foo<Assoc = i32> {} + | ^^^ ^ ----------- unsatisfied trait bound introduced here note: required by a bound in `needs_bar` --> $DIR/two-projection-param-candidates-are-ambiguous.rs:23:17 | @@ -14,4 +17,4 @@ LL | fn needs_bar<T: Bar>() {} error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0283`. +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/traits/next-solver/object-unsafety.rs b/tests/ui/traits/next-solver/object-unsafety.rs index 4222607b5bf..3aa1af4956e 100644 --- a/tests/ui/traits/next-solver/object-unsafety.rs +++ b/tests/ui/traits/next-solver/object-unsafety.rs @@ -11,9 +11,9 @@ fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From { pub fn copy_any<T>(t: &T) -> T { copy::<dyn Setup<From=T>>(t) //~^ ERROR the type `&<dyn Setup<From = T> as Setup>::From` is not well-formed - //~| ERROR the trait bound `dyn Setup<From = T>: Setup` is not satisfied //~| ERROR mismatched types //~| ERROR the type `<dyn Setup<From = T> as Setup>::From` is not well-formed + //~| ERROR the trait bound `T: Copy` is not satisfied // FIXME(-Znext-solver): These error messages are horrible and some of them // are even simple fallout from previous error. diff --git a/tests/ui/traits/next-solver/object-unsafety.stderr b/tests/ui/traits/next-solver/object-unsafety.stderr index a9cbb721511..7c9a6077fe7 100644 --- a/tests/ui/traits/next-solver/object-unsafety.stderr +++ b/tests/ui/traits/next-solver/object-unsafety.stderr @@ -1,18 +1,19 @@ -error[E0277]: the trait bound `dyn Setup<From = T>: Setup` is not satisfied +error[E0277]: the trait bound `T: Copy` is not satisfied in `dyn Setup<From = T>` --> $DIR/object-unsafety.rs:12:12 | LL | copy::<dyn Setup<From=T>>(t) - | ^^^^^^^^^^^^^^^^^ the trait `Setup` is not implemented for `dyn Setup<From = T>` + | ^^^^^^^^^^^^^^^^^ within `dyn Setup<From = T>`, the trait `Copy` is not implemented for `T`, which is required by `dyn Setup<From = T>: Setup` | + = note: required because it appears within the type `dyn Setup<From = T>` note: required by a bound in `copy` --> $DIR/object-unsafety.rs:7:12 | LL | fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From { | ^^^^^ required by this bound in `copy` -help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement +help: consider restricting type parameter `T` | -LL | pub fn copy_any<T>(t: &T) -> T where dyn Setup<From = T>: Setup { - | ++++++++++++++++++++++++++++++++ +LL | pub fn copy_any<T: std::marker::Copy>(t: &T) -> T { + | +++++++++++++++++++ error: the type `&<dyn Setup<From = T> as Setup>::From` is not well-formed --> $DIR/object-unsafety.rs:12:31 diff --git a/tests/ui/traits/next-solver/overflow/exponential-trait-goals.rs b/tests/ui/traits/next-solver/overflow/exponential-trait-goals.rs index 186d0e8be56..052d803765d 100644 --- a/tests/ui/traits/next-solver/overflow/exponential-trait-goals.rs +++ b/tests/ui/traits/next-solver/overflow/exponential-trait-goals.rs @@ -15,5 +15,5 @@ fn impls<T: Trait>() {} fn main() { impls::<W<_>>(); - //~^ ERROR overflow evaluating the requirement `W<_>: Trait` + //~^ ERROR overflow evaluating the requirement `_: Sized` } diff --git a/tests/ui/traits/next-solver/overflow/exponential-trait-goals.stderr b/tests/ui/traits/next-solver/overflow/exponential-trait-goals.stderr index b032ae3e740..6583cae8bb9 100644 --- a/tests/ui/traits/next-solver/overflow/exponential-trait-goals.stderr +++ b/tests/ui/traits/next-solver/overflow/exponential-trait-goals.stderr @@ -1,9 +1,16 @@ -error[E0275]: overflow evaluating the requirement `W<_>: Trait` +error[E0275]: overflow evaluating the requirement `_: Sized` --> $DIR/exponential-trait-goals.rs:17:13 | LL | impls::<W<_>>(); | ^^^^ | +note: required for `W<(W<_>, W<_>)>` to implement `Trait` + --> $DIR/exponential-trait-goals.rs:7:12 + | +LL | impl<T, U> Trait for W<(W<T>, W<U>)> + | - ^^^^^ ^^^^^^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here note: required by a bound in `impls` --> $DIR/exponential-trait-goals.rs:14:13 | diff --git a/tests/ui/traits/next-solver/overflow/global-cache.stderr b/tests/ui/traits/next-solver/overflow/global-cache.stderr index 67616619384..9e467721e83 100644 --- a/tests/ui/traits/next-solver/overflow/global-cache.stderr +++ b/tests/ui/traits/next-solver/overflow/global-cache.stderr @@ -5,6 +5,15 @@ LL | impls_trait::<Four<Four<Four<Four<()>>>>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "18"]` attribute to your crate (`global_cache`) +note: required for `Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<()>>>>>>>>>>>` to implement `Trait` + --> $DIR/global-cache.rs:12:16 + | +LL | impl<T: Trait> Trait for Inc<T> {} + | ----- ^^^^^ ^^^^^^ + | | + | unsatisfied trait bound introduced here + = note: 5 redundant requirements hidden + = note: required for `Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<()>>>>>>>>>>>>>>>>` to implement `Trait` note: required by a bound in `impls_trait` --> $DIR/global-cache.rs:15:19 | diff --git a/tests/ui/type-alias-impl-trait/coherence.stderr b/tests/ui/type-alias-impl-trait/coherence.stderr index 4462b70f782..266a532a1db 100644 --- a/tests/ui/type-alias-impl-trait/coherence.stderr +++ b/tests/ui/type-alias-impl-trait/coherence.stderr @@ -4,7 +4,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar LL | impl foreign_crate::ForeignTrait for AliasOfForeignType<()> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------- | | | - | | `AliasOfForeignType<()>` is not defined in the current crate + | | type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate | impl doesn't use only types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/typeck/issue-100285.stderr b/tests/ui/typeck/issue-100285.stderr index 9c8685a7712..c0deb63af59 100644 --- a/tests/ui/typeck/issue-100285.stderr +++ b/tests/ui/typeck/issue-100285.stderr @@ -49,7 +49,7 @@ LL ~ return Some(4); LL | } else { LL ~ return Some(5); LL | } -LL | +LL | LL ~ } LL ~ None | diff --git a/tests/ui/typeck/issue-31173.stderr b/tests/ui/typeck/issue-31173.stderr index 0983147a5f0..9598bc61352 100644 --- a/tests/ui/typeck/issue-31173.stderr +++ b/tests/ui/typeck/issue-31173.stderr @@ -34,7 +34,7 @@ LL | | .cloned() LL | | .collect(); | | -^^^^^^^ method cannot be called due to unsatisfied trait bounds | |_________| - | + | | = note: the following trait bounds were not satisfied: `<TakeWhile<&mut std::vec::IntoIter<u8>, {closure@$DIR/issue-31173.rs:7:21: 7:25}> as Iterator>::Item = &_` diff --git a/tests/ui/ufcs/ufcs-explicit-self-bad.stderr b/tests/ui/ufcs/ufcs-explicit-self-bad.stderr index 7c250775475..c48d094daea 100644 --- a/tests/ui/ufcs/ufcs-explicit-self-bad.stderr +++ b/tests/ui/ufcs/ufcs-explicit-self-bad.stderr @@ -15,7 +15,7 @@ LL | fn dummy2(&self); = note: expected signature `fn(&&'a Bar<_>)` found signature `fn(&Bar<_>)` -error[E0307]: invalid `self` parameter type: isize +error[E0307]: invalid `self` parameter type: `isize` --> $DIR/ufcs-explicit-self-bad.rs:8:18 | LL | fn foo(self: isize, x: isize) -> isize { @@ -24,7 +24,7 @@ LL | fn foo(self: isize, x: isize) -> isize { = note: type of `self` must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) -error[E0307]: invalid `self` parameter type: Bar<isize> +error[E0307]: invalid `self` parameter type: `Bar<isize>` --> $DIR/ufcs-explicit-self-bad.rs:19:18 | LL | fn foo(self: Bar<isize>, x: isize) -> isize { @@ -33,7 +33,7 @@ LL | fn foo(self: Bar<isize>, x: isize) -> isize { = note: type of `self` must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) -error[E0307]: invalid `self` parameter type: &Bar<usize> +error[E0307]: invalid `self` parameter type: `&Bar<usize>` --> $DIR/ufcs-explicit-self-bad.rs:23:18 | LL | fn bar(self: &Bar<usize>, x: isize) -> isize { diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr index b7e9e1baa7b..c0fce5c2aaa 100644 --- a/tests/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr @@ -15,7 +15,7 @@ help: consider introducing a named lifetime parameter LL ~ fn main<'a>() { LL | eq::< dyn for<'a> Foo<(&'a isize,), Output=&'a isize>, ... -LL | +LL | LL ~ let _: dyn Foo(&'a isize, &'a usize) -> &'a usize; | diff --git a/tests/ui/unpretty/staged-api-invalid-path-108697.rs b/tests/ui/unpretty/staged-api-invalid-path-108697.rs new file mode 100644 index 00000000000..1b6ef249191 --- /dev/null +++ b/tests/ui/unpretty/staged-api-invalid-path-108697.rs @@ -0,0 +1,9 @@ +// issue: rust-lang/rust#108697 +// ICE: tcx.resolutions(()) is not supported for local crate -Zunpretty=mir +// on invalid module path with staged_api +//@ compile-flags: -Zunpretty=mir +//@ normalize-stderr-test: "The system cannot find the file specified." -> "No such file or directory" +#![feature(staged_api)] +#[path = "lol"] +mod foo; +//~^ ERROR couldn't read diff --git a/tests/ui/unpretty/staged-api-invalid-path-108697.stderr b/tests/ui/unpretty/staged-api-invalid-path-108697.stderr new file mode 100644 index 00000000000..9c6d1a042d7 --- /dev/null +++ b/tests/ui/unpretty/staged-api-invalid-path-108697.stderr @@ -0,0 +1,8 @@ +error: couldn't read $DIR/lol: No such file or directory (os error 2) + --> $DIR/staged-api-invalid-path-108697.rs:8:1 + | +LL | mod foo; + | ^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/variance/variance-regions-unused-indirect.stderr b/tests/ui/variance/variance-regions-unused-indirect.stderr index ec4d480baab..8cdbb3c0f5e 100644 --- a/tests/ui/variance/variance-regions-unused-indirect.stderr +++ b/tests/ui/variance/variance-regions-unused-indirect.stderr @@ -16,7 +16,7 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle | LL ~ Foo1(Box<Bar<'a>>) LL | } -LL | +LL | LL | enum Bar<'a> { LL ~ Bar1(Box<Foo<'a>>) | |
