diff options
530 files changed, 7591 insertions, 5686 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7b9f87c079e..15c6d4011e1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -90,9 +90,6 @@ jobs: - name: install WIX run: src/ci/scripts/install-wix.sh if: success() && !env.SKIP_JOB - - name: install InnoSetup - run: src/ci/scripts/install-innosetup.sh - if: success() && !env.SKIP_JOB - name: ensure the build happens on a partition with enough space run: src/ci/scripts/symlink-build-dir.sh if: success() && !env.SKIP_JOB @@ -193,9 +190,6 @@ jobs: - name: install WIX run: src/ci/scripts/install-wix.sh if: success() && !env.SKIP_JOB - - name: install InnoSetup - run: src/ci/scripts/install-innosetup.sh - if: success() && !env.SKIP_JOB - name: ensure the build happens on a partition with enough space run: src/ci/scripts/symlink-build-dir.sh if: success() && !env.SKIP_JOB @@ -369,6 +363,35 @@ jobs: env: DEPLOY_TOOLSTATES_JSON: toolstates-linux.json os: ubuntu-latest-xl + - name: dist-x86_64-apple + env: + SCRIPT: "./x.py dist" + RUST_CONFIGURE_ARGS: "--target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc" + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + DIST_REQUIRE_ALL_TOOLS: 1 + os: macos-latest + - name: dist-x86_64-apple-alt + env: + SCRIPT: "./x.py dist" + RUST_CONFIGURE_ARGS: "--enable-extended --enable-profiler --set rust.jemalloc" + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + os: macos-latest + - name: x86_64-apple + env: + SCRIPT: "./x.py test" + RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc" + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + os: macos-latest - name: x86_64-msvc-1 env: RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler" @@ -508,138 +531,6 @@ jobs: - name: install WIX run: src/ci/scripts/install-wix.sh if: success() && !env.SKIP_JOB - - name: install InnoSetup - run: src/ci/scripts/install-innosetup.sh - if: success() && !env.SKIP_JOB - - name: ensure the build happens on a partition with enough space - run: src/ci/scripts/symlink-build-dir.sh - if: success() && !env.SKIP_JOB - - name: disable git crlf conversion - run: src/ci/scripts/disable-git-crlf-conversion.sh - if: success() && !env.SKIP_JOB - - name: install MSYS2 - run: src/ci/scripts/install-msys2.sh - if: success() && !env.SKIP_JOB - - name: install MinGW - run: src/ci/scripts/install-mingw.sh - if: success() && !env.SKIP_JOB - - name: install ninja - run: src/ci/scripts/install-ninja.sh - if: success() && !env.SKIP_JOB - - name: enable ipv6 on Docker - run: src/ci/scripts/enable-docker-ipv6.sh - if: success() && !env.SKIP_JOB - - name: disable git crlf conversion - run: src/ci/scripts/disable-git-crlf-conversion.sh - if: success() && !env.SKIP_JOB - - name: checkout submodules - run: src/ci/scripts/checkout-submodules.sh - if: success() && !env.SKIP_JOB - - name: ensure line endings are correct - run: src/ci/scripts/verify-line-endings.sh - if: success() && !env.SKIP_JOB - - name: run the build - run: src/ci/scripts/run-build-from-ci.sh - env: - AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}" - AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}" - TOOLSTATE_REPO_ACCESS_TOKEN: "${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}" - if: success() && !env.SKIP_JOB - - name: upload artifacts to S3 - run: src/ci/scripts/upload-artifacts.sh - env: - AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}" - AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}" - if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')" - auto-fallible: - name: auto-fallible - env: - CI_JOB_NAME: "${{ matrix.name }}" - SCCACHE_BUCKET: rust-lang-gha-caches - DEPLOY_BUCKET: rust-lang-gha - TOOLSTATE_REPO: "https://github.com/pietroalbini/rust-toolstate" - TOOLSTATE_ISSUES_API_URL: "https://api.github.com/repos/pietroalbini/rust-toolstate/issues" - TOOLSTATE_PUBLISH: 1 - CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZOMUQATD5 - ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZH5AYXDVF - CACHE_DOMAIN: ci-caches-gha.rust-lang.org - if: "github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'" - strategy: - matrix: - include: - - name: dist-x86_64-apple - env: - SCRIPT: "./x.py dist" - RUST_CONFIGURE_ARGS: "--target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc" - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - DIST_REQUIRE_ALL_TOOLS: 1 - os: macos-latest - - name: dist-x86_64-apple-alt - env: - SCRIPT: "./x.py dist" - RUST_CONFIGURE_ARGS: "--enable-extended --enable-profiler --set rust.jemalloc" - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - os: macos-latest - - name: x86_64-apple - env: - SCRIPT: "./x.py test" - RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc" - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.8 - MACOSX_STD_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - os: macos-latest - timeout-minutes: 600 - runs-on: "${{ matrix.os }}" - steps: - - name: disable git crlf conversion - run: git config --global core.autocrlf false - shell: bash - - name: checkout the source code - uses: actions/checkout@v1 - with: - fetch-depth: 2 - - name: configure GitHub Actions to kill the build when outdated - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master - with: - github_token: "${{ secrets.github_token }}" - if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'" - - name: add extra environment variables - run: src/ci/scripts/setup-environment.sh - env: - EXTRA_VARIABLES: "${{ toJson(matrix.env) }}" - if: success() && !env.SKIP_JOB - - name: decide whether to skip this job - run: src/ci/scripts/should-skip-this.sh - if: success() && !env.SKIP_JOB - - name: collect CPU statistics - run: src/ci/scripts/collect-cpu-stats.sh - if: success() && !env.SKIP_JOB - - name: show the current environment - run: src/ci/scripts/dump-environment.sh - if: success() && !env.SKIP_JOB - - name: install awscli - run: src/ci/scripts/install-awscli.sh - if: success() && !env.SKIP_JOB - - name: install sccache - run: src/ci/scripts/install-sccache.sh - if: success() && !env.SKIP_JOB - - name: install clang - run: src/ci/scripts/install-clang.sh - if: success() && !env.SKIP_JOB - - name: install WIX - run: src/ci/scripts/install-wix.sh - if: success() && !env.SKIP_JOB - - name: install InnoSetup - run: src/ci/scripts/install-innosetup.sh - if: success() && !env.SKIP_JOB - name: ensure the build happens on a partition with enough space run: src/ci/scripts/symlink-build-dir.sh if: success() && !env.SKIP_JOB diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9c4afcefa1f..373604adb05 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,529 +1,8 @@ # Contributing to Rust -[contributing-to-rust]: #contributing-to-rust -Thank you for your interest in contributing to Rust! There are many ways to -contribute, and we appreciate all of them. This document is a bit long, so here's -links to the major sections: +Thank you for your interest in contributing to Rust! -* [Feature Requests](#feature-requests) -* [Bug Reports](#bug-reports) -* [The Build System](#the-build-system) -* [Pull Requests](#pull-requests) -* [Writing Documentation](#writing-documentation) -* [Issue Triage](#issue-triage) -* [Out-of-tree Contributions](#out-of-tree-contributions) -* [Helpful Links and Information](#helpful-links-and-information) +To get started, read the [Getting Started] guide in the [rustc-dev-guide]. -If you have questions, please make a post on [internals.rust-lang.org][internals] or -hop on the [Rust Discord server][rust-discord] or [Rust Zulip server][rust-zulip]. - -As a reminder, all contributors are expected to follow our [Code of Conduct][coc]. - -The [rustc-dev-guide] is your friend! It describes how the compiler works and how -to contribute to it in more detail than this document. - -If this is your first time contributing, the [walkthrough] chapter of the guide -can give you a good example of how a typical contribution would go. - -[internals]: https://internals.rust-lang.org -[rust-discord]: http://discord.gg/rust-lang -[rust-zulip]: https://rust-lang.zulipchat.com -[coc]: https://www.rust-lang.org/conduct.html +[Getting Started]: https://rustc-dev-guide.rust-lang.org/getting-started.md [rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/ -[walkthrough]: https://rustc-dev-guide.rust-lang.org/walkthrough.html - -## Feature Requests -[feature-requests]: #feature-requests - -To request a change to the way the Rust language works, please head over -to the [RFCs repository](https://github.com/rust-lang/rfcs) and view the -[README](https://github.com/rust-lang/rfcs/blob/master/README.md) -for instructions. - -## Bug Reports -[bug-reports]: #bug-reports - -While bugs are unfortunate, they're a reality in software. We can't fix what we -don't know about, so please report liberally. If you're not sure if something -is a bug or not, feel free to file a bug anyway. - -**If you believe reporting your bug publicly represents a security risk to Rust users, -please follow our [instructions for reporting security vulnerabilities](https://www.rust-lang.org/policies/security)**. - -If you're using the nightly channel, please check if the bug exists in the -latest toolchain before filing your bug. It might be fixed already. - -If you have the chance, before reporting a bug, please [search existing -issues](https://github.com/rust-lang/rust/search?q=&type=Issues&utf8=%E2%9C%93), -as it's possible that someone else has already reported your error. This doesn't -always work, and sometimes it's hard to know what to search for, so consider this -extra credit. We won't mind if you accidentally file a duplicate report. - -Similarly, to help others who encountered the bug find your issue, -consider filing an issue with a descriptive title, which contains information that might be unique to it. -This can be the language or compiler feature used, the conditions that trigger the bug, -or part of the error message if there is any. -An example could be: **"impossible case reached" on lifetime inference for impl Trait in return position**. - -Opening an issue is as easy as following [this -link](https://github.com/rust-lang/rust/issues/new) and filling out the fields. -Here's a template that you can use to file a bug, though it's not necessary to -use it exactly: - - <short summary of the bug> - - I tried this code: - - <code sample that causes the bug> - - I expected to see this happen: <explanation> - - Instead, this happened: <explanation> - - ## Meta - - `rustc --version --verbose`: - - Backtrace: - -All three components are important: what you did, what you expected, what -happened instead. Please include the output of `rustc --version --verbose`, -which includes important information about what platform you're on, what -version of Rust you're using, etc. - -Sometimes, a backtrace is helpful, and so including that is nice. To get -a backtrace, set the `RUST_BACKTRACE` environment variable to a value -other than `0`. The easiest way -to do this is to invoke `rustc` like this: - -```bash -$ RUST_BACKTRACE=1 rustc ... -``` - -## The Build System - -For info on how to configure and build the compiler, please see [this -chapter][rustcguidebuild] of the rustc-dev-guide. This chapter contains info for -contributions to the compiler and the standard library. It also lists some -really useful commands to the build system (`./x.py`), which could save you a -lot of time. - -[rustcguidebuild]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html - -## Pull Requests -[pull-requests]: #pull-requests - -Pull requests are the primary mechanism we use to change Rust. GitHub itself -has some [great documentation][about-pull-requests] on using the Pull Request feature. -We use the "fork and pull" model [described here][development-models], where -contributors push changes to their personal fork and create pull requests to -bring those changes into the source repository. - -[about-pull-requests]: https://help.github.com/articles/about-pull-requests/ -[development-models]: https://help.github.com/articles/about-collaborative-development-models/ - -Please make pull requests against the `master` branch. - -Rust follows a no merge policy, meaning, when you encounter merge -conflicts you are expected to always rebase instead of merge. -E.g. always use rebase when bringing the latest changes from -the master branch to your feature branch. -Also, please make sure that fixup commits are squashed into other related -commits with meaningful commit messages. - -GitHub allows [closing issues using keywords][closing-keywords]. This feature -should be used to keep the issue tracker tidy. However, it is generally preferred -to put the "closes #123" text in the PR description rather than the issue commit; -particularly during rebasing, citing the issue number in the commit can "spam" -the issue in question. - -[closing-keywords]: https://help.github.com/en/articles/closing-issues-using-keywords - -Please make sure your pull request is in compliance with Rust's style -guidelines by running - - $ python x.py test tidy - -Make this check before every pull request (and every new commit in a pull -request); you can add [git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) -before every push to make sure you never forget to make this check. - -All pull requests are reviewed by another person. We have a bot, -[@rust-highfive][rust-highfive], that will automatically assign a random person to review your -request. - -If you want to request that a specific person reviews your pull request, -you can add an `r?` to the pull request description. For example, [Steve][steveklabnik] usually reviews -documentation changes. So if you were to make a documentation change, add - - r? @steveklabnik - -to the end of the pull request description, and [@rust-highfive][rust-highfive] will assign -[@steveklabnik][steveklabnik] instead of a random person. This is entirely optional. - -After someone has reviewed your pull request, they will leave an annotation -on the pull request with an `r+`. It will look something like this: - - @bors r+ - -This tells [@bors][bors], our lovable integration bot, that your pull request has -been approved. The PR then enters the [merge queue][merge-queue], where [@bors][bors] -will run all the tests on every platform we support. If it all works out, -[@bors][bors] will merge your code into `master` and close the pull request. - -Depending on the scale of the change, you may see a slightly different form of `r+`: - - @bors r+ rollup - -The additional `rollup` tells [@bors][bors] that this change is eligible for to be -"rolled up". Changes that are rolled up are tested and merged at the same time, to -speed the process up. Typically only small changes that are expected not to conflict -with one another are rolled up. - -[rust-highfive]: https://github.com/rust-highfive -[steveklabnik]: https://github.com/steveklabnik -[bors]: https://github.com/bors -[merge-queue]: https://buildbot2.rust-lang.org/homu/queue/rust - -Speaking of tests, Rust has a comprehensive test suite. More information about -it can be found [here][rctd]. - -### External Dependencies (subtree) - -As a developer to this repository, you don't have to treat the following external projects -differently from other crates that are directly in this repo: - -* Clippy - -They are just regular files and directories. This is in contrast to `submodule` dependencies -(see below for those). Only tool authors will actually use any operations here. - -#### Synchronizing a subtree - -There are two synchronization directions: `subtree push` and `subtree pull`. - -``` -git subtree push -P src/tools/clippy git@github.com:your-github-name/rust-clippy sync-from-rust -``` - -takes all the changes that -happened to the copy in this repo and creates commits on the remote repo that match the local -changes. Every local commit that touched the subtree causes a commit on the remote repo, but is -modified to move the files from the specified directory to the tool repo root. - -Make sure to not pick the `master` branch on the tool repo, so you can open a normal PR to the tool -to merge that subrepo push. - -``` -git subtree pull -P src/tools/clippy https://github.com/rust-lang/rust-clippy master -``` - -takes all changes since the last `subtree pull` from the tool repo -repo and adds these commits to the rustc repo + a merge commit that moves the tool changes into -the specified directory in the rust repository. - -It is recommended that you always do a push first and get that merged to the tool master branch. -Then, when you do a pull, the merge works without conflicts. -While it's definitely possible to resolve conflicts during a pull, you may have to redo the conflict -resolution if your PR doesn't get merged fast enough and there are new conflicts. Do not try to -rebase the result of a `git subtree pull`, rebasing merge commits is a bad idea in general. - -You always need to specify the `-P` prefix to the subtree directory and the corresponding remote -repository. If you specify the wrong directory or repository -you'll get very fun merges that try to push the wrong directory to the wrong remote repository. -Luckily you can just abort this without any consequences by throwing away either the pulled commits -in rustc or the pushed branch on the remote and try again. It is usually fairly obvious -that this is happening because you suddenly get thousands of commits that want to be synchronized. - -#### Creating a new subtree dependency - -If you want to create a new subtree dependency from an existing repository, call (from this -repository's root directory!) - -``` -git subtree add -P src/tools/clippy https://github.com/rust-lang/rust-clippy.git master -``` - -This will create a new commit, which you may not rebase under any circumstances! Delete the commit -and redo the operation if you need to rebase. - -Now you're done, the `src/tools/clippy` directory behaves as if Clippy were part of the rustc -monorepo, so no one but you (or others that synchronize subtrees) actually needs to use `git subtree`. - - -### External Dependencies (submodules) - -Currently building Rust will also build the following external projects: - -* [miri](https://github.com/rust-lang/miri) -* [rustfmt](https://github.com/rust-lang/rustfmt) -* [rls](https://github.com/rust-lang/rls/) - -We allow breakage of these tools in the nightly channel. Maintainers of these -projects will be notified of the breakages and should fix them as soon as -possible. - -After the external is fixed, one could add the changes with - -```sh -git add path/to/submodule -``` - -outside the submodule. - -In order to prepare your tool-fixing PR, you can run the build locally by doing -`./x.py build src/tools/TOOL`. If you will be editing the sources -there, you may wish to set `submodules = false` in the `config.toml` -to prevent `x.py` from resetting to the original branch. - -Breakage is not allowed in the beta and stable channels, and must be addressed -before the PR is merged. - -#### Breaking Tools Built With The Compiler - -Rust's build system builds a number of tools that make use of the -internals of the compiler. This includes -[RLS](https://github.com/rust-lang/rls) and -[rustfmt](https://github.com/rust-lang/rustfmt). If these tools -break because of your changes, you may run into a sort of "chicken and egg" -problem. These tools rely on the latest compiler to be built so you can't update -them to reflect your changes to the compiler until those changes are merged into -the compiler. At the same time, you can't get your changes merged into the compiler -because the rust-lang/rust build won't pass until those tools build and pass their -tests. - -That means that, in the default state, you can't update the compiler without first -fixing rustfmt, rls and the other tools that the compiler builds. - -Luckily, a feature was [added to Rust's build](https://github.com/rust-lang/rust/issues/45861) -to make all of this easy to handle. The idea is that we allow these tools to be "broken", -so that the rust-lang/rust build passes without trying to build them, then land the change -in the compiler, wait for a nightly, and go update the tools that you broke. Once you're done -and the tools are working again, you go back in the compiler and update the tools -so they can be distributed again. - -This should avoid a bunch of synchronization dances and is also much easier on contributors as -there's no need to block on rls/rustfmt/other tools changes going upstream. - -Here are those same steps in detail: - -1. (optional) First, if it doesn't exist already, create a `config.toml` by copying - `config.toml.example` in the root directory of the Rust repository. - Set `submodules = false` in the `[build]` section. This will prevent `x.py` - from resetting to the original branch after you make your changes. If you - need to [update any submodules to their latest versions](#updating-submodules), - see the section of this file about that for more information. -2. (optional) Run `./x.py test src/tools/rustfmt` (substituting the submodule - that broke for `rustfmt`). Fix any errors in the submodule (and possibly others). -3. (optional) Make commits for your changes and send them to upstream repositories as a PR. -4. (optional) Maintainers of these submodules will **not** merge the PR. The PR can't be - merged because CI will be broken. You'll want to write a message on the PR referencing - your change, and how the PR should be merged once your change makes it into a nightly. -5. Wait for your PR to merge. -6. Wait for a nightly -7. (optional) Help land your PR on the upstream repository now that your changes are in nightly. -8. (optional) Send a PR to rust-lang/rust updating the submodule. - -#### Updating submodules - -These instructions are specific to updating `rustfmt`, however they may apply -to the other submodules as well. Please help by improving these instructions -if you find any discrepancies or special cases that need to be addressed. - -To update the `rustfmt` submodule, start by running the appropriate -[`git submodule` command](https://git-scm.com/book/en/v2/Git-Tools-Submodules). -For example, to update to the latest commit on the remote master branch, -you may want to run: -``` -git submodule update --remote src/tools/rustfmt -``` -If you run `./x.py build` now, and you are lucky, it may just work. If you see -an error message about patches that did not resolve to any crates, you will need -to complete a few more steps which are outlined with their rationale below. - -*(This error may change in the future to include more information.)* -``` -error: failed to resolve patches for `https://github.com/rust-lang/rustfmt` - -Caused by: - patch for `rustfmt-nightly` in `https://github.com/rust-lang/rustfmt` did not resolve to any crates -failed to run: ~/rust/build/x86_64-unknown-linux-gnu/stage0/bin/cargo build --manifest-path ~/rust/src/bootstrap/Cargo.toml -``` - -If you haven't used the `[patch]` -section of `Cargo.toml` before, there is [some relevant documentation about it -in the cargo docs](http://doc.crates.io/manifest.html#the-patch-section). In -addition to that, you should read the -[Overriding dependencies](http://doc.crates.io/specifying-dependencies.html#overriding-dependencies) -section of the documentation as well. - -Specifically, the following [section in Overriding dependencies](http://doc.crates.io/specifying-dependencies.html#testing-a-bugfix) reveals what the problem is: - -> Next up we need to ensure that our lock file is updated to use this new version of uuid so our project uses the locally checked out copy instead of one from crates.io. The way [patch] works is that it'll load the dependency at ../path/to/uuid and then whenever crates.io is queried for versions of uuid it'll also return the local version. -> -> This means that the version number of the local checkout is significant and will affect whether the patch is used. Our manifest declared uuid = "1.0" which means we'll only resolve to >= 1.0.0, < 2.0.0, and Cargo's greedy resolution algorithm also means that we'll resolve to the maximum version within that range. Typically this doesn't matter as the version of the git repository will already be greater or match the maximum version published on crates.io, but it's important to keep this in mind! - -This says that when we updated the submodule, the version number in our -`src/tools/rustfmt/Cargo.toml` changed. The new version is different from -the version in `Cargo.lock`, so the build can no longer continue. - -To resolve this, we need to update `Cargo.lock`. Luckily, cargo provides a -command to do this easily. - -``` -$ cargo update -p rustfmt-nightly -``` - -This should change the version listed in `Cargo.lock` to the new version you updated -the submodule to. Running `./x.py build` should work now. - -## Writing Documentation - -Documentation improvements are very welcome. The source of `doc.rust-lang.org` -is located in `src/doc` in the tree, and standard API documentation is generated -from the source code itself. Documentation pull requests function in the same way -as other pull requests. - -To find documentation-related issues, sort by the [T-doc label][tdoc]. - -[tdoc]: https://github.com/rust-lang/rust/issues?q=is%3Aopen%20is%3Aissue%20label%3AT-doc - -You can find documentation style guidelines in [RFC 1574][rfc1574]. - -[rfc1574]: https://github.com/rust-lang/rfcs/blob/master/text/1574-more-api-documentation-conventions.md#appendix-a-full-conventions-text - -In many cases, you don't need a full `./x.py doc`, which will build the entire -stage 2 compiler and compile the various books published on -[doc.rust-lang.org]. When updating documentation for the standard library, -first try `./x.py doc --stage 0 src/libstd`. If that fails, or if you need to -see the output from the latest version of `rustdoc`, use `--stage 1` instead of -`--stage 0`. Results should appear in `build/$TARGET/crate-docs`. - -[doc.rust-lang.org]: htts://doc.rust-lang.org - -You can also use `rustdoc` directly to check small fixes. For example, -`rustdoc src/doc/reference.md` will render reference to `doc/reference.html`. -The CSS might be messed up, but you can verify that the HTML is right. - -Additionally, contributions to the [rustc-dev-guide] are always welcome. Contributions -can be made directly at [the -rust-lang/rustc-dev-guide](https://github.com/rust-lang/rustc-dev-guide) repo. The issue -tracker in that repo is also a great way to find things that need doing. There -are issues for beginners and advanced compiler devs alike! - -## Issue Triage - -Sometimes, an issue will stay open, even though the bug has been fixed. And -sometimes, the original bug may go stale because something has changed in the -meantime. - -It can be helpful to go through older bug reports and make sure that they are -still valid. Load up an older issue, double check that it's still true, and -leave a comment letting us know if it is or is not. The [least recently -updated sort][lru] is good for finding issues like this. - -Contributors with sufficient permissions on the Rust repo can help by adding -labels to triage issues: - -* Yellow, **A**-prefixed labels state which **area** of the project an issue - relates to. - -* Magenta, **B**-prefixed labels identify bugs which are **blockers**. - -* Dark blue, **beta-** labels track changes which need to be backported into - the beta branches. - -* Light purple, **C**-prefixed labels represent the **category** of an issue. - -* Green, **E**-prefixed labels explain the level of **experience** necessary - to fix the issue. - -* The dark blue **final-comment-period** label marks bugs that are using the - RFC signoff functionality of [rfcbot] and are currently in the final - comment period. - -* Red, **I**-prefixed labels indicate the **importance** of the issue. The - [I-nominated][inom] label indicates that an issue has been nominated for - prioritizing at the next triage meeting. - -* The purple **metabug** label marks lists of bugs collected by other - categories. - -* Purple gray, **O**-prefixed labels are the **operating system** or platform - that this issue is specific to. - -* Orange, **P**-prefixed labels indicate a bug's **priority**. These labels - are only assigned during triage meetings, and replace the [I-nominated][inom] - label. - -* The gray **proposed-final-comment-period** label marks bugs that are using - the RFC signoff functionality of [rfcbot] and are currently awaiting - signoff of all team members in order to enter the final comment period. - -* Pink, **regression**-prefixed labels track regressions from stable to the - release channels. - -* The light orange **relnotes** label marks issues that should be documented in - the release notes of the next release. - -* Gray, **S**-prefixed labels are used for tracking the **status** of pull - requests. - -* Blue, **T**-prefixed bugs denote which **team** the issue belongs to. - -If you're looking for somewhere to start, check out the [E-easy][eeasy] tag. - -[inom]: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AI-nominated -[eeasy]: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy -[lru]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-asc -[rfcbot]: https://github.com/anp/rfcbot-rs/ - -## Out-of-tree Contributions - -There are a number of other ways to contribute to Rust that don't deal with -this repository. - -Answer questions in the _Get Help!_ channels from the [Rust Discord server][rust-discord], on [users.rust-lang.org][users], -or on [StackOverflow][so]. - -Participate in the [RFC process](https://github.com/rust-lang/rfcs). - -Find a [requested community library][community-library], build it, and publish -it to [Crates.io](http://crates.io). Easier said than done, but very, very -valuable! - -[rust-discord]: https://discord.gg/rust-lang -[users]: https://users.rust-lang.org/ -[so]: http://stackoverflow.com/questions/tagged/rust -[community-library]: https://github.com/rust-lang/rfcs/labels/A-community-library - -## Helpful Links and Information - -For people new to Rust, and just starting to contribute, or even for -more seasoned developers, some useful places to look for information -are: - -* The [rustc dev guide] contains information about how various parts of the compiler work and how to contribute to the compiler -* [Rust Forge][rustforge] contains additional documentation, including write-ups of how to achieve common tasks -* The [Rust Internals forum][rif], a place to ask questions and - discuss Rust's internals -* The [generated documentation for rust's compiler][gdfrustc] -* The [rust reference][rr], even though it doesn't specifically talk about Rust's internals, it's a great resource nonetheless -* Although out of date, [Tom Lee's great blog article][tlgba] is very helpful -* [rustaceans.org][ro] is helpful, but mostly dedicated to IRC -* The [Rust Compiler Testing Docs][rctd] -* For [@bors][bors], [this cheat sheet][cheatsheet] is helpful -(though you'll need to replace `@homu` with `@bors` in any commands) -* **Google!** ([search only in Rust Documentation][gsearchdocs] to find types, traits, etc. quickly) -* Don't be afraid to ask! The Rust community is friendly and helpful. - -[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/about-this-guide.html -[gdfrustc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ -[gsearchdocs]: https://www.google.com/search?q=site:doc.rust-lang.org+your+query+here -[rif]: http://internals.rust-lang.org -[rr]: https://doc.rust-lang.org/book/README.html -[rustforge]: https://forge.rust-lang.org/ -[tlgba]: http://tomlee.co/2014/04/a-more-detailed-tour-of-the-rust-compiler/ -[ro]: http://www.rustaceans.org/ -[rctd]: https://rustc-dev-guide.rust-lang.org/tests/intro.html -[cheatsheet]: https://buildbot2.rust-lang.org/homu/ diff --git a/Cargo.lock b/Cargo.lock index e9fb097df92..84ad4d485dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2347,9 +2347,9 @@ dependencies = [ [[package]] name = "psm" -version = "0.1.8" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "659ecfea2142a458893bb7673134bad50b752fea932349c213d6a23874ce3aa7" +checksum = "092d385624a084892d07374caa7b0994956692cf40650419a1f1a787a8d229cf" dependencies = [ "cc", ] diff --git a/Cargo.toml b/Cargo.toml index f10d539d829..be15e50e2bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,16 +33,16 @@ exclude = [ "obj", ] -# These options are controlled from our rustc wrapper script, so turn them off -# here and have them controlled elsewhere. -[profile.dev] -debug = false -debug-assertions = false -[profile.test] -debug = false +[profile.release.package.compiler_builtins] +# The compiler-builtins crate cannot reference libcore, and it's own CI will +# verify that this is the case. This requires, however, that the crate is built +# without overflow checks and debug assertions. Forcefully disable debug +# assertions and overflow checks here which should ensure that even if these +# assertions are enabled for libstd we won't enable then for compiler_builtins +# which should ensure we still link everything correctly. debug-assertions = false +overflow-checks = false -[profile.release.package.compiler_builtins] # For compiler-builtins we always use a high number of codegen units. # The goal here is to place every single intrinsic into its own object # file to avoid symbol clashes with the system libgcc if possible. Note diff --git a/README.md b/README.md index 42fc0a63c0f..70d3d51ce9b 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,14 @@ -# The Rust Programming Language +<a href = "https://www.rust-lang.org/"> +<img width = "90%" height = "auto" src = "https://img.shields.io/badge/Rust-Programming%20Language-black?style=flat&logo=rust" alt = "The Rust Programming Language"> +</a> This is the main source code repository for [Rust]. It contains the compiler, -standard library, and documentation. +standard library, and documentation. [Rust]: https://www.rust-lang.org +**Note: this README is for _users_ rather than _contributors_.** + ## Quick Start Read ["Installation"] from [The Book]. @@ -14,13 +18,15 @@ Read ["Installation"] from [The Book]. ## Installing from Source -_Note: If you wish to contribute to the compiler, you should read [this -chapter][rustcguidebuild] of the rustc-dev-guide instead of this section._ +**Note: If you wish to _contribute_ to the compiler, you should read the +[Getting Started][gettingstarted] of the rustc-dev-guide instead of this +section.** -The Rust build system has a Python script called `x.py` to bootstrap building -the compiler. More information about it may be found by running `./x.py --help` -or reading the [rustc dev guide][rustcguidebuild]. +The Rust build system uses a Python script called `x.py` to build the compiler, +which manages the bootstrapping process. More information about it can be found +by running `./x.py --help` or reading the [rustc dev guide][rustcguidebuild]. +[gettingstarted]: https://rustc-dev-guide.rust-lang.org/getting-started.md [rustcguidebuild]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html ### Building on a Unix-like system @@ -54,9 +60,8 @@ or reading the [rustc dev guide][rustcguidebuild]. $ cp config.toml.example config.toml ``` - It is recommended that if you plan to use the Rust build system to create - an installation (using `./x.py install`) that you set the `prefix` value - in the `[install]` section to a directory that you have write permissions. + If you plan to use `x.py install` to create an installation, it is recommended + that you set the `prefix` value in the `[install]` section to a directory. Create install directory if you are not installing in default directory @@ -143,8 +148,8 @@ shell with: ``` Currently, building Rust only works with some known versions of Visual Studio. If -you have a more recent version installed the build system doesn't understand -then you may need to force rustbuild to use an older version. This can be done +you have a more recent version installed and the build system doesn't understand, +you may need to force rustbuild to use an older version. This can be done by manually calling the appropriate vcvars file before running the bootstrap. ```batch @@ -224,10 +229,6 @@ Snapshot binaries are currently built and tested on several platforms: You may find that other platforms work, but these are our officially supported build environments that are most likely to work. -There is more advice about hacking on Rust in [CONTRIBUTING.md]. - -[CONTRIBUTING.md]: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md - ## Getting Help The Rust community congregates in a few places: @@ -242,21 +243,8 @@ The Rust community congregates in a few places: ## Contributing -To contribute to Rust, please see [CONTRIBUTING](CONTRIBUTING.md). - -Most real-time collaboration happens in a variety of channels on the -[Rust Discord server][rust-discord], with channels dedicated for getting help, -community, documentation, and all major contribution areas in the Rust ecosystem. -A good place to ask for help would be the #help channel. - -The [rustc dev guide] might be a good place to start if you want to find out how -various parts of the compiler work. - -Also, you may find the [rustdocs for the compiler itself][rustdocs] useful. - -[rust-discord]: https://discord.gg/rust-lang -[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/about-this-guide.html -[rustdocs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ +If you are interested in contributing to the Rust project, please take a look +at the [Getting Started][gettingstarted] guide in the [rustc-dev-guide]. ## License diff --git a/config.toml.example b/config.toml.example index c0be7dded17..2fa613755d6 100644 --- a/config.toml.example +++ b/config.toml.example @@ -378,7 +378,7 @@ # nightly features #channel = "dev" -# The root location of the MUSL installation directory. +# The root location of the musl installation directory. #musl-root = "..." # By default the `rustc` executable is built with `-Wl,-rpath` flags on Unix @@ -521,12 +521,15 @@ # only use static libraries. If unset, the target's default linkage is used. #crt-static = false -# The root location of the MUSL installation directory. The library directory +# The root location of the musl installation directory. The library directory # will also need to contain libunwind.a for an unwinding implementation. Note -# that this option only makes sense for MUSL targets that produce statically +# that this option only makes sense for musl targets that produce statically # linked binaries #musl-root = "..." +# The full path to the musl libdir. +#musl-libdir = musl-root/lib + # The root location of the `wasm32-wasi` sysroot. #wasi-root = "..." diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index a8c00c8c3ca..3072a4a1ae7 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -101,30 +101,6 @@ fn main() { { cmd.arg("-C").arg("panic=abort"); } - - // Set various options from config.toml to configure how we're building - // code. - let debug_assertions = match env::var("RUSTC_DEBUG_ASSERTIONS") { - Ok(s) => { - if s == "true" { - "y" - } else { - "n" - } - } - Err(..) => "n", - }; - - // The compiler builtins are pretty sensitive to symbols referenced in - // libcore and such, so we never compile them with debug assertions. - // - // FIXME(rust-lang/cargo#7253) we should be doing this in `builder.rs` - // with env vars instead of doing it here in this script. - if crate_name == Some("compiler_builtins") { - cmd.arg("-C").arg("debug-assertions=no"); - } else { - cmd.arg("-C").arg(format!("debug-assertions={}", debug_assertions)); - } } else { // FIXME(rust-lang/cargo#5754) we shouldn't be using special env vars // here, but rather Cargo should know what flags to pass rustc itself. diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 0735ba8869a..f9403260f77 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -950,14 +950,6 @@ impl<'a> Builder<'a> { .env("RUSTC", self.out.join("bootstrap/debug/rustc")) .env("RUSTC_REAL", self.rustc(compiler)) .env("RUSTC_STAGE", stage.to_string()) - .env( - "RUSTC_DEBUG_ASSERTIONS", - if mode == Mode::Std { - self.config.rust_debug_assertions_std.to_string() - } else { - self.config.rust_debug_assertions.to_string() - }, - ) .env("RUSTC_SYSROOT", &sysroot) .env("RUSTC_LIBDIR", &libdir) .env("RUSTDOC", self.out.join("bootstrap/debug/rustdoc")) @@ -981,7 +973,7 @@ impl<'a> Builder<'a> { // we're gated on RUSTC_RPATH here. // // Ok, so the astute might be wondering "why isn't `-C rpath` used - // here?" and that is indeed a good question to task. This codegen + // here?" and that is indeed a good question to ask. This codegen // option is the compiler's current interface to generating an rpath. // Unfortunately it doesn't quite suffice for us. The flag currently // takes no value as an argument, so the compiler calculates what it @@ -1041,6 +1033,14 @@ impl<'a> Builder<'a> { } }; cargo.env(profile_var("DEBUG"), debuginfo_level.to_string()); + cargo.env( + profile_var("DEBUG_ASSERTIONS"), + if mode == Mode::Std { + self.config.rust_debug_assertions_std.to_string() + } else { + self.config.rust_debug_assertions.to_string() + }, + ); if !mode.is_tool() { cargo.env("RUSTC_FORCE_UNSTABLE", "1"); diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs index cca8ab80c93..1e75e67af0c 100644 --- a/src/bootstrap/builder/tests.rs +++ b/src/bootstrap/builder/tests.rs @@ -54,6 +54,11 @@ fn dist_baseline() { &[dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },] ); assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]); + // Make sure rustdoc is only built once. + assert_eq!( + first(builder.cache.all::<tool::Rustdoc>()), + &[tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } },] + ); } #[test] @@ -414,3 +419,77 @@ fn test_exclude() { // Ensure other tests are not affected. assert!(builder.cache.contains::<test::RustdocUi>()); } + +#[test] +fn doc_default() { + let mut config = configure(&[], &[]); + config.compiler_docs = true; + config.cmd = Subcommand::Doc { paths: Vec::new(), open: false }; + let build = Build::new(config); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), &[]); + let a = INTERNER.intern_str("A"); + + // error_index_generator uses stage 1 to share rustdoc artifacts with the + // rustdoc tool. + assert_eq!( + first(builder.cache.all::<doc::ErrorIndex>()), + &[doc::ErrorIndex { compiler: Compiler { host: a, stage: 1 }, target: a },] + ); + assert_eq!( + first(builder.cache.all::<tool::ErrorIndex>()), + &[tool::ErrorIndex { compiler: Compiler { host: a, stage: 1 } }] + ); + // This is actually stage 1, but Rustdoc::run swaps out the compiler with + // stage minus 1 if --stage is not 0. Very confusing! + assert_eq!( + first(builder.cache.all::<tool::Rustdoc>()), + &[tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } },] + ); +} + +#[test] +fn test_docs() { + // Behavior of `x.py test` doing various documentation tests. + let mut config = configure(&[], &[]); + config.cmd = Subcommand::Test { + paths: vec![], + test_args: vec![], + rustc_args: vec![], + fail_fast: true, + doc_tests: DocTests::Yes, + bless: false, + compare_mode: None, + rustfix_coverage: false, + pass: None, + }; + let build = Build::new(config); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Test), &[]); + let a = INTERNER.intern_str("A"); + + // error_index_generator uses stage 1 to share rustdoc artifacts with the + // rustdoc tool. + assert_eq!( + first(builder.cache.all::<doc::ErrorIndex>()), + &[doc::ErrorIndex { compiler: Compiler { host: a, stage: 1 }, target: a },] + ); + assert_eq!( + first(builder.cache.all::<tool::ErrorIndex>()), + &[tool::ErrorIndex { compiler: Compiler { host: a, stage: 1 } }] + ); + // Unfortunately rustdoc is built twice. Once from stage1 for compiletest + // (and other things), and once from stage0 for std crates. Ideally it + // would only be built once. If someone wants to fix this, it might be + // worth investigating if it would be possible to test std from stage1. + // Note that the stages here are +1 than what they actually are because + // Rustdoc::run swaps out the compiler with stage minus 1 if --stage is + // not 0. + assert_eq!( + first(builder.cache.all::<tool::Rustdoc>()), + &[ + tool::Rustdoc { compiler: Compiler { host: a, stage: 1 } }, + tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } }, + ] + ); +} diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index b07ff21755e..84545dcedb6 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -177,7 +177,7 @@ fn copy_self_contained_objects( // To do that we have to distribute musl startup objects as a part of Rust toolchain // and link with them manually in the self-contained mode. if target.contains("musl") { - let srcdir = builder.musl_root(target).unwrap().join("lib"); + let srcdir = builder.musl_libdir(target).unwrap(); for &obj in &["crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] { copy_and_stamp( builder, @@ -266,8 +266,8 @@ pub fn std_cargo(builder: &Builder<'_>, target: Interned<String>, stage: u32, ca // Help the libc crate compile by assisting it in finding various // sysroot native libraries. if target.contains("musl") { - if let Some(p) = builder.musl_root(target) { - let root = format!("native={}/lib", p.to_str().unwrap()); + if let Some(p) = builder.musl_libdir(target) { + let root = format!("native={}", p.to_str().unwrap()); cargo.rustflag("-L").rustflag(&root); } } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 771f952abc0..ff545a6ddcf 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -173,6 +173,7 @@ pub struct Target { pub ndk: Option<PathBuf>, pub crt_static: Option<bool>, pub musl_root: Option<PathBuf>, + pub musl_libdir: Option<PathBuf>, pub wasi_root: Option<PathBuf>, pub qemu_rootfs: Option<PathBuf>, pub no_std: bool, @@ -363,6 +364,7 @@ struct TomlTarget { android_ndk: Option<String>, crt_static: Option<bool>, musl_root: Option<String>, + musl_libdir: Option<String>, wasi_root: Option<String>, qemu_rootfs: Option<String>, no_std: Option<bool>, @@ -631,6 +633,7 @@ impl Config { target.linker = cfg.linker.clone().map(PathBuf::from); target.crt_static = cfg.crt_static; target.musl_root = cfg.musl_root.clone().map(PathBuf::from); + target.musl_libdir = cfg.musl_libdir.clone().map(PathBuf::from); target.wasi_root = cfg.wasi_root.clone().map(PathBuf::from); target.qemu_rootfs = cfg.qemu_rootfs.clone().map(PathBuf::from); diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 8a2463d378f..28430b56ee5 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1875,28 +1875,7 @@ impl Step for Extended { prepare("rust-mingw"); } - builder.install(&xform(&etc.join("exe/rust.iss")), &exe, 0o644); - builder.install(&etc.join("exe/modpath.iss"), &exe, 0o644); - builder.install(&etc.join("exe/upgrade.iss"), &exe, 0o644); builder.install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644); - builder.create(&exe.join("LICENSE.txt"), &license); - - // Generate exe installer - builder.info("building `exe` installer with `iscc`"); - let mut cmd = Command::new("iscc"); - cmd.arg("rust.iss").arg("/Q").current_dir(&exe); - if target.contains("windows-gnu") { - cmd.arg("/dMINGW"); - } - add_env(builder, &mut cmd, target); - let time = timeit(builder); - builder.run(&mut cmd); - drop(time); - builder.install( - &exe.join(format!("{}-{}.exe", pkgname(builder, "rust"), target)), - &distdir(builder), - 0o755, - ); // Generate msi installer let wix = PathBuf::from(env::var_os("WIX").unwrap()); diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 8b76158f9e5..d02c19467ee 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -518,8 +518,7 @@ impl Step for Rustc { let out = builder.compiler_doc_out(target); t!(fs::create_dir_all(&out)); - // Get the correct compiler for this stage. - let compiler = builder.compiler_for(stage, builder.config.build, target); + let compiler = builder.compiler(stage, builder.config.build); if !builder.config.compiler_docs { builder.info("\tskipping - compiler/librustdoc docs disabled"); @@ -599,8 +598,7 @@ impl Step for Rustdoc { let out = builder.compiler_doc_out(target); t!(fs::create_dir_all(&out)); - // Get the correct compiler for this stage. - let compiler = builder.compiler_for(stage, builder.config.build, target); + let compiler = builder.compiler(stage, builder.config.build); if !builder.config.compiler_docs { builder.info("\tskipping - compiler/librustdoc docs disabled"); @@ -639,9 +637,10 @@ impl Step for Rustdoc { } } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Ord, PartialOrd, Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct ErrorIndex { - target: Interned<String>, + pub compiler: Compiler, + pub target: Interned<String>, } impl Step for ErrorIndex { @@ -655,26 +654,26 @@ impl Step for ErrorIndex { } fn make_run(run: RunConfig<'_>) { - run.builder.ensure(ErrorIndex { target: run.target }); + let target = run.target; + // error_index_generator depends on librustdoc. Use the compiler that + // is normally used to build rustdoc for other documentation so that + // it shares the same artifacts. + let compiler = + run.builder.compiler_for(run.builder.top_stage, run.builder.config.build, target); + run.builder.ensure(ErrorIndex { compiler, target }); } /// Generates the HTML rendered error-index by running the /// `error_index_generator` tool. fn run(self, builder: &Builder<'_>) { - let target = self.target; - - builder.info(&format!("Documenting error index ({})", target)); - let out = builder.doc_out(target); + builder.info(&format!("Documenting error index ({})", self.target)); + let out = builder.doc_out(self.target); t!(fs::create_dir_all(&out)); - let compiler = builder.compiler(2, builder.config.build); - let mut index = tool::ErrorIndex::command(builder, compiler); + let mut index = tool::ErrorIndex::command(builder, self.compiler); index.arg("html"); index.arg(out.join("error-index.html")); index.arg(crate::channel::CFG_RELEASE_NUM); - // FIXME: shouldn't have to pass this env var - index.env("CFG_BUILD", &builder.config.build); - builder.run(&mut index); } } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 5728b9d24de..b611af54565 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -888,6 +888,15 @@ impl Build { .map(|p| &**p) } + /// Returns the "musl libdir" for this `target`. + fn musl_libdir(&self, target: Interned<String>) -> Option<PathBuf> { + let t = self.config.target_config.get(&target)?; + if let libdir @ Some(_) = &t.musl_libdir { + return libdir.clone(); + } + self.musl_root(target).map(|root| root.join("lib")) + } + /// Returns the sysroot for the wasi target, if defined fn wasi_root(&self, target: Interned<String>) -> Option<&Path> { self.config.target_config.get(&target).and_then(|t| t.wasi_root.as_ref()).map(|p| &**p) diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 106db90b2d0..cceb7941650 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -175,6 +175,17 @@ impl Step for Llvm { cfg.define("LLVM_ENABLE_ZLIB", "OFF"); } + // Are we compiling for iOS/tvOS? + if target.contains("apple-ios") || target.contains("apple-tvos") { + // These two defines prevent CMake from automatically trying to add a MacOSX sysroot, which leads to a compiler error. + cfg.define("CMAKE_OSX_SYSROOT", "/"); + cfg.define("CMAKE_OSX_DEPLOYMENT_TARGET", ""); + // Prevent cmake from adding -bundle to CFLAGS automatically, which leads to a compiler error because "-bitcode_bundle" also gets added. + cfg.define("LLVM_ENABLE_PLUGINS", "OFF"); + // Zlib fails to link properly, leading to a compiler error. + cfg.define("LLVM_ENABLE_ZLIB", "OFF"); + } + if builder.config.llvm_thin_lto { cfg.define("LLVM_ENABLE_LTO", "Thin"); if !target.contains("apple") { @@ -412,6 +423,14 @@ fn configure_cmake( if let Some(ref s) = builder.config.llvm_cflags { cflags.push_str(&format!(" {}", s)); } + // Some compiler features used by LLVM (such as thread locals) will not work on a min version below iOS 10. + if target.contains("apple-ios") { + if target.contains("86-") { + cflags.push_str(" -miphonesimulator-version-min=10.0"); + } else { + cflags.push_str(" -miphoneos-version-min=10.0"); + } + } cfg.define("CMAKE_C_FLAGS", cflags); let mut cxxflags = builder.cflags(target, GitRepo::Llvm).join(" "); if builder.config.llvm_static_stdcpp && !target.contains("msvc") && !target.contains("netbsd") { diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 74b47d07728..3301d41cfee 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -199,10 +199,10 @@ pub fn check(build: &mut Build) { let target = build.config.target_config.entry(target.clone()).or_default(); target.musl_root = Some("/usr".into()); } - match build.musl_root(*target) { - Some(root) => { - if fs::metadata(root.join("lib/libc.a")).is_err() { - panic!("couldn't find libc.a in musl dir: {}", root.join("lib").display()); + match build.musl_libdir(*target) { + Some(libdir) => { + if fs::metadata(libdir.join("libc.a")).is_err() { + panic!("couldn't find libc.a in musl libdir: {}", libdir.display()); } } None => panic!( diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 12ab6b1636c..77bcc00d75b 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1454,8 +1454,11 @@ impl Step for ErrorIndex { } fn make_run(run: RunConfig<'_>) { - run.builder - .ensure(ErrorIndex { compiler: run.builder.compiler(run.builder.top_stage, run.host) }); + // error_index_generator depends on librustdoc. Use the compiler that + // is normally used to build rustdoc for other tests (like compiletest + // tests in src/test/rustdoc) so that it shares the same artifacts. + let compiler = run.builder.compiler_for(run.builder.top_stage, run.host, run.host); + run.builder.ensure(ErrorIndex { compiler }); } /// Runs the error index generator tool to execute the tests located in the error @@ -1467,22 +1470,23 @@ impl Step for ErrorIndex { fn run(self, builder: &Builder<'_>) { let compiler = self.compiler; - builder.ensure(compile::Std { compiler, target: compiler.host }); - let dir = testdir(builder, compiler.host); t!(fs::create_dir_all(&dir)); let output = dir.join("error-index.md"); - let mut tool = tool::ErrorIndex::command( - builder, - builder.compiler(compiler.stage, builder.config.build), - ); - tool.arg("markdown").arg(&output).env("CFG_BUILD", &builder.config.build); + let mut tool = tool::ErrorIndex::command(builder, compiler); + tool.arg("markdown").arg(&output); - builder.info(&format!("Testing error-index stage{}", compiler.stage)); + // Use the rustdoc that was built by self.compiler. This copy of + // rustdoc is shared with other tests (like compiletest tests in + // src/test/rustdoc). This helps avoid building rustdoc multiple + // times. + let rustdoc_compiler = builder.compiler(builder.top_stage, builder.config.build); + builder.info(&format!("Testing error-index stage{}", rustdoc_compiler.stage)); let _time = util::timeit(&builder); builder.run_quiet(&mut tool); - markdown_test(builder, compiler, &output); + builder.ensure(compile::Std { compiler: rustdoc_compiler, target: rustdoc_compiler.host }); + markdown_test(builder, rustdoc_compiler, &output); } } @@ -1797,9 +1801,13 @@ impl Step for CrateRustdoc { fn run(self, builder: &Builder<'_>) { let test_kind = self.test_kind; + let target = self.host; - let compiler = builder.compiler(builder.top_stage, self.host); - let target = compiler.host; + // Use the previous stage compiler to reuse the artifacts that are + // created when running compiletest for src/test/rustdoc. If this used + // `compiler`, then it would cause rustdoc to be built *again*, which + // isn't really necessary. + let compiler = builder.compiler_for(builder.top_stage, target, target); builder.ensure(compile::Rustc { compiler, target }); let mut cargo = tool::prepare_tool_cargo( @@ -1825,6 +1833,32 @@ impl Step for CrateRustdoc { cargo.arg("'-Ctarget-feature=-crt-static'"); } + // This is needed for running doctests on librustdoc. This is a bit of + // an unfortunate interaction with how bootstrap works and how cargo + // sets up the dylib path, and the fact that the doctest (in + // html/markdown.rs) links to rustc-private libs. For stage1, the + // compiler host dylibs (in stage1/lib) are not the same as the target + // dylibs (in stage1/lib/rustlib/...). This is different from a normal + // rust distribution where they are the same. + // + // On the cargo side, normal tests use `target_process` which handles + // setting up the dylib for a *target* (stage1/lib/rustlib/... in this + // case). However, for doctests it uses `rustdoc_process` which only + // sets up the dylib path for the *host* (stage1/lib), which is the + // wrong directory. + // + // It should be considered to just stop running doctests on + // librustdoc. There is only one test, and it doesn't look too + // important. There might be other ways to avoid this, but it seems + // pretty convoluted. + // + // See also https://github.com/rust-lang/rust/issues/13983 where the + // host vs target dylibs for rustdoc are consistently tricky to deal + // with. + let mut dylib_path = dylib_path(); + dylib_path.insert(0, PathBuf::from(&*builder.sysroot_libdir(compiler, target))); + cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); + if !builder.config.verbose_tests { cargo.arg("--quiet"); } diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 063fb8fbb95..45f5073f431 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -366,7 +366,7 @@ bootstrap_tool!( ExpandYamlAnchors, "src/tools/expand-yaml-anchors", "expand-yaml-anchors"; ); -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)] pub struct ErrorIndex { pub compiler: Compiler, } @@ -392,9 +392,9 @@ impl Step for ErrorIndex { fn make_run(run: RunConfig<'_>) { // Compile the error-index in the same stage as rustdoc to avoid // recompiling rustdoc twice if we can. - let stage = if run.builder.top_stage >= 2 { run.builder.top_stage } else { 0 }; - run.builder - .ensure(ErrorIndex { compiler: run.builder.compiler(stage, run.builder.config.build) }); + let host = run.builder.config.build; + let compiler = run.builder.compiler_for(run.builder.top_stage, host, host); + run.builder.ensure(ErrorIndex { compiler }); } fn run(self, builder: &Builder<'_>) -> PathBuf { @@ -449,7 +449,7 @@ impl Step for RemoteTestServer { } } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)] pub struct Rustdoc { /// This should only ever be 0 or 2. /// We sometimes want to reference the "bootstrap" rustdoc, which is why this option is here. diff --git a/src/ci/azure-pipelines/steps/run.yml b/src/ci/azure-pipelines/steps/run.yml index e43116c06b6..34fc4d76fa2 100644 --- a/src/ci/azure-pipelines/steps/run.yml +++ b/src/ci/azure-pipelines/steps/run.yml @@ -66,10 +66,6 @@ steps: displayName: Install wix condition: and(succeeded(), not(variables.SKIP_JOB)) -- bash: src/ci/scripts/install-innosetup.sh - displayName: Install InnoSetup - condition: and(succeeded(), not(variables.SKIP_JOB)) - - bash: src/ci/scripts/symlink-build-dir.sh displayName: Ensure the build happens on a partition with enough space condition: and(succeeded(), not(variables.SKIP_JOB)) diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index d891ad1b668..8071b635804 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -5,7 +5,27 @@ set -e export MSYS_NO_PATHCONV=1 script=`cd $(dirname $0) && pwd`/`basename $0` -image=$1 + +image="" +dev=0 + +while [[ $# -gt 0 ]] +do + case "$1" in + --dev) + dev=1 + ;; + *) + if [ -n "$image" ] + then + echo "expected single argument for the image name" + exit 1 + fi + image="$1" + ;; + esac + shift +done docker_dir="`dirname $script`" ci_dir="`dirname $docker_dir`" @@ -163,6 +183,15 @@ else args="$args --env LOCAL_USER_ID=`id -u`" fi +if [ "$dev" = "1" ] +then + # Interactive + TTY + args="$args -it" + command="/bin/bash" +else + command="/checkout/src/ci/run.sh" +fi + docker \ run \ --workdir /checkout/obj \ @@ -183,7 +212,7 @@ docker \ --init \ --rm \ rust-ci \ - /checkout/src/ci/run.sh + $command if [ -f /.dockerenv ]; then rm -rf $objdir diff --git a/src/ci/docker/test-various/Dockerfile b/src/ci/docker/test-various/Dockerfile index 9276e4ed82d..6775baa8c32 100644 --- a/src/ci/docker/test-various/Dockerfile +++ b/src/ci/docker/test-various/Dockerfile @@ -17,7 +17,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ wget \ patch -RUN curl -sL https://nodejs.org/dist/v9.2.0/node-v9.2.0-linux-x64.tar.xz | \ +RUN curl -sL https://nodejs.org/dist/v14.4.0/node-v14.4.0-linux-x64.tar.xz | \ tar -xJ WORKDIR /build/ @@ -30,7 +30,7 @@ RUN sh /scripts/sccache.sh ENV RUST_CONFIGURE_ARGS \ --musl-root-x86_64=/usr/local/x86_64-linux-musl \ - --set build.nodejs=/node-v9.2.0-linux-x64/bin/node \ + --set build.nodejs=/node-v14.4.0-linux-x64/bin/node \ --set rust.lld # Some run-make tests have assertions about code size, and enabling debug diff --git a/src/ci/docker/wasm32/Dockerfile b/src/ci/docker/wasm32/Dockerfile index 8232539edda..92461305320 100644 --- a/src/ci/docker/wasm32/Dockerfile +++ b/src/ci/docker/wasm32/Dockerfile @@ -25,7 +25,18 @@ RUN ln `which python3` /usr/bin/python ENV PATH=$PATH:/emsdk-portable ENV PATH=$PATH:/emsdk-portable/upstream/emscripten/ -ENV PATH=$PATH:/emsdk-portable/node/12.9.1_64bit/bin/ + +# Rust's build system requires NodeJS to be in the path, but the directory in +# which emsdk stores it contains the version number. This caused breakages in +# the past when emsdk bumped the node version causing the path to point to a +# missing directory. +# +# To avoid the problem this symlinks the latest NodeJs version available to +# "latest", and adds that to the path. +RUN ln -s /emsdk-portable/node/$(ls /emsdk-portable/node | sort -V | tail -n 1) \ + /emsdk-portable/node/latest +ENV PATH=$PATH:/emsdk-portable/node/latest/bin/ + ENV BINARYEN_ROOT=/emsdk-portable/upstream/ ENV EMSDK=/emsdk-portable ENV EM_CONFIG=/emsdk-portable/.emscripten diff --git a/src/ci/docker/x86_64-gnu-llvm-8/Dockerfile b/src/ci/docker/x86_64-gnu-llvm-8/Dockerfile index 58fdc6f2623..1d9cad149d9 100644 --- a/src/ci/docker/x86_64-gnu-llvm-8/Dockerfile +++ b/src/ci/docker/x86_64-gnu-llvm-8/Dockerfile @@ -45,6 +45,15 @@ ENV SCRIPT python2.7 ../x.py test --exclude src/tools/tidy && \ # (we're only interested in the MIR output, so this doesn't matter) python2.7 ../x.py test src/test/mir-opt --pass=build \ --target=armv5te-unknown-linux-gnueabi && \ + # Run the UI test suite again, but in `--pass=check` mode + # + # This is intended to make sure that both `--pass=check` continues to + # work. + # + # FIXME: We ideally want to test this in 32-bit mode, but currently + # (due to the LLVM problems mentioned above) that isn't readily + # possible. + python2.7 ../x.py test src/test/ui --pass=check && \ # Run tidy at the very end, after all the other tests. python2.7 ../x.py test src/tools/tidy diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 5e67567c76b..00170226e63 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -131,10 +131,6 @@ x--expand-yaml-anchors--remove: run: src/ci/scripts/install-wix.sh <<: *step - - name: install InnoSetup - run: src/ci/scripts/install-innosetup.sh - <<: *step - - name: ensure the build happens on a partition with enough space run: src/ci/scripts/symlink-build-dir.sh <<: *step @@ -414,6 +410,42 @@ jobs: DEPLOY_TOOLSTATES_JSON: toolstates-linux.json <<: *job-linux-xl + #################### + # macOS Builders # + #################### + + - name: dist-x86_64-apple + env: + SCRIPT: ./x.py dist + RUST_CONFIGURE_ARGS: --target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + DIST_REQUIRE_ALL_TOOLS: 1 + <<: *job-macos-xl + + - name: dist-x86_64-apple-alt + env: + SCRIPT: ./x.py dist + RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + <<: *job-macos-xl + + - name: x86_64-apple + env: + SCRIPT: ./x.py test + RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + <<: *job-macos-xl + ###################### # Windows Builders # ###################### @@ -559,51 +591,6 @@ jobs: SCRIPT: python x.py dist <<: *job-windows-xl - auto-fallible: - <<: *base-ci-job - name: auto-fallible - env: - <<: [*shared-ci-variables, *prod-variables] - if: github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust' - strategy: - matrix: - include: - #################### - # macOS Builders # - #################### - - - name: dist-x86_64-apple - env: - SCRIPT: ./x.py dist - RUST_CONFIGURE_ARGS: --target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - DIST_REQUIRE_ALL_TOOLS: 1 - <<: *job-macos-xl - - - name: dist-x86_64-apple-alt - env: - SCRIPT: ./x.py dist - RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --set rust.jemalloc - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - <<: *job-macos-xl - - - name: x86_64-apple - env: - SCRIPT: ./x.py test - RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.8 - MACOSX_STD_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - <<: *job-macos-xl - master: name: master runs-on: ubuntu-latest diff --git a/src/ci/scripts/install-innosetup.sh b/src/ci/scripts/install-innosetup.sh deleted file mode 100755 index 04ca249777a..00000000000 --- a/src/ci/scripts/install-innosetup.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -# We use InnoSetup and its `iscc` program to also create combined installers. -# Honestly at this point WIX above and `iscc` are just holdovers from -# oh-so-long-ago and are required for creating installers on Windows. I think -# one is MSI installers and one is EXE, but they're not used so frequently at -# this point anyway so perhaps it's a wash! - -set -euo pipefail -IFS=$'\n\t' - -source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" - -if isWindows; then - curl.exe -o is-install.exe "${MIRRORS_BASE}/2017-08-22-is.exe" - cmd.exe //c "is-install.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-" - - ciCommandAddPath "C:\\Program Files (x86)\\Inno Setup 5" -fi diff --git a/src/doc/unstable-book/src/language-features/track-caller.md b/src/doc/unstable-book/src/language-features/track-caller.md deleted file mode 100644 index afc11a2b949..00000000000 --- a/src/doc/unstable-book/src/language-features/track-caller.md +++ /dev/null @@ -1,5 +0,0 @@ -# `track_caller` - -The tracking issue for this feature is: [#47809](https://github.com/rust-lang/rust/issues/47809). - ------------------------- diff --git a/src/etc/installer/exe/modpath.iss b/src/etc/installer/exe/modpath.iss deleted file mode 100644 index 2cfc8698c4b..00000000000 --- a/src/etc/installer/exe/modpath.iss +++ /dev/null @@ -1,219 +0,0 @@ -// ---------------------------------------------------------------------------- -// -// Inno Setup Ver: 5.4.2 -// Script Version: 1.4.1 -// Author: Jared Breland <jbreland@legroom.net> -// Homepage: http://www.legroom.net/software -// License: GNU Lesser General Public License (LGPL), version 3 -// http://www.gnu.org/licenses/lgpl.html -// -// Script Function: -// Allow modification of environmental path directly from Inno Setup installers -// -// Instructions: -// Copy modpath.iss to the same directory as your setup script -// -// Add this statement to your [Setup] section -// ChangesEnvironment=true -// -// Add this statement to your [Tasks] section -// You can change the Description or Flags -// You can change the Name, but it must match the ModPathName setting below -// Name: modifypath; Description: &Add application directory to your environmental path; Flags: unchecked -// -// Add the following to the end of your [Code] section -// ModPathName defines the name of the task defined above -// ModPathType defines whether the 'user' or 'system' path will be modified; -// this will default to user if anything other than system is set -// setArrayLength must specify the total number of dirs to be added -// Result[0] contains first directory, Result[1] contains second, etc. -// const -// ModPathName = 'modifypath'; -// ModPathType = 'user'; -// -// function ModPathDir(): TArrayOfString; -// begin -// setArrayLength(Result, 1); -// Result[0] := ExpandConstant('{app}'); -// end; -// #include "modpath.iss" -// ---------------------------------------------------------------------------- - -procedure ModPath(); -var - oldpath: String; - newpath: String; - updatepath: Boolean; - pathArr: TArrayOfString; - aExecFile: String; - aExecArr: TArrayOfString; - i, d: Integer; - pathdir: TArrayOfString; - regroot: Integer; - regpath: String; - -begin - // Get constants from main script and adjust behavior accordingly - // ModPathType MUST be 'system' or 'user'; force 'user' if invalid - if ModPathType = 'system' then begin - regroot := HKEY_LOCAL_MACHINE; - regpath := 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'; - end else begin - regroot := HKEY_CURRENT_USER; - regpath := 'Environment'; - end; - - // Get array of new directories and act on each individually - pathdir := ModPathDir(); - for d := 0 to GetArrayLength(pathdir)-1 do begin - updatepath := true; - - // Modify WinNT path - if UsingWinNT() = true then begin - - // Get current path, split into an array - RegQueryStringValue(regroot, regpath, 'Path', oldpath); - oldpath := oldpath + ';'; - i := 0; - - while (Pos(';', oldpath) > 0) do begin - SetArrayLength(pathArr, i+1); - pathArr[i] := Copy(oldpath, 0, Pos(';', oldpath)-1); - oldpath := Copy(oldpath, Pos(';', oldpath)+1, Length(oldpath)); - i := i + 1; - - // Check if current directory matches app dir - if pathdir[d] = pathArr[i-1] then begin - // if uninstalling, remove dir from path - if IsUninstaller() = true then begin - continue; - // if installing, flag that dir already exists in path - end else begin - updatepath := false; - end; - end; - - // Add current directory to new path - if i = 1 then begin - newpath := pathArr[i-1]; - end else begin - newpath := newpath + ';' + pathArr[i-1]; - end; - end; - - // Append app dir to path if not already included - if (IsUninstaller() = false) AND (updatepath = true) then - newpath := newpath + ';' + pathdir[d]; - - // Write new path - RegWriteStringValue(regroot, regpath, 'Path', newpath); - - // Modify Win9x path - end else begin - - // Convert to shortened dirname - pathdir[d] := GetShortName(pathdir[d]); - - // If autoexec.bat exists, check if app dir already exists in path - aExecFile := 'C:\AUTOEXEC.BAT'; - if FileExists(aExecFile) then begin - LoadStringsFromFile(aExecFile, aExecArr); - for i := 0 to GetArrayLength(aExecArr)-1 do begin - if IsUninstaller() = false then begin - // If app dir already exists while installing, skip add - if (Pos(pathdir[d], aExecArr[i]) > 0) then - updatepath := false; - break; - end else begin - // If app dir exists and = what we originally set, then delete at uninstall - if aExecArr[i] = 'SET PATH=%PATH%;' + pathdir[d] then - aExecArr[i] := ''; - end; - end; - end; - - // If app dir not found, or autoexec.bat didn't exist, then (create and) append to current path - if (IsUninstaller() = false) AND (updatepath = true) then begin - SaveStringToFile(aExecFile, #13#10 + 'SET PATH=%PATH%;' + pathdir[d], True); - - // If uninstalling, write the full autoexec out - end else begin - SaveStringsToFile(aExecFile, aExecArr, False); - end; - end; - end; -end; - -// Split a string into an array using passed delimiter -procedure Explode(var Dest: TArrayOfString; Text: String; Separator: String); -var - i: Integer; -begin - i := 0; - repeat - SetArrayLength(Dest, i+1); - if Pos(Separator,Text) > 0 then begin - Dest[i] := Copy(Text, 1, Pos(Separator, Text)-1); - Text := Copy(Text, Pos(Separator,Text) + Length(Separator), Length(Text)); - i := i + 1; - end else begin - Dest[i] := Text; - Text := ''; - end; - until Length(Text)=0; -end; - - -procedure ModPathCurStepChanged(CurStep: TSetupStep); -var - taskname: String; -begin - taskname := ModPathName; - if CurStep = ssPostInstall then - if IsTaskSelected(taskname) then - ModPath(); -end; - -procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); -var - aSelectedTasks: TArrayOfString; - i: Integer; - taskname: String; - regpath: String; - regstring: String; - appid: String; -begin - // only run during actual uninstall - if CurUninstallStep = usUninstall then begin - // get list of selected tasks saved in registry at install time - appid := '{#emit SetupSetting("AppId")}'; - if appid = '' then appid := '{#emit SetupSetting("AppName")}'; - regpath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\'+appid+'_is1'); - RegQueryStringValue(HKLM, regpath, 'Inno Setup: Selected Tasks', regstring); - if regstring = '' then RegQueryStringValue(HKCU, regpath, 'Inno Setup: Selected Tasks', regstring); - - // check each task; if matches modpath taskname, trigger patch removal - if regstring <> '' then begin - taskname := ModPathName; - Explode(aSelectedTasks, regstring, ','); - if GetArrayLength(aSelectedTasks) > 0 then begin - for i := 0 to GetArrayLength(aSelectedTasks)-1 do begin - if comparetext(aSelectedTasks[i], taskname) = 0 then - ModPath(); - end; - end; - end; - end; -end; - -function NeedRestart(): Boolean; -var - taskname: String; -begin - taskname := ModPathName; - if IsTaskSelected(taskname) and not UsingWinNT() then begin - Result := True; - end else begin - Result := False; - end; -end; diff --git a/src/etc/installer/exe/rust.iss b/src/etc/installer/exe/rust.iss deleted file mode 100644 index 70648beac38..00000000000 --- a/src/etc/installer/exe/rust.iss +++ /dev/null @@ -1,87 +0,0 @@ -#define CFG_RELEASE_NUM GetEnv("CFG_RELEASE_NUM") -#define CFG_RELEASE GetEnv("CFG_RELEASE") -#define CFG_PACKAGE_NAME GetEnv("CFG_PACKAGE_NAME") -#define CFG_BUILD GetEnv("CFG_BUILD") - -[Setup] - -SetupIconFile=rust-logo.ico -AppName=Rust -AppVersion={#CFG_RELEASE} -AppCopyright=Copyright (C) 2006-2014 Mozilla Foundation, MIT license -AppPublisher=Mozilla Foundation -AppPublisherURL=http://www.rust-lang.org -VersionInfoVersion={#CFG_RELEASE_NUM} -LicenseFile=LICENSE.txt - -PrivilegesRequired=lowest -DisableWelcomePage=true -DisableProgramGroupPage=true -DisableReadyPage=true -DisableStartupPrompt=true - -OutputDir=.\ -SourceDir=.\ -OutputBaseFilename={#CFG_PACKAGE_NAME}-{#CFG_BUILD} -DefaultDirName={sd}\Rust - -Compression=lzma2/normal -InternalCompressLevel=normal -SolidCompression=no - -ChangesEnvironment=true -ChangesAssociations=no -AllowUNCPath=false -AllowNoIcons=true -Uninstallable=yes - -[Tasks] -Name: modifypath; Description: &Add {app}\bin to your PATH (recommended) - -[Components] -Name: rust; Description: "Rust compiler and standard crates"; Types: full compact custom; Flags: fixed -#ifdef MINGW -Name: gcc; Description: "Linker and platform libraries"; Types: full -#endif -Name: docs; Description: "HTML documentation"; Types: full -Name: cargo; Description: "Cargo, the Rust package manager"; Types: full -Name: std; Description: "The Rust Standard Library"; Types: full -// tool-rls-start -Name: rls; Description: "RLS, the Rust Language Server" -// tool-rls-end - -[Files] -Source: "rustc/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: rust -#ifdef MINGW -Source: "rust-mingw/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: gcc -#endif -Source: "rust-docs/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: docs -Source: "cargo/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: cargo -Source: "rust-std/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: std -// tool-rls-start -Source: "rls/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: rls -Source: "rust-analysis/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: rls -// tool-rls-end - -[Code] -const - ModPathName = 'modifypath'; - ModPathType = 'user'; - -function ModPathDir(): TArrayOfString; -begin - setArrayLength(Result, 1) - Result[0] := ExpandConstant('{app}\bin'); -end; - -#include "modpath.iss" -#include "upgrade.iss" - -// Both modpath.iss and upgrade.iss want to overload CurStepChanged. -// This version does the overload then delegates to each. - -procedure CurStepChanged(CurStep: TSetupStep); -begin - UpgradeCurStepChanged(CurStep); - ModPathCurStepChanged(CurStep); -end; diff --git a/src/etc/installer/exe/upgrade.iss b/src/etc/installer/exe/upgrade.iss deleted file mode 100644 index 29da7c333bb..00000000000 --- a/src/etc/installer/exe/upgrade.iss +++ /dev/null @@ -1,61 +0,0 @@ -// The following code taken from https://stackoverflow.com/questions/2000296/innosetup-how-to-automatically-uninstall-previous-installed-version -// It performs upgrades by running the uninstaller before the install - -///////////////////////////////////////////////////////////////////// -function GetUninstallString(): String; -var - sUnInstPath: String; - sUnInstallString: String; -begin - sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\Rust_is1'); - sUnInstallString := ''; - if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then - RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString); - Result := sUnInstallString; -end; - - -///////////////////////////////////////////////////////////////////// -function IsUpgrade(): Boolean; -begin - Result := (GetUninstallString() <> ''); -end; - - -///////////////////////////////////////////////////////////////////// -function UnInstallOldVersion(): Integer; -var - sUnInstallString: String; - iResultCode: Integer; -begin -// Return Values: -// 1 - uninstall string is empty -// 2 - error executing the UnInstallString -// 3 - successfully executed the UnInstallString - - // default return value - Result := 0; - - // get the uninstall string of the old app - sUnInstallString := GetUninstallString(); - if sUnInstallString <> '' then begin - sUnInstallString := RemoveQuotes(sUnInstallString); - if Exec(sUnInstallString, '/SILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then - Result := 3 - else - Result := 2; - end else - Result := 1; -end; - -///////////////////////////////////////////////////////////////////// -procedure UpgradeCurStepChanged(CurStep: TSetupStep); -begin - if (CurStep=ssInstall) then - begin - if (IsUpgrade()) then - begin - UnInstallOldVersion(); - end; - end; -end; diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index f1b560b9b96..3320ebdf821 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -384,7 +384,10 @@ impl<T: ?Sized> Box<T> { /// /// unsafe { /// let ptr = alloc(Layout::new::<i32>()) as *mut i32; - /// *ptr = 5; + /// // In general .write is required to avoid attempting to destruct + /// // the (uninitialized) previous contents of `ptr`, though for this + /// // simple example `*ptr = 5` would have worked as well. + /// ptr.write(5); /// let x = Box::from_raw(ptr); /// } /// ``` diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index bcd7445ecf9..ed81ce71ddf 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -80,9 +80,7 @@ impl<T> RawVec<T, Global> { /// /// # Panics /// - /// * Panics if the requested capacity exceeds `usize::MAX` bytes. - /// * Panics on 32-bit platforms if the requested capacity exceeds - /// `isize::MAX` bytes. + /// Panics if the requested capacity exceeds `isize::MAX` bytes. /// /// # Aborts /// @@ -262,9 +260,7 @@ impl<T, A: AllocRef> RawVec<T, A> { /// /// # Panics /// - /// * Panics if the requested capacity exceeds `usize::MAX` bytes. - /// * Panics on 32-bit platforms if the requested capacity exceeds - /// `isize::MAX` bytes. + /// Panics if the new capacity exceeds `isize::MAX` bytes. /// /// # Aborts /// @@ -329,9 +325,7 @@ impl<T, A: AllocRef> RawVec<T, A> { /// /// # Panics /// - /// * Panics if the requested capacity exceeds `usize::MAX` bytes. - /// * Panics on 32-bit platforms if the requested capacity exceeds - /// `isize::MAX` bytes. + /// Panics if the new capacity exceeds `isize::MAX` bytes. /// /// # Aborts /// diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 64d9692244d..13ef94dee23 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -2518,3 +2518,11 @@ impl DoubleEndedIterator for Drain<'_> { #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Drain<'_> {} + +#[stable(feature = "from_char_for_string", since = "1.46.0")] +impl From<char> for String { + #[inline] + fn from(c: char) -> Self { + c.to_string() + } +} diff --git a/src/liballoc/tests/btree/map.rs b/src/liballoc/tests/btree/map.rs index 682d829d219..f66b5814ca0 100644 --- a/src/liballoc/tests/btree/map.rs +++ b/src/liballoc/tests/btree/map.rs @@ -310,6 +310,7 @@ fn test_iter_mixed() { } #[test] +#[cfg_attr(miri, ignore)] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915> fn test_iter_min_max() { let mut a = BTreeMap::new(); assert_eq!(a.iter().min(), None); diff --git a/src/liballoc/tests/string.rs b/src/liballoc/tests/string.rs index 9ea020d2d19..d38655af78c 100644 --- a/src/liballoc/tests/string.rs +++ b/src/liballoc/tests/string.rs @@ -714,3 +714,10 @@ fn test_try_reserve_exact() { } } } + +#[test] +fn test_from_char() { + assert_eq!(String::from('a'), 'a'.to_string()); + let s: String = 'x'.into(); + assert_eq!(s, 'x'.to_string()); +} diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index c2cf64393ad..5db96a504a6 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -491,7 +491,7 @@ impl<T> Vec<T> { /// /// # Panics /// - /// Panics if the new capacity overflows `usize`. + /// Panics if the new capacity exceeds `isize::MAX` bytes. /// /// # Examples /// @@ -1188,7 +1188,7 @@ impl<T> Vec<T> { /// /// # Panics /// - /// Panics if the number of elements in the vector overflows a `usize`. + /// Panics if the new capacity exceeds `isize::MAX` bytes. /// /// # Examples /// diff --git a/src/libcore/alloc/global.rs b/src/libcore/alloc/global.rs index 147fe696ac0..c198797e650 100644 --- a/src/libcore/alloc/global.rs +++ b/src/libcore/alloc/global.rs @@ -127,9 +127,12 @@ pub unsafe trait GlobalAlloc { #[stable(feature = "global_alloc", since = "1.28.0")] unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { let size = layout.size(); - let ptr = self.alloc(layout); + // SAFETY: the safety contract for `alloc` must be upheld by the caller. + let ptr = unsafe { self.alloc(layout) }; if !ptr.is_null() { - ptr::write_bytes(ptr, 0, size); + // SAFETY: as allocation succeeded, the region from `ptr` + // of size `size` is guaranteed to be valid for writes. + unsafe { ptr::write_bytes(ptr, 0, size) }; } ptr } @@ -187,11 +190,18 @@ pub unsafe trait GlobalAlloc { /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html #[stable(feature = "global_alloc", since = "1.28.0")] unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); - let new_ptr = self.alloc(new_layout); + // SAFETY: the caller must ensure that the `new_size` does not overflow. + // `layout.align()` comes from a `Layout` and is thus guaranteed to be valid. + let new_layout = unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) }; + // SAFETY: the caller must ensure that `new_layout` is greater than zero. + let new_ptr = unsafe { self.alloc(new_layout) }; if !new_ptr.is_null() { - ptr::copy_nonoverlapping(ptr, new_ptr, cmp::min(layout.size(), new_size)); - self.dealloc(ptr, layout); + // SAFETY: the previously allocated block cannot overlap the newly allocated block. + // The safety contract for `dealloc` must be upheld by the caller. + unsafe { + ptr::copy_nonoverlapping(ptr, new_ptr, cmp::min(layout.size(), new_size)); + self.dealloc(ptr, layout); + } } new_ptr } diff --git a/src/libcore/alloc/layout.rs b/src/libcore/alloc/layout.rs index a09c2387d0d..ae7ae704465 100644 --- a/src/libcore/alloc/layout.rs +++ b/src/libcore/alloc/layout.rs @@ -90,7 +90,8 @@ impl Layout { #[rustc_const_stable(feature = "alloc_layout", since = "1.28.0")] #[inline] pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self { - Layout { size_: size, align_: NonZeroUsize::new_unchecked(align) } + // SAFETY: the caller must ensure that `align` is greater than zero. + Layout { size_: size, align_: unsafe { NonZeroUsize::new_unchecked(align) } } } /// The minimum size in bytes for a memory block of this layout. diff --git a/src/libcore/alloc/mod.rs b/src/libcore/alloc/mod.rs index 1346fbd4810..be4e051b1ca 100644 --- a/src/libcore/alloc/mod.rs +++ b/src/libcore/alloc/mod.rs @@ -54,7 +54,9 @@ impl AllocInit { #[inline] #[unstable(feature = "allocator_api", issue = "32838")] pub unsafe fn init(self, memory: MemoryBlock) { - self.init_offset(memory, 0) + // SAFETY: the safety contract for `init_offset` must be + // upheld by the caller. + unsafe { self.init_offset(memory, 0) } } /// Initialize the memory block like specified by `init` at the specified `offset`. @@ -78,7 +80,10 @@ impl AllocInit { match self { AllocInit::Uninitialized => (), AllocInit::Zeroed => { - memory.ptr.as_ptr().add(offset).write_bytes(0, memory.size - offset) + // SAFETY: the caller must guarantee that `offset` is smaller than or equal to `memory.size`, + // so the memory from `memory.ptr + offset` of length `memory.size - offset` + // is guaranteed to be contaned in `memory` and thus valid for writes. + unsafe { memory.ptr.as_ptr().add(offset).write_bytes(0, memory.size - offset) } } } } @@ -281,11 +286,23 @@ pub unsafe trait AllocRef { return Ok(MemoryBlock { ptr, size }); } - let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); + let new_layout = + // SAFETY: the caller must ensure that the `new_size` does not overflow. + // `layout.align()` comes from a `Layout` and is thus guaranteed to be valid for a Layout. + // The caller must ensure that `new_size` is greater than zero. + unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) }; let new_memory = self.alloc(new_layout, init)?; - ptr::copy_nonoverlapping(ptr.as_ptr(), new_memory.ptr.as_ptr(), size); - self.dealloc(ptr, layout); - Ok(new_memory) + + // SAFETY: because `new_size` must be greater than or equal to `size`, both the old and new + // memory allocation are valid for reads and writes for `size` bytes. Also, because the old + // allocation wasn't yet deallocated, it cannot overlap `new_memory`. Thus, the call to + // `copy_nonoverlapping` is safe. + // The safety contract for `dealloc` must be upheld by the caller. + unsafe { + ptr::copy_nonoverlapping(ptr.as_ptr(), new_memory.ptr.as_ptr(), size); + self.dealloc(ptr, layout); + Ok(new_memory) + } } } } @@ -356,11 +373,23 @@ pub unsafe trait AllocRef { return Ok(MemoryBlock { ptr, size }); } - let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); + let new_layout = + // SAFETY: the caller must ensure that the `new_size` does not overflow. + // `layout.align()` comes from a `Layout` and is thus guaranteed to be valid for a Layout. + // The caller must ensure that `new_size` is greater than zero. + unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) }; let new_memory = self.alloc(new_layout, AllocInit::Uninitialized)?; - ptr::copy_nonoverlapping(ptr.as_ptr(), new_memory.ptr.as_ptr(), new_size); - self.dealloc(ptr, layout); - Ok(new_memory) + + // SAFETY: because `new_size` must be lower than or equal to `size`, both the old and new + // memory allocation are valid for reads and writes for `new_size` bytes. Also, because the + // old allocation wasn't yet deallocated, it cannot overlap `new_memory`. Thus, the call to + // `copy_nonoverlapping` is safe. + // The safety contract for `dealloc` must be upheld by the caller. + unsafe { + ptr::copy_nonoverlapping(ptr.as_ptr(), new_memory.ptr.as_ptr(), new_size); + self.dealloc(ptr, layout); + Ok(new_memory) + } } } } @@ -386,7 +415,8 @@ where #[inline] unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) { - (**self).dealloc(ptr, layout) + // SAFETY: the safety contract must be upheld by the caller + unsafe { (**self).dealloc(ptr, layout) } } #[inline] @@ -398,7 +428,8 @@ where placement: ReallocPlacement, init: AllocInit, ) -> Result<MemoryBlock, AllocErr> { - (**self).grow(ptr, layout, new_size, placement, init) + // SAFETY: the safety contract must be upheld by the caller + unsafe { (**self).grow(ptr, layout, new_size, placement, init) } } #[inline] @@ -409,6 +440,7 @@ where new_size: usize, placement: ReallocPlacement, ) -> Result<MemoryBlock, AllocErr> { - (**self).shrink(ptr, layout, new_size, placement) + // SAFETY: the safety contract must be upheld by the caller + unsafe { (**self).shrink(ptr, layout, new_size, placement) } } } diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index c4293ed7bcf..51d9695687f 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -1005,7 +1005,12 @@ impl<T: ?Sized> RefCell<T> { #[inline] pub unsafe fn try_borrow_unguarded(&self) -> Result<&T, BorrowError> { if !is_writing(self.borrow.get()) { - Ok(&*self.value.get()) + // SAFETY: We check that nobody is actively writing now, but it is + // the caller's responsibility to ensure that nobody writes until + // the returned reference is no longer in use. + // Also, `self.value.get()` refers to the value owned by `self` + // and is thus guaranteed to be valid for the lifetime of `self`. + Ok(unsafe { &*self.value.get() }) } else { Err(BorrowError { _private: () }) } diff --git a/src/libcore/char/convert.rs b/src/libcore/char/convert.rs index d7e39946148..c329eec76ac 100644 --- a/src/libcore/char/convert.rs +++ b/src/libcore/char/convert.rs @@ -99,7 +99,8 @@ pub fn from_u32(i: u32) -> Option<char> { #[inline] #[stable(feature = "char_from_unchecked", since = "1.5.0")] pub unsafe fn from_u32_unchecked(i: u32) -> char { - if cfg!(debug_assertions) { char::from_u32(i).unwrap() } else { transmute(i) } + // SAFETY: the caller must guarantee that `i` is a valid char value. + if cfg!(debug_assertions) { char::from_u32(i).unwrap() } else { unsafe { transmute(i) } } } #[stable(feature = "char_convert", since = "1.13.0")] diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs index dd2f01c679f..72555d781ed 100644 --- a/src/libcore/char/methods.rs +++ b/src/libcore/char/methods.rs @@ -183,7 +183,8 @@ impl char { #[unstable(feature = "assoc_char_funcs", reason = "recently added", issue = "71763")] #[inline] pub unsafe fn from_u32_unchecked(i: u32) -> char { - super::convert::from_u32_unchecked(i) + // SAFETY: the safety contract must be upheld by the caller. + unsafe { super::convert::from_u32_unchecked(i) } } /// Converts a digit in the given radix to a `char`. diff --git a/src/libcore/convert/num.rs b/src/libcore/convert/num.rs index 46ba0a279b7..336c0b26bc7 100644 --- a/src/libcore/convert/num.rs +++ b/src/libcore/convert/num.rs @@ -28,7 +28,8 @@ macro_rules! impl_float_to_int { #[doc(hidden)] #[inline] unsafe fn to_int_unchecked(self) -> $Int { - crate::intrinsics::float_to_int_unchecked(self) + // SAFETY: the safety contract must be upheld by the caller. + unsafe { crate::intrinsics::float_to_int_unchecked(self) } } } )+ diff --git a/src/libcore/ffi.rs b/src/libcore/ffi.rs index 7bc2866dc2e..ca463200650 100644 --- a/src/libcore/ffi.rs +++ b/src/libcore/ffi.rs @@ -333,7 +333,8 @@ impl<'f> VaListImpl<'f> { /// Advance to the next arg. #[inline] pub unsafe fn arg<T: sealed_trait::VaArgSafe>(&mut self) -> T { - va_arg(self) + // SAFETY: the caller must uphold the safety contract for `va_arg`. + unsafe { va_arg(self) } } /// Copies the `va_list` at the current location. @@ -343,7 +344,10 @@ impl<'f> VaListImpl<'f> { { let mut ap = self.clone(); let ret = f(ap.as_va_list()); - va_end(&mut ap); + // SAFETY: the caller must uphold the safety contract for `va_end`. + unsafe { + va_end(&mut ap); + } ret } } diff --git a/src/libcore/future/mod.rs b/src/libcore/future/mod.rs index 9dbc23f5c04..2555d91ae8d 100644 --- a/src/libcore/future/mod.rs +++ b/src/libcore/future/mod.rs @@ -85,5 +85,7 @@ where #[unstable(feature = "gen_future", issue = "50547")] #[inline] pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> { - &mut *cx.0.as_ptr().cast() + // SAFETY: the caller must guarantee that `cx.0` is a valid pointer + // that fulfills all the requirements for a mutable reference. + unsafe { &mut *cx.0.as_ptr().cast() } } diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index ac058609f45..f2bbf646f32 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -130,15 +130,19 @@ unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 { let mut i = 0; // current byte index (from LSB) in the output u64 let mut out = 0; if i + 3 < len { - out = load_int_le!(buf, start + i, u32) as u64; + // SAFETY: `i` cannot be greater than `len`, and the caller must guarantee + // that the index start..start+len is in bounds. + out = unsafe { load_int_le!(buf, start + i, u32) } as u64; i += 4; } if i + 1 < len { - out |= (load_int_le!(buf, start + i, u16) as u64) << (i * 8); + // SAFETY: same as above. + out |= (unsafe { load_int_le!(buf, start + i, u16) } as u64) << (i * 8); i += 2 } if i < len { - out |= (*buf.get_unchecked(start + i) as u64) << (i * 8); + // SAFETY: same as above. + out |= (unsafe { *buf.get_unchecked(start + i) } as u64) << (i * 8); i += 1; } debug_assert_eq!(i, len); diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs index 0d794de5fe8..9ebcde79b63 100644 --- a/src/libcore/hint.rs +++ b/src/libcore/hint.rs @@ -46,7 +46,9 @@ use crate::intrinsics; #[inline] #[stable(feature = "unreachable", since = "1.27.0")] pub unsafe fn unreachable_unchecked() -> ! { - intrinsics::unreachable() + // SAFETY: the safety contract for `intrinsics::unreachable` must + // be upheld by the caller. + unsafe { intrinsics::unreachable() } } /// Emits a machine instruction hinting to the processor that it is running in busy-wait diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 5d090187591..aff4e4a8d98 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -952,6 +952,7 @@ extern "rust-intrinsic" { /// Any use other than with `if` statements will probably not have an effect. /// /// This intrinsic does not have a stable counterpart. + #[rustc_const_unstable(feature = "const_likely", issue = "none")] pub fn likely(b: bool) -> bool; /// Hints to the compiler that branch condition is likely to be false. @@ -960,6 +961,7 @@ extern "rust-intrinsic" { /// Any use other than with `if` statements will probably not have an effect. /// /// This intrinsic does not have a stable counterpart. + #[rustc_const_unstable(feature = "const_likely", issue = "none")] pub fn unlikely(b: bool) -> bool; /// Executes a breakpoint trap, for inspection by a debugger. @@ -1956,7 +1958,40 @@ extern "rust-intrinsic" { /// generation. #[cfg(not(bootstrap))] #[lang = "count_code_region"] - pub fn count_code_region(index: u32); + pub fn count_code_region(index: u32, start_byte_pos: u32, end_byte_pos: u32); + + /// Internal marker for code coverage expressions, injected into the MIR when the + /// "instrument-coverage" option is enabled. This intrinsic is not converted into a + /// backend intrinsic call, but its arguments are extracted during the production of a + /// "coverage map", which is injected into the generated code, as additional data. + /// This marker identifies a code region and two other counters or counter expressions + /// whose sum is the number of times the code region was executed. + #[cfg(not(bootstrap))] + pub fn coverage_counter_add( + index: u32, + left_index: u32, + right_index: u32, + start_byte_pos: u32, + end_byte_pos: u32, + ); + + /// This marker identifies a code region and two other counters or counter expressions + /// whose difference is the number of times the code region was executed. + /// (See `coverage_counter_add` for more information.) + #[cfg(not(bootstrap))] + pub fn coverage_counter_subtract( + index: u32, + left_index: u32, + right_index: u32, + start_byte_pos: u32, + end_byte_pos: u32, + ); + + /// This marker identifies a code region to be added to the "coverage map" to indicate source + /// code that can never be reached. + /// (See `coverage_counter_add` for more information.) + #[cfg(not(bootstrap))] + pub fn coverage_unreachable(start_byte_pos: u32, end_byte_pos: u32); /// See documentation of `<*const T>::guaranteed_eq` for details. #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] @@ -2097,7 +2132,10 @@ pub unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) { // Not panicking to keep codegen impact smaller. abort(); } - copy_nonoverlapping(src, dst, count) + + // SAFETY: the safety contract for `copy_nonoverlapping` must be + // upheld by the caller. + unsafe { copy_nonoverlapping(src, dst, count) } } /// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source @@ -2163,7 +2201,9 @@ pub unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) { // Not panicking to keep codegen impact smaller. abort(); } - copy(src, dst, count) + + // SAFETY: the safety contract for `copy` must be upheld by the caller. + unsafe { copy(src, dst, count) } } /// Sets `count * size_of::<T>()` bytes of memory starting at `dst` to @@ -2246,5 +2286,7 @@ pub unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) { } debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer"); - write_bytes(dst, val, count) + + // SAFETY: the safety contract for `write_bytes` must be upheld by the caller. + unsafe { write_bytes(dst, val, count) } } diff --git a/src/libcore/iter/adapters/fuse.rs b/src/libcore/iter/adapters/fuse.rs index 502fc2e6315..d2e2fc04a2b 100644 --- a/src/libcore/iter/adapters/fuse.rs +++ b/src/libcore/iter/adapters/fuse.rs @@ -178,9 +178,10 @@ where { unsafe fn get_unchecked(&mut self, i: usize) -> I::Item { match self.iter { - Some(ref mut iter) => iter.get_unchecked(i), + // SAFETY: the caller must uphold the contract for `TrustedRandomAccess::get_unchecked`. + Some(ref mut iter) => unsafe { iter.get_unchecked(i) }, // SAFETY: the caller asserts there is an item at `i`, so we're not exhausted. - None => intrinsics::unreachable(), + None => unsafe { intrinsics::unreachable() }, } } diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index 00529f0e2d5..133643a0c7f 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -272,7 +272,8 @@ where T: Copy, { unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item { - *self.it.get_unchecked(i) + // SAFETY: the caller must uphold the contract for `TrustedRandomAccess::get_unchecked`. + unsafe { *self.it.get_unchecked(i) } } #[inline] @@ -402,7 +403,8 @@ where T: Clone, { default unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item { - self.it.get_unchecked(i).clone() + // SAFETY: the caller must uphold the contract for `TrustedRandomAccess::get_unchecked`. + unsafe { self.it.get_unchecked(i) }.clone() } #[inline] @@ -418,7 +420,8 @@ where T: Copy, { unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item { - *self.it.get_unchecked(i) + // SAFETY: the caller must uphold the contract for `TrustedRandomAccess::get_unchecked`. + unsafe { *self.it.get_unchecked(i) } } #[inline] @@ -930,7 +933,8 @@ where F: FnMut(I::Item) -> B, { unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item { - (self.f)(self.iter.get_unchecked(i)) + // SAFETY: the caller must uphold the contract for `TrustedRandomAccess::get_unchecked`. + (self.f)(unsafe { self.iter.get_unchecked(i) }) } #[inline] fn may_have_side_effect() -> bool { @@ -1392,7 +1396,8 @@ where I: TrustedRandomAccess, { unsafe fn get_unchecked(&mut self, i: usize) -> (usize, I::Item) { - (self.count + i, self.iter.get_unchecked(i)) + // SAFETY: the caller must uphold the contract for `TrustedRandomAccess::get_unchecked`. + (self.count + i, unsafe { self.iter.get_unchecked(i) }) } fn may_have_side_effect() -> bool { diff --git a/src/libcore/iter/adapters/zip.rs b/src/libcore/iter/adapters/zip.rs index e83d36a580f..985e6561665 100644 --- a/src/libcore/iter/adapters/zip.rs +++ b/src/libcore/iter/adapters/zip.rs @@ -271,7 +271,8 @@ where B: TrustedRandomAccess, { unsafe fn get_unchecked(&mut self, i: usize) -> (A::Item, B::Item) { - (self.a.get_unchecked(i), self.b.get_unchecked(i)) + // SAFETY: the caller must uphold the contract for `TrustedRandomAccess::get_unchecked`. + unsafe { (self.a.get_unchecked(i), self.b.get_unchecked(i)) } } fn may_have_side_effect() -> bool { diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index bd7e6cfa5a7..ee53b6a13f8 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -189,12 +189,14 @@ macro_rules! step_identical_methods { () => { #[inline] unsafe fn forward_unchecked(start: Self, n: usize) -> Self { - start.unchecked_add(n as Self) + // SAFETY: the caller has to guarantee that `start + n` doesn't overflow. + unsafe { start.unchecked_add(n as Self) } } #[inline] unsafe fn backward_unchecked(start: Self, n: usize) -> Self { - start.unchecked_sub(n as Self) + // SAFETY: the caller has to guarantee that `start - n` doesn't overflow. + unsafe { start.unchecked_sub(n as Self) } } #[inline] @@ -450,21 +452,33 @@ unsafe impl Step for char { #[inline] unsafe fn forward_unchecked(start: char, count: usize) -> char { let start = start as u32; - let mut res = Step::forward_unchecked(start, count); + // SAFETY: the caller must guarantee that this doesn't overflow + // the range of values for a char. + let mut res = unsafe { Step::forward_unchecked(start, count) }; if start < 0xD800 && 0xD800 <= res { - res = Step::forward_unchecked(res, 0x800); + // SAFETY: the caller must guarantee that this doesn't overflow + // the range of values for a char. + res = unsafe { Step::forward_unchecked(res, 0x800) }; } - char::from_u32_unchecked(res) + // SAFETY: because of the previous contract, this is guaranteed + // by the caller to be a valid char. + unsafe { char::from_u32_unchecked(res) } } #[inline] unsafe fn backward_unchecked(start: char, count: usize) -> char { let start = start as u32; - let mut res = Step::backward_unchecked(start, count); + // SAFETY: the caller must guarantee that this doesn't overflow + // the range of values for a char. + let mut res = unsafe { Step::backward_unchecked(start, count) }; if start >= 0xE000 && 0xE000 > res { - res = Step::backward_unchecked(res, 0x800); + // SAFETY: the caller must guarantee that this doesn't overflow + // the range of values for a char. + res = unsafe { Step::backward_unchecked(res, 0x800) }; } - char::from_u32_unchecked(res) + // SAFETY: because of the previous contract, this is guaranteed + // by the caller to be a valid char. + unsafe { char::from_u32_unchecked(res) } } } diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index aeb52bffbf2..50c56434fa9 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -92,6 +92,7 @@ #![feature(const_slice_from_raw_parts)] #![feature(const_slice_ptr_len)] #![feature(const_type_name)] +#![feature(const_likely)] #![feature(custom_inner_attributes)] #![feature(decl_macro)] #![feature(doc_cfg)] @@ -118,7 +119,7 @@ #![feature(staged_api)] #![feature(std_internals)] #![feature(stmt_expr_attributes)] -#![feature(track_caller)] +#![cfg_attr(bootstrap, feature(track_caller))] #![feature(transparent_unions)] #![feature(unboxed_closures)] #![feature(unsized_locals)] @@ -148,6 +149,8 @@ #![feature(const_type_id)] #![feature(const_caller_location)] #![feature(no_niche)] // rust-lang/rust#68303 +#![feature(unsafe_block_in_unsafe_fn)] +#![deny(unsafe_op_in_unsafe_fn)] #[prelude_import] #[allow(unused)] @@ -278,7 +281,13 @@ pub mod primitive; // set up in such a way that directly pulling it here works such that the // crate uses the this crate as its libcore. #[path = "../stdarch/crates/core_arch/src/mod.rs"] -#[allow(missing_docs, missing_debug_implementations, dead_code, unused_imports)] +#[allow( + missing_docs, + missing_debug_implementations, + dead_code, + unused_imports, + unsafe_op_in_unsafe_fn +)] // FIXME: This annotation should be moved into rust-lang/stdarch after clashing_extern_declarations is // merged. It currently cannot because bootstrap fails as the lint hasn't been defined yet. #[cfg_attr(not(bootstrap), allow(clashing_extern_declarations))] diff --git a/src/libcore/macros/mod.rs b/src/libcore/macros/mod.rs index 3cfdde60135..17f7349bac2 100644 --- a/src/libcore/macros/mod.rs +++ b/src/libcore/macros/mod.rs @@ -1,6 +1,6 @@ #[doc(include = "panic.md")] #[macro_export] -#[allow_internal_unstable(core_panic, track_caller)] +#[allow_internal_unstable(core_panic, const_caller_location)] #[stable(feature = "core", since = "1.6.0")] macro_rules! panic { () => ( @@ -151,7 +151,7 @@ macro_rules! assert_ne { /// An unchecked assertion allows a program in an inconsistent state to keep /// running, which might have unexpected consequences but does not introduce /// unsafety as long as this only happens in safe code. The performance cost -/// of assertions, is however, not measurable in general. Replacing [`assert!`] +/// of assertions, however, is not measurable in general. Replacing [`assert!`] /// with `debug_assert!` is thus only encouraged after thorough profiling, and /// more importantly, only in safe code! /// diff --git a/src/libcore/mem/manually_drop.rs b/src/libcore/mem/manually_drop.rs index 18767c482c7..920f5e9c0bd 100644 --- a/src/libcore/mem/manually_drop.rs +++ b/src/libcore/mem/manually_drop.rs @@ -122,7 +122,9 @@ impl<T> ManuallyDrop<T> { #[stable(feature = "manually_drop_take", since = "1.42.0")] #[inline] pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T { - ptr::read(&slot.value) + // SAFETY: we are reading from a reference, which is guaranteed + // to be valid for reads. + unsafe { ptr::read(&slot.value) } } } @@ -152,7 +154,10 @@ impl<T: ?Sized> ManuallyDrop<T> { #[stable(feature = "manually_drop", since = "1.20.0")] #[inline] pub unsafe fn drop(slot: &mut ManuallyDrop<T>) { - ptr::drop_in_place(&mut slot.value) + // SAFETY: we are dropping the value pointed to by a mutable reference + // which is guaranteed to be valid for writes. + // It is up to the caller to make sure that `slot` isn't dropped again. + unsafe { ptr::drop_in_place(&mut slot.value) } } } diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs index 499016545e9..7732525a0fc 100644 --- a/src/libcore/mem/maybe_uninit.rs +++ b/src/libcore/mem/maybe_uninit.rs @@ -494,8 +494,12 @@ impl<T> MaybeUninit<T> { #[inline(always)] #[rustc_diagnostic_item = "assume_init"] pub unsafe fn assume_init(self) -> T { - intrinsics::assert_inhabited::<T>(); - ManuallyDrop::into_inner(self.value) + // SAFETY: the caller must guarantee that `self` is initialized. + // This also means that `self` must be a `value` variant. + unsafe { + intrinsics::assert_inhabited::<T>(); + ManuallyDrop::into_inner(self.value) + } } /// Reads the value from the `MaybeUninit<T>` container. The resulting `T` is subject @@ -558,8 +562,12 @@ impl<T> MaybeUninit<T> { #[unstable(feature = "maybe_uninit_extra", issue = "63567")] #[inline(always)] pub unsafe fn read(&self) -> T { - intrinsics::assert_inhabited::<T>(); - self.as_ptr().read() + // SAFETY: the caller must guarantee that `self` is initialized. + // Reading from `self.as_ptr()` is safe since `self` should be initialized. + unsafe { + intrinsics::assert_inhabited::<T>(); + self.as_ptr().read() + } } /// Gets a shared reference to the contained value. @@ -620,8 +628,12 @@ impl<T> MaybeUninit<T> { #[unstable(feature = "maybe_uninit_ref", issue = "63568")] #[inline(always)] pub unsafe fn get_ref(&self) -> &T { - intrinsics::assert_inhabited::<T>(); - &*self.value + // SAFETY: the caller must guarantee that `self` is initialized. + // This also means that `self` must be a `value` variant. + unsafe { + intrinsics::assert_inhabited::<T>(); + &*self.value + } } /// Gets a mutable (unique) reference to the contained value. @@ -738,8 +750,12 @@ impl<T> MaybeUninit<T> { #[unstable(feature = "maybe_uninit_ref", issue = "63568")] #[inline(always)] pub unsafe fn get_mut(&mut self) -> &mut T { - intrinsics::assert_inhabited::<T>(); - &mut *self.value + // SAFETY: the caller must guarantee that `self` is initialized. + // This also means that `self` must be a `value` variant. + unsafe { + intrinsics::assert_inhabited::<T>(); + &mut *self.value + } } /// Assuming all the elements are initialized, get a slice to them. @@ -752,7 +768,11 @@ impl<T> MaybeUninit<T> { #[unstable(feature = "maybe_uninit_slice_assume_init", issue = "none")] #[inline(always)] pub unsafe fn slice_get_ref(slice: &[Self]) -> &[T] { - &*(slice as *const [Self] as *const [T]) + // SAFETY: casting slice to a `*const [T]` is safe since the caller guarantees that + // `slice` is initialized, and`MaybeUninit` is guaranteed to have the same layout as `T`. + // The pointer obtained is valid since it refers to memory owned by `slice` which is a + // reference and thus guaranteed to be valid for reads. + unsafe { &*(slice as *const [Self] as *const [T]) } } /// Assuming all the elements are initialized, get a mutable slice to them. @@ -765,7 +785,9 @@ impl<T> MaybeUninit<T> { #[unstable(feature = "maybe_uninit_slice_assume_init", issue = "none")] #[inline(always)] pub unsafe fn slice_get_mut(slice: &mut [Self]) -> &mut [T] { - &mut *(slice as *mut [Self] as *mut [T]) + // SAFETY: similar to safety notes for `slice_get_ref`, but we have a + // mutable reference which is also guaranteed to be valid for writes. + unsafe { &mut *(slice as *mut [Self] as *mut [T]) } } /// Gets a pointer to the first element of the array. diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index 46e6ea7cd18..272088815ec 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -623,8 +623,11 @@ pub const fn needs_drop<T>() -> bool { #[allow(deprecated)] #[rustc_diagnostic_item = "mem_zeroed"] pub unsafe fn zeroed<T>() -> T { - intrinsics::assert_zero_valid::<T>(); - MaybeUninit::zeroed().assume_init() + // SAFETY: the caller must guarantee that an all-zero value is valid for `T`. + unsafe { + intrinsics::assert_zero_valid::<T>(); + MaybeUninit::zeroed().assume_init() + } } /// Bypasses Rust's normal memory-initialization checks by pretending to @@ -656,8 +659,11 @@ pub unsafe fn zeroed<T>() -> T { #[allow(deprecated)] #[rustc_diagnostic_item = "mem_uninitialized"] pub unsafe fn uninitialized<T>() -> T { - intrinsics::assert_uninit_valid::<T>(); - MaybeUninit::uninit().assume_init() + // SAFETY: the caller must guarantee that an unitialized value is valid for `T`. + unsafe { + intrinsics::assert_uninit_valid::<T>(); + MaybeUninit::uninit().assume_init() + } } /// Swaps the values at two mutable locations, without deinitializing either one. @@ -922,9 +928,14 @@ pub fn drop<T>(_x: T) {} pub unsafe fn transmute_copy<T, U>(src: &T) -> U { // If U has a higher alignment requirement, src may not be suitably aligned. if align_of::<U>() > align_of::<T>() { - ptr::read_unaligned(src as *const T as *const U) + // SAFETY: `src` is a reference which is guaranteed to be valid for reads. + // The caller must guarantee that the actual transmutation is safe. + unsafe { ptr::read_unaligned(src as *const T as *const U) } } else { - ptr::read(src as *const T as *const U) + // SAFETY: `src` is a reference which is guaranteed to be valid for reads. + // We just checked that `src as *const U` was properly aligned. + // The caller must guarantee that the actual transmutation is safe. + unsafe { ptr::read(src as *const T as *const U) } } } diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 6313de31ce4..061d1ea6b1c 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -629,7 +629,9 @@ impl f32 { where Self: FloatToInt<Int>, { - FloatToInt::<Int>::to_int_unchecked(self) + // SAFETY: the caller must uphold the safety contract for + // `FloatToInt::to_int_unchecked`. + unsafe { FloatToInt::<Int>::to_int_unchecked(self) } } /// Raw transmutation to `u32`. diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index d42e5392c58..b0df4d64f6e 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -643,7 +643,9 @@ impl f64 { where Self: FloatToInt<Int>, { - FloatToInt::<Int>::to_int_unchecked(self) + // SAFETY: the caller must uphold the safety contract for + // `FloatToInt::to_int_unchecked`. + unsafe { FloatToInt::<Int>::to_int_unchecked(self) } } /// Raw transmutation to `u64`. diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 1714d2ee98e..f4a1afd436a 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -21,6 +21,21 @@ macro_rules! try_opt { }; } +#[cfg(bootstrap)] +macro_rules! unlikely { + ($e: expr) => { + $e + }; +} + +#[cfg(not(bootstrap))] +#[allow_internal_unstable(const_likely)] +macro_rules! unlikely { + ($e: expr) => { + intrinsics::unlikely($e) + }; +} + macro_rules! impl_nonzero_fmt { ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => { $( @@ -74,7 +89,8 @@ assert_eq!(size_of::<Option<core::num::", stringify!($Ty), ">>(), size_of::<", s #[rustc_const_stable(feature = "nonzero", since = "1.34.0")] #[inline] pub const unsafe fn new_unchecked(n: $Int) -> Self { - Self(n) + // SAFETY: this is guaranteed to be safe by the caller. + unsafe { Self(n) } } /// Creates a non-zero if the given value is not zero. @@ -457,13 +473,13 @@ $EndFeature, " Basic usage: ``` -", $Feature, "#![feature(leading_trailing_ones)] -let n = -1", stringify!($SelfT), "; +", $Feature, "let n = -1", stringify!($SelfT), "; assert_eq!(n.leading_ones(), ", stringify!($BITS), ");", $EndFeature, " ```"), - #[unstable(feature = "leading_trailing_ones", issue = "57969")] + #[stable(feature = "leading_trailing_ones", since = "1.46.0")] + #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")] #[inline] pub const fn leading_ones(self) -> u32 { (self as $UnsignedT).leading_ones() @@ -478,13 +494,13 @@ $EndFeature, " Basic usage: ``` -", $Feature, "#![feature(leading_trailing_ones)] -let n = 3", stringify!($SelfT), "; +", $Feature, "let n = 3", stringify!($SelfT), "; assert_eq!(n.trailing_ones(), 2);", $EndFeature, " ```"), - #[unstable(feature = "leading_trailing_ones", issue = "57969")] + #[stable(feature = "leading_trailing_ones", since = "1.46.0")] + #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")] #[inline] pub const fn trailing_ones(self) -> u32 { (self as $UnsignedT).trailing_ones() @@ -745,7 +761,7 @@ $EndFeature, " #[inline] pub const fn checked_add(self, rhs: Self) -> Option<Self> { let (a, b) = self.overflowing_add(rhs); - if b {None} else {Some(a)} + if unlikely!(b) {None} else {Some(a)} } } @@ -762,7 +778,9 @@ cannot occur. This results in undefined behavior when `self + rhs > ", stringify without modifying the original"] #[inline] pub unsafe fn unchecked_add(self, rhs: Self) -> Self { - intrinsics::unchecked_add(self, rhs) + // SAFETY: the caller must uphold the safety contract for + // `unchecked_add`. + unsafe { intrinsics::unchecked_add(self, rhs) } } } @@ -787,7 +805,7 @@ $EndFeature, " #[inline] pub const fn checked_sub(self, rhs: Self) -> Option<Self> { let (a, b) = self.overflowing_sub(rhs); - if b {None} else {Some(a)} + if unlikely!(b) {None} else {Some(a)} } } @@ -804,7 +822,9 @@ cannot occur. This results in undefined behavior when `self - rhs > ", stringify without modifying the original"] #[inline] pub unsafe fn unchecked_sub(self, rhs: Self) -> Self { - intrinsics::unchecked_sub(self, rhs) + // SAFETY: the caller must uphold the safety contract for + // `unchecked_sub`. + unsafe { intrinsics::unchecked_sub(self, rhs) } } } @@ -829,7 +849,7 @@ $EndFeature, " #[inline] pub const fn checked_mul(self, rhs: Self) -> Option<Self> { let (a, b) = self.overflowing_mul(rhs); - if b {None} else {Some(a)} + if unlikely!(b) {None} else {Some(a)} } } @@ -846,7 +866,9 @@ cannot occur. This results in undefined behavior when `self * rhs > ", stringify without modifying the original"] #[inline] pub unsafe fn unchecked_mul(self, rhs: Self) -> Self { - intrinsics::unchecked_mul(self, rhs) + // SAFETY: the caller must uphold the safety contract for + // `unchecked_mul`. + unsafe { intrinsics::unchecked_mul(self, rhs) } } } @@ -871,7 +893,7 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn checked_div(self, rhs: Self) -> Option<Self> { - if rhs == 0 || (self == Self::MIN && rhs == -1) { + if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) { None } else { // SAFETY: div by zero and by INT_MIN have been checked above @@ -900,7 +922,7 @@ assert_eq!((1", stringify!($SelfT), ").checked_div_euclid(0), None); without modifying the original"] #[inline] pub const fn checked_div_euclid(self, rhs: Self) -> Option<Self> { - if rhs == 0 || (self == Self::MIN && rhs == -1) { + if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) { None } else { Some(self.div_euclid(rhs)) @@ -929,7 +951,7 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn checked_rem(self, rhs: Self) -> Option<Self> { - if rhs == 0 || (self == Self::MIN && rhs == -1) { + if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) { None } else { // SAFETY: div by zero and by INT_MIN have been checked above @@ -957,7 +979,7 @@ assert_eq!(", stringify!($SelfT), "::MIN.checked_rem_euclid(-1), None); without modifying the original"] #[inline] pub const fn checked_rem_euclid(self, rhs: Self) -> Option<Self> { - if rhs == 0 || (self == Self::MIN && rhs == -1) { + if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) { None } else { Some(self.rem_euclid(rhs)) @@ -983,7 +1005,7 @@ $EndFeature, " #[inline] pub const fn checked_neg(self) -> Option<Self> { let (a, b) = self.overflowing_neg(); - if b {None} else {Some(a)} + if unlikely!(b) {None} else {Some(a)} } } @@ -1007,7 +1029,7 @@ $EndFeature, " #[inline] pub const fn checked_shl(self, rhs: u32) -> Option<Self> { let (a, b) = self.overflowing_shl(rhs); - if b {None} else {Some(a)} + if unlikely!(b) {None} else {Some(a)} } } @@ -1031,7 +1053,7 @@ $EndFeature, " #[inline] pub const fn checked_shr(self, rhs: u32) -> Option<Self> { let (a, b) = self.overflowing_shr(rhs); - if b {None} else {Some(a)} + if unlikely!(b) {None} else {Some(a)} } } @@ -1738,7 +1760,7 @@ $EndFeature, " #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { - if self == Self::MIN && rhs == -1 { + if unlikely!(self == Self::MIN && rhs == -1) { (self, true) } else { (self / rhs, false) @@ -1771,7 +1793,7 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euclid(-1), (", stringi #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { - if self == Self::MIN && rhs == -1 { + if unlikely!(self == Self::MIN && rhs == -1) { (self, true) } else { (self.div_euclid(rhs), false) @@ -1805,7 +1827,7 @@ $EndFeature, " #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { - if self == Self::MIN && rhs == -1 { + if unlikely!(self == Self::MIN && rhs == -1) { (0, true) } else { (self % rhs, false) @@ -1838,7 +1860,7 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem_euclid(-1), (0, true)); without modifying the original"] #[inline] pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { - if self == Self::MIN && rhs == -1 { + if unlikely!(self == Self::MIN && rhs == -1) { (0, true) } else { (self.rem_euclid(rhs), false) @@ -1869,7 +1891,7 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_neg(), (", stringify!($Self #[allow(unused_attributes)] #[cfg_attr(bootstrap, allow_internal_unstable(const_if_match))] pub const fn overflowing_neg(self) -> (Self, bool) { - if self == Self::MIN { + if unlikely!(self == Self::MIN) { (Self::MIN, true) } else { (-self, false) @@ -2695,12 +2717,12 @@ assert_eq!(n.trailing_zeros(), 3);", $EndFeature, " Basic usage: ``` -", $Feature, "#![feature(leading_trailing_ones)] -let n = !(", stringify!($SelfT), "::MAX >> 2); +", $Feature, "let n = !(", stringify!($SelfT), "::MAX >> 2); assert_eq!(n.leading_ones(), 2);", $EndFeature, " ```"), - #[unstable(feature = "leading_trailing_ones", issue = "57969")] + #[stable(feature = "leading_trailing_ones", since = "1.46.0")] + #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")] #[inline] pub const fn leading_ones(self) -> u32 { (!self).leading_zeros() @@ -2716,12 +2738,12 @@ of `self`. Basic usage: ``` -", $Feature, "#![feature(leading_trailing_ones)] -let n = 0b1010111", stringify!($SelfT), "; +", $Feature, "let n = 0b1010111", stringify!($SelfT), "; assert_eq!(n.trailing_ones(), 3);", $EndFeature, " ```"), - #[unstable(feature = "leading_trailing_ones", issue = "57969")] + #[stable(feature = "leading_trailing_ones", since = "1.46.0")] + #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")] #[inline] pub const fn trailing_ones(self) -> u32 { (!self).trailing_zeros() @@ -2981,7 +3003,7 @@ assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(3), None);", $EndFeat #[inline] pub const fn checked_add(self, rhs: Self) -> Option<Self> { let (a, b) = self.overflowing_add(rhs); - if b {None} else {Some(a)} + if unlikely!(b) {None} else {Some(a)} } } @@ -2998,7 +3020,9 @@ cannot occur. This results in undefined behavior when `self + rhs > ", stringify without modifying the original"] #[inline] pub unsafe fn unchecked_add(self, rhs: Self) -> Self { - intrinsics::unchecked_add(self, rhs) + // SAFETY: the caller must uphold the safety contract for + // `unchecked_add`. + unsafe { intrinsics::unchecked_add(self, rhs) } } } @@ -3021,7 +3045,7 @@ assert_eq!(0", stringify!($SelfT), ".checked_sub(1), None);", $EndFeature, " #[inline] pub const fn checked_sub(self, rhs: Self) -> Option<Self> { let (a, b) = self.overflowing_sub(rhs); - if b {None} else {Some(a)} + if unlikely!(b) {None} else {Some(a)} } } @@ -3038,7 +3062,9 @@ cannot occur. This results in undefined behavior when `self - rhs > ", stringify without modifying the original"] #[inline] pub unsafe fn unchecked_sub(self, rhs: Self) -> Self { - intrinsics::unchecked_sub(self, rhs) + // SAFETY: the caller must uphold the safety contract for + // `unchecked_sub`. + unsafe { intrinsics::unchecked_sub(self, rhs) } } } @@ -3061,7 +3087,7 @@ assert_eq!(", stringify!($SelfT), "::MAX.checked_mul(2), None);", $EndFeature, " #[inline] pub const fn checked_mul(self, rhs: Self) -> Option<Self> { let (a, b) = self.overflowing_mul(rhs); - if b {None} else {Some(a)} + if unlikely!(b) {None} else {Some(a)} } } @@ -3078,7 +3104,9 @@ cannot occur. This results in undefined behavior when `self * rhs > ", stringify without modifying the original"] #[inline] pub unsafe fn unchecked_mul(self, rhs: Self) -> Self { - intrinsics::unchecked_mul(self, rhs) + // SAFETY: the caller must uphold the safety contract for + // `unchecked_mul`. + unsafe { intrinsics::unchecked_mul(self, rhs) } } } @@ -3100,11 +3128,12 @@ assert_eq!(1", stringify!($SelfT), ".checked_div(0), None);", $EndFeature, " without modifying the original"] #[inline] pub const fn checked_div(self, rhs: Self) -> Option<Self> { - match rhs { - 0 => None, + if unlikely!(rhs == 0) { + None + } else { // SAFETY: div by zero has been checked above and unsigned types have no other // failure modes for division - rhs => Some(unsafe { intrinsics::unchecked_div(self, rhs) }), + Some(unsafe { intrinsics::unchecked_div(self, rhs) }) } } } @@ -3127,7 +3156,7 @@ assert_eq!(1", stringify!($SelfT), ".checked_div_euclid(0), None); without modifying the original"] #[inline] pub const fn checked_div_euclid(self, rhs: Self) -> Option<Self> { - if rhs == 0 { + if unlikely!(rhs == 0) { None } else { Some(self.div_euclid(rhs)) @@ -3154,7 +3183,7 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);", $EndFeature, " without modifying the original"] #[inline] pub const fn checked_rem(self, rhs: Self) -> Option<Self> { - if rhs == 0 { + if unlikely!(rhs == 0) { None } else { // SAFETY: div by zero has been checked above and unsigned types have no other @@ -3182,7 +3211,7 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None); without modifying the original"] #[inline] pub const fn checked_rem_euclid(self, rhs: Self) -> Option<Self> { - if rhs == 0 { + if unlikely!(rhs == 0) { None } else { Some(self.rem_euclid(rhs)) @@ -3209,7 +3238,7 @@ assert_eq!(1", stringify!($SelfT), ".checked_neg(), None);", $EndFeature, " #[inline] pub const fn checked_neg(self) -> Option<Self> { let (a, b) = self.overflowing_neg(); - if b {None} else {Some(a)} + if unlikely!(b) {None} else {Some(a)} } } @@ -3232,7 +3261,7 @@ assert_eq!(0x10", stringify!($SelfT), ".checked_shl(129), None);", $EndFeature, #[inline] pub const fn checked_shl(self, rhs: u32) -> Option<Self> { let (a, b) = self.overflowing_shl(rhs); - if b {None} else {Some(a)} + if unlikely!(b) {None} else {Some(a)} } } @@ -3255,7 +3284,7 @@ assert_eq!(0x10", stringify!($SelfT), ".checked_shr(129), None);", $EndFeature, #[inline] pub const fn checked_shr(self, rhs: u32) -> Option<Self> { let (a, b) = self.overflowing_shr(rhs); - if b {None} else {Some(a)} + if unlikely!(b) {None} else {Some(a)} } } diff --git a/src/libcore/panic.rs b/src/libcore/panic.rs index c7009b76e81..543aa969330 100644 --- a/src/libcore/panic.rs +++ b/src/libcore/panic.rs @@ -190,7 +190,6 @@ impl<'a> Location<'a> { /// # Examples /// /// ``` - /// #![feature(track_caller)] /// use core::panic::Location; /// /// /// Returns the [`Location`] at which it is called. @@ -206,7 +205,7 @@ impl<'a> Location<'a> { /// /// let fixed_location = get_just_one_location(); /// assert_eq!(fixed_location.file(), file!()); - /// assert_eq!(fixed_location.line(), 15); + /// assert_eq!(fixed_location.line(), 14); /// assert_eq!(fixed_location.column(), 5); /// /// // running the same untracked function in a different location gives us the same result @@ -217,7 +216,7 @@ impl<'a> Location<'a> { /// /// let this_location = get_caller_location(); /// assert_eq!(this_location.file(), file!()); - /// assert_eq!(this_location.line(), 29); + /// assert_eq!(this_location.line(), 28); /// assert_eq!(this_location.column(), 21); /// /// // running the tracked function in a different location produces a different value @@ -226,13 +225,8 @@ impl<'a> Location<'a> { /// assert_ne!(this_location.line(), another_location.line()); /// assert_ne!(this_location.column(), another_location.column()); /// ``` - // FIXME: When stabilizing this method, please also update the documentation - // of `intrinsics::caller_location`. - #[unstable( - feature = "track_caller", - reason = "uses #[track_caller] which is not yet stable", - issue = "47809" - )] + #[stable(feature = "track_caller", since = "1.46.0")] + #[rustc_const_unstable(feature = "const_caller_location", issue = "47809")] #[track_caller] pub const fn caller() -> &'static Location<'static> { crate::intrinsics::caller_location() diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 6f5bf7ad9da..da299f026f8 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -679,7 +679,10 @@ impl<'a, T: ?Sized> Pin<&'a T> { { let pointer = &*self.pointer; let new_pointer = func(pointer); - Pin::new_unchecked(new_pointer) + + // SAFETY: the safety contract for `new_unchecked` must be + // upheld by the caller. + unsafe { Pin::new_unchecked(new_pointer) } } /// Gets a shared reference out of a pin. @@ -769,9 +772,13 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { U: ?Sized, F: FnOnce(&mut T) -> &mut U, { - let pointer = Pin::get_unchecked_mut(self); + // SAFETY: the caller is responsible for not moving the + // value out of this reference. + let pointer = unsafe { Pin::get_unchecked_mut(self) }; let new_pointer = func(pointer); - Pin::new_unchecked(new_pointer) + // SAFETY: as the value of `this` is guaranteed to not have + // been moved out, this call to `new_unchecked` is safe. + unsafe { Pin::new_unchecked(new_pointer) } } } diff --git a/src/libcore/ptr/const_ptr.rs b/src/libcore/ptr/const_ptr.rs index 64a506a6377..d1d7a715238 100644 --- a/src/libcore/ptr/const_ptr.rs +++ b/src/libcore/ptr/const_ptr.rs @@ -95,7 +95,9 @@ impl<T: ?Sized> *const T { #[stable(feature = "ptr_as_ref", since = "1.9.0")] #[inline] pub unsafe fn as_ref<'a>(self) -> Option<&'a T> { - if self.is_null() { None } else { Some(&*self) } + // SAFETY: the caller must guarantee that `self` is valid + // for a reference if it isn't null. + if self.is_null() { None } else { unsafe { Some(&*self) } } } /// Calculates the offset from a pointer. @@ -157,7 +159,8 @@ impl<T: ?Sized> *const T { where T: Sized, { - intrinsics::offset(self, count) + // SAFETY: the caller must uphold the safety contract for `offset`. + unsafe { intrinsics::offset(self, count) } } /// Calculates the offset from a pointer using wrapping arithmetic. @@ -292,7 +295,8 @@ impl<T: ?Sized> *const T { { let pointee_size = mem::size_of::<T>(); assert!(0 < pointee_size && pointee_size <= isize::MAX as usize); - intrinsics::ptr_offset_from(self, origin) + // SAFETY: the caller must uphold the safety contract for `ptr_offset_from`. + unsafe { intrinsics::ptr_offset_from(self, origin) } } /// Returns whether two pointers are guaranteed to be equal. @@ -471,7 +475,8 @@ impl<T: ?Sized> *const T { where T: Sized, { - self.offset(count as isize) + // SAFETY: the caller must uphold the safety contract for `offset`. + unsafe { self.offset(count as isize) } } /// Calculates the offset from a pointer (convenience for @@ -534,7 +539,8 @@ impl<T: ?Sized> *const T { where T: Sized, { - self.offset((count as isize).wrapping_neg()) + // SAFETY: the caller must uphold the safety contract for `offset`. + unsafe { self.offset((count as isize).wrapping_neg()) } } /// Calculates the offset from a pointer using wrapping arithmetic. @@ -663,7 +669,8 @@ impl<T: ?Sized> *const T { where T: Sized, { - read(self) + // SAFETY: the caller must uphold the safety contract for `read`. + unsafe { read(self) } } /// Performs a volatile read of the value from `self` without moving it. This @@ -682,7 +689,8 @@ impl<T: ?Sized> *const T { where T: Sized, { - read_volatile(self) + // SAFETY: the caller must uphold the safety contract for `read_volatile`. + unsafe { read_volatile(self) } } /// Reads the value from `self` without moving it. This leaves the @@ -699,7 +707,8 @@ impl<T: ?Sized> *const T { where T: Sized, { - read_unaligned(self) + // SAFETY: the caller must uphold the safety contract for `read_unaligned`. + unsafe { read_unaligned(self) } } /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source @@ -716,7 +725,8 @@ impl<T: ?Sized> *const T { where T: Sized, { - copy(self, dest, count) + // SAFETY: the caller must uphold the safety contract for `copy`. + unsafe { copy(self, dest, count) } } /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source @@ -733,7 +743,8 @@ impl<T: ?Sized> *const T { where T: Sized, { - copy_nonoverlapping(self, dest, count) + // SAFETY: the caller must uphold the safety contract for `copy_nonoverlapping`. + unsafe { copy_nonoverlapping(self, dest, count) } } /// Computes the offset that needs to be applied to the pointer in order to make it aligned to diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs index ca2b0c85ec1..5f028f9ea76 100644 --- a/src/libcore/ptr/mod.rs +++ b/src/libcore/ptr/mod.rs @@ -184,7 +184,9 @@ mod mut_ptr; pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) { // Code here does not matter - this is replaced by the // real drop glue by the compiler. - drop_in_place(to_drop) + + // SAFETY: see comment above + unsafe { drop_in_place(to_drop) } } /// Creates a null raw pointer. @@ -374,9 +376,15 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) { let mut tmp = MaybeUninit::<T>::uninit(); // Perform the swap - copy_nonoverlapping(x, tmp.as_mut_ptr(), 1); - copy(y, x, 1); // `x` and `y` may overlap - copy_nonoverlapping(tmp.as_ptr(), y, 1); + // SAFETY: the caller must guarantee that `x` and `y` are + // valid for writes and properly aligned. `tmp` cannot be + // overlapping either `x` or `y` because `tmp` was just allocated + // on the stack as a separate allocated object. + unsafe { + copy_nonoverlapping(x, tmp.as_mut_ptr(), 1); + copy(y, x, 1); // `x` and `y` may overlap + copy_nonoverlapping(tmp.as_ptr(), y, 1); + } } /// Swaps `count * size_of::<T>()` bytes between the two regions of memory @@ -432,7 +440,9 @@ pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) { let x = x as *mut u8; let y = y as *mut u8; let len = mem::size_of::<T>() * count; - swap_nonoverlapping_bytes(x, y, len) + // SAFETY: the caller must guarantee that `x` and `y` are + // valid for writes and properly aligned. + unsafe { swap_nonoverlapping_bytes(x, y, len) } } #[inline] @@ -440,11 +450,16 @@ pub(crate) unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) { // For types smaller than the block optimization below, // just swap directly to avoid pessimizing codegen. if mem::size_of::<T>() < 32 { - let z = read(x); - copy_nonoverlapping(y, x, 1); - write(y, z); + // SAFETY: the caller must guarantee that `x` and `y` are valid + // for writes, properly aligned, and non-overlapping. + unsafe { + let z = read(x); + copy_nonoverlapping(y, x, 1); + write(y, z); + } } else { - swap_nonoverlapping(x, y, 1); + // SAFETY: the caller must uphold the safety contract for `swap_nonoverlapping`. + unsafe { swap_nonoverlapping(x, y, 1) }; } } @@ -471,14 +486,23 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { // Declaring `t` here avoids aligning the stack when this loop is unused let mut t = mem::MaybeUninit::<Block>::uninit(); let t = t.as_mut_ptr() as *mut u8; - let x = x.add(i); - let y = y.add(i); - // Swap a block of bytes of x & y, using t as a temporary buffer - // This should be optimized into efficient SIMD operations where available - copy_nonoverlapping(x, t, block_size); - copy_nonoverlapping(y, x, block_size); - copy_nonoverlapping(t, y, block_size); + // SAFETY: As `i < len`, and as the caller must guarantee that `x` and `y` are valid + // for `len` bytes, `x + i` and `y + i` must be valid adresses, which fulfills the + // safety contract for `add`. + // + // Also, the caller must guarantee that `x` and `y` are valid for writes, properly aligned, + // and non-overlapping, which fulfills the safety contract for `copy_nonoverlapping`. + unsafe { + let x = x.add(i); + let y = y.add(i); + + // Swap a block of bytes of x & y, using t as a temporary buffer + // This should be optimized into efficient SIMD operations where available + copy_nonoverlapping(x, t, block_size); + copy_nonoverlapping(y, x, block_size); + copy_nonoverlapping(t, y, block_size); + } i += block_size; } @@ -488,12 +512,16 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { let rem = len - i; let t = t.as_mut_ptr() as *mut u8; - let x = x.add(i); - let y = y.add(i); - copy_nonoverlapping(x, t, rem); - copy_nonoverlapping(y, x, rem); - copy_nonoverlapping(t, y, rem); + // SAFETY: see previous safety comment. + unsafe { + let x = x.add(i); + let y = y.add(i); + + copy_nonoverlapping(x, t, rem); + copy_nonoverlapping(y, x, rem); + copy_nonoverlapping(t, y, rem); + } } } @@ -540,7 +568,13 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn replace<T>(dst: *mut T, mut src: T) -> T { - mem::swap(&mut *dst, &mut src); // cannot overlap + // SAFETY: the caller must guarantee that `dst` is valid to be + // cast to a mutable reference (valid for writes, aligned, initialized), + // and cannot overlap `src` since `dst` must point to a distinct + // allocated object. + unsafe { + mem::swap(&mut *dst, &mut src); // cannot overlap + } src } @@ -658,8 +692,16 @@ pub unsafe fn replace<T>(dst: *mut T, mut src: T) -> T { pub unsafe fn read<T>(src: *const T) -> T { // `copy_nonoverlapping` takes care of debug_assert. let mut tmp = MaybeUninit::<T>::uninit(); - copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); - tmp.assume_init() + // SAFETY: the caller must guarantee that `src` is valid for reads. + // `src` cannot overlap `tmp` because `tmp` was just allocated on + // the stack as a separate allocated object. + // + // Also, since we just wrote a valid value into `tmp`, it is guaranteed + // to be properly initialized. + unsafe { + copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); + tmp.assume_init() + } } /// Reads the value from `src` without moving it. This leaves the @@ -752,8 +794,16 @@ pub unsafe fn read<T>(src: *const T) -> T { pub unsafe fn read_unaligned<T>(src: *const T) -> T { // `copy_nonoverlapping` takes care of debug_assert. let mut tmp = MaybeUninit::<T>::uninit(); - copy_nonoverlapping(src as *const u8, tmp.as_mut_ptr() as *mut u8, mem::size_of::<T>()); - tmp.assume_init() + // SAFETY: the caller must guarantee that `src` is valid for reads. + // `src` cannot overlap `tmp` because `tmp` was just allocated on + // the stack as a separate allocated object. + // + // Also, since we just wrote a valid value into `tmp`, it is guaranteed + // to be properly initialized. + unsafe { + copy_nonoverlapping(src as *const u8, tmp.as_mut_ptr() as *mut u8, mem::size_of::<T>()); + tmp.assume_init() + } } /// Overwrites a memory location with the given value without reading or @@ -847,7 +897,8 @@ pub unsafe fn write<T>(dst: *mut T, src: T) { // Not panicking to keep codegen impact smaller. abort(); } - intrinsics::move_val_init(&mut *dst, src) + // SAFETY: the caller must uphold the safety contract for `move_val_init`. + unsafe { intrinsics::move_val_init(&mut *dst, src) } } /// Overwrites a memory location with the given value without reading or @@ -939,8 +990,13 @@ pub unsafe fn write<T>(dst: *mut T, src: T) { #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) { - // `copy_nonoverlapping` takes care of debug_assert. - copy_nonoverlapping(&src as *const T as *const u8, dst as *mut u8, mem::size_of::<T>()); + // SAFETY: the caller must guarantee that `dst` is valid for writes. + // `dst` cannot overlap `src` because the caller has mutable access + // to `dst` while `src` is owned by this function. + unsafe { + // `copy_nonoverlapping` takes care of debug_assert. + copy_nonoverlapping(&src as *const T as *const u8, dst as *mut u8, mem::size_of::<T>()); + } mem::forget(src); } @@ -1015,7 +1071,8 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T { // Not panicking to keep codegen impact smaller. abort(); } - intrinsics::volatile_load(src) + // SAFETY: the caller must uphold the safety contract for `volatile_load`. + unsafe { intrinsics::volatile_load(src) } } /// Performs a volatile write of a memory location with the given value without @@ -1087,7 +1144,10 @@ pub unsafe fn write_volatile<T>(dst: *mut T, src: T) { // Not panicking to keep codegen impact smaller. abort(); } - intrinsics::volatile_store(dst, src); + // SAFETY: the caller must uphold the safety contract for `volatile_store`. + unsafe { + intrinsics::volatile_store(dst, src); + } } /// Align pointer `p`. @@ -1173,8 +1233,8 @@ pub(crate) unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usize { } let smoda = stride & a_minus_one; - // a is power-of-two so cannot be 0. stride = 0 is handled above. - let gcdpow = intrinsics::cttz_nonzero(stride).min(intrinsics::cttz_nonzero(a)); + // SAFETY: a is power-of-two so cannot be 0. stride = 0 is handled above. + let gcdpow = unsafe { intrinsics::cttz_nonzero(stride).min(intrinsics::cttz_nonzero(a)) }; let gcd = 1usize << gcdpow; if p as usize & (gcd.wrapping_sub(1)) == 0 { diff --git a/src/libcore/ptr/mut_ptr.rs b/src/libcore/ptr/mut_ptr.rs index 6b5cd9fdb85..7d4b6339b51 100644 --- a/src/libcore/ptr/mut_ptr.rs +++ b/src/libcore/ptr/mut_ptr.rs @@ -89,7 +89,9 @@ impl<T: ?Sized> *mut T { #[stable(feature = "ptr_as_ref", since = "1.9.0")] #[inline] pub unsafe fn as_ref<'a>(self) -> Option<&'a T> { - if self.is_null() { None } else { Some(&*self) } + // SAFETY: the caller must guarantee that `self` is valid for a + // reference if it isn't null. + if self.is_null() { None } else { unsafe { Some(&*self) } } } /// Calculates the offset from a pointer. @@ -151,7 +153,10 @@ impl<T: ?Sized> *mut T { where T: Sized, { - intrinsics::offset(self, count) as *mut T + // SAFETY: the caller must uphold the safety contract for `offset`. + // The obtained pointer is valid for writes since the caller must + // guarantee that it points to the same allocated object as `self`. + unsafe { intrinsics::offset(self, count) as *mut T } } /// Calculates the offset from a pointer using wrapping arithmetic. @@ -270,7 +275,9 @@ impl<T: ?Sized> *mut T { #[stable(feature = "ptr_as_ref", since = "1.9.0")] #[inline] pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> { - if self.is_null() { None } else { Some(&mut *self) } + // SAFETY: the caller must guarantee that `self` is be valid for + // a mutable reference if it isn't null. + if self.is_null() { None } else { unsafe { Some(&mut *self) } } } /// Returns whether two pointers are guaranteed to be equal. @@ -406,7 +413,8 @@ impl<T: ?Sized> *mut T { where T: Sized, { - (self as *const T).offset_from(origin) + // SAFETY: the caller must uphold the safety contract for `offset_from`. + unsafe { (self as *const T).offset_from(origin) } } /// Calculates the distance between two pointers. The returned value is in @@ -518,7 +526,8 @@ impl<T: ?Sized> *mut T { where T: Sized, { - self.offset(count as isize) + // SAFETY: the caller must uphold the safety contract for `offset`. + unsafe { self.offset(count as isize) } } /// Calculates the offset from a pointer (convenience for @@ -581,7 +590,8 @@ impl<T: ?Sized> *mut T { where T: Sized, { - self.offset((count as isize).wrapping_neg()) + // SAFETY: the caller must uphold the safety contract for `offset`. + unsafe { self.offset((count as isize).wrapping_neg()) } } /// Calculates the offset from a pointer using wrapping arithmetic. @@ -710,7 +720,8 @@ impl<T: ?Sized> *mut T { where T: Sized, { - read(self) + // SAFETY: the caller must uphold the safety contract for ``. + unsafe { read(self) } } /// Performs a volatile read of the value from `self` without moving it. This @@ -729,7 +740,8 @@ impl<T: ?Sized> *mut T { where T: Sized, { - read_volatile(self) + // SAFETY: the caller must uphold the safety contract for `read_volatile`. + unsafe { read_volatile(self) } } /// Reads the value from `self` without moving it. This leaves the @@ -746,7 +758,8 @@ impl<T: ?Sized> *mut T { where T: Sized, { - read_unaligned(self) + // SAFETY: the caller must uphold the safety contract for `read_unaligned`. + unsafe { read_unaligned(self) } } /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source @@ -763,7 +776,8 @@ impl<T: ?Sized> *mut T { where T: Sized, { - copy(self, dest, count) + // SAFETY: the caller must uphold the safety contract for `copy`. + unsafe { copy(self, dest, count) } } /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source @@ -780,7 +794,8 @@ impl<T: ?Sized> *mut T { where T: Sized, { - copy_nonoverlapping(self, dest, count) + // SAFETY: the caller must uphold the safety contract for `copy_nonoverlapping`. + unsafe { copy_nonoverlapping(self, dest, count) } } /// Copies `count * size_of<T>` bytes from `src` to `self`. The source @@ -797,7 +812,8 @@ impl<T: ?Sized> *mut T { where T: Sized, { - copy(src, self, count) + // SAFETY: the caller must uphold the safety contract for `copy`. + unsafe { copy(src, self, count) } } /// Copies `count * size_of<T>` bytes from `src` to `self`. The source @@ -814,7 +830,8 @@ impl<T: ?Sized> *mut T { where T: Sized, { - copy_nonoverlapping(src, self, count) + // SAFETY: the caller must uphold the safety contract for `copy_nonoverlapping`. + unsafe { copy_nonoverlapping(src, self, count) } } /// Executes the destructor (if any) of the pointed-to value. @@ -825,7 +842,8 @@ impl<T: ?Sized> *mut T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn drop_in_place(self) { - drop_in_place(self) + // SAFETY: the caller must uphold the safety contract for `drop_in_place`. + unsafe { drop_in_place(self) } } /// Overwrites a memory location with the given value without reading or @@ -840,7 +858,8 @@ impl<T: ?Sized> *mut T { where T: Sized, { - write(self, val) + // SAFETY: the caller must uphold the safety contract for `write`. + unsafe { write(self, val) } } /// Invokes memset on the specified pointer, setting `count * size_of::<T>()` @@ -855,7 +874,8 @@ impl<T: ?Sized> *mut T { where T: Sized, { - write_bytes(self, val, count) + // SAFETY: the caller must uphold the safety contract for `write_bytes`. + unsafe { write_bytes(self, val, count) } } /// Performs a volatile write of a memory location with the given value without @@ -874,7 +894,8 @@ impl<T: ?Sized> *mut T { where T: Sized, { - write_volatile(self, val) + // SAFETY: the caller must uphold the safety contract for `write_volatile`. + unsafe { write_volatile(self, val) } } /// Overwrites a memory location with the given value without reading or @@ -891,7 +912,8 @@ impl<T: ?Sized> *mut T { where T: Sized, { - write_unaligned(self, val) + // SAFETY: the caller must uphold the safety contract for `write_unaligned`. + unsafe { write_unaligned(self, val) } } /// Replaces the value at `self` with `src`, returning the old @@ -906,7 +928,8 @@ impl<T: ?Sized> *mut T { where T: Sized, { - replace(self, src) + // SAFETY: the caller must uphold the safety contract for `replace`. + unsafe { replace(self, src) } } /// Swaps the values at two mutable locations of the same type, without @@ -922,7 +945,8 @@ impl<T: ?Sized> *mut T { where T: Sized, { - swap(self, with) + // SAFETY: the caller must uphold the safety contract for `swap`. + unsafe { swap(self, with) } } /// Computes the offset that needs to be applied to the pointer in order to make it aligned to diff --git a/src/libcore/ptr/non_null.rs b/src/libcore/ptr/non_null.rs index 870364a61dd..c2d31bfb6a4 100644 --- a/src/libcore/ptr/non_null.rs +++ b/src/libcore/ptr/non_null.rs @@ -87,7 +87,8 @@ impl<T: ?Sized> NonNull<T> { #[rustc_const_stable(feature = "const_nonnull_new_unchecked", since = "1.32.0")] #[inline] pub const unsafe fn new_unchecked(ptr: *mut T) -> Self { - NonNull { pointer: ptr as _ } + // SAFETY: the caller must guarantee that `ptr` is non-null. + unsafe { NonNull { pointer: ptr as _ } } } /// Creates a new `NonNull` if `ptr` is non-null. @@ -118,7 +119,9 @@ impl<T: ?Sized> NonNull<T> { #[stable(feature = "nonnull", since = "1.25.0")] #[inline] pub unsafe fn as_ref(&self) -> &T { - &*self.as_ptr() + // SAFETY: the caller must guarantee that `self` meets all the + // requirements for a reference. + unsafe { &*self.as_ptr() } } /// Mutably dereferences the content. @@ -129,7 +132,9 @@ impl<T: ?Sized> NonNull<T> { #[stable(feature = "nonnull", since = "1.25.0")] #[inline] pub unsafe fn as_mut(&mut self) -> &mut T { - &mut *self.as_ptr() + // SAFETY: the caller must guarantee that `self` meets all the + // requirements for a mutable reference. + unsafe { &mut *self.as_ptr() } } /// Casts to a pointer of another type. diff --git a/src/libcore/ptr/unique.rs b/src/libcore/ptr/unique.rs index f58d35f0613..78647eee338 100644 --- a/src/libcore/ptr/unique.rs +++ b/src/libcore/ptr/unique.rs @@ -87,7 +87,8 @@ impl<T: ?Sized> Unique<T> { /// `ptr` must be non-null. #[inline] pub const unsafe fn new_unchecked(ptr: *mut T) -> Self { - Unique { pointer: ptr as _, _marker: PhantomData } + // SAFETY: the caller must guarantee that `ptr` is non-null. + unsafe { Unique { pointer: ptr as _, _marker: PhantomData } } } /// Creates a new `Unique` if `ptr` is non-null. @@ -114,7 +115,9 @@ impl<T: ?Sized> Unique<T> { /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`. #[inline] pub unsafe fn as_ref(&self) -> &T { - &*self.as_ptr() + // SAFETY: the caller must guarantee that `self` meets all the + // requirements for a reference. + unsafe { &*self.as_ptr() } } /// Mutably dereferences the content. @@ -124,7 +127,9 @@ impl<T: ?Sized> Unique<T> { /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`. #[inline] pub unsafe fn as_mut(&mut self) -> &mut T { - &mut *self.as_ptr() + // SAFETY: the caller must guarantee that `self` meets all the + // requirements for a mutable reference. + unsafe { &mut *self.as_ptr() } } /// Casts to a pointer of another type. diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 6a50cdbc1d9..e7a2d7adede 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -310,7 +310,8 @@ impl<T> [T] { where I: SliceIndex<Self>, { - index.get_unchecked(self) + // SAFETY: the caller must uphold the safety requirements for `get_unchecked`. + unsafe { index.get_unchecked(self) } } /// Returns a mutable reference to an element or subslice, without doing @@ -341,7 +342,8 @@ impl<T> [T] { where I: SliceIndex<Self>, { - index.get_unchecked_mut(self) + // SAFETY: the caller must uphold the safety requirements for `get_unchecked_mut`. + unsafe { index.get_unchecked_mut(self) } } /// Returns a raw pointer to the slice's buffer. @@ -1459,6 +1461,68 @@ impl<T> [T] { m >= n && needle == &self[m - n..] } + /// Returns a subslice with the prefix removed. + /// + /// This method returns [`None`] if slice does not start with `prefix`. + /// Also it returns the original slice if `prefix` is an empty slice. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_strip)] + /// let v = &[10, 40, 30]; + /// assert_eq!(v.strip_prefix(&[10]), Some(&[40, 30][..])); + /// assert_eq!(v.strip_prefix(&[10, 40]), Some(&[30][..])); + /// assert_eq!(v.strip_prefix(&[50]), None); + /// assert_eq!(v.strip_prefix(&[10, 50]), None); + /// ``` + #[must_use = "returns the subslice without modifying the original"] + #[unstable(feature = "slice_strip", issue = "73413")] + pub fn strip_prefix(&self, prefix: &[T]) -> Option<&[T]> + where + T: PartialEq, + { + let n = prefix.len(); + if n <= self.len() { + let (head, tail) = self.split_at(n); + if head == prefix { + return Some(tail); + } + } + None + } + + /// Returns a subslice with the suffix removed. + /// + /// This method returns [`None`] if slice does not end with `suffix`. + /// Also it returns the original slice if `suffix` is an empty slice + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_strip)] + /// let v = &[10, 40, 30]; + /// assert_eq!(v.strip_suffix(&[30]), Some(&[10, 40][..])); + /// assert_eq!(v.strip_suffix(&[40, 30]), Some(&[10][..])); + /// assert_eq!(v.strip_suffix(&[50]), None); + /// assert_eq!(v.strip_suffix(&[50, 30]), None); + /// ``` + #[must_use = "returns the subslice without modifying the original"] + #[unstable(feature = "slice_strip", issue = "73413")] + pub fn strip_suffix(&self, suffix: &[T]) -> Option<&[T]> + where + T: PartialEq, + { + let (len, n) = (self.len(), suffix.len()); + if n <= len { + let (head, tail) = self.split_at(len - n); + if tail == suffix { + return Some(head); + } + } + None + } + /// Binary searches this sorted slice for a given element. /// /// If the value is found then [`Result::Ok`] is returned, containing the @@ -2519,18 +2583,21 @@ impl<T> [T] { // First, find at what point do we split between the first and 2nd slice. Easy with // ptr.align_offset. let ptr = self.as_ptr(); - let offset = crate::ptr::align_offset(ptr, mem::align_of::<U>()); + let offset = unsafe { crate::ptr::align_offset(ptr, mem::align_of::<U>()) }; if offset > self.len() { (self, &[], &[]) } else { let (left, rest) = self.split_at(offset); - // now `rest` is definitely aligned, so `from_raw_parts_mut` below is okay let (us_len, ts_len) = rest.align_to_offsets::<U>(); - ( - left, - from_raw_parts(rest.as_ptr() as *const U, us_len), - from_raw_parts(rest.as_ptr().add(rest.len() - ts_len), ts_len), - ) + // SAFETY: now `rest` is definitely aligned, so `from_raw_parts` below is okay, + // since the caller guarantees that we can transmute `T` to `U` safely. + unsafe { + ( + left, + from_raw_parts(rest.as_ptr() as *const U, us_len), + from_raw_parts(rest.as_ptr().add(rest.len() - ts_len), ts_len), + ) + } } } @@ -2575,21 +2642,23 @@ impl<T> [T] { // First, find at what point do we split between the first and 2nd slice. Easy with // ptr.align_offset. let ptr = self.as_ptr(); - let offset = crate::ptr::align_offset(ptr, mem::align_of::<U>()); + let offset = unsafe { crate::ptr::align_offset(ptr, mem::align_of::<U>()) }; if offset > self.len() { (self, &mut [], &mut []) } else { let (left, rest) = self.split_at_mut(offset); - // now `rest` is definitely aligned, so `from_raw_parts_mut` below is okay let (us_len, ts_len) = rest.align_to_offsets::<U>(); let rest_len = rest.len(); let mut_ptr = rest.as_mut_ptr(); // We can't use `rest` again after this, that would invalidate its alias `mut_ptr`! - ( - left, - from_raw_parts_mut(mut_ptr as *mut U, us_len), - from_raw_parts_mut(mut_ptr.add(rest_len - ts_len), ts_len), - ) + // SAFETY: see comments for `align_to`. + unsafe { + ( + left, + from_raw_parts_mut(mut_ptr as *mut U, us_len), + from_raw_parts_mut(mut_ptr.add(rest_len - ts_len), ts_len), + ) + } } } @@ -2914,12 +2983,18 @@ impl<T> SliceIndex<[T]> for usize { #[inline] unsafe fn get_unchecked(self, slice: &[T]) -> &T { - &*slice.as_ptr().add(self) + // SAFETY: `slice` cannot be longer than `isize::MAX` and + // the caller guarantees that `self` is in bounds of `slice` + // so `self` cannot overflow an `isize`, so the call to `add` is safe. + // The obtained pointer comes from a reference which is guaranteed + // to be valid. + unsafe { &*slice.as_ptr().add(self) } } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut T { - &mut *slice.as_mut_ptr().add(self) + // SAFETY: see comments for `get_unchecked` above. + unsafe { &mut *slice.as_mut_ptr().add(self) } } #[inline] @@ -2959,12 +3034,18 @@ impl<T> SliceIndex<[T]> for ops::Range<usize> { #[inline] unsafe fn get_unchecked(self, slice: &[T]) -> &[T] { - from_raw_parts(slice.as_ptr().add(self.start), self.end - self.start) + // SAFETY: `slice` cannot be longer than `isize::MAX` and + // the caller guarantees that `self` is in bounds of `slice` + // so `self` cannot overflow an `isize`, so the call to `add` is safe. + // Also, since the caller guarantees that `self` is in bounds of `slice`, + // `from_raw_parts` will give a subslice of `slice` which is always safe. + unsafe { from_raw_parts(slice.as_ptr().add(self.start), self.end - self.start) } } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] { - from_raw_parts_mut(slice.as_mut_ptr().add(self.start), self.end - self.start) + // SAFETY: see comments for `get_unchecked` above. + unsafe { from_raw_parts_mut(slice.as_mut_ptr().add(self.start), self.end - self.start) } } #[inline] @@ -3004,12 +3085,14 @@ impl<T> SliceIndex<[T]> for ops::RangeTo<usize> { #[inline] unsafe fn get_unchecked(self, slice: &[T]) -> &[T] { - (0..self.end).get_unchecked(slice) + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { (0..self.end).get_unchecked(slice) } } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] { - (0..self.end).get_unchecked_mut(slice) + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { (0..self.end).get_unchecked_mut(slice) } } #[inline] @@ -3039,12 +3122,14 @@ impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> { #[inline] unsafe fn get_unchecked(self, slice: &[T]) -> &[T] { - (self.start..slice.len()).get_unchecked(slice) + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { (self.start..slice.len()).get_unchecked(slice) } } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] { - (self.start..slice.len()).get_unchecked_mut(slice) + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { (self.start..slice.len()).get_unchecked_mut(slice) } } #[inline] @@ -3113,12 +3198,14 @@ impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> { #[inline] unsafe fn get_unchecked(self, slice: &[T]) -> &[T] { - (*self.start()..self.end() + 1).get_unchecked(slice) + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { (*self.start()..self.end() + 1).get_unchecked(slice) } } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] { - (*self.start()..self.end() + 1).get_unchecked_mut(slice) + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { (*self.start()..self.end() + 1).get_unchecked_mut(slice) } } #[inline] @@ -3154,12 +3241,14 @@ impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> { #[inline] unsafe fn get_unchecked(self, slice: &[T]) -> &[T] { - (0..=self.end).get_unchecked(slice) + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { (0..=self.end).get_unchecked(slice) } } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] { - (0..=self.end).get_unchecked_mut(slice) + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { (0..=self.end).get_unchecked_mut(slice) } } #[inline] @@ -3308,7 +3397,9 @@ macro_rules! iterator { self.ptr.as_ptr() } else { let old = self.ptr.as_ptr(); - self.ptr = NonNull::new_unchecked(self.ptr.as_ptr().offset(offset)); + // SAFETY: the caller guarantees that `offset` doesn't exceed `self.len()`, + // so this new pointer is inside `self` and thus guaranteed to be non-null. + self.ptr = unsafe { NonNull::new_unchecked(self.ptr.as_ptr().offset(offset)) }; old } } @@ -3322,7 +3413,10 @@ macro_rules! iterator { zst_shrink!(self, offset); self.ptr.as_ptr() } else { - self.end = self.end.offset(-offset); + // SAFETY: the caller guarantees that `offset` doesn't exceed `self.len()`, + // which is guaranteed to not overflow an `isize`. Also, the resulting pointer + // is in bounds of `slice`, which fulfills the other requirements for `offset`. + self.end = unsafe { self.end.offset(-offset) }; self.end } } @@ -4640,7 +4734,11 @@ impl<T> FusedIterator for Windows<'_, T> {} #[doc(hidden)] unsafe impl<'a, T> TrustedRandomAccess for Windows<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] { - from_raw_parts(self.v.as_ptr().add(i), self.size) + // SAFETY: since the caller guarantees that `i` is in bounds, + // which means that `i` cannot overflow an `isize`, and the + // slice created by `from_raw_parts` is a subslice of `self.v` + // thus is guaranteed to be valid for the lifetime `'a` of `self.v`. + unsafe { from_raw_parts(self.v.as_ptr().add(i), self.size) } } fn may_have_side_effect() -> bool { false @@ -4784,7 +4882,14 @@ unsafe impl<'a, T> TrustedRandomAccess for Chunks<'a, T> { None => self.v.len(), Some(end) => cmp::min(end, self.v.len()), }; - from_raw_parts(self.v.as_ptr().add(start), end - start) + // SAFETY: the caller guarantees that `i` is in bounds, + // which means that `start` must be in bounds of the + // underlying `self.v` slice, and we made sure that `end` + // is also in bounds of `self.v`. Thus, `start` cannot overflow + // an `isize`, and the slice constructed by `from_raw_parts` + // is a subslice of `self.v` which is guaranteed to be valid + // for the lifetime `'a` of `self.v`. + unsafe { from_raw_parts(self.v.as_ptr().add(start), end - start) } } fn may_have_side_effect() -> bool { false @@ -4926,7 +5031,8 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksMut<'a, T> { None => self.v.len(), Some(end) => cmp::min(end, self.v.len()), }; - from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start) + // SAFETY: see comments for `Chunks::get_unchecked`. + unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start) } } fn may_have_side_effect() -> bool { false @@ -5063,7 +5169,8 @@ impl<T> FusedIterator for ChunksExact<'_, T> {} unsafe impl<'a, T> TrustedRandomAccess for ChunksExact<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] { let start = i * self.chunk_size; - from_raw_parts(self.v.as_ptr().add(start), self.chunk_size) + // SAFETY: mostly identical to `Chunks::get_unchecked`. + unsafe { from_raw_parts(self.v.as_ptr().add(start), self.chunk_size) } } fn may_have_side_effect() -> bool { false @@ -5197,7 +5304,8 @@ impl<T> FusedIterator for ChunksExactMut<'_, T> {} unsafe impl<'a, T> TrustedRandomAccess for ChunksExactMut<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] { let start = i * self.chunk_size; - from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size) + // SAFETY: see comments for `ChunksExactMut::get_unchecked`. + unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size) } } fn may_have_side_effect() -> bool { false @@ -5344,7 +5452,8 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunks<'a, T> { None => 0, Some(start) => start, }; - from_raw_parts(self.v.as_ptr().add(start), end - start) + // SAFETY: mostly identical to `Chunks::get_unchecked`. + unsafe { from_raw_parts(self.v.as_ptr().add(start), end - start) } } fn may_have_side_effect() -> bool { false @@ -5489,7 +5598,8 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksMut<'a, T> { None => 0, Some(start) => start, }; - from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start) + // SAFETY: see comments for `RChunks::get_unchecked`. + unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start) } } fn may_have_side_effect() -> bool { false @@ -5630,7 +5740,8 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExact<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] { let end = self.v.len() - i * self.chunk_size; let start = end - self.chunk_size; - from_raw_parts(self.v.as_ptr().add(start), self.chunk_size) + // SAFETY: mostmy identical to `Chunks::get_unchecked`. + unsafe { from_raw_parts(self.v.as_ptr().add(start), self.chunk_size) } } fn may_have_side_effect() -> bool { false @@ -5769,7 +5880,8 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExactMut<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] { let end = self.v.len() - i * self.chunk_size; let start = end - self.chunk_size; - from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size) + // SAFETY: see comments for `RChunksExact::get_unchecked`. + unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size) } } fn may_have_side_effect() -> bool { false @@ -5865,7 +5977,8 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize, "attempt to create slice covering at least half the address space" ); - &*ptr::slice_from_raw_parts(data, len) + // SAFETY: the caller must uphold the safety contract for `from_raw_parts`. + unsafe { &*ptr::slice_from_raw_parts(data, len) } } /// Performs the same functionality as [`from_raw_parts`], except that a @@ -5905,7 +6018,8 @@ pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize, "attempt to create slice covering at least half the address space" ); - &mut *ptr::slice_from_raw_parts_mut(data, len) + // SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`. + unsafe { &mut *ptr::slice_from_raw_parts_mut(data, len) } } /// Converts a reference to T into a slice of length 1 (without copying). @@ -6181,7 +6295,11 @@ impl_marker_for!(BytewiseEquality, #[doc(hidden)] unsafe impl<'a, T> TrustedRandomAccess for Iter<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a T { - &*self.ptr.as_ptr().add(i) + // SAFETY: the caller must guarantee that `i` is in bounds + // of the underlying slice, so `i` cannot overflow an `isize`, + // and the returned references is guaranteed to refer to an element + // of the slice and thus guaranteed to be valid. + unsafe { &*self.ptr.as_ptr().add(i) } } fn may_have_side_effect() -> bool { false @@ -6191,7 +6309,8 @@ unsafe impl<'a, T> TrustedRandomAccess for Iter<'a, T> { #[doc(hidden)] unsafe impl<'a, T> TrustedRandomAccess for IterMut<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut T { - &mut *self.ptr.as_ptr().add(i) + // SAFETY: see comments for `Iter::get_unchecked`. + unsafe { &mut *self.ptr.as_ptr().add(i) } } fn may_have_side_effect() -> bool { false diff --git a/src/libcore/slice/rotate.rs b/src/libcore/slice/rotate.rs index f73e14f27e0..a89596b15ef 100644 --- a/src/libcore/slice/rotate.rs +++ b/src/libcore/slice/rotate.rs @@ -1,3 +1,5 @@ +// ignore-tidy-undocumented-unsafe + use crate::cmp; use crate::mem::{self, MaybeUninit}; use crate::ptr; @@ -77,9 +79,9 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize) // the way until about `left + right == 32`, but the worst case performance breaks even // around 16. 24 was chosen as middle ground. If the size of `T` is larger than 4 // `usize`s, this algorithm also outperforms other algorithms. - let x = mid.sub(left); + let x = unsafe { mid.sub(left) }; // beginning of first round - let mut tmp: T = x.read(); + let mut tmp: T = unsafe { x.read() }; let mut i = right; // `gcd` can be found before hand by calculating `gcd(left + right, right)`, // but it is faster to do one loop which calculates the gcd as a side effect, then @@ -90,7 +92,7 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize) // the very end. This is possibly due to the fact that swapping or replacing temporaries // uses only one memory address in the loop instead of needing to manage two. loop { - tmp = x.add(i).replace(tmp); + tmp = unsafe { x.add(i).replace(tmp) }; // instead of incrementing `i` and then checking if it is outside the bounds, we // check if `i` will go outside the bounds on the next increment. This prevents // any wrapping of pointers or `usize`. @@ -98,7 +100,7 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize) i -= left; if i == 0 { // end of first round - x.write(tmp); + unsafe { x.write(tmp) }; break; } // this conditional must be here if `left + right >= 15` @@ -111,14 +113,14 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize) } // finish the chunk with more rounds for start in 1..gcd { - tmp = x.add(start).read(); + tmp = unsafe { x.add(start).read() }; i = start + right; loop { - tmp = x.add(i).replace(tmp); + tmp = unsafe { x.add(i).replace(tmp) }; if i >= left { i -= left; if i == start { - x.add(start).write(tmp); + unsafe { x.add(start).write(tmp) }; break; } } else { @@ -133,15 +135,19 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize) // The `[T; 0]` here is to ensure this is appropriately aligned for T let mut rawarray = MaybeUninit::<(BufType, [T; 0])>::uninit(); let buf = rawarray.as_mut_ptr() as *mut T; - let dim = mid.sub(left).add(right); + let dim = unsafe { mid.sub(left).add(right) }; if left <= right { - ptr::copy_nonoverlapping(mid.sub(left), buf, left); - ptr::copy(mid, mid.sub(left), right); - ptr::copy_nonoverlapping(buf, dim, left); + unsafe { + ptr::copy_nonoverlapping(mid.sub(left), buf, left); + ptr::copy(mid, mid.sub(left), right); + ptr::copy_nonoverlapping(buf, dim, left); + } } else { - ptr::copy_nonoverlapping(mid, buf, right); - ptr::copy(mid.sub(left), dim, left); - ptr::copy_nonoverlapping(buf, mid.sub(left), right); + unsafe { + ptr::copy_nonoverlapping(mid, buf, right); + ptr::copy(mid.sub(left), dim, left); + ptr::copy_nonoverlapping(buf, mid.sub(left), right); + } } return; } else if left >= right { @@ -150,8 +156,10 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize) // of this algorithm would be, and swapping using that last chunk instead of swapping // adjacent chunks like this algorithm is doing, but this way is still faster. loop { - ptr::swap_nonoverlapping(mid.sub(right), mid, right); - mid = mid.sub(right); + unsafe { + ptr::swap_nonoverlapping(mid.sub(right), mid, right); + mid = mid.sub(right); + } left -= right; if left < right { break; @@ -160,8 +168,10 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize) } else { // Algorithm 3, `left < right` loop { - ptr::swap_nonoverlapping(mid.sub(left), mid, left); - mid = mid.add(left); + unsafe { + ptr::swap_nonoverlapping(mid.sub(left), mid, left); + mid = mid.add(left); + } right -= left; if right < left { break; diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 6c4b28499a6..0014501d2c4 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -419,7 +419,11 @@ pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_utf8_unchecked(v: &[u8]) -> &str { - &*(v as *const [u8] as *const str) + // SAFETY: the caller must guarantee that the bytes `v` + // are valid UTF-8, thus the cast to `*const str` is safe. + // Also, the pointer dereference is safe because that pointer + // comes from a reference which is guaranteed to be valid for reads. + unsafe { &*(v as *const [u8] as *const str) } } /// Converts a slice of bytes to a string slice without checking @@ -444,7 +448,11 @@ pub unsafe fn from_utf8_unchecked(v: &[u8]) -> &str { #[inline] #[stable(feature = "str_mut_extras", since = "1.20.0")] pub unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str { - &mut *(v as *mut [u8] as *mut str) + // SAFETY: the caller must guarantee that the bytes `v` + // are valid UTF-8, thus the cast to `*mut str` is safe. + // Also, the pointer dereference is safe because that pointer + // comes from a reference which is guaranteed to be valid for writes. + unsafe { &mut *(v as *mut [u8] as *mut str) } } #[stable(feature = "rust1", since = "1.0.0")] @@ -867,7 +875,9 @@ unsafe impl TrustedLen for Bytes<'_> {} #[doc(hidden)] unsafe impl TrustedRandomAccess for Bytes<'_> { unsafe fn get_unchecked(&mut self, i: usize) -> u8 { - self.0.get_unchecked(i) + // SAFETY: the caller must uphold the safety contract + // for `TrustedRandomAccess::get_unchecked`. + unsafe { self.0.get_unchecked(i) } } fn may_have_side_effect() -> bool { false @@ -1904,15 +1914,27 @@ mod traits { } #[inline] unsafe fn get_unchecked(self, slice: &str) -> &Self::Output { - let ptr = slice.as_ptr().add(self.start); + // SAFETY: the caller guarantees that `self` is in bounds of `slice` + // which satisfies all the conditions for `add`. + let ptr = unsafe { slice.as_ptr().add(self.start) }; let len = self.end - self.start; - super::from_utf8_unchecked(slice::from_raw_parts(ptr, len)) + // SAFETY: as the caller guarantees that `self` is in bounds of `slice`, + // we can safely construct a subslice with `from_raw_parts` and use it + // since we return a shared thus immutable reference. + // The call to `from_utf8_unchecked` is safe since the data comes from + // a `str` which is guaranteed to be valid utf8, since the caller + // must guarantee that `self.start` and `self.end` are char boundaries. + unsafe { super::from_utf8_unchecked(slice::from_raw_parts(ptr, len)) } } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output { - let ptr = slice.as_mut_ptr().add(self.start); + // SAFETY: see comments for `get_unchecked`. + let ptr = unsafe { slice.as_mut_ptr().add(self.start) }; let len = self.end - self.start; - super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, len)) + // SAFETY: mostly identical to the comments for `get_unchecked`, except that we + // can return a mutable reference since the caller passed a mutable reference + // and is thus guaranteed to have exclusive write access to `slice`. + unsafe { super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, len)) } } #[inline] fn index(self, slice: &str) -> &Self::Output { @@ -1974,12 +1996,21 @@ mod traits { #[inline] unsafe fn get_unchecked(self, slice: &str) -> &Self::Output { let ptr = slice.as_ptr(); - super::from_utf8_unchecked(slice::from_raw_parts(ptr, self.end)) + // SAFETY: as the caller guarantees that `self` is in bounds of `slice`, + // we can safely construct a subslice with `from_raw_parts` and use it + // since we return a shared thus immutable reference. + // The call to `from_utf8_unchecked` is safe since the data comes from + // a `str` which is guaranteed to be valid utf8, since the caller + // must guarantee that `self.end` is a char boundary. + unsafe { super::from_utf8_unchecked(slice::from_raw_parts(ptr, self.end)) } } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output { let ptr = slice.as_mut_ptr(); - super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, self.end)) + // SAFETY: mostly identical to `get_unchecked`, except that we can safely + // return a mutable reference since the caller passed a mutable reference + // and is thus guaranteed to have exclusive write access to `slice`. + unsafe { super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, self.end)) } } #[inline] fn index(self, slice: &str) -> &Self::Output { @@ -2036,15 +2067,27 @@ mod traits { } #[inline] unsafe fn get_unchecked(self, slice: &str) -> &Self::Output { - let ptr = slice.as_ptr().add(self.start); + // SAFETY: the caller guarantees that `self` is in bounds of `slice` + // which satisfies all the conditions for `add`. + let ptr = unsafe { slice.as_ptr().add(self.start) }; let len = slice.len() - self.start; - super::from_utf8_unchecked(slice::from_raw_parts(ptr, len)) + // SAFETY: as the caller guarantees that `self` is in bounds of `slice`, + // we can safely construct a subslice with `from_raw_parts` and use it + // since we return a shared thus immutable reference. + // The call to `from_utf8_unchecked` is safe since the data comes from + // a `str` which is guaranteed to be valid utf8, since the caller + // must guarantee that `self.start` is a char boundary. + unsafe { super::from_utf8_unchecked(slice::from_raw_parts(ptr, len)) } } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output { - let ptr = slice.as_mut_ptr().add(self.start); + // SAFETY: identical to `get_unchecked`. + let ptr = unsafe { slice.as_mut_ptr().add(self.start) }; let len = slice.len() - self.start; - super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, len)) + // SAFETY: mostly identical to `get_unchecked`, except that we can safely + // return a mutable reference since the caller passed a mutable reference + // and is thus guaranteed to have exclusive write access to `slice`. + unsafe { super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, len)) } } #[inline] fn index(self, slice: &str) -> &Self::Output { @@ -2099,11 +2142,13 @@ mod traits { } #[inline] unsafe fn get_unchecked(self, slice: &str) -> &Self::Output { - (*self.start()..self.end() + 1).get_unchecked(slice) + // SAFETY: the caller must uphold the safety contract for `get_unchecked`. + unsafe { (*self.start()..self.end() + 1).get_unchecked(slice) } } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output { - (*self.start()..self.end() + 1).get_unchecked_mut(slice) + // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`. + unsafe { (*self.start()..self.end() + 1).get_unchecked_mut(slice) } } #[inline] fn index(self, slice: &str) -> &Self::Output { @@ -2148,11 +2193,13 @@ mod traits { } #[inline] unsafe fn get_unchecked(self, slice: &str) -> &Self::Output { - (..self.end + 1).get_unchecked(slice) + // SAFETY: the caller must uphold the safety contract for `get_unchecked`. + unsafe { (..self.end + 1).get_unchecked(slice) } } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output { - (..self.end + 1).get_unchecked_mut(slice) + // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`. + unsafe { (..self.end + 1).get_unchecked_mut(slice) } } #[inline] fn index(self, slice: &str) -> &Self::Output { @@ -2373,7 +2420,11 @@ impl str { #[stable(feature = "str_mut_extras", since = "1.20.0")] #[inline(always)] pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] { - &mut *(self as *mut str as *mut [u8]) + // SAFETY: the cast from `&str` to `&[u8]` is safe since `str` + // has the same layout as `&[u8]` (only libstd can make this guarantee). + // The pointer dereference is safe since it comes from a mutable reference which + // is guaranteed to be valid for writes. + unsafe { &mut *(self as *mut str as *mut [u8]) } } /// Converts a string slice to a raw pointer. @@ -2509,7 +2560,8 @@ impl str { #[stable(feature = "str_checked_slicing", since = "1.20.0")] #[inline] pub unsafe fn get_unchecked<I: SliceIndex<str>>(&self, i: I) -> &I::Output { - i.get_unchecked(self) + // SAFETY: the caller must uphold the safety contract for `get_unchecked`. + unsafe { i.get_unchecked(self) } } /// Returns a mutable, unchecked subslice of `str`. @@ -2541,7 +2593,8 @@ impl str { #[stable(feature = "str_checked_slicing", since = "1.20.0")] #[inline] pub unsafe fn get_unchecked_mut<I: SliceIndex<str>>(&mut self, i: I) -> &mut I::Output { - i.get_unchecked_mut(self) + // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`. + unsafe { i.get_unchecked_mut(self) } } /// Creates a string slice from another string slice, bypassing safety @@ -2591,7 +2644,8 @@ impl str { #[rustc_deprecated(since = "1.29.0", reason = "use `get_unchecked(begin..end)` instead")] #[inline] pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str { - (begin..end).get_unchecked(self) + // SAFETY: the caller must uphold the safety contract for `get_unchecked`. + unsafe { (begin..end).get_unchecked(self) } } /// Creates a string slice from another string slice, bypassing safety @@ -2622,7 +2676,8 @@ impl str { #[rustc_deprecated(since = "1.29.0", reason = "use `get_unchecked_mut(begin..end)` instead")] #[inline] pub unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut str { - (begin..end).get_unchecked_mut(self) + // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`. + unsafe { (begin..end).get_unchecked_mut(self) } } /// Divide one string slice into two at an index. diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 1cd68f2881b..fcae6c86774 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -2335,35 +2335,44 @@ fn strongest_failure_ordering(order: Ordering) -> Ordering { #[inline] unsafe fn atomic_store<T: Copy>(dst: *mut T, val: T, order: Ordering) { - match order { - Release => intrinsics::atomic_store_rel(dst, val), - Relaxed => intrinsics::atomic_store_relaxed(dst, val), - SeqCst => intrinsics::atomic_store(dst, val), - Acquire => panic!("there is no such thing as an acquire store"), - AcqRel => panic!("there is no such thing as an acquire/release store"), + // SAFETY: the caller must uphold the safety contract for `atomic_store`. + unsafe { + match order { + Release => intrinsics::atomic_store_rel(dst, val), + Relaxed => intrinsics::atomic_store_relaxed(dst, val), + SeqCst => intrinsics::atomic_store(dst, val), + Acquire => panic!("there is no such thing as an acquire store"), + AcqRel => panic!("there is no such thing as an acquire/release store"), + } } } #[inline] unsafe fn atomic_load<T: Copy>(dst: *const T, order: Ordering) -> T { - match order { - Acquire => intrinsics::atomic_load_acq(dst), - Relaxed => intrinsics::atomic_load_relaxed(dst), - SeqCst => intrinsics::atomic_load(dst), - Release => panic!("there is no such thing as a release load"), - AcqRel => panic!("there is no such thing as an acquire/release load"), + // SAFETY: the caller must uphold the safety contract for `atomic_load`. + unsafe { + match order { + Acquire => intrinsics::atomic_load_acq(dst), + Relaxed => intrinsics::atomic_load_relaxed(dst), + SeqCst => intrinsics::atomic_load(dst), + Release => panic!("there is no such thing as a release load"), + AcqRel => panic!("there is no such thing as an acquire/release load"), + } } } #[inline] #[cfg(target_has_atomic = "8")] unsafe fn atomic_swap<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { - match order { - Acquire => intrinsics::atomic_xchg_acq(dst, val), - Release => intrinsics::atomic_xchg_rel(dst, val), - AcqRel => intrinsics::atomic_xchg_acqrel(dst, val), - Relaxed => intrinsics::atomic_xchg_relaxed(dst, val), - SeqCst => intrinsics::atomic_xchg(dst, val), + // SAFETY: the caller must uphold the safety contract for `atomic_swap`. + unsafe { + match order { + Acquire => intrinsics::atomic_xchg_acq(dst, val), + Release => intrinsics::atomic_xchg_rel(dst, val), + AcqRel => intrinsics::atomic_xchg_acqrel(dst, val), + Relaxed => intrinsics::atomic_xchg_relaxed(dst, val), + SeqCst => intrinsics::atomic_xchg(dst, val), + } } } @@ -2371,12 +2380,15 @@ unsafe fn atomic_swap<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic = "8")] unsafe fn atomic_add<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { - match order { - Acquire => intrinsics::atomic_xadd_acq(dst, val), - Release => intrinsics::atomic_xadd_rel(dst, val), - AcqRel => intrinsics::atomic_xadd_acqrel(dst, val), - Relaxed => intrinsics::atomic_xadd_relaxed(dst, val), - SeqCst => intrinsics::atomic_xadd(dst, val), + // SAFETY: the caller must uphold the safety contract for `atomic_add`. + unsafe { + match order { + Acquire => intrinsics::atomic_xadd_acq(dst, val), + Release => intrinsics::atomic_xadd_rel(dst, val), + AcqRel => intrinsics::atomic_xadd_acqrel(dst, val), + Relaxed => intrinsics::atomic_xadd_relaxed(dst, val), + SeqCst => intrinsics::atomic_xadd(dst, val), + } } } @@ -2384,12 +2396,15 @@ unsafe fn atomic_add<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic = "8")] unsafe fn atomic_sub<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { - match order { - Acquire => intrinsics::atomic_xsub_acq(dst, val), - Release => intrinsics::atomic_xsub_rel(dst, val), - AcqRel => intrinsics::atomic_xsub_acqrel(dst, val), - Relaxed => intrinsics::atomic_xsub_relaxed(dst, val), - SeqCst => intrinsics::atomic_xsub(dst, val), + // SAFETY: the caller must uphold the safety contract for `atomic_sub`. + unsafe { + match order { + Acquire => intrinsics::atomic_xsub_acq(dst, val), + Release => intrinsics::atomic_xsub_rel(dst, val), + AcqRel => intrinsics::atomic_xsub_acqrel(dst, val), + Relaxed => intrinsics::atomic_xsub_relaxed(dst, val), + SeqCst => intrinsics::atomic_xsub(dst, val), + } } } @@ -2402,19 +2417,22 @@ unsafe fn atomic_compare_exchange<T: Copy>( success: Ordering, failure: Ordering, ) -> Result<T, T> { - let (val, ok) = match (success, failure) { - (Acquire, Acquire) => intrinsics::atomic_cxchg_acq(dst, old, new), - (Release, Relaxed) => intrinsics::atomic_cxchg_rel(dst, old, new), - (AcqRel, Acquire) => intrinsics::atomic_cxchg_acqrel(dst, old, new), - (Relaxed, Relaxed) => intrinsics::atomic_cxchg_relaxed(dst, old, new), - (SeqCst, SeqCst) => intrinsics::atomic_cxchg(dst, old, new), - (Acquire, Relaxed) => intrinsics::atomic_cxchg_acq_failrelaxed(dst, old, new), - (AcqRel, Relaxed) => intrinsics::atomic_cxchg_acqrel_failrelaxed(dst, old, new), - (SeqCst, Relaxed) => intrinsics::atomic_cxchg_failrelaxed(dst, old, new), - (SeqCst, Acquire) => intrinsics::atomic_cxchg_failacq(dst, old, new), - (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"), - (_, Release) => panic!("there is no such thing as a release failure ordering"), - _ => panic!("a failure ordering can't be stronger than a success ordering"), + // SAFETY: the caller must uphold the safety contract for `atomic_compare_exchange`. + let (val, ok) = unsafe { + match (success, failure) { + (Acquire, Acquire) => intrinsics::atomic_cxchg_acq(dst, old, new), + (Release, Relaxed) => intrinsics::atomic_cxchg_rel(dst, old, new), + (AcqRel, Acquire) => intrinsics::atomic_cxchg_acqrel(dst, old, new), + (Relaxed, Relaxed) => intrinsics::atomic_cxchg_relaxed(dst, old, new), + (SeqCst, SeqCst) => intrinsics::atomic_cxchg(dst, old, new), + (Acquire, Relaxed) => intrinsics::atomic_cxchg_acq_failrelaxed(dst, old, new), + (AcqRel, Relaxed) => intrinsics::atomic_cxchg_acqrel_failrelaxed(dst, old, new), + (SeqCst, Relaxed) => intrinsics::atomic_cxchg_failrelaxed(dst, old, new), + (SeqCst, Acquire) => intrinsics::atomic_cxchg_failacq(dst, old, new), + (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"), + (_, Release) => panic!("there is no such thing as a release failure ordering"), + _ => panic!("a failure ordering can't be stronger than a success ordering"), + } }; if ok { Ok(val) } else { Err(val) } } @@ -2428,19 +2446,22 @@ unsafe fn atomic_compare_exchange_weak<T: Copy>( success: Ordering, failure: Ordering, ) -> Result<T, T> { - let (val, ok) = match (success, failure) { - (Acquire, Acquire) => intrinsics::atomic_cxchgweak_acq(dst, old, new), - (Release, Relaxed) => intrinsics::atomic_cxchgweak_rel(dst, old, new), - (AcqRel, Acquire) => intrinsics::atomic_cxchgweak_acqrel(dst, old, new), - (Relaxed, Relaxed) => intrinsics::atomic_cxchgweak_relaxed(dst, old, new), - (SeqCst, SeqCst) => intrinsics::atomic_cxchgweak(dst, old, new), - (Acquire, Relaxed) => intrinsics::atomic_cxchgweak_acq_failrelaxed(dst, old, new), - (AcqRel, Relaxed) => intrinsics::atomic_cxchgweak_acqrel_failrelaxed(dst, old, new), - (SeqCst, Relaxed) => intrinsics::atomic_cxchgweak_failrelaxed(dst, old, new), - (SeqCst, Acquire) => intrinsics::atomic_cxchgweak_failacq(dst, old, new), - (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"), - (_, Release) => panic!("there is no such thing as a release failure ordering"), - _ => panic!("a failure ordering can't be stronger than a success ordering"), + // SAFETY: the caller must uphold the safety contract for `atomic_compare_exchange_weak`. + let (val, ok) = unsafe { + match (success, failure) { + (Acquire, Acquire) => intrinsics::atomic_cxchgweak_acq(dst, old, new), + (Release, Relaxed) => intrinsics::atomic_cxchgweak_rel(dst, old, new), + (AcqRel, Acquire) => intrinsics::atomic_cxchgweak_acqrel(dst, old, new), + (Relaxed, Relaxed) => intrinsics::atomic_cxchgweak_relaxed(dst, old, new), + (SeqCst, SeqCst) => intrinsics::atomic_cxchgweak(dst, old, new), + (Acquire, Relaxed) => intrinsics::atomic_cxchgweak_acq_failrelaxed(dst, old, new), + (AcqRel, Relaxed) => intrinsics::atomic_cxchgweak_acqrel_failrelaxed(dst, old, new), + (SeqCst, Relaxed) => intrinsics::atomic_cxchgweak_failrelaxed(dst, old, new), + (SeqCst, Acquire) => intrinsics::atomic_cxchgweak_failacq(dst, old, new), + (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"), + (_, Release) => panic!("there is no such thing as a release failure ordering"), + _ => panic!("a failure ordering can't be stronger than a success ordering"), + } }; if ok { Ok(val) } else { Err(val) } } @@ -2448,48 +2469,60 @@ unsafe fn atomic_compare_exchange_weak<T: Copy>( #[inline] #[cfg(target_has_atomic = "8")] unsafe fn atomic_and<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { - match order { - Acquire => intrinsics::atomic_and_acq(dst, val), - Release => intrinsics::atomic_and_rel(dst, val), - AcqRel => intrinsics::atomic_and_acqrel(dst, val), - Relaxed => intrinsics::atomic_and_relaxed(dst, val), - SeqCst => intrinsics::atomic_and(dst, val), + // SAFETY: the caller must uphold the safety contract for `atomic_and` + unsafe { + match order { + Acquire => intrinsics::atomic_and_acq(dst, val), + Release => intrinsics::atomic_and_rel(dst, val), + AcqRel => intrinsics::atomic_and_acqrel(dst, val), + Relaxed => intrinsics::atomic_and_relaxed(dst, val), + SeqCst => intrinsics::atomic_and(dst, val), + } } } #[inline] #[cfg(target_has_atomic = "8")] unsafe fn atomic_nand<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { - match order { - Acquire => intrinsics::atomic_nand_acq(dst, val), - Release => intrinsics::atomic_nand_rel(dst, val), - AcqRel => intrinsics::atomic_nand_acqrel(dst, val), - Relaxed => intrinsics::atomic_nand_relaxed(dst, val), - SeqCst => intrinsics::atomic_nand(dst, val), + // SAFETY: the caller must uphold the safety contract for `atomic_nand` + unsafe { + match order { + Acquire => intrinsics::atomic_nand_acq(dst, val), + Release => intrinsics::atomic_nand_rel(dst, val), + AcqRel => intrinsics::atomic_nand_acqrel(dst, val), + Relaxed => intrinsics::atomic_nand_relaxed(dst, val), + SeqCst => intrinsics::atomic_nand(dst, val), + } } } #[inline] #[cfg(target_has_atomic = "8")] unsafe fn atomic_or<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { - match order { - Acquire => intrinsics::atomic_or_acq(dst, val), - Release => intrinsics::atomic_or_rel(dst, val), - AcqRel => intrinsics::atomic_or_acqrel(dst, val), - Relaxed => intrinsics::atomic_or_relaxed(dst, val), - SeqCst => intrinsics::atomic_or(dst, val), + // SAFETY: the caller must uphold the safety contract for `atomic_or` + unsafe { + match order { + Acquire => intrinsics::atomic_or_acq(dst, val), + Release => intrinsics::atomic_or_rel(dst, val), + AcqRel => intrinsics::atomic_or_acqrel(dst, val), + Relaxed => intrinsics::atomic_or_relaxed(dst, val), + SeqCst => intrinsics::atomic_or(dst, val), + } } } #[inline] #[cfg(target_has_atomic = "8")] unsafe fn atomic_xor<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { - match order { - Acquire => intrinsics::atomic_xor_acq(dst, val), - Release => intrinsics::atomic_xor_rel(dst, val), - AcqRel => intrinsics::atomic_xor_acqrel(dst, val), - Relaxed => intrinsics::atomic_xor_relaxed(dst, val), - SeqCst => intrinsics::atomic_xor(dst, val), + // SAFETY: the caller must uphold the safety contract for `atomic_xor` + unsafe { + match order { + Acquire => intrinsics::atomic_xor_acq(dst, val), + Release => intrinsics::atomic_xor_rel(dst, val), + AcqRel => intrinsics::atomic_xor_acqrel(dst, val), + Relaxed => intrinsics::atomic_xor_relaxed(dst, val), + SeqCst => intrinsics::atomic_xor(dst, val), + } } } @@ -2497,12 +2530,15 @@ unsafe fn atomic_xor<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic = "8")] unsafe fn atomic_max<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { - match order { - Acquire => intrinsics::atomic_max_acq(dst, val), - Release => intrinsics::atomic_max_rel(dst, val), - AcqRel => intrinsics::atomic_max_acqrel(dst, val), - Relaxed => intrinsics::atomic_max_relaxed(dst, val), - SeqCst => intrinsics::atomic_max(dst, val), + // SAFETY: the caller must uphold the safety contract for `atomic_max` + unsafe { + match order { + Acquire => intrinsics::atomic_max_acq(dst, val), + Release => intrinsics::atomic_max_rel(dst, val), + AcqRel => intrinsics::atomic_max_acqrel(dst, val), + Relaxed => intrinsics::atomic_max_relaxed(dst, val), + SeqCst => intrinsics::atomic_max(dst, val), + } } } @@ -2510,12 +2546,15 @@ unsafe fn atomic_max<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic = "8")] unsafe fn atomic_min<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { - match order { - Acquire => intrinsics::atomic_min_acq(dst, val), - Release => intrinsics::atomic_min_rel(dst, val), - AcqRel => intrinsics::atomic_min_acqrel(dst, val), - Relaxed => intrinsics::atomic_min_relaxed(dst, val), - SeqCst => intrinsics::atomic_min(dst, val), + // SAFETY: the caller must uphold the safety contract for `atomic_min` + unsafe { + match order { + Acquire => intrinsics::atomic_min_acq(dst, val), + Release => intrinsics::atomic_min_rel(dst, val), + AcqRel => intrinsics::atomic_min_acqrel(dst, val), + Relaxed => intrinsics::atomic_min_relaxed(dst, val), + SeqCst => intrinsics::atomic_min(dst, val), + } } } @@ -2523,12 +2562,15 @@ unsafe fn atomic_min<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic = "8")] unsafe fn atomic_umax<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { - match order { - Acquire => intrinsics::atomic_umax_acq(dst, val), - Release => intrinsics::atomic_umax_rel(dst, val), - AcqRel => intrinsics::atomic_umax_acqrel(dst, val), - Relaxed => intrinsics::atomic_umax_relaxed(dst, val), - SeqCst => intrinsics::atomic_umax(dst, val), + // SAFETY: the caller must uphold the safety contract for `atomic_umax` + unsafe { + match order { + Acquire => intrinsics::atomic_umax_acq(dst, val), + Release => intrinsics::atomic_umax_rel(dst, val), + AcqRel => intrinsics::atomic_umax_acqrel(dst, val), + Relaxed => intrinsics::atomic_umax_relaxed(dst, val), + SeqCst => intrinsics::atomic_umax(dst, val), + } } } @@ -2536,12 +2578,15 @@ unsafe fn atomic_umax<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic = "8")] unsafe fn atomic_umin<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { - match order { - Acquire => intrinsics::atomic_umin_acq(dst, val), - Release => intrinsics::atomic_umin_rel(dst, val), - AcqRel => intrinsics::atomic_umin_acqrel(dst, val), - Relaxed => intrinsics::atomic_umin_relaxed(dst, val), - SeqCst => intrinsics::atomic_umin(dst, val), + // SAFETY: the caller must uphold the safety contract for `atomic_umin` + unsafe { + match order { + Acquire => intrinsics::atomic_umin_acq(dst, val), + Release => intrinsics::atomic_umin_rel(dst, val), + AcqRel => intrinsics::atomic_umin_acqrel(dst, val), + Relaxed => intrinsics::atomic_umin_relaxed(dst, val), + SeqCst => intrinsics::atomic_umin(dst, val), + } } } diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 524c38a7ab4..68a5e20a66f 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -40,11 +40,12 @@ #![feature(const_raw_ptr_deref)] #![feature(never_type)] #![feature(unwrap_infallible)] -#![feature(leading_trailing_ones)] #![feature(const_forget)] #![feature(option_unwrap_none)] #![feature(peekable_next_if)] #![feature(partition_point)] +#![feature(unsafe_block_in_unsafe_fn)] +#![deny(unsafe_op_in_unsafe_fn)] extern crate test; diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs index 99fbb1ee3ea..6543117774a 100644 --- a/src/librustc_ast/ast.rs +++ b/src/librustc_ast/ast.rs @@ -511,6 +511,9 @@ pub struct Block { pub span: Span, } +/// A match pattern. +/// +/// Patterns appear in match statements and some other contexts, such as `let` and `if let`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Pat { pub id: NodeId, diff --git a/src/librustc_ast/attr/mod.rs b/src/librustc_ast/attr/mod.rs index 6c128f0176f..76139209c91 100644 --- a/src/librustc_ast/attr/mod.rs +++ b/src/librustc_ast/attr/mod.rs @@ -475,7 +475,7 @@ impl MetaItem { let span = span.with_hi(segments.last().unwrap().ident.span.hi()); Path { span, segments } } - Some(TokenTree::Token(Token { kind: token::Interpolated(nt, _), .. })) => match *nt { + Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. })) => match *nt { token::Nonterminal::NtMeta(ref item) => return item.meta(item.path.span), token::Nonterminal::NtPath(ref path) => path.clone(), _ => return None, @@ -560,6 +560,9 @@ impl MetaItemKind { tokens: &mut impl Iterator<Item = TokenTree>, ) -> Option<MetaItemKind> { match tokens.next() { + Some(TokenTree::Delimited(_, token::NoDelim, inner_tokens)) => { + MetaItemKind::name_value_from_tokens(&mut inner_tokens.trees()) + } Some(TokenTree::Token(token)) => { Lit::from_token(&token).ok().map(MetaItemKind::NameValue) } @@ -619,13 +622,20 @@ impl NestedMetaItem { where I: Iterator<Item = TokenTree>, { - if let Some(TokenTree::Token(token)) = tokens.peek() { - if let Ok(lit) = Lit::from_token(token) { + match tokens.peek() { + Some(TokenTree::Token(token)) => { + if let Ok(lit) = Lit::from_token(token) { + tokens.next(); + return Some(NestedMetaItem::Literal(lit)); + } + } + Some(TokenTree::Delimited(_, token::NoDelim, inner_tokens)) => { + let inner_tokens = inner_tokens.clone(); tokens.next(); - return Some(NestedMetaItem::Literal(lit)); + return NestedMetaItem::from_tokens(&mut inner_tokens.into_trees().peekable()); } + _ => {} } - MetaItem::from_tokens(tokens).map(NestedMetaItem::MetaItem) } } diff --git a/src/librustc_ast/mut_visit.rs b/src/librustc_ast/mut_visit.rs index 3fd2815daa1..54f81ef106f 100644 --- a/src/librustc_ast/mut_visit.rs +++ b/src/librustc_ast/mut_visit.rs @@ -656,7 +656,7 @@ pub fn noop_visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) { *span = ident.span; return; // Avoid visiting the span for the second time. } - token::Interpolated(nt, _) => { + token::Interpolated(nt) => { let mut nt = Lrc::make_mut(nt); vis.visit_interpolated(&mut nt); } diff --git a/src/librustc_ast/token.rs b/src/librustc_ast/token.rs index 89be3e6e212..173ea5e48d6 100644 --- a/src/librustc_ast/token.rs +++ b/src/librustc_ast/token.rs @@ -11,7 +11,7 @@ use crate::tokenstream::TokenTree; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; use rustc_macros::HashStable_Generic; -use rustc_span::symbol::kw; +use rustc_span::symbol::{kw, sym}; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::{self, Span, DUMMY_SP}; use std::borrow::Cow; @@ -182,15 +182,6 @@ fn ident_can_begin_type(name: Symbol, span: Span, is_raw: bool) -> bool { .contains(&name) } -/// A hack used to pass AST fragments to attribute and derive macros -/// as a single nonterminal token instead of a token stream. -/// FIXME: It needs to be removed, but there are some compatibility issues (see #73345). -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] -pub enum FlattenGroup { - Yes, - No, -} - #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] pub enum TokenKind { /* Expression-operator symbols. */ @@ -245,7 +236,7 @@ pub enum TokenKind { /// treat regular and interpolated lifetime identifiers in the same way. Lifetime(Symbol), - Interpolated(Lrc<Nonterminal>, FlattenGroup), + Interpolated(Lrc<Nonterminal>), // Can be expanded into several tokens. /// A doc comment. @@ -352,7 +343,7 @@ impl Token { /// if they keep spans or perform edition checks. pub fn uninterpolated_span(&self) -> Span { match &self.kind { - Interpolated(nt, _) => nt.span(), + Interpolated(nt) => nt.span(), _ => self.span, } } @@ -391,7 +382,7 @@ impl Token { ModSep | // global path Lifetime(..) | // labeled loop Pound => true, // expression attributes - Interpolated(ref nt, _) => match **nt { + Interpolated(ref nt) => match **nt { NtLiteral(..) | NtExpr(..) | NtBlock(..) | @@ -417,7 +408,7 @@ impl Token { Lifetime(..) | // lifetime bound in trait object Lt | BinOp(Shl) | // associated path ModSep => true, // global path - Interpolated(ref nt, _) => match **nt { + Interpolated(ref nt) => match **nt { NtTy(..) | NtPath(..) => true, _ => false, }, @@ -429,7 +420,7 @@ impl Token { pub fn can_begin_const_arg(&self) -> bool { match self.kind { OpenDelim(Brace) => true, - Interpolated(ref nt, _) => match **nt { + Interpolated(ref nt) => match **nt { NtExpr(..) | NtBlock(..) | NtLiteral(..) => true, _ => false, }, @@ -464,7 +455,7 @@ impl Token { match self.uninterpolate().kind { Literal(..) | BinOp(Minus) => true, Ident(name, false) if name.is_bool_lit() => true, - Interpolated(ref nt, _) => match &**nt { + Interpolated(ref nt) => match &**nt { NtLiteral(_) => true, NtExpr(e) => match &e.kind { ast::ExprKind::Lit(_) => true, @@ -485,7 +476,7 @@ impl Token { // otherwise returns the original token. pub fn uninterpolate(&self) -> Cow<'_, Token> { match &self.kind { - Interpolated(nt, _) => match **nt { + Interpolated(nt) => match **nt { NtIdent(ident, is_raw) => { Cow::Owned(Token::new(Ident(ident.name, is_raw), ident.span)) } @@ -532,7 +523,7 @@ impl Token { /// Returns `true` if the token is an interpolated path. fn is_path(&self) -> bool { - if let Interpolated(ref nt, _) = self.kind { + if let Interpolated(ref nt) = self.kind { if let NtPath(..) = **nt { return true; } @@ -544,7 +535,7 @@ impl Token { /// That is, is this a pre-parsed expression dropped into the token stream /// (which happens while parsing the result of macro expansion)? pub fn is_whole_expr(&self) -> bool { - if let Interpolated(ref nt, _) = self.kind { + if let Interpolated(ref nt) = self.kind { if let NtExpr(_) | NtLiteral(_) | NtPath(_) | NtIdent(..) | NtBlock(_) = **nt { return true; } @@ -555,7 +546,7 @@ impl Token { // Is the token an interpolated block (`$b:block`)? pub fn is_whole_block(&self) -> bool { - if let Interpolated(ref nt, _) = self.kind { + if let Interpolated(ref nt) = self.kind { if let NtBlock(..) = **nt { return true; } @@ -785,6 +776,26 @@ impl Nonterminal { NtTT(tt) => tt.span(), } } + + /// This nonterminal looks like some specific enums from + /// `proc-macro-hack` and `procedural-masquerade` crates. + /// We need to maintain some special pretty-printing behavior for them due to incorrect + /// asserts in old versions of those crates and their wide use in the ecosystem. + /// See issue #73345 for more details. + /// FIXME(#73933): Remove this eventually. + pub fn pretty_printing_compatibility_hack(&self) -> bool { + if let NtItem(item) = self { + let name = item.ident.name; + if name == sym::ProceduralMasqueradeDummyType || name == sym::ProcMacroHack { + if let ast::ItemKind::Enum(enum_def, _) = &item.kind { + if let [variant] = &*enum_def.variants { + return variant.ident.name == sym::Input; + } + } + } + } + false + } } impl PartialEq for Nonterminal { diff --git a/src/librustc_ast/util/literal.rs b/src/librustc_ast/util/literal.rs index ea59f867c59..4428d09902b 100644 --- a/src/librustc_ast/util/literal.rs +++ b/src/librustc_ast/util/literal.rs @@ -205,7 +205,7 @@ impl Lit { token::Lit::new(token::Bool, name, None) } token::Literal(lit) => lit, - token::Interpolated(ref nt, _) => { + token::Interpolated(ref nt) => { if let token::NtExpr(expr) | token::NtLiteral(expr) = &**nt { if let ast::ExprKind::Lit(lit) = &expr.kind { return Ok(lit.clone()); diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index bc0980f041b..b5d3beb4f8a 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -39,8 +39,8 @@ use rustc_ast::ast; use rustc_ast::ast::*; use rustc_ast::attr; use rustc_ast::node_id::NodeMap; -use rustc_ast::token::{self, Nonterminal, Token}; -use rustc_ast::tokenstream::{TokenStream, TokenTree}; +use rustc_ast::token::{self, DelimToken, Nonterminal, Token}; +use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; use rustc_ast::visit::{self, AssocCtxt, Visitor}; use rustc_ast::walk_list; use rustc_ast_pretty::pprust; @@ -1027,9 +1027,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_token(&mut self, token: Token) -> TokenStream { match token.kind { - token::Interpolated(nt, _) => { + token::Interpolated(nt) => { let tts = (self.nt_to_tokenstream)(&nt, &self.sess.parse_sess, token.span); - self.lower_token_stream(tts) + TokenTree::Delimited( + DelimSpan::from_single(token.span), + DelimToken::NoDelim, + self.lower_token_stream(tts), + ) + .into() } _ => TokenTree::Token(token).into(), } diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index 86faa1f086c..2d803262f79 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -9,7 +9,7 @@ use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_ast::attr; use rustc_ast::ptr::P; use rustc_ast::token::{self, BinOpToken, DelimToken, Nonterminal, Token, TokenKind}; -use rustc_ast::tokenstream::{self, TokenStream, TokenTree}; +use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_ast::util::parser::{self, AssocOp, Fixity}; use rustc_ast::util::{classify, comments}; use rustc_span::edition::Edition; @@ -148,9 +148,14 @@ pub fn to_string(f: impl FnOnce(&mut State<'_>)) -> String { printer.s.eof() } -// This makes comma-separated lists look slightly nicer, -// and also addresses a specific regression described in issue #63896. +// This makes printed token streams look slightly nicer, +// and also addresses some specific regressions described in #63896 and #73345. fn tt_prepend_space(tt: &TokenTree, prev: &TokenTree) -> bool { + if let TokenTree::Token(token) = prev { + if let token::DocComment(s) = token.kind { + return !s.as_str().starts_with("//"); + } + } match tt { TokenTree::Token(token) => match token.kind { token::Comma => false, @@ -163,7 +168,14 @@ fn tt_prepend_space(tt: &TokenTree, prev: &TokenTree) -> bool { }, _ => true, }, - _ => true, + TokenTree::Delimited(_, DelimToken::Bracket, _) => match prev { + TokenTree::Token(token) => match token.kind { + token::Pound => false, + _ => true, + }, + _ => true, + }, + TokenTree::Delimited(..) => true, } } @@ -245,7 +257,7 @@ fn token_kind_to_string_ext(tok: &TokenKind, convert_dollar_crate: Option<Span>) token::CloseDelim(token::Bracket) => "]".to_string(), token::OpenDelim(token::Brace) => "{".to_string(), token::CloseDelim(token::Brace) => "}".to_string(), - token::OpenDelim(token::NoDelim) | token::CloseDelim(token::NoDelim) => " ".to_string(), + token::OpenDelim(token::NoDelim) | token::CloseDelim(token::NoDelim) => "".to_string(), token::Pound => "#".to_string(), token::Dollar => "$".to_string(), token::Question => "?".to_string(), @@ -266,7 +278,7 @@ fn token_kind_to_string_ext(tok: &TokenKind, convert_dollar_crate: Option<Span>) token::Shebang(s) => format!("/* shebang: {}*/", s), token::Unknown(s) => s.to_string(), - token::Interpolated(ref nt, _) => nonterminal_to_string(nt), + token::Interpolated(ref nt) => nonterminal_to_string(nt), } } @@ -293,7 +305,7 @@ pub fn nonterminal_to_string(nt: &Nonterminal) -> String { token::NtIdent(e, is_raw) => IdentPrinter::for_ast_ident(e, is_raw).to_string(), token::NtLifetime(e) => e.to_string(), token::NtLiteral(ref e) => expr_to_string(e), - token::NtTT(ref tree) => tt_to_string(tree.clone()), + token::NtTT(ref tree) => tt_to_string(tree), token::NtVis(ref e) => vis_to_string(e), } } @@ -314,11 +326,11 @@ pub fn expr_to_string(e: &ast::Expr) -> String { to_string(|s| s.print_expr(e)) } -pub fn tt_to_string(tt: tokenstream::TokenTree) -> String { +pub fn tt_to_string(tt: &TokenTree) -> String { to_string(|s| s.print_tt(tt, false)) } -pub fn tts_to_string(tokens: TokenStream) -> String { +pub fn tts_to_string(tokens: &TokenStream) -> String { to_string(|s| s.print_tts(tokens, false)) } @@ -585,7 +597,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere false, None, delim.to_token(), - tokens.clone(), + tokens, true, span, ), @@ -594,7 +606,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere if let MacArgs::Eq(_, tokens) = &item.args { self.space(); self.word_space("="); - self.print_tts(tokens.clone(), true); + self.print_tts(tokens, true); } } } @@ -635,9 +647,9 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere /// appropriate macro, transcribe back into the grammar we just parsed from, /// and then pretty-print the resulting AST nodes (so, e.g., we print /// expression arguments as expressions). It can be done! I think. - fn print_tt(&mut self, tt: tokenstream::TokenTree, convert_dollar_crate: bool) { + fn print_tt(&mut self, tt: &TokenTree, convert_dollar_crate: bool) { match tt { - TokenTree::Token(ref token) => { + TokenTree::Token(token) => { self.word(token_to_string_ext(&token, convert_dollar_crate)); if let token::DocComment(..) = token.kind { self.hardbreak() @@ -648,7 +660,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere None, false, None, - delim, + *delim, tts, convert_dollar_crate, dspan.entire(), @@ -657,14 +669,14 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere } } - fn print_tts(&mut self, tts: tokenstream::TokenStream, convert_dollar_crate: bool) { - let mut iter = tts.into_trees().peekable(); + fn print_tts(&mut self, tts: &TokenStream, convert_dollar_crate: bool) { + let mut iter = tts.trees().peekable(); while let Some(tt) = iter.next() { - let show_space = - if let Some(next) = iter.peek() { tt_prepend_space(next, &tt) } else { false }; - self.print_tt(tt, convert_dollar_crate); - if show_space { - self.space(); + self.print_tt(&tt, convert_dollar_crate); + if let Some(next) = iter.peek() { + if tt_prepend_space(next, &tt) { + self.space(); + } } } } @@ -675,7 +687,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere has_bang: bool, ident: Option<Ident>, delim: DelimToken, - tts: TokenStream, + tts: &TokenStream, convert_dollar_crate: bool, span: Span, ) { @@ -1253,7 +1265,7 @@ impl<'a> State<'a> { has_bang, Some(item.ident), macro_def.body.delim(), - macro_def.body.inner_tokens(), + ¯o_def.body.inner_tokens(), true, item.span, ); @@ -1577,7 +1589,7 @@ impl<'a> State<'a> { true, None, m.args.delim(), - m.args.inner_tokens(), + &m.args.inner_tokens(), true, m.span(), ); diff --git a/src/librustc_builtin_macros/log_syntax.rs b/src/librustc_builtin_macros/log_syntax.rs index ae3a889428a..ede34a76125 100644 --- a/src/librustc_builtin_macros/log_syntax.rs +++ b/src/librustc_builtin_macros/log_syntax.rs @@ -7,7 +7,7 @@ pub fn expand_log_syntax<'cx>( sp: rustc_span::Span, tts: TokenStream, ) -> Box<dyn base::MacResult + 'cx> { - println!("{}", pprust::tts_to_string(tts)); + println!("{}", pprust::tts_to_string(&tts)); // any so that `log_syntax` can be invoked as an expression and item. base::DummyResult::any_valid(sp) diff --git a/src/librustc_builtin_macros/source_util.rs b/src/librustc_builtin_macros/source_util.rs index 1b164eae5a3..e46cf67e64d 100644 --- a/src/librustc_builtin_macros/source_util.rs +++ b/src/librustc_builtin_macros/source_util.rs @@ -71,7 +71,7 @@ pub fn expand_stringify( tts: TokenStream, ) -> Box<dyn base::MacResult + 'static> { let sp = cx.with_def_site_ctxt(sp); - let s = pprust::tts_to_string(tts); + let s = pprust::tts_to_string(&tts); base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&s))) } diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index e99fb8dcae1..d5e0d7d36ee 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -150,6 +150,11 @@ pub fn compile_codegen_unit( cx.create_used_variable() } + // Finalize code coverage by injecting the coverage map + if cx.sess().opts.debugging_opts.instrument_coverage { + cx.coverageinfo_finalize(); + } + // Finalize debuginfo if cx.sess().opts.debuginfo != DebugInfo::None { cx.debuginfo_finalize(); diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index ba285b5ef38..89b70dce52c 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -18,6 +18,7 @@ use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_span::sym; use rustc_target::abi::{self, Align, Size}; use rustc_target::spec::{HasTargetSpec, Target}; use std::borrow::Cow; @@ -652,6 +653,56 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { unsafe { llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, UNNAMED) } } + fn fptoui_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> { + // WebAssembly has saturating floating point to integer casts if the + // `nontrapping-fptoint` target feature is activated. We'll use those if + // they are available. + if self.sess().target.target.arch == "wasm32" + && self.sess().target_features.contains(&sym::nontrapping_fptoint) + { + let src_ty = self.cx.val_ty(val); + let float_width = self.cx.float_width(src_ty); + let int_width = self.cx.int_width(dest_ty); + let name = match (int_width, float_width) { + (32, 32) => Some("llvm.wasm.trunc.saturate.unsigned.i32.f32"), + (32, 64) => Some("llvm.wasm.trunc.saturate.unsigned.i32.f64"), + (64, 32) => Some("llvm.wasm.trunc.saturate.unsigned.i64.f32"), + (64, 64) => Some("llvm.wasm.trunc.saturate.unsigned.i64.f64"), + _ => None, + }; + if let Some(name) = name { + let intrinsic = self.get_intrinsic(name); + return Some(self.call(intrinsic, &[val], None)); + } + } + None + } + + fn fptosi_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> { + // WebAssembly has saturating floating point to integer casts if the + // `nontrapping-fptoint` target feature is activated. We'll use those if + // they are available. + if self.sess().target.target.arch == "wasm32" + && self.sess().target_features.contains(&sym::nontrapping_fptoint) + { + let src_ty = self.cx.val_ty(val); + let float_width = self.cx.float_width(src_ty); + let int_width = self.cx.int_width(dest_ty); + let name = match (int_width, float_width) { + (32, 32) => Some("llvm.wasm.trunc.saturate.signed.i32.f32"), + (32, 64) => Some("llvm.wasm.trunc.saturate.signed.i32.f64"), + (64, 32) => Some("llvm.wasm.trunc.saturate.signed.i64.f32"), + (64, 64) => Some("llvm.wasm.trunc.saturate.signed.i64.f64"), + _ => None, + }; + if let Some(name) = name { + let intrinsic = self.get_intrinsic(name); + return Some(self.call(intrinsic, &[val], None)); + } + } + None + } + fn fptoui(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { unsafe { llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, UNNAMED) } } diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 7ff5ac5cbdc..d484e15eb2f 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -1,5 +1,6 @@ use crate::attributes; use crate::callee::get_fn; +use crate::coverageinfo; use crate::debuginfo; use crate::llvm; use crate::llvm_util; @@ -77,6 +78,7 @@ pub struct CodegenCx<'ll, 'tcx> { pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>, pub isize_ty: &'ll Type, + pub coverage_cx: Option<coverageinfo::CrateCoverageContext<'tcx>>, pub dbg_cx: Option<debuginfo::CrateDebugContext<'ll, 'tcx>>, eh_personality: Cell<Option<&'ll Value>>, @@ -256,6 +258,13 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { let (llcx, llmod) = (&*llvm_module.llcx, llvm_module.llmod()); + let coverage_cx = if tcx.sess.opts.debugging_opts.instrument_coverage { + let covctx = coverageinfo::CrateCoverageContext::new(); + Some(covctx) + } else { + None + }; + let dbg_cx = if tcx.sess.opts.debuginfo != DebugInfo::None { let dctx = debuginfo::CrateDebugContext::new(llmod); debuginfo::metadata::compile_unit_metadata(tcx, &codegen_unit.name().as_str(), &dctx); @@ -285,6 +294,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { scalar_lltypes: Default::default(), pointee_infos: Default::default(), isize_ty, + coverage_cx, dbg_cx, eh_personality: Cell::new(None), rust_try_fn: Cell::new(None), @@ -296,6 +306,11 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { crate fn statics_to_rauw(&self) -> &RefCell<Vec<(&'ll Value, &'ll Value)>> { &self.statics_to_rauw } + + #[inline] + pub fn coverage_context(&'a self) -> &'a coverageinfo::CrateCoverageContext<'tcx> { + self.coverage_cx.as_ref().unwrap() + } } impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { @@ -482,6 +497,15 @@ impl CodegenCx<'b, 'tcx> { t_v8f64: t_f64, 8; } + ifn!("llvm.wasm.trunc.saturate.unsigned.i32.f32", fn(t_f32) -> t_i32); + ifn!("llvm.wasm.trunc.saturate.unsigned.i32.f64", fn(t_f64) -> t_i32); + ifn!("llvm.wasm.trunc.saturate.unsigned.i64.f32", fn(t_f32) -> t_i64); + ifn!("llvm.wasm.trunc.saturate.unsigned.i64.f64", fn(t_f64) -> t_i64); + ifn!("llvm.wasm.trunc.saturate.signed.i32.f32", fn(t_f32) -> t_i32); + ifn!("llvm.wasm.trunc.saturate.signed.i32.f64", fn(t_f64) -> t_i32); + ifn!("llvm.wasm.trunc.saturate.signed.i64.f32", fn(t_f32) -> t_i64); + ifn!("llvm.wasm.trunc.saturate.signed.i64.f64", fn(t_f64) -> t_i64); + ifn!("llvm.trap", fn() -> void); ifn!("llvm.debugtrap", fn() -> void); ifn!("llvm.frameaddress", fn(t_i32) -> i8p); @@ -749,8 +773,6 @@ impl CodegenCx<'b, 'tcx> { ifn!("llvm.lifetime.start.p0i8", fn(t_i64, i8p) -> void); ifn!("llvm.lifetime.end.p0i8", fn(t_i64, i8p) -> void); - ifn!("llvm.instrprof.increment", fn(i8p, t_i64, t_i32, t_i32) -> void); - ifn!("llvm.expect.i1", fn(i1, i1) -> i1); ifn!("llvm.eh.typeid.for", fn(i8p) -> t_i32); ifn!("llvm.localescape", fn(...) -> void); @@ -765,6 +787,10 @@ impl CodegenCx<'b, 'tcx> { ifn!("llvm.va_end", fn(i8p) -> void); ifn!("llvm.va_copy", fn(i8p, i8p) -> void); + if self.sess().opts.debugging_opts.instrument_coverage { + ifn!("llvm.instrprof.increment", fn(i8p, t_i64, t_i32, t_i32) -> void); + } + if self.sess().opts.debuginfo != DebugInfo::None { ifn!("llvm.dbg.declare", fn(self.type_metadata(), self.type_metadata()) -> void); ifn!("llvm.dbg.value", fn(self.type_metadata(), t_i64, self.type_metadata()) -> void); diff --git a/src/librustc_codegen_llvm/coverageinfo/mod.rs b/src/librustc_codegen_llvm/coverageinfo/mod.rs new file mode 100644 index 00000000000..ff9f8f7aeaa --- /dev/null +++ b/src/librustc_codegen_llvm/coverageinfo/mod.rs @@ -0,0 +1,126 @@ +use crate::builder::Builder; +use crate::common::CodegenCx; +use log::debug; +use rustc_codegen_ssa::coverageinfo::map::*; +use rustc_codegen_ssa::traits::{CoverageInfoBuilderMethods, CoverageInfoMethods}; +use rustc_data_structures::fx::FxHashMap; +use rustc_middle::ty::Instance; + +use std::cell::RefCell; + +/// A context object for maintaining all state needed by the coverageinfo module. +pub struct CrateCoverageContext<'tcx> { + // Coverage region data for each instrumented function identified by DefId. + pub(crate) coverage_regions: RefCell<FxHashMap<Instance<'tcx>, FunctionCoverageRegions>>, +} + +impl<'tcx> CrateCoverageContext<'tcx> { + pub fn new() -> Self { + Self { coverage_regions: Default::default() } + } +} + +/// Generates and exports the Coverage Map. +// FIXME(richkadel): Actually generate and export the coverage map to LLVM. +// The current implementation is actually just debug messages to show the data is available. +pub fn finalize(cx: &CodegenCx<'_, '_>) { + let coverage_regions = &*cx.coverage_context().coverage_regions.borrow(); + for instance in coverage_regions.keys() { + let coverageinfo = cx.tcx.coverageinfo(instance.def_id()); + debug_assert!(coverageinfo.num_counters > 0); + debug!( + "Generate coverage map for: {:?}, hash: {}, num_counters: {}", + instance, coverageinfo.hash, coverageinfo.num_counters + ); + let function_coverage_regions = &coverage_regions[instance]; + for (index, region) in function_coverage_regions.indexed_regions() { + match region.kind { + CoverageKind::Counter => debug!( + " Counter {}, for {}..{}", + index, region.coverage_span.start_byte_pos, region.coverage_span.end_byte_pos + ), + CoverageKind::CounterExpression(lhs, op, rhs) => debug!( + " CounterExpression {} = {} {:?} {}, for {}..{}", + index, + lhs, + op, + rhs, + region.coverage_span.start_byte_pos, + region.coverage_span.end_byte_pos + ), + } + } + for unreachable in function_coverage_regions.unreachable_regions() { + debug!( + " Unreachable code region: {}..{}", + unreachable.start_byte_pos, unreachable.end_byte_pos + ); + } + } +} + +impl CoverageInfoMethods for CodegenCx<'ll, 'tcx> { + fn coverageinfo_finalize(&self) { + finalize(self) + } +} + +impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { + fn add_counter_region( + &mut self, + instance: Instance<'tcx>, + index: u32, + start_byte_pos: u32, + end_byte_pos: u32, + ) { + debug!( + "adding counter to coverage map: instance={:?}, index={}, byte range {}..{}", + instance, index, start_byte_pos, end_byte_pos, + ); + let mut coverage_regions = self.coverage_context().coverage_regions.borrow_mut(); + coverage_regions.entry(instance).or_default().add_counter( + index, + start_byte_pos, + end_byte_pos, + ); + } + + fn add_counter_expression_region( + &mut self, + instance: Instance<'tcx>, + index: u32, + lhs: u32, + op: CounterOp, + rhs: u32, + start_byte_pos: u32, + end_byte_pos: u32, + ) { + debug!( + "adding counter expression to coverage map: instance={:?}, index={}, {} {:?} {}, byte range {}..{}", + instance, index, lhs, op, rhs, start_byte_pos, end_byte_pos, + ); + let mut coverage_regions = self.coverage_context().coverage_regions.borrow_mut(); + coverage_regions.entry(instance).or_default().add_counter_expression( + index, + lhs, + op, + rhs, + start_byte_pos, + end_byte_pos, + ); + } + + fn add_unreachable_region( + &mut self, + instance: Instance<'tcx>, + start_byte_pos: u32, + end_byte_pos: u32, + ) { + debug!( + "adding unreachable code to coverage map: instance={:?}, byte range {}..{}", + instance, start_byte_pos, end_byte_pos, + ); + let mut coverage_regions = self.coverage_context().coverage_regions.borrow_mut(); + coverage_regions.entry(instance).or_default().add_unreachable(start_byte_pos, end_byte_pos); + } +} diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 130c0cf1877..de90ac0bac1 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -13,12 +13,15 @@ use rustc_ast::ast; use rustc_codegen_ssa::base::{compare_simd_types, to_immediate, wants_msvc_seh}; use rustc_codegen_ssa::common::span_invalid_monomorphization_error; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; +use rustc_codegen_ssa::coverageinfo::CounterOp; use rustc_codegen_ssa::glue; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::MemFlags; use rustc_hir as hir; +use rustc_middle::mir::coverage; +use rustc_middle::mir::Operand; use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt}; use rustc_middle::ty::{self, Ty}; use rustc_middle::{bug, span_bug}; @@ -81,6 +84,53 @@ fn get_simple_intrinsic(cx: &CodegenCx<'ll, '_>, name: &str) -> Option<&'ll Valu } impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { + fn is_codegen_intrinsic( + &mut self, + intrinsic: &str, + args: &Vec<Operand<'tcx>>, + caller_instance: ty::Instance<'tcx>, + ) -> bool { + match intrinsic { + "count_code_region" => { + use coverage::count_code_region_args::*; + self.add_counter_region( + caller_instance, + op_to_u32(&args[COUNTER_INDEX]), + op_to_u32(&args[START_BYTE_POS]), + op_to_u32(&args[END_BYTE_POS]), + ); + true // Also inject the counter increment in the backend + } + "coverage_counter_add" | "coverage_counter_subtract" => { + use coverage::coverage_counter_expression_args::*; + self.add_counter_expression_region( + caller_instance, + op_to_u32(&args[COUNTER_EXPRESSION_INDEX]), + op_to_u32(&args[LEFT_INDEX]), + if intrinsic == "coverage_counter_add" { + CounterOp::Add + } else { + CounterOp::Subtract + }, + op_to_u32(&args[RIGHT_INDEX]), + op_to_u32(&args[START_BYTE_POS]), + op_to_u32(&args[END_BYTE_POS]), + ); + false // Does not inject backend code + } + "coverage_unreachable" => { + use coverage::coverage_unreachable_args::*; + self.add_unreachable_region( + caller_instance, + op_to_u32(&args[START_BYTE_POS]), + op_to_u32(&args[END_BYTE_POS]), + ); + false // Does not inject backend code + } + _ => true, // Unhandled intrinsics should be passed to `codegen_intrinsic_call()` + } + } + fn codegen_intrinsic_call( &mut self, instance: ty::Instance<'tcx>, @@ -143,15 +193,16 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { // FIXME(richkadel): The current implementation assumes the MIR for the given // caller_instance represents a single function. Validate and/or correct if inlining // and/or monomorphization invalidates these assumptions. - let coverage_data = tcx.coverage_data(caller_instance.def_id()); + let coverageinfo = tcx.coverageinfo(caller_instance.def_id()); let mangled_fn = tcx.symbol_name(caller_instance); let (mangled_fn_name, _len_val) = self.const_str(mangled_fn.name); - let hash = self.const_u64(coverage_data.hash); - let num_counters = self.const_u32(coverage_data.num_counters); - let index = args[0].immediate(); + let hash = self.const_u64(coverageinfo.hash); + let num_counters = self.const_u32(coverageinfo.num_counters); + use coverage::count_code_region_args::*; + let index = args[COUNTER_INDEX].immediate(); debug!( "count_code_region to LLVM intrinsic instrprof.increment(fn_name={}, hash={:?}, num_counters={:?}, index={:?})", - mangled_fn.name, hash, num_counters, index + mangled_fn.name, hash, num_counters, index, ); self.instrprof_increment(mangled_fn_name, hash, num_counters, index) } @@ -2131,3 +2182,7 @@ fn float_type_width(ty: Ty<'_>) -> Option<u64> { _ => None, } } + +fn op_to_u32<'tcx>(op: &Operand<'tcx>) -> u32 { + Operand::scalar_from_const(op).to_u32().expect("Scalar is u32") +} diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 55ee660d9f7..565968f9952 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -55,6 +55,7 @@ mod callee; mod common; mod consts; mod context; +mod coverageinfo; mod debuginfo; mod declare; mod intrinsic; diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index 80278bb9f53..2e2ce154410 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -250,8 +250,11 @@ const RISCV_WHITELIST: &[(&str, Option<Symbol>)] = &[ ("e", Some(sym::riscv_target_feature)), ]; -const WASM_WHITELIST: &[(&str, Option<Symbol>)] = - &[("simd128", Some(sym::wasm_target_feature)), ("atomics", Some(sym::wasm_target_feature))]; +const WASM_WHITELIST: &[(&str, Option<Symbol>)] = &[ + ("simd128", Some(sym::wasm_target_feature)), + ("atomics", Some(sym::wasm_target_feature)), + ("nontrapping-fptoint", Some(sym::wasm_target_feature)), +]; /// When rustdoc is running, provide a list of all known features so that all their respective /// primitives may be documented. diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index a3402941078..3adaa07db91 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1597,6 +1597,9 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( cmd.arg(format!("--dynamic-linker={}ld.so.1", prefix)); } + // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER + cmd.add_eh_frame_header(); + // NO-OPT-OUT, OBJECT-FILES-NO if crt_objects_fallback { cmd.no_crt_objects(); diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs index d6ef94bfd17..54f55c806d0 100644 --- a/src/librustc_codegen_ssa/back/linker.rs +++ b/src/librustc_codegen_ssa/back/linker.rs @@ -129,6 +129,7 @@ pub trait Linker { fn group_start(&mut self); fn group_end(&mut self); fn linker_plugin_lto(&mut self); + fn add_eh_frame_header(&mut self) {} fn finalize(&mut self); } @@ -615,6 +616,19 @@ impl<'a> Linker for GccLinker<'a> { } } } + + // Add the `GNU_EH_FRAME` program header which is required to locate unwinding information. + // Some versions of `gcc` add it implicitly, some (e.g. `musl-gcc`) don't, + // so we just always add it. + fn add_eh_frame_header(&mut self) { + // The condition here is "uses ELF" basically. + if !self.sess.target.target.options.is_like_osx + && !self.sess.target.target.options.is_like_windows + && self.sess.target.target.target_os != "uefi" + { + self.linker_arg("--eh-frame-hdr"); + } + } } pub struct MsvcLinker<'a> { diff --git a/src/librustc_codegen_ssa/coverageinfo/map.rs b/src/librustc_codegen_ssa/coverageinfo/map.rs new file mode 100644 index 00000000000..3bd262cf2b2 --- /dev/null +++ b/src/librustc_codegen_ssa/coverageinfo/map.rs @@ -0,0 +1,83 @@ +use rustc_data_structures::fx::FxHashMap; +use std::collections::hash_map; +use std::slice; + +#[derive(Copy, Clone, Debug)] +pub enum CounterOp { + Add, + Subtract, +} + +pub enum CoverageKind { + Counter, + CounterExpression(u32, CounterOp, u32), +} + +pub struct CoverageSpan { + pub start_byte_pos: u32, + pub end_byte_pos: u32, +} + +pub struct CoverageRegion { + pub kind: CoverageKind, + pub coverage_span: CoverageSpan, +} + +/// Collects all of the coverage regions associated with (a) injected counters, (b) counter +/// expressions (additions or subtraction), and (c) unreachable regions (always counted as zero), +/// for a given Function. Counters and counter expressions are indexed because they can be operands +/// in an expression. +/// +/// Note, it's important to distinguish the `unreachable` region type from what LLVM's refers to as +/// a "gap region" (or "gap area"). A gap region is a code region within a counted region (either +/// counter or expression), but the line or lines in the gap region are not executable (such as +/// lines with only whitespace or comments). According to LLVM Code Coverage Mapping documentation, +/// "A count for a gap area is only used as the line execution count if there are no other regions +/// on a line." +#[derive(Default)] +pub struct FunctionCoverageRegions { + indexed: FxHashMap<u32, CoverageRegion>, + unreachable: Vec<CoverageSpan>, +} + +impl FunctionCoverageRegions { + pub fn add_counter(&mut self, index: u32, start_byte_pos: u32, end_byte_pos: u32) { + self.indexed.insert( + index, + CoverageRegion { + kind: CoverageKind::Counter, + coverage_span: CoverageSpan { start_byte_pos, end_byte_pos }, + }, + ); + } + + pub fn add_counter_expression( + &mut self, + index: u32, + lhs: u32, + op: CounterOp, + rhs: u32, + start_byte_pos: u32, + end_byte_pos: u32, + ) { + self.indexed.insert( + index, + CoverageRegion { + kind: CoverageKind::CounterExpression(lhs, op, rhs), + coverage_span: CoverageSpan { start_byte_pos, end_byte_pos }, + }, + ); + } + + pub fn add_unreachable(&mut self, start_byte_pos: u32, end_byte_pos: u32) { + self.unreachable.push(CoverageSpan { start_byte_pos, end_byte_pos }); + } + + pub fn indexed_regions(&self) -> hash_map::Iter<'_, u32, CoverageRegion> { + self.indexed.iter() + } + + pub fn unreachable_regions(&self) -> slice::Iter<'_, CoverageSpan> { + self.unreachable.iter() + } +} diff --git a/src/librustc_codegen_ssa/coverageinfo/mod.rs b/src/librustc_codegen_ssa/coverageinfo/mod.rs new file mode 100644 index 00000000000..304f8e19da4 --- /dev/null +++ b/src/librustc_codegen_ssa/coverageinfo/mod.rs @@ -0,0 +1,3 @@ +pub mod map; + +pub use map::CounterOp; diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs index bd3721850f3..618df15f5bc 100644 --- a/src/librustc_codegen_ssa/lib.rs +++ b/src/librustc_codegen_ssa/lib.rs @@ -34,6 +34,7 @@ use std::path::{Path, PathBuf}; pub mod back; pub mod base; pub mod common; +pub mod coverageinfo; pub mod debuginfo; pub mod glue; pub mod meth; diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 480f9a50320..7514eb8e889 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -651,6 +651,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } if intrinsic.is_some() && intrinsic != Some("drop_in_place") { + let intrinsic = intrinsic.unwrap(); + + // `is_codegen_intrinsic()` allows the backend implementation to perform compile-time + // operations before converting the `args` to backend values. + if !bx.is_codegen_intrinsic(intrinsic, &args, self.instance) { + // If the intrinsic call was fully addressed by the `is_codegen_intrinsic()` call + // (as a compile-time operation), return immediately. This avoids the need to + // convert the arguments, the call to `codegen_intrinsic_call()`, and the return + // value handling. + return; + } + let dest = match ret_dest { _ if fn_abi.ret.is_indirect() => llargs[0], ReturnDest::Nothing => { @@ -670,7 +682,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // third argument must be constant. This is // checked by const-qualification, which also // promotes any complex rvalues to constants. - if i == 2 && intrinsic.unwrap().starts_with("simd_shuffle") { + if i == 2 && intrinsic.starts_with("simd_shuffle") { if let mir::Operand::Constant(constant) = arg { let c = self.eval_mir_constant(constant); let (llval, ty) = self.simd_shuffle_indices( diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 57f72b1065d..4b2be7b5321 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -774,12 +774,17 @@ fn cast_float_to_int<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( float_ty: Bx::Type, int_ty: Bx::Type, ) -> Bx::Value { - let fptosui_result = if signed { bx.fptosi(x, int_ty) } else { bx.fptoui(x, int_ty) }; - if let Some(false) = bx.cx().sess().opts.debugging_opts.saturating_float_casts { - return fptosui_result; + return if signed { bx.fptosi(x, int_ty) } else { bx.fptoui(x, int_ty) }; + } + + let try_sat_result = if signed { bx.fptosi_sat(x, int_ty) } else { bx.fptoui_sat(x, int_ty) }; + if let Some(try_sat_result) = try_sat_result { + return try_sat_result; } + let fptosui_result = if signed { bx.fptosi(x, int_ty) } else { bx.fptoui(x, int_ty) }; + let int_width = bx.cx().int_width(int_ty); let float_width = bx.cx().float_width(float_ty); // LLVM's fpto[su]i returns undef when the input x is infinite, NaN, or does not fit into the diff --git a/src/librustc_codegen_ssa/traits/builder.rs b/src/librustc_codegen_ssa/traits/builder.rs index 7ffc9f15bff..65eb70e173e 100644 --- a/src/librustc_codegen_ssa/traits/builder.rs +++ b/src/librustc_codegen_ssa/traits/builder.rs @@ -1,5 +1,6 @@ use super::abi::AbiBuilderMethods; use super::asm::AsmBuilderMethods; +use super::coverageinfo::CoverageInfoBuilderMethods; use super::debuginfo::DebugInfoBuilderMethods; use super::intrinsic::IntrinsicCallMethods; use super::type_::ArgAbiMethods; @@ -29,6 +30,7 @@ pub enum OverflowOp { pub trait BuilderMethods<'a, 'tcx>: HasCodegen<'tcx> + + CoverageInfoBuilderMethods<'tcx> + DebugInfoBuilderMethods + ArgAbiMethods<'tcx> + AbiBuilderMethods<'tcx> @@ -156,6 +158,8 @@ pub trait BuilderMethods<'a, 'tcx>: fn trunc(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; fn sext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; + fn fptoui_sat(&mut self, val: Self::Value, dest_ty: Self::Type) -> Option<Self::Value>; + fn fptosi_sat(&mut self, val: Self::Value, dest_ty: Self::Type) -> Option<Self::Value>; fn fptoui(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; fn fptosi(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; fn uitofp(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; diff --git a/src/librustc_codegen_ssa/traits/coverageinfo.rs b/src/librustc_codegen_ssa/traits/coverageinfo.rs new file mode 100644 index 00000000000..d80f90fa4fa --- /dev/null +++ b/src/librustc_codegen_ssa/traits/coverageinfo.rs @@ -0,0 +1,35 @@ +use super::BackendTypes; +use crate::coverageinfo::CounterOp; +use rustc_middle::ty::Instance; + +pub trait CoverageInfoMethods: BackendTypes { + fn coverageinfo_finalize(&self); +} + +pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes { + fn add_counter_region( + &mut self, + instance: Instance<'tcx>, + index: u32, + start_byte_pos: u32, + end_byte_pos: u32, + ); + + fn add_counter_expression_region( + &mut self, + instance: Instance<'tcx>, + index: u32, + lhs: u32, + op: CounterOp, + rhs: u32, + start_byte_pos: u32, + end_byte_pos: u32, + ); + + fn add_unreachable_region( + &mut self, + instance: Instance<'tcx>, + start_byte_pos: u32, + end_byte_pos: u32, + ); +} diff --git a/src/librustc_codegen_ssa/traits/intrinsic.rs b/src/librustc_codegen_ssa/traits/intrinsic.rs index f6201949851..e713cc948c1 100644 --- a/src/librustc_codegen_ssa/traits/intrinsic.rs +++ b/src/librustc_codegen_ssa/traits/intrinsic.rs @@ -1,5 +1,6 @@ use super::BackendTypes; use crate::mir::operand::OperandRef; +use rustc_middle::mir::Operand; use rustc_middle::ty::{self, Ty}; use rustc_span::Span; use rustc_target::abi::call::FnAbi; @@ -18,6 +19,16 @@ pub trait IntrinsicCallMethods<'tcx>: BackendTypes { caller_instance: ty::Instance<'tcx>, ); + /// Intrinsic-specific pre-codegen processing, if any is required. Some intrinsics are handled + /// at compile time and do not generate code. Returns true if codegen is required or false if + /// the intrinsic does not need code generation. + fn is_codegen_intrinsic( + &mut self, + intrinsic: &str, + args: &Vec<Operand<'tcx>>, + caller_instance: ty::Instance<'tcx>, + ) -> bool; + fn abort(&mut self); fn assume(&mut self, val: Self::Value); fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value; diff --git a/src/librustc_codegen_ssa/traits/mod.rs b/src/librustc_codegen_ssa/traits/mod.rs index 6b782731d53..0ac519dd0b1 100644 --- a/src/librustc_codegen_ssa/traits/mod.rs +++ b/src/librustc_codegen_ssa/traits/mod.rs @@ -19,6 +19,7 @@ mod asm; mod backend; mod builder; mod consts; +mod coverageinfo; mod debuginfo; mod declare; mod intrinsic; @@ -32,6 +33,7 @@ pub use self::asm::{AsmBuilderMethods, AsmMethods, InlineAsmOperandRef}; pub use self::backend::{Backend, BackendTypes, CodegenBackend, ExtraBackendMethods}; pub use self::builder::{BuilderMethods, OverflowOp}; pub use self::consts::ConstMethods; +pub use self::coverageinfo::{CoverageInfoBuilderMethods, CoverageInfoMethods}; pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoMethods}; pub use self::declare::{DeclareMethods, PreDefineMethods}; pub use self::intrinsic::IntrinsicCallMethods; @@ -56,6 +58,7 @@ pub trait CodegenMethods<'tcx>: + MiscMethods<'tcx> + ConstMethods<'tcx> + StaticMethods + + CoverageInfoMethods + DebugInfoMethods<'tcx> + DeclareMethods<'tcx> + AsmMethods @@ -72,6 +75,7 @@ impl<'tcx, T> CodegenMethods<'tcx> for T where + MiscMethods<'tcx> + ConstMethods<'tcx> + StaticMethods + + CoverageInfoMethods + DebugInfoMethods<'tcx> + DeclareMethods<'tcx> + AsmMethods diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs index 197169b7036..7cf5202d919 100644 --- a/src/librustc_data_structures/obligation_forest/mod.rs +++ b/src/librustc_data_structures/obligation_forest/mod.rs @@ -412,9 +412,7 @@ impl<O: ForestObligation> ObligationForest<O> { // be computed with the initial length, and we would miss the appended // nodes. Therefore we use a `while` loop. let mut index = 0; - while index < self.nodes.len() { - let node = &mut self.nodes[index]; - + while let Some(node) = self.nodes.get_mut(index) { // `processor.process_obligation` can modify the predicate within // `node.obligation`, and that predicate is the key used for // `self.active_cache`. This means that `self.active_cache` can get @@ -666,8 +664,8 @@ impl<O: ForestObligation> ObligationForest<O> { for node in &mut self.nodes { let mut i = 0; - while i < node.dependents.len() { - let new_index = node_rewrites[node.dependents[i]]; + while let Some(dependent) = node.dependents.get_mut(i) { + let new_index = node_rewrites[*dependent]; if new_index >= orig_nodes_len { node.dependents.swap_remove(i); if i == 0 && node.has_parent { @@ -675,7 +673,7 @@ impl<O: ForestObligation> ObligationForest<O> { node.has_parent = false; } } else { - node.dependents[i] = new_index; + *dependent = new_index; i += 1; } } diff --git a/src/librustc_data_structures/transitive_relation.rs b/src/librustc_data_structures/transitive_relation.rs index de503fe8228..189da3395ad 100644 --- a/src/librustc_data_structures/transitive_relation.rs +++ b/src/librustc_data_structures/transitive_relation.rs @@ -391,14 +391,12 @@ impl<T: Clone + Debug + Eq + Hash> TransitiveRelation<T> { /// - Input: `[a, x, b, y]`. Output: `[a, x]`. fn pare_down(candidates: &mut Vec<usize>, closure: &BitMatrix<usize, usize>) { let mut i = 0; - while i < candidates.len() { - let candidate_i = candidates[i]; + while let Some(&candidate_i) = candidates.get(i) { i += 1; let mut j = i; let mut dead = 0; - while j < candidates.len() { - let candidate_j = candidates[j]; + while let Some(&candidate_j) = candidates.get(j) { if closure.contains(candidate_i, candidate_j) { // If `i` can reach `j`, then we can remove `j`. So just // mark it as dead and move on; subsequent indices will be diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index b45ab0f80ff..c2c19b6b405 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -6,6 +6,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(nll)] +#![cfg_attr(bootstrap, feature(track_caller))] #![recursion_limit = "256"] #[macro_use] diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 0a21eb8de05..6a34a310f73 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -80,8 +80,7 @@ where PpmTyped => { abort_on_err(tcx.analysis(LOCAL_CRATE), tcx.sess); - let empty_tables = ty::TypeckTables::empty(None); - let annotation = TypedAnnotation { tcx, tables: Cell::new(&empty_tables) }; + let annotation = TypedAnnotation { tcx, maybe_typeck_tables: Cell::new(None) }; tcx.dep_graph.with_ignore(|| f(&annotation, tcx.hir().krate())) } _ => panic!("Should use call_with_pp_support"), @@ -304,12 +303,22 @@ impl<'a> pprust::PpAnn for HygieneAnnotation<'a> { } } -struct TypedAnnotation<'a, 'tcx> { +struct TypedAnnotation<'tcx> { tcx: TyCtxt<'tcx>, - tables: Cell<&'a ty::TypeckTables<'tcx>>, + maybe_typeck_tables: Cell<Option<&'tcx ty::TypeckTables<'tcx>>>, } -impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> { +impl<'tcx> TypedAnnotation<'tcx> { + /// Gets the type-checking side-tables for the current body. + /// As this will ICE if called outside bodies, only call when working with + /// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies). + #[track_caller] + fn tables(&self) -> &'tcx ty::TypeckTables<'tcx> { + self.maybe_typeck_tables.get().expect("`TypedAnnotation::tables` called outside of body") + } +} + +impl<'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'tcx> { fn sess(&self) -> &Session { &self.tcx.sess } @@ -327,15 +336,15 @@ impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> { } } -impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> { +impl<'tcx> pprust_hir::PpAnn for TypedAnnotation<'tcx> { fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) { - let old_tables = self.tables.get(); + let old_maybe_typeck_tables = self.maybe_typeck_tables.get(); if let pprust_hir::Nested::Body(id) = nested { - self.tables.set(self.tcx.body_tables(id)); + self.maybe_typeck_tables.set(Some(self.tcx.body_tables(id))); } let pp_ann = &(&self.tcx.hir() as &dyn hir::intravisit::Map<'_>); pprust_hir::PpAnn::nested(pp_ann, state, nested); - self.tables.set(old_tables); + self.maybe_typeck_tables.set(old_maybe_typeck_tables); } fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) { if let pprust_hir::AnnNode::Expr(_) = node { @@ -347,7 +356,7 @@ impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> { s.s.space(); s.s.word("as"); s.s.space(); - s.s.word(self.tables.get().expr_ty(expr).to_string()); + s.s.word(self.tables().expr_ty(expr).to_string()); s.pclose(); } } diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 162585360fb..00c072e1b04 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -382,6 +382,7 @@ E0668: include_str!("./error_codes/E0668.md"), E0669: include_str!("./error_codes/E0669.md"), E0670: include_str!("./error_codes/E0670.md"), E0671: include_str!("./error_codes/E0671.md"), +E0687: include_str!("./error_codes/E0687.md"), E0689: include_str!("./error_codes/E0689.md"), E0690: include_str!("./error_codes/E0690.md"), E0691: include_str!("./error_codes/E0691.md"), @@ -447,6 +448,7 @@ E0763: include_str!("./error_codes/E0763.md"), E0764: include_str!("./error_codes/E0764.md"), E0765: include_str!("./error_codes/E0765.md"), E0766: include_str!("./error_codes/E0766.md"), +E0767: include_str!("./error_codes/E0767.md"), ; // E0006, // merged with E0005 // E0008, // cannot bind by-move into a pattern guard @@ -613,7 +615,6 @@ E0766: include_str!("./error_codes/E0766.md"), E0640, // infer outlives requirements // E0645, // trait aliases not finished E0667, // `impl Trait` in projections - E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders // E0694, // an unknown tool name found in scoped attributes // E0702, // replaced with a generic attribute input check diff --git a/src/librustc_error_codes/error_codes/E0687.md b/src/librustc_error_codes/error_codes/E0687.md new file mode 100644 index 00000000000..67b7db2d31f --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0687.md @@ -0,0 +1,36 @@ +In-band lifetimes cannot be used in `fn`/`Fn` syntax. + +Erroneous code examples: + +```compile_fail,E0687 +#![feature(in_band_lifetimes)] + +fn foo(x: fn(&'a u32)) {} // error! + +fn bar(x: &Fn(&'a u32)) {} // error! + +fn baz(x: fn(&'a u32), y: &'a u32) {} // error! + +struct Foo<'a> { x: &'a u32 } + +impl Foo<'a> { + fn bar(&self, x: fn(&'a u32)) {} // error! +} +``` + +Lifetimes used in `fn` or `Fn` syntax must be explicitly +declared using `<...>` binders. For example: + +``` +fn foo<'a>(x: fn(&'a u32)) {} // ok! + +fn bar<'a>(x: &Fn(&'a u32)) {} // ok! + +fn baz<'a>(x: fn(&'a u32), y: &'a u32) {} // ok! + +struct Foo<'a> { x: &'a u32 } + +impl<'a> Foo<'a> { + fn bar(&self, x: fn(&'a u32)) {} // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0712.md b/src/librustc_error_codes/error_codes/E0712.md index 89f60084f0a..7e09210e787 100644 --- a/src/librustc_error_codes/error_codes/E0712.md +++ b/src/librustc_error_codes/error_codes/E0712.md @@ -1,5 +1,5 @@ -This error occurs because a borrow of a thread-local variable was made inside a -function which outlived the lifetime of the function. +A borrow of a thread-local variable was made inside a function which outlived +the lifetime of the function. Erroneous code example: diff --git a/src/librustc_error_codes/error_codes/E0736.md b/src/librustc_error_codes/error_codes/E0736.md index 8a60dc32059..0f3d41ba66d 100644 --- a/src/librustc_error_codes/error_codes/E0736.md +++ b/src/librustc_error_codes/error_codes/E0736.md @@ -3,8 +3,6 @@ Erroneous code example: ```compile_fail,E0736 -#![feature(track_caller)] - #[naked] #[track_caller] fn foo() {} diff --git a/src/librustc_error_codes/error_codes/E0737.md b/src/librustc_error_codes/error_codes/E0737.md index c6553e97b7e..ab5e60692b4 100644 --- a/src/librustc_error_codes/error_codes/E0737.md +++ b/src/librustc_error_codes/error_codes/E0737.md @@ -5,8 +5,6 @@ restrictions. Erroneous code example: ```compile_fail,E0737 -#![feature(track_caller)] - #[track_caller] extern "C" fn foo() {} ``` diff --git a/src/librustc_error_codes/error_codes/E0739.md b/src/librustc_error_codes/error_codes/E0739.md index 707751066ed..8d9039bef93 100644 --- a/src/librustc_error_codes/error_codes/E0739.md +++ b/src/librustc_error_codes/error_codes/E0739.md @@ -3,7 +3,6 @@ Erroneous code example: ```compile_fail,E0739 -#![feature(track_caller)] #[track_caller] struct Bar { a: u8, diff --git a/src/librustc_error_codes/error_codes/E0767.md b/src/librustc_error_codes/error_codes/E0767.md new file mode 100644 index 00000000000..679fe7e41e9 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0767.md @@ -0,0 +1,20 @@ +An unreachable label was used. + +Erroneous code example: + +```compile_fail,E0767 +'a: loop { + || { + loop { break 'a } // error: use of unreachable label `'a` + }; +} +``` + +Ensure that the label is within scope. Labels are not reachable through +functions, closures, async blocks or modules. Example: + +``` +'a: loop { + break 'a; // ok! +} +``` diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 0c1418d3cad..362913ceadf 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -5,7 +5,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(crate_visibility_modifier)] #![feature(nll)] -#![feature(track_caller)] +#![cfg_attr(bootstrap, feature(track_caller))] pub use emitter::ColorConfig; diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs index 757eee8bb46..db9293bddeb 100644 --- a/src/librustc_expand/base.rs +++ b/src/librustc_expand/base.rs @@ -4,14 +4,14 @@ use crate::module::DirectoryOwnership; use rustc_ast::ast::{self, Attribute, NodeId, PatKind}; use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::ptr::P; -use rustc_ast::token::{self, FlattenGroup}; -use rustc_ast::tokenstream::{self, TokenStream, TokenTree}; +use rustc_ast::token; +use rustc_ast::tokenstream::{self, TokenStream}; use rustc_ast::visit::{AssocCtxt, Visitor}; use rustc_attr::{self as attr, Deprecation, HasAttrs, Stability}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{self, Lrc}; use rustc_errors::{DiagnosticBuilder, ErrorReported}; -use rustc_parse::{self, parser, MACRO_ARGUMENTS}; +use rustc_parse::{self, nt_to_tokenstream, parser, MACRO_ARGUMENTS}; use rustc_session::{parse::ParseSess, Limit}; use rustc_span::def_id::DefId; use rustc_span::edition::Edition; @@ -120,10 +120,7 @@ impl Annotatable { } } - crate fn into_tokens(self) -> TokenStream { - // `Annotatable` can be converted into tokens directly, but we - // are packing it into a nonterminal as a piece of AST to make - // the produced token stream look nicer in pretty-printed form. + crate fn into_tokens(self, sess: &ParseSess) -> TokenStream { let nt = match self { Annotatable::Item(item) => token::NtItem(item), Annotatable::TraitItem(item) | Annotatable::ImplItem(item) => { @@ -142,7 +139,7 @@ impl Annotatable { | Annotatable::StructField(..) | Annotatable::Variant(..) => panic!("unexpected annotatable"), }; - TokenTree::token(token::Interpolated(Lrc::new(nt), FlattenGroup::Yes), DUMMY_SP).into() + nt_to_tokenstream(&nt, sess, DUMMY_SP) } pub fn expect_item(self) -> P<ast::Item> { @@ -374,7 +371,7 @@ where impl MutVisitor for AvoidInterpolatedIdents { fn visit_tt(&mut self, tt: &mut tokenstream::TokenTree) { if let tokenstream::TokenTree::Token(token) = tt { - if let token::Interpolated(nt, _) = &token.kind { + if let token::Interpolated(nt) = &token.kind { if let token::NtIdent(ident, is_raw) = **nt { *tt = tokenstream::TokenTree::token( token::Ident(ident.name, is_raw), diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 4e41bd4bbfa..bd7a094c5e3 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -705,7 +705,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { SyntaxExtensionKind::Attr(expander) => { self.gate_proc_macro_input(&item); self.gate_proc_macro_attr_item(span, &item); - let tokens = item.into_tokens(); + let tokens = item.into_tokens(self.cx.parse_sess); let attr_item = attr.unwrap_normal_item(); if let MacArgs::Eq(..) = attr_item.args { self.cx.span_err(span, "key-value macro attributes are not supported"); diff --git a/src/librustc_expand/mbe/macro_parser.rs b/src/librustc_expand/mbe/macro_parser.rs index c90a438c25e..3c15a81c67f 100644 --- a/src/librustc_expand/mbe/macro_parser.rs +++ b/src/librustc_expand/mbe/macro_parser.rs @@ -790,7 +790,7 @@ fn may_begin_with(token: &Token, name: Symbol) -> bool { }, sym::block => match token.kind { token::OpenDelim(token::Brace) => true, - token::Interpolated(ref nt, _) => match **nt { + token::Interpolated(ref nt) => match **nt { token::NtItem(_) | token::NtPat(_) | token::NtTy(_) @@ -804,7 +804,7 @@ fn may_begin_with(token: &Token, name: Symbol) -> bool { }, sym::path | sym::meta => match token.kind { token::ModSep | token::Ident(..) => true, - token::Interpolated(ref nt, _) => match **nt { + token::Interpolated(ref nt) => match **nt { token::NtPath(_) | token::NtMeta(_) => true, _ => may_be_ident(&nt), }, @@ -823,12 +823,12 @@ fn may_begin_with(token: &Token, name: Symbol) -> bool { token::ModSep | // path token::Lt | // path (UFCS constant) token::BinOp(token::Shl) => true, // path (double UFCS) - token::Interpolated(ref nt, _) => may_be_ident(nt), + token::Interpolated(ref nt) => may_be_ident(nt), _ => false, }, sym::lifetime => match token.kind { token::Lifetime(_) => true, - token::Interpolated(ref nt, _) => match **nt { + token::Interpolated(ref nt) => match **nt { token::NtLifetime(_) | token::NtTT(_) => true, _ => false, }, diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs index 8cdb5b09c9e..36b323df697 100644 --- a/src/librustc_expand/mbe/macro_rules.rs +++ b/src/librustc_expand/mbe/macro_rules.rs @@ -224,7 +224,7 @@ fn generic_extension<'cx>( let sess = cx.parse_sess; if cx.trace_macros() { - let msg = format!("expanding `{}! {{ {} }}`", name, pprust::tts_to_string(arg.clone())); + let msg = format!("expanding `{}! {{ {} }}`", name, pprust::tts_to_string(&arg)); trace_macros_note(&mut cx.expansions, sp, msg); } @@ -300,7 +300,7 @@ fn generic_extension<'cx>( } if cx.trace_macros() { - let msg = format!("to `{}`", pprust::tts_to_string(tts.clone())); + let msg = format!("to `{}`", pprust::tts_to_string(&tts)); trace_macros_note(&mut cx.expansions, sp, msg); } @@ -387,6 +387,7 @@ pub fn compile_declarative_macro( def: &ast::Item, edition: Edition, ) -> SyntaxExtension { + debug!("compile_declarative_macro: {:?}", def); let mk_syn_ext = |expander| { SyntaxExtension::new( sess, diff --git a/src/librustc_expand/mbe/quoted.rs b/src/librustc_expand/mbe/quoted.rs index de66c2ada40..09306f26ee0 100644 --- a/src/librustc_expand/mbe/quoted.rs +++ b/src/librustc_expand/mbe/quoted.rs @@ -90,7 +90,7 @@ pub(super) fn parse( /// # Parameters /// /// - `tree`: the tree we wish to convert. -/// - `trees`: an iterator over trees. We may need to read more tokens from it in order to finish +/// - `outer_trees`: an iterator over trees. We may need to read more tokens from it in order to finish /// converting `tree` /// - `expect_matchers`: same as for `parse` (see above). /// - `sess`: the parsing session. Any errors will be emitted to this session. @@ -98,7 +98,7 @@ pub(super) fn parse( /// unstable features or not. fn parse_tree( tree: tokenstream::TokenTree, - trees: &mut impl Iterator<Item = tokenstream::TokenTree>, + outer_trees: &mut impl Iterator<Item = tokenstream::TokenTree>, expect_matchers: bool, sess: &ParseSess, node_id: NodeId, @@ -106,56 +106,72 @@ fn parse_tree( // Depending on what `tree` is, we could be parsing different parts of a macro match tree { // `tree` is a `$` token. Look at the next token in `trees` - tokenstream::TokenTree::Token(Token { kind: token::Dollar, span }) => match trees.next() { - // `tree` is followed by a delimited set of token trees. This indicates the beginning - // of a repetition sequence in the macro (e.g. `$(pat)*`). - Some(tokenstream::TokenTree::Delimited(span, delim, tts)) => { - // Must have `(` not `{` or `[` - if delim != token::Paren { - let tok = pprust::token_kind_to_string(&token::OpenDelim(delim)); - let msg = format!("expected `(`, found `{}`", tok); - sess.span_diagnostic.span_err(span.entire(), &msg); - } - // Parse the contents of the sequence itself - let sequence = parse(tts, expect_matchers, sess, node_id); - // Get the Kleene operator and optional separator - let (separator, kleene) = parse_sep_and_kleene_op(trees, span.entire(), sess); - // Count the number of captured "names" (i.e., named metavars) - let name_captures = macro_parser::count_names(&sequence); - TokenTree::Sequence( - span, - Lrc::new(SequenceRepetition { - tts: sequence, - separator, - kleene, - num_captures: name_captures, - }), - ) + tokenstream::TokenTree::Token(Token { kind: token::Dollar, span }) => { + // FIXME: Handle `None`-delimited groups in a more systematic way + // during parsing. + let mut next = outer_trees.next(); + let mut trees: Box<dyn Iterator<Item = tokenstream::TokenTree>>; + if let Some(tokenstream::TokenTree::Delimited(_, token::NoDelim, tts)) = next { + trees = Box::new(tts.into_trees()); + next = trees.next(); + } else { + trees = Box::new(outer_trees); } - // `tree` is followed by an `ident`. This could be `$meta_var` or the `$crate` special - // metavariable that names the crate of the invocation. - Some(tokenstream::TokenTree::Token(token)) if token.is_ident() => { - let (ident, is_raw) = token.ident().unwrap(); - let span = ident.span.with_lo(span.lo()); - if ident.name == kw::Crate && !is_raw { - TokenTree::token(token::Ident(kw::DollarCrate, is_raw), span) - } else { - TokenTree::MetaVar(span, ident) + match next { + // `tree` is followed by a delimited set of token trees. This indicates the beginning + // of a repetition sequence in the macro (e.g. `$(pat)*`). + Some(tokenstream::TokenTree::Delimited(span, delim, tts)) => { + // Must have `(` not `{` or `[` + if delim != token::Paren { + let tok = pprust::token_kind_to_string(&token::OpenDelim(delim)); + let msg = format!("expected `(`, found `{}`", tok); + sess.span_diagnostic.span_err(span.entire(), &msg); + } + // Parse the contents of the sequence itself + let sequence = parse(tts, expect_matchers, sess, node_id); + // Get the Kleene operator and optional separator + let (separator, kleene) = + parse_sep_and_kleene_op(&mut trees, span.entire(), sess); + // Count the number of captured "names" (i.e., named metavars) + let name_captures = macro_parser::count_names(&sequence); + TokenTree::Sequence( + span, + Lrc::new(SequenceRepetition { + tts: sequence, + separator, + kleene, + num_captures: name_captures, + }), + ) } - } - // `tree` is followed by a random token. This is an error. - Some(tokenstream::TokenTree::Token(token)) => { - let msg = - format!("expected identifier, found `{}`", pprust::token_to_string(&token),); - sess.span_diagnostic.span_err(token.span, &msg); - TokenTree::MetaVar(token.span, Ident::invalid()) - } + // `tree` is followed by an `ident`. This could be `$meta_var` or the `$crate` special + // metavariable that names the crate of the invocation. + Some(tokenstream::TokenTree::Token(token)) if token.is_ident() => { + let (ident, is_raw) = token.ident().unwrap(); + let span = ident.span.with_lo(span.lo()); + if ident.name == kw::Crate && !is_raw { + TokenTree::token(token::Ident(kw::DollarCrate, is_raw), span) + } else { + TokenTree::MetaVar(span, ident) + } + } - // There are no more tokens. Just return the `$` we already have. - None => TokenTree::token(token::Dollar, span), - }, + // `tree` is followed by a random token. This is an error. + Some(tokenstream::TokenTree::Token(token)) => { + let msg = format!( + "expected identifier, found `{}`", + pprust::token_to_string(&token), + ); + sess.span_diagnostic.span_err(token.span, &msg); + TokenTree::MetaVar(token.span, Ident::invalid()) + } + + // There are no more tokens. Just return the `$` we already have. + None => TokenTree::token(token::Dollar, span), + } + } // `tree` is an arbitrary token. Keep it. tokenstream::TokenTree::Token(token) => TokenTree::Token(token), diff --git a/src/librustc_expand/mbe/transcribe.rs b/src/librustc_expand/mbe/transcribe.rs index 486f0a6420d..e2d3d5c4d64 100644 --- a/src/librustc_expand/mbe/transcribe.rs +++ b/src/librustc_expand/mbe/transcribe.rs @@ -4,7 +4,7 @@ use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch}; use rustc_ast::ast::MacCall; use rustc_ast::mut_visit::{self, MutVisitor}; -use rustc_ast::token::{self, FlattenGroup, NtTT, Token}; +use rustc_ast::token::{self, NtTT, Token}; use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; @@ -240,10 +240,7 @@ pub(super) fn transcribe<'a>( result.push(tt.clone().into()); } else { marker.visit_span(&mut sp); - let token = TokenTree::token( - token::Interpolated(nt.clone(), FlattenGroup::No), - sp, - ); + let token = TokenTree::token(token::Interpolated(nt.clone()), sp); result.push(token.into()); } } else { diff --git a/src/librustc_expand/proc_macro.rs b/src/librustc_expand/proc_macro.rs index 1e26c832a26..54012d62a72 100644 --- a/src/librustc_expand/proc_macro.rs +++ b/src/librustc_expand/proc_macro.rs @@ -2,10 +2,11 @@ use crate::base::{self, *}; use crate::proc_macro_server; use rustc_ast::ast::{self, ItemKind, MetaItemKind, NestedMetaItem}; -use rustc_ast::token::{self, FlattenGroup}; -use rustc_ast::tokenstream::{self, TokenStream}; +use rustc_ast::token; +use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, ErrorReported}; +use rustc_parse::nt_to_tokenstream; use rustc_span::symbol::sym; use rustc_span::{Span, DUMMY_SP}; @@ -102,8 +103,12 @@ impl MultiItemModifier for ProcMacroDerive { } } - let token = token::Interpolated(Lrc::new(token::NtItem(item)), FlattenGroup::Yes); - let input = tokenstream::TokenTree::token(token, DUMMY_SP).into(); + let item = token::NtItem(item); + let input = if item.pretty_printing_compatibility_hack() { + TokenTree::token(token::Interpolated(Lrc::new(item)), DUMMY_SP).into() + } else { + nt_to_tokenstream(&item, ecx.parse_sess, DUMMY_SP) + }; let server = proc_macro_server::Rustc::new(ecx); let stream = match self.client.run(&EXEC_STRATEGY, server, input) { diff --git a/src/librustc_expand/proc_macro_server.rs b/src/librustc_expand/proc_macro_server.rs index c88b5a37f71..ce53b9c0b66 100644 --- a/src/librustc_expand/proc_macro_server.rs +++ b/src/librustc_expand/proc_macro_server.rs @@ -1,7 +1,7 @@ use crate::base::ExtCtxt; use rustc_ast::ast; -use rustc_ast::token::{self, FlattenGroup}; +use rustc_ast::token; use rustc_ast::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint}; use rustc_ast::util::comments; use rustc_ast_pretty::pprust; @@ -60,12 +60,7 @@ impl FromInternal<(TreeAndJoint, &'_ ParseSess, &'_ mut Vec<Self>)> let Token { kind, span } = match tree { tokenstream::TokenTree::Delimited(span, delim, tts) => { let delimiter = Delimiter::from_internal(delim); - return TokenTree::Group(Group { - delimiter, - stream: tts, - span, - flatten: FlattenGroup::No, - }); + return TokenTree::Group(Group { delimiter, stream: tts, span, flatten: false }); } tokenstream::TokenTree::Token(token) => token, }; @@ -172,7 +167,7 @@ impl FromInternal<(TreeAndJoint, &'_ ParseSess, &'_ mut Vec<Self>)> delimiter: Delimiter::Bracket, stream, span: DelimSpan::from_single(span), - flatten: FlattenGroup::No, + flatten: false, })); if style == ast::AttrStyle::Inner { stack.push(tt!(Punct::new('!', false))); @@ -180,13 +175,13 @@ impl FromInternal<(TreeAndJoint, &'_ ParseSess, &'_ mut Vec<Self>)> tt!(Punct::new('#', false)) } - Interpolated(nt, flatten) => { + Interpolated(nt) => { let stream = nt_to_tokenstream(&nt, sess, span); TokenTree::Group(Group { delimiter: Delimiter::None, stream, span: DelimSpan::from_single(span), - flatten, + flatten: nt.pretty_printing_compatibility_hack(), }) } @@ -293,7 +288,7 @@ pub struct Group { /// A hack used to pass AST fragments to attribute and derive macros /// as a single nonterminal token instead of a token stream. /// FIXME: It needs to be removed, but there are some compatibility issues (see #73345). - flatten: FlattenGroup, + flatten: bool, } #[derive(Copy, Clone, PartialEq, Eq, Hash)] @@ -413,7 +408,7 @@ impl server::TokenStream for Rustc<'_> { ) } fn to_string(&mut self, stream: &Self::TokenStream) -> String { - pprust::tts_to_string(stream.clone()) + pprust::tts_to_string(stream) } fn from_token_tree( &mut self, @@ -453,7 +448,7 @@ impl server::TokenStreamIter for Rustc<'_> { // Such token needs to be "unwrapped" and not represented as a delimited group. // FIXME: It needs to be removed, but there are some compatibility issues (see #73345). if let TokenTree::Group(ref group) = tree { - if matches!(group.flatten, FlattenGroup::Yes) { + if group.flatten { iter.cursor.append(group.stream.clone()); continue; } @@ -469,7 +464,7 @@ impl server::Group for Rustc<'_> { delimiter, stream, span: DelimSpan::from_single(server::Span::call_site(self)), - flatten: FlattenGroup::No, + flatten: false, } } fn delimiter(&mut self, group: &Self::Group) -> Delimiter { diff --git a/src/librustc_feature/accepted.rs b/src/librustc_feature/accepted.rs index b164b21913d..d93c17b05b4 100644 --- a/src/librustc_feature/accepted.rs +++ b/src/librustc_feature/accepted.rs @@ -265,6 +265,9 @@ declare_features! ( (accepted, const_if_match, "1.45.0", Some(49146), None), /// Allows the use of `loop` and `while` in constants. (accepted, const_loop, "1.45.0", Some(52000), None), + /// Allows `#[track_caller]` to be used which provides + /// accurate caller location reporting during panic (RFC 2091). + (accepted, track_caller, "1.46.0", Some(47809), None), // ------------------------------------------------------------------------- // feature-group-end: accepted features diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 8660d6a8d64..b9a55377949 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -494,10 +494,6 @@ declare_features! ( /// Allows the use of raw-dylibs (RFC 2627). (active, raw_dylib, "1.40.0", Some(58713), None), - /// Allows `#[track_caller]` to be used which provides - /// accurate caller location reporting during panic (RFC 2091). - (active, track_caller, "1.40.0", Some(47809), None), - /// Allows making `dyn Trait` well-formed even if `Trait` is not object safe. /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden. diff --git a/src/librustc_feature/builtin_attrs.rs b/src/librustc_feature/builtin_attrs.rs index 524a3579710..c9a34f03375 100644 --- a/src/librustc_feature/builtin_attrs.rs +++ b/src/librustc_feature/builtin_attrs.rs @@ -260,6 +260,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ungated!(cold, Whitelisted, template!(Word)), ungated!(no_builtins, Whitelisted, template!(Word)), ungated!(target_feature, Whitelisted, template!(List: r#"enable = "name""#)), + ungated!(track_caller, Whitelisted, template!(Word)), gated!( no_sanitize, Whitelisted, template!(List: "address, memory, thread"), @@ -333,7 +334,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ gated!(ffi_returns_twice, Whitelisted, template!(Word), experimental!(ffi_returns_twice)), gated!(ffi_pure, Whitelisted, template!(Word), experimental!(ffi_pure)), gated!(ffi_const, Whitelisted, template!(Word), experimental!(ffi_const)), - gated!(track_caller, Whitelisted, template!(Word), experimental!(track_caller)), gated!( register_attr, CrateLevel, template!(List: "attr1, attr2, ..."), experimental!(register_attr), diff --git a/src/librustc_index/vec.rs b/src/librustc_index/vec.rs index 4dde33283f5..c5dedab9793 100644 --- a/src/librustc_index/vec.rs +++ b/src/librustc_index/vec.rs @@ -536,7 +536,8 @@ impl<I: Idx, T> IndexVec<I, T> { } /// Create an `IndexVec` with `n` elements, where the value of each - /// element is the result of `func(i)` + /// element is the result of `func(i)`. (The underlying vector will + /// be allocated only once, with a capacity of at least `n`.) #[inline] pub fn from_fn_n(func: impl FnMut(I) -> T, n: usize) -> Self { let indices = (0..n).map(I::new); diff --git a/src/librustc_infer/infer/at.rs b/src/librustc_infer/infer/at.rs index d44b8f55414..a7749d33b7c 100644 --- a/src/librustc_infer/infer/at.rs +++ b/src/librustc_infer/infer/at.rs @@ -82,7 +82,7 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - self.trace_exp(a_is_expected, a, b).sub(&a, &b) + self.trace_exp(a_is_expected, a, b).sub(a, b) } /// Makes `actual <: expected`. For example, if type-checking a @@ -109,7 +109,7 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - self.trace_exp(a_is_expected, a, b).eq(&a, &b) + self.trace_exp(a_is_expected, a, b).eq(a, b) } /// Makes `expected <: actual`. @@ -117,7 +117,7 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - self.trace(expected, actual).eq(&expected, &actual) + self.trace(expected, actual).eq(expected, actual) } pub fn relate<T>(self, expected: T, variance: ty::Variance, actual: T) -> InferResult<'tcx, ()> @@ -147,7 +147,7 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - self.trace(expected, actual).lub(&expected, &actual) + self.trace(expected, actual).lub(expected, actual) } /// Computes the greatest-lower-bound, or mutual subtype, of two @@ -157,7 +157,7 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - self.trace(expected, actual).glb(&expected, &actual) + self.trace(expected, actual).glb(expected, actual) } /// Sets the "trace" values that will be used for @@ -186,7 +186,7 @@ impl<'a, 'tcx> At<'a, 'tcx> { impl<'a, 'tcx> Trace<'a, 'tcx> { /// Makes `a <: b` where `a` may or may not be expected (if /// `a_is_expected` is true, then `a` is expected). - pub fn sub<T>(self, a: &T, b: &T) -> InferResult<'tcx, ()> + pub fn sub<T>(self, a: T, b: T) -> InferResult<'tcx, ()> where T: Relate<'tcx>, { @@ -203,7 +203,7 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { /// Makes `a == b`; the expectation is set by the call to /// `trace()`. - pub fn eq<T>(self, a: &T, b: &T) -> InferResult<'tcx, ()> + pub fn eq<T>(self, a: T, b: T) -> InferResult<'tcx, ()> where T: Relate<'tcx>, { @@ -218,7 +218,7 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { }) } - pub fn lub<T>(self, a: &T, b: &T) -> InferResult<'tcx, T> + pub fn lub<T>(self, a: T, b: T) -> InferResult<'tcx, T> where T: Relate<'tcx>, { @@ -233,7 +233,7 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { }) } - pub fn glb<T>(self, a: &T, b: &T) -> InferResult<'tcx, T> + pub fn glb<T>(self, a: T, b: T) -> InferResult<'tcx, T> where T: Relate<'tcx>, { diff --git a/src/librustc_infer/infer/canonical/query_response.rs b/src/librustc_infer/infer/canonical/query_response.rs index 8af526e3ad3..5cba581b9df 100644 --- a/src/librustc_infer/infer/canonical/query_response.rs +++ b/src/librustc_infer/infer/canonical/query_response.rs @@ -271,7 +271,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { }, ty::Variance::Invariant, ) - .relate(&v1, &v2)?; + .relate(v1, v2)?; } (GenericArgKind::Const(v1), GenericArgKind::Const(v2)) => { @@ -285,7 +285,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { }, ty::Variance::Invariant, ) - .relate(&v1, &v2)?; + .relate(v1, v2)?; } _ => { @@ -302,7 +302,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { // Screen out `'a: 'a` cases -- we skip the binder here but // only compare the inner values to one another, so they are still at // consistent binding levels. - let &ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); + let ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); if k1 != r2.into() { Some(r_c) } else { None } }), ); @@ -526,7 +526,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { ) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a + Captures<'tcx> { unsubstituted_region_constraints.iter().map(move |constraint| { let constraint = substitute_value(self.tcx, result_subst, constraint); - let &ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below + let ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below Obligation::new( cause.clone(), diff --git a/src/librustc_infer/infer/combine.rs b/src/librustc_infer/infer/combine.rs index 4ef4ed47cb1..c8d4e9f0e14 100644 --- a/src/librustc_infer/infer/combine.rs +++ b/src/librustc_infer/infer/combine.rs @@ -318,10 +318,10 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { // to associate causes/spans with each of the relations in // the stack to get this right. match dir { - EqTo => self.equate(a_is_expected).relate(&a_ty, &b_ty), - SubtypeOf => self.sub(a_is_expected).relate(&a_ty, &b_ty), + EqTo => self.equate(a_is_expected).relate(a_ty, b_ty), + SubtypeOf => self.sub(a_is_expected).relate(a_ty, b_ty), SupertypeOf => { - self.sub(a_is_expected).relate_with_variance(ty::Contravariant, &a_ty, &b_ty) + self.sub(a_is_expected).relate_with_variance(ty::Contravariant, a_ty, b_ty) } }?; @@ -379,7 +379,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { param_env: self.param_env, }; - let ty = match generalize.relate(&ty, &ty) { + let ty = match generalize.relate(ty, ty) { Ok(ty) => ty, Err(e) => { debug!("generalize: failure {:?}", e); @@ -490,8 +490,8 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { fn binders<T>( &mut self, - a: &ty::Binder<T>, - b: &ty::Binder<T>, + a: ty::Binder<T>, + b: ty::Binder<T>, ) -> RelateResult<'tcx, ty::Binder<T>> where T: Relate<'tcx>, @@ -519,8 +519,8 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { fn relate_with_variance<T: Relate<'tcx>>( &mut self, variance: ty::Variance, - a: &T, - b: &T, + a: T, + b: T, ) -> RelateResult<'tcx, T> { let old_ambient_variance = self.ambient_variance; self.ambient_variance = self.ambient_variance.xform(variance); @@ -552,7 +552,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { match probe { TypeVariableValue::Known { value: u } => { debug!("generalize: known value {:?}", u); - self.relate(&u, &u) + self.relate(u, u) } TypeVariableValue::Unknown { universe } => { match self.ambient_variance { @@ -655,7 +655,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { let variable_table = &mut inner.const_unification_table(); let var_value = variable_table.probe_value(vid); match var_value.val { - ConstVariableValue::Known { value: u } => self.relate(&u, &u), + ConstVariableValue::Known { value: u } => self.relate(u, u), ConstVariableValue::Unknown { universe } => { if self.for_universe.can_name(universe) { Ok(c) diff --git a/src/librustc_infer/infer/equate.rs b/src/librustc_infer/infer/equate.rs index e3cafb82719..7de752d1de0 100644 --- a/src/librustc_infer/infer/equate.rs +++ b/src/librustc_infer/infer/equate.rs @@ -59,8 +59,8 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> { fn relate_with_variance<T: Relate<'tcx>>( &mut self, _: ty::Variance, - a: &T, - b: &T, + a: T, + b: T, ) -> RelateResult<'tcx, T> { self.relate(a, b) } @@ -124,8 +124,8 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> { fn binders<T>( &mut self, - a: &ty::Binder<T>, - b: &ty::Binder<T>, + a: ty::Binder<T>, + b: ty::Binder<T>, ) -> RelateResult<'tcx, ty::Binder<T>> where T: Relate<'tcx>, @@ -136,7 +136,7 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> { } else { // Fast path for the common case. self.relate(a.skip_binder(), b.skip_binder())?; - Ok(a.clone()) + Ok(a) } } } diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index 7fdcbd31df3..b1ea2223707 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -1684,7 +1684,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // Attempt to obtain the span of the parameter so we can // suggest adding an explicit lifetime bound to it. let generics = - self.in_progress_tables.and_then(|table| table.borrow().hir_owner).map(|table_owner| { + self.in_progress_tables.map(|table| table.borrow().hir_owner).map(|table_owner| { let hir_id = hir.as_local_hir_id(table_owner); let parent_id = hir.get_parent_item(hir_id); ( diff --git a/src/librustc_infer/infer/glb.rs b/src/librustc_infer/infer/glb.rs index ec219a95b94..8a0ab52f383 100644 --- a/src/librustc_infer/infer/glb.rs +++ b/src/librustc_infer/infer/glb.rs @@ -43,8 +43,8 @@ impl TypeRelation<'tcx> for Glb<'combine, 'infcx, 'tcx> { fn relate_with_variance<T: Relate<'tcx>>( &mut self, variance: ty::Variance, - a: &T, - b: &T, + a: T, + b: T, ) -> RelateResult<'tcx, T> { match variance { ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b), @@ -85,8 +85,8 @@ impl TypeRelation<'tcx> for Glb<'combine, 'infcx, 'tcx> { fn binders<T>( &mut self, - a: &ty::Binder<T>, - b: &ty::Binder<T>, + a: ty::Binder<T>, + b: ty::Binder<T>, ) -> RelateResult<'tcx, ty::Binder<T>> where T: Relate<'tcx>, @@ -112,8 +112,8 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx, fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> { let mut sub = self.fields.sub(self.a_is_expected); - sub.relate(&v, &a)?; - sub.relate(&v, &b)?; + sub.relate(v, a)?; + sub.relate(v, b)?; Ok(()) } } diff --git a/src/librustc_infer/infer/higher_ranked/mod.rs b/src/librustc_infer/infer/higher_ranked/mod.rs index b6251e34008..ea19dff7db1 100644 --- a/src/librustc_infer/infer/higher_ranked/mod.rs +++ b/src/librustc_infer/infer/higher_ranked/mod.rs @@ -11,8 +11,8 @@ use rustc_middle::ty::{self, Binder, TypeFoldable}; impl<'a, 'tcx> CombineFields<'a, 'tcx> { pub fn higher_ranked_sub<T>( &mut self, - a: &Binder<T>, - b: &Binder<T>, + a: Binder<T>, + b: Binder<T>, a_is_expected: bool, ) -> RelateResult<'tcx, Binder<T>> where @@ -33,20 +33,20 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { self.infcx.commit_if_ok(|_| { // First, we instantiate each bound region in the supertype with a // fresh placeholder region. - let (b_prime, _) = self.infcx.replace_bound_vars_with_placeholders(b); + let (b_prime, _) = self.infcx.replace_bound_vars_with_placeholders(&b); // Next, we instantiate each bound region in the subtype // with a fresh region variable. These region variables -- // but no other pre-existing region variables -- can name // the placeholders. let (a_prime, _) = - self.infcx.replace_bound_vars_with_fresh_vars(span, HigherRankedType, a); + self.infcx.replace_bound_vars_with_fresh_vars(span, HigherRankedType, &a); debug!("a_prime={:?}", a_prime); debug!("b_prime={:?}", b_prime); // Compare types now that bound regions have been replaced. - let result = self.sub(a_is_expected).relate(&a_prime, &b_prime)?; + let result = self.sub(a_is_expected).relate(a_prime, b_prime)?; debug!("higher_ranked_sub: OK result={:?}", result); diff --git a/src/librustc_infer/infer/lub.rs b/src/librustc_infer/infer/lub.rs index a0453db2cb4..3e2ea3d0f8f 100644 --- a/src/librustc_infer/infer/lub.rs +++ b/src/librustc_infer/infer/lub.rs @@ -43,8 +43,8 @@ impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> { fn relate_with_variance<T: Relate<'tcx>>( &mut self, variance: ty::Variance, - a: &T, - b: &T, + a: T, + b: T, ) -> RelateResult<'tcx, T> { match variance { ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b), @@ -85,8 +85,8 @@ impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> { fn binders<T>( &mut self, - a: &ty::Binder<T>, - b: &ty::Binder<T>, + a: ty::Binder<T>, + b: ty::Binder<T>, ) -> RelateResult<'tcx, ty::Binder<T>> where T: Relate<'tcx>, @@ -97,7 +97,7 @@ impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> { // very challenging, switch to invariance. This is obviously // overly conservative but works ok in practice. self.relate_with_variance(ty::Variance::Invariant, a, b)?; - Ok(a.clone()) + Ok(a) } } @@ -118,8 +118,8 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx, fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> { let mut sub = self.fields.sub(self.a_is_expected); - sub.relate(&a, &v)?; - sub.relate(&b, &v)?; + sub.relate(a, v)?; + sub.relate(b, v)?; Ok(()) } } diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs index 76ac61c0672..27da514a17f 100644 --- a/src/librustc_infer/infer/mod.rs +++ b/src/librustc_infer/infer/mod.rs @@ -588,7 +588,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { /// Used only by `rustc_typeck` during body type-checking/inference, /// will initialize `in_progress_tables` with fresh `TypeckTables`. pub fn with_fresh_in_progress_tables(mut self, table_owner: LocalDefId) -> Self { - self.fresh_tables = Some(RefCell::new(ty::TypeckTables::empty(Some(table_owner)))); + self.fresh_tables = Some(RefCell::new(ty::TypeckTables::new(table_owner))); self } diff --git a/src/librustc_infer/infer/nll_relate/mod.rs b/src/librustc_infer/infer/nll_relate/mod.rs index 2350c28dfaa..cb1f1c08d88 100644 --- a/src/librustc_infer/infer/nll_relate/mod.rs +++ b/src/librustc_infer/infer/nll_relate/mod.rs @@ -161,7 +161,7 @@ where fn create_scope( &mut self, - value: &ty::Binder<impl TypeFoldable<'tcx>>, + value: ty::Binder<impl Relate<'tcx>>, universally_quantified: UniversallyQuantified, ) -> BoundRegionScope<'tcx> { let mut scope = BoundRegionScope::default(); @@ -369,7 +369,7 @@ where universe, }; - generalizer.relate(&value, &value) + generalizer.relate(value, value) } } @@ -495,8 +495,8 @@ where fn relate_with_variance<T: Relate<'tcx>>( &mut self, variance: ty::Variance, - a: &T, - b: &T, + a: T, + b: T, ) -> RelateResult<'tcx, T> { debug!("relate_with_variance(variance={:?}, a={:?}, b={:?})", variance, a, b); @@ -613,8 +613,8 @@ where fn binders<T>( &mut self, - a: &ty::Binder<T>, - b: &ty::Binder<T>, + a: ty::Binder<T>, + b: ty::Binder<T>, ) -> RelateResult<'tcx, ty::Binder<T>> where T: Relate<'tcx>, @@ -640,11 +640,10 @@ where debug!("binders({:?}: {:?}, ambient_variance={:?})", a, b, self.ambient_variance); - if !a.skip_binder().has_escaping_bound_vars() && !b.skip_binder().has_escaping_bound_vars() - { + if let (Some(a), Some(b)) = (a.no_bound_vars(), b.no_bound_vars()) { // Fast path for the common case. - self.relate(a.skip_binder(), b.skip_binder())?; - return Ok(a.clone()); + self.relate(a, b)?; + return Ok(ty::Binder::bind(a)); } if self.ambient_covariance() { @@ -839,8 +838,8 @@ where fn relate_with_variance<T: Relate<'tcx>>( &mut self, variance: ty::Variance, - a: &T, - b: &T, + a: T, + b: T, ) -> RelateResult<'tcx, T> { debug!( "TypeGeneralizer::relate_with_variance(variance={:?}, a={:?}, b={:?})", @@ -890,7 +889,7 @@ where match variables.probe(vid) { TypeVariableValue::Known { value: u } => { drop(variables); - self.relate(&u, &u) + self.relate(u, u) } TypeVariableValue::Unknown { universe: _universe } => { if self.ambient_variance == ty::Bivariant { @@ -984,7 +983,7 @@ where let variable_table = &mut inner.const_unification_table(); let var_value = variable_table.probe_value(vid); match var_value.val.known() { - Some(u) => self.relate(&u, &u), + Some(u) => self.relate(u, u), None => { let new_var_id = variable_table.new_key(ConstVarValue { origin: var_value.origin, @@ -1001,8 +1000,8 @@ where fn binders<T>( &mut self, - a: &ty::Binder<T>, - _: &ty::Binder<T>, + a: ty::Binder<T>, + _: ty::Binder<T>, ) -> RelateResult<'tcx, ty::Binder<T>> where T: Relate<'tcx>, diff --git a/src/librustc_infer/infer/sub.rs b/src/librustc_infer/infer/sub.rs index 90962d210b5..d190f7e4342 100644 --- a/src/librustc_infer/infer/sub.rs +++ b/src/librustc_infer/infer/sub.rs @@ -62,8 +62,8 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> { fn relate_with_variance<T: Relate<'tcx>>( &mut self, variance: ty::Variance, - a: &T, - b: &T, + a: T, + b: T, ) -> RelateResult<'tcx, T> { match variance { ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b), @@ -162,8 +162,8 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> { fn binders<T>( &mut self, - a: &ty::Binder<T>, - b: &ty::Binder<T>, + a: ty::Binder<T>, + b: ty::Binder<T>, ) -> RelateResult<'tcx, ty::Binder<T>> where T: Relate<'tcx>, diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs index d861b444c88..e35dbbc0c2f 100644 --- a/src/librustc_interface/tests.rs +++ b/src/librustc_interface/tests.rs @@ -500,7 +500,6 @@ fn test_debugging_options_tracking_hash() { untracked!(print_link_args, true); untracked!(print_llvm_passes, true); untracked!(print_mono_items, Some(String::from("abc"))); - untracked!(print_region_graph, true); untracked!(print_type_sizes, true); untracked!(query_dep_graph, true); untracked!(query_stats, true); diff --git a/src/librustc_lexer/src/cursor.rs b/src/librustc_lexer/src/cursor.rs index ed0911379c4..c0045d3f79b 100644 --- a/src/librustc_lexer/src/cursor.rs +++ b/src/librustc_lexer/src/cursor.rs @@ -23,8 +23,8 @@ impl<'a> Cursor<'a> { } } - /// For debug assertions only - /// Returns the last eaten symbol (or '\0' in release builds). + /// Returns the last eaten symbol (or `'\0'` in release builds). + /// (For debug assertions only.) pub(crate) fn prev(&self) -> char { #[cfg(debug_assertions)] { diff --git a/src/librustc_lexer/src/lib.rs b/src/librustc_lexer/src/lib.rs index 77b3d26463d..2f4b1bbd3ba 100644 --- a/src/librustc_lexer/src/lib.rs +++ b/src/librustc_lexer/src/lib.rs @@ -51,8 +51,9 @@ pub enum TokenKind { // Multi-char tokens: /// "// comment" LineComment, - /// "/* block comment */" - /// Block comments can be recursive, so the sequence like "/* /* */" + /// `/* block comment */` + /// + /// Block comments can be recursive, so the sequence like `/* /* */` /// will not be considered terminated and will result in a parsing error. BlockComment { terminated: bool }, /// Any whitespace characters sequence. diff --git a/src/librustc_lint/array_into_iter.rs b/src/librustc_lint/array_into_iter.rs index 82ac60be17c..31faad3368f 100644 --- a/src/librustc_lint/array_into_iter.rs +++ b/src/librustc_lint/array_into_iter.rs @@ -21,8 +21,8 @@ declare_lint_pass!( ArrayIntoIter => [ARRAY_INTO_ITER] ); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIntoIter { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'tcx>) { +impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { // We only care about method call expressions. if let hir::ExprKind::MethodCall(call, span, args, _) = &expr.kind { if call.ident.name != sym::into_iter { diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 36d2954ac6e..75e8d1cebdb 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -104,7 +104,7 @@ declare_lint! { declare_lint_pass!(BoxPointers => [BOX_POINTERS]); impl BoxPointers { - fn check_heap_type(&self, cx: &LateContext<'_, '_>, span: Span, ty: Ty<'_>) { + fn check_heap_type(&self, cx: &LateContext<'_>, span: Span, ty: Ty<'_>) { for leaf in ty.walk() { if let GenericArgKind::Type(leaf_ty) = leaf.unpack() { if leaf_ty.is_box() { @@ -117,8 +117,8 @@ impl BoxPointers { } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoxPointers { - fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for BoxPointers { + fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { match it.kind { hir::ItemKind::Fn(..) | hir::ItemKind::TyAlias(..) @@ -143,7 +143,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoxPointers { } } - fn check_expr(&mut self, cx: &LateContext<'_, '_>, e: &hir::Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'_>, e: &hir::Expr<'_>) { let ty = cx.tables().node_type(e.hir_id); self.check_heap_type(cx, e.span, ty); } @@ -157,15 +157,15 @@ declare_lint! { declare_lint_pass!(NonShorthandFieldPatterns => [NON_SHORTHAND_FIELD_PATTERNS]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonShorthandFieldPatterns { - fn check_pat(&mut self, cx: &LateContext<'_, '_>, pat: &hir::Pat<'_>) { +impl<'tcx> LateLintPass<'tcx> for NonShorthandFieldPatterns { + fn check_pat(&mut self, cx: &LateContext<'_>, pat: &hir::Pat<'_>) { if let PatKind::Struct(ref qpath, field_pats, _) = pat.kind { let variant = cx .tables() .pat_ty(pat) .ty_adt_def() .expect("struct pattern type is not an ADT") - .variant_of_res(cx.tables().qpath_res(qpath, pat.hir_id)); + .variant_of_res(cx.qpath_res(qpath, pat.hir_id)); for fieldpat in field_pats { if fieldpat.is_shorthand { continue; @@ -348,7 +348,7 @@ impl MissingDoc { fn check_missing_docs_attrs( &self, - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, id: Option<hir::HirId>, attrs: &[ast::Attribute], sp: Span, @@ -388,8 +388,8 @@ impl MissingDoc { } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { - fn enter_lint_attrs(&mut self, _: &LateContext<'_, '_>, attrs: &[ast::Attribute]) { +impl<'tcx> LateLintPass<'tcx> for MissingDoc { + fn enter_lint_attrs(&mut self, _: &LateContext<'_>, attrs: &[ast::Attribute]) { let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| { attr.check_name(sym::doc) @@ -401,11 +401,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { self.doc_hidden_stack.push(doc_hidden); } - fn exit_lint_attrs(&mut self, _: &LateContext<'_, '_>, _attrs: &[ast::Attribute]) { + fn exit_lint_attrs(&mut self, _: &LateContext<'_>, _attrs: &[ast::Attribute]) { self.doc_hidden_stack.pop().expect("empty doc_hidden_stack"); } - fn check_crate(&mut self, cx: &LateContext<'_, '_>, krate: &hir::Crate<'_>) { + fn check_crate(&mut self, cx: &LateContext<'_>, krate: &hir::Crate<'_>) { self.check_missing_docs_attrs(cx, None, &krate.item.attrs, krate.item.span, "the", "crate"); for macro_def in krate.exported_macros { @@ -420,7 +420,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { } } - fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item<'_>) { + fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { match it.kind { hir::ItemKind::Trait(.., trait_item_refs) => { // Issue #11592: traits are always considered exported, even when private. @@ -467,7 +467,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { self.check_missing_docs_attrs(cx, Some(it.hir_id), &it.attrs, it.span, article, desc); } - fn check_trait_item(&mut self, cx: &LateContext<'_, '_>, trait_item: &hir::TraitItem<'_>) { + fn check_trait_item(&mut self, cx: &LateContext<'_>, trait_item: &hir::TraitItem<'_>) { if self.private_traits.contains(&trait_item.hir_id) { return; } @@ -485,7 +485,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { ); } - fn check_impl_item(&mut self, cx: &LateContext<'_, '_>, impl_item: &hir::ImplItem<'_>) { + fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) { // If the method is an impl for a trait, don't doc. if method_context(cx, impl_item.hir_id) == MethodLateContext::TraitImpl { return; @@ -503,7 +503,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { ); } - fn check_struct_field(&mut self, cx: &LateContext<'_, '_>, sf: &hir::StructField<'_>) { + fn check_struct_field(&mut self, cx: &LateContext<'_>, sf: &hir::StructField<'_>) { if !sf.is_positional() { self.check_missing_docs_attrs( cx, @@ -516,7 +516,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { } } - fn check_variant(&mut self, cx: &LateContext<'_, '_>, v: &hir::Variant<'_>) { + fn check_variant(&mut self, cx: &LateContext<'_>, v: &hir::Variant<'_>) { self.check_missing_docs_attrs(cx, Some(v.id), &v.attrs, v.span, "a", "variant"); } } @@ -529,8 +529,8 @@ declare_lint! { declare_lint_pass!(MissingCopyImplementations => [MISSING_COPY_IMPLEMENTATIONS]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingCopyImplementations { - fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { + fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { if !cx.access_levels.is_reachable(item.hir_id) { return; } @@ -590,8 +590,8 @@ pub struct MissingDebugImplementations { impl_lint_pass!(MissingDebugImplementations => [MISSING_DEBUG_IMPLEMENTATIONS]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDebugImplementations { - fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations { + fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { if !cx.access_levels.is_reachable(item.hir_id) { return; } @@ -813,8 +813,8 @@ declare_lint! { declare_lint_pass!(InvalidNoMangleItems => [NO_MANGLE_CONST_ITEMS, NO_MANGLE_GENERIC_ITEMS]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems { - fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems { + fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { match it.kind { hir::ItemKind::Fn(.., ref generics, _) => { if let Some(no_mangle_attr) = attr::find_by_name(&it.attrs, sym::no_mangle) { @@ -883,8 +883,8 @@ declare_lint! { declare_lint_pass!(MutableTransmutes => [MUTABLE_TRANSMUTES]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes { - fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for MutableTransmutes { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) { use rustc_target::spec::abi::Abi::RustIntrinsic; if let Some((&ty::Ref(_, _, from_mt), &ty::Ref(_, _, to_mt))) = get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (&ty1.kind, &ty2.kind)) @@ -896,12 +896,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes { } } - fn get_transmute_from_to<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, + fn get_transmute_from_to<'tcx>( + cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, ) -> Option<(Ty<'tcx>, Ty<'tcx>)> { let def = if let hir::ExprKind::Path(ref qpath) = expr.kind { - cx.tables().qpath_res(qpath, expr.hir_id) + cx.qpath_res(qpath, expr.hir_id) } else { return None; }; @@ -911,13 +911,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes { } let sig = cx.tables().node_type(expr.hir_id).fn_sig(cx.tcx); let from = sig.inputs().skip_binder()[0]; - let to = *sig.output().skip_binder(); + let to = sig.output().skip_binder(); return Some((from, to)); } None } - fn def_id_is_transmute(cx: &LateContext<'_, '_>, def_id: DefId) -> bool { + fn def_id_is_transmute(cx: &LateContext<'_>, def_id: DefId) -> bool { cx.tcx.fn_sig(def_id).abi() == RustIntrinsic && cx.tcx.item_name(def_id) == sym::transmute } @@ -935,8 +935,8 @@ declare_lint_pass!( UnstableFeatures => [UNSTABLE_FEATURES] ); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnstableFeatures { - fn check_attribute(&mut self, ctx: &LateContext<'_, '_>, attr: &ast::Attribute) { +impl<'tcx> LateLintPass<'tcx> for UnstableFeatures { + fn check_attribute(&mut self, ctx: &LateContext<'_>, attr: &ast::Attribute) { if attr.check_name(sym::feature) { if let Some(items) = attr.meta_item_list() { for item in items { @@ -963,7 +963,7 @@ declare_lint_pass!( impl UnreachablePub { fn perform_lint( &self, - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, what: &str, id: hir::HirId, vis: &hir::Visibility<'_>, @@ -1003,16 +1003,12 @@ impl UnreachablePub { } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnreachablePub { - fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for UnreachablePub { + fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { self.perform_lint(cx, "item", item.hir_id, &item.vis, item.span, true); } - fn check_foreign_item( - &mut self, - cx: &LateContext<'_, '_>, - foreign_item: &hir::ForeignItem<'tcx>, - ) { + fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'tcx>) { self.perform_lint( cx, "item", @@ -1023,11 +1019,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnreachablePub { ); } - fn check_struct_field(&mut self, cx: &LateContext<'_, '_>, field: &hir::StructField<'_>) { + fn check_struct_field(&mut self, cx: &LateContext<'_>, field: &hir::StructField<'_>) { self.perform_lint(cx, "field", field.hir_id, &field.vis, field.span, false); } - fn check_impl_item(&mut self, cx: &LateContext<'_, '_>, impl_item: &hir::ImplItem<'_>) { + fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) { self.perform_lint(cx, "item", impl_item.hir_id, &impl_item.vis, impl_item.span, false); } } @@ -1096,8 +1092,8 @@ impl TypeAliasBounds { } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeAliasBounds { - fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds { + fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { let (ty, type_alias_generics) = match item.kind { hir::ItemKind::TyAlias(ref ty, ref generics) => (&*ty, generics), _ => return, @@ -1170,15 +1166,15 @@ declare_lint_pass!( UnusedBrokenConst => [] ); -fn check_const(cx: &LateContext<'_, '_>, body_id: hir::BodyId) { +fn check_const(cx: &LateContext<'_>, body_id: hir::BodyId) { let def_id = cx.tcx.hir().body_owner_def_id(body_id).to_def_id(); // trigger the query once for all constants since that will already report the errors // FIXME: Use ensure here let _ = cx.tcx.const_eval_poly(def_id); } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedBrokenConst { - fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for UnusedBrokenConst { + fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { match it.kind { hir::ItemKind::Const(_, body_id) => { check_const(cx, body_id); @@ -1203,8 +1199,8 @@ declare_lint_pass!( TrivialConstraints => [TRIVIAL_BOUNDS] ); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TrivialConstraints { - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item<'tcx>) { +impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::PredicateKind::*; @@ -1372,8 +1368,8 @@ impl UnnameableTestItems { } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnameableTestItems { - fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for UnnameableTestItems { + fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { if self.items_nameable { if let hir::ItemKind::Mod(..) = it.kind { } else { @@ -1390,7 +1386,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnameableTestItems { } } - fn check_item_post(&mut self, _cx: &LateContext<'_, '_>, it: &hir::Item<'_>) { + fn check_item_post(&mut self, _cx: &LateContext<'_>, it: &hir::Item<'_>) { if !self.items_nameable && self.boundary == Some(it.hir_id) { self.items_nameable = true; } @@ -1639,8 +1635,8 @@ impl ExplicitOutlivesRequirements { } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExplicitOutlivesRequirements { - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { use rustc_middle::middle::resolve_lifetime::Region; let infer_static = cx.tcx.features().infer_static_outlives_requirements; @@ -1850,8 +1846,8 @@ declare_lint! { declare_lint_pass!(InvalidValue => [INVALID_VALUE]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &hir::Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for InvalidValue { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) { #[derive(Debug, Copy, Clone, PartialEq)] enum InitKind { Zeroed, @@ -1880,7 +1876,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { } /// Determine if this expression is a "dangerous initialization". - fn is_dangerous_init(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>) -> Option<InitKind> { + fn is_dangerous_init(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<InitKind> { // `transmute` is inside an anonymous module (the `extern` block?); // `Invalid` represents the empty string and matches that. // FIXME(#66075): use diagnostic items. Somehow, that does not seem to work @@ -1891,7 +1887,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { if let hir::ExprKind::Call(ref path_expr, ref args) = expr.kind { // Find calls to `mem::{uninitialized,zeroed}` methods. if let hir::ExprKind::Path(ref qpath) = path_expr.kind { - let def_id = cx.tables().qpath_res(qpath, path_expr.hir_id).opt_def_id()?; + let def_id = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()?; if cx.tcx.is_diagnostic_item(sym::mem_zeroed, def_id) { return Some(InitKind::Zeroed); @@ -1911,8 +1907,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { // See if the `self` parameter is one of the dangerous constructors. if let hir::ExprKind::Call(ref path_expr, _) = args[0].kind { if let hir::ExprKind::Path(ref qpath) = path_expr.kind { - let def_id = - cx.tables().qpath_res(qpath, path_expr.hir_id).opt_def_id()?; + let def_id = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()?; if cx.tcx.is_diagnostic_item(sym::maybe_uninit_zeroed, def_id) { return Some(InitKind::Zeroed); @@ -2135,11 +2130,7 @@ impl ClashingExternDeclarations { /// Checks whether two types are structurally the same enough that the declarations shouldn't /// clash. We need this so we don't emit a lint when two modules both declare an extern struct, /// with the same members (as the declarations shouldn't clash). - fn structurally_same_type<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - a: Ty<'tcx>, - b: Ty<'tcx>, - ) -> bool { + fn structurally_same_type<'tcx>(cx: &LateContext<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> bool { let tcx = cx.tcx; if a == b || rustc_middle::ty::TyS::same_type(a, b) { // All nominally-same types are structurally same, too. @@ -2213,8 +2204,8 @@ impl ClashingExternDeclarations { impl_lint_pass!(ClashingExternDeclarations => [CLASHING_EXTERN_DECLARATIONS]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ClashingExternDeclarations { - fn check_foreign_item(&mut self, cx: &LateContext<'a, 'tcx>, this_fi: &hir::ForeignItem<'_>) { +impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations { + fn check_foreign_item(&mut self, cx: &LateContext<'tcx>, this_fi: &hir::ForeignItem<'_>) { trace!("ClashingExternDeclarations: check_foreign_item: {:?}", this_fi); if let ForeignItemKind::Fn(..) = this_fi.kind { let tcx = *&cx.tcx; diff --git a/src/librustc_lint/context.rs b/src/librustc_lint/context.rs index 0b4ae131af0..edbeea6db41 100644 --- a/src/librustc_lint/context.rs +++ b/src/librustc_lint/context.rs @@ -24,6 +24,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync; use rustc_errors::{struct_span_err, Applicability}; 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::lint::LintDiagnosticBuilder; @@ -420,27 +421,24 @@ impl LintStore { } /// Context for lint checking after type checking. -pub struct LateContext<'a, 'tcx> { +pub struct LateContext<'tcx> { /// Type context we're checking in. pub tcx: TyCtxt<'tcx>, /// Current body, or `None` if outside a body. pub enclosing_body: Option<hir::BodyId>, - /// Type-checking side-tables for the current body. Access using the - /// `tables` method, which handles querying the tables on demand. + /// Type-checking side-tables for the current body. Access using the `tables` + /// and `maybe_tables` methods, which handle querying the tables on demand. // FIXME(eddyb) move all the code accessing internal fields like this, // to this module, to avoid exposing it to lint logic. pub(super) cached_typeck_tables: Cell<Option<&'tcx ty::TypeckTables<'tcx>>>, - // HACK(eddyb) replace this with having `Option` around `&TypeckTables`. - pub(super) empty_typeck_tables: &'a ty::TypeckTables<'tcx>, - /// Parameter environment for the item we are in. pub param_env: ty::ParamEnv<'tcx>, /// Items accessible from the crate being checked. - pub access_levels: &'a AccessLevels, + pub access_levels: &'tcx AccessLevels, /// The store of registered lints and the lint levels. pub lint_store: &'tcx LintStore, @@ -626,7 +624,7 @@ impl<'a> EarlyContext<'a> { } } -impl LintContext for LateContext<'_, '_> { +impl LintContext for LateContext<'_> { type PassObject = LateLintPassObject; /// Gets the overall compiler `Session` object. @@ -675,20 +673,37 @@ impl LintContext for EarlyContext<'_> { } } -impl<'a, 'tcx> LateContext<'a, 'tcx> { +impl<'tcx> LateContext<'tcx> { /// Gets the type-checking side-tables for the current body, - /// or empty `TypeckTables` if outside a body. - // FIXME(eddyb) return `Option<&'tcx ty::TypeckTables<'tcx>>`, - // where `None` indicates we're outside a body. - pub fn tables(&self) -> &'a ty::TypeckTables<'tcx> { - if let Some(body) = self.enclosing_body { - self.cached_typeck_tables.get().unwrap_or_else(|| { + /// or `None` if outside a body. + pub fn maybe_typeck_tables(&self) -> Option<&'tcx ty::TypeckTables<'tcx>> { + self.cached_typeck_tables.get().or_else(|| { + self.enclosing_body.map(|body| { let tables = self.tcx.body_tables(body); self.cached_typeck_tables.set(Some(tables)); tables }) - } else { - self.empty_typeck_tables + }) + } + + /// Gets the type-checking side-tables for the current body. + /// As this will ICE if called outside bodies, only call when working with + /// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies). + #[track_caller] + pub fn tables(&self) -> &'tcx ty::TypeckTables<'tcx> { + self.maybe_typeck_tables().expect("`LateContext::tables` called outside of body") + } + + /// Returns the final resolution of a `QPath`, or `Res::Err` if unavailable. + /// Unlike `.tables().qpath_res(qpath, id)`, this can be used even outside + /// bodies (e.g. for paths in `hir::Ty`), without any risk of ICE-ing. + pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res { + match *qpath { + hir::QPath::Resolved(_, ref path) => path.res, + hir::QPath::TypeRelative(..) => self + .maybe_typeck_tables() + .and_then(|tables| tables.type_dependent_def(id)) + .map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), } } @@ -834,7 +849,7 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> { } } -impl<'a, 'tcx> LayoutOf for LateContext<'a, 'tcx> { +impl<'tcx> LayoutOf for LateContext<'tcx> { type Ty = Ty<'tcx>; type TyAndLayout = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>; diff --git a/src/librustc_lint/internal.rs b/src/librustc_lint/internal.rs index 12b7459e88d..30fae324392 100644 --- a/src/librustc_lint/internal.rs +++ b/src/librustc_lint/internal.rs @@ -84,8 +84,8 @@ declare_lint_pass!(TyTyKind => [ USAGE_OF_QUALIFIED_TY, ]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind { - fn check_path(&mut self, cx: &LateContext<'_, '_>, path: &'tcx Path<'tcx>, _: HirId) { +impl<'tcx> LateLintPass<'tcx> for TyTyKind { + fn check_path(&mut self, cx: &LateContext<'_>, path: &'tcx Path<'tcx>, _: HirId) { let segments = path.segments.iter().rev().skip(1).rev(); if let Some(last) = segments.last() { @@ -105,7 +105,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind { } } - fn check_ty(&mut self, cx: &LateContext<'_, '_>, ty: &'tcx Ty<'tcx>) { + fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx Ty<'tcx>) { match &ty.kind { TyKind::Path(qpath) => { if let QPath::Resolved(_, path) = qpath { @@ -164,7 +164,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind { } } -fn lint_ty_kind_usage(cx: &LateContext<'_, '_>, segment: &PathSegment<'_>) -> bool { +fn lint_ty_kind_usage(cx: &LateContext<'_>, segment: &PathSegment<'_>) -> bool { if let Some(res) = segment.res { if let Some(did) = res.opt_def_id() { return cx.tcx.is_diagnostic_item(sym::TyKind, did); @@ -174,7 +174,7 @@ fn lint_ty_kind_usage(cx: &LateContext<'_, '_>, segment: &PathSegment<'_>) -> bo false } -fn is_ty_or_ty_ctxt(cx: &LateContext<'_, '_>, ty: &Ty<'_>) -> Option<String> { +fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, ty: &Ty<'_>) -> Option<String> { if let TyKind::Path(qpath) = &ty.kind { if let QPath::Resolved(_, path) = qpath { let did = path.res.opt_def_id()?; diff --git a/src/librustc_lint/late.rs b/src/librustc_lint/late.rs index ef62d44c402..5feb17af24f 100644 --- a/src/librustc_lint/late.rs +++ b/src/librustc_lint/late.rs @@ -44,12 +44,12 @@ macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({ $cx.pass.$f(&$cx.context, $($args),*); }) } -struct LateContextAndPass<'a, 'tcx, T: LateLintPass<'a, 'tcx>> { - context: LateContext<'a, 'tcx>, +struct LateContextAndPass<'tcx, T: LateLintPass<'tcx>> { + context: LateContext<'tcx>, pass: T, } -impl<'a, 'tcx, T: LateLintPass<'a, 'tcx>> LateContextAndPass<'a, 'tcx, T> { +impl<'tcx, T: LateLintPass<'tcx>> LateContextAndPass<'tcx, T> { /// Merge the lints specified by any lint attributes into the /// current lint context, call the provided function, then reset the /// lints in effect to their previous state. @@ -93,9 +93,7 @@ impl<'a, 'tcx, T: LateLintPass<'a, 'tcx>> LateContextAndPass<'a, 'tcx, T> { } } -impl<'a, 'tcx, T: LateLintPass<'a, 'tcx>> hir_visit::Visitor<'tcx> - for LateContextAndPass<'a, 'tcx, T> -{ +impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPass<'tcx, T> { type Map = Map<'tcx>; /// Because lints are scoped lexically, we want to walk nested @@ -348,8 +346,8 @@ impl LintPass for LateLintPassObjects<'_> { } macro_rules! expand_late_lint_pass_impl_methods { - ([$a:tt, $hir:tt], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( - $(fn $name(&mut self, context: &LateContext<$a, $hir>, $($param: $arg),*) { + ([$hir:tt], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( + $(fn $name(&mut self, context: &LateContext<$hir>, $($param: $arg),*) { for obj in self.lints.iter_mut() { obj.$name(context, $($param),*); } @@ -358,16 +356,16 @@ macro_rules! expand_late_lint_pass_impl_methods { } macro_rules! late_lint_pass_impl { - ([], [$hir:tt], $methods:tt) => ( - impl<'a, $hir> LateLintPass<'a, $hir> for LateLintPassObjects<'_> { - expand_late_lint_pass_impl_methods!(['a, $hir], $methods); + ([], [$hir:tt], $methods:tt) => { + impl<$hir> LateLintPass<$hir> for LateLintPassObjects<'_> { + expand_late_lint_pass_impl_methods!([$hir], $methods); } - ) + }; } crate::late_lint_methods!(late_lint_pass_impl, [], ['tcx]); -fn late_lint_mod_pass<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( +fn late_lint_mod_pass<'tcx, T: LateLintPass<'tcx>>( tcx: TyCtxt<'tcx>, module_def_id: LocalDefId, pass: T, @@ -378,7 +376,6 @@ fn late_lint_mod_pass<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( tcx, enclosing_body: None, cached_typeck_tables: Cell::new(None), - empty_typeck_tables: &ty::TypeckTables::empty(None), param_env: ty::ParamEnv::empty(), access_levels, lint_store: unerased_lint_store(tcx), @@ -398,7 +395,7 @@ fn late_lint_mod_pass<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( } } -pub fn late_lint_mod<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( +pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx>>( tcx: TyCtxt<'tcx>, module_def_id: LocalDefId, builtin_lints: T, @@ -418,7 +415,7 @@ pub fn late_lint_mod<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( } } -fn late_lint_pass_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tcx>, pass: T) { +fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T) { let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE); let krate = tcx.hir().krate(); @@ -427,7 +424,6 @@ fn late_lint_pass_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tc tcx, enclosing_body: None, cached_typeck_tables: Cell::new(None), - empty_typeck_tables: &ty::TypeckTables::empty(None), param_env: ty::ParamEnv::empty(), access_levels, lint_store: unerased_lint_store(tcx), @@ -450,7 +446,7 @@ fn late_lint_pass_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tc }) } -fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tcx>, builtin_lints: T) { +fn late_lint_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, builtin_lints: T) { let mut passes = unerased_lint_store(tcx).late_passes.iter().map(|p| (p)()).collect::<Vec<_>>(); if !tcx.sess.opts.debugging_opts.no_interleave_lints { @@ -480,7 +476,7 @@ fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tcx>, b } /// Performs lint checking on a crate. -pub fn check_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( +pub fn check_crate<'tcx, T: LateLintPass<'tcx>>( tcx: TyCtxt<'tcx>, builtin_lints: impl FnOnce() -> T + Send, ) { diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 4da98d20159..45a86cf2cc6 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -34,6 +34,7 @@ #![feature(never_type)] #![feature(nll)] #![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(track_caller))] #![recursion_limit = "256"] #[macro_use] diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs index 052b461039b..dc6b8670498 100644 --- a/src/librustc_lint/nonstandard_style.rs +++ b/src/librustc_lint/nonstandard_style.rs @@ -18,7 +18,7 @@ pub enum MethodLateContext { PlainImpl, } -pub fn method_context(cx: &LateContext<'_, '_>, id: hir::HirId) -> MethodLateContext { +pub fn method_context(cx: &LateContext<'_>, id: hir::HirId) -> MethodLateContext { let def_id = cx.tcx.hir().local_def_id(id); let item = cx.tcx.associated_item(def_id); match item.container { @@ -200,7 +200,7 @@ impl NonSnakeCase { } /// Checks if a given identifier is snake case, and reports a diagnostic if not. - fn check_snake_case(&self, cx: &LateContext<'_, '_>, sort: &str, ident: &Ident) { + fn check_snake_case(&self, cx: &LateContext<'_>, sort: &str, ident: &Ident) { fn is_snake_case(ident: &str) -> bool { if ident.is_empty() { return true; @@ -248,10 +248,10 @@ impl NonSnakeCase { } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { +impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { fn check_mod( &mut self, - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, _: &'tcx hir::Mod<'tcx>, _: Span, id: hir::HirId, @@ -300,7 +300,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { } } - fn check_generic_param(&mut self, cx: &LateContext<'_, '_>, param: &hir::GenericParam<'_>) { + fn check_generic_param(&mut self, cx: &LateContext<'_>, param: &hir::GenericParam<'_>) { if let GenericParamKind::Lifetime { .. } = param.kind { self.check_snake_case(cx, "lifetime", ¶m.name.ident()); } @@ -308,7 +308,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { fn check_fn( &mut self, - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, fk: FnKind<'_>, _: &hir::FnDecl<'_>, _: &hir::Body<'_>, @@ -336,13 +336,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { } } - fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item<'_>) { + fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { if let hir::ItemKind::Mod(_) = it.kind { self.check_snake_case(cx, "module", &it.ident); } } - fn check_trait_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::TraitItem<'_>) { + fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &hir::TraitItem<'_>) { if let hir::TraitItemKind::Fn(_, hir::TraitFn::Required(pnames)) = item.kind { self.check_snake_case(cx, "trait method", &item.ident); for param_name in pnames { @@ -351,7 +351,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { } } - fn check_pat(&mut self, cx: &LateContext<'_, '_>, p: &hir::Pat<'_>) { + fn check_pat(&mut self, cx: &LateContext<'_>, p: &hir::Pat<'_>) { if let &PatKind::Binding(_, hid, ident, _) = &p.kind { if let hir::Node::Pat(parent_pat) = cx.tcx.hir().get(cx.tcx.hir().get_parent_node(hid)) { @@ -370,7 +370,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { } } - fn check_struct_def(&mut self, cx: &LateContext<'_, '_>, s: &hir::VariantData<'_>) { + fn check_struct_def(&mut self, cx: &LateContext<'_>, s: &hir::VariantData<'_>) { for sf in s.fields() { self.check_snake_case(cx, "structure field", &sf.ident); } @@ -386,7 +386,7 @@ declare_lint! { declare_lint_pass!(NonUpperCaseGlobals => [NON_UPPER_CASE_GLOBALS]); impl NonUpperCaseGlobals { - fn check_upper_case(cx: &LateContext<'_, '_>, sort: &str, ident: &Ident) { + fn check_upper_case(cx: &LateContext<'_>, sort: &str, ident: &Ident) { let name = &ident.name.as_str(); if name.chars().any(|c| c.is_lowercase()) { cx.struct_span_lint(NON_UPPER_CASE_GLOBALS, ident.span, |lint| { @@ -404,8 +404,8 @@ impl NonUpperCaseGlobals { } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonUpperCaseGlobals { - fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals { + fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { match it.kind { hir::ItemKind::Static(..) if !attr::contains_name(&it.attrs, sym::no_mangle) => { NonUpperCaseGlobals::check_upper_case(cx, "static variable", &it.ident); @@ -417,19 +417,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonUpperCaseGlobals { } } - fn check_trait_item(&mut self, cx: &LateContext<'_, '_>, ti: &hir::TraitItem<'_>) { + fn check_trait_item(&mut self, cx: &LateContext<'_>, ti: &hir::TraitItem<'_>) { if let hir::TraitItemKind::Const(..) = ti.kind { NonUpperCaseGlobals::check_upper_case(cx, "associated constant", &ti.ident); } } - fn check_impl_item(&mut self, cx: &LateContext<'_, '_>, ii: &hir::ImplItem<'_>) { + fn check_impl_item(&mut self, cx: &LateContext<'_>, ii: &hir::ImplItem<'_>) { if let hir::ImplItemKind::Const(..) = ii.kind { NonUpperCaseGlobals::check_upper_case(cx, "associated constant", &ii.ident); } } - fn check_pat(&mut self, cx: &LateContext<'_, '_>, p: &hir::Pat<'_>) { + fn check_pat(&mut self, cx: &LateContext<'_>, p: &hir::Pat<'_>) { // Lint for constants that look like binding identifiers (#7526) if let PatKind::Path(hir::QPath::Resolved(None, ref path)) = p.kind { if let Res::Def(DefKind::Const, _) = path.res { @@ -444,7 +444,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonUpperCaseGlobals { } } - fn check_generic_param(&mut self, cx: &LateContext<'_, '_>, param: &hir::GenericParam<'_>) { + fn check_generic_param(&mut self, cx: &LateContext<'_>, param: &hir::GenericParam<'_>) { if let GenericParamKind::Const { .. } = param.kind { NonUpperCaseGlobals::check_upper_case(cx, "const parameter", ¶m.name.ident()); } diff --git a/src/librustc_lint/passes.rs b/src/librustc_lint/passes.rs index 04a398a29ba..75e50f74a81 100644 --- a/src/librustc_lint/passes.rs +++ b/src/librustc_lint/passes.rs @@ -90,15 +90,15 @@ macro_rules! expand_lint_pass_methods { macro_rules! declare_late_lint_pass { ([], [$hir:tt], [$($methods:tt)*]) => ( - pub trait LateLintPass<'a, $hir>: LintPass { - expand_lint_pass_methods!(&LateContext<'a, $hir>, [$($methods)*]); + pub trait LateLintPass<$hir>: LintPass { + expand_lint_pass_methods!(&LateContext<$hir>, [$($methods)*]); } ) } late_lint_methods!(declare_late_lint_pass, [], ['tcx]); -impl LateLintPass<'_, '_> for HardwiredLints {} +impl LateLintPass<'_> for HardwiredLints {} #[macro_export] macro_rules! expand_combined_late_lint_pass_method { @@ -110,7 +110,7 @@ macro_rules! expand_combined_late_lint_pass_method { #[macro_export] macro_rules! expand_combined_late_lint_pass_methods { ($passes:tt, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( - $(fn $name(&mut self, context: &LateContext<'a, 'tcx>, $($param: $arg),*) { + $(fn $name(&mut self, context: &LateContext<'tcx>, $($param: $arg),*) { expand_combined_late_lint_pass_method!($passes, self, $name, (context, $($param),*)); })* ) @@ -138,7 +138,7 @@ macro_rules! declare_combined_late_lint_pass { } } - impl<'a, 'tcx> LateLintPass<'a, 'tcx> for $name { + impl<'tcx> LateLintPass<'tcx> for $name { expand_combined_late_lint_pass_methods!([$($passes),*], $methods); } @@ -282,4 +282,4 @@ macro_rules! declare_combined_early_lint_pass { /// A lint pass boxed up as a trait object. pub type EarlyLintPassObject = Box<dyn EarlyLintPass + sync::Send + sync::Sync + 'static>; pub type LateLintPassObject = - Box<dyn for<'a, 'tcx> LateLintPass<'a, 'tcx> + sync::Send + sync::Sync + 'static>; + Box<dyn for<'tcx> LateLintPass<'tcx> + sync::Send + sync::Sync + 'static>; diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index d0275a0dd0d..b3015dcc2ae 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -55,8 +55,8 @@ impl TypeLimits { /// Attempts to special-case the overflowing literal lint when it occurs as a range endpoint. /// Returns `true` iff the lint was overridden. -fn lint_overflowing_range_endpoint<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn lint_overflowing_range_endpoint<'tcx>( + cx: &LateContext<'tcx>, lit: &hir::Lit, lit_val: u128, max: u128, @@ -127,7 +127,7 @@ fn uint_ty_range(uint_ty: ast::UintTy) -> (u128, u128) { } } -fn get_bin_hex_repr(cx: &LateContext<'_, '_>, lit: &hir::Lit) -> Option<String> { +fn get_bin_hex_repr(cx: &LateContext<'_>, lit: &hir::Lit) -> Option<String> { let src = cx.sess().source_map().span_to_snippet(lit.span).ok()?; let firstch = src.chars().next()?; @@ -142,7 +142,7 @@ fn get_bin_hex_repr(cx: &LateContext<'_, '_>, lit: &hir::Lit) -> Option<String> } fn report_bin_hex_error( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, expr: &hir::Expr<'_>, ty: attr::IntType, repr_str: String, @@ -233,8 +233,8 @@ fn get_type_suggestion(t: Ty<'_>, val: u128, negative: bool) -> Option<&'static } } -fn lint_int_literal<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn lint_int_literal<'tcx>( + cx: &LateContext<'tcx>, type_limits: &TypeLimits, e: &'tcx hir::Expr<'tcx>, lit: &hir::Lit, @@ -283,8 +283,8 @@ fn lint_int_literal<'a, 'tcx>( } } -fn lint_uint_literal<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn lint_uint_literal<'tcx>( + cx: &LateContext<'tcx>, e: &'tcx hir::Expr<'tcx>, lit: &hir::Lit, t: ast::UintTy, @@ -347,8 +347,8 @@ fn lint_uint_literal<'a, 'tcx>( } } -fn lint_literal<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn lint_literal<'tcx>( + cx: &LateContext<'tcx>, type_limits: &TypeLimits, e: &'tcx hir::Expr<'tcx>, lit: &hir::Lit, @@ -391,8 +391,8 @@ fn lint_literal<'a, 'tcx>( } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx hir::Expr<'tcx>) { +impl<'tcx> LateLintPass<'tcx> for TypeLimits { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx hir::Expr<'tcx>) { match e.kind { hir::ExprKind::Unary(hir::UnOp::UnNeg, ref expr) => { // propagate negation, if the negation itself isn't negated @@ -436,7 +436,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { } fn check_limits( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, binop: hir::BinOp, l: &hir::Expr<'_>, r: &hir::Expr<'_>, @@ -515,7 +515,7 @@ enum ImproperCTypesMode { } struct ImproperCTypesVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, mode: ImproperCTypesMode, } @@ -939,7 +939,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool { struct ProhibitOpaqueTypes<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, ty: Option<Ty<'tcx>>, }; @@ -1050,8 +1050,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypesDeclarations { - fn check_foreign_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::ForeignItem<'_>) { +impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDeclarations { + fn check_foreign_item(&mut self, cx: &LateContext<'_>, it: &hir::ForeignItem<'_>) { let mut vis = ImproperCTypesVisitor { cx, mode: ImproperCTypesMode::Declarations }; let abi = cx.tcx.hir().get_foreign_abi(it.hir_id); @@ -1069,10 +1069,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypesDeclarations { } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypesDefinitions { +impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDefinitions { fn check_fn( &mut self, - cx: &LateContext<'a, 'tcx>, + cx: &LateContext<'tcx>, kind: hir::intravisit::FnKind<'tcx>, decl: &'tcx hir::FnDecl<'_>, _: &'tcx hir::Body<'_>, @@ -1096,8 +1096,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypesDefinitions { declare_lint_pass!(VariantSizeDifferences => [VARIANT_SIZE_DIFFERENCES]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences { - fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences { + fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { if let hir::ItemKind::Enum(ref enum_definition, _) = it.kind { let item_def_id = cx.tcx.hir().local_def_id(it.hir_id); let t = cx.tcx.type_of(item_def_id); diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 506ac77894a..c407f608a14 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -35,8 +35,8 @@ declare_lint! { declare_lint_pass!(UnusedResults => [UNUSED_MUST_USE, UNUSED_RESULTS]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { - fn check_stmt(&mut self, cx: &LateContext<'_, '_>, s: &hir::Stmt<'_>) { +impl<'tcx> LateLintPass<'tcx> for UnusedResults { + fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) { let expr = match s.kind { hir::StmtKind::Semi(ref expr) => &**expr, _ => return, @@ -55,7 +55,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { hir::ExprKind::Call(ref callee, _) => { match callee.kind { hir::ExprKind::Path(ref qpath) => { - match cx.tables().qpath_res(qpath, callee.hir_id) { + match cx.qpath_res(qpath, callee.hir_id) { Res::Def(DefKind::Fn | DefKind::AssocFn, def_id) => Some(def_id), // `Res::Local` if it was a closure, for which we // do not currently support must-use linting @@ -116,7 +116,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { // Returns whether an error has been emitted (and thus another does not need to be later). fn check_must_use_ty<'tcx>( - cx: &LateContext<'_, 'tcx>, + cx: &LateContext<'tcx>, ty: Ty<'tcx>, expr: &hir::Expr<'_>, span: Span, @@ -213,7 +213,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { // this would still require a copy into the format string, which would only be executed // when needed. fn check_must_use_def( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, def_id: DefId, span: Span, descr_pre_path: &str, @@ -251,8 +251,8 @@ declare_lint! { declare_lint_pass!(PathStatements => [PATH_STATEMENTS]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PathStatements { - fn check_stmt(&mut self, cx: &LateContext<'_, '_>, s: &hir::Stmt<'_>) { +impl<'tcx> LateLintPass<'tcx> for PathStatements { + fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) { if let hir::StmtKind::Semi(ref expr) = s.kind { if let hir::ExprKind::Path(_) = expr.kind { cx.struct_span_lint(PATH_STATEMENTS, s.span, |lint| { @@ -276,8 +276,8 @@ impl UnusedAttributes { impl_lint_pass!(UnusedAttributes => [UNUSED_ATTRIBUTES]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes { - fn check_attribute(&mut self, cx: &LateContext<'_, '_>, attr: &ast::Attribute) { +impl<'tcx> LateLintPass<'tcx> for UnusedAttributes { + fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) { debug!("checking attribute: {:?}", attr); if attr.is_doc_comment() { @@ -943,8 +943,8 @@ declare_lint! { declare_lint_pass!(UnusedAllocation => [UNUSED_ALLOCATION]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAllocation { - fn check_expr(&mut self, cx: &LateContext<'_, '_>, e: &hir::Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for UnusedAllocation { + fn check_expr(&mut self, cx: &LateContext<'_>, e: &hir::Expr<'_>) { match e.kind { hir::ExprKind::Box(_) => {} _ => return, diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index 2254d553337..1ac16e0d311 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -450,19 +450,17 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> { let imported_source_files = if tag == TAG_VALID_SPAN_LOCAL { self.cdata().imported_source_files(sess) } else { - // FIXME: We don't decode dependencies of proc-macros. - // Remove this once #69976 is merged + // When we encode a proc-macro crate, all `Span`s should be encoded + // with `TAG_VALID_SPAN_LOCAL` if self.cdata().root.is_proc_macro_crate() { - debug!( - "SpecializedDecoder<Span>::specialized_decode: skipping span for proc-macro crate {:?}", - self.cdata().cnum - ); // Decode `CrateNum` as u32 - using `CrateNum::decode` will ICE // since we don't have `cnum_map` populated. - // This advances the decoder position so that we can continue - // to read metadata. - let _ = u32::decode(self)?; - return Ok(DUMMY_SP); + let cnum = u32::decode(self)?; + panic!( + "Decoding of crate {:?} tried to access proc-macro dep {:?}", + self.cdata().root.name, + cnum + ); } // tag is TAG_VALID_SPAN_FOREIGN, checked by `debug_assert` above let cnum = CrateNum::decode(self)?; @@ -990,8 +988,13 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { DefKind::Macro(macro_kind(raw_macro)), self.local_def_id(def_index), ); - let ident = Ident::from_str(raw_macro.name()); - callback(Export { ident, res, vis: ty::Visibility::Public, span: DUMMY_SP }); + let ident = self.item_ident(def_index, sess); + callback(Export { + ident, + res, + vis: ty::Visibility::Public, + span: self.get_span(def_index, sess), + }); } } return; diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs index 1b168bf0117..abbe45fe02e 100644 --- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs +++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs @@ -239,6 +239,8 @@ provide! { <'tcx> tcx, def_id, other, cdata, syms } + + crate_extern_paths => { cdata.source().paths().cloned().collect() } } pub fn provide(providers: &mut Providers<'_>) { diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index d01c767e2bc..fb4fee402ab 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -16,6 +16,7 @@ use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::itemlikevisit::{ItemLikeVisitor, ParItemLikeVisitor}; use rustc_hir::lang_items; use rustc_hir::{AnonConst, GenericParamKind}; +use rustc_index::bit_set::GrowableBitSet; use rustc_index::vec::Idx; use rustc_middle::hir::map::Map; use rustc_middle::middle::cstore::{EncodedMetadata, ForeignModule, LinkagePreference, NativeLib}; @@ -51,7 +52,20 @@ struct EncodeContext<'tcx> { interpret_allocs_inverse: Vec<interpret::AllocId>, // This is used to speed up Span encoding. - source_file_cache: Lrc<SourceFile>, + // The `usize` is an index into the `MonotonicVec` + // that stores the `SourceFile` + source_file_cache: (Lrc<SourceFile>, usize), + // The indices (into the `SourceMap`'s `MonotonicVec`) + // of all of the `SourceFiles` that we need to serialize. + // When we serialize a `Span`, we insert the index of its + // `SourceFile` into the `GrowableBitSet`. + // + // This needs to be a `GrowableBitSet` and not a + // regular `BitSet` because we may actually import new `SourceFiles` + // during metadata encoding, due to executing a query + // with a result containing a foreign `Span`. + required_source_files: Option<GrowableBitSet<usize>>, + is_proc_macro: bool, } macro_rules! encoder_methods { @@ -154,18 +168,23 @@ impl<'tcx> SpecializedEncoder<Span> for EncodeContext<'tcx> { // The Span infrastructure should make sure that this invariant holds: debug_assert!(span.lo <= span.hi); - if !self.source_file_cache.contains(span.lo) { + if !self.source_file_cache.0.contains(span.lo) { let source_map = self.tcx.sess.source_map(); let source_file_index = source_map.lookup_source_file_idx(span.lo); - self.source_file_cache = source_map.files()[source_file_index].clone(); + self.source_file_cache = + (source_map.files()[source_file_index].clone(), source_file_index); } - if !self.source_file_cache.contains(span.hi) { + if !self.source_file_cache.0.contains(span.hi) { // Unfortunately, macro expansion still sometimes generates Spans // that malformed in this way. return TAG_INVALID_SPAN.encode(self); } + let source_files = self.required_source_files.as_mut().expect("Already encoded SourceMap!"); + // Record the fact that we need to encode the data for this `SourceFile` + source_files.insert(self.source_file_cache.1); + // There are two possible cases here: // 1. This span comes from a 'foreign' crate - e.g. some crate upstream of the // crate we are writing metadata for. When the metadata for *this* crate gets @@ -176,7 +195,13 @@ impl<'tcx> SpecializedEncoder<Span> for EncodeContext<'tcx> { // 2. This span comes from our own crate. No special hamdling is needed - we just // write `TAG_VALID_SPAN_LOCAL` to let the deserializer know that it should use // our own source map information. - let (tag, lo, hi) = if self.source_file_cache.is_imported() { + // + // If we're a proc-macro crate, we always treat this as a local `Span`. + // In `encode_source_map`, we serialize foreign `SourceFile`s into our metadata + // if we're a proc-macro crate. + // This allows us to avoid loading the dependencies of proc-macro crates: all of + // the information we need to decode `Span`s is stored in the proc-macro crate. + let (tag, lo, hi) = if self.source_file_cache.0.is_imported() && !self.is_proc_macro { // To simplify deserialization, we 'rebase' this span onto the crate it originally came from // (the crate that 'owns' the file it references. These rebased 'lo' and 'hi' values // are relative to the source map information for the 'foreign' crate whose CrateNum @@ -188,13 +213,13 @@ impl<'tcx> SpecializedEncoder<Span> for EncodeContext<'tcx> { // Span that can be used without any additional trouble. let external_start_pos = { // Introduce a new scope so that we drop the 'lock()' temporary - match &*self.source_file_cache.external_src.lock() { + match &*self.source_file_cache.0.external_src.lock() { ExternalSource::Foreign { original_start_pos, .. } => *original_start_pos, src => panic!("Unexpected external source {:?}", src), } }; - let lo = (span.lo - self.source_file_cache.start_pos) + external_start_pos; - let hi = (span.hi - self.source_file_cache.start_pos) + external_start_pos; + let lo = (span.lo - self.source_file_cache.0.start_pos) + external_start_pos; + let hi = (span.hi - self.source_file_cache.0.start_pos) + external_start_pos; (TAG_VALID_SPAN_FOREIGN, lo, hi) } else { @@ -212,7 +237,7 @@ impl<'tcx> SpecializedEncoder<Span> for EncodeContext<'tcx> { if tag == TAG_VALID_SPAN_FOREIGN { // This needs to be two lines to avoid holding the `self.source_file_cache` // while calling `cnum.encode(self)` - let cnum = self.source_file_cache.cnum; + let cnum = self.source_file_cache.0.cnum; cnum.encode(self)?; } Ok(()) @@ -386,17 +411,24 @@ impl<'tcx> EncodeContext<'tcx> { let all_source_files = source_map.files(); let (working_dir, _cwd_remapped) = self.tcx.sess.working_dir.clone(); + // By replacing the `Option` with `None`, we ensure that we can't + // accidentally serialize any more `Span`s after the source map encoding + // is done. + let required_source_files = self.required_source_files.take().unwrap(); let adapted = all_source_files .iter() - .filter(|source_file| { - // No need to re-export imported source_files, as any downstream - // crate will import them from their original source. - // FIXME(eddyb) the `Span` encoding should take that into account. - !source_file.is_imported() + .enumerate() + .filter(|(idx, source_file)| { + // Only serialize `SourceFile`s that were used + // during the encoding of a `Span` + required_source_files.contains(*idx) && + // Don't serialize imported `SourceFile`s, unless + // we're in a proc-macro crate. + (!source_file.is_imported() || self.is_proc_macro) }) - .map(|source_file| { - match source_file.name { + .map(|(_, source_file)| { + let mut adapted = match source_file.name { // This path of this SourceFile has been modified by // path-remapping, so we use it verbatim (and avoid // cloning the whole map in the process). @@ -419,15 +451,30 @@ impl<'tcx> EncodeContext<'tcx> { // expanded code, not from a file _ => source_file.clone(), + }; + + // We're serializing this `SourceFile` into our crate metadata, + // so mark it as coming from this crate. + // This also ensures that we don't try to deserialize the + // `CrateNum` for a proc-macro dependency - since proc macro + // dependencies aren't loaded when we deserialize a proc-macro, + // trying to remap the `CrateNum` would fail. + if self.is_proc_macro { + Lrc::make_mut(&mut adapted).cnum = LOCAL_CRATE; } + adapted }) .collect::<Vec<_>>(); self.lazy(adapted.iter().map(|rc| &**rc)) } + fn is_proc_macro(&self) -> bool { + self.tcx.sess.crate_types().contains(&CrateType::ProcMacro) + } + fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> { - let is_proc_macro = self.tcx.sess.crate_types().contains(&CrateType::ProcMacro); + let is_proc_macro = self.is_proc_macro(); let mut i = self.position(); @@ -458,11 +505,6 @@ impl<'tcx> EncodeContext<'tcx> { let foreign_modules = self.encode_foreign_modules(); - // Encode source_map - i = self.position(); - let source_map = self.encode_source_map(); - let source_map_bytes = self.position() - i; - // Encode DefPathTable i = self.position(); let def_path_table = self.encode_def_path_table(); @@ -514,12 +556,19 @@ impl<'tcx> EncodeContext<'tcx> { let proc_macro_data_bytes = self.position() - i; // Encode exported symbols info. This is prefetched in `encode_metadata` so we encode - // this last to give the prefetching as much time as possible to complete. + // this late to give the prefetching as much time as possible to complete. i = self.position(); let exported_symbols = self.tcx.exported_symbols(LOCAL_CRATE); let exported_symbols = self.encode_exported_symbols(&exported_symbols); let exported_symbols_bytes = self.position() - i; + // Encode source_map. This needs to be done last, + // since encoding `Span`s tells us which `SourceFiles` we actually + // need to encode. + i = self.position(); + let source_map = self.encode_source_map(); + let source_map_bytes = self.position() - i; + let attrs = tcx.hir().krate_attrs(); let has_default_lib_allocator = attr::contains_name(&attrs, sym::default_lib_allocator); @@ -1854,6 +1903,8 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata { // Will be filled with the root position after encoding everything. encoder.emit_raw_bytes(&[0, 0, 0, 0]); + let source_map_files = tcx.sess.source_map().files(); + let mut ecx = EncodeContext { opaque: encoder, tcx, @@ -1861,10 +1912,13 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata { lazy_state: LazyState::NoNode, type_shorthands: Default::default(), predicate_shorthands: Default::default(), - source_file_cache: tcx.sess.source_map().files()[0].clone(), + source_file_cache: (source_map_files[0].clone(), 0), interpret_allocs: Default::default(), interpret_allocs_inverse: Default::default(), + required_source_files: Some(GrowableBitSet::with_capacity(source_map_files.len())), + is_proc_macro: tcx.sess.crate_types().contains(&CrateType::ProcMacro), }; + drop(source_map_files); // Encode the rustc version string in a predictable location. rustc_version().encode(&mut ecx).unwrap(); diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs index 381e7ee115e..8abc3784d6d 100644 --- a/src/librustc_metadata/rmeta/mod.rs +++ b/src/librustc_metadata/rmeta/mod.rs @@ -192,7 +192,6 @@ crate struct CrateRoot<'tcx> { diagnostic_items: Lazy<[(Symbol, DefIndex)]>, native_libraries: Lazy<[NativeLib]>, foreign_modules: Lazy<[ForeignModule]>, - source_map: Lazy<[rustc_span::SourceFile]>, def_path_table: Lazy<rustc_hir::definitions::DefPathTable>, impls: Lazy<[TraitImpls]>, interpret_alloc_index: Lazy<[u32]>, @@ -203,6 +202,7 @@ crate struct CrateRoot<'tcx> { proc_macro_data: Option<Lazy<[DefIndex]>>, exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]), + source_map: Lazy<[rustc_span::SourceFile]>, compiler_builtins: bool, needs_allocator: bool, diff --git a/src/librustc_middle/ich/impls_ty.rs b/src/librustc_middle/ich/impls_ty.rs index ef6247881c0..8f15c99f951 100644 --- a/src/librustc_middle/ich/impls_ty.rs +++ b/src/librustc_middle/ich/impls_ty.rs @@ -123,7 +123,7 @@ where T: HashStable<StableHashingContext<'a>>, { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - self.skip_binder().hash_stable(hcx, hasher); + self.as_ref().skip_binder().hash_stable(hcx, hasher); } } diff --git a/src/librustc_middle/lib.rs b/src/librustc_middle/lib.rs index 676346fbebd..96b8ca27183 100644 --- a/src/librustc_middle/lib.rs +++ b/src/librustc_middle/lib.rs @@ -42,7 +42,7 @@ #![feature(or_patterns)] #![feature(range_is_empty)] #![feature(min_specialization)] -#![feature(track_caller)] +#![cfg_attr(bootstrap, feature(track_caller))] #![feature(trusted_len)] #![feature(stmt_expr_attributes)] #![feature(test)] diff --git a/src/librustc_middle/mir/coverage/mod.rs b/src/librustc_middle/mir/coverage/mod.rs new file mode 100644 index 00000000000..327f321bd75 --- /dev/null +++ b/src/librustc_middle/mir/coverage/mod.rs @@ -0,0 +1,24 @@ +//! Metadata from source code coverage analysis and instrumentation. + +/// Positional arguments to `libcore::count_code_region()` +pub mod count_code_region_args { + pub const COUNTER_INDEX: usize = 0; + pub const START_BYTE_POS: usize = 1; + pub const END_BYTE_POS: usize = 2; +} + +/// Positional arguments to `libcore::coverage_counter_add()` and +/// `libcore::coverage_counter_subtract()` +pub mod coverage_counter_expression_args { + pub const COUNTER_EXPRESSION_INDEX: usize = 0; + pub const LEFT_INDEX: usize = 1; + pub const RIGHT_INDEX: usize = 2; + pub const START_BYTE_POS: usize = 3; + pub const END_BYTE_POS: usize = 4; +} + +/// Positional arguments to `libcore::coverage_unreachable()` +pub mod coverage_unreachable_args { + pub const START_BYTE_POS: usize = 0; + pub const END_BYTE_POS: usize = 1; +} diff --git a/src/librustc_middle/mir/mod.rs b/src/librustc_middle/mir/mod.rs index 0ed0d905007..ad4e8b55b75 100644 --- a/src/librustc_middle/mir/mod.rs +++ b/src/librustc_middle/mir/mod.rs @@ -19,7 +19,6 @@ use rustc_target::abi::VariantIdx; use polonius_engine::Atom; pub use rustc_ast::ast::Mutability; -use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::graph::dominators::{dominators, Dominators}; use rustc_data_structures::graph::{self, GraphSuccessors}; @@ -40,11 +39,14 @@ use std::{iter, mem, option}; use self::predecessors::{PredecessorCache, Predecessors}; pub use self::query::*; +pub mod coverage; pub mod interpret; pub mod mono; mod predecessors; mod query; pub mod tcx; +pub mod terminator; +pub use terminator::*; pub mod traversal; mod type_foldable; pub mod visit; @@ -1046,191 +1048,6 @@ pub struct BasicBlockData<'tcx> { pub is_cleanup: bool, } -#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] -pub struct Terminator<'tcx> { - pub source_info: SourceInfo, - pub kind: TerminatorKind<'tcx>, -} - -#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)] -pub enum TerminatorKind<'tcx> { - /// Block should have one successor in the graph; we jump there. - Goto { target: BasicBlock }, - - /// Operand evaluates to an integer; jump depending on its value - /// to one of the targets, and otherwise fallback to `otherwise`. - SwitchInt { - /// The discriminant value being tested. - discr: Operand<'tcx>, - - /// The type of value being tested. - /// This is always the same as the type of `discr`. - /// FIXME: remove this redundant information. Currently, it is relied on by pretty-printing. - switch_ty: Ty<'tcx>, - - /// Possible values. The locations to branch to in each case - /// are found in the corresponding indices from the `targets` vector. - values: Cow<'tcx, [u128]>, - - /// Possible branch sites. The last element of this vector is used - /// for the otherwise branch, so targets.len() == values.len() + 1 - /// should hold. - // - // This invariant is quite non-obvious and also could be improved. - // One way to make this invariant is to have something like this instead: - // - // branches: Vec<(ConstInt, BasicBlock)>, - // otherwise: Option<BasicBlock> // exhaustive if None - // - // However we’ve decided to keep this as-is until we figure a case - // where some other approach seems to be strictly better than other. - targets: Vec<BasicBlock>, - }, - - /// Indicates that the landing pad is finished and unwinding should - /// continue. Emitted by `build::scope::diverge_cleanup`. - Resume, - - /// Indicates that the landing pad is finished and that the process - /// should abort. Used to prevent unwinding for foreign items. - Abort, - - /// Indicates a normal return. The return place should have - /// been filled in before this executes. This can occur multiple times - /// in different basic blocks. - Return, - - /// Indicates a terminator that can never be reached. - Unreachable, - - /// Drop the `Place`. - Drop { place: Place<'tcx>, target: BasicBlock, unwind: Option<BasicBlock> }, - - /// Drop the `Place` and assign the new value over it. This ensures - /// that the assignment to `P` occurs *even if* the destructor for - /// place unwinds. Its semantics are best explained by the - /// elaboration: - /// - /// ``` - /// BB0 { - /// DropAndReplace(P <- V, goto BB1, unwind BB2) - /// } - /// ``` - /// - /// becomes - /// - /// ``` - /// BB0 { - /// Drop(P, goto BB1, unwind BB2) - /// } - /// BB1 { - /// // P is now uninitialized - /// P <- V - /// } - /// BB2 { - /// // P is now uninitialized -- its dtor panicked - /// P <- V - /// } - /// ``` - DropAndReplace { - place: Place<'tcx>, - value: Operand<'tcx>, - target: BasicBlock, - unwind: Option<BasicBlock>, - }, - - /// Block ends with a call of a converging function. - Call { - /// The function that’s being called. - func: Operand<'tcx>, - /// Arguments the function is called with. - /// These are owned by the callee, which is free to modify them. - /// This allows the memory occupied by "by-value" arguments to be - /// reused across function calls without duplicating the contents. - args: Vec<Operand<'tcx>>, - /// Destination for the return value. If some, the call is converging. - destination: Option<(Place<'tcx>, BasicBlock)>, - /// Cleanups to be done if the call unwinds. - cleanup: Option<BasicBlock>, - /// `true` if this is from a call in HIR rather than from an overloaded - /// operator. True for overloaded function call. - from_hir_call: bool, - /// This `Span` is the span of the function, without the dot and receiver - /// (e.g. `foo(a, b)` in `x.foo(a, b)` - fn_span: Span, - }, - - /// Jump to the target if the condition has the expected value, - /// otherwise panic with a message and a cleanup target. - Assert { - cond: Operand<'tcx>, - expected: bool, - msg: AssertMessage<'tcx>, - target: BasicBlock, - cleanup: Option<BasicBlock>, - }, - - /// A suspend point. - Yield { - /// The value to return. - value: Operand<'tcx>, - /// Where to resume to. - resume: BasicBlock, - /// The place to store the resume argument in. - resume_arg: Place<'tcx>, - /// Cleanup to be done if the generator is dropped at this suspend point. - drop: Option<BasicBlock>, - }, - - /// Indicates the end of the dropping of a generator. - GeneratorDrop, - - /// A block where control flow only ever takes one real path, but borrowck - /// needs to be more conservative. - FalseEdge { - /// The target normal control flow will take. - real_target: BasicBlock, - /// A block control flow could conceptually jump to, but won't in - /// practice. - imaginary_target: BasicBlock, - }, - /// A terminator for blocks that only take one path in reality, but where we - /// reserve the right to unwind in borrowck, even if it won't happen in practice. - /// This can arise in infinite loops with no function calls for example. - FalseUnwind { - /// The target normal control flow will take. - real_target: BasicBlock, - /// The imaginary cleanup block link. This particular path will never be taken - /// in practice, but in order to avoid fragility we want to always - /// consider it in borrowck. We don't want to accept programs which - /// pass borrowck only when `panic=abort` or some assertions are disabled - /// due to release vs. debug mode builds. This needs to be an `Option` because - /// of the `remove_noop_landing_pads` and `no_landing_pads` passes. - unwind: Option<BasicBlock>, - }, - - /// Block ends with an inline assembly block. This is a terminator since - /// inline assembly is allowed to diverge. - InlineAsm { - /// The template for the inline assembly, with placeholders. - template: &'tcx [InlineAsmTemplatePiece], - - /// The operands for the inline assembly, as `Operand`s or `Place`s. - operands: Vec<InlineAsmOperand<'tcx>>, - - /// Miscellaneous options for the inline assembly. - options: InlineAsmOptions, - - /// Source spans for each line of the inline assembly code. These are - /// used to map assembler errors back to the line in the source code. - line_spans: &'tcx [Span], - - /// Destination block after the inline assembly returns, unless it is - /// diverging (InlineAsmOptions::NORETURN). - destination: Option<BasicBlock>, - }, -} - /// Information about an assertion failure. #[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)] pub enum AssertKind<O> { @@ -1279,149 +1096,6 @@ pub type Successors<'a> = pub type SuccessorsMut<'a> = iter::Chain<option::IntoIter<&'a mut BasicBlock>, slice::IterMut<'a, BasicBlock>>; -impl<'tcx> Terminator<'tcx> { - pub fn successors(&self) -> Successors<'_> { - self.kind.successors() - } - - pub fn successors_mut(&mut self) -> SuccessorsMut<'_> { - self.kind.successors_mut() - } - - pub fn unwind(&self) -> Option<&Option<BasicBlock>> { - self.kind.unwind() - } - - pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> { - self.kind.unwind_mut() - } -} - -impl<'tcx> TerminatorKind<'tcx> { - pub fn if_( - tcx: TyCtxt<'tcx>, - cond: Operand<'tcx>, - t: BasicBlock, - f: BasicBlock, - ) -> TerminatorKind<'tcx> { - static BOOL_SWITCH_FALSE: &[u128] = &[0]; - TerminatorKind::SwitchInt { - discr: cond, - switch_ty: tcx.types.bool, - values: From::from(BOOL_SWITCH_FALSE), - targets: vec![f, t], - } - } - - pub fn successors(&self) -> Successors<'_> { - use self::TerminatorKind::*; - match *self { - Resume - | Abort - | GeneratorDrop - | Return - | Unreachable - | Call { destination: None, cleanup: None, .. } - | InlineAsm { destination: None, .. } => None.into_iter().chain(&[]), - Goto { target: ref t } - | Call { destination: None, cleanup: Some(ref t), .. } - | Call { destination: Some((_, ref t)), cleanup: None, .. } - | Yield { resume: ref t, drop: None, .. } - | DropAndReplace { target: ref t, unwind: None, .. } - | Drop { target: ref t, unwind: None, .. } - | Assert { target: ref t, cleanup: None, .. } - | FalseUnwind { real_target: ref t, unwind: None } - | InlineAsm { destination: Some(ref t), .. } => Some(t).into_iter().chain(&[]), - Call { destination: Some((_, ref t)), cleanup: Some(ref u), .. } - | Yield { resume: ref t, drop: Some(ref u), .. } - | DropAndReplace { target: ref t, unwind: Some(ref u), .. } - | Drop { target: ref t, unwind: Some(ref u), .. } - | Assert { target: ref t, cleanup: Some(ref u), .. } - | FalseUnwind { real_target: ref t, unwind: Some(ref u) } => { - Some(t).into_iter().chain(slice::from_ref(u)) - } - SwitchInt { ref targets, .. } => None.into_iter().chain(&targets[..]), - FalseEdge { ref real_target, ref imaginary_target } => { - Some(real_target).into_iter().chain(slice::from_ref(imaginary_target)) - } - } - } - - pub fn successors_mut(&mut self) -> SuccessorsMut<'_> { - use self::TerminatorKind::*; - match *self { - Resume - | Abort - | GeneratorDrop - | Return - | Unreachable - | Call { destination: None, cleanup: None, .. } - | InlineAsm { destination: None, .. } => None.into_iter().chain(&mut []), - Goto { target: ref mut t } - | Call { destination: None, cleanup: Some(ref mut t), .. } - | Call { destination: Some((_, ref mut t)), cleanup: None, .. } - | Yield { resume: ref mut t, drop: None, .. } - | DropAndReplace { target: ref mut t, unwind: None, .. } - | Drop { target: ref mut t, unwind: None, .. } - | Assert { target: ref mut t, cleanup: None, .. } - | FalseUnwind { real_target: ref mut t, unwind: None } - | InlineAsm { destination: Some(ref mut t), .. } => Some(t).into_iter().chain(&mut []), - Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut u), .. } - | Yield { resume: ref mut t, drop: Some(ref mut u), .. } - | DropAndReplace { target: ref mut t, unwind: Some(ref mut u), .. } - | Drop { target: ref mut t, unwind: Some(ref mut u), .. } - | Assert { target: ref mut t, cleanup: Some(ref mut u), .. } - | FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } => { - Some(t).into_iter().chain(slice::from_mut(u)) - } - SwitchInt { ref mut targets, .. } => None.into_iter().chain(&mut targets[..]), - FalseEdge { ref mut real_target, ref mut imaginary_target } => { - Some(real_target).into_iter().chain(slice::from_mut(imaginary_target)) - } - } - } - - pub fn unwind(&self) -> Option<&Option<BasicBlock>> { - match *self { - TerminatorKind::Goto { .. } - | TerminatorKind::Resume - | TerminatorKind::Abort - | TerminatorKind::Return - | TerminatorKind::Unreachable - | TerminatorKind::GeneratorDrop - | TerminatorKind::Yield { .. } - | TerminatorKind::SwitchInt { .. } - | TerminatorKind::FalseEdge { .. } - | TerminatorKind::InlineAsm { .. } => None, - TerminatorKind::Call { cleanup: ref unwind, .. } - | TerminatorKind::Assert { cleanup: ref unwind, .. } - | TerminatorKind::DropAndReplace { ref unwind, .. } - | TerminatorKind::Drop { ref unwind, .. } - | TerminatorKind::FalseUnwind { ref unwind, .. } => Some(unwind), - } - } - - pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> { - match *self { - TerminatorKind::Goto { .. } - | TerminatorKind::Resume - | TerminatorKind::Abort - | TerminatorKind::Return - | TerminatorKind::Unreachable - | TerminatorKind::GeneratorDrop - | TerminatorKind::Yield { .. } - | TerminatorKind::SwitchInt { .. } - | TerminatorKind::FalseEdge { .. } - | TerminatorKind::InlineAsm { .. } => None, - TerminatorKind::Call { cleanup: ref mut unwind, .. } - | TerminatorKind::Assert { cleanup: ref mut unwind, .. } - | TerminatorKind::DropAndReplace { ref mut unwind, .. } - | TerminatorKind::Drop { ref mut unwind, .. } - | TerminatorKind::FalseUnwind { ref mut unwind, .. } => Some(unwind), - } - } -} - impl<'tcx> BasicBlockData<'tcx> { pub fn new(terminator: Option<Terminator<'tcx>>) -> BasicBlockData<'tcx> { BasicBlockData { statements: vec![], terminator, is_cleanup: false } @@ -1628,169 +1302,6 @@ impl<O: fmt::Debug> fmt::Debug for AssertKind<O> { } } -impl<'tcx> Debug for TerminatorKind<'tcx> { - fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { - self.fmt_head(fmt)?; - let successor_count = self.successors().count(); - let labels = self.fmt_successor_labels(); - assert_eq!(successor_count, labels.len()); - - match successor_count { - 0 => Ok(()), - - 1 => write!(fmt, " -> {:?}", self.successors().next().unwrap()), - - _ => { - write!(fmt, " -> [")?; - for (i, target) in self.successors().enumerate() { - if i > 0 { - write!(fmt, ", ")?; - } - write!(fmt, "{}: {:?}", labels[i], target)?; - } - write!(fmt, "]") - } - } - } -} - -impl<'tcx> TerminatorKind<'tcx> { - /// Writes the "head" part of the terminator; that is, its name and the data it uses to pick the - /// successor basic block, if any. The only information not included is the list of possible - /// successors, which may be rendered differently between the text and the graphviz format. - pub fn fmt_head<W: Write>(&self, fmt: &mut W) -> fmt::Result { - use self::TerminatorKind::*; - match self { - Goto { .. } => write!(fmt, "goto"), - SwitchInt { discr, .. } => write!(fmt, "switchInt({:?})", discr), - Return => write!(fmt, "return"), - GeneratorDrop => write!(fmt, "generator_drop"), - Resume => write!(fmt, "resume"), - Abort => write!(fmt, "abort"), - Yield { value, resume_arg, .. } => write!(fmt, "{:?} = yield({:?})", resume_arg, value), - Unreachable => write!(fmt, "unreachable"), - Drop { place, .. } => write!(fmt, "drop({:?})", place), - DropAndReplace { place, value, .. } => { - write!(fmt, "replace({:?} <- {:?})", place, value) - } - Call { func, args, destination, .. } => { - if let Some((destination, _)) = destination { - write!(fmt, "{:?} = ", destination)?; - } - write!(fmt, "{:?}(", func)?; - for (index, arg) in args.iter().enumerate() { - if index > 0 { - write!(fmt, ", ")?; - } - write!(fmt, "{:?}", arg)?; - } - write!(fmt, ")") - } - Assert { cond, expected, msg, .. } => { - write!(fmt, "assert(")?; - if !expected { - write!(fmt, "!")?; - } - write!(fmt, "{:?}, ", cond)?; - msg.fmt_assert_args(fmt)?; - write!(fmt, ")") - } - FalseEdge { .. } => write!(fmt, "falseEdge"), - FalseUnwind { .. } => write!(fmt, "falseUnwind"), - InlineAsm { template, ref operands, options, .. } => { - write!(fmt, "asm!(\"{}\"", InlineAsmTemplatePiece::to_string(template))?; - for op in operands { - write!(fmt, ", ")?; - let print_late = |&late| if late { "late" } else { "" }; - match op { - InlineAsmOperand::In { reg, value } => { - write!(fmt, "in({}) {:?}", reg, value)?; - } - InlineAsmOperand::Out { reg, late, place: Some(place) } => { - write!(fmt, "{}out({}) {:?}", print_late(late), reg, place)?; - } - InlineAsmOperand::Out { reg, late, place: None } => { - write!(fmt, "{}out({}) _", print_late(late), reg)?; - } - InlineAsmOperand::InOut { - reg, - late, - in_value, - out_place: Some(out_place), - } => { - write!( - fmt, - "in{}out({}) {:?} => {:?}", - print_late(late), - reg, - in_value, - out_place - )?; - } - InlineAsmOperand::InOut { reg, late, in_value, out_place: None } => { - write!(fmt, "in{}out({}) {:?} => _", print_late(late), reg, in_value)?; - } - InlineAsmOperand::Const { value } => { - write!(fmt, "const {:?}", value)?; - } - InlineAsmOperand::SymFn { value } => { - write!(fmt, "sym_fn {:?}", value)?; - } - InlineAsmOperand::SymStatic { def_id } => { - write!(fmt, "sym_static {:?}", def_id)?; - } - } - } - write!(fmt, ", options({:?}))", options) - } - } - } - - /// Returns the list of labels for the edges to the successor basic blocks. - pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> { - use self::TerminatorKind::*; - match *self { - Return | Resume | Abort | Unreachable | GeneratorDrop => vec![], - Goto { .. } => vec!["".into()], - SwitchInt { ref values, switch_ty, .. } => ty::tls::with(|tcx| { - let param_env = ty::ParamEnv::empty(); - let switch_ty = tcx.lift(&switch_ty).unwrap(); - let size = tcx.layout_of(param_env.and(switch_ty)).unwrap().size; - values - .iter() - .map(|&u| { - ty::Const::from_scalar(tcx, Scalar::from_uint(u, size), switch_ty) - .to_string() - .into() - }) - .chain(iter::once("otherwise".into())) - .collect() - }), - Call { destination: Some(_), cleanup: Some(_), .. } => { - vec!["return".into(), "unwind".into()] - } - Call { destination: Some(_), cleanup: None, .. } => vec!["return".into()], - Call { destination: None, cleanup: Some(_), .. } => vec!["unwind".into()], - Call { destination: None, cleanup: None, .. } => vec![], - Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()], - Yield { drop: None, .. } => vec!["resume".into()], - DropAndReplace { unwind: None, .. } | Drop { unwind: None, .. } => { - vec!["return".into()] - } - DropAndReplace { unwind: Some(_), .. } | Drop { unwind: Some(_), .. } => { - vec!["return".into(), "unwind".into()] - } - Assert { cleanup: None, .. } => vec!["".into()], - Assert { .. } => vec!["success".into(), "unwind".into()], - FalseEdge { .. } => vec!["real".into(), "imaginary".into()], - FalseUnwind { unwind: Some(_), .. } => vec!["real".into(), "cleanup".into()], - FalseUnwind { unwind: None, .. } => vec!["real".into()], - InlineAsm { destination: Some(_), .. } => vec!["".into()], - InlineAsm { destination: None, .. } => vec![], - } - } -} - /////////////////////////////////////////////////////////////////////////// // Statements @@ -2307,6 +1818,18 @@ impl<'tcx> Operand<'tcx> { }) } + /// Convenience helper to make a `Scalar` from the given `Operand`, assuming that `Operand` + /// wraps a constant literal value. Panics if this is not the case. + pub fn scalar_from_const(operand: &Operand<'tcx>) -> Scalar { + match operand { + Operand::Constant(constant) => match constant.literal.val.try_to_scalar() { + Some(scalar) => scalar, + _ => panic!("{:?}: Scalar value expected", constant.literal.val), + }, + _ => panic!("{:?}: Constant expected", operand), + } + } + pub fn to_copy(&self) -> Self { match *self { Operand::Copy(_) | Operand::Constant(_) => self.clone(), @@ -2980,18 +2503,3 @@ impl Location { } } } - -/// Coverage data associated with each function (MIR) instrumented with coverage counters, when -/// compiled with `-Zinstrument_coverage`. The query `tcx.coverage_data(DefId)` computes these -/// values on demand (during code generation). This query is only valid after executing the MIR pass -/// `InstrumentCoverage`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] -pub struct CoverageData { - /// A hash value that can be used by the consumer of the coverage profile data to detect - /// changes to the instrumented source of the associated MIR body (typically, for an - /// individual function). - pub hash: u64, - - /// The total number of coverage region counters added to the MIR `Body`. - pub num_counters: u32, -} diff --git a/src/librustc_middle/mir/query.rs b/src/librustc_middle/mir/query.rs index 9ad79230a4f..8dddaf40c82 100644 --- a/src/librustc_middle/mir/query.rs +++ b/src/librustc_middle/mir/query.rs @@ -309,3 +309,17 @@ pub struct DestructuredConst<'tcx> { pub variant: Option<VariantIdx>, pub fields: &'tcx [&'tcx ty::Const<'tcx>], } + +/// Coverage information summarized from a MIR if instrumented for source code coverage (see +/// compiler option `-Zinstrument-coverage`). This information is generated by the +/// `InstrumentCoverage` MIR pass and can be retrieved via the `coverageinfo` query. +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] +pub struct CoverageInfo { + /// A hash value that can be used by the consumer of the coverage profile data to detect + /// changes to the instrumented source of the associated MIR body (typically, for an + /// individual function). + pub hash: u64, + + /// The total number of coverage region counters added to the MIR `Body`. + pub num_counters: u32, +} diff --git a/src/librustc_middle/mir/terminator/mod.rs b/src/librustc_middle/mir/terminator/mod.rs new file mode 100644 index 00000000000..1f5041141d5 --- /dev/null +++ b/src/librustc_middle/mir/terminator/mod.rs @@ -0,0 +1,507 @@ +use crate::mir::interpret::Scalar; +use crate::ty::{self, Ty, TyCtxt}; +use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; + +use super::{ + AssertMessage, BasicBlock, InlineAsmOperand, Operand, Place, SourceInfo, Successors, + SuccessorsMut, +}; +pub use rustc_ast::ast::Mutability; +use rustc_macros::HashStable; +use rustc_span::Span; +use std::borrow::Cow; +use std::fmt::{self, Debug, Formatter, Write}; +use std::iter; +use std::slice; + +pub use super::query::*; + +#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)] +pub enum TerminatorKind<'tcx> { + /// Block should have one successor in the graph; we jump there. + Goto { target: BasicBlock }, + + /// Operand evaluates to an integer; jump depending on its value + /// to one of the targets, and otherwise fallback to `otherwise`. + SwitchInt { + /// The discriminant value being tested. + discr: Operand<'tcx>, + + /// The type of value being tested. + /// This is always the same as the type of `discr`. + /// FIXME: remove this redundant information. Currently, it is relied on by pretty-printing. + switch_ty: Ty<'tcx>, + + /// Possible values. The locations to branch to in each case + /// are found in the corresponding indices from the `targets` vector. + values: Cow<'tcx, [u128]>, + + /// Possible branch sites. The last element of this vector is used + /// for the otherwise branch, so targets.len() == values.len() + 1 + /// should hold. + // + // This invariant is quite non-obvious and also could be improved. + // One way to make this invariant is to have something like this instead: + // + // branches: Vec<(ConstInt, BasicBlock)>, + // otherwise: Option<BasicBlock> // exhaustive if None + // + // However we’ve decided to keep this as-is until we figure a case + // where some other approach seems to be strictly better than other. + targets: Vec<BasicBlock>, + }, + + /// Indicates that the landing pad is finished and unwinding should + /// continue. Emitted by `build::scope::diverge_cleanup`. + Resume, + + /// Indicates that the landing pad is finished and that the process + /// should abort. Used to prevent unwinding for foreign items. + Abort, + + /// Indicates a normal return. The return place should have + /// been filled in before this executes. This can occur multiple times + /// in different basic blocks. + Return, + + /// Indicates a terminator that can never be reached. + Unreachable, + + /// Drop the `Place`. + Drop { place: Place<'tcx>, target: BasicBlock, unwind: Option<BasicBlock> }, + + /// Drop the `Place` and assign the new value over it. This ensures + /// that the assignment to `P` occurs *even if* the destructor for + /// place unwinds. Its semantics are best explained by the + /// elaboration: + /// + /// ``` + /// BB0 { + /// DropAndReplace(P <- V, goto BB1, unwind BB2) + /// } + /// ``` + /// + /// becomes + /// + /// ``` + /// BB0 { + /// Drop(P, goto BB1, unwind BB2) + /// } + /// BB1 { + /// // P is now uninitialized + /// P <- V + /// } + /// BB2 { + /// // P is now uninitialized -- its dtor panicked + /// P <- V + /// } + /// ``` + DropAndReplace { + place: Place<'tcx>, + value: Operand<'tcx>, + target: BasicBlock, + unwind: Option<BasicBlock>, + }, + + /// Block ends with a call of a converging function. + Call { + /// The function that’s being called. + func: Operand<'tcx>, + /// Arguments the function is called with. + /// These are owned by the callee, which is free to modify them. + /// This allows the memory occupied by "by-value" arguments to be + /// reused across function calls without duplicating the contents. + args: Vec<Operand<'tcx>>, + /// Destination for the return value. If some, the call is converging. + destination: Option<(Place<'tcx>, BasicBlock)>, + /// Cleanups to be done if the call unwinds. + cleanup: Option<BasicBlock>, + /// `true` if this is from a call in HIR rather than from an overloaded + /// operator. True for overloaded function call. + from_hir_call: bool, + /// This `Span` is the span of the function, without the dot and receiver + /// (e.g. `foo(a, b)` in `x.foo(a, b)` + fn_span: Span, + }, + + /// Jump to the target if the condition has the expected value, + /// otherwise panic with a message and a cleanup target. + Assert { + cond: Operand<'tcx>, + expected: bool, + msg: AssertMessage<'tcx>, + target: BasicBlock, + cleanup: Option<BasicBlock>, + }, + + /// A suspend point. + Yield { + /// The value to return. + value: Operand<'tcx>, + /// Where to resume to. + resume: BasicBlock, + /// The place to store the resume argument in. + resume_arg: Place<'tcx>, + /// Cleanup to be done if the generator is dropped at this suspend point. + drop: Option<BasicBlock>, + }, + + /// Indicates the end of the dropping of a generator. + GeneratorDrop, + + /// A block where control flow only ever takes one real path, but borrowck + /// needs to be more conservative. + FalseEdge { + /// The target normal control flow will take. + real_target: BasicBlock, + /// A block control flow could conceptually jump to, but won't in + /// practice. + imaginary_target: BasicBlock, + }, + /// A terminator for blocks that only take one path in reality, but where we + /// reserve the right to unwind in borrowck, even if it won't happen in practice. + /// This can arise in infinite loops with no function calls for example. + FalseUnwind { + /// The target normal control flow will take. + real_target: BasicBlock, + /// The imaginary cleanup block link. This particular path will never be taken + /// in practice, but in order to avoid fragility we want to always + /// consider it in borrowck. We don't want to accept programs which + /// pass borrowck only when `panic=abort` or some assertions are disabled + /// due to release vs. debug mode builds. This needs to be an `Option` because + /// of the `remove_noop_landing_pads` and `no_landing_pads` passes. + unwind: Option<BasicBlock>, + }, + + /// Block ends with an inline assembly block. This is a terminator since + /// inline assembly is allowed to diverge. + InlineAsm { + /// The template for the inline assembly, with placeholders. + template: &'tcx [InlineAsmTemplatePiece], + + /// The operands for the inline assembly, as `Operand`s or `Place`s. + operands: Vec<InlineAsmOperand<'tcx>>, + + /// Miscellaneous options for the inline assembly. + options: InlineAsmOptions, + + /// Source spans for each line of the inline assembly code. These are + /// used to map assembler errors back to the line in the source code. + line_spans: &'tcx [Span], + + /// Destination block after the inline assembly returns, unless it is + /// diverging (InlineAsmOptions::NORETURN). + destination: Option<BasicBlock>, + }, +} +#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] +pub struct Terminator<'tcx> { + pub source_info: SourceInfo, + pub kind: TerminatorKind<'tcx>, +} + +impl<'tcx> Terminator<'tcx> { + pub fn successors(&self) -> Successors<'_> { + self.kind.successors() + } + + pub fn successors_mut(&mut self) -> SuccessorsMut<'_> { + self.kind.successors_mut() + } + + pub fn unwind(&self) -> Option<&Option<BasicBlock>> { + self.kind.unwind() + } + + pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> { + self.kind.unwind_mut() + } +} + +impl<'tcx> TerminatorKind<'tcx> { + pub fn if_( + tcx: TyCtxt<'tcx>, + cond: Operand<'tcx>, + t: BasicBlock, + f: BasicBlock, + ) -> TerminatorKind<'tcx> { + static BOOL_SWITCH_FALSE: &[u128] = &[0]; + TerminatorKind::SwitchInt { + discr: cond, + switch_ty: tcx.types.bool, + values: From::from(BOOL_SWITCH_FALSE), + targets: vec![f, t], + } + } + + pub fn successors(&self) -> Successors<'_> { + use self::TerminatorKind::*; + match *self { + Resume + | Abort + | GeneratorDrop + | Return + | Unreachable + | Call { destination: None, cleanup: None, .. } + | InlineAsm { destination: None, .. } => None.into_iter().chain(&[]), + Goto { target: ref t } + | Call { destination: None, cleanup: Some(ref t), .. } + | Call { destination: Some((_, ref t)), cleanup: None, .. } + | Yield { resume: ref t, drop: None, .. } + | DropAndReplace { target: ref t, unwind: None, .. } + | Drop { target: ref t, unwind: None, .. } + | Assert { target: ref t, cleanup: None, .. } + | FalseUnwind { real_target: ref t, unwind: None } + | InlineAsm { destination: Some(ref t), .. } => Some(t).into_iter().chain(&[]), + Call { destination: Some((_, ref t)), cleanup: Some(ref u), .. } + | Yield { resume: ref t, drop: Some(ref u), .. } + | DropAndReplace { target: ref t, unwind: Some(ref u), .. } + | Drop { target: ref t, unwind: Some(ref u), .. } + | Assert { target: ref t, cleanup: Some(ref u), .. } + | FalseUnwind { real_target: ref t, unwind: Some(ref u) } => { + Some(t).into_iter().chain(slice::from_ref(u)) + } + SwitchInt { ref targets, .. } => None.into_iter().chain(&targets[..]), + FalseEdge { ref real_target, ref imaginary_target } => { + Some(real_target).into_iter().chain(slice::from_ref(imaginary_target)) + } + } + } + + pub fn successors_mut(&mut self) -> SuccessorsMut<'_> { + use self::TerminatorKind::*; + match *self { + Resume + | Abort + | GeneratorDrop + | Return + | Unreachable + | Call { destination: None, cleanup: None, .. } + | InlineAsm { destination: None, .. } => None.into_iter().chain(&mut []), + Goto { target: ref mut t } + | Call { destination: None, cleanup: Some(ref mut t), .. } + | Call { destination: Some((_, ref mut t)), cleanup: None, .. } + | Yield { resume: ref mut t, drop: None, .. } + | DropAndReplace { target: ref mut t, unwind: None, .. } + | Drop { target: ref mut t, unwind: None, .. } + | Assert { target: ref mut t, cleanup: None, .. } + | FalseUnwind { real_target: ref mut t, unwind: None } + | InlineAsm { destination: Some(ref mut t), .. } => Some(t).into_iter().chain(&mut []), + Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut u), .. } + | Yield { resume: ref mut t, drop: Some(ref mut u), .. } + | DropAndReplace { target: ref mut t, unwind: Some(ref mut u), .. } + | Drop { target: ref mut t, unwind: Some(ref mut u), .. } + | Assert { target: ref mut t, cleanup: Some(ref mut u), .. } + | FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } => { + Some(t).into_iter().chain(slice::from_mut(u)) + } + SwitchInt { ref mut targets, .. } => None.into_iter().chain(&mut targets[..]), + FalseEdge { ref mut real_target, ref mut imaginary_target } => { + Some(real_target).into_iter().chain(slice::from_mut(imaginary_target)) + } + } + } + + pub fn unwind(&self) -> Option<&Option<BasicBlock>> { + match *self { + TerminatorKind::Goto { .. } + | TerminatorKind::Resume + | TerminatorKind::Abort + | TerminatorKind::Return + | TerminatorKind::Unreachable + | TerminatorKind::GeneratorDrop + | TerminatorKind::Yield { .. } + | TerminatorKind::SwitchInt { .. } + | TerminatorKind::FalseEdge { .. } + | TerminatorKind::InlineAsm { .. } => None, + TerminatorKind::Call { cleanup: ref unwind, .. } + | TerminatorKind::Assert { cleanup: ref unwind, .. } + | TerminatorKind::DropAndReplace { ref unwind, .. } + | TerminatorKind::Drop { ref unwind, .. } + | TerminatorKind::FalseUnwind { ref unwind, .. } => Some(unwind), + } + } + + pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> { + match *self { + TerminatorKind::Goto { .. } + | TerminatorKind::Resume + | TerminatorKind::Abort + | TerminatorKind::Return + | TerminatorKind::Unreachable + | TerminatorKind::GeneratorDrop + | TerminatorKind::Yield { .. } + | TerminatorKind::SwitchInt { .. } + | TerminatorKind::FalseEdge { .. } + | TerminatorKind::InlineAsm { .. } => None, + TerminatorKind::Call { cleanup: ref mut unwind, .. } + | TerminatorKind::Assert { cleanup: ref mut unwind, .. } + | TerminatorKind::DropAndReplace { ref mut unwind, .. } + | TerminatorKind::Drop { ref mut unwind, .. } + | TerminatorKind::FalseUnwind { ref mut unwind, .. } => Some(unwind), + } + } +} + +impl<'tcx> Debug for TerminatorKind<'tcx> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { + self.fmt_head(fmt)?; + let successor_count = self.successors().count(); + let labels = self.fmt_successor_labels(); + assert_eq!(successor_count, labels.len()); + + match successor_count { + 0 => Ok(()), + + 1 => write!(fmt, " -> {:?}", self.successors().next().unwrap()), + + _ => { + write!(fmt, " -> [")?; + for (i, target) in self.successors().enumerate() { + if i > 0 { + write!(fmt, ", ")?; + } + write!(fmt, "{}: {:?}", labels[i], target)?; + } + write!(fmt, "]") + } + } + } +} + +impl<'tcx> TerminatorKind<'tcx> { + /// Writes the "head" part of the terminator; that is, its name and the data it uses to pick the + /// successor basic block, if any. The only information not included is the list of possible + /// successors, which may be rendered differently between the text and the graphviz format. + pub fn fmt_head<W: Write>(&self, fmt: &mut W) -> fmt::Result { + use self::TerminatorKind::*; + match self { + Goto { .. } => write!(fmt, "goto"), + SwitchInt { discr, .. } => write!(fmt, "switchInt({:?})", discr), + Return => write!(fmt, "return"), + GeneratorDrop => write!(fmt, "generator_drop"), + Resume => write!(fmt, "resume"), + Abort => write!(fmt, "abort"), + Yield { value, resume_arg, .. } => write!(fmt, "{:?} = yield({:?})", resume_arg, value), + Unreachable => write!(fmt, "unreachable"), + Drop { place, .. } => write!(fmt, "drop({:?})", place), + DropAndReplace { place, value, .. } => { + write!(fmt, "replace({:?} <- {:?})", place, value) + } + Call { func, args, destination, .. } => { + if let Some((destination, _)) = destination { + write!(fmt, "{:?} = ", destination)?; + } + write!(fmt, "{:?}(", func)?; + for (index, arg) in args.iter().enumerate() { + if index > 0 { + write!(fmt, ", ")?; + } + write!(fmt, "{:?}", arg)?; + } + write!(fmt, ")") + } + Assert { cond, expected, msg, .. } => { + write!(fmt, "assert(")?; + if !expected { + write!(fmt, "!")?; + } + write!(fmt, "{:?}, ", cond)?; + msg.fmt_assert_args(fmt)?; + write!(fmt, ")") + } + FalseEdge { .. } => write!(fmt, "falseEdge"), + FalseUnwind { .. } => write!(fmt, "falseUnwind"), + InlineAsm { template, ref operands, options, .. } => { + write!(fmt, "asm!(\"{}\"", InlineAsmTemplatePiece::to_string(template))?; + for op in operands { + write!(fmt, ", ")?; + let print_late = |&late| if late { "late" } else { "" }; + match op { + InlineAsmOperand::In { reg, value } => { + write!(fmt, "in({}) {:?}", reg, value)?; + } + InlineAsmOperand::Out { reg, late, place: Some(place) } => { + write!(fmt, "{}out({}) {:?}", print_late(late), reg, place)?; + } + InlineAsmOperand::Out { reg, late, place: None } => { + write!(fmt, "{}out({}) _", print_late(late), reg)?; + } + InlineAsmOperand::InOut { + reg, + late, + in_value, + out_place: Some(out_place), + } => { + write!( + fmt, + "in{}out({}) {:?} => {:?}", + print_late(late), + reg, + in_value, + out_place + )?; + } + InlineAsmOperand::InOut { reg, late, in_value, out_place: None } => { + write!(fmt, "in{}out({}) {:?} => _", print_late(late), reg, in_value)?; + } + InlineAsmOperand::Const { value } => { + write!(fmt, "const {:?}", value)?; + } + InlineAsmOperand::SymFn { value } => { + write!(fmt, "sym_fn {:?}", value)?; + } + InlineAsmOperand::SymStatic { def_id } => { + write!(fmt, "sym_static {:?}", def_id)?; + } + } + } + write!(fmt, ", options({:?}))", options) + } + } + } + + /// Returns the list of labels for the edges to the successor basic blocks. + pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> { + use self::TerminatorKind::*; + match *self { + Return | Resume | Abort | Unreachable | GeneratorDrop => vec![], + Goto { .. } => vec!["".into()], + SwitchInt { ref values, switch_ty, .. } => ty::tls::with(|tcx| { + let param_env = ty::ParamEnv::empty(); + let switch_ty = tcx.lift(&switch_ty).unwrap(); + let size = tcx.layout_of(param_env.and(switch_ty)).unwrap().size; + values + .iter() + .map(|&u| { + ty::Const::from_scalar(tcx, Scalar::from_uint(u, size), switch_ty) + .to_string() + .into() + }) + .chain(iter::once("otherwise".into())) + .collect() + }), + Call { destination: Some(_), cleanup: Some(_), .. } => { + vec!["return".into(), "unwind".into()] + } + Call { destination: Some(_), cleanup: None, .. } => vec!["return".into()], + Call { destination: None, cleanup: Some(_), .. } => vec!["unwind".into()], + Call { destination: None, cleanup: None, .. } => vec![], + Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()], + Yield { drop: None, .. } => vec!["resume".into()], + DropAndReplace { unwind: None, .. } | Drop { unwind: None, .. } => { + vec!["return".into()] + } + DropAndReplace { unwind: Some(_), .. } | Drop { unwind: Some(_), .. } => { + vec!["return".into(), "unwind".into()] + } + Assert { cleanup: None, .. } => vec!["".into()], + Assert { .. } => vec!["success".into(), "unwind".into()], + FalseEdge { .. } => vec!["real".into(), "imaginary".into()], + FalseUnwind { unwind: Some(_), .. } => vec!["real".into(), "cleanup".into()], + FalseUnwind { unwind: None, .. } => vec!["real".into()], + InlineAsm { destination: Some(_), .. } => vec!["".into()], + InlineAsm { destination: None, .. } => vec![], + } + } +} diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs index ba5a8c3ec20..3285be555d3 100644 --- a/src/librustc_middle/query/mod.rs +++ b/src/librustc_middle/query/mod.rs @@ -231,8 +231,10 @@ rustc_queries! { cache_on_disk_if { key.is_local() } } - query coverage_data(key: DefId) -> mir::CoverageData { - desc { |tcx| "retrieving coverage data from MIR for `{}`", tcx.def_path_str(key) } + /// Returns coverage summary info for a function, after executing the `InstrumentCoverage` + /// MIR pass (assuming the -Zinstrument-coverage option is enabled). + query coverageinfo(key: DefId) -> mir::CoverageInfo { + desc { |tcx| "retrieving coverage info from MIR for `{}`", tcx.def_path_str(key) } storage(ArenaCacheSelector<'tcx>) cache_on_disk_if { key.is_local() } } @@ -1042,6 +1044,10 @@ rustc_queries! { eval_always desc { "looking up the extra filename for a crate" } } + query crate_extern_paths(_: CrateNum) -> Vec<PathBuf> { + eval_always + desc { "looking up the paths for extern crates" } + } } TypeChecking { diff --git a/src/librustc_middle/ty/_match.rs b/src/librustc_middle/ty/_match.rs index db9229ae3d2..4693a2f66fb 100644 --- a/src/librustc_middle/ty/_match.rs +++ b/src/librustc_middle/ty/_match.rs @@ -46,8 +46,8 @@ impl TypeRelation<'tcx> for Match<'tcx> { fn relate_with_variance<T: Relate<'tcx>>( &mut self, _: ty::Variance, - a: &T, - b: &T, + a: T, + b: T, ) -> RelateResult<'tcx, T> { self.relate(a, b) } @@ -112,8 +112,8 @@ impl TypeRelation<'tcx> for Match<'tcx> { fn binders<T>( &mut self, - a: &ty::Binder<T>, - b: &ty::Binder<T>, + a: ty::Binder<T>, + b: ty::Binder<T>, ) -> RelateResult<'tcx, ty::Binder<T>> where T: Relate<'tcx>, diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs index e2f601371b1..d942c07965a 100644 --- a/src/librustc_middle/ty/context.rs +++ b/src/librustc_middle/ty/context.rs @@ -188,7 +188,7 @@ pub struct CommonConsts<'tcx> { } pub struct LocalTableInContext<'a, V> { - hir_owner: Option<LocalDefId>, + hir_owner: LocalDefId, data: &'a ItemLocalMap<V>, } @@ -199,42 +199,27 @@ pub struct LocalTableInContext<'a, V> { /// would be in a different frame of reference and using its `local_id` /// would result in lookup errors, or worse, in silently wrong data being /// stored/returned. -fn validate_hir_id_for_typeck_tables( - hir_owner: Option<LocalDefId>, - hir_id: hir::HirId, - mut_access: bool, -) { - if let Some(hir_owner) = hir_owner { - if hir_id.owner != hir_owner { - ty::tls::with(|tcx| { - bug!( - "node {} with HirId::owner {:?} cannot be placed in TypeckTables with hir_owner {:?}", - tcx.hir().node_to_string(hir_id), - hir_id.owner, - hir_owner - ) - }); - } - } else { - // We use "Null Object" TypeckTables in some of the analysis passes. - // These are just expected to be empty and their `hir_owner` is - // `None`. Therefore we cannot verify whether a given `HirId` would - // be a valid key for the given table. Instead we make sure that - // nobody tries to write to such a Null Object table. - if mut_access { - bug!("access to invalid TypeckTables") - } +fn validate_hir_id_for_typeck_tables(hir_owner: LocalDefId, hir_id: hir::HirId) { + if hir_id.owner != hir_owner { + ty::tls::with(|tcx| { + bug!( + "node {} with HirId::owner {:?} cannot be placed in TypeckTables with hir_owner {:?}", + tcx.hir().node_to_string(hir_id), + hir_id.owner, + hir_owner + ) + }); } } impl<'a, V> LocalTableInContext<'a, V> { pub fn contains_key(&self, id: hir::HirId) -> bool { - validate_hir_id_for_typeck_tables(self.hir_owner, id, false); + validate_hir_id_for_typeck_tables(self.hir_owner, id); self.data.contains_key(&id.local_id) } pub fn get(&self, id: hir::HirId) -> Option<&V> { - validate_hir_id_for_typeck_tables(self.hir_owner, id, false); + validate_hir_id_for_typeck_tables(self.hir_owner, id); self.data.get(&id.local_id) } @@ -252,28 +237,28 @@ impl<'a, V> ::std::ops::Index<hir::HirId> for LocalTableInContext<'a, V> { } pub struct LocalTableInContextMut<'a, V> { - hir_owner: Option<LocalDefId>, + hir_owner: LocalDefId, data: &'a mut ItemLocalMap<V>, } impl<'a, V> LocalTableInContextMut<'a, V> { pub fn get_mut(&mut self, id: hir::HirId) -> Option<&mut V> { - validate_hir_id_for_typeck_tables(self.hir_owner, id, true); + validate_hir_id_for_typeck_tables(self.hir_owner, id); self.data.get_mut(&id.local_id) } pub fn entry(&mut self, id: hir::HirId) -> Entry<'_, hir::ItemLocalId, V> { - validate_hir_id_for_typeck_tables(self.hir_owner, id, true); + validate_hir_id_for_typeck_tables(self.hir_owner, id); self.data.entry(id.local_id) } pub fn insert(&mut self, id: hir::HirId, val: V) -> Option<V> { - validate_hir_id_for_typeck_tables(self.hir_owner, id, true); + validate_hir_id_for_typeck_tables(self.hir_owner, id); self.data.insert(id.local_id, val) } pub fn remove(&mut self, id: hir::HirId) -> Option<V> { - validate_hir_id_for_typeck_tables(self.hir_owner, id, true); + validate_hir_id_for_typeck_tables(self.hir_owner, id); self.data.remove(&id.local_id) } } @@ -324,7 +309,7 @@ pub struct GeneratorInteriorTypeCause<'tcx> { #[derive(RustcEncodable, RustcDecodable, Debug)] pub struct TypeckTables<'tcx> { /// The `HirId::owner` all `ItemLocalId`s in this table are relative to. - pub hir_owner: Option<LocalDefId>, + pub hir_owner: LocalDefId, /// Resolved definitions for `<T>::X` associated paths and /// method calls, including those of overloaded operators. @@ -432,7 +417,7 @@ pub struct TypeckTables<'tcx> { } impl<'tcx> TypeckTables<'tcx> { - pub fn empty(hir_owner: Option<LocalDefId>) -> TypeckTables<'tcx> { + pub fn new(hir_owner: LocalDefId) -> TypeckTables<'tcx> { TypeckTables { hir_owner, type_dependent_defs: Default::default(), @@ -474,7 +459,7 @@ impl<'tcx> TypeckTables<'tcx> { } pub fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> { - validate_hir_id_for_typeck_tables(self.hir_owner, id, false); + validate_hir_id_for_typeck_tables(self.hir_owner, id); self.type_dependent_defs.get(&id.local_id).cloned().and_then(|r| r.ok()) } @@ -521,7 +506,7 @@ impl<'tcx> TypeckTables<'tcx> { } pub fn node_type_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> { - validate_hir_id_for_typeck_tables(self.hir_owner, id, false); + validate_hir_id_for_typeck_tables(self.hir_owner, id); self.node_types.get(&id.local_id).cloned() } @@ -530,12 +515,12 @@ impl<'tcx> TypeckTables<'tcx> { } pub fn node_substs(&self, id: hir::HirId) -> SubstsRef<'tcx> { - validate_hir_id_for_typeck_tables(self.hir_owner, id, false); + validate_hir_id_for_typeck_tables(self.hir_owner, id); self.node_substs.get(&id.local_id).cloned().unwrap_or_else(|| InternalSubsts::empty()) } pub fn node_substs_opt(&self, id: hir::HirId) -> Option<SubstsRef<'tcx>> { - validate_hir_id_for_typeck_tables(self.hir_owner, id, false); + validate_hir_id_for_typeck_tables(self.hir_owner, id); self.node_substs.get(&id.local_id).cloned() } @@ -578,7 +563,7 @@ impl<'tcx> TypeckTables<'tcx> { } pub fn expr_adjustments(&self, expr: &hir::Expr<'_>) -> &[ty::adjustment::Adjustment<'tcx>] { - validate_hir_id_for_typeck_tables(self.hir_owner, expr.hir_id, false); + validate_hir_id_for_typeck_tables(self.hir_owner, expr.hir_id); self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..]) } @@ -657,7 +642,7 @@ impl<'tcx> TypeckTables<'tcx> { } pub fn is_coercion_cast(&self, hir_id: hir::HirId) -> bool { - validate_hir_id_for_typeck_tables(self.hir_owner, hir_id, true); + validate_hir_id_for_typeck_tables(self.hir_owner, hir_id); self.coercion_casts.contains(&hir_id.local_id) } @@ -710,7 +695,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckTables<'tcx> { hash_stable_hashmap(hcx, hasher, upvar_capture_map, |up_var_id, hcx| { let ty::UpvarId { var_path, closure_expr_id } = *up_var_id; - assert_eq!(Some(var_path.hir_id.owner), hir_owner); + assert_eq!(var_path.hir_id.owner, hir_owner); ( hcx.local_def_path_hash(var_path.hir_id.owner), @@ -1049,6 +1034,7 @@ impl<'tcx> TyCtxt<'tcx> { Some(attr) => attr, None => return Bound::Unbounded, }; + debug!("layout_scalar_valid_range: attr={:?}", attr); for meta in attr.meta_item_list().expect("rustc_layout_scalar_valid_range takes args") { match meta.literal().expect("attribute takes lit").kind { ast::LitKind::Int(a, _) => return Bound::Included(a), @@ -1169,7 +1155,7 @@ impl<'tcx> TyCtxt<'tcx> { self.ty_error_with_message(DUMMY_SP, "TyKind::Error constructed but no error reported") } - /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg to + /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to /// ensure it gets used. #[track_caller] pub fn ty_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Ty<'tcx> { diff --git a/src/librustc_middle/ty/error.rs b/src/librustc_middle/ty/error.rs index 6113359ca93..30ff5a2d9eb 100644 --- a/src/librustc_middle/ty/error.rs +++ b/src/librustc_middle/ty/error.rs @@ -57,7 +57,6 @@ pub enum TypeError<'tcx> { /// type). CyclicTy(Ty<'tcx>), ProjectionMismatched(ExpectedFound<DefId>), - ProjectionBoundsLength(ExpectedFound<usize>), ExistentialMismatch(ExpectedFound<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>), ObjectUnsafeCoercion(DefId), ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>), @@ -174,13 +173,6 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { tcx.def_path_str(values.found) ) }), - ProjectionBoundsLength(ref values) => write!( - f, - "expected {} associated type binding{}, found {}", - values.expected, - pluralize!(values.expected), - values.found - ), ExistentialMismatch(ref values) => report_maybe_different( f, &format!("trait `{}`", values.expected), @@ -216,7 +208,6 @@ impl<'tcx> TypeError<'tcx> { | RegionsPlaceholderMismatch | Traits(_) | ProjectionMismatched(_) - | ProjectionBoundsLength(_) | ExistentialMismatch(_) | ConstMismatch(_) | IntrinsicCast diff --git a/src/librustc_middle/ty/flags.rs b/src/librustc_middle/ty/flags.rs index c782eee9387..0e86fcf53b2 100644 --- a/src/librustc_middle/ty/flags.rs +++ b/src/librustc_middle/ty/flags.rs @@ -88,13 +88,13 @@ impl FlagComputation { self.add_substs(substs); } - &ty::GeneratorWitness(ref ts) => { + &ty::GeneratorWitness(ts) => { let mut computation = FlagComputation::new(); - computation.add_tys(&ts.skip_binder()[..]); + computation.add_tys(ts.skip_binder()); self.add_bound_computation(computation); } - &ty::Closure(_, ref substs) => { + &ty::Closure(_, substs) => { self.add_substs(substs); } @@ -122,7 +122,7 @@ impl FlagComputation { self.add_substs(substs); } - &ty::Projection(ref data) => { + &ty::Projection(data) => { self.add_flags(TypeFlags::HAS_TY_PROJECTION); self.add_projection_ty(data); } @@ -211,7 +211,7 @@ impl FlagComputation { self.add_bound_computation(computation); } - ty::PredicateKind::Projection(projection) => { + &ty::PredicateKind::Projection(projection) => { let mut computation = FlagComputation::new(); let ty::ProjectionPredicate { projection_ty, ty } = projection.skip_binder(); computation.add_projection_ty(projection_ty); @@ -298,7 +298,7 @@ impl FlagComputation { self.add_ty(projection.ty); } - fn add_projection_ty(&mut self, projection_ty: &ty::ProjectionTy<'_>) { + fn add_projection_ty(&mut self, projection_ty: ty::ProjectionTy<'_>) { self.add_substs(projection_ty.substs); } diff --git a/src/librustc_middle/ty/fold.rs b/src/librustc_middle/ty/fold.rs index 2d25c7c6ac9..492f8ce9ef1 100644 --- a/src/librustc_middle/ty/fold.rs +++ b/src/librustc_middle/ty/fold.rs @@ -336,7 +336,7 @@ impl<'tcx> TyCtxt<'tcx> { { fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> bool { self.outer_index.shift_in(1); - let result = t.skip_binder().visit_with(self); + let result = t.as_ref().skip_binder().visit_with(self); self.outer_index.shift_out(1); result } @@ -558,7 +558,7 @@ impl<'tcx> TyCtxt<'tcx> { let fld_c = |bound_ct, ty| { self.mk_const(ty::Const { val: ty::ConstKind::Bound(ty::INNERMOST, bound_ct), ty }) }; - self.replace_escaping_bound_vars(value.skip_binder(), fld_r, fld_t, fld_c) + self.replace_escaping_bound_vars(value.as_ref().skip_binder(), fld_r, fld_t, fld_c) } /// Replaces all escaping bound vars. The `fld_r` closure replaces escaping @@ -617,7 +617,7 @@ impl<'tcx> TyCtxt<'tcx> { H: FnMut(ty::BoundVar, Ty<'tcx>) -> &'tcx ty::Const<'tcx>, T: TypeFoldable<'tcx>, { - self.replace_escaping_bound_vars(value.skip_binder(), fld_r, fld_t, fld_c) + self.replace_escaping_bound_vars(value.as_ref().skip_binder(), fld_r, fld_t, fld_c) } /// Replaces any late-bound regions bound in `value` with @@ -673,7 +673,7 @@ impl<'tcx> TyCtxt<'tcx> { T: TypeFoldable<'tcx>, { let mut collector = LateBoundRegionsCollector::new(just_constraint); - let result = value.skip_binder().visit_with(&mut collector); + let result = value.as_ref().skip_binder().visit_with(&mut collector); assert!(!result); // should never have stopped early collector.regions } diff --git a/src/librustc_middle/ty/layout.rs b/src/librustc_middle/ty/layout.rs index e4cc96dd83b..39b8566e7a8 100644 --- a/src/librustc_middle/ty/layout.rs +++ b/src/librustc_middle/ty/layout.rs @@ -2303,7 +2303,7 @@ impl<'tcx> ty::Instance<'tcx> { let env_ty = tcx.closure_env_ty(def_id, substs).unwrap(); sig.map_bound(|sig| tcx.mk_fn_sig( - iter::once(*env_ty.skip_binder()).chain(sig.inputs().iter().cloned()), + iter::once(env_ty.skip_binder()).chain(sig.inputs().iter().cloned()), sig.output(), sig.c_variadic, sig.unsafety, diff --git a/src/librustc_middle/ty/print/pretty.rs b/src/librustc_middle/ty/print/pretty.rs index 06121424971..9fa1260f64d 100644 --- a/src/librustc_middle/ty/print/pretty.rs +++ b/src/librustc_middle/ty/print/pretty.rs @@ -189,7 +189,7 @@ pub trait PrettyPrinter<'tcx>: where T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>, { - value.skip_binder().print(self) + value.as_ref().skip_binder().print(self) } /// Prints comma-separated elements. diff --git a/src/librustc_middle/ty/query/mod.rs b/src/librustc_middle/ty/query/mod.rs index 35d19b7603f..2ad49b1acce 100644 --- a/src/librustc_middle/ty/query/mod.rs +++ b/src/librustc_middle/ty/query/mod.rs @@ -57,6 +57,7 @@ use rustc_span::{Span, DUMMY_SP}; use std::borrow::Cow; use std::collections::BTreeMap; use std::ops::Deref; +use std::path::PathBuf; use std::sync::Arc; #[macro_use] diff --git a/src/librustc_middle/ty/relate.rs b/src/librustc_middle/ty/relate.rs index e9a8b9095bf..cee04ce8c6a 100644 --- a/src/librustc_middle/ty/relate.rs +++ b/src/librustc_middle/ty/relate.rs @@ -13,7 +13,6 @@ use rustc_hir::def_id::DefId; use rustc_span::DUMMY_SP; use rustc_target::spec::abi; use std::iter; -use std::rc::Rc; pub type RelateResult<'tcx, T> = Result<T, TypeError<'tcx>>; @@ -42,7 +41,7 @@ pub trait TypeRelation<'tcx>: Sized { } /// Generic relation routine suitable for most anything. - fn relate<T: Relate<'tcx>>(&mut self, a: &T, b: &T) -> RelateResult<'tcx, T> { + fn relate<T: Relate<'tcx>>(&mut self, a: T, b: T) -> RelateResult<'tcx, T> { Relate::relate(self, a, b) } @@ -68,8 +67,8 @@ pub trait TypeRelation<'tcx>: Sized { fn relate_with_variance<T: Relate<'tcx>>( &mut self, variance: ty::Variance, - a: &T, - b: &T, + a: T, + b: T, ) -> RelateResult<'tcx, T>; // Overridable relations. You shouldn't typically call these @@ -94,18 +93,18 @@ pub trait TypeRelation<'tcx>: Sized { fn binders<T>( &mut self, - a: &ty::Binder<T>, - b: &ty::Binder<T>, + a: ty::Binder<T>, + b: ty::Binder<T>, ) -> RelateResult<'tcx, ty::Binder<T>> where T: Relate<'tcx>; } -pub trait Relate<'tcx>: TypeFoldable<'tcx> { +pub trait Relate<'tcx>: TypeFoldable<'tcx> + Copy { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: &Self, - b: &Self, + a: Self, + b: Self, ) -> RelateResult<'tcx, Self>; } @@ -115,8 +114,8 @@ pub trait Relate<'tcx>: TypeFoldable<'tcx> { impl<'tcx> Relate<'tcx> for ty::TypeAndMut<'tcx> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: &ty::TypeAndMut<'tcx>, - b: &ty::TypeAndMut<'tcx>, + a: ty::TypeAndMut<'tcx>, + b: ty::TypeAndMut<'tcx>, ) -> RelateResult<'tcx, ty::TypeAndMut<'tcx>> { debug!("{}.mts({:?}, {:?})", relation.tag(), a, b); if a.mutbl != b.mutbl { @@ -127,7 +126,7 @@ impl<'tcx> Relate<'tcx> for ty::TypeAndMut<'tcx> { ast::Mutability::Not => ty::Covariant, ast::Mutability::Mut => ty::Invariant, }; - let ty = relation.relate_with_variance(variance, &a.ty, &b.ty)?; + let ty = relation.relate_with_variance(variance, a.ty, b.ty)?; Ok(ty::TypeAndMut { ty, mutbl }) } } @@ -143,7 +142,7 @@ pub fn relate_substs<R: TypeRelation<'tcx>>( let params = a_subst.iter().zip(b_subst).enumerate().map(|(i, (a, b))| { let variance = variances.map_or(ty::Invariant, |v| v[i]); - relation.relate_with_variance(variance, &a, &b) + relation.relate_with_variance(variance, a, b) }); Ok(tcx.mk_substs(params)?) @@ -152,8 +151,8 @@ pub fn relate_substs<R: TypeRelation<'tcx>>( impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: &ty::FnSig<'tcx>, - b: &ty::FnSig<'tcx>, + a: ty::FnSig<'tcx>, + b: ty::FnSig<'tcx>, ) -> RelateResult<'tcx, ty::FnSig<'tcx>> { let tcx = relation.tcx(); @@ -164,8 +163,8 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { &b.c_variadic, ))); } - let unsafety = relation.relate(&a.unsafety, &b.unsafety)?; - let abi = relation.relate(&a.abi, &b.abi)?; + let unsafety = relation.relate(a.unsafety, b.unsafety)?; + let abi = relation.relate(a.abi, b.abi)?; if a.inputs().len() != b.inputs().len() { return Err(TypeError::ArgCount); @@ -180,9 +179,9 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { .chain(iter::once(((a.output(), b.output()), true))) .map(|((a, b), is_output)| { if is_output { - relation.relate(&a, &b) + relation.relate(a, b) } else { - relation.relate_with_variance(ty::Contravariant, &a, &b) + relation.relate_with_variance(ty::Contravariant, a, b) } }); Ok(ty::FnSig { @@ -197,13 +196,13 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { impl<'tcx> Relate<'tcx> for ast::Unsafety { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: &ast::Unsafety, - b: &ast::Unsafety, + a: ast::Unsafety, + b: ast::Unsafety, ) -> RelateResult<'tcx, ast::Unsafety> { if a != b { - Err(TypeError::UnsafetyMismatch(expected_found(relation, a, b))) + Err(TypeError::UnsafetyMismatch(expected_found(relation, &a, &b))) } else { - Ok(*a) + Ok(a) } } } @@ -211,18 +210,18 @@ impl<'tcx> Relate<'tcx> for ast::Unsafety { impl<'tcx> Relate<'tcx> for abi::Abi { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: &abi::Abi, - b: &abi::Abi, + a: abi::Abi, + b: abi::Abi, ) -> RelateResult<'tcx, abi::Abi> { - if a == b { Ok(*a) } else { Err(TypeError::AbiMismatch(expected_found(relation, a, b))) } + if a == b { Ok(a) } else { Err(TypeError::AbiMismatch(expected_found(relation, &a, &b))) } } } impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: &ty::ProjectionTy<'tcx>, - b: &ty::ProjectionTy<'tcx>, + a: ty::ProjectionTy<'tcx>, + b: ty::ProjectionTy<'tcx>, ) -> RelateResult<'tcx, ty::ProjectionTy<'tcx>> { if a.item_def_id != b.item_def_id { Err(TypeError::ProjectionMismatched(expected_found( @@ -231,7 +230,7 @@ impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> { &b.item_def_id, ))) } else { - let substs = relation.relate(&a.substs, &b.substs)?; + let substs = relation.relate(a.substs, b.substs)?; Ok(ty::ProjectionTy { item_def_id: a.item_def_id, substs: &substs }) } } @@ -240,8 +239,8 @@ impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> { impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: &ty::ExistentialProjection<'tcx>, - b: &ty::ExistentialProjection<'tcx>, + a: ty::ExistentialProjection<'tcx>, + b: ty::ExistentialProjection<'tcx>, ) -> RelateResult<'tcx, ty::ExistentialProjection<'tcx>> { if a.item_def_id != b.item_def_id { Err(TypeError::ProjectionMismatched(expected_found( @@ -250,37 +249,18 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> { &b.item_def_id, ))) } else { - let ty = relation.relate_with_variance(ty::Invariant, &a.ty, &b.ty)?; - let substs = relation.relate_with_variance(ty::Invariant, &a.substs, &b.substs)?; + let ty = relation.relate_with_variance(ty::Invariant, a.ty, b.ty)?; + let substs = relation.relate_with_variance(ty::Invariant, a.substs, b.substs)?; Ok(ty::ExistentialProjection { item_def_id: a.item_def_id, substs, ty }) } } } -impl<'tcx> Relate<'tcx> for Vec<ty::PolyExistentialProjection<'tcx>> { - fn relate<R: TypeRelation<'tcx>>( - relation: &mut R, - a: &Vec<ty::PolyExistentialProjection<'tcx>>, - b: &Vec<ty::PolyExistentialProjection<'tcx>>, - ) -> RelateResult<'tcx, Vec<ty::PolyExistentialProjection<'tcx>>> { - // To be compatible, `a` and `b` must be for precisely the - // same set of traits and item names. We always require that - // projection bounds lists are sorted by trait-def-id and item-name, - // so we can just iterate through the lists pairwise, so long as they are the - // same length. - if a.len() != b.len() { - Err(TypeError::ProjectionBoundsLength(expected_found(relation, &a.len(), &b.len()))) - } else { - a.iter().zip(b).map(|(a, b)| relation.relate(a, b)).collect() - } - } -} - impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: &ty::TraitRef<'tcx>, - b: &ty::TraitRef<'tcx>, + a: ty::TraitRef<'tcx>, + b: ty::TraitRef<'tcx>, ) -> RelateResult<'tcx, ty::TraitRef<'tcx>> { // Different traits cannot be related. if a.def_id != b.def_id { @@ -295,8 +275,8 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> { impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: &ty::ExistentialTraitRef<'tcx>, - b: &ty::ExistentialTraitRef<'tcx>, + a: ty::ExistentialTraitRef<'tcx>, + b: ty::ExistentialTraitRef<'tcx>, ) -> RelateResult<'tcx, ty::ExistentialTraitRef<'tcx>> { // Different traits cannot be related. if a.def_id != b.def_id { @@ -308,18 +288,18 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> { } } -#[derive(Debug, Clone, TypeFoldable)] +#[derive(Copy, Debug, Clone, TypeFoldable)] struct GeneratorWitness<'tcx>(&'tcx ty::List<Ty<'tcx>>); impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: &GeneratorWitness<'tcx>, - b: &GeneratorWitness<'tcx>, + a: GeneratorWitness<'tcx>, + b: GeneratorWitness<'tcx>, ) -> RelateResult<'tcx, GeneratorWitness<'tcx>> { assert_eq!(a.0.len(), b.0.len()); let tcx = relation.tcx(); - let types = tcx.mk_type_list(a.0.iter().zip(b.0).map(|(a, b)| relation.relate(&a, &b)))?; + let types = tcx.mk_type_list(a.0.iter().zip(b.0).map(|(a, b)| relation.relate(a, b)))?; Ok(GeneratorWitness(types)) } } @@ -327,8 +307,8 @@ impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> { impl<'tcx> Relate<'tcx> for Ty<'tcx> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: &Ty<'tcx>, - b: &Ty<'tcx>, + a: Ty<'tcx>, + b: Ty<'tcx>, ) -> RelateResult<'tcx, Ty<'tcx>> { relation.tys(a, b) } @@ -379,7 +359,7 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>( (&ty::Foreign(a_id), &ty::Foreign(b_id)) if a_id == b_id => Ok(tcx.mk_foreign(a_id)), - (&ty::Dynamic(ref a_obj, ref a_region), &ty::Dynamic(ref b_obj, ref b_region)) => { + (&ty::Dynamic(a_obj, a_region), &ty::Dynamic(b_obj, b_region)) => { let region_bound = relation.with_cause(Cause::ExistentialRegionBound, |relation| { relation.relate_with_variance(ty::Contravariant, a_region, b_region) })?; @@ -392,7 +372,7 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>( // All Generator types with the same id represent // the (anonymous) type of the same generator expression. So // all of their regions should be equated. - let substs = relation.relate(&a_substs, &b_substs)?; + let substs = relation.relate(a_substs, b_substs)?; Ok(tcx.mk_generator(a_id, substs, movability)) } @@ -402,7 +382,7 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>( let a_types = a_types.map_bound(GeneratorWitness); let b_types = b_types.map_bound(GeneratorWitness); // Then remove the GeneratorWitness for the result - let types = relation.relate(&a_types, &b_types)?.map_bound(|witness| witness.0); + let types = relation.relate(a_types, b_types)?.map_bound(|witness| witness.0); Ok(tcx.mk_generator_witness(types)) } @@ -410,26 +390,26 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>( // All Closure types with the same id represent // the (anonymous) type of the same closure expression. So // all of their regions should be equated. - let substs = relation.relate(&a_substs, &b_substs)?; + let substs = relation.relate(a_substs, b_substs)?; Ok(tcx.mk_closure(a_id, &substs)) } - (&ty::RawPtr(ref a_mt), &ty::RawPtr(ref b_mt)) => { + (&ty::RawPtr(a_mt), &ty::RawPtr(b_mt)) => { let mt = relation.relate(a_mt, b_mt)?; Ok(tcx.mk_ptr(mt)) } (&ty::Ref(a_r, a_ty, a_mutbl), &ty::Ref(b_r, b_ty, b_mutbl)) => { - let r = relation.relate_with_variance(ty::Contravariant, &a_r, &b_r)?; + let r = relation.relate_with_variance(ty::Contravariant, a_r, b_r)?; let a_mt = ty::TypeAndMut { ty: a_ty, mutbl: a_mutbl }; let b_mt = ty::TypeAndMut { ty: b_ty, mutbl: b_mutbl }; - let mt = relation.relate(&a_mt, &b_mt)?; + let mt = relation.relate(a_mt, b_mt)?; Ok(tcx.mk_ref(r, mt)) } (&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) => { - let t = relation.relate(&a_t, &b_t)?; - match relation.relate(&sz_a, &sz_b) { + let t = relation.relate(a_t, b_t)?; + match relation.relate(sz_a, sz_b) { Ok(sz) => Ok(tcx.mk_ty(ty::Array(t, sz))), // FIXME(#72219) Implement improved diagnostics for mismatched array // length? @@ -450,16 +430,14 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>( } (&ty::Slice(a_t), &ty::Slice(b_t)) => { - let t = relation.relate(&a_t, &b_t)?; + let t = relation.relate(a_t, b_t)?; Ok(tcx.mk_slice(t)) } (&ty::Tuple(as_), &ty::Tuple(bs)) => { if as_.len() == bs.len() { Ok(tcx.mk_tup( - as_.iter() - .zip(bs) - .map(|(a, b)| relation.relate(&a.expect_ty(), &b.expect_ty())), + as_.iter().zip(bs).map(|(a, b)| relation.relate(a.expect_ty(), b.expect_ty())), )?) } else if !(as_.is_empty() || bs.is_empty()) { Err(TypeError::TupleSize(expected_found(relation, &as_.len(), &bs.len()))) @@ -476,12 +454,12 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>( } (&ty::FnPtr(a_fty), &ty::FnPtr(b_fty)) => { - let fty = relation.relate(&a_fty, &b_fty)?; + let fty = relation.relate(a_fty, b_fty)?; Ok(tcx.mk_fn_ptr(fty)) } // these two are already handled downstream in case of lazy normalization - (ty::Projection(a_data), ty::Projection(b_data)) => { + (&ty::Projection(a_data), &ty::Projection(b_data)) => { let projection_ty = relation.relate(a_data, b_data)?; Ok(tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs)) } @@ -603,8 +581,8 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>( ty::ConstKind::Unevaluated(b_def_id, b_substs, b_promoted), ) if a_def_id == b_def_id && a_promoted == b_promoted => { let substs = - relation.relate_with_variance(ty::Variance::Invariant, &a_substs, &b_substs)?; - Ok(ty::ConstKind::Unevaluated(a_def_id, &substs, a_promoted)) + relation.relate_with_variance(ty::Variance::Invariant, a_substs, b_substs)?; + Ok(ty::ConstKind::Unevaluated(a_def_id, substs, a_promoted)) } _ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))), }; @@ -614,8 +592,8 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>( impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: &Self, - b: &Self, + a: Self, + b: Self, ) -> RelateResult<'tcx, Self> { let tcx = relation.tcx(); @@ -629,16 +607,16 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> { b_v.sort_by(|a, b| a.stable_cmp(tcx, b)); b_v.dedup(); if a_v.len() != b_v.len() { - return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))); + return Err(TypeError::ExistentialMismatch(expected_found(relation, &a, &b))); } let v = a_v.into_iter().zip(b_v.into_iter()).map(|(ep_a, ep_b)| { use crate::ty::ExistentialPredicate::*; match (ep_a, ep_b) { - (Trait(ref a), Trait(ref b)) => Ok(Trait(relation.relate(a, b)?)), - (Projection(ref a), Projection(ref b)) => Ok(Projection(relation.relate(a, b)?)), - (AutoTrait(ref a), AutoTrait(ref b)) if a == b => Ok(AutoTrait(*a)), - _ => Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))), + (Trait(a), Trait(b)) => Ok(Trait(relation.relate(a, b)?)), + (Projection(a), Projection(b)) => Ok(Projection(relation.relate(a, b)?)), + (AutoTrait(a), AutoTrait(b)) if a == b => Ok(AutoTrait(a)), + _ => Err(TypeError::ExistentialMismatch(expected_found(relation, &a, &b))), } }); Ok(tcx.mk_existential_predicates(v)?) @@ -648,8 +626,8 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> { impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: &ty::ClosureSubsts<'tcx>, - b: &ty::ClosureSubsts<'tcx>, + a: ty::ClosureSubsts<'tcx>, + b: ty::ClosureSubsts<'tcx>, ) -> RelateResult<'tcx, ty::ClosureSubsts<'tcx>> { let substs = relate_substs(relation, None, a.substs, b.substs)?; Ok(ty::ClosureSubsts { substs }) @@ -659,8 +637,8 @@ impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> { impl<'tcx> Relate<'tcx> for ty::GeneratorSubsts<'tcx> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: &ty::GeneratorSubsts<'tcx>, - b: &ty::GeneratorSubsts<'tcx>, + a: ty::GeneratorSubsts<'tcx>, + b: ty::GeneratorSubsts<'tcx>, ) -> RelateResult<'tcx, ty::GeneratorSubsts<'tcx>> { let substs = relate_substs(relation, None, a.substs, b.substs)?; Ok(ty::GeneratorSubsts { substs }) @@ -670,8 +648,8 @@ impl<'tcx> Relate<'tcx> for ty::GeneratorSubsts<'tcx> { impl<'tcx> Relate<'tcx> for SubstsRef<'tcx> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: &SubstsRef<'tcx>, - b: &SubstsRef<'tcx>, + a: SubstsRef<'tcx>, + b: SubstsRef<'tcx>, ) -> RelateResult<'tcx, SubstsRef<'tcx>> { relate_substs(relation, None, a, b) } @@ -680,72 +658,48 @@ impl<'tcx> Relate<'tcx> for SubstsRef<'tcx> { impl<'tcx> Relate<'tcx> for ty::Region<'tcx> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: &ty::Region<'tcx>, - b: &ty::Region<'tcx>, + a: ty::Region<'tcx>, + b: ty::Region<'tcx>, ) -> RelateResult<'tcx, ty::Region<'tcx>> { - relation.regions(*a, *b) + relation.regions(a, b) } } impl<'tcx> Relate<'tcx> for &'tcx ty::Const<'tcx> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: &&'tcx ty::Const<'tcx>, - b: &&'tcx ty::Const<'tcx>, + a: &'tcx ty::Const<'tcx>, + b: &'tcx ty::Const<'tcx>, ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { - relation.consts(*a, *b) + relation.consts(a, b) } } impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::Binder<T> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: &ty::Binder<T>, - b: &ty::Binder<T>, + a: ty::Binder<T>, + b: ty::Binder<T>, ) -> RelateResult<'tcx, ty::Binder<T>> { relation.binders(a, b) } } -impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for Rc<T> { - fn relate<R: TypeRelation<'tcx>>( - relation: &mut R, - a: &Rc<T>, - b: &Rc<T>, - ) -> RelateResult<'tcx, Rc<T>> { - let a: &T = a; - let b: &T = b; - Ok(Rc::new(relation.relate(a, b)?)) - } -} - -impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for Box<T> { - fn relate<R: TypeRelation<'tcx>>( - relation: &mut R, - a: &Box<T>, - b: &Box<T>, - ) -> RelateResult<'tcx, Box<T>> { - let a: &T = a; - let b: &T = b; - Ok(Box::new(relation.relate(a, b)?)) - } -} - impl<'tcx> Relate<'tcx> for GenericArg<'tcx> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: &GenericArg<'tcx>, - b: &GenericArg<'tcx>, + a: GenericArg<'tcx>, + b: GenericArg<'tcx>, ) -> RelateResult<'tcx, GenericArg<'tcx>> { match (a.unpack(), b.unpack()) { (GenericArgKind::Lifetime(a_lt), GenericArgKind::Lifetime(b_lt)) => { - Ok(relation.relate(&a_lt, &b_lt)?.into()) + Ok(relation.relate(a_lt, b_lt)?.into()) } (GenericArgKind::Type(a_ty), GenericArgKind::Type(b_ty)) => { - Ok(relation.relate(&a_ty, &b_ty)?.into()) + Ok(relation.relate(a_ty, b_ty)?.into()) } (GenericArgKind::Const(a_ct), GenericArgKind::Const(b_ct)) => { - Ok(relation.relate(&a_ct, &b_ct)?.into()) + Ok(relation.relate(a_ct, b_ct)?.into()) } (GenericArgKind::Lifetime(unpacked), x) => { bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x) @@ -763,22 +717,22 @@ impl<'tcx> Relate<'tcx> for GenericArg<'tcx> { impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: &ty::TraitPredicate<'tcx>, - b: &ty::TraitPredicate<'tcx>, + a: ty::TraitPredicate<'tcx>, + b: ty::TraitPredicate<'tcx>, ) -> RelateResult<'tcx, ty::TraitPredicate<'tcx>> { - Ok(ty::TraitPredicate { trait_ref: relation.relate(&a.trait_ref, &b.trait_ref)? }) + Ok(ty::TraitPredicate { trait_ref: relation.relate(a.trait_ref, b.trait_ref)? }) } } impl<'tcx> Relate<'tcx> for ty::ProjectionPredicate<'tcx> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: &ty::ProjectionPredicate<'tcx>, - b: &ty::ProjectionPredicate<'tcx>, + a: ty::ProjectionPredicate<'tcx>, + b: ty::ProjectionPredicate<'tcx>, ) -> RelateResult<'tcx, ty::ProjectionPredicate<'tcx>> { Ok(ty::ProjectionPredicate { - projection_ty: relation.relate(&a.projection_ty, &b.projection_ty)?, - ty: relation.relate(&a.ty, &b.ty)?, + projection_ty: relation.relate(a.projection_ty, b.projection_ty)?, + ty: relation.relate(a.ty, b.ty)?, }) } } diff --git a/src/librustc_middle/ty/structural_impls.rs b/src/librustc_middle/ty/structural_impls.rs index f736037b5c1..1d3607fe32f 100644 --- a/src/librustc_middle/ty/structural_impls.rs +++ b/src/librustc_middle/ty/structural_impls.rs @@ -514,7 +514,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::PredicateKind<'a> { impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::Binder<T> { type Lifted = ty::Binder<T::Lifted>; fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { - tcx.lift(self.skip_binder()).map(ty::Binder::bind) + tcx.lift(self.as_ref().skip_binder()).map(ty::Binder::bind) } } @@ -655,7 +655,6 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { VariadicMismatch(x) => VariadicMismatch(x), CyclicTy(t) => return tcx.lift(&t).map(|t| CyclicTy(t)), ProjectionMismatched(x) => ProjectionMismatched(x), - ProjectionBoundsLength(x) => ProjectionBoundsLength(x), Sorts(ref x) => return tcx.lift(x).map(Sorts), ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch), ConstMismatch(ref x) => return tcx.lift(x).map(ConstMismatch), @@ -798,7 +797,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> { } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool { - self.skip_binder().visit_with(visitor) + self.as_ref().skip_binder().visit_with(visitor) } fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool { diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs index 8f86d2ef522..c7683cefd82 100644 --- a/src/librustc_middle/ty/sty.rs +++ b/src/librustc_middle/ty/sty.rs @@ -615,7 +615,7 @@ impl<'tcx> ExistentialPredicate<'tcx> { impl<'tcx> Binder<ExistentialPredicate<'tcx>> { pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Predicate<'tcx> { use crate::ty::ToPredicate; - match *self.skip_binder() { + match self.skip_binder() { ExistentialPredicate::Trait(tr) => { Binder(tr).with_self_ty(tcx, self_ty).without_const().to_predicate(tcx) } @@ -776,7 +776,7 @@ impl<'tcx> PolyTraitRef<'tcx> { pub fn to_poly_trait_predicate(&self) -> ty::PolyTraitPredicate<'tcx> { // Note that we preserve binding levels - Binder(ty::TraitPredicate { trait_ref: *self.skip_binder() }) + Binder(ty::TraitPredicate { trait_ref: self.skip_binder() }) } } @@ -880,8 +880,8 @@ impl<T> Binder<T> { /// - extracting the `DefId` from a PolyTraitRef; /// - comparing the self type of a PolyTraitRef to see if it is equal to /// a type parameter `X`, since the type `X` does not reference any regions - pub fn skip_binder(&self) -> &T { - &self.0 + pub fn skip_binder(self) -> T { + self.0 } pub fn as_ref(&self) -> Binder<&T> { @@ -916,11 +916,7 @@ impl<T> Binder<T> { where T: TypeFoldable<'tcx>, { - if self.skip_binder().has_escaping_bound_vars() { - None - } else { - Some(self.skip_binder().clone()) - } + if self.0.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) } } /// Given two things that have the same binder level, @@ -997,7 +993,7 @@ impl<'tcx> ProjectionTy<'tcx> { } } -#[derive(Clone, Debug, TypeFoldable)] +#[derive(Copy, Clone, Debug, TypeFoldable)] pub struct GenSig<'tcx> { pub resume_ty: Ty<'tcx>, pub yield_ty: Ty<'tcx>, diff --git a/src/librustc_middle/ty/walk.rs b/src/librustc_middle/ty/walk.rs index 633d4fda8a4..82c649b8f54 100644 --- a/src/librustc_middle/ty/walk.rs +++ b/src/librustc_middle/ty/walk.rs @@ -133,7 +133,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) ty::Dynamic(obj, lt) => { stack.push(lt.into()); stack.extend(obj.iter().rev().flat_map(|predicate| { - let (substs, opt_ty) = match *predicate.skip_binder() { + let (substs, opt_ty) = match predicate.skip_binder() { ty::ExistentialPredicate::Trait(tr) => (tr.substs, None), ty::ExistentialPredicate::Projection(p) => (p.substs, Some(p.ty)), ty::ExistentialPredicate::AutoTrait(_) => diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs index e85f69554d0..17846055f6c 100644 --- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs @@ -1923,7 +1923,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // We use a mix of the HIR and the Ty types to get information // as the HIR doesn't have full types for closure arguments. - let return_ty = *sig.output().skip_binder(); + let return_ty = sig.output().skip_binder(); let mut return_span = fn_decl.output.span(); if let hir::FnRetTy::Return(ty) = &fn_decl.output { if let hir::TyKind::Rptr(lifetime, _) = ty.kind { @@ -1965,7 +1965,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let argument_ty = sig.inputs().skip_binder().first()?; let return_span = fn_decl.output.span(); - let return_ty = *sig.output().skip_binder(); + let return_ty = sig.output().skip_binder(); // We expect the first argument to be a reference. match argument_ty.kind { diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs index 99b9788c20b..26c2aea41d5 100644 --- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs @@ -122,7 +122,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if self.regioncx.universal_regions().is_universal_region(r) { Some(r) } else { - let upper_bound = self.regioncx.universal_upper_bound(r); + // We just want something nameable, even if it's not + // actually an upper bound. + let upper_bound = self.regioncx.approx_universal_upper_bound(r); if self.regioncx.upper_bound_in_region_scc(r, upper_bound) { self.to_error_region_vid(upper_bound) diff --git a/src/librustc_mir/borrow_check/region_infer/mod.rs b/src/librustc_mir/borrow_check/region_infer/mod.rs index 3e459bd52f7..081125cb625 100644 --- a/src/librustc_mir/borrow_check/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/region_infer/mod.rs @@ -1114,6 +1114,40 @@ impl<'tcx> RegionInferenceContext<'tcx> { lub } + /// Like `universal_upper_bound`, but returns an approximation more suitable + /// for diagnostics. If `r` contains multiple disjoint universal regions + /// (e.g. 'a and 'b in `fn foo<'a, 'b> { ... }`, we pick the lower-numbered region. + /// This corresponds to picking named regions over unnamed regions + /// (e.g. picking early-bound regions over a closure late-bound region). + /// + /// This means that the returned value may not be a true upper bound, since + /// only 'static is known to outlive disjoint universal regions. + /// Therefore, this method should only be used in diagnostic code, + /// where displaying *some* named universal region is better than + /// falling back to 'static. + pub(in crate::borrow_check) fn approx_universal_upper_bound(&self, r: RegionVid) -> RegionVid { + debug!("approx_universal_upper_bound(r={:?}={})", r, self.region_value_str(r)); + + // Find the smallest universal region that contains all other + // universal regions within `region`. + let mut lub = self.universal_regions.fr_fn_body; + let r_scc = self.constraint_sccs.scc(r); + let static_r = self.universal_regions.fr_static; + for ur in self.scc_values.universal_regions_outlived_by(r_scc) { + let new_lub = self.universal_region_relations.postdom_upper_bound(lub, ur); + debug!("approx_universal_upper_bound: ur={:?} lub={:?} new_lub={:?}", ur, lub, new_lub); + if ur != static_r && lub != static_r && new_lub == static_r { + lub = std::cmp::min(ur, lub); + } else { + lub = new_lub; + } + } + + debug!("approx_universal_upper_bound: r={:?} lub={:?}", r, lub); + + lub + } + /// Tests if `test` is true when applied to `lower_bound` at /// `point`. fn eval_verify_bound( diff --git a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs index 7e352bfba77..325dca8c8ca 100644 --- a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs +++ b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs @@ -141,7 +141,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { { tcx.fold_regions(&ty, &mut false, |region, _| match *region { ty::ReVar(vid) => { - let upper_bound = self.universal_upper_bound(vid); + // Find something that we can name + let upper_bound = self.approx_universal_upper_bound(vid); self.definitions[upper_bound].external_name.unwrap_or(region) } _ => region, diff --git a/src/librustc_mir/borrow_check/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/type_check/relate_tys.rs index 285d9ed6469..91b1a1fbd97 100644 --- a/src/librustc_mir/borrow_check/type_check/relate_tys.rs +++ b/src/librustc_mir/borrow_check/type_check/relate_tys.rs @@ -31,7 +31,7 @@ pub(super) fn relate_types<'tcx>( NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category), v, ) - .relate(&a, &b)?; + .relate(a, b)?; Ok(()) } diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 88ba28dab82..85186264022 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -409,8 +409,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ); self.copy_op(self.operand_index(args[0], index)?, dest)?; } + sym::likely | sym::unlikely => { + // These just return their argument + self.copy_op(args[0], dest)?; + } // FIXME(#73156): Handle source code coverage in const eval - sym::count_code_region => (), + sym::count_code_region + | sym::coverage_counter_add + | sym::coverage_counter_subtract + | sym::coverage_unreachable => (), _ => return Ok(false), } diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index ca1f0aecd04..f00fc96e591 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -531,9 +531,12 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { if is_lang_panic_fn(self.tcx, def_id) { self.check_op(ops::Panic); } else if let Some(feature) = is_unstable_const_fn(self.tcx, def_id) { - // Exempt unstable const fns inside of macros with + // Exempt unstable const fns inside of macros or functions with // `#[allow_internal_unstable]`. - if !self.span.allows_unstable(feature) { + use crate::transform::qualify_min_const_fn::lib_feature_allowed; + if !self.span.allows_unstable(feature) + && !lib_feature_allowed(self.tcx, self.def_id, feature) + { self.check_op(ops::FnCallUnstable(def_id, feature)); } } else { diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 068d055fa78..c03be2a8fcd 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -39,7 +39,14 @@ struct CallSite<'tcx> { impl<'tcx> MirPass<'tcx> for Inline { fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 { - Inliner { tcx, source }.run_pass(body); + if tcx.sess.opts.debugging_opts.instrument_coverage { + // The current implementation of source code coverage injects code region counters + // into the MIR, and assumes a 1-to-1 correspondence between MIR and source-code- + // based function. + debug!("function inlining is disabled when compiling with `instrument_coverage`"); + } else { + Inliner { tcx, source }.run_pass(body); + } } } } diff --git a/src/librustc_mir/transform/instrument_coverage.rs b/src/librustc_mir/transform/instrument_coverage.rs index 06b648ab5a9..25e154f2e95 100644 --- a/src/librustc_mir/transform/instrument_coverage.rs +++ b/src/librustc_mir/transform/instrument_coverage.rs @@ -5,65 +5,71 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::lang_items; use rustc_middle::hir; use rustc_middle::ich::StableHashingContext; -use rustc_middle::mir::interpret::{ConstValue, Scalar}; +use rustc_middle::mir::coverage::*; +use rustc_middle::mir::interpret::Scalar; +use rustc_middle::mir::CoverageInfo; use rustc_middle::mir::{ - self, traversal, BasicBlock, BasicBlockData, CoverageData, Operand, Place, SourceInfo, - StatementKind, Terminator, TerminatorKind, START_BLOCK, + self, traversal, BasicBlock, BasicBlockData, Operand, Place, SourceInfo, StatementKind, + Terminator, TerminatorKind, START_BLOCK, }; use rustc_middle::ty; use rustc_middle::ty::query::Providers; +use rustc_middle::ty::FnDef; use rustc_middle::ty::TyCtxt; -use rustc_middle::ty::{ConstKind, FnDef}; use rustc_span::def_id::DefId; -use rustc_span::Span; +use rustc_span::{Pos, Span}; /// Inserts call to count_code_region() as a placeholder to be replaced during code generation with /// the intrinsic llvm.instrprof.increment. pub struct InstrumentCoverage; -/// The `query` provider for `CoverageData`, requested by `codegen_intrinsic_call()` when +/// The `query` provider for `CoverageInfo`, requested by `codegen_intrinsic_call()` when /// constructing the arguments for `llvm.instrprof.increment`. pub(crate) fn provide(providers: &mut Providers<'_>) { - providers.coverage_data = |tcx, def_id| { - let mir_body = tcx.optimized_mir(def_id); - // FIXME(richkadel): The current implementation assumes the MIR for the given DefId - // represents a single function. Validate and/or correct if inlining and/or monomorphization - // invalidates these assumptions. - let count_code_region_fn = - tcx.require_lang_item(lang_items::CountCodeRegionFnLangItem, None); - let mut num_counters: u32 = 0; - // The `num_counters` argument to `llvm.instrprof.increment` is the number of injected - // counters, with each counter having an index from `0..num_counters-1`. MIR optimization - // may split and duplicate some BasicBlock sequences. Simply counting the calls may not - // not work; but computing the num_counters by adding `1` to the highest index (for a given - // instrumented function) is valid. - for (_, data) in traversal::preorder(mir_body) { - if let Some(terminator) = &data.terminator { - if let TerminatorKind::Call { func: Operand::Constant(func), args, .. } = - &terminator.kind - { - if let FnDef(called_fn_def_id, _) = func.literal.ty.kind { - if called_fn_def_id == count_code_region_fn { - if let Operand::Constant(constant) = - args.get(0).expect("count_code_region has at least one arg") - { - if let ConstKind::Value(ConstValue::Scalar(value)) = - constant.literal.val - { - let index = value - .to_u32() - .expect("count_code_region index at arg0 is u32"); - num_counters = std::cmp::max(num_counters, index + 1); - } - } - } - } + providers.coverageinfo = |tcx, def_id| coverageinfo_from_mir(tcx, def_id); +} + +fn coverageinfo_from_mir<'tcx>(tcx: TyCtxt<'tcx>, mir_def_id: DefId) -> CoverageInfo { + let mir_body = tcx.optimized_mir(mir_def_id); + // FIXME(richkadel): The current implementation assumes the MIR for the given DefId + // represents a single function. Validate and/or correct if inlining (which should be disabled + // if -Zinstrument-coverage is enabled) and/or monomorphization invalidates these assumptions. + let count_code_region_fn = tcx.require_lang_item(lang_items::CountCodeRegionFnLangItem, None); + + // The `num_counters` argument to `llvm.instrprof.increment` is the number of injected + // counters, with each counter having an index from `0..num_counters-1`. MIR optimization + // may split and duplicate some BasicBlock sequences. Simply counting the calls may not + // not work; but computing the num_counters by adding `1` to the highest index (for a given + // instrumented function) is valid. + let mut num_counters: u32 = 0; + for terminator in traversal::preorder(mir_body) + .map(|(_, data)| (data, count_code_region_fn)) + .filter_map(terminators_that_call_given_fn) + { + if let TerminatorKind::Call { args, .. } = &terminator.kind { + let index_arg = args.get(count_code_region_args::COUNTER_INDEX).expect("arg found"); + let index = + mir::Operand::scalar_from_const(index_arg).to_u32().expect("index arg is u32"); + num_counters = std::cmp::max(num_counters, index + 1); + } + } + let hash = if num_counters > 0 { hash_mir_source(tcx, mir_def_id) } else { 0 }; + CoverageInfo { num_counters, hash } +} + +fn terminators_that_call_given_fn( + (data, fn_def_id): (&'tcx BasicBlockData<'tcx>, DefId), +) -> Option<&'tcx Terminator<'tcx>> { + if let Some(terminator) = &data.terminator { + if let TerminatorKind::Call { func: Operand::Constant(func), .. } = &terminator.kind { + if let FnDef(called_fn_def_id, _) = func.literal.ty.kind { + if called_fn_def_id == fn_def_id { + return Some(&terminator); } } } - let hash = if num_counters > 0 { hash_mir_source(tcx, def_id) } else { 0 }; - CoverageData { num_counters, hash } - }; + } + None } struct Instrumentor<'tcx> { @@ -102,17 +108,16 @@ impl<'tcx> Instrumentor<'tcx> { fn inject_counters(&mut self, mir_body: &mut mir::Body<'tcx>) { // FIXME(richkadel): As a first step, counters are only injected at the top of each // function. The complete solution will inject counters at each conditional code branch. - let top_of_function = START_BLOCK; - let entire_function = mir_body.span; - - self.inject_counter(mir_body, top_of_function, entire_function); + let code_region = mir_body.span; + let next_block = START_BLOCK; + self.inject_counter(mir_body, code_region, next_block); } fn inject_counter( &mut self, mir_body: &mut mir::Body<'tcx>, - next_block: BasicBlock, code_region: Span, + next_block: BasicBlock, ) { let injection_point = code_region.shrink_to_lo(); @@ -121,12 +126,20 @@ impl<'tcx> Instrumentor<'tcx> { self.tcx.require_lang_item(lang_items::CountCodeRegionFnLangItem, None), injection_point, ); - let counter_index = Operand::const_from_scalar( - self.tcx, - self.tcx.types.u32, - Scalar::from_u32(self.next_counter()), - injection_point, - ); + + let index = self.next_counter(); + + let mut args = Vec::new(); + + use count_code_region_args::*; + debug_assert_eq!(COUNTER_INDEX, args.len()); + args.push(self.const_u32(index, injection_point)); + + debug_assert_eq!(START_BYTE_POS, args.len()); + args.push(self.const_u32(code_region.lo().to_u32(), injection_point)); + + debug_assert_eq!(END_BYTE_POS, args.len()); + args.push(self.const_u32(code_region.hi().to_u32(), injection_point)); let mut patch = MirPatch::new(mir_body); @@ -136,7 +149,7 @@ impl<'tcx> Instrumentor<'tcx> { new_block, TerminatorKind::Call { func: count_code_region_fn, - args: vec![counter_index], + args, // new_block will swapped with the next_block, after applying patch destination: Some((Place::from(temp), new_block)), cleanup: None, @@ -154,6 +167,10 @@ impl<'tcx> Instrumentor<'tcx> { // `next_block`), just swap the indexes, leaving the rest of the graph unchanged. mir_body.basic_blocks_mut().swap(next_block, new_block); } + + fn const_u32(&self, value: u32, span: Span) -> Operand<'tcx> { + Operand::const_from_scalar(self.tcx, self.tcx.types.u32, Scalar::from_u32(value), span) + } } fn function_handle<'tcx>(tcx: TyCtxt<'tcx>, fn_def_id: DefId, span: Span) -> Operand<'tcx> { diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index 5a3663384fb..2f5257080cd 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -328,6 +328,26 @@ fn feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bo .map_or(false, |mut features| features.any(|name| name == feature_gate)) } +/// Returns `true` if the given library feature gate is allowed within the function with the given `DefId`. +pub fn lib_feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bool { + // All features require that the corresponding gate be enabled, + // even if the function has `#[allow_internal_unstable(the_gate)]`. + if !tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == feature_gate) { + return false; + } + + // If this crate is not using stability attributes, or this function is not claiming to be a + // stable `const fn`, that is all that is required. + if !tcx.features().staged_api || tcx.has_attr(def_id, sym::rustc_const_unstable) { + return true; + } + + // However, we cannot allow stable `const fn`s to use unstable features without an explicit + // opt-in via `allow_internal_unstable`. + attr::allow_internal_unstable(&tcx.get_attrs(def_id), &tcx.sess.diagnostic()) + .map_or(false, |mut features| features.any(|name| name == feature_gate)) +} + fn check_terminator( tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, @@ -367,8 +387,17 @@ fn check_terminator( fn_span: _, } => { let fn_ty = func.ty(body, tcx); - if let ty::FnDef(def_id, _) = fn_ty.kind { - if !crate::const_eval::is_min_const_fn(tcx, def_id) { + if let ty::FnDef(fn_def_id, _) = fn_ty.kind { + // Allow unstable const if we opt in by using #[allow_internal_unstable] + // on function or macro declaration. + if !crate::const_eval::is_min_const_fn(tcx, fn_def_id) + && !crate::const_eval::is_unstable_const_fn(tcx, fn_def_id) + .map(|feature| { + span.allows_unstable(feature) + || lib_feature_allowed(tcx, def_id, feature) + }) + .unwrap_or(false) + { return Err(( span, format!( @@ -380,10 +409,10 @@ fn check_terminator( )); } - check_operand(tcx, func, span, def_id, body)?; + check_operand(tcx, func, span, fn_def_id, body)?; for arg in args { - check_operand(tcx, arg, span, def_id, body)?; + check_operand(tcx, arg, span, fn_def_id, body)?; } Ok(()) } else { diff --git a/src/librustc_mir/transform/validate.rs b/src/librustc_mir/transform/validate.rs index d3f486c815e..e794a6949d2 100644 --- a/src/librustc_mir/transform/validate.rs +++ b/src/librustc_mir/transform/validate.rs @@ -74,8 +74,8 @@ pub fn equal_up_to_regions( fn relate_with_variance<T: Relate<'tcx>>( &mut self, _: ty::Variance, - a: &T, - b: &T, + a: T, + b: T, ) -> RelateResult<'tcx, T> { // Ignore variance, require types to be exactly the same. self.relate(a, b) @@ -108,8 +108,8 @@ pub fn equal_up_to_regions( fn binders<T>( &mut self, - a: &ty::Binder<T>, - b: &ty::Binder<T>, + a: ty::Binder<T>, + b: ty::Binder<T>, ) -> RelateResult<'tcx, ty::Binder<T>> where T: Relate<'tcx>, @@ -121,7 +121,7 @@ pub fn equal_up_to_regions( // Instantiate and run relation. let mut relator: LifetimeIgnoreRelation<'tcx> = LifetimeIgnoreRelation { tcx: tcx, param_env }; - relator.relate(&src, &dest).is_ok() + relator.relate(src, dest).is_ok() } struct TypeChecker<'a, 'tcx> { diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index 6ac5d41ec61..18b92bf29bf 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -4,8 +4,8 @@ //! This file includes the logic for exhaustiveness and usefulness checking for //! pattern-matching. Specifically, given a list of patterns for a type, we can //! tell whether: -//! (a) the patterns cover every possible constructor for the type [exhaustiveness] -//! (b) each pattern is necessary [usefulness] +//! (a) the patterns cover every possible constructor for the type (exhaustiveness) +//! (b) each pattern is necessary (usefulness) //! //! The algorithm implemented here is a modified version of the one described in: //! http://moscova.inria.fr/~maranget/papers/warn/index.html @@ -101,53 +101,54 @@ //! To match the paper, the top of the stack is at the beginning / on the left. //! //! There are two important operations on pattern-stacks necessary to understand the algorithm: -//! 1. We can pop a given constructor off the top of a stack. This operation is called -//! `specialize`, and is denoted `S(c, p)` where `c` is a constructor (like `Some` or -//! `None`) and `p` a pattern-stack. -//! If the pattern on top of the stack can cover `c`, this removes the constructor and -//! pushes its arguments onto the stack. It also expands OR-patterns into distinct patterns. -//! Otherwise the pattern-stack is discarded. -//! This essentially filters those pattern-stacks whose top covers the constructor `c` and -//! discards the others. //! -//! For example, the first pattern above initially gives a stack `[(Some(true), _)]`. If we -//! pop the tuple constructor, we are left with `[Some(true), _]`, and if we then pop the -//! `Some` constructor we get `[true, _]`. If we had popped `None` instead, we would get -//! nothing back. +//! 1. We can pop a given constructor off the top of a stack. This operation is called +//! `specialize`, and is denoted `S(c, p)` where `c` is a constructor (like `Some` or +//! `None`) and `p` a pattern-stack. +//! If the pattern on top of the stack can cover `c`, this removes the constructor and +//! pushes its arguments onto the stack. It also expands OR-patterns into distinct patterns. +//! Otherwise the pattern-stack is discarded. +//! This essentially filters those pattern-stacks whose top covers the constructor `c` and +//! discards the others. //! -//! This returns zero or more new pattern-stacks, as follows. We look at the pattern `p_1` -//! on top of the stack, and we have four cases: -//! 1.1. `p_1 = c(r_1, .., r_a)`, i.e. the top of the stack has constructor `c`. We -//! push onto the stack the arguments of this constructor, and return the result: -//! r_1, .., r_a, p_2, .., p_n -//! 1.2. `p_1 = c'(r_1, .., r_a')` where `c ≠ c'`. We discard the current stack and -//! return nothing. -//! 1.3. `p_1 = _`. We push onto the stack as many wildcards as the constructor `c` has -//! arguments (its arity), and return the resulting stack: -//! _, .., _, p_2, .., p_n -//! 1.4. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting -//! stack: -//! S(c, (r_1, p_2, .., p_n)) -//! S(c, (r_2, p_2, .., p_n)) +//! For example, the first pattern above initially gives a stack `[(Some(true), _)]`. If we +//! pop the tuple constructor, we are left with `[Some(true), _]`, and if we then pop the +//! `Some` constructor we get `[true, _]`. If we had popped `None` instead, we would get +//! nothing back. //! -//! 2. We can pop a wildcard off the top of the stack. This is called `D(p)`, where `p` is -//! a pattern-stack. -//! This is used when we know there are missing constructor cases, but there might be -//! existing wildcard patterns, so to check the usefulness of the matrix, we have to check -//! all its *other* components. +//! This returns zero or more new pattern-stacks, as follows. We look at the pattern `p_1` +//! on top of the stack, and we have four cases: +//! 1.1. `p_1 = c(r_1, .., r_a)`, i.e. the top of the stack has constructor `c`. We +//! push onto the stack the arguments of this constructor, and return the result: +//! r_1, .., r_a, p_2, .., p_n +//! 1.2. `p_1 = c'(r_1, .., r_a')` where `c ≠ c'`. We discard the current stack and +//! return nothing. +//! 1.3. `p_1 = _`. We push onto the stack as many wildcards as the constructor `c` has +//! arguments (its arity), and return the resulting stack: +//! _, .., _, p_2, .., p_n +//! 1.4. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting +//! stack: +//! S(c, (r_1, p_2, .., p_n)) +//! S(c, (r_2, p_2, .., p_n)) //! -//! It is computed as follows. We look at the pattern `p_1` on top of the stack, -//! and we have three cases: -//! 1.1. `p_1 = c(r_1, .., r_a)`. We discard the current stack and return nothing. -//! 1.2. `p_1 = _`. We return the rest of the stack: -//! p_2, .., p_n -//! 1.3. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting -//! stack. -//! D((r_1, p_2, .., p_n)) -//! D((r_2, p_2, .., p_n)) +//! 2. We can pop a wildcard off the top of the stack. This is called `D(p)`, where `p` is +//! a pattern-stack. +//! This is used when we know there are missing constructor cases, but there might be +//! existing wildcard patterns, so to check the usefulness of the matrix, we have to check +//! all its *other* components. //! -//! Note that the OR-patterns are not always used directly in Rust, but are used to derive the -//! exhaustive integer matching rules, so they're written here for posterity. +//! It is computed as follows. We look at the pattern `p_1` on top of the stack, +//! and we have three cases: +//! 1.1. `p_1 = c(r_1, .., r_a)`. We discard the current stack and return nothing. +//! 1.2. `p_1 = _`. We return the rest of the stack: +//! p_2, .., p_n +//! 1.3. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting +//! stack. +//! D((r_1, p_2, .., p_n)) +//! D((r_2, p_2, .., p_n)) +//! +//! Note that the OR-patterns are not always used directly in Rust, but are used to derive the +//! exhaustive integer matching rules, so they're written here for posterity. //! //! Both those operations extend straightforwardly to a list or pattern-stacks, i.e. a matrix, by //! working row-by-row. Popping a constructor ends up keeping only the matrix rows that start with @@ -168,66 +169,66 @@ //! //! Inductive step. (`n > 0`, i.e., whether there's at least one column //! [which may then be expanded into further columns later]) -//! We're going to match on the top of the new pattern-stack, `p_1`. -//! - If `p_1 == c(r_1, .., r_a)`, i.e. we have a constructor pattern. -//! Then, the usefulness of `p_1` can be reduced to whether it is useful when -//! we ignore all the patterns in the first column of `P` that involve other constructors. -//! This is where `S(c, P)` comes in: -//! `U(P, p) := U(S(c, P), S(c, p))` -//! This special case is handled in `is_useful_specialized`. +//! We're going to match on the top of the new pattern-stack, `p_1`. +//! - If `p_1 == c(r_1, .., r_a)`, i.e. we have a constructor pattern. +//! Then, the usefulness of `p_1` can be reduced to whether it is useful when +//! we ignore all the patterns in the first column of `P` that involve other constructors. +//! This is where `S(c, P)` comes in: +//! `U(P, p) := U(S(c, P), S(c, p))` +//! This special case is handled in `is_useful_specialized`. //! -//! For example, if `P` is: -//! [ -//! [Some(true), _], -//! [None, 0], -//! ] -//! and `p` is [Some(false), 0], then we don't care about row 2 since we know `p` only -//! matches values that row 2 doesn't. For row 1 however, we need to dig into the -//! arguments of `Some` to know whether some new value is covered. So we compute -//! `U([[true, _]], [false, 0])`. +//! For example, if `P` is: +//! [ +//! [Some(true), _], +//! [None, 0], +//! ] +//! and `p` is [Some(false), 0], then we don't care about row 2 since we know `p` only +//! matches values that row 2 doesn't. For row 1 however, we need to dig into the +//! arguments of `Some` to know whether some new value is covered. So we compute +//! `U([[true, _]], [false, 0])`. //! -//! - If `p_1 == _`, then we look at the list of constructors that appear in the first -//! component of the rows of `P`: -//! + If there are some constructors that aren't present, then we might think that the -//! wildcard `_` is useful, since it covers those constructors that weren't covered -//! before. -//! That's almost correct, but only works if there were no wildcards in those first -//! components. So we need to check that `p` is useful with respect to the rows that -//! start with a wildcard, if there are any. This is where `D` comes in: -//! `U(P, p) := U(D(P), D(p))` +//! - If `p_1 == _`, then we look at the list of constructors that appear in the first +//! component of the rows of `P`: +//! + If there are some constructors that aren't present, then we might think that the +//! wildcard `_` is useful, since it covers those constructors that weren't covered +//! before. +//! That's almost correct, but only works if there were no wildcards in those first +//! components. So we need to check that `p` is useful with respect to the rows that +//! start with a wildcard, if there are any. This is where `D` comes in: +//! `U(P, p) := U(D(P), D(p))` //! -//! For example, if `P` is: -//! [ -//! [_, true, _], -//! [None, false, 1], -//! ] -//! and `p` is [_, false, _], the `Some` constructor doesn't appear in `P`. So if we -//! only had row 2, we'd know that `p` is useful. However row 1 starts with a -//! wildcard, so we need to check whether `U([[true, _]], [false, 1])`. +//! For example, if `P` is: +//! [ +//! [_, true, _], +//! [None, false, 1], +//! ] +//! and `p` is [_, false, _], the `Some` constructor doesn't appear in `P`. So if we +//! only had row 2, we'd know that `p` is useful. However row 1 starts with a +//! wildcard, so we need to check whether `U([[true, _]], [false, 1])`. //! -//! + Otherwise, all possible constructors (for the relevant type) are present. In this -//! case we must check whether the wildcard pattern covers any unmatched value. For -//! that, we can think of the `_` pattern as a big OR-pattern that covers all -//! possible constructors. For `Option`, that would mean `_ = None | Some(_)` for -//! example. The wildcard pattern is useful in this case if it is useful when -//! specialized to one of the possible constructors. So we compute: -//! `U(P, p) := ∃(k ϵ constructors) U(S(k, P), S(k, p))` +//! + Otherwise, all possible constructors (for the relevant type) are present. In this +//! case we must check whether the wildcard pattern covers any unmatched value. For +//! that, we can think of the `_` pattern as a big OR-pattern that covers all +//! possible constructors. For `Option`, that would mean `_ = None | Some(_)` for +//! example. The wildcard pattern is useful in this case if it is useful when +//! specialized to one of the possible constructors. So we compute: +//! `U(P, p) := ∃(k ϵ constructors) U(S(k, P), S(k, p))` //! -//! For example, if `P` is: -//! [ -//! [Some(true), _], -//! [None, false], -//! ] -//! and `p` is [_, false], both `None` and `Some` constructors appear in the first -//! components of `P`. We will therefore try popping both constructors in turn: we -//! compute U([[true, _]], [_, false]) for the `Some` constructor, and U([[false]], -//! [false]) for the `None` constructor. The first case returns true, so we know that -//! `p` is useful for `P`. Indeed, it matches `[Some(false), _]` that wasn't matched -//! before. +//! For example, if `P` is: +//! [ +//! [Some(true), _], +//! [None, false], +//! ] +//! and `p` is [_, false], both `None` and `Some` constructors appear in the first +//! components of `P`. We will therefore try popping both constructors in turn: we +//! compute `U([[true, _]], [_, false])` for the `Some` constructor, and `U([[false]], +//! [false])` for the `None` constructor. The first case returns true, so we know that +//! `p` is useful for `P`. Indeed, it matches `[Some(false), _]` that wasn't matched +//! before. //! -//! - If `p_1 == r_1 | r_2`, then the usefulness depends on each `r_i` separately: -//! `U(P, p) := U(P, (r_1, p_2, .., p_n)) -//! || U(P, (r_2, p_2, .., p_n))` +//! - If `p_1 == r_1 | r_2`, then the usefulness depends on each `r_i` separately: +//! `U(P, p) := U(P, (r_1, p_2, .., p_n)) +//! || U(P, (r_2, p_2, .., p_n))` //! //! Modifications to the algorithm //! ------------------------------ diff --git a/src/librustc_parse/parser/attr.rs b/src/librustc_parse/parser/attr.rs index b8cb146145b..803f14a2a22 100644 --- a/src/librustc_parse/parser/attr.rs +++ b/src/librustc_parse/parser/attr.rs @@ -155,7 +155,7 @@ impl<'a> Parser<'a> { /// The delimiters or `=` are still put into the resulting token stream. pub fn parse_attr_item(&mut self) -> PResult<'a, ast::AttrItem> { let item = match self.token.kind { - token::Interpolated(ref nt, _) => match **nt { + token::Interpolated(ref nt) => match **nt { Nonterminal::NtMeta(ref item) => Some(item.clone().into_inner()), _ => None, }, @@ -254,7 +254,7 @@ impl<'a> Parser<'a> { /// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ; pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> { let nt_meta = match self.token.kind { - token::Interpolated(ref nt, _) => match **nt { + token::Interpolated(ref nt) => match **nt { token::NtMeta(ref e) => Some(e.clone()), _ => None, }, diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index fc9ffc30924..16a118cb48c 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -376,7 +376,14 @@ impl<'a> Parser<'a> { /// let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>(); /// ^^ help: remove extra angle brackets /// ``` - pub(super) fn check_trailing_angle_brackets(&mut self, segment: &PathSegment, end: TokenKind) { + /// + /// If `true` is returned, then trailing brackets were recovered, tokens were consumed + /// up until one of the tokens in 'end' was encountered, and an error was emitted. + pub(super) fn check_trailing_angle_brackets( + &mut self, + segment: &PathSegment, + end: &[&TokenKind], + ) -> bool { // This function is intended to be invoked after parsing a path segment where there are two // cases: // @@ -409,7 +416,7 @@ impl<'a> Parser<'a> { parsed_angle_bracket_args, ); if !parsed_angle_bracket_args { - return; + return false; } // Keep the span at the start so we can highlight the sequence of `>` characters to be @@ -447,18 +454,18 @@ impl<'a> Parser<'a> { number_of_gt, number_of_shr, ); if number_of_gt < 1 && number_of_shr < 1 { - return; + return false; } // Finally, double check that we have our end token as otherwise this is the // second case. if self.look_ahead(position, |t| { trace!("check_trailing_angle_brackets: t={:?}", t); - *t == end + end.contains(&&t.kind) }) { // Eat from where we started until the end token so that parsing can continue // as if we didn't have those extra angle brackets. - self.eat_to_tokens(&[&end]); + self.eat_to_tokens(end); let span = lo.until(self.token.span); let total_num_of_gt = number_of_gt + number_of_shr * 2; @@ -473,7 +480,9 @@ impl<'a> Parser<'a> { Applicability::MachineApplicable, ) .emit(); + return true; } + false } /// Check to see if a pair of chained operators looks like an attempt at chained comparison, @@ -1415,7 +1424,7 @@ impl<'a> Parser<'a> { if self.token != token::Lt { err.span_suggestion( pat.span, - "if this was a parameter name, give it a type", + "if this is a parameter name, give it a type", format!("{}: TypeName", ident), Applicability::HasPlaceholders, ); diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 2745b18a8cd..abb44493353 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -26,7 +26,7 @@ use std::mem; /// `token::Interpolated` tokens. macro_rules! maybe_whole_expr { ($p:expr) => { - if let token::Interpolated(nt, _) = &$p.token.kind { + if let token::Interpolated(nt) = &$p.token.kind { match &**nt { token::NtExpr(e) | token::NtLiteral(e) => { let e = e.clone(); @@ -867,7 +867,7 @@ impl<'a> Parser<'a> { let fn_span_lo = self.token.span; let segment = self.parse_path_segment(PathStyle::Expr)?; - self.check_trailing_angle_brackets(&segment, token::OpenDelim(token::Paren)); + self.check_trailing_angle_brackets(&segment, &[&token::OpenDelim(token::Paren)]); if self.check(&token::OpenDelim(token::Paren)) { // Method call `expr.f()` diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 10df16964da..5923a185dcf 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -9,7 +9,7 @@ use rustc_ast::ast::{AssocItem, AssocItemKind, ForeignItemKind, Item, ItemKind, use rustc_ast::ast::{Async, Const, Defaultness, IsAuto, Mutability, Unsafe, UseTree, UseTreeKind}; use rustc_ast::ast::{BindingMode, Block, FnDecl, FnSig, Param, SelfKind}; use rustc_ast::ast::{EnumDef, Generics, StructField, TraitRef, Ty, TyKind, Variant, VariantData}; -use rustc_ast::ast::{FnHeader, ForeignItem, PathSegment, Visibility, VisibilityKind}; +use rustc_ast::ast::{FnHeader, ForeignItem, Path, PathSegment, Visibility, VisibilityKind}; use rustc_ast::ast::{MacArgs, MacCall, MacDelimiter}; use rustc_ast::ptr::P; use rustc_ast::token::{self, TokenKind}; @@ -1262,6 +1262,25 @@ impl<'a> Parser<'a> { sp, &format!("expected `,`, or `}}`, found {}", super::token_descr(&self.token)), ); + + // Try to recover extra trailing angle brackets + let mut recovered = false; + if let TyKind::Path(_, Path { segments, .. }) = &a_var.ty.kind { + if let Some(last_segment) = segments.last() { + recovered = self.check_trailing_angle_brackets( + last_segment, + &[&token::Comma, &token::CloseDelim(token::Brace)], + ); + if recovered { + // Handle a case like `Vec<u8>>,` where we can continue parsing fields + // after the comma + self.eat(&token::Comma); + // `check_trailing_angle_brackets` already emitted a nicer error + err.cancel(); + } + } + } + if self.token.is_ident() { // This is likely another field; emit the diagnostic and keep going err.span_suggestion( @@ -1271,6 +1290,14 @@ impl<'a> Parser<'a> { Applicability::MachineApplicable, ); err.emit(); + recovered = true; + } + + if recovered { + // Make sure an error was emitted (either by recovering an angle bracket, + // or by finding an identifier as the next token), since we're + // going to continue parsing + assert!(self.sess.span_diagnostic.has_errors()); } else { return Err(err); } @@ -1780,7 +1807,7 @@ impl<'a> Parser<'a> { fn is_named_param(&self) -> bool { let offset = match self.token.kind { - token::Interpolated(ref nt, _) => match **nt { + token::Interpolated(ref nt) => match **nt { token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon), _ => 0, }, diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 04074479a21..7811d5fb741 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -54,7 +54,7 @@ enum BlockMode { #[macro_export] macro_rules! maybe_whole { ($p:expr, $constructor:ident, |$x:ident| $e:expr) => { - if let token::Interpolated(nt, _) = &$p.token.kind { + if let token::Interpolated(nt) = &$p.token.kind { if let token::$constructor(x) = &**nt { let $x = x.clone(); $p.bump(); @@ -69,7 +69,7 @@ macro_rules! maybe_whole { macro_rules! maybe_recover_from_interpolated_ty_qpath { ($self: expr, $allow_qpath_recovery: expr) => { if $allow_qpath_recovery && $self.look_ahead(1, |t| t == &token::ModSep) { - if let token::Interpolated(nt, _) = &$self.token.kind { + if let token::Interpolated(nt) = &$self.token.kind { if let token::NtTy(ty) = &**nt { let ty = ty.clone(); $self.bump(); @@ -922,7 +922,7 @@ impl<'a> Parser<'a> { if self.eat(&token::Eq) { let eq_span = self.prev_token.span; let mut is_interpolated_expr = false; - if let token::Interpolated(nt, _) = &self.token.kind { + if let token::Interpolated(nt) = &self.token.kind { if let token::NtExpr(..) = **nt { is_interpolated_expr = true; } diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs index 742183d3697..6603d0afc02 100644 --- a/src/librustc_parse/parser/pat.rs +++ b/src/librustc_parse/parser/pat.rs @@ -515,7 +515,7 @@ impl<'a> Parser<'a> { self.recover_additional_muts(); // Make sure we don't allow e.g. `let mut $p;` where `$p:pat`. - if let token::Interpolated(ref nt, _) = self.token.kind { + if let token::Interpolated(ref nt) = self.token.kind { if let token::NtPat(_) = **nt { self.expected_ident_found().emit(); } diff --git a/src/librustc_parse/parser/path.rs b/src/librustc_parse/parser/path.rs index 5210614548d..67e9b3af4a8 100644 --- a/src/librustc_parse/parser/path.rs +++ b/src/librustc_parse/parser/path.rs @@ -169,7 +169,7 @@ impl<'a> Parser<'a> { // `PathStyle::Expr` is only provided at the root invocation and never in // `parse_path_segment` to recurse and therefore can be checked to maintain // this invariant. - self.check_trailing_angle_brackets(&segment, token::ModSep); + self.check_trailing_angle_brackets(&segment, &[&token::ModSep]); } segments.push(segment); diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs index 503fbb64db8..87348894a5a 100644 --- a/src/librustc_passes/dead.rs +++ b/src/librustc_passes/dead.rs @@ -37,10 +37,10 @@ fn should_explore(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { } } -struct MarkSymbolVisitor<'a, 'tcx> { +struct MarkSymbolVisitor<'tcx> { worklist: Vec<hir::HirId>, tcx: TyCtxt<'tcx>, - tables: &'a ty::TypeckTables<'tcx>, + maybe_typeck_tables: Option<&'tcx ty::TypeckTables<'tcx>>, live_symbols: FxHashSet<hir::HirId>, repr_has_repr_c: bool, in_pat: bool, @@ -50,7 +50,15 @@ struct MarkSymbolVisitor<'a, 'tcx> { struct_constructors: FxHashMap<hir::HirId, hir::HirId>, } -impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { +impl<'tcx> MarkSymbolVisitor<'tcx> { + /// Gets the type-checking side-tables for the current body. + /// As this will ICE if called outside bodies, only call when working with + /// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies). + #[track_caller] + fn tables(&self) -> &'tcx ty::TypeckTables<'tcx> { + self.maybe_typeck_tables.expect("`MarkSymbolVisitor::tables` called outside of body") + } + fn check_def_id(&mut self, def_id: DefId) { if let Some(def_id) = def_id.as_local() { let hir_id = self.tcx.hir().as_local_hir_id(def_id); @@ -107,7 +115,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } fn lookup_and_handle_method(&mut self, id: hir::HirId) { - if let Some(def_id) = self.tables.type_dependent_def_id(id) { + if let Some(def_id) = self.tables().type_dependent_def_id(id) { self.check_def_id(def_id); } else { bug!("no type-dependent def for method"); @@ -115,9 +123,9 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } fn handle_field_access(&mut self, lhs: &hir::Expr<'_>, hir_id: hir::HirId) { - match self.tables.expr_ty_adjusted(lhs).kind { + match self.tables().expr_ty_adjusted(lhs).kind { ty::Adt(def, _) => { - let index = self.tcx.field_index(hir_id, self.tables); + let index = self.tcx.field_index(hir_id, self.tables()); self.insert_def_id(def.non_enum_variant().fields[index].did); } ty::Tuple(..) => {} @@ -131,7 +139,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { res: Res, pats: &[hir::FieldPat<'_>], ) { - let variant = match self.tables.node_type(lhs.hir_id).kind { + let variant = match self.tables().node_type(lhs.hir_id).kind { ty::Adt(adt, _) => adt.variant_of_res(res), _ => span_bug!(lhs.span, "non-ADT in struct pattern"), }; @@ -139,7 +147,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { if let PatKind::Wild = pat.pat.kind { continue; } - let index = self.tcx.field_index(pat.hir_id, self.tables); + let index = self.tcx.field_index(pat.hir_id, self.tables()); self.insert_def_id(variant.fields[index].did); } } @@ -204,14 +212,14 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn mark_as_used_if_union(&mut self, adt: &ty::AdtDef, fields: &[hir::Field<'_>]) { if adt.is_union() && adt.non_enum_variant().fields.len() > 1 && adt.did.is_local() { for field in fields { - let index = self.tcx.field_index(field.hir_id, self.tables); + let index = self.tcx.field_index(field.hir_id, self.tables()); self.insert_def_id(adt.non_enum_variant().fields[index].did); } } } } -impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> { @@ -219,11 +227,10 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { } fn visit_nested_body(&mut self, body: hir::BodyId) { - let old_tables = self.tables; - self.tables = self.tcx.body_tables(body); + let old_maybe_typeck_tables = self.maybe_typeck_tables.replace(self.tcx.body_tables(body)); let body = self.tcx.hir().body(body); self.visit_body(body); - self.tables = old_tables; + self.maybe_typeck_tables = old_maybe_typeck_tables; } fn visit_variant_data( @@ -248,7 +255,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { match expr.kind { hir::ExprKind::Path(ref qpath @ hir::QPath::TypeRelative(..)) => { - let res = self.tables.qpath_res(qpath, expr.hir_id); + let res = self.tables().qpath_res(qpath, expr.hir_id); self.handle_res(res); } hir::ExprKind::MethodCall(..) => { @@ -258,9 +265,9 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { self.handle_field_access(&lhs, expr.hir_id); } hir::ExprKind::Struct(ref qpath, ref fields, _) => { - let res = self.tables.qpath_res(qpath, expr.hir_id); + let res = self.tables().qpath_res(qpath, expr.hir_id); self.handle_res(res); - if let ty::Adt(ref adt, _) = self.tables.expr_ty(expr).kind { + if let ty::Adt(ref adt, _) = self.tables().expr_ty(expr).kind { self.mark_as_used_if_union(adt, fields); } } @@ -283,11 +290,11 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) { match pat.kind { PatKind::Struct(ref path, ref fields, _) => { - let res = self.tables.qpath_res(path, pat.hir_id); + let res = self.tables().qpath_res(path, pat.hir_id); self.handle_field_pattern_match(pat, res, fields); } PatKind::Path(ref qpath) => { - let res = self.tables.qpath_res(qpath, pat.hir_id); + let res = self.tables().qpath_res(qpath, pat.hir_id); self.handle_res(res); } _ => (), @@ -473,7 +480,7 @@ fn find_live<'tcx>( let mut symbol_visitor = MarkSymbolVisitor { worklist, tcx, - tables: &ty::TypeckTables::empty(None), + maybe_typeck_tables: None, live_symbols: Default::default(), repr_has_repr_c: false, in_pat: false, diff --git a/src/librustc_passes/intrinsicck.rs b/src/librustc_passes/intrinsicck.rs index 683039df15a..e4f4885690f 100644 --- a/src/librustc_passes/intrinsicck.rs +++ b/src/librustc_passes/intrinsicck.rs @@ -422,7 +422,7 @@ impl Visitor<'tcx> for ExprVisitor<'tcx> { let typ = self.tables.node_type(expr.hir_id); let sig = typ.fn_sig(self.tcx); let from = sig.inputs().skip_binder()[0]; - let to = *sig.output().skip_binder(); + let to = sig.output().skip_binder(); self.check_transmute(expr.span, from, to); } } diff --git a/src/librustc_passes/lang_items.rs b/src/librustc_passes/lang_items.rs index 0be37cb0960..0326591a931 100644 --- a/src/librustc_passes/lang_items.rs +++ b/src/librustc_passes/lang_items.rs @@ -146,6 +146,28 @@ impl LanguageItemCollector<'tcx> { )); } } + let mut note_def = |which, def_id: DefId| { + let crate_name = self.tcx.crate_name(def_id.krate); + let note = if def_id.is_local() { + format!("{} definition in the local crate (`{}`)", which, crate_name) + } else { + let paths: Vec<_> = self + .tcx + .crate_extern_paths(def_id.krate) + .iter() + .map(|p| p.display().to_string()) + .collect(); + format!( + "{} definition in `{}` loaded from {}", + which, + crate_name, + paths.join(", ") + ) + }; + err.note(¬e); + }; + note_def("first", original_def_id); + note_def("second", item_def_id); } err.emit(); } diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index b55c5ec47ee..5109d8debee 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -8,6 +8,7 @@ #![feature(in_band_lifetimes)] #![feature(nll)] #![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(track_caller))] #![recursion_limit = "256"] #[macro_use] diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs index 798c6b8925b..b288a41e0cf 100644 --- a/src/librustc_passes/liveness.rs +++ b/src/librustc_passes/liveness.rs @@ -1123,16 +1123,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { match target { Some(b) => self.propagate_through_opt_expr(opt_expr.as_ref().map(|e| &**e), b), - None => { - // FIXME: This should have been checked earlier. Once this is fixed, - // replace with `delay_span_bug`. (#62480) - self.ir - .tcx - .sess - .struct_span_err(expr.span, "`break` to unknown label") - .emit(); - rustc_errors::FatalError.raise() - } + None => span_bug!(expr.span, "`break` to unknown label"), } } diff --git a/src/librustc_passes/reachable.rs b/src/librustc_passes/reachable.rs index c9a4428c007..50fcefa3569 100644 --- a/src/librustc_passes/reachable.rs +++ b/src/librustc_passes/reachable.rs @@ -60,10 +60,10 @@ fn method_might_be_inlined( } // Information needed while computing reachability. -struct ReachableContext<'a, 'tcx> { +struct ReachableContext<'tcx> { // The type context. tcx: TyCtxt<'tcx>, - tables: &'a ty::TypeckTables<'tcx>, + maybe_typeck_tables: Option<&'tcx ty::TypeckTables<'tcx>>, // The set of items which must be exported in the linkage sense. reachable_symbols: HirIdSet, // A worklist of item IDs. Each item ID in this worklist will be inlined @@ -73,7 +73,7 @@ struct ReachableContext<'a, 'tcx> { any_library: bool, } -impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for ReachableContext<'tcx> { type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { @@ -81,18 +81,17 @@ impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> { } fn visit_nested_body(&mut self, body: hir::BodyId) { - let old_tables = self.tables; - self.tables = self.tcx.body_tables(body); + let old_maybe_typeck_tables = self.maybe_typeck_tables.replace(self.tcx.body_tables(body)); let body = self.tcx.hir().body(body); self.visit_body(body); - self.tables = old_tables; + self.maybe_typeck_tables = old_maybe_typeck_tables; } fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { let res = match expr.kind { - hir::ExprKind::Path(ref qpath) => Some(self.tables.qpath_res(qpath, expr.hir_id)), + hir::ExprKind::Path(ref qpath) => Some(self.tables().qpath_res(qpath, expr.hir_id)), hir::ExprKind::MethodCall(..) => self - .tables + .tables() .type_dependent_def(expr.hir_id) .map(|(kind, def_id)| Res::Def(kind, def_id)), _ => None, @@ -133,7 +132,15 @@ impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> { } } -impl<'a, 'tcx> ReachableContext<'a, 'tcx> { +impl<'tcx> ReachableContext<'tcx> { + /// Gets the type-checking side-tables for the current body. + /// As this will ICE if called outside bodies, only call when working with + /// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies). + #[track_caller] + fn tables(&self) -> &'tcx ty::TypeckTables<'tcx> { + self.maybe_typeck_tables.expect("`ReachableContext::tables` called outside of body") + } + // Returns true if the given def ID represents a local item that is // eligible for inlining and false otherwise. fn def_id_represents_local_inlined_item(&self, def_id: DefId) -> bool { @@ -381,7 +388,7 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) -> &'tcx HirIdSet }); let mut reachable_context = ReachableContext { tcx, - tables: &ty::TypeckTables::empty(None), + maybe_typeck_tables: None, reachable_symbols: Default::default(), worklist: Vec::new(), any_library, diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index ad512c63352..2e1775ca465 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -331,12 +331,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { } } -struct MissingStabilityAnnotations<'a, 'tcx> { +struct MissingStabilityAnnotations<'tcx> { tcx: TyCtxt<'tcx>, - access_levels: &'a AccessLevels, + access_levels: &'tcx AccessLevels, } -impl<'a, 'tcx> MissingStabilityAnnotations<'a, 'tcx> { +impl<'tcx> MissingStabilityAnnotations<'tcx> { fn check_missing_stability(&self, hir_id: HirId, span: Span) { let stab = self.tcx.stability().local_stability(hir_id); let is_error = @@ -349,7 +349,7 @@ impl<'a, 'tcx> MissingStabilityAnnotations<'a, 'tcx> { } } -impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { type Map = Map<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 9e6e7ea962b..de21365c536 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -2,6 +2,7 @@ #![feature(in_band_lifetimes)] #![feature(nll)] #![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(track_caller))] #![recursion_limit = "256"] use rustc_attr as attr; @@ -92,14 +93,14 @@ where for (predicate, _span) in predicates { match predicate.kind() { ty::PredicateKind::Trait(poly_predicate, _) => { - let ty::TraitPredicate { trait_ref } = *poly_predicate.skip_binder(); + let ty::TraitPredicate { trait_ref } = poly_predicate.skip_binder(); if self.visit_trait(trait_ref) { return true; } } ty::PredicateKind::Projection(poly_predicate) => { let ty::ProjectionPredicate { projection_ty, ty } = - *poly_predicate.skip_binder(); + poly_predicate.skip_binder(); if ty.visit_with(self) { return true; } @@ -108,7 +109,7 @@ where } } ty::PredicateKind::TypeOutlives(poly_predicate) => { - let ty::OutlivesPredicate(ty, _region) = *poly_predicate.skip_binder(); + let ty::OutlivesPredicate(ty, _region) = poly_predicate.skip_binder(); if ty.visit_with(self) { return true; } @@ -175,7 +176,7 @@ where ty::Dynamic(predicates, ..) => { // All traits in the list are considered the "primary" part of the type // and are visited by shallow visitors. - for predicate in *predicates.skip_binder() { + for predicate in predicates.skip_binder() { let trait_ref = match predicate { ty::ExistentialPredicate::Trait(trait_ref) => trait_ref, ty::ExistentialPredicate::Projection(proj) => proj.trait_ref(tcx), @@ -345,17 +346,6 @@ fn def_id_visibility<'tcx>( } } -// Set the correct `TypeckTables` for the given `item_id` (or an empty table if -// there is no `TypeckTables` for the item). -fn item_tables<'a, 'tcx>( - tcx: TyCtxt<'tcx>, - hir_id: hir::HirId, - empty_tables: &'a ty::TypeckTables<'tcx>, -) -> &'a ty::TypeckTables<'tcx> { - let def_id = tcx.hir().local_def_id(hir_id); - if tcx.has_typeck_tables(def_id) { tcx.typeck_tables_of(def_id) } else { empty_tables } -} - fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visibility { if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 } } @@ -1029,14 +1019,21 @@ impl DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> { /// This pass performs remaining checks for fields in struct expressions and patterns. ////////////////////////////////////////////////////////////////////////////////////// -struct NamePrivacyVisitor<'a, 'tcx> { +struct NamePrivacyVisitor<'tcx> { tcx: TyCtxt<'tcx>, - tables: &'a ty::TypeckTables<'tcx>, + maybe_typeck_tables: Option<&'tcx ty::TypeckTables<'tcx>>, current_item: Option<hir::HirId>, - empty_tables: &'a ty::TypeckTables<'tcx>, } -impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> { +impl<'tcx> NamePrivacyVisitor<'tcx> { + /// Gets the type-checking side-tables for the current body. + /// As this will ICE if called outside bodies, only call when working with + /// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies). + #[track_caller] + fn tables(&self) -> &'tcx ty::TypeckTables<'tcx> { + self.maybe_typeck_tables.expect("`NamePrivacyVisitor::tables` called outside of body") + } + // Checks that a field in a struct constructor (expression or pattern) is accessible. fn check_field( &mut self, @@ -1072,7 +1069,7 @@ impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> { } } -impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> { type Map = Map<'tcx>; /// We want to visit items in the context of their containing @@ -1087,39 +1084,22 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { } fn visit_nested_body(&mut self, body: hir::BodyId) { - let orig_tables = mem::replace(&mut self.tables, self.tcx.body_tables(body)); + let old_maybe_typeck_tables = self.maybe_typeck_tables.replace(self.tcx.body_tables(body)); let body = self.tcx.hir().body(body); self.visit_body(body); - self.tables = orig_tables; + self.maybe_typeck_tables = old_maybe_typeck_tables; } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { - let orig_current_item = mem::replace(&mut self.current_item, Some(item.hir_id)); - let orig_tables = - mem::replace(&mut self.tables, item_tables(self.tcx, item.hir_id, self.empty_tables)); + let orig_current_item = self.current_item.replace(item.hir_id); intravisit::walk_item(self, item); self.current_item = orig_current_item; - self.tables = orig_tables; - } - - fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) { - let orig_tables = - mem::replace(&mut self.tables, item_tables(self.tcx, ti.hir_id, self.empty_tables)); - intravisit::walk_trait_item(self, ti); - self.tables = orig_tables; - } - - fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) { - let orig_tables = - mem::replace(&mut self.tables, item_tables(self.tcx, ii.hir_id, self.empty_tables)); - intravisit::walk_impl_item(self, ii); - self.tables = orig_tables; } fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { if let hir::ExprKind::Struct(ref qpath, fields, ref base) = expr.kind { - let res = self.tables.qpath_res(qpath, expr.hir_id); - let adt = self.tables.expr_ty(expr).ty_adt_def().unwrap(); + let res = self.tables().qpath_res(qpath, expr.hir_id); + let adt = self.tables().expr_ty(expr).ty_adt_def().unwrap(); let variant = adt.variant_of_res(res); if let Some(ref base) = *base { // If the expression uses FRU we need to make sure all the unmentioned fields @@ -1128,7 +1108,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { for (vf_index, variant_field) in variant.fields.iter().enumerate() { let field = fields .iter() - .find(|f| self.tcx.field_index(f.hir_id, self.tables) == vf_index); + .find(|f| self.tcx.field_index(f.hir_id, self.tables()) == vf_index); let (use_ctxt, span) = match field { Some(field) => (field.ident.span, field.span), None => (base.span, base.span), @@ -1138,7 +1118,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { } else { for field in fields { let use_ctxt = field.ident.span; - let index = self.tcx.field_index(field.hir_id, self.tables); + let index = self.tcx.field_index(field.hir_id, self.tables()); self.check_field(use_ctxt, field.span, adt, &variant.fields[index], false); } } @@ -1149,12 +1129,12 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) { if let PatKind::Struct(ref qpath, fields, _) = pat.kind { - let res = self.tables.qpath_res(qpath, pat.hir_id); - let adt = self.tables.pat_ty(pat).ty_adt_def().unwrap(); + let res = self.tables().qpath_res(qpath, pat.hir_id); + let adt = self.tables().pat_ty(pat).ty_adt_def().unwrap(); let variant = adt.variant_of_res(res); for field in fields { let use_ctxt = field.ident.span; - let index = self.tcx.field_index(field.hir_id, self.tables); + let index = self.tcx.field_index(field.hir_id, self.tables()); self.check_field(use_ctxt, field.span, adt, &variant.fields[index], false); } } @@ -1169,16 +1149,22 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { /// Checks are performed on "semantic" types regardless of names and their hygiene. //////////////////////////////////////////////////////////////////////////////////////////// -struct TypePrivacyVisitor<'a, 'tcx> { +struct TypePrivacyVisitor<'tcx> { tcx: TyCtxt<'tcx>, - tables: &'a ty::TypeckTables<'tcx>, + maybe_typeck_tables: Option<&'tcx ty::TypeckTables<'tcx>>, current_item: LocalDefId, - in_body: bool, span: Span, - empty_tables: &'a ty::TypeckTables<'tcx>, } -impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> { +impl<'tcx> TypePrivacyVisitor<'tcx> { + /// Gets the type-checking side-tables for the current body. + /// As this will ICE if called outside bodies, only call when working with + /// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies). + #[track_caller] + fn tables(&self) -> &'tcx ty::TypeckTables<'tcx> { + self.maybe_typeck_tables.expect("`TypePrivacyVisitor::tables` called outside of body") + } + fn item_is_accessible(&self, did: DefId) -> bool { def_id_visibility(self.tcx, did) .0 @@ -1188,10 +1174,11 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> { // Take node-id of an expression or pattern and check its type for privacy. fn check_expr_pat_type(&mut self, id: hir::HirId, span: Span) -> bool { self.span = span; - if self.visit(self.tables.node_type(id)) || self.visit(self.tables.node_substs(id)) { + let tables = self.tables(); + if self.visit(tables.node_type(id)) || self.visit(tables.node_substs(id)) { return true; } - if let Some(adjustments) = self.tables.adjustments().get(id) { + if let Some(adjustments) = tables.adjustments().get(id) { for adjustment in adjustments { if self.visit(adjustment.target) { return true; @@ -1214,7 +1201,7 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> { } } -impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { type Map = Map<'tcx>; /// We want to visit items in the context of their containing @@ -1229,19 +1216,17 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { } fn visit_nested_body(&mut self, body: hir::BodyId) { - let orig_tables = mem::replace(&mut self.tables, self.tcx.body_tables(body)); - let orig_in_body = mem::replace(&mut self.in_body, true); + let old_maybe_typeck_tables = self.maybe_typeck_tables.replace(self.tcx.body_tables(body)); let body = self.tcx.hir().body(body); self.visit_body(body); - self.tables = orig_tables; - self.in_body = orig_in_body; + self.maybe_typeck_tables = old_maybe_typeck_tables; } fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) { self.span = hir_ty.span; - if self.in_body { + if let Some(tables) = self.maybe_typeck_tables { // Types in bodies. - if self.visit(self.tables.node_type(hir_ty.hir_id)) { + if self.visit(tables.node_type(hir_ty.hir_id)) { return; } } else { @@ -1258,7 +1243,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { fn visit_trait_ref(&mut self, trait_ref: &'tcx hir::TraitRef<'tcx>) { self.span = trait_ref.path.span; - if !self.in_body { + if self.maybe_typeck_tables.is_none() { // Avoid calling `hir_trait_to_predicates` in bodies, it will ICE. // The traits' privacy in bodies is already checked as a part of trait object types. let bounds = rustc_typeck::hir_trait_to_predicates( @@ -1270,7 +1255,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { ); for (trait_predicate, _, _) in bounds.trait_bounds { - if self.visit_trait(*trait_predicate.skip_binder()) { + if self.visit_trait(trait_predicate.skip_binder()) { return; } } @@ -1304,7 +1289,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { hir::ExprKind::MethodCall(_, span, _, _) => { // Method calls have to be checked specially. self.span = span; - if let Some(def_id) = self.tables.type_dependent_def_id(expr.hir_id) { + if let Some(def_id) = self.tables().type_dependent_def_id(expr.hir_id) { if self.visit(self.tcx.type_of(def_id)) { return; } @@ -1327,9 +1312,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { // more code internal visibility at link time. (Access to private functions // is already prohibited by type privacy for function types.) fn visit_qpath(&mut self, qpath: &'tcx hir::QPath<'tcx>, id: hir::HirId, span: Span) { - let def = match self.tables.qpath_res(qpath, id) { - Res::Def(kind, def_id) => Some((kind, def_id)), - _ => None, + let def = match qpath { + hir::QPath::Resolved(_, path) => match path.res { + Res::Def(kind, def_id) => Some((kind, def_id)), + _ => None, + }, + hir::QPath::TypeRelative(..) => { + self.maybe_typeck_tables.and_then(|tables| tables.type_dependent_def(id)) + } }; let def = def.filter(|(kind, _)| match kind { DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy | DefKind::Static => true, @@ -1385,31 +1375,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { let orig_current_item = mem::replace(&mut self.current_item, self.tcx.hir().local_def_id(item.hir_id)); - let orig_in_body = mem::replace(&mut self.in_body, false); - let orig_tables = - mem::replace(&mut self.tables, item_tables(self.tcx, item.hir_id, self.empty_tables)); + let old_maybe_typeck_tables = self.maybe_typeck_tables.take(); intravisit::walk_item(self, item); - self.tables = orig_tables; - self.in_body = orig_in_body; + self.maybe_typeck_tables = old_maybe_typeck_tables; self.current_item = orig_current_item; } - - fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) { - let orig_tables = - mem::replace(&mut self.tables, item_tables(self.tcx, ti.hir_id, self.empty_tables)); - intravisit::walk_trait_item(self, ti); - self.tables = orig_tables; - } - - fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) { - let orig_tables = - mem::replace(&mut self.tables, item_tables(self.tcx, ii.hir_id, self.empty_tables)); - intravisit::walk_impl_item(self, ii); - self.tables = orig_tables; - } } -impl DefIdVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { +impl DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -2066,29 +2039,16 @@ pub fn provide(providers: &mut Providers<'_>) { } fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { - let empty_tables = ty::TypeckTables::empty(None); - // Check privacy of names not checked in previous compilation stages. - let mut visitor = NamePrivacyVisitor { - tcx, - tables: &empty_tables, - current_item: None, - empty_tables: &empty_tables, - }; + let mut visitor = NamePrivacyVisitor { tcx, maybe_typeck_tables: None, current_item: None }; let (module, span, hir_id) = tcx.hir().get_module(module_def_id); intravisit::walk_mod(&mut visitor, module, hir_id); // Check privacy of explicitly written types and traits as well as // inferred types of expressions and patterns. - let mut visitor = TypePrivacyVisitor { - tcx, - tables: &empty_tables, - current_item: module_def_id, - in_body: false, - span, - empty_tables: &empty_tables, - }; + let mut visitor = + TypePrivacyVisitor { tcx, maybe_typeck_tables: None, current_item: module_def_id, span }; intravisit::walk_mod(&mut visitor, module, hir_id); } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index a92d451dfd0..bca65c63e91 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -1325,7 +1325,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { } fn visit_token(&mut self, t: Token) { - if let token::Interpolated(nt, _) = t.kind { + if let token::Interpolated(nt) = t.kind { if let token::NtExpr(ref expr) = *nt { if let ast::ExprKind::MacCall(..) = expr.kind { self.visit_invoc(expr.id); diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs index c25a20210e0..32af920020c 100644 --- a/src/librustc_resolve/def_collector.rs +++ b/src/librustc_resolve/def_collector.rs @@ -256,7 +256,7 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> { } fn visit_token(&mut self, t: Token) { - if let token::Interpolated(nt, _) = t.kind { + if let token::Interpolated(nt) = t.kind { if let token::NtExpr(ref expr) = *nt { if let ExprKind::MacCall(..) = expr.kind { self.visit_macro_invoc(expr.id); diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 2854683b61b..c64c617b54b 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -33,6 +33,10 @@ type Res = def::Res<ast::NodeId>; /// A vector of spans and replacements, a message and applicability. crate type Suggestion = (Vec<(Span, String)>, String, Applicability); +/// Potential candidate for an undeclared or out-of-scope label - contains the ident of a +/// similarly named label and whether or not it is reachable. +crate type LabelSuggestion = (Ident, bool); + crate struct TypoSuggestion { pub candidate: Symbol, pub res: Res, @@ -282,7 +286,7 @@ impl<'a> Resolver<'a> { err.span_label(span, "used in a pattern more than once"); err } - ResolutionError::UndeclaredLabel(name, lev_candidate) => { + ResolutionError::UndeclaredLabel { name, suggestion } => { let mut err = struct_span_err!( self.session, span, @@ -290,16 +294,31 @@ impl<'a> Resolver<'a> { "use of undeclared label `{}`", name ); - if let Some(lev_candidate) = lev_candidate { - err.span_suggestion( - span, - "a label with a similar name exists in this scope", - lev_candidate.to_string(), - Applicability::MaybeIncorrect, - ); - } else { - err.span_label(span, format!("undeclared label `{}`", name)); + + err.span_label(span, format!("undeclared label `{}`", name)); + + match suggestion { + // A reachable label with a similar name exists. + Some((ident, true)) => { + err.span_label(ident.span, "a label with a similar name is reachable"); + err.span_suggestion( + span, + "try using similarly named label", + ident.name.to_string(), + Applicability::MaybeIncorrect, + ); + } + // An unreachable label with a similar name exists. + Some((ident, false)) => { + err.span_label( + ident.span, + "a label with a similar name exists but is unreachable", + ); + } + // No similarly-named labels exist. + None => (), } + err } ResolutionError::SelfImportsOnlyAllowedWithin { root, span_with_rename } => { @@ -433,6 +452,45 @@ impl<'a> Resolver<'a> { err.span_label(span, "`Self` in type parameter default".to_string()); err } + ResolutionError::UnreachableLabel { name, definition_span, suggestion } => { + let mut err = struct_span_err!( + self.session, + span, + E0767, + "use of unreachable label `{}`", + name, + ); + + err.span_label(definition_span, "unreachable label defined here"); + err.span_label(span, format!("unreachable label `{}`", name)); + err.note( + "labels are unreachable through functions, closures, async blocks and modules", + ); + + match suggestion { + // A reachable label with a similar name exists. + Some((ident, true)) => { + err.span_label(ident.span, "a label with a similar name is reachable"); + err.span_suggestion( + span, + "try using similarly named label", + ident.name.to_string(), + Applicability::MaybeIncorrect, + ); + } + // An unreachable label with a similar name exists. + Some((ident, false)) => { + err.span_label( + ident.span, + "a label with a similar name exists but is also unreachable", + ); + } + // No similarly-named labels exist. + None => (), + } + + err + } } } diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 84ba9094ea1..4451791780e 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -13,7 +13,6 @@ use crate::{ResolutionError, Resolver, Segment, UseError}; use rustc_ast::ast::*; use rustc_ast::ptr::P; -use rustc_ast::util::lev_distance::find_best_match_for_name; use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; use rustc_ast::{unwrap_or, walk_list}; use rustc_ast_lowering::ResolverAstLowering; @@ -101,6 +100,9 @@ crate enum RibKind<'a> { /// upvars). AssocItemRibKind, + /// We passed through a closure. Disallow labels. + ClosureOrAsyncRibKind, + /// We passed through a function definition. Disallow upvars. /// Permit only those const parameters that are specified in the function's generics. FnItemRibKind, @@ -124,11 +126,15 @@ crate enum RibKind<'a> { } impl RibKind<'_> { - // Whether this rib kind contains generic parameters, as opposed to local - // variables. + /// Whether this rib kind contains generic parameters, as opposed to local + /// variables. crate fn contains_params(&self) -> bool { match self { - NormalRibKind | FnItemRibKind | ConstantItemRibKind | ModuleRibKind(_) + NormalRibKind + | ClosureOrAsyncRibKind + | FnItemRibKind + | ConstantItemRibKind + | ModuleRibKind(_) | MacroDefinition(_) => false, AssocItemRibKind | ItemRibKind(_) | ForwardTyParamBanRibKind => true, } @@ -474,7 +480,8 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // Bail if there's no body. FnKind::Fn(.., None) => return visit::walk_fn(self, fn_kind, sp), FnKind::Fn(FnCtxt::Free | FnCtxt::Foreign, ..) => FnItemRibKind, - FnKind::Fn(FnCtxt::Assoc(_), ..) | FnKind::Closure(..) => NormalRibKind, + FnKind::Fn(FnCtxt::Assoc(_), ..) => NormalRibKind, + FnKind::Closure(..) => ClosureOrAsyncRibKind, }; let previous_value = replace(&mut self.diagnostic_metadata.current_function, Some((fn_kind, sp))); @@ -725,37 +732,81 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } } - /// Searches the current set of local scopes for labels. Returns the first non-`None` label that - /// is returned by the given predicate function - /// - /// Stops after meeting a closure. - fn search_label<P, R>(&self, mut ident: Ident, pred: P) -> Option<R> - where - P: Fn(&Rib<'_, NodeId>, Ident) -> Option<R>, - { - for rib in self.label_ribs.iter().rev() { - match rib.kind { - NormalRibKind => {} + /// Searches the current set of local scopes for labels. Returns the `NodeId` of the resolved + /// label and reports an error if the label is not found or is unreachable. + fn resolve_label(&self, mut label: Ident) -> Option<NodeId> { + let mut suggestion = None; + + // Preserve the original span so that errors contain "in this macro invocation" + // information. + let original_span = label.span; + + for i in (0..self.label_ribs.len()).rev() { + let rib = &self.label_ribs[i]; + + if let MacroDefinition(def) = rib.kind { // If an invocation of this macro created `ident`, give up on `ident` // and switch to `ident`'s source from the macro definition. - MacroDefinition(def) => { - if def == self.r.macro_def(ident.span.ctxt()) { - ident.span.remove_mark(); - } - } - _ => { - // Do not resolve labels across function boundary - return None; + if def == self.r.macro_def(label.span.ctxt()) { + label.span.remove_mark(); } } - let r = pred(rib, ident); - if r.is_some() { - return r; + + let ident = label.normalize_to_macro_rules(); + if let Some((ident, id)) = rib.bindings.get_key_value(&ident) { + return if self.is_label_valid_from_rib(i) { + Some(*id) + } else { + self.r.report_error( + original_span, + ResolutionError::UnreachableLabel { + name: &label.name.as_str(), + definition_span: ident.span, + suggestion, + }, + ); + + None + }; } + + // Diagnostics: Check if this rib contains a label with a similar name, keep track of + // the first such label that is encountered. + suggestion = suggestion.or_else(|| self.suggestion_for_label_in_rib(i, label)); } + + self.r.report_error( + original_span, + ResolutionError::UndeclaredLabel { name: &label.name.as_str(), suggestion }, + ); None } + /// Determine whether or not a label from the `rib_index`th label rib is reachable. + fn is_label_valid_from_rib(&self, rib_index: usize) -> bool { + let ribs = &self.label_ribs[rib_index + 1..]; + + for rib in ribs { + match rib.kind { + NormalRibKind | MacroDefinition(..) => { + // Nothing to do. Continue. + } + + AssocItemRibKind + | ClosureOrAsyncRibKind + | FnItemRibKind + | ItemRibKind(..) + | ConstantItemRibKind + | ModuleRibKind(..) + | ForwardTyParamBanRibKind => { + return false; + } + } + } + + true + } + fn resolve_adt(&mut self, item: &'ast Item, generics: &'ast Generics) { debug!("resolve_adt"); self.with_current_self_item(item, |this| { @@ -2044,35 +2095,10 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } ExprKind::Break(Some(label), _) | ExprKind::Continue(Some(label)) => { - let node_id = self.search_label(label.ident, |rib, ident| { - rib.bindings.get(&ident.normalize_to_macro_rules()).cloned() - }); - match node_id { - None => { - // Search again for close matches... - // Picks the first label that is "close enough", which is not necessarily - // the closest match - let close_match = self.search_label(label.ident, |rib, ident| { - let names = rib.bindings.iter().filter_map(|(id, _)| { - if id.span.ctxt() == label.ident.span.ctxt() { - Some(&id.name) - } else { - None - } - }); - find_best_match_for_name(names, &ident.as_str(), None) - }); - self.r.record_partial_res(expr.id, PartialRes::new(Res::Err)); - self.r.report_error( - label.ident.span, - ResolutionError::UndeclaredLabel(&label.ident.as_str(), close_match), - ); - } - Some(node_id) => { - // Since this res is a label, it is never read. - self.r.label_res_map.insert(expr.id, node_id); - self.diagnostic_metadata.unused_labels.remove(&node_id); - } + if let Some(node_id) = self.resolve_label(label.ident) { + // Since this res is a label, it is never read. + self.r.label_res_map.insert(expr.id, node_id); + self.diagnostic_metadata.unused_labels.remove(&node_id); } // visit `break` argument if any @@ -2144,21 +2170,26 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // closure are detected as upvars rather than normal closure arg usages. ExprKind::Closure(_, Async::Yes { .. }, _, ref fn_decl, ref body, _span) => { self.with_rib(ValueNS, NormalRibKind, |this| { - // Resolve arguments: - this.resolve_params(&fn_decl.inputs); - // No need to resolve return type -- - // the outer closure return type is `FnRetTy::Default`. + this.with_label_rib(ClosureOrAsyncRibKind, |this| { + // Resolve arguments: + this.resolve_params(&fn_decl.inputs); + // No need to resolve return type -- + // the outer closure return type is `FnRetTy::Default`. - // Now resolve the inner closure - { - // No need to resolve arguments: the inner closure has none. - // Resolve the return type: - visit::walk_fn_ret_ty(this, &fn_decl.output); - // Resolve the body - this.visit_expr(body); - } + // Now resolve the inner closure + { + // No need to resolve arguments: the inner closure has none. + // Resolve the return type: + visit::walk_fn_ret_ty(this, &fn_decl.output); + // Resolve the body + this.visit_expr(body); + } + }) }); } + ExprKind::Async(..) | ExprKind::Closure(..) => { + self.with_label_rib(ClosureOrAsyncRibKind, |this| visit::walk_expr(this, expr)); + } _ => { visit::walk_expr(self, expr); } diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index 1bce160acb6..e469ca80c59 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -1,4 +1,4 @@ -use crate::diagnostics::{ImportSuggestion, TypoSuggestion}; +use crate::diagnostics::{ImportSuggestion, LabelSuggestion, TypoSuggestion}; use crate::late::lifetimes::{ElisionFailureInfo, LifetimeContext}; use crate::late::{LateResolutionVisitor, RibKind}; use crate::path_names_to_string; @@ -992,6 +992,32 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { } None } + + /// Given the target `label`, search the `rib_index`th label rib for similarly named labels, + /// optionally returning the closest match and whether it is reachable. + crate fn suggestion_for_label_in_rib( + &self, + rib_index: usize, + label: Ident, + ) -> Option<LabelSuggestion> { + // Are ribs from this `rib_index` within scope? + let within_scope = self.is_label_valid_from_rib(rib_index); + + let rib = &self.label_ribs[rib_index]; + let names = rib + .bindings + .iter() + .filter(|(id, _)| id.span.ctxt() == label.span.ctxt()) + .map(|(id, _)| &id.name); + + find_best_match_for_name(names, &label.as_str(), None).map(|symbol| { + // Upon finding a similar name, get the ident that it was from - the span + // contained within helps make a useful diagnostic. In addition, determine + // whether this candidate is within scope. + let (ident, _) = rib.bindings.iter().find(|(ident, _)| ident.name == symbol).unwrap(); + (*ident, within_scope) + }) + } } impl<'tcx> LifetimeContext<'_, 'tcx> { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index dccaf76723a..f3a1934abc9 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -61,7 +61,7 @@ use std::collections::BTreeSet; use std::{cmp, fmt, iter, ptr}; use diagnostics::{extend_span_to_previous_binding, find_span_of_binding_until_next_binding}; -use diagnostics::{ImportSuggestion, Suggestion}; +use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion}; use imports::{Import, ImportKind, ImportResolver, NameResolution}; use late::{HasGenericParams, PathSource, Rib, RibKind::*}; use macros::{MacroRulesBinding, MacroRulesScope}; @@ -197,7 +197,7 @@ enum ResolutionError<'a> { /// Error E0416: identifier is bound more than once in the same pattern. IdentifierBoundMoreThanOnceInSamePattern(&'a str), /// Error E0426: use of undeclared label. - UndeclaredLabel(&'a str, Option<Symbol>), + UndeclaredLabel { name: &'a str, suggestion: Option<LabelSuggestion> }, /// Error E0429: `self` imports are only allowed within a `{ }` list. SelfImportsOnlyAllowedWithin { root: bool, span_with_rename: Span }, /// Error E0430: `self` import can only appear once in the list. @@ -216,6 +216,8 @@ enum ResolutionError<'a> { ForwardDeclaredTyParam, // FIXME(const_generics:defaults) /// Error E0735: type parameters with a default cannot use `Self` SelfInTyParamDefault, + /// Error E0767: use of unreachable label + UnreachableLabel { name: &'a str, definition_span: Span, suggestion: Option<LabelSuggestion> }, } enum VisResolutionError<'a> { @@ -2453,6 +2455,7 @@ impl<'a> Resolver<'a> { for rib in ribs { match rib.kind { NormalRibKind + | ClosureOrAsyncRibKind | ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind => { @@ -2488,6 +2491,7 @@ impl<'a> Resolver<'a> { for rib in ribs { let has_generic_params = match rib.kind { NormalRibKind + | ClosureOrAsyncRibKind | AssocItemRibKind | ModuleRibKind(..) | MacroDefinition(..) diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index e63e31e03c9..bd3724449fa 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -72,12 +72,12 @@ macro_rules! access_from_vis { }; } -pub struct DumpVisitor<'l, 'tcx> { - pub save_ctxt: SaveContext<'l, 'tcx>, +pub struct DumpVisitor<'tcx> { + pub save_ctxt: SaveContext<'tcx>, tcx: TyCtxt<'tcx>, dumper: Dumper, - span: SpanUtils<'l>, + span: SpanUtils<'tcx>, // Set of macro definition (callee) spans, and the set // of macro use (callsite) spans. We store these to ensure // we only write one macro def per unique macro definition, and @@ -86,8 +86,8 @@ pub struct DumpVisitor<'l, 'tcx> { // macro_calls: FxHashSet<Span>, } -impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { - pub fn new(save_ctxt: SaveContext<'l, 'tcx>) -> DumpVisitor<'l, 'tcx> { +impl<'tcx> DumpVisitor<'tcx> { + pub fn new(save_ctxt: SaveContext<'tcx>) -> DumpVisitor<'tcx> { let span_utils = SpanUtils::new(&save_ctxt.tcx.sess); let dumper = Dumper::new(save_ctxt.config.clone()); DumpVisitor { @@ -109,15 +109,15 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { F: FnOnce(&mut Self), { let tables = if self.tcx.has_typeck_tables(item_def_id) { - self.tcx.typeck_tables_of(item_def_id) + Some(self.tcx.typeck_tables_of(item_def_id)) } else { - self.save_ctxt.empty_tables + None }; - let old_tables = self.save_ctxt.tables; - self.save_ctxt.tables = tables; + let old_maybe_typeck_tables = self.save_ctxt.maybe_typeck_tables; + self.save_ctxt.maybe_typeck_tables = tables; f(self); - self.save_ctxt.tables = old_tables; + self.save_ctxt.maybe_typeck_tables = old_maybe_typeck_tables; } fn span_from_span(&self, span: Span) -> SpanData { @@ -226,7 +226,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { collector.visit_pat(&arg.pat); for (hir_id, ident, ..) in collector.collected_idents { - let typ = match self.save_ctxt.tables.node_type_opt(hir_id) { + let typ = match self.save_ctxt.tables().node_type_opt(hir_id) { Some(s) => s.to_string(), None => continue, }; @@ -859,7 +859,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { match p.kind { hir::PatKind::Struct(ref _path, fields, _) => { // FIXME do something with _path? - let adt = match self.save_ctxt.tables.node_type_opt(p.hir_id) { + let adt = match self.save_ctxt.tables().node_type_opt(p.hir_id) { Some(ty) if ty.ty_adt_def().is_some() => ty.ty_adt_def().unwrap(), _ => { intravisit::walk_pat(self, p); @@ -900,7 +900,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { Res::Local(hir_id) => { let typ = self .save_ctxt - .tables + .tables() .node_type_opt(hir_id) .map(|t| t.to_string()) .unwrap_or_default(); @@ -1160,7 +1160,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { } } -impl<'l, 'tcx> Visitor<'tcx> for DumpVisitor<'l, 'tcx> { +impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { type Map = Map<'tcx>; fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> { @@ -1393,7 +1393,7 @@ impl<'l, 'tcx> Visitor<'tcx> for DumpVisitor<'l, 'tcx> { match ex.kind { hir::ExprKind::Struct(ref path, ref fields, ref base) => { let hir_expr = self.save_ctxt.tcx.hir().expect_expr(ex.hir_id); - let adt = match self.save_ctxt.tables.expr_ty_opt(&hir_expr) { + let adt = match self.save_ctxt.tables().expr_ty_opt(&hir_expr) { Some(ty) if ty.ty_adt_def().is_some() => ty.ty_adt_def().unwrap(), _ => { intravisit::walk_expr(self, ex); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index f5c3e84c624..5ecb256719f 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -1,6 +1,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(nll)] #![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(track_caller))] #![recursion_limit = "256"] mod dump_visitor; @@ -47,13 +48,10 @@ use rls_data::{ use log::{debug, error, info}; -pub struct SaveContext<'l, 'tcx> { +pub struct SaveContext<'tcx> { tcx: TyCtxt<'tcx>, - tables: &'l ty::TypeckTables<'tcx>, - /// Used as a fallback when nesting the typeck tables during item processing - /// (if these are not available for that item, e.g. don't own a body) - empty_tables: &'l ty::TypeckTables<'tcx>, - access_levels: &'l AccessLevels, + maybe_typeck_tables: Option<&'tcx ty::TypeckTables<'tcx>>, + access_levels: &'tcx AccessLevels, span_utils: SpanUtils<'tcx>, config: Config, impl_counter: Cell<u32>, @@ -66,7 +64,15 @@ pub enum Data { RelationData(Relation, Impl), } -impl<'l, 'tcx> SaveContext<'l, 'tcx> { +impl<'tcx> SaveContext<'tcx> { + /// Gets the type-checking side-tables for the current body. + /// As this will ICE if called outside bodies, only call when working with + /// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies). + #[track_caller] + fn tables(&self) -> &'tcx ty::TypeckTables<'tcx> { + self.maybe_typeck_tables.expect("`SaveContext::tables` called outside of body") + } + fn span_from_span(&self, span: Span) -> SpanData { use rls_span::{Column, Row}; @@ -518,13 +524,13 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { } pub fn get_expr_data(&self, expr: &hir::Expr<'_>) -> Option<Data> { - let ty = self.tables.expr_ty_adjusted_opt(expr)?; + let ty = self.tables().expr_ty_adjusted_opt(expr)?; if matches!(ty.kind, ty::Error(_)) { return None; } match expr.kind { hir::ExprKind::Field(ref sub_ex, ident) => { - match self.tables.expr_ty_adjusted(&sub_ex).kind { + match self.tables().expr_ty_adjusted(&sub_ex).kind { ty::Adt(def, _) if !def.is_enum() => { let variant = &def.non_enum_variant(); filter!(self.span_utils, ident.span); @@ -569,7 +575,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { } } hir::ExprKind::MethodCall(ref seg, ..) => { - let method_id = match self.tables.type_dependent_def_id(expr.hir_id) { + let method_id = match self.tables().type_dependent_def_id(expr.hir_id) { Some(id) => id, None => { debug!("could not resolve method id for {:?}", expr); @@ -618,7 +624,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { }, Node::Expr(&hir::Expr { kind: hir::ExprKind::Struct(ref qpath, ..), .. }) => { - self.tables.qpath_res(qpath, hir_id) + self.tables().qpath_res(qpath, hir_id) } Node::Expr(&hir::Expr { kind: hir::ExprKind::Path(ref qpath), .. }) @@ -629,9 +635,12 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { | hir::PatKind::TupleStruct(ref qpath, ..), .. }) - | Node::Ty(&hir::Ty { kind: hir::TyKind::Path(ref qpath), .. }) => { - self.tables.qpath_res(qpath, hir_id) - } + | Node::Ty(&hir::Ty { kind: hir::TyKind::Path(ref qpath), .. }) => match qpath { + hir::QPath::Resolved(_, path) => path.res, + hir::QPath::TypeRelative(..) => self + .maybe_typeck_tables + .map_or(Res::Err, |tables| tables.qpath_res(qpath, hir_id)), + }, Node::Binding(&hir::Pat { kind: hir::PatKind::Binding(_, canonical_id, ..), .. @@ -908,7 +917,7 @@ impl<'l> Visitor<'l> for PathCollector<'l> { /// Defines what to do with the results of saving the analysis. pub trait SaveHandler { - fn save(&mut self, save_ctxt: &SaveContext<'_, '_>, analysis: &Analysis); + fn save(&mut self, save_ctxt: &SaveContext<'_>, analysis: &Analysis); } /// Dump the save-analysis results to a file. @@ -922,7 +931,7 @@ impl<'a> DumpHandler<'a> { DumpHandler { odir, cratename: cratename.to_owned() } } - fn output_file(&self, ctx: &SaveContext<'_, '_>) -> (BufWriter<File>, PathBuf) { + fn output_file(&self, ctx: &SaveContext<'_>) -> (BufWriter<File>, PathBuf) { let sess = &ctx.tcx.sess; let file_name = match ctx.config.output_file { Some(ref s) => PathBuf::from(s), @@ -958,7 +967,7 @@ impl<'a> DumpHandler<'a> { } impl SaveHandler for DumpHandler<'_> { - fn save(&mut self, save_ctxt: &SaveContext<'_, '_>, analysis: &Analysis) { + fn save(&mut self, save_ctxt: &SaveContext<'_>, analysis: &Analysis) { let sess = &save_ctxt.tcx.sess; let (output, file_name) = self.output_file(&save_ctxt); if let Err(e) = serde_json::to_writer(output, &analysis) { @@ -977,7 +986,7 @@ pub struct CallbackHandler<'b> { } impl SaveHandler for CallbackHandler<'_> { - fn save(&mut self, _: &SaveContext<'_, '_>, analysis: &Analysis) { + fn save(&mut self, _: &SaveContext<'_>, analysis: &Analysis) { (self.callback)(analysis) } } @@ -1001,8 +1010,7 @@ pub fn process_crate<'l, 'tcx, H: SaveHandler>( let save_ctxt = SaveContext { tcx, - tables: &ty::TypeckTables::empty(None), - empty_tables: &ty::TypeckTables::empty(None), + maybe_typeck_tables: None, access_levels: &access_levels, span_utils: SpanUtils::new(&tcx.sess), config: find_config(config), @@ -1057,7 +1065,7 @@ fn id_from_def_id(id: DefId) -> rls_data::Id { rls_data::Id { krate: id.krate.as_u32(), index: id.index.as_u32() } } -fn id_from_hir_id(id: hir::HirId, scx: &SaveContext<'_, '_>) -> rls_data::Id { +fn id_from_hir_id(id: hir::HirId, scx: &SaveContext<'_>) -> rls_data::Id { let def_id = scx.tcx.hir().opt_local_def_id(id); def_id.map(|id| id_from_def_id(id.to_def_id())).unwrap_or_else(|| { // Create a *fake* `DefId` out of a `HirId` by combining the owner @@ -1075,10 +1083,7 @@ fn null_id() -> rls_data::Id { rls_data::Id { krate: u32::MAX, index: u32::MAX } } -fn lower_attributes( - attrs: Vec<ast::Attribute>, - scx: &SaveContext<'_, '_>, -) -> Vec<rls_data::Attribute> { +fn lower_attributes(attrs: Vec<ast::Attribute>, scx: &SaveContext<'_>) -> Vec<rls_data::Attribute> { attrs .into_iter() // Only retain real attributes. Doc comments are lowered separately. diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index cd2a5deeb2d..33355c4c558 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -36,7 +36,7 @@ use rustc_hir_pretty::id_to_string; use rustc_hir_pretty::{bounds_to_string, path_segment_to_string, path_to_string, ty_to_string}; use rustc_span::symbol::{Ident, Symbol}; -pub fn item_signature(item: &hir::Item<'_>, scx: &SaveContext<'_, '_>) -> Option<Signature> { +pub fn item_signature(item: &hir::Item<'_>, scx: &SaveContext<'_>) -> Option<Signature> { if !scx.config.signatures { return None; } @@ -45,7 +45,7 @@ pub fn item_signature(item: &hir::Item<'_>, scx: &SaveContext<'_, '_>) -> Option pub fn foreign_item_signature( item: &hir::ForeignItem<'_>, - scx: &SaveContext<'_, '_>, + scx: &SaveContext<'_>, ) -> Option<Signature> { if !scx.config.signatures { return None; @@ -55,10 +55,7 @@ pub fn foreign_item_signature( /// Signature for a struct or tuple field declaration. /// Does not include a trailing comma. -pub fn field_signature( - field: &hir::StructField<'_>, - scx: &SaveContext<'_, '_>, -) -> Option<Signature> { +pub fn field_signature(field: &hir::StructField<'_>, scx: &SaveContext<'_>) -> Option<Signature> { if !scx.config.signatures { return None; } @@ -66,10 +63,7 @@ pub fn field_signature( } /// Does not include a trailing comma. -pub fn variant_signature( - variant: &hir::Variant<'_>, - scx: &SaveContext<'_, '_>, -) -> Option<Signature> { +pub fn variant_signature(variant: &hir::Variant<'_>, scx: &SaveContext<'_>) -> Option<Signature> { if !scx.config.signatures { return None; } @@ -81,7 +75,7 @@ pub fn method_signature( ident: Ident, generics: &hir::Generics<'_>, m: &hir::FnSig<'_>, - scx: &SaveContext<'_, '_>, + scx: &SaveContext<'_>, ) -> Option<Signature> { if !scx.config.signatures { return None; @@ -94,7 +88,7 @@ pub fn assoc_const_signature( ident: Symbol, ty: &hir::Ty<'_>, default: Option<&hir::Expr<'_>>, - scx: &SaveContext<'_, '_>, + scx: &SaveContext<'_>, ) -> Option<Signature> { if !scx.config.signatures { return None; @@ -107,7 +101,7 @@ pub fn assoc_type_signature( ident: Ident, bounds: Option<hir::GenericBounds<'_>>, default: Option<&hir::Ty<'_>>, - scx: &SaveContext<'_, '_>, + scx: &SaveContext<'_>, ) -> Option<Signature> { if !scx.config.signatures { return None; @@ -118,7 +112,7 @@ pub fn assoc_type_signature( type Result = std::result::Result<Signature, &'static str>; trait Sig { - fn make(&self, offset: usize, id: Option<hir::HirId>, scx: &SaveContext<'_, '_>) -> Result; + fn make(&self, offset: usize, id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result; } fn extend_sig( @@ -154,12 +148,7 @@ fn text_sig(text: String) -> Signature { } impl<'hir> Sig for hir::Ty<'hir> { - fn make( - &self, - offset: usize, - _parent_id: Option<hir::HirId>, - scx: &SaveContext<'_, '_>, - ) -> Result { + fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result { let id = Some(self.hir_id); match self.kind { hir::TyKind::Slice(ref ty) => { @@ -334,12 +323,7 @@ impl<'hir> Sig for hir::Ty<'hir> { } impl<'hir> Sig for hir::Item<'hir> { - fn make( - &self, - offset: usize, - _parent_id: Option<hir::HirId>, - scx: &SaveContext<'_, '_>, - ) -> Result { + fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result { let id = Some(self.hir_id); match self.kind { @@ -574,7 +558,7 @@ impl<'hir> Sig for hir::Item<'hir> { } impl<'hir> Sig for hir::Path<'hir> { - fn make(&self, offset: usize, id: Option<hir::HirId>, scx: &SaveContext<'_, '_>) -> Result { + fn make(&self, offset: usize, id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result { let res = scx.get_path_res(id.ok_or("Missing id for Path")?); let (name, start, end) = match res { @@ -608,12 +592,7 @@ impl<'hir> Sig for hir::Path<'hir> { // This does not cover the where clause, which must be processed separately. impl<'hir> Sig for hir::Generics<'hir> { - fn make( - &self, - offset: usize, - _parent_id: Option<hir::HirId>, - scx: &SaveContext<'_, '_>, - ) -> Result { + fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result { if self.params.is_empty() { return Ok(text_sig(String::new())); } @@ -671,12 +650,7 @@ impl<'hir> Sig for hir::Generics<'hir> { } impl<'hir> Sig for hir::StructField<'hir> { - fn make( - &self, - offset: usize, - _parent_id: Option<hir::HirId>, - scx: &SaveContext<'_, '_>, - ) -> Result { + fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result { let mut text = String::new(); text.push_str(&self.ident.to_string()); @@ -696,12 +670,7 @@ impl<'hir> Sig for hir::StructField<'hir> { } impl<'hir> Sig for hir::Variant<'hir> { - fn make( - &self, - offset: usize, - parent_id: Option<hir::HirId>, - scx: &SaveContext<'_, '_>, - ) -> Result { + fn make(&self, offset: usize, parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result { let mut text = self.ident.to_string(); match self.data { hir::VariantData::Struct(fields, r) => { @@ -760,12 +729,7 @@ impl<'hir> Sig for hir::Variant<'hir> { } impl<'hir> Sig for hir::ForeignItem<'hir> { - fn make( - &self, - offset: usize, - _parent_id: Option<hir::HirId>, - scx: &SaveContext<'_, '_>, - ) -> Result { + fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result { let id = Some(self.hir_id); match self.kind { hir::ForeignItemKind::Fn(decl, _, ref generics) => { @@ -839,7 +803,7 @@ fn name_and_generics( generics: &hir::Generics<'_>, id: hir::HirId, name: Ident, - scx: &SaveContext<'_, '_>, + scx: &SaveContext<'_>, ) -> Result { let name = name.to_string(); let def = SigElement { @@ -859,7 +823,7 @@ fn make_assoc_type_signature( ident: Ident, bounds: Option<hir::GenericBounds<'_>>, default: Option<&hir::Ty<'_>>, - scx: &SaveContext<'_, '_>, + scx: &SaveContext<'_>, ) -> Result { let mut text = "type ".to_owned(); let name = ident.to_string(); @@ -891,7 +855,7 @@ fn make_assoc_const_signature( ident: Symbol, ty: &hir::Ty<'_>, default: Option<&hir::Expr<'_>>, - scx: &SaveContext<'_, '_>, + scx: &SaveContext<'_>, ) -> Result { let mut text = "const ".to_owned(); let name = ident.to_string(); @@ -922,7 +886,7 @@ fn make_method_signature( ident: Ident, generics: &hir::Generics<'_>, m: &hir::FnSig<'_>, - scx: &SaveContext<'_, '_>, + scx: &SaveContext<'_>, ) -> Result { // FIXME code dup with function signature let mut text = String::new(); diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs index 9337f241d70..2ad7d09cbf4 100644 --- a/src/librustc_session/options.rs +++ b/src/librustc_session/options.rs @@ -881,8 +881,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, (default: no)"), instrument_coverage: bool = (false, parse_bool, [TRACKED], "instrument the generated code with LLVM code region counters to (in the \ - future) generate coverage reports (default: no; note, the compiler build \ - config must include `profiler = true`)"), + future) generate coverage reports; disables/overrides some optimization \ + options (note, the compiler build config must include `profiler = true`) \ + (default: no)"), instrument_mcount: bool = (false, parse_bool, [TRACKED], "insert function instrument code for mcount-based tracing (default: no)"), keep_hygiene_data: bool = (false, parse_bool, [UNTRACKED], @@ -958,9 +959,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "print the LLVM optimization passes being run (default: no)"), print_mono_items: Option<String> = (None, parse_opt_string, [UNTRACKED], "print the result of the monomorphization collection pass"), - print_region_graph: bool = (false, parse_bool, [UNTRACKED], - "prints region inference graph. \ - Use with RUST_REGION_GRAPH=help for more info (default: no)"), print_type_sizes: bool = (false, parse_bool, [UNTRACKED], "print layout information for each type encountered (default: no)"), profile: bool = (false, parse_bool, [TRACKED], diff --git a/src/librustc_span/hygiene.rs b/src/librustc_span/hygiene.rs index 60bbdd0495c..90f4cc09660 100644 --- a/src/librustc_span/hygiene.rs +++ b/src/librustc_span/hygiene.rs @@ -395,10 +395,11 @@ pub fn debug_hygiene_data(verbose: bool) -> String { data.expn_data.iter().enumerate().for_each(|(id, expn_info)| { let expn_info = expn_info.as_ref().expect("no expansion data for an expansion ID"); s.push_str(&format!( - "\n{}: parent: {:?}, call_site_ctxt: {:?}, kind: {:?}", + "\n{}: parent: {:?}, call_site_ctxt: {:?}, def_site_ctxt: {:?}, kind: {:?}", id, expn_info.parent, expn_info.call_site.ctxt(), + expn_info.def_site.ctxt(), expn_info.kind, )); }); diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs index 6dcb1430cdc..046554067f4 100644 --- a/src/librustc_span/lib.rs +++ b/src/librustc_span/lib.rs @@ -309,7 +309,9 @@ impl Ord for Span { } } -/// A collection of spans. Spans have two orthogonal attributes: +/// A collection of `Span`s. +/// +/// Spans have two orthogonal attributes: /// /// - They can be *primary spans*. In this case they are the locus of /// the error, and would be rendered with `^^^`. diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs index 4b5bce1db26..e062c7766e7 100644 --- a/src/librustc_span/source_map.rs +++ b/src/librustc_span/source_map.rs @@ -40,6 +40,41 @@ pub fn original_sp(sp: Span, enclosing_sp: Span) -> Span { } } +pub mod monotonic { + use std::ops::{Deref, DerefMut}; + + /// A `MonotonicVec` is a `Vec` which can only be grown. + /// Once inserted, an element can never be removed or swapped, + /// guaranteeing that any indices into a `MonotonicVec` are stable + // This is declared in its own module to ensure that the private + // field is inaccessible + pub struct MonotonicVec<T>(Vec<T>); + impl<T> MonotonicVec<T> { + pub fn new(val: Vec<T>) -> MonotonicVec<T> { + MonotonicVec(val) + } + + pub fn push(&mut self, val: T) { + self.0.push(val); + } + } + + impl<T> Default for MonotonicVec<T> { + fn default() -> Self { + MonotonicVec::new(vec![]) + } + } + + impl<T> Deref for MonotonicVec<T> { + type Target = Vec<T>; + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + impl<T> !DerefMut for MonotonicVec<T> {} +} + #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, HashStable_Generic)] pub struct Spanned<T> { pub node: T, @@ -125,7 +160,7 @@ impl StableSourceFileId { #[derive(Default)] pub(super) struct SourceMapFiles { - source_files: Vec<Lrc<SourceFile>>, + source_files: monotonic::MonotonicVec<Lrc<SourceFile>>, stable_id_to_source_file: FxHashMap<StableSourceFileId, Lrc<SourceFile>>, } @@ -199,7 +234,9 @@ impl SourceMap { Ok(bytes) } - pub fn files(&self) -> MappedLockGuard<'_, Vec<Lrc<SourceFile>>> { + // By returning a `MonotonicVec`, we ensure that consumers cannot invalidate + // any existing indices pointing into `files`. + pub fn files(&self) -> MappedLockGuard<'_, monotonic::MonotonicVec<Lrc<SourceFile>>> { LockGuard::map(self.files.borrow(), |files| &mut files.source_files) } @@ -912,6 +949,8 @@ impl SourceMap { } // Returns the index of the `SourceFile` (in `self.files`) that contains `pos`. + // This index is guaranteed to be valid for the lifetime of this `SourceMap`, + // since `source_files` is a `MonotonicVec` pub fn lookup_source_file_idx(&self, pos: BytePos) -> usize { self.files .borrow() diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index 857734037af..12ac2ed1c0b 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -242,6 +242,9 @@ symbols! { core, core_intrinsics, count_code_region, + coverage_counter_add, + coverage_counter_subtract, + coverage_unreachable, crate_id, crate_in_paths, crate_local, @@ -401,6 +404,7 @@ symbols! { infer_outlives_requirements, infer_static_outlives_requirements, inline, + Input, intel, into_iter, IntoIterator, @@ -427,6 +431,7 @@ symbols! { lhs, lib, lifetime, + likely, line, link, linkage, @@ -512,6 +517,7 @@ symbols! { None, non_exhaustive, non_modrs_mods, + nontrapping_fptoint: "nontrapping-fptoint", noreturn, no_niche, no_sanitize, @@ -588,6 +594,8 @@ symbols! { proc_macro_mod, proc_macro_non_items, proc_macro_path_invoc, + ProceduralMasqueradeDummyType, + ProcMacroHack, profiler_builtins, profiler_runtime, ptr_guaranteed_eq, @@ -813,6 +821,7 @@ symbols! { underscore_lifetimes, uniform_paths, universal_impl_trait, + unlikely, unmarked_api, unreachable_code, unrestricted_attribute_tokens, diff --git a/src/librustc_symbol_mangling/v0.rs b/src/librustc_symbol_mangling/v0.rs index 7d117b77cf5..ecf27fbf542 100644 --- a/src/librustc_symbol_mangling/v0.rs +++ b/src/librustc_symbol_mangling/v0.rs @@ -219,7 +219,7 @@ impl SymbolMangler<'tcx> { lifetime_depths.end += lifetimes; self.binders.push(BinderLevel { lifetime_depths }); - self = print_value(self, value.skip_binder())?; + self = print_value(self, value.as_ref().skip_binder())?; self.binders.pop(); Ok(self) diff --git a/src/librustc_target/spec/cloudabi_base.rs b/src/librustc_target/spec/cloudabi_base.rs index 3659c9ecdfc..39039435f58 100644 --- a/src/librustc_target/spec/cloudabi_base.rs +++ b/src/librustc_target/spec/cloudabi_base.rs @@ -7,7 +7,6 @@ pub fn opts() -> TargetOptions { vec![ "-Wl,-Bstatic".to_string(), "-Wl,--no-dynamic-linker".to_string(), - "-Wl,--eh-frame-hdr".to_string(), "-Wl,--gc-sections".to_string(), ], ); diff --git a/src/librustc_target/spec/fuchsia_base.rs b/src/librustc_target/spec/fuchsia_base.rs index dd55788b664..6f432dc1171 100644 --- a/src/librustc_target/spec/fuchsia_base.rs +++ b/src/librustc_target/spec/fuchsia_base.rs @@ -6,7 +6,6 @@ pub fn opts() -> TargetOptions { LinkerFlavor::Lld(LldFlavor::Ld), vec![ "--build-id".to_string(), - "--eh-frame-hdr".to_string(), "--hash-style=gnu".to_string(), "-z".to_string(), "max-page-size=4096".to_string(), diff --git a/src/librustc_target/spec/linux_musl_base.rs b/src/librustc_target/spec/linux_musl_base.rs index 0fdd8760806..b90e91d2901 100644 --- a/src/librustc_target/spec/linux_musl_base.rs +++ b/src/librustc_target/spec/linux_musl_base.rs @@ -1,15 +1,9 @@ use crate::spec::crt_objects::{self, CrtObjectsFallback}; -use crate::spec::{LinkerFlavor, TargetOptions}; +use crate::spec::TargetOptions; pub fn opts() -> TargetOptions { let mut base = super::linux_base::opts(); - // At least when this was tested, the linker would not add the - // `GNU_EH_FRAME` program header to executables generated, which is required - // when unwinding to locate the unwinding information. I'm not sure why this - // argument is *not* necessary for normal builds, but it can't hurt! - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,--eh-frame-hdr".to_string()); - base.pre_link_objects_fallback = crt_objects::pre_musl_fallback(); base.post_link_objects_fallback = crt_objects::post_musl_fallback(); base.crt_objects_fallback = Some(CrtObjectsFallback::Musl); diff --git a/src/librustc_target/spec/mipsel_sony_psp.rs b/src/librustc_target/spec/mipsel_sony_psp.rs index 0c74454d0c5..b3bda97c8a5 100644 --- a/src/librustc_target/spec/mipsel_sony_psp.rs +++ b/src/librustc_target/spec/mipsel_sony_psp.rs @@ -6,10 +6,7 @@ const LINKER_SCRIPT: &str = include_str!("./mipsel_sony_psp_linker_script.ld"); pub fn target() -> TargetResult { let mut pre_link_args = LinkArgs::new(); - pre_link_args.insert( - LinkerFlavor::Lld(LldFlavor::Ld), - vec!["--eh-frame-hdr".to_string(), "--emit-relocs".to_string()], - ); + pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["--emit-relocs".to_string()]); Ok(Target { llvm_target: "mipsel-sony-psp".to_string(), diff --git a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs index d01545619c8..3b5233a3e67 100644 --- a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs +++ b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs @@ -5,7 +5,6 @@ use super::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions}; pub fn target() -> Result<Target, String> { const PRE_LINK_ARGS: &[&str] = &[ "--as-needed", - "--eh-frame-hdr", "-z", "noexecstack", "-e", diff --git a/src/librustc_trait_selection/opaque_types.rs b/src/librustc_trait_selection/opaque_types.rs index adccdd0b261..ce478de7c75 100644 --- a/src/librustc_trait_selection/opaque_types.rs +++ b/src/librustc_trait_selection/opaque_types.rs @@ -691,7 +691,7 @@ where OP: FnMut(ty::Region<'tcx>), { fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> bool { - t.skip_binder().visit_with(self); + t.as_ref().skip_binder().visit_with(self); false // keep visiting } diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs index fd0c1a54d27..ad6e81ed3e8 100644 --- a/src/librustc_trait_selection/traits/error_reporting/mod.rs +++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs @@ -429,6 +429,24 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ); } + let is_fn_trait = [ + self.tcx.lang_items().fn_trait(), + self.tcx.lang_items().fn_mut_trait(), + self.tcx.lang_items().fn_once_trait(), + ] + .contains(&Some(trait_ref.def_id())); + let is_target_feature_fn = + if let ty::FnDef(def_id, _) = trait_ref.skip_binder().self_ty().kind { + !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty() + } else { + false + }; + if is_fn_trait && is_target_feature_fn { + err.note( + "`#[target_feature]` functions do not implement the `Fn` traits", + ); + } + // Try to report a help message if !trait_ref.has_infer_types_or_consts() && self.predicate_can_apply(obligation.param_env, trait_ref) @@ -1569,7 +1587,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { // no need to overload user in such cases return; } - let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder(); + let SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder(); // both must be type variables, or the other would've been instantiated assert!(a.is_ty_var() && b.is_ty_var()); self.need_type_info_err(body_id, span, a, ErrorCode::E0282) diff --git a/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs b/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs index fd87759a762..ec51dddc2c8 100644 --- a/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs +++ b/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs @@ -122,7 +122,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ) -> OnUnimplementedNote { let def_id = self.impl_similar_to(trait_ref, obligation).unwrap_or_else(|| trait_ref.def_id()); - let trait_ref = *trait_ref.skip_binder(); + let trait_ref = trait_ref.skip_binder(); let mut flags = vec![]; flags.push(( @@ -219,7 +219,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } } if let ty::Dynamic(traits, _) = self_ty.kind { - for t in *traits.skip_binder() { + for t in traits.skip_binder() { if let ty::ExistentialPredicate::Trait(trait_ref) = t { flags.push((sym::_Self, Some(self.tcx.def_path_str(trait_ref.def_id)))) } diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 176bd90303d..cdfe5f9f92d 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -1179,7 +1179,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ) -> DiagnosticBuilder<'tcx> { crate fn build_fn_sig_string<'tcx>( tcx: TyCtxt<'tcx>, - trait_ref: &ty::TraitRef<'tcx>, + trait_ref: ty::TraitRef<'tcx>, ) -> String { let inputs = trait_ref.substs.type_at(1); let sig = if let ty::Tuple(inputs) = inputs.kind { @@ -1360,7 +1360,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } ty::GeneratorWitness(..) => {} _ if generator.is_none() => { - trait_ref = Some(*derived_obligation.parent_trait_ref.skip_binder()); + trait_ref = Some(derived_obligation.parent_trait_ref.skip_binder()); target_ty = Some(ty); } _ => {} @@ -1407,7 +1407,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ); let query_tables; let tables: &TypeckTables<'tcx> = match &in_progress_tables { - Some(t) if t.hir_owner.map(|owner| owner.to_def_id()) == Some(generator_did_root) => t, + Some(t) if t.hir_owner.to_def_id() == generator_did_root => t, _ => { query_tables = self.tcx.typeck_tables_of(generator_did.expect_local()); &query_tables diff --git a/src/librustc_trait_selection/traits/select/candidate_assembly.rs b/src/librustc_trait_selection/traits/select/candidate_assembly.rs index 4dab5814f7b..597a7a58022 100644 --- a/src/librustc_trait_selection/traits/select/candidate_assembly.rs +++ b/src/librustc_trait_selection/traits/select/candidate_assembly.rs @@ -220,7 +220,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Okay to skip binder because the substs on generator types never // touch bound regions, they just capture the in-scope // type/region parameters. - let self_ty = *obligation.self_ty().skip_binder(); + let self_ty = obligation.self_ty().skip_binder(); match self_ty.kind { ty::Generator(..) => { debug!( @@ -299,14 +299,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } // Okay to skip binder because what we are inspecting doesn't involve bound regions. - let self_ty = *obligation.self_ty().skip_binder(); + let self_ty = obligation.self_ty().skip_binder(); match self_ty.kind { ty::Infer(ty::TyVar(_)) => { debug!("assemble_fn_pointer_candidates: ambiguous self-type"); candidates.ambiguous = true; // Could wind up being a fn() type. } // Provide an impl, but only for suitable `fn` pointers. - ty::FnDef(..) | ty::FnPtr(_) => { + ty::FnPtr(_) => { if let ty::FnSig { unsafety: hir::Unsafety::Normal, abi: Abi::Rust, @@ -317,6 +317,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates.vec.push(FnPointerCandidate); } } + // Provide an impl for suitable functions, rejecting `#[target_feature]` functions (RFC 2396). + ty::FnDef(def_id, _) => { + if let ty::FnSig { + unsafety: hir::Unsafety::Normal, + abi: Abi::Rust, + c_variadic: false, + .. + } = self_ty.fn_sig(self.tcx()).skip_binder() + { + if self.tcx().codegen_fn_attrs(def_id).target_features.is_empty() { + candidates.vec.push(FnPointerCandidate); + } + } + } _ => {} } @@ -362,7 +376,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates: &mut SelectionCandidateSet<'tcx>, ) -> Result<(), SelectionError<'tcx>> { // Okay to skip binder here because the tests we do below do not involve bound regions. - let self_ty = *obligation.self_ty().skip_binder(); + let self_ty = obligation.self_ty().skip_binder(); debug!("assemble_candidates_from_auto_impls(self_ty={:?})", self_ty); let def_id = obligation.predicate.def_id(); @@ -583,7 +597,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates: &mut SelectionCandidateSet<'tcx>, ) -> Result<(), SelectionError<'tcx>> { // Okay to skip binder here because the tests we do below do not involve bound regions. - let self_ty = *obligation.self_ty().skip_binder(); + let self_ty = obligation.self_ty().skip_binder(); debug!("assemble_candidates_for_trait_alias(self_ty={:?})", self_ty); let def_id = obligation.predicate.def_id(); diff --git a/src/librustc_trait_selection/traits/select/confirmation.rs b/src/librustc_trait_selection/traits/select/confirmation.rs index 834bf17227d..fa970589bbb 100644 --- a/src/librustc_trait_selection/traits/select/confirmation.rs +++ b/src/librustc_trait_selection/traits/select/confirmation.rs @@ -326,7 +326,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // probably flatten the binder from the obligation and the binder // from the object. Have to try to make a broken test case that // results. - let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); + let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); let poly_trait_ref = match self_ty.kind { ty::Dynamic(ref data, ..) => data .principal() @@ -379,7 +379,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!("confirm_fn_pointer_candidate({:?})", obligation); // Okay to skip binder; it is reintroduced below. - let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); + let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); let sig = self_ty.fn_sig(self.tcx()); let trait_ref = closure_trait_ref_and_return_type( self.tcx(), @@ -448,7 +448,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Okay to skip binder because the substs on generator types never // touch bound regions, they just capture the in-scope // type/region parameters. - let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); + let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); let (generator_def_id, substs) = match self_ty.kind { ty::Generator(id, substs, _) => (id, substs), _ => bug!("closure candidate for non-closure {:?}", obligation), @@ -497,7 +497,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Okay to skip binder because the substs on closure types never // touch bound regions, they just capture the in-scope // type/region parameters. - let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); + let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); let (closure_def_id, substs) = match self_ty.kind { ty::Closure(id, substs) => (id, substs), _ => bug!("closure candidate for non-closure {:?}", obligation), diff --git a/src/librustc_trait_selection/traits/select/mod.rs b/src/librustc_trait_selection/traits/select/mod.rs index cff5efbfd0f..c41a27c6f43 100644 --- a/src/librustc_trait_selection/traits/select/mod.rs +++ b/src/librustc_trait_selection/traits/select/mod.rs @@ -748,8 +748,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { && stack.iter().skip(1).any(|prev| { stack.obligation.param_env == prev.obligation.param_env && self.match_fresh_trait_refs( - &stack.fresh_trait_ref, - &prev.fresh_trait_ref, + stack.fresh_trait_ref, + prev.fresh_trait_ref, prev.obligation.param_env, ) }) @@ -1944,8 +1944,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn match_fresh_trait_refs( &self, - previous: &ty::PolyTraitRef<'tcx>, - current: &ty::PolyTraitRef<'tcx>, + previous: ty::PolyTraitRef<'tcx>, + current: ty::PolyTraitRef<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> bool { let mut matcher = ty::_match::Match::new(self.tcx(), param_env); diff --git a/src/librustc_trait_selection/traits/wf.rs b/src/librustc_trait_selection/traits/wf.rs index 1825c159ff3..ebff2dd9b23 100644 --- a/src/librustc_trait_selection/traits/wf.rs +++ b/src/librustc_trait_selection/traits/wf.rs @@ -695,7 +695,7 @@ pub fn object_region_bounds<'tcx>( let open_ty = tcx.mk_ty_infer(ty::FreshTy(0)); let predicates = existential_predicates.iter().filter_map(|predicate| { - if let ty::ExistentialPredicate::Projection(_) = *predicate.skip_binder() { + if let ty::ExistentialPredicate::Projection(_) = predicate.skip_binder() { None } else { Some(predicate.with_self_ty(tcx, open_ty)) diff --git a/src/librustc_traits/chalk/lowering.rs b/src/librustc_traits/chalk/lowering.rs index e09359b8b3f..ed021e5b9de 100644 --- a/src/librustc_traits/chalk/lowering.rs +++ b/src/librustc_traits/chalk/lowering.rs @@ -615,7 +615,7 @@ crate fn collect_bound_vars<'a, 'tcx, T: TypeFoldable<'tcx>>( ty: &'a Binder<T>, ) -> (T, chalk_ir::VariableKinds<RustInterner<'tcx>>, BTreeMap<DefId, u32>) { let mut bound_vars_collector = BoundVarsCollector::new(); - ty.skip_binder().visit_with(&mut bound_vars_collector); + ty.as_ref().skip_binder().visit_with(&mut bound_vars_collector); let mut parameters = bound_vars_collector.parameters; let named_parameters: BTreeMap<DefId, u32> = bound_vars_collector .named_parameters @@ -625,7 +625,7 @@ crate fn collect_bound_vars<'a, 'tcx, T: TypeFoldable<'tcx>>( .collect(); let mut bound_var_substitutor = NamedBoundVarSubstitutor::new(tcx, &named_parameters); - let new_ty = ty.skip_binder().fold_with(&mut bound_var_substitutor); + let new_ty = ty.as_ref().skip_binder().fold_with(&mut bound_var_substitutor); for var in named_parameters.values() { parameters.insert(*var, chalk_ir::VariableKind::Lifetime); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 1b08bf2fc77..5d1949626dd 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1802,7 +1802,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Calling `skip_binder` is okay because the predicates are re-bound. let regular_trait_predicates = existential_trait_refs - .map(|trait_ref| ty::ExistentialPredicate::Trait(*trait_ref.skip_binder())); + .map(|trait_ref| ty::ExistentialPredicate::Trait(trait_ref.skip_binder())); let auto_trait_predicates = auto_traits .into_iter() .map(|trait_ref| ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id())); @@ -1810,7 +1810,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .chain(auto_trait_predicates) .chain( existential_projections - .map(|x| ty::ExistentialPredicate::Projection(*x.skip_binder())), + .map(|x| ty::ExistentialPredicate::Projection(x.skip_binder())), ) .collect::<SmallVec<[_; 8]>>(); v.sort_by(|a, b| a.stable_cmp(tcx, b)); diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 6d09ddc925f..fce2b18b782 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -188,7 +188,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } ty::Infer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid), ty::FnPtr(sig) => { - let expected_sig = ExpectedSig { cause_span: None, sig: *sig.skip_binder() }; + let expected_sig = ExpectedSig { cause_span: None, sig: sig.skip_binder() }; (Some(expected_sig), Some(ty::ClosureKind::Fn)) } _ => (None, None), @@ -501,7 +501,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for ((hir_ty, &supplied_ty), expected_ty) in decl .inputs .iter() - .zip(*supplied_sig.inputs().skip_binder()) // binder moved to (*) below + .zip(supplied_sig.inputs().skip_binder()) // binder moved to (*) below .zip(expected_sigs.liberated_sig.inputs()) // `liberated_sig` is E'. { diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index b6cd8da2362..e6b3224050e 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -964,7 +964,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let sig = self .at(cause, self.param_env) .trace(prev_ty, new_ty) - .lub(&a_sig, &b_sig) + .lub(a_sig, b_sig) .map(|ok| self.register_infer_ok_obligations(ok))?; // Reify both sides and return the reified fn pointer type. diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 4e97ba41dcb..e6217e0cc1b 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -502,7 +502,7 @@ fn compare_self_type<'tcx>( ty::ImplContainer(_) => impl_trait_ref.self_ty(), ty::TraitContainer(_) => tcx.types.self_param, }; - let self_arg_ty = *tcx.fn_sig(method.def_id).input(0).skip_binder(); + let self_arg_ty = tcx.fn_sig(method.def_id).input(0).skip_binder(); let param_env = ty::ParamEnv::reveal_all(); tcx.infer_ctxt().enter(|infcx| { diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index e27c2e45039..f6991120f34 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -227,10 +227,10 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( let predicate_matches_closure = |p: Predicate<'tcx>| { let mut relator: SimpleEqRelation<'tcx> = SimpleEqRelation::new(tcx, self_param_env); match (predicate.kind(), p.kind()) { - (ty::PredicateKind::Trait(a, _), ty::PredicateKind::Trait(b, _)) => { + (&ty::PredicateKind::Trait(a, _), &ty::PredicateKind::Trait(b, _)) => { relator.relate(a, b).is_ok() } - (ty::PredicateKind::Projection(a), ty::PredicateKind::Projection(b)) => { + (&ty::PredicateKind::Projection(a), &ty::PredicateKind::Projection(b)) => { relator.relate(a, b).is_ok() } _ => predicate == p, @@ -310,8 +310,8 @@ impl TypeRelation<'tcx> for SimpleEqRelation<'tcx> { fn relate_with_variance<T: Relate<'tcx>>( &mut self, _: ty::Variance, - a: &T, - b: &T, + a: T, + b: T, ) -> RelateResult<'tcx, T> { // Here we ignore variance because we require drop impl's types // to be *exactly* the same as to the ones in the struct definition. @@ -354,8 +354,8 @@ impl TypeRelation<'tcx> for SimpleEqRelation<'tcx> { fn binders<T>( &mut self, - a: &ty::Binder<T>, - b: &ty::Binder<T>, + a: ty::Binder<T>, + b: ty::Binder<T>, ) -> RelateResult<'tcx, ty::Binder<T>> where T: Relate<'tcx>, @@ -364,8 +364,8 @@ impl TypeRelation<'tcx> for SimpleEqRelation<'tcx> { // Anonymizing the LBRs is necessary to solve (Issue #59497). // After we do so, it should be totally fine to skip the binders. - let anon_a = self.tcx.anonymize_late_bound_regions(a); - let anon_b = self.tcx.anonymize_late_bound_regions(b); + let anon_a = self.tcx.anonymize_late_bound_regions(&a); + let anon_b = self.tcx.anonymize_late_bound_regions(&b); self.relate(anon_a.skip_binder(), anon_b.skip_binder())?; Ok(a.clone()) diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 1c0b22ca737..6205088adad 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -352,7 +352,17 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { return; } - "count_code_region" => (0, vec![tcx.types.u32], tcx.mk_unit()), + "count_code_region" => { + (0, vec![tcx.types.u32, tcx.types.u32, tcx.types.u32], tcx.mk_unit()) + } + + "coverage_counter_add" | "coverage_counter_subtract" => ( + 0, + vec![tcx.types.u32, tcx.types.u32, tcx.types.u32, tcx.types.u32, tcx.types.u32], + tcx.mk_unit(), + ), + + "coverage_unreachable" => (0, vec![tcx.types.u32, tcx.types.u32], tcx.mk_unit()), ref other => { struct_span_err!( diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 67bdd04d371..fbf81e94d03 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -608,7 +608,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Adt(def, _) => bound_spans.push((def_span(def.did), msg)), // Point at the trait object that couldn't satisfy the bound. ty::Dynamic(preds, _) => { - for pred in *preds.skip_binder() { + for pred in preds.skip_binder() { match pred { ty::ExistentialPredicate::Trait(tr) => { bound_spans.push((def_span(tr.def_id), msg.clone())) @@ -1039,22 +1039,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut suggested = false; if let (Some(ref param), Some(ref table)) = (param_type, self.in_progress_tables) { let table_owner = table.borrow().hir_owner; - if let Some(table_owner) = table_owner { - let generics = self.tcx.generics_of(table_owner.to_def_id()); - let type_param = generics.type_param(param, self.tcx); - let hir = &self.tcx.hir(); - if let Some(def_id) = type_param.def_id.as_local() { - let id = hir.as_local_hir_id(def_id); - // Get the `hir::Param` to verify whether it already has any bounds. - // We do this to avoid suggesting code that ends up as `T: FooBar`, - // instead we suggest `T: Foo + Bar` in that case. - match hir.get(id) { - Node::GenericParam(ref param) => { - let mut impl_trait = false; - let has_bounds = if let hir::GenericParamKind::Type { - synthetic: Some(_), - .. - } = ¶m.kind + let generics = self.tcx.generics_of(table_owner.to_def_id()); + let type_param = generics.type_param(param, self.tcx); + let hir = &self.tcx.hir(); + if let Some(def_id) = type_param.def_id.as_local() { + let id = hir.as_local_hir_id(def_id); + // Get the `hir::Param` to verify whether it already has any bounds. + // We do this to avoid suggesting code that ends up as `T: FooBar`, + // instead we suggest `T: Foo + Bar` in that case. + match hir.get(id) { + Node::GenericParam(ref param) => { + let mut impl_trait = false; + let has_bounds = + if let hir::GenericParamKind::Type { synthetic: Some(_), .. } = + ¶m.kind { // We've found `fn foo(x: impl Trait)` instead of // `fn foo<T>(x: T)`. We want to suggest the correct @@ -1065,64 +1063,63 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { param.bounds.get(0) }; - let sp = hir.span(id); - let sp = if let Some(first_bound) = has_bounds { - // `sp` only covers `T`, change it so that it covers - // `T:` when appropriate - sp.until(first_bound.span()) - } else { - sp - }; - let trait_def_ids: FxHashSet<DefId> = param - .bounds - .iter() - .filter_map(|bound| Some(bound.trait_ref()?.trait_def_id()?)) - .collect(); - if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) { - err.span_suggestions( - sp, - &message(format!( - "restrict type parameter `{}` with", - param.name.ident(), - )), - candidates.iter().map(|t| { - format!( - "{}{} {}{}", - param.name.ident(), - if impl_trait { " +" } else { ":" }, - self.tcx.def_path_str(t.def_id), - if has_bounds.is_some() { " + " } else { "" }, - ) - }), - Applicability::MaybeIncorrect, - ); - } - suggested = true; - } - Node::Item(hir::Item { - kind: hir::ItemKind::Trait(.., bounds, _), - ident, - .. - }) => { - let (sp, sep, article) = if bounds.is_empty() { - (ident.span.shrink_to_hi(), ":", "a") - } else { - (bounds.last().unwrap().span().shrink_to_hi(), " +", "another") - }; + let sp = hir.span(id); + let sp = if let Some(first_bound) = has_bounds { + // `sp` only covers `T`, change it so that it covers + // `T:` when appropriate + sp.until(first_bound.span()) + } else { + sp + }; + let trait_def_ids: FxHashSet<DefId> = param + .bounds + .iter() + .filter_map(|bound| Some(bound.trait_ref()?.trait_def_id()?)) + .collect(); + if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) { err.span_suggestions( sp, - &message(format!("add {} supertrait for", article)), + &message(format!( + "restrict type parameter `{}` with", + param.name.ident(), + )), candidates.iter().map(|t| { - format!("{} {}", sep, self.tcx.def_path_str(t.def_id),) + format!( + "{}{} {}{}", + param.name.ident(), + if impl_trait { " +" } else { ":" }, + self.tcx.def_path_str(t.def_id), + if has_bounds.is_some() { " + " } else { "" }, + ) }), Applicability::MaybeIncorrect, ); - suggested = true; } - _ => {} + suggested = true; + } + Node::Item(hir::Item { + kind: hir::ItemKind::Trait(.., bounds, _), + ident, + .. + }) => { + let (sp, sep, article) = if bounds.is_empty() { + (ident.span.shrink_to_hi(), ":", "a") + } else { + (bounds.last().unwrap().span().shrink_to_hi(), " +", "another") + }; + err.span_suggestions( + sp, + &message(format!("add {} supertrait for", article)), + candidates.iter().map(|t| { + format!("{} {}", sep, self.tcx.def_path_str(t.def_id),) + }), + Applicability::MaybeIncorrect, + ); + suggested = true; } + _ => {} } - }; + } } if !suggested { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7c4048ab223..58fd0f989c6 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1126,7 +1126,7 @@ fn typeck_tables_of_with_fallback<'tcx>( // Consistency check our TypeckTables instance can hold all ItemLocalIds // it will need to hold. - assert_eq!(tables.hir_owner, Some(id.owner)); + assert_eq!(tables.hir_owner, id.owner); tables } @@ -2446,7 +2446,7 @@ fn bounds_from_generic_predicates( /// Return placeholder code for the given function. fn fn_sig_suggestion( tcx: TyCtxt<'_>, - sig: &ty::FnSig<'_>, + sig: ty::FnSig<'_>, ident: Ident, predicates: ty::GenericPredicates<'_>, assoc: &ty::AssocItem, diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 94a5685a992..a1e060b97ad 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -500,7 +500,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return false; } // We're emitting a suggestion, so we can just ignore regions - let fn_sig = *self.tcx.fn_sig(def_id).skip_binder(); + let fn_sig = self.tcx.fn_sig(def_id).skip_binder(); let other_ty = if let FnDef(def_id, _) = other_ty.kind { if !self.tcx.has_typeck_tables(def_id) { diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 4704d8fc766..fa17696e02b 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -109,12 +109,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { ) -> WritebackCx<'cx, 'tcx> { let owner = body.id().hir_id.owner; - WritebackCx { - fcx, - tables: ty::TypeckTables::empty(Some(owner)), - body, - rustc_dump_user_substs, - } + WritebackCx { fcx, tables: ty::TypeckTables::new(owner), body, rustc_dump_user_substs } } fn tcx(&self) -> TyCtxt<'tcx> { @@ -342,7 +337,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fn visit_closures(&mut self) { let fcx_tables = self.fcx.tables.borrow(); assert_eq!(fcx_tables.hir_owner, self.tables.hir_owner); - let common_hir_owner = fcx_tables.hir_owner.unwrap(); + let common_hir_owner = fcx_tables.hir_owner; for (&id, &origin) in fcx_tables.closure_kind_origins().iter() { let hir_id = hir::HirId { owner: common_hir_owner, local_id: id }; @@ -363,7 +358,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fn visit_user_provided_tys(&mut self) { let fcx_tables = self.fcx.tables.borrow(); assert_eq!(fcx_tables.hir_owner, self.tables.hir_owner); - let common_hir_owner = fcx_tables.hir_owner.unwrap(); + let common_hir_owner = fcx_tables.hir_owner; let mut errors_buffer = Vec::new(); for (&local_id, c_ty) in fcx_tables.user_provided_types().iter() { @@ -561,7 +556,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fn visit_liberated_fn_sigs(&mut self) { let fcx_tables = self.fcx.tables.borrow(); assert_eq!(fcx_tables.hir_owner, self.tables.hir_owner); - let common_hir_owner = fcx_tables.hir_owner.unwrap(); + let common_hir_owner = fcx_tables.hir_owner; for (&local_id, fn_sig) in fcx_tables.liberated_fn_sigs().iter() { let hir_id = hir::HirId { owner: common_hir_owner, local_id }; @@ -573,7 +568,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fn visit_fru_field_types(&mut self) { let fcx_tables = self.fcx.tables.borrow(); assert_eq!(fcx_tables.hir_owner, self.tables.hir_owner); - let common_hir_owner = fcx_tables.hir_owner.unwrap(); + let common_hir_owner = fcx_tables.hir_owner; for (&local_id, ftys) in fcx_tables.fru_field_types().iter() { let hir_id = hir::HirId { owner: common_hir_owner, local_id }; diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index a45a44a6801..3b203dd222a 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -216,7 +216,7 @@ fn check_object_overlap<'tcx>( let component_def_ids = data.iter().flat_map(|predicate| { match predicate.skip_binder() { ty::ExistentialPredicate::Trait(tr) => Some(tr.def_id), - ty::ExistentialPredicate::AutoTrait(def_id) => Some(*def_id), + ty::ExistentialPredicate::AutoTrait(def_id) => Some(def_id), // An associated type projection necessarily comes with // an additional `Trait` requirement. ty::ExistentialPredicate::Projection(..) => None, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index b486e3d3536..8920203e6af 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2102,11 +2102,11 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( .emit(); } }; - for (input, ty) in decl.inputs.iter().zip(*fty.inputs().skip_binder()) { + for (input, ty) in decl.inputs.iter().zip(fty.inputs().skip_binder()) { check(&input, ty) } if let hir::FnRetTy::Return(ref ty) = decl.output { - check(&ty, *fty.output().skip_binder()) + check(&ty, fty.output().skip_binder()) } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 73fe87b05d4..bfe8464347d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -347,7 +347,7 @@ impl Clean<GenericBound> for (ty::PolyTraitRef<'_>, &[TypeBinding]) { GenericBound::TraitBound( PolyTrait { - trait_: (*poly_trait_ref.skip_binder(), bounds).clean(cx), + trait_: (poly_trait_ref.skip_binder(), bounds).clean(cx), generic_params: late_bound_regions, }, hir::TraitBoundModifier::None, @@ -549,7 +549,7 @@ impl<'tcx> Clean<Option<WherePredicate>> for ty::PolyOutlivesPredicate<Ty<'tcx>, impl<'tcx> Clean<WherePredicate> for ty::PolyProjectionPredicate<'tcx> { fn clean(&self, cx: &DocContext<'_>) -> WherePredicate { - let ty::ProjectionPredicate { projection_ty, ty } = *self.skip_binder(); + let ty::ProjectionPredicate { projection_ty, ty } = self.skip_binder(); WherePredicate::EqPredicate { lhs: projection_ty.clean(cx), rhs: ty.clean(cx) } } } @@ -1177,7 +1177,7 @@ impl Clean<Item> for ty::AssocItem { ty::ImplContainer(def_id) => cx.tcx.type_of(def_id), ty::TraitContainer(_) => cx.tcx.types.self_param, }; - let self_arg_ty = *sig.input(0).skip_binder(); + let self_arg_ty = sig.input(0).skip_binder(); if self_arg_ty == self_ty { decl.inputs.values[0].type_ = Generic(String::from("Self")); } else if let ty::Ref(_, ty, _) = self_arg_ty.kind { @@ -1679,7 +1679,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> { if let ty::PredicateKind::Projection(proj) = pred.kind() { let proj = proj.skip_binder(); if proj.projection_ty.trait_ref(cx.tcx) - == *trait_ref.skip_binder() + == trait_ref.skip_binder() { Some(TypeBinding { name: cx diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 17f890375f8..4d031cb7a52 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -8,6 +8,7 @@ //! extension traits of `std::os::$platform`. #![stable(feature = "rust1", since = "1.0.0")] +#![deny(unsafe_op_in_unsafe_fn)] use crate::ffi::OsString; use crate::fmt; @@ -666,7 +667,8 @@ impl Read for File { #[inline] unsafe fn initializer(&self) -> Initializer { - Initializer::nop() + // SAFETY: Read is guaranteed to work on uninitialized memory + unsafe { Initializer::nop() } } } #[stable(feature = "rust1", since = "1.0.0")] @@ -711,7 +713,8 @@ impl Read for &File { #[inline] unsafe fn initializer(&self) -> Initializer { - Initializer::nop() + // SAFETY: Read is guaranteed to work on uninitialized memory + unsafe { Initializer::nop() } } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index d972cf6db18..0b3386c05d5 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -1281,11 +1281,84 @@ mod self_upper_keyword {} #[doc(keyword = "static")] // -/// A place that is valid for the duration of a program. +/// A static item is a value which is valid for the entire duration of your +/// program (a `'static` lifetime). /// -/// The documentation for this keyword is [not yet complete]. Pull requests welcome! +/// On the surface, `static` items seem very similar to [`const`]s: both contain +/// a value, both require type annotations and both can only be initialized with +/// constant functions and values. However, `static`s are notably different in +/// that they represent a location in memory. That means that you can have +/// references to `static` items and potentially even modify them, making them +/// essentially global variables. /// -/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601 +/// Static items do not call [`drop`] at the end of the program. +/// +/// There are two types of `static` items: those declared in association with +/// the [`mut`] keyword and those without. +/// +/// Static items cannot be moved: +/// +/// ```rust,compile_fail,E0507 +/// static VEC: Vec<u32> = vec![]; +/// +/// fn move_vec(v: Vec<u32>) -> Vec<u32> { +/// v +/// } +/// +/// // This line causes an error +/// move_vec(VEC); +/// ``` +/// +/// # Simple `static`s +/// +/// Accessing non-[`mut`] `static` items is considered safe, but some +/// restrictions apply. Most notably, the type of a `static` value needs to +/// implement the [`Sync`] trait, ruling out interior mutability containers +/// like [`RefCell`]. See the [Reference] for more information. +/// +/// ```rust +/// static FOO: [i32; 5] = [1, 2, 3, 4, 5]; +/// +/// let r1 = &FOO as *const _; +/// let r2 = &FOO as *const _; +/// // With a strictly read-only static, references will have the same adress +/// assert_eq!(r1, r2); +/// // A static item can be used just like a variable in many cases +/// println!("{:?}", FOO); +/// ``` +/// +/// # Mutable `static`s +/// +/// If a `static` item is declared with the [`mut`] keyword, then it is allowed +/// to be modified by the program. However, accessing mutable `static`s can +/// cause undefined behavior in a number of ways, for example due to data races +/// in a multithreaded context. As such, all accesses to mutable `static`s +/// require an [`unsafe`] block. +/// +/// Despite their unsafety, mutable `static`s are necessary in many contexts: +/// they can be used to represent global state shared by the whole program or in +/// [`extern`] blocks to bind to variables from C libraries. +/// +/// In an [`extern`] block: +/// +/// ```rust,no_run +/// # #![allow(dead_code)] +/// extern "C" { +/// static mut ERROR_MESSAGE: *mut std::os::raw::c_char; +/// } +/// ``` +/// +/// Mutable `static`s, just like simple `static`s, have some restrictions that +/// apply to them. See the [Reference] for more information. +/// +/// [`const`]: keyword.const.html +/// [`extern`]: keyword.extern.html +/// [`mut`]: keyword.mut.html +/// [`unsafe`]: keyword.unsafe.html +/// [`drop`]: mem/fn.drop.html +/// [`Sync`]: marker/trait.Sync.html +/// [`RefCell`]: cell/struct.RefCell.html +/// [Reference]: ../reference/items/static-items.html mod static_keyword {} #[doc(keyword = "struct")] @@ -1463,9 +1536,44 @@ mod true_keyword {} // /// Define an alias for an existing type. /// -/// The documentation for this keyword is [not yet complete]. Pull requests welcome! +/// The syntax is `type Name = ExistingType;`. /// -/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601 +/// # Examples +/// +/// `type` does **not** create a new type: +/// +/// ```rust +/// type Meters = u32; +/// type Kilograms = u32; +/// +/// let m: Meters = 3; +/// let k: Kilograms = 3; +/// +/// assert_eq!(m, k); +/// ``` +/// +/// In traits, `type` is used to declare an [associated type]: +/// +/// ```rust +/// trait Iterator { +/// // associated type declaration +/// type Item; +/// fn next(&mut self) -> Option<Self::Item>; +/// } +/// +/// struct Once<T>(Option<T>); +/// +/// impl<T> Iterator for Once<T> { +/// // associated type definition +/// type Item = T; +/// fn next(&mut self) -> Option<Self::Item> { +/// self.0.take() +/// } +/// } +/// ``` +/// +/// [`trait`]: keyword.trait.html +/// [associated type]: ../reference/items/associated-items.html#associated-types mod type_keyword {} #[doc(keyword = "unsafe")] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index ef699ede2a1..bd585d39c24 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -316,9 +316,10 @@ #![feature(toowned_clone_into)] #![feature(total_cmp)] #![feature(trace_macros)] -#![feature(track_caller)] +#![cfg_attr(bootstrap, feature(track_caller))] #![feature(try_reserve)] #![feature(unboxed_closures)] +#![feature(unsafe_block_in_unsafe_fn)] #![feature(untagged_unions)] #![feature(unwind_attributes)] #![feature(vec_into_raw_parts)] diff --git a/src/libstd/net/parser.rs b/src/libstd/net/parser.rs index 3f38ee54710..12d3baf6333 100644 --- a/src/libstd/net/parser.rs +++ b/src/libstd/net/parser.rs @@ -10,163 +10,132 @@ use crate::str::FromStr; struct Parser<'a> { // parsing as ASCII, so can use byte array - s: &'a [u8], - pos: usize, + state: &'a [u8], } impl<'a> Parser<'a> { - fn new(s: &'a str) -> Parser<'a> { - Parser { s: s.as_bytes(), pos: 0 } + fn new(input: &'a str) -> Parser<'a> { + Parser { state: input.as_bytes() } } fn is_eof(&self) -> bool { - self.pos == self.s.len() + self.state.is_empty() } - // Commit only if parser returns Some - fn read_atomically<T, F>(&mut self, cb: F) -> Option<T> + /// Run a parser, and restore the pre-parse state if it fails + fn read_atomically<T, F>(&mut self, inner: F) -> Option<T> where F: FnOnce(&mut Parser<'_>) -> Option<T>, { - let pos = self.pos; - let r = cb(self); - if r.is_none() { - self.pos = pos; + let state = self.state; + let result = inner(self); + if result.is_none() { + self.state = state; } - r + result } - // Commit only if parser read till EOF - fn read_till_eof<T, F>(&mut self, cb: F) -> Option<T> + /// Run a parser, but fail if the entire input wasn't consumed. + /// Doesn't run atomically. + fn read_till_eof<T, F>(&mut self, inner: F) -> Option<T> where F: FnOnce(&mut Parser<'_>) -> Option<T>, { - self.read_atomically(move |p| cb(p).filter(|_| p.is_eof())) + inner(self).filter(|_| self.is_eof()) } - // Apply 3 parsers sequentially - fn read_seq_3<A, B, C, PA, PB, PC>(&mut self, pa: PA, pb: PB, pc: PC) -> Option<(A, B, C)> + /// Same as read_till_eof, but returns a Result<AddrParseError> on failure + fn parse_with<T, F>(&mut self, inner: F) -> Result<T, AddrParseError> where - PA: FnOnce(&mut Parser<'_>) -> Option<A>, - PB: FnOnce(&mut Parser<'_>) -> Option<B>, - PC: FnOnce(&mut Parser<'_>) -> Option<C>, + F: FnOnce(&mut Parser<'_>) -> Option<T>, { - self.read_atomically(move |p| { - let a = pa(p); - let b = if a.is_some() { pb(p) } else { None }; - let c = if b.is_some() { pc(p) } else { None }; - match (a, b, c) { - (Some(a), Some(b), Some(c)) => Some((a, b, c)), - _ => None, - } - }) + self.read_till_eof(inner).ok_or(AddrParseError(())) } - // Read next char + /// Read the next character from the input fn read_char(&mut self) -> Option<char> { - if self.is_eof() { - None - } else { - let r = self.s[self.pos] as char; - self.pos += 1; - Some(r) - } - } - - // Return char and advance iff next char is equal to requested - fn read_given_char(&mut self, c: char) -> Option<char> { - self.read_atomically(|p| match p.read_char() { - Some(next) if next == c => Some(next), - _ => None, + self.state.split_first().map(|(&b, tail)| { + self.state = tail; + b as char }) } - // Read digit - fn read_digit(&mut self, radix: u8) -> Option<u8> { - fn parse_digit(c: char, radix: u8) -> Option<u8> { - let c = c as u8; - // assuming radix is either 10 or 16 - if c >= b'0' && c <= b'9' { - Some(c - b'0') - } else if radix > 10 && c >= b'a' && c < b'a' + (radix - 10) { - Some(c - b'a' + 10) - } else if radix > 10 && c >= b'A' && c < b'A' + (radix - 10) { - Some(c - b'A' + 10) - } else { - None - } - } - - self.read_atomically(|p| p.read_char().and_then(|c| parse_digit(c, radix))) + /// Read the next character from the input if it matches the target + fn read_given_char(&mut self, target: char) -> Option<char> { + self.read_atomically(|p| p.read_char().filter(|&c| c == target)) } - fn read_number_impl(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> { - let mut r = 0; - let mut digit_count = 0; - loop { - match self.read_digit(radix) { - Some(d) => { - r = r * (radix as u32) + (d as u32); - digit_count += 1; - if digit_count > max_digits || r >= upto { - return None; - } - } - None => { - if digit_count == 0 { - return None; - } else { - return Some(r); - } - } - }; - } + /// Helper for reading separators in an indexed loop. Reads the separator + /// character iff index > 0, then runs the parser. When used in a loop, + /// the separator character will only be read on index > 0 (see + /// read_ipv4_addr for an example) + fn read_separator<T, F>(&mut self, sep: char, index: usize, inner: F) -> Option<T> + where + F: FnOnce(&mut Parser<'_>) -> Option<T>, + { + self.read_atomically(move |p| { + if index > 0 { + let _ = p.read_given_char(sep)?; + } + inner(p) + }) } - // Read number, failing if max_digits of number value exceeded - fn read_number(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> { - self.read_atomically(|p| p.read_number_impl(radix, max_digits, upto)) + // Read a single digit in the given radix. For instance, 0-9 in radix 10; + // 0-9A-F in radix 16. + fn read_digit(&mut self, radix: u32) -> Option<u32> { + self.read_atomically(move |p| p.read_char()?.to_digit(radix)) } - fn read_ipv4_addr_impl(&mut self) -> Option<Ipv4Addr> { - let mut bs = [0; 4]; - let mut i = 0; - while i < 4 { - if i != 0 && self.read_given_char('.').is_none() { - return None; + // Read a number off the front of the input in the given radix, stopping + // at the first non-digit character or eof. Fails if the number has more + // digits than max_digits, or the value is >= upto, or if there is no number. + fn read_number(&mut self, radix: u32, max_digits: u32, upto: u32) -> Option<u32> { + self.read_atomically(move |p| { + let mut result = 0; + let mut digit_count = 0; + + while let Some(digit) = p.read_digit(radix) { + result = (result * radix) + digit; + digit_count += 1; + if digit_count > max_digits || result >= upto { + return None; + } } - bs[i] = self.read_number(10, 3, 0x100).map(|n| n as u8)?; - i += 1; - } - Some(Ipv4Addr::new(bs[0], bs[1], bs[2], bs[3])) + if digit_count == 0 { None } else { Some(result) } + }) } - // Read IPv4 address + /// Read an IPv4 address fn read_ipv4_addr(&mut self) -> Option<Ipv4Addr> { - self.read_atomically(|p| p.read_ipv4_addr_impl()) - } + self.read_atomically(|p| { + let mut groups = [0; 4]; - fn read_ipv6_addr_impl(&mut self) -> Option<Ipv6Addr> { - fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> Ipv6Addr { - assert!(head.len() + tail.len() <= 8); - let mut gs = [0; 8]; - gs[..head.len()].copy_from_slice(head); - gs[(8 - tail.len())..8].copy_from_slice(tail); - Ipv6Addr::new(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7]) - } + for (i, slot) in groups.iter_mut().enumerate() { + *slot = p.read_separator('.', i, |p| p.read_number(10, 3, 0x100))? as u8; + } + + Some(groups.into()) + }) + } - fn read_groups(p: &mut Parser<'_>, groups: &mut [u16; 8], limit: usize) -> (usize, bool) { - let mut i = 0; - while i < limit { + /// Read an IPV6 Address + fn read_ipv6_addr(&mut self) -> Option<Ipv6Addr> { + /// Read a chunk of an ipv6 address into `groups`. Returns the number + /// of groups read, along with a bool indicating if an embedded + /// trailing ipv4 address was read. Specifically, read a series of + /// colon-separated ipv6 groups (0x0000 - 0xFFFF), with an optional + /// trailing embedded ipv4 address. + fn read_groups(p: &mut Parser<'_>, groups: &mut [u16]) -> (usize, bool) { + let limit = groups.len(); + + for (i, slot) in groups.iter_mut().enumerate() { + // Try to read a trailing embedded ipv4 address. There must be + // at least two groups left. if i < limit - 1 { - let ipv4 = p.read_atomically(|p| { - if i == 0 || p.read_given_char(':').is_some() { - p.read_ipv4_addr() - } else { - None - } - }); + let ipv4 = p.read_separator(':', i, |p| p.read_ipv4_addr()); + if let Some(v4_addr) = ipv4 { let octets = v4_addr.octets(); groups[i + 0] = ((octets[0] as u16) << 8) | (octets[1] as u16); @@ -175,83 +144,85 @@ impl<'a> Parser<'a> { } } - let group = p.read_atomically(|p| { - if i == 0 || p.read_given_char(':').is_some() { - p.read_number(16, 4, 0x10000).map(|n| n as u16) - } else { - None - } - }); + let group = p.read_separator(':', i, |p| p.read_number(16, 4, 0x10000)); + match group { - Some(g) => groups[i] = g, + Some(g) => *slot = g as u16, None => return (i, false), } - i += 1; } - (i, false) + (groups.len(), false) } - let mut head = [0; 8]; - let (head_size, head_ipv4) = read_groups(self, &mut head, 8); + self.read_atomically(|p| { + // Read the front part of the address; either the whole thing, or up + // to the first :: + let mut head = [0; 8]; + let (head_size, head_ipv4) = read_groups(p, &mut head); - if head_size == 8 { - return Some(Ipv6Addr::new( - head[0], head[1], head[2], head[3], head[4], head[5], head[6], head[7], - )); - } + if head_size == 8 { + return Some(head.into()); + } - // IPv4 part is not allowed before `::` - if head_ipv4 { - return None; - } + // IPv4 part is not allowed before `::` + if head_ipv4 { + return None; + } - // read `::` if previous code parsed less than 8 groups - if self.read_given_char(':').is_none() || self.read_given_char(':').is_none() { - return None; - } + // read `::` if previous code parsed less than 8 groups + // `::` indicates one or more groups of 16 bits of zeros + let _ = p.read_given_char(':')?; + let _ = p.read_given_char(':')?; - let mut tail = [0; 8]; - // `::` indicates one or more groups of 16 bits of zeros - let limit = 8 - (head_size + 1); - let (tail_size, _) = read_groups(self, &mut tail, limit); - Some(ipv6_addr_from_head_tail(&head[..head_size], &tail[..tail_size])) - } + // Read the back part of the address. The :: must contain at least one + // set of zeroes, so our max length is 7. + let mut tail = [0; 7]; + let limit = 8 - (head_size + 1); + let (tail_size, _) = read_groups(p, &mut tail[..limit]); - fn read_ipv6_addr(&mut self) -> Option<Ipv6Addr> { - self.read_atomically(|p| p.read_ipv6_addr_impl()) + // Concat the head and tail of the IP address + head[(8 - tail_size)..8].copy_from_slice(&tail[..tail_size]); + + Some(head.into()) + }) } + /// Read an IP Address, either IPV4 or IPV6. fn read_ip_addr(&mut self) -> Option<IpAddr> { - self.read_ipv4_addr().map(IpAddr::V4).or_else(|| self.read_ipv6_addr().map(IpAddr::V6)) + self.read_ipv4_addr().map(IpAddr::V4).or_else(move || self.read_ipv6_addr().map(IpAddr::V6)) } - fn read_socket_addr_v4(&mut self) -> Option<SocketAddrV4> { - let ip_addr = |p: &mut Parser<'_>| p.read_ipv4_addr(); - let colon = |p: &mut Parser<'_>| p.read_given_char(':'); - let port = |p: &mut Parser<'_>| p.read_number(10, 5, 0x10000).map(|n| n as u16); + /// Read a : followed by a port in base 10 + fn read_port(&mut self) -> Option<u16> { + self.read_atomically(|p| { + let _ = p.read_given_char(':')?; + let port = p.read_number(10, 5, 0x10000)?; + Some(port as u16) + }) + } - self.read_seq_3(ip_addr, colon, port).map(|t| { - let (ip, _, port): (Ipv4Addr, char, u16) = t; - SocketAddrV4::new(ip, port) + /// Read an IPV4 address with a port + fn read_socket_addr_v4(&mut self) -> Option<SocketAddrV4> { + self.read_atomically(|p| { + let ip = p.read_ipv4_addr()?; + let port = p.read_port()?; + Some(SocketAddrV4::new(ip, port)) }) } + /// Read an IPV6 address with a port fn read_socket_addr_v6(&mut self) -> Option<SocketAddrV6> { - let ip_addr = |p: &mut Parser<'_>| { - let open_br = |p: &mut Parser<'_>| p.read_given_char('['); - let ip_addr = |p: &mut Parser<'_>| p.read_ipv6_addr(); - let clos_br = |p: &mut Parser<'_>| p.read_given_char(']'); - p.read_seq_3(open_br, ip_addr, clos_br).map(|t| t.1) - }; - let colon = |p: &mut Parser<'_>| p.read_given_char(':'); - let port = |p: &mut Parser<'_>| p.read_number(10, 5, 0x10000).map(|n| n as u16); - - self.read_seq_3(ip_addr, colon, port).map(|t| { - let (ip, _, port): (Ipv6Addr, char, u16) = t; - SocketAddrV6::new(ip, port, 0, 0) + self.read_atomically(|p| { + let _ = p.read_given_char('[')?; + let ip = p.read_ipv6_addr()?; + let _ = p.read_given_char(']')?; + + let port = p.read_port()?; + Some(SocketAddrV6::new(ip, port, 0, 0)) }) } + /// Read an IP address with a port fn read_socket_addr(&mut self) -> Option<SocketAddr> { self.read_socket_addr_v4() .map(SocketAddr::V4) @@ -263,10 +234,7 @@ impl<'a> Parser<'a> { impl FromStr for IpAddr { type Err = AddrParseError; fn from_str(s: &str) -> Result<IpAddr, AddrParseError> { - match Parser::new(s).read_till_eof(|p| p.read_ip_addr()) { - Some(s) => Ok(s), - None => Err(AddrParseError(())), - } + Parser::new(s).parse_with(|p| p.read_ip_addr()) } } @@ -274,10 +242,7 @@ impl FromStr for IpAddr { impl FromStr for Ipv4Addr { type Err = AddrParseError; fn from_str(s: &str) -> Result<Ipv4Addr, AddrParseError> { - match Parser::new(s).read_till_eof(|p| p.read_ipv4_addr()) { - Some(s) => Ok(s), - None => Err(AddrParseError(())), - } + Parser::new(s).parse_with(|p| p.read_ipv4_addr()) } } @@ -285,10 +250,7 @@ impl FromStr for Ipv4Addr { impl FromStr for Ipv6Addr { type Err = AddrParseError; fn from_str(s: &str) -> Result<Ipv6Addr, AddrParseError> { - match Parser::new(s).read_till_eof(|p| p.read_ipv6_addr()) { - Some(s) => Ok(s), - None => Err(AddrParseError(())), - } + Parser::new(s).parse_with(|p| p.read_ipv6_addr()) } } @@ -296,10 +258,7 @@ impl FromStr for Ipv6Addr { impl FromStr for SocketAddrV4 { type Err = AddrParseError; fn from_str(s: &str) -> Result<SocketAddrV4, AddrParseError> { - match Parser::new(s).read_till_eof(|p| p.read_socket_addr_v4()) { - Some(s) => Ok(s), - None => Err(AddrParseError(())), - } + Parser::new(s).parse_with(|p| p.read_socket_addr_v4()) } } @@ -307,10 +266,7 @@ impl FromStr for SocketAddrV4 { impl FromStr for SocketAddrV6 { type Err = AddrParseError; fn from_str(s: &str) -> Result<SocketAddrV6, AddrParseError> { - match Parser::new(s).read_till_eof(|p| p.read_socket_addr_v6()) { - Some(s) => Ok(s), - None => Err(AddrParseError(())), - } + Parser::new(s).parse_with(|p| p.read_socket_addr_v6()) } } @@ -318,10 +274,7 @@ impl FromStr for SocketAddrV6 { impl FromStr for SocketAddr { type Err = AddrParseError; fn from_str(s: &str) -> Result<SocketAddr, AddrParseError> { - match Parser::new(s).read_till_eof(|p| p.read_socket_addr()) { - Some(s) => Ok(s), - None => Err(AddrParseError(())), - } + Parser::new(s).parse_with(|p| p.read_socket_addr()) } } @@ -376,3 +329,146 @@ impl Error for AddrParseError { "invalid IP address syntax" } } + +#[cfg(test)] +mod tests { + // FIXME: These tests are all excellent candidates for AFL fuzz testing + use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; + use crate::str::FromStr; + + const PORT: u16 = 8080; + + const IPV4: Ipv4Addr = Ipv4Addr::new(192, 168, 0, 1); + const IPV4_STR: &str = "192.168.0.1"; + const IPV4_STR_PORT: &str = "192.168.0.1:8080"; + + const IPV6: Ipv6Addr = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0xc0a8, 0x1); + const IPV6_STR_FULL: &str = "2001:db8:0:0:0:0:c0a8:1"; + const IPV6_STR_COMPRESS: &str = "2001:db8::c0a8:1"; + const IPV6_STR_V4: &str = "2001:db8::192.168.0.1"; + const IPV6_STR_PORT: &str = "[2001:db8::c0a8:1]:8080"; + + #[test] + fn parse_ipv4() { + let result: Ipv4Addr = IPV4_STR.parse().unwrap(); + assert_eq!(result, IPV4); + + assert!(Ipv4Addr::from_str(IPV4_STR_PORT).is_err()); + assert!(Ipv4Addr::from_str(IPV6_STR_FULL).is_err()); + assert!(Ipv4Addr::from_str(IPV6_STR_COMPRESS).is_err()); + assert!(Ipv4Addr::from_str(IPV6_STR_V4).is_err()); + assert!(Ipv4Addr::from_str(IPV6_STR_PORT).is_err()); + } + + #[test] + fn parse_ipv6() { + let result: Ipv6Addr = IPV6_STR_FULL.parse().unwrap(); + assert_eq!(result, IPV6); + + let result: Ipv6Addr = IPV6_STR_COMPRESS.parse().unwrap(); + assert_eq!(result, IPV6); + + let result: Ipv6Addr = IPV6_STR_V4.parse().unwrap(); + assert_eq!(result, IPV6); + + assert!(Ipv6Addr::from_str(IPV4_STR).is_err()); + assert!(Ipv6Addr::from_str(IPV4_STR_PORT).is_err()); + assert!(Ipv6Addr::from_str(IPV6_STR_PORT).is_err()); + } + + #[test] + fn parse_ip() { + let result: IpAddr = IPV4_STR.parse().unwrap(); + assert_eq!(result, IpAddr::from(IPV4)); + + let result: IpAddr = IPV6_STR_FULL.parse().unwrap(); + assert_eq!(result, IpAddr::from(IPV6)); + + let result: IpAddr = IPV6_STR_COMPRESS.parse().unwrap(); + assert_eq!(result, IpAddr::from(IPV6)); + + let result: IpAddr = IPV6_STR_V4.parse().unwrap(); + assert_eq!(result, IpAddr::from(IPV6)); + + assert!(IpAddr::from_str(IPV4_STR_PORT).is_err()); + assert!(IpAddr::from_str(IPV6_STR_PORT).is_err()); + } + + #[test] + fn parse_socket_v4() { + let result: SocketAddrV4 = IPV4_STR_PORT.parse().unwrap(); + assert_eq!(result, SocketAddrV4::new(IPV4, PORT)); + + assert!(SocketAddrV4::from_str(IPV4_STR).is_err()); + assert!(SocketAddrV4::from_str(IPV6_STR_FULL).is_err()); + assert!(SocketAddrV4::from_str(IPV6_STR_COMPRESS).is_err()); + assert!(SocketAddrV4::from_str(IPV6_STR_V4).is_err()); + assert!(SocketAddrV4::from_str(IPV6_STR_PORT).is_err()); + } + + #[test] + fn parse_socket_v6() { + let result: SocketAddrV6 = IPV6_STR_PORT.parse().unwrap(); + assert_eq!(result, SocketAddrV6::new(IPV6, PORT, 0, 0)); + + assert!(SocketAddrV6::from_str(IPV4_STR).is_err()); + assert!(SocketAddrV6::from_str(IPV4_STR_PORT).is_err()); + assert!(SocketAddrV6::from_str(IPV6_STR_FULL).is_err()); + assert!(SocketAddrV6::from_str(IPV6_STR_COMPRESS).is_err()); + assert!(SocketAddrV6::from_str(IPV6_STR_V4).is_err()); + } + + #[test] + fn parse_socket() { + let result: SocketAddr = IPV4_STR_PORT.parse().unwrap(); + assert_eq!(result, SocketAddr::from((IPV4, PORT))); + + let result: SocketAddr = IPV6_STR_PORT.parse().unwrap(); + assert_eq!(result, SocketAddr::from((IPV6, PORT))); + + assert!(SocketAddr::from_str(IPV4_STR).is_err()); + assert!(SocketAddr::from_str(IPV6_STR_FULL).is_err()); + assert!(SocketAddr::from_str(IPV6_STR_COMPRESS).is_err()); + assert!(SocketAddr::from_str(IPV6_STR_V4).is_err()); + } + + #[test] + fn ipv6_corner_cases() { + let result: Ipv6Addr = "1::".parse().unwrap(); + assert_eq!(result, Ipv6Addr::new(1, 0, 0, 0, 0, 0, 0, 0)); + + let result: Ipv6Addr = "1:1::".parse().unwrap(); + assert_eq!(result, Ipv6Addr::new(1, 1, 0, 0, 0, 0, 0, 0)); + + let result: Ipv6Addr = "::1".parse().unwrap(); + assert_eq!(result, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); + + let result: Ipv6Addr = "::1:1".parse().unwrap(); + assert_eq!(result, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 1, 1)); + + let result: Ipv6Addr = "::".parse().unwrap(); + assert_eq!(result, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)); + + let result: Ipv6Addr = "::192.168.0.1".parse().unwrap(); + assert_eq!(result, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc0a8, 0x1)); + + let result: Ipv6Addr = "::1:192.168.0.1".parse().unwrap(); + assert_eq!(result, Ipv6Addr::new(0, 0, 0, 0, 0, 1, 0xc0a8, 0x1)); + + let result: Ipv6Addr = "1:1:1:1:1:1:192.168.0.1".parse().unwrap(); + assert_eq!(result, Ipv6Addr::new(1, 1, 1, 1, 1, 1, 0xc0a8, 0x1)); + } + + // Things that might not seem like failures but are + #[test] + fn ipv6_corner_failures() { + // No IP address before the :: + assert!(Ipv6Addr::from_str("1:192.168.0.1::").is_err()); + + // :: must have at least 1 set of zeroes + assert!(Ipv6Addr::from_str("1:1:1:1::1:1:1:1").is_err()); + + // Need brackets for a port + assert!(SocketAddrV6::from_str("1:1:1:1:1:1:1:1:8080").is_err()); + } +} diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 640c9f3636d..193ab5b47ef 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -61,6 +61,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { c::ERROR_FILE_NOT_FOUND => return ErrorKind::NotFound, c::ERROR_PATH_NOT_FOUND => return ErrorKind::NotFound, c::ERROR_NO_DATA => return ErrorKind::BrokenPipe, + c::ERROR_INVALID_PARAMETER => return ErrorKind::InvalidInput, c::ERROR_SEM_TIMEOUT | c::WAIT_TIMEOUT | c::ERROR_DRIVER_CANCEL_TIMEOUT diff --git a/src/llvm-project b/src/llvm-project -Subproject 0ddefeca92b2e1835c80e9b01d9ecc7efc906b1 +Subproject 6c040dd86ed62d38e585279027486e6efc42fb3 diff --git a/src/test/codegen/wasm_casts_nontrapping.rs b/src/test/codegen/wasm_casts_nontrapping.rs new file mode 100644 index 00000000000..bd6073d8c20 --- /dev/null +++ b/src/test/codegen/wasm_casts_nontrapping.rs @@ -0,0 +1,162 @@ +// only-wasm32 +// compile-flags: -C target-feature=+nontrapping-fptoint +#![crate_type = "lib"] + +// CHECK-LABEL: @cast_f64_i64 +#[no_mangle] +pub fn cast_f64_i64(a: f64) -> i64 { + // CHECK: tail call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double {{.*}}) + // CHECK-NEXT: ret i64 {{.*}} + a as _ +} + +// CHECK-LABEL: @cast_f64_i32 +#[no_mangle] +pub fn cast_f64_i32(a: f64) -> i32 { + // CHECK: tail call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double {{.*}}) + // CHECK-NEXT: ret i32 {{.*}} + a as _ +} + +// CHECK-LABEL: @cast_f32_i64 +#[no_mangle] +pub fn cast_f32_i64(a: f32) -> i64 { + // CHECK: tail call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float {{.*}}) + // CHECK-NEXT: ret i64 {{.*}} + a as _ +} + +// CHECK-LABEL: @cast_f32_i32 +#[no_mangle] +pub fn cast_f32_i32(a: f32) -> i32 { + // CHECK: tail call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float {{.*}}) + // CHECK-NEXT: ret i32 {{.*}} + a as _ +} + + +// CHECK-LABEL: @cast_f64_u64 +#[no_mangle] +pub fn cast_f64_u64(a: f64) -> u64 { + // CHECK: tail call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double {{.*}}) + // CHECK-NEXT: ret i64 {{.*}} + a as _ +} + +// CHECK-LABEL: @cast_f64_u32 +#[no_mangle] +pub fn cast_f64_u32(a: f64) -> u32 { + // CHECK: tail call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double {{.*}}) + // CHECK-NEXT: ret i32 {{.*}} + a as _ +} + +// CHECK-LABEL: @cast_f32_u64 +#[no_mangle] +pub fn cast_f32_u64(a: f32) -> u64 { + // CHECK: tail call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float {{.*}}) + // CHECK-NEXT: ret i64 {{.*}} + a as _ +} + +// CHECK-LABEL: @cast_f32_u32 +#[no_mangle] +pub fn cast_f32_u32(a: f32) -> u32 { + // CHECK: tail call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float {{.*}}) + // CHECK-NEXT: ret i32 {{.*}} + a as _ +} + +// CHECK-LABEL: @cast_f32_u8 +#[no_mangle] +pub fn cast_f32_u8(a: f32) -> u8 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptoui float {{.*}} to i8 + // CHECK-NEXT: select i1 {{.*}}, i8 {{.*}}, i8 {{.*}} + // CHECK-NEXT: ret i8 {{.*}} + a as _ +} + + + +// CHECK-LABEL: @cast_unchecked_f64_i64 +#[no_mangle] +pub unsafe fn cast_unchecked_f64_i64(a: f64) -> i64 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptosi double {{.*}} to i64 + // CHECK-NEXT: ret i64 {{.*}} + a.to_int_unchecked() +} + +// CHECK-LABEL: @cast_unchecked_f64_i32 +#[no_mangle] +pub unsafe fn cast_unchecked_f64_i32(a: f64) -> i32 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptosi double {{.*}} to i32 + // CHECK-NEXT: ret i32 {{.*}} + a.to_int_unchecked() +} + +// CHECK-LABEL: @cast_unchecked_f32_i64 +#[no_mangle] +pub unsafe fn cast_unchecked_f32_i64(a: f32) -> i64 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptosi float {{.*}} to i64 + // CHECK-NEXT: ret i64 {{.*}} + a.to_int_unchecked() +} + +// CHECK-LABEL: @cast_unchecked_f32_i32 +#[no_mangle] +pub unsafe fn cast_unchecked_f32_i32(a: f32) -> i32 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptosi float {{.*}} to i32 + // CHECK-NEXT: ret i32 {{.*}} + a.to_int_unchecked() +} + + +// CHECK-LABEL: @cast_unchecked_f64_u64 +#[no_mangle] +pub unsafe fn cast_unchecked_f64_u64(a: f64) -> u64 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptoui double {{.*}} to i64 + // CHECK-NEXT: ret i64 {{.*}} + a.to_int_unchecked() +} + +// CHECK-LABEL: @cast_unchecked_f64_u32 +#[no_mangle] +pub unsafe fn cast_unchecked_f64_u32(a: f64) -> u32 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptoui double {{.*}} to i32 + // CHECK-NEXT: ret i32 {{.*}} + a.to_int_unchecked() +} + +// CHECK-LABEL: @cast_unchecked_f32_u64 +#[no_mangle] +pub unsafe fn cast_unchecked_f32_u64(a: f32) -> u64 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptoui float {{.*}} to i64 + // CHECK-NEXT: ret i64 {{.*}} + a.to_int_unchecked() +} + +// CHECK-LABEL: @cast_unchecked_f32_u32 +#[no_mangle] +pub unsafe fn cast_unchecked_f32_u32(a: f32) -> u32 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptoui float {{.*}} to i32 + // CHECK-NEXT: ret i32 {{.*}} + a.to_int_unchecked() +} + +// CHECK-LABEL: @cast_unchecked_f32_u8 +#[no_mangle] +pub unsafe fn cast_unchecked_f32_u8(a: f32) -> u8 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptoui float {{.*}} to i8 + // CHECK-NEXT: ret i8 {{.*}} + a.to_int_unchecked() +} diff --git a/src/test/codegen/wasm_casts_trapping.rs b/src/test/codegen/wasm_casts_trapping.rs new file mode 100644 index 00000000000..45b90519049 --- /dev/null +++ b/src/test/codegen/wasm_casts_trapping.rs @@ -0,0 +1,169 @@ +// only-wasm32 +// compile-flags: -C target-feature=-nontrapping-fptoint +#![crate_type = "lib"] + +// CHECK-LABEL: @cast_f64_i64 +#[no_mangle] +pub fn cast_f64_i64(a: f64) -> i64 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptosi double {{.*}} to i64 + // CHECK-NEXT: select i1 {{.*}}, i64 {{.*}}, i64 {{.*}} + a as _ +} + +// CHECK-LABEL: @cast_f64_i32 +#[no_mangle] +pub fn cast_f64_i32(a: f64) -> i32 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptosi double {{.*}} to i32 + // CHECK-NEXT: select i1 {{.*}}, i32 {{.*}}, i32 {{.*}} + a as _ +} + +// CHECK-LABEL: @cast_f32_i64 +#[no_mangle] +pub fn cast_f32_i64(a: f32) -> i64 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptosi float {{.*}} to i64 + // CHECK-NEXT: select i1 {{.*}}, i64 {{.*}}, i64 {{.*}} + a as _ +} + +// CHECK-LABEL: @cast_f32_i32 +#[no_mangle] +pub fn cast_f32_i32(a: f32) -> i32 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptosi float {{.*}} to i32 + // CHECK-NEXT: select i1 {{.*}}, i32 {{.*}}, i32 {{.*}} + a as _ +} + + +// CHECK-LABEL: @cast_f64_u64 +#[no_mangle] +pub fn cast_f64_u64(a: f64) -> u64 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptoui double {{.*}} to i64 + // CHECK-NEXT: select i1 {{.*}}, i64 {{.*}}, i64 {{.*}} + a as _ +} + +// CHECK-LABEL: @cast_f64_u32 +#[no_mangle] +pub fn cast_f64_u32(a: f64) -> u32 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptoui double {{.*}} to i32 + // CHECK-NEXT: select i1 {{.*}}, i32 {{.*}}, i32 {{.*}} + a as _ +} + +// CHECK-LABEL: @cast_f32_u64 +#[no_mangle] +pub fn cast_f32_u64(a: f32) -> u64 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptoui float {{.*}} to i64 + // CHECK-NEXT: select i1 {{.*}}, i64 {{.*}}, i64 {{.*}} + a as _ +} + +// CHECK-LABEL: @cast_f32_u32 +#[no_mangle] +pub fn cast_f32_u32(a: f32) -> u32 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptoui float {{.*}} to i32 + // CHECK-NEXT: select i1 {{.*}}, i32 {{.*}}, i32 {{.*}} + a as _ +} + +// CHECK-LABEL: @cast_f32_u8 +#[no_mangle] +pub fn cast_f32_u8(a: f32) -> u8 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptoui float {{.*}} to i8 + // CHECK-NEXT: select i1 {{.*}}, i8 {{.*}}, i8 {{.*}} + a as _ +} + + + +// CHECK-LABEL: @cast_unchecked_f64_i64 +#[no_mangle] +pub unsafe fn cast_unchecked_f64_i64(a: f64) -> i64 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptosi double {{.*}} to i64 + // CHECK-NEXT: ret i64 {{.*}} + a.to_int_unchecked() +} + +// CHECK-LABEL: @cast_unchecked_f64_i32 +#[no_mangle] +pub unsafe fn cast_unchecked_f64_i32(a: f64) -> i32 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptosi double {{.*}} to i32 + // CHECK-NEXT: ret i32 {{.*}} + a.to_int_unchecked() +} + +// CHECK-LABEL: @cast_unchecked_f32_i64 +#[no_mangle] +pub unsafe fn cast_unchecked_f32_i64(a: f32) -> i64 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptosi float {{.*}} to i64 + // CHECK-NEXT: ret i64 {{.*}} + a.to_int_unchecked() +} + +// CHECK-LABEL: @cast_unchecked_f32_i32 +#[no_mangle] +pub unsafe fn cast_unchecked_f32_i32(a: f32) -> i32 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptosi float {{.*}} to i32 + // CHECK-NEXT: ret i32 {{.*}} + a.to_int_unchecked() +} + + +// CHECK-LABEL: @cast_unchecked_f64_u64 +#[no_mangle] +pub unsafe fn cast_unchecked_f64_u64(a: f64) -> u64 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptoui double {{.*}} to i64 + // CHECK-NEXT: ret i64 {{.*}} + a.to_int_unchecked() +} + +// CHECK-LABEL: @cast_unchecked_f64_u32 +#[no_mangle] +pub unsafe fn cast_unchecked_f64_u32(a: f64) -> u32 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptoui double {{.*}} to i32 + // CHECK-NEXT: ret i32 {{.*}} + a.to_int_unchecked() +} + +// CHECK-LABEL: @cast_unchecked_f32_u64 +#[no_mangle] +pub unsafe fn cast_unchecked_f32_u64(a: f32) -> u64 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptoui float {{.*}} to i64 + // CHECK-NEXT: ret i64 {{.*}} + a.to_int_unchecked() +} + +// CHECK-LABEL: @cast_unchecked_f32_u32 +#[no_mangle] +pub unsafe fn cast_unchecked_f32_u32(a: f32) -> u32 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptoui float {{.*}} to i32 + // CHECK-NEXT: ret i32 {{.*}} + a.to_int_unchecked() +} + +// CHECK-LABEL: @cast_unchecked_f32_u8 +#[no_mangle] +pub unsafe fn cast_unchecked_f32_u8(a: f32) -> u8 { + // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: fptoui float {{.*}} to i8 + // CHECK-NEXT: ret i8 {{.*}} + a.to_int_unchecked() +} diff --git a/src/test/mir-opt/instrument_coverage/rustc.bar.InstrumentCoverage.diff b/src/test/mir-opt/instrument_coverage/rustc.bar.InstrumentCoverage.diff index 8a079f0da4b..af2899c887a 100644 --- a/src/test/mir-opt/instrument_coverage/rustc.bar.InstrumentCoverage.diff +++ b/src/test/mir-opt/instrument_coverage/rustc.bar.InstrumentCoverage.diff @@ -7,19 +7,31 @@ bb0: { + StorageLive(_1); // scope 0 at $DIR/instrument_coverage.rs:18:1: 20:2 -+ _1 = const std::intrinsics::count_code_region(const 0_u32) -> bb2; // scope 0 at $DIR/instrument_coverage.rs:18:1: 20:2 ++ _1 = const std::intrinsics::count_code_region(const 0_u32, const 484_u32, const 513_u32) -> bb2; // scope 0 at $DIR/instrument_coverage.rs:18:1: 20:2 + // ty::Const -+ // + ty: unsafe extern "rust-intrinsic" fn(u32) {std::intrinsics::count_code_region} ++ // + ty: unsafe extern "rust-intrinsic" fn(u32, u32, u32) {std::intrinsics::count_code_region} + // + val: Value(Scalar(<ZST>)) + // mir::Constant + // + span: $DIR/instrument_coverage.rs:18:1: 18:1 -+ // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32) {std::intrinsics::count_code_region}, val: Value(Scalar(<ZST>)) } ++ // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32, u32, u32) {std::intrinsics::count_code_region}, val: Value(Scalar(<ZST>)) } + // ty::Const + // + ty: u32 + // + val: Value(Scalar(0x00000000)) + // mir::Constant + // + span: $DIR/instrument_coverage.rs:18:1: 18:1 + // + literal: Const { ty: u32, val: Value(Scalar(0x00000000)) } ++ // ty::Const ++ // + ty: u32 ++ // + val: Value(Scalar(0x000001e4)) ++ // mir::Constant ++ // + span: $DIR/instrument_coverage.rs:18:1: 18:1 ++ // + literal: Const { ty: u32, val: Value(Scalar(0x000001e4)) } ++ // ty::Const ++ // + ty: u32 ++ // + val: Value(Scalar(0x00000201)) ++ // mir::Constant ++ // + span: $DIR/instrument_coverage.rs:18:1: 18:1 ++ // + literal: Const { ty: u32, val: Value(Scalar(0x00000201)) } + } + + bb1 (cleanup): { diff --git a/src/test/mir-opt/instrument_coverage/rustc.main.InstrumentCoverage.diff b/src/test/mir-opt/instrument_coverage/rustc.main.InstrumentCoverage.diff index 3c2ec1dc06b..4a300230f8a 100644 --- a/src/test/mir-opt/instrument_coverage/rustc.main.InstrumentCoverage.diff +++ b/src/test/mir-opt/instrument_coverage/rustc.main.InstrumentCoverage.diff @@ -11,19 +11,31 @@ bb0: { - falseUnwind -> [real: bb1, cleanup: bb2]; // scope 0 at $DIR/instrument_coverage.rs:10:5: 14:6 + StorageLive(_4); // scope 0 at $DIR/instrument_coverage.rs:9:1: 15:2 -+ _4 = const std::intrinsics::count_code_region(const 0_u32) -> bb7; // scope 0 at $DIR/instrument_coverage.rs:9:1: 15:2 ++ _4 = const std::intrinsics::count_code_region(const 0_u32, const 387_u32, const 465_u32) -> bb7; // scope 0 at $DIR/instrument_coverage.rs:9:1: 15:2 + // ty::Const -+ // + ty: unsafe extern "rust-intrinsic" fn(u32) {std::intrinsics::count_code_region} ++ // + ty: unsafe extern "rust-intrinsic" fn(u32, u32, u32) {std::intrinsics::count_code_region} + // + val: Value(Scalar(<ZST>)) + // mir::Constant + // + span: $DIR/instrument_coverage.rs:9:1: 9:1 -+ // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32) {std::intrinsics::count_code_region}, val: Value(Scalar(<ZST>)) } ++ // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32, u32, u32) {std::intrinsics::count_code_region}, val: Value(Scalar(<ZST>)) } + // ty::Const + // + ty: u32 + // + val: Value(Scalar(0x00000000)) + // mir::Constant + // + span: $DIR/instrument_coverage.rs:9:1: 9:1 + // + literal: Const { ty: u32, val: Value(Scalar(0x00000000)) } ++ // ty::Const ++ // + ty: u32 ++ // + val: Value(Scalar(0x00000183)) ++ // mir::Constant ++ // + span: $DIR/instrument_coverage.rs:9:1: 9:1 ++ // + literal: Const { ty: u32, val: Value(Scalar(0x00000183)) } ++ // ty::Const ++ // + ty: u32 ++ // + val: Value(Scalar(0x000001d1)) ++ // mir::Constant ++ // + span: $DIR/instrument_coverage.rs:9:1: 9:1 ++ // + literal: Const { ty: u32, val: Value(Scalar(0x000001d1)) } } bb1: { diff --git a/src/test/run-make/rustc-macro-dep-files/foo.rs b/src/test/run-make/rustc-macro-dep-files/foo.rs index 00b1c26d43f..66db1a21736 100644 --- a/src/test/run-make/rustc-macro-dep-files/foo.rs +++ b/src/test/run-make/rustc-macro-dep-files/foo.rs @@ -7,6 +7,6 @@ use proc_macro::TokenStream; #[proc_macro_derive(A)] pub fn derive(input: TokenStream) -> TokenStream { let input = input.to_string(); - assert!(input.contains("struct A;")); + assert!(input.contains("struct A ;")); "struct B;".parse().unwrap() } diff --git a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs index 1b6a38acb1c..9ba26754778 100644 --- a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs +++ b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs @@ -33,10 +33,10 @@ declare_lint! { declare_lint_pass!(MissingWhitelistedAttrPass => [MISSING_WHITELISTED_ATTR]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingWhitelistedAttrPass { +impl<'tcx> LateLintPass<'tcx> for MissingWhitelistedAttrPass { fn check_fn( &mut self, - cx: &LateContext<'a, 'tcx>, + cx: &LateContext<'tcx>, _: intravisit::FnKind<'tcx>, _: &'tcx hir::FnDecl, _: &'tcx hir::Body, diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs index f8cb1640cb4..bfb4da4c8f5 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs @@ -26,7 +26,7 @@ macro_rules! fake_lint_pass { } } - impl<'a, 'tcx> LateLintPass<'a, 'tcx> for $struct { + impl LateLintPass<'_> for $struct { fn check_crate(&mut self, cx: &LateContext, krate: &rustc_hir::Crate) { $( if !attr::contains_name(&krate.item.attrs, $attr) { diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs index 6978d02c09d..e6a6f73bd47 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs @@ -25,7 +25,7 @@ declare_lint! { declare_lint_pass!(Pass => [CRATE_NOT_OKAY]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'tcx> LateLintPass<'tcx> for Pass { fn check_crate(&mut self, cx: &LateContext, krate: &rustc_hir::Crate) { if !attr::contains_name(&krate.item.attrs, Symbol::intern("crate_okay")) { cx.lint(CRATE_NOT_OKAY, |lint| { diff --git a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs index 5a8eaa63db2..02216b33dc3 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs @@ -20,7 +20,7 @@ declare_lint!(PLEASE_LINT, Warn, "Warn about items named 'pleaselintme'"); declare_lint_pass!(Pass => [TEST_LINT, PLEASE_LINT]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { +impl<'tcx> LateLintPass<'tcx> for Pass { fn check_item(&mut self, cx: &LateContext, it: &rustc_hir::Item) { match &*it.ident.as_str() { "lintme" => cx.lint(TEST_LINT, |lint| { diff --git a/src/test/ui/anon-params/anon-params-denied-2018.stderr b/src/test/ui/anon-params/anon-params-denied-2018.stderr index e7a806a8468..840294db083 100644 --- a/src/test/ui/anon-params/anon-params-denied-2018.stderr +++ b/src/test/ui/anon-params/anon-params-denied-2018.stderr @@ -9,7 +9,7 @@ help: if this is a `self` type, give it a parameter name | LL | fn foo(self: i32); | ^^^^^^^^^ -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | fn foo(i32: TypeName); | ^^^^^^^^^^^^^ @@ -29,7 +29,7 @@ help: if this is a `self` type, give it a parameter name | LL | fn bar_with_default_impl(self: String, String) {} | ^^^^^^^^^^^^ -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | fn bar_with_default_impl(String: TypeName, String) {} | ^^^^^^^^^^^^^^^^ @@ -45,7 +45,7 @@ LL | fn bar_with_default_impl(String, String) {} | ^ expected one of `:`, `@`, or `|` | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | fn bar_with_default_impl(String, String: TypeName) {} | ^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL | fn baz(a:usize, b, c: usize) -> usize { | ^ expected one of `:`, `@`, or `|` | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | fn baz(a:usize, b: TypeName, c: usize) -> usize { | ^^^^^^^^^^^ diff --git a/src/test/ui/asm/sym.rs b/src/test/ui/asm/sym.rs index 8cff16aa75f..9931697e412 100644 --- a/src/test/ui/asm/sym.rs +++ b/src/test/ui/asm/sym.rs @@ -3,7 +3,7 @@ // only-linux // run-pass -#![feature(asm, track_caller, thread_local)] +#![feature(asm, thread_local)] extern "C" fn f1() -> i32 { 111 diff --git a/src/test/ui/async-await/issue-67765-async-diagnostic.rs b/src/test/ui/async-await/issue-67765-async-diagnostic.rs new file mode 100644 index 00000000000..5093916e73a --- /dev/null +++ b/src/test/ui/async-await/issue-67765-async-diagnostic.rs @@ -0,0 +1,16 @@ +// edition:2018 +// +// Regression test for issue #67765 +// Tests that we point at the proper location when giving +// a lifetime error. +fn main() {} + +async fn func<'a>() -> Result<(), &'a str> { + let s = String::new(); + + let b = &s[..]; + + Err(b)?; //~ ERROR cannot return value referencing local variable `s` + + Ok(()) +} diff --git a/src/test/ui/async-await/issue-67765-async-diagnostic.stderr b/src/test/ui/async-await/issue-67765-async-diagnostic.stderr new file mode 100644 index 00000000000..78253042bee --- /dev/null +++ b/src/test/ui/async-await/issue-67765-async-diagnostic.stderr @@ -0,0 +1,12 @@ +error[E0515]: cannot return value referencing local variable `s` + --> $DIR/issue-67765-async-diagnostic.rs:13:11 + | +LL | let b = &s[..]; + | - `s` is borrowed here +LL | +LL | Err(b)?; + | ^ returns a value referencing data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/src/test/ui/async-await/issues/issue-60674.stdout b/src/test/ui/async-await/issues/issue-60674.stdout index 86c3591b3af..395d9e21b38 100644 --- a/src/test/ui/async-await/issues/issue-60674.stdout +++ b/src/test/ui/async-await/issues/issue-60674.stdout @@ -1,3 +1,3 @@ -async fn f(mut x: u8) { } -async fn g((mut x, y, mut z): (u8, u8, u8)) { } -async fn g(mut x: u8, (a, mut b, c): (u8, u8, u8), y: u8) { } +async fn f(mut x : u8) { } +async fn g((mut x, y, mut z) : (u8, u8, u8)) { } +async fn g(mut x : u8, (a, mut b, c) : (u8, u8, u8), y : u8) { } diff --git a/src/test/ui/break-outside-loop.rs b/src/test/ui/break-outside-loop.rs index a6f9d0423d0..26769b30dd5 100644 --- a/src/test/ui/break-outside-loop.rs +++ b/src/test/ui/break-outside-loop.rs @@ -27,7 +27,9 @@ fn main() { // not the `loop`, which failed in the call to `find_breakable`. (#65383) 'lab: loop { || { - break 'lab; //~ ERROR `break` inside of a closure + break 'lab; + //~^ ERROR use of unreachable label `'lab` + //~| ERROR `break` inside of a closure }; } } diff --git a/src/test/ui/break-outside-loop.stderr b/src/test/ui/break-outside-loop.stderr index 8e300fd848d..287bf9af62e 100644 --- a/src/test/ui/break-outside-loop.stderr +++ b/src/test/ui/break-outside-loop.stderr @@ -1,3 +1,14 @@ +error[E0767]: use of unreachable label `'lab` + --> $DIR/break-outside-loop.rs:30:19 + | +LL | 'lab: loop { + | ---- unreachable label defined here +LL | || { +LL | break 'lab; + | ^^^^ unreachable label `'lab` + | + = note: labels are unreachable through functions, closures, async blocks and modules + error[E0268]: `break` outside of a loop --> $DIR/break-outside-loop.rs:10:15 | @@ -41,7 +52,7 @@ LL | || { LL | break 'lab; | ^^^^^^^^^^ cannot `break` inside of a closure -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors -Some errors have detailed explanations: E0267, E0268. +Some errors have detailed explanations: E0267, E0268, E0767. For more information about an error, try `rustc --explain E0267`. diff --git a/src/test/ui/const-generics/lazy-normalization/issue-71922.rs b/src/test/ui/const-generics/lazy-normalization/issue-71922.rs deleted file mode 100644 index 0d392ddcaed..00000000000 --- a/src/test/ui/const-generics/lazy-normalization/issue-71922.rs +++ /dev/null @@ -1,19 +0,0 @@ -#![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete -trait Foo {} - -impl<const N: usize> Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} -//~^ ERROR constant expression depends on a generic parameter - -trait FooImpl<const IS_ZERO: bool> {} - -impl FooImpl<{ 0u8 == 0u8 }> for [(); 0] {} - -impl<const N: usize> FooImpl<{ 0u8 != 0u8 }> for [(); N] {} - -fn foo<T: Foo>(_: T) {} - -fn main() { - foo([]); - foo([()]); -} diff --git a/src/test/ui/const-generics/lazy-normalization/issue-71922.stderr b/src/test/ui/const-generics/lazy-normalization/issue-71922.stderr deleted file mode 100644 index 00917571e71..00000000000 --- a/src/test/ui/const-generics/lazy-normalization/issue-71922.stderr +++ /dev/null @@ -1,19 +0,0 @@ -warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-71922.rs:1:12 - | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information - -error: constant expression depends on a generic parameter - --> $DIR/issue-71922.rs:5:50 - | -LL | impl<const N: usize> Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} - | ^^^^^^^^^^^^^^^^^^^ - | - = note: this may fail depending on what value the parameter takes - -error: aborting due to previous error; 1 warning emitted - diff --git a/src/test/ui/consts/miri_unleashed/drop.stderr b/src/test/ui/consts/miri_unleashed/drop.stderr index 34ab5155e22..1fa3992cc5a 100644 --- a/src/test/ui/consts/miri_unleashed/drop.stderr +++ b/src/test/ui/consts/miri_unleashed/drop.stderr @@ -4,7 +4,9 @@ error[E0080]: could not evaluate static initializer LL | / pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) { LL | | // Code here does not matter - this is replaced by the LL | | // real drop glue by the compiler. -LL | | drop_in_place(to_drop) +LL | | +LL | | // SAFETY: see comment above +LL | | unsafe { drop_in_place(to_drop) } LL | | } | | ^ | | | diff --git a/src/test/ui/consts/offset_from_ub.stderr b/src/test/ui/consts/offset_from_ub.stderr index cde2fe32626..aa65f4de3e1 100644 --- a/src/test/ui/consts/offset_from_ub.stderr +++ b/src/test/ui/consts/offset_from_ub.stderr @@ -1,12 +1,12 @@ error: any use of this value will cause an error --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL | -LL | intrinsics::ptr_offset_from(self, origin) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | ptr_offset_from cannot compute offset of pointers into different allocations. - | inside `std::ptr::const_ptr::<impl *const Struct>::offset_from` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL - | inside `DIFFERENT_ALLOC` at $DIR/offset_from_ub.rs:17:27 +LL | unsafe { intrinsics::ptr_offset_from(self, origin) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | ptr_offset_from cannot compute offset of pointers into different allocations. + | inside `std::ptr::const_ptr::<impl *const Struct>::offset_from` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL + | inside `DIFFERENT_ALLOC` at $DIR/offset_from_ub.rs:17:27 | ::: $DIR/offset_from_ub.rs:11:1 | @@ -24,12 +24,12 @@ LL | | }; error: any use of this value will cause an error --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL | -LL | intrinsics::ptr_offset_from(self, origin) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | unable to turn bytes into a pointer - | inside `std::ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL - | inside `NOT_PTR` at $DIR/offset_from_ub.rs:23:14 +LL | unsafe { intrinsics::ptr_offset_from(self, origin) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | unable to turn bytes into a pointer + | inside `std::ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL + | inside `NOT_PTR` at $DIR/offset_from_ub.rs:23:14 | ::: $DIR/offset_from_ub.rs:21:1 | @@ -42,12 +42,12 @@ LL | | }; error: any use of this value will cause an error --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL | -LL | intrinsics::ptr_offset_from(self, origin) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | exact_div: 1_isize cannot be divided by 2_isize without remainder - | inside `std::ptr::const_ptr::<impl *const u16>::offset_from` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL - | inside `NOT_MULTIPLE_OF_SIZE` at $DIR/offset_from_ub.rs:31:14 +LL | unsafe { intrinsics::ptr_offset_from(self, origin) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | exact_div: 1_isize cannot be divided by 2_isize without remainder + | inside `std::ptr::const_ptr::<impl *const u16>::offset_from` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL + | inside `NOT_MULTIPLE_OF_SIZE` at $DIR/offset_from_ub.rs:31:14 | ::: $DIR/offset_from_ub.rs:26:1 | @@ -63,12 +63,12 @@ LL | | }; error: any use of this value will cause an error --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL | -LL | intrinsics::ptr_offset_from(self, origin) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | inbounds test failed: 0x0 is not a valid pointer - | inside `std::ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL - | inside `OFFSET_FROM_NULL` at $DIR/offset_from_ub.rs:37:14 +LL | unsafe { intrinsics::ptr_offset_from(self, origin) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | inbounds test failed: 0x0 is not a valid pointer + | inside `std::ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL + | inside `OFFSET_FROM_NULL` at $DIR/offset_from_ub.rs:37:14 | ::: $DIR/offset_from_ub.rs:34:1 | @@ -82,12 +82,12 @@ LL | | }; error: any use of this value will cause an error --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL | -LL | intrinsics::ptr_offset_from(self, origin) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | unable to turn bytes into a pointer - | inside `std::ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL - | inside `DIFFERENT_INT` at $DIR/offset_from_ub.rs:44:14 +LL | unsafe { intrinsics::ptr_offset_from(self, origin) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | unable to turn bytes into a pointer + | inside `std::ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL + | inside `DIFFERENT_INT` at $DIR/offset_from_ub.rs:44:14 | ::: $DIR/offset_from_ub.rs:40:1 | diff --git a/src/test/ui/consts/offset_ub.stderr b/src/test/ui/consts/offset_ub.stderr index 0ab81cc0c5b..0a144a6bac2 100644 --- a/src/test/ui/consts/offset_ub.stderr +++ b/src/test/ui/consts/offset_ub.stderr @@ -1,12 +1,12 @@ error: any use of this value will cause an error --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL | -LL | intrinsics::offset(self, count) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | overflowing in-bounds pointer arithmetic - | inside `std::ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL - | inside `BEFORE_START` at $DIR/offset_ub.rs:7:46 +LL | unsafe { intrinsics::offset(self, count) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | overflowing in-bounds pointer arithmetic + | inside `std::ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL + | inside `BEFORE_START` at $DIR/offset_ub.rs:7:46 | ::: $DIR/offset_ub.rs:7:1 | @@ -18,12 +18,12 @@ LL | pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) error: any use of this value will cause an error --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL | -LL | intrinsics::offset(self, count) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | inbounds test failed: pointer must be in-bounds at offset 2, but is outside bounds of allocN which has size 1 - | inside `std::ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL - | inside `AFTER_END` at $DIR/offset_ub.rs:8:43 +LL | unsafe { intrinsics::offset(self, count) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | inbounds test failed: pointer must be in-bounds at offset 2, but is outside bounds of allocN which has size 1 + | inside `std::ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL + | inside `AFTER_END` at $DIR/offset_ub.rs:8:43 | ::: $DIR/offset_ub.rs:8:1 | @@ -33,12 +33,12 @@ LL | pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) }; error: any use of this value will cause an error --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL | -LL | intrinsics::offset(self, count) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | inbounds test failed: pointer must be in-bounds at offset 101, but is outside bounds of allocN which has size 100 - | inside `std::ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL - | inside `AFTER_ARRAY` at $DIR/offset_ub.rs:9:45 +LL | unsafe { intrinsics::offset(self, count) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | inbounds test failed: pointer must be in-bounds at offset 101, but is outside bounds of allocN which has size 100 + | inside `std::ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL + | inside `AFTER_ARRAY` at $DIR/offset_ub.rs:9:45 | ::: $DIR/offset_ub.rs:9:1 | @@ -48,12 +48,12 @@ LL | pub const AFTER_ARRAY: *const u8 = unsafe { [0u8; 100].as_ptr().offset(101) error: any use of this value will cause an error --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL | -LL | intrinsics::offset(self, count) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | overflowing in-bounds pointer arithmetic - | inside `std::ptr::const_ptr::<impl *const u16>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL - | inside `OVERFLOW` at $DIR/offset_ub.rs:11:43 +LL | unsafe { intrinsics::offset(self, count) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | overflowing in-bounds pointer arithmetic + | inside `std::ptr::const_ptr::<impl *const u16>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL + | inside `OVERFLOW` at $DIR/offset_ub.rs:11:43 | ::: $DIR/offset_ub.rs:11:1 | @@ -63,12 +63,12 @@ LL | pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize:: error: any use of this value will cause an error --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL | -LL | intrinsics::offset(self, count) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | overflowing in-bounds pointer arithmetic - | inside `std::ptr::const_ptr::<impl *const u16>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL - | inside `UNDERFLOW` at $DIR/offset_ub.rs:12:44 +LL | unsafe { intrinsics::offset(self, count) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | overflowing in-bounds pointer arithmetic + | inside `std::ptr::const_ptr::<impl *const u16>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL + | inside `UNDERFLOW` at $DIR/offset_ub.rs:12:44 | ::: $DIR/offset_ub.rs:12:1 | @@ -78,12 +78,12 @@ LL | pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize: error: any use of this value will cause an error --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL | -LL | intrinsics::offset(self, count) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | overflowing in-bounds pointer arithmetic - | inside `std::ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL - | inside `OVERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:13:56 +LL | unsafe { intrinsics::offset(self, count) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | overflowing in-bounds pointer arithmetic + | inside `std::ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL + | inside `OVERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:13:56 | ::: $DIR/offset_ub.rs:13:1 | @@ -93,12 +93,12 @@ LL | pub const OVERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (usize::MAX as *cons error: any use of this value will cause an error --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL | -LL | intrinsics::offset(self, count) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | overflowing in-bounds pointer arithmetic - | inside `std::ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL - | inside `UNDERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:14:57 +LL | unsafe { intrinsics::offset(self, count) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | overflowing in-bounds pointer arithmetic + | inside `std::ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL + | inside `UNDERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:14:57 | ::: $DIR/offset_ub.rs:14:1 | @@ -108,12 +108,12 @@ LL | pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).of error: any use of this value will cause an error --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL | -LL | intrinsics::offset(self, count) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | inbounds test failed: pointer must be in-bounds at offset 1, but is outside bounds of allocN which has size 0 - | inside `std::ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL - | inside `ZERO_SIZED_ALLOC` at $DIR/offset_ub.rs:16:50 +LL | unsafe { intrinsics::offset(self, count) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | inbounds test failed: pointer must be in-bounds at offset 1, but is outside bounds of allocN which has size 0 + | inside `std::ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL + | inside `ZERO_SIZED_ALLOC` at $DIR/offset_ub.rs:16:50 | ::: $DIR/offset_ub.rs:16:1 | @@ -123,12 +123,12 @@ LL | pub const ZERO_SIZED_ALLOC: *const u8 = unsafe { [0u8; 0].as_ptr().offset(1 error: any use of this value will cause an error --> $SRC_DIR/libcore/ptr/mut_ptr.rs:LL:COL | -LL | intrinsics::offset(self, count) as *mut T - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | unable to turn bytes into a pointer - | inside `std::ptr::mut_ptr::<impl *mut u8>::offset` at $SRC_DIR/libcore/ptr/mut_ptr.rs:LL:COL - | inside `DANGLING` at $DIR/offset_ub.rs:17:42 +LL | unsafe { intrinsics::offset(self, count) as *mut T } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | unable to turn bytes into a pointer + | inside `std::ptr::mut_ptr::<impl *mut u8>::offset` at $SRC_DIR/libcore/ptr/mut_ptr.rs:LL:COL + | inside `DANGLING` at $DIR/offset_ub.rs:17:42 | ::: $DIR/offset_ub.rs:17:1 | @@ -138,12 +138,12 @@ LL | pub const DANGLING: *const u8 = unsafe { ptr::NonNull::<u8>::dangling().as_ error: any use of this value will cause an error --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL | -LL | intrinsics::offset(self, count) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | inbounds test failed: 0x0 is not a valid pointer - | inside `std::ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL - | inside `NULL_OFFSET_ZERO` at $DIR/offset_ub.rs:20:50 +LL | unsafe { intrinsics::offset(self, count) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | inbounds test failed: 0x0 is not a valid pointer + | inside `std::ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL + | inside `NULL_OFFSET_ZERO` at $DIR/offset_ub.rs:20:50 | ::: $DIR/offset_ub.rs:20:1 | @@ -153,12 +153,12 @@ LL | pub const NULL_OFFSET_ZERO: *const u8 = unsafe { ptr::null::<u8>().offset(0 error: any use of this value will cause an error --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL | -LL | intrinsics::offset(self, count) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | unable to turn bytes into a pointer - | inside `std::ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL - | inside `UNDERFLOW_ABS` at $DIR/offset_ub.rs:23:47 +LL | unsafe { intrinsics::offset(self, count) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | unable to turn bytes into a pointer + | inside `std::ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL + | inside `UNDERFLOW_ABS` at $DIR/offset_ub.rs:23:47 | ::: $DIR/offset_ub.rs:23:1 | diff --git a/src/test/ui/duplicate_entry_error.rs b/src/test/ui/duplicate_entry_error.rs index b8d98a8999b..776ecedea7e 100644 --- a/src/test/ui/duplicate_entry_error.rs +++ b/src/test/ui/duplicate_entry_error.rs @@ -1,3 +1,4 @@ +// normalize-stderr-test "loaded from .*libstd-.*.rlib" -> "loaded from SYSROOT/libstd-*.rlib" // note-pattern: first defined in crate `std`. // Test for issue #31788 and E0152 diff --git a/src/test/ui/duplicate_entry_error.stderr b/src/test/ui/duplicate_entry_error.stderr index 2d52ea3f6c2..61cccf40ed8 100644 --- a/src/test/ui/duplicate_entry_error.stderr +++ b/src/test/ui/duplicate_entry_error.stderr @@ -1,5 +1,5 @@ error[E0152]: found duplicate lang item `panic_impl` - --> $DIR/duplicate_entry_error.rs:10:1 + --> $DIR/duplicate_entry_error.rs:11:1 | LL | / fn panic_impl(info: &PanicInfo) -> ! { LL | | @@ -8,6 +8,8 @@ LL | | } | |_^ | = note: the lang item is first defined in crate `std` (which `duplicate_entry_error` depends on) + = note: first definition in `std` loaded from SYSROOT/libstd-*.rlib + = note: second definition in the local crate (`duplicate_entry_error`) error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0152.rs b/src/test/ui/error-codes/E0152.rs index 94467b9bdde..d716ca1a14f 100644 --- a/src/test/ui/error-codes/E0152.rs +++ b/src/test/ui/error-codes/E0152.rs @@ -1,3 +1,4 @@ +// normalize-stderr-test "loaded from .*liballoc-.*.rlib" -> "loaded from SYSROOT/liballoc-*.rlib" #![feature(lang_items)] #[lang = "owned_box"] diff --git a/src/test/ui/error-codes/E0152.stderr b/src/test/ui/error-codes/E0152.stderr index fbaa276ce10..7445c2880af 100644 --- a/src/test/ui/error-codes/E0152.stderr +++ b/src/test/ui/error-codes/E0152.stderr @@ -1,10 +1,12 @@ error[E0152]: found duplicate lang item `owned_box` - --> $DIR/E0152.rs:4:1 + --> $DIR/E0152.rs:5:1 | LL | struct Foo; | ^^^^^^^^^^^ | = note: the lang item is first defined in crate `alloc` (which `std` depends on) + = note: first definition in `alloc` loaded from SYSROOT/liballoc-*.rlib + = note: second definition in the local crate (`E0152`) error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0767.rs b/src/test/ui/error-codes/E0767.rs new file mode 100644 index 00000000000..6c6cb746e6c --- /dev/null +++ b/src/test/ui/error-codes/E0767.rs @@ -0,0 +1,7 @@ +fn main () { + 'a: loop { + || { + loop { break 'a; } //~ ERROR E0767 + } + } +} diff --git a/src/test/ui/error-codes/E0767.stderr b/src/test/ui/error-codes/E0767.stderr new file mode 100644 index 00000000000..2429823306b --- /dev/null +++ b/src/test/ui/error-codes/E0767.stderr @@ -0,0 +1,14 @@ +error[E0767]: use of unreachable label `'a` + --> $DIR/E0767.rs:4:26 + | +LL | 'a: loop { + | -- unreachable label defined here +LL | || { +LL | loop { break 'a; } + | ^^ unreachable label `'a` + | + = note: labels are unreachable through functions, closures, async blocks and modules + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0767`. diff --git a/src/test/ui/feature-gates/feature-gate-track_caller.rs b/src/test/ui/feature-gates/feature-gate-track_caller.rs deleted file mode 100644 index 5865cf0a4f7..00000000000 --- a/src/test/ui/feature-gates/feature-gate-track_caller.rs +++ /dev/null @@ -1,5 +0,0 @@ -#[track_caller] -fn f() {} -//~^^ ERROR the `#[track_caller]` attribute is an experimental feature - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-track_caller.stderr b/src/test/ui/feature-gates/feature-gate-track_caller.stderr deleted file mode 100644 index 8ceab501617..00000000000 --- a/src/test/ui/feature-gates/feature-gate-track_caller.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: the `#[track_caller]` attribute is an experimental feature - --> $DIR/feature-gate-track_caller.rs:1:1 - | -LL | #[track_caller] - | ^^^^^^^^^^^^^^^ - | - = note: see issue #47809 <https://github.com/rust-lang/rust/issues/47809> for more information - = help: add `#![feature(track_caller)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/hygiene/unpretty-debug.stdout b/src/test/ui/hygiene/unpretty-debug.stdout index acd852103ca..81164030d8e 100644 --- a/src/test/ui/hygiene/unpretty-debug.stdout +++ b/src/test/ui/hygiene/unpretty-debug.stdout @@ -16,8 +16,8 @@ fn y /* 0#0 */() { } /* Expansions: -0: parent: ExpnId(0), call_site_ctxt: #0, kind: Root -1: parent: ExpnId(0), call_site_ctxt: #0, kind: Macro(Bang, "foo") +0: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Root +1: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "foo") SyntaxContexts: #0: parent: #0, outer_mark: (ExpnId(0), Opaque) diff --git a/src/test/ui/in-band-lifetimes/E0687.stderr b/src/test/ui/in-band-lifetimes/E0687.stderr index e8e5100e00e..7aea2f22046 100644 --- a/src/test/ui/in-band-lifetimes/E0687.stderr +++ b/src/test/ui/in-band-lifetimes/E0687.stderr @@ -24,3 +24,4 @@ LL | fn bar(&self, x: fn(&'a u32)) {} error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0687`. diff --git a/src/test/ui/in-band-lifetimes/E0687_where.stderr b/src/test/ui/in-band-lifetimes/E0687_where.stderr index b422869c4db..af0f9665f5d 100644 --- a/src/test/ui/in-band-lifetimes/E0687_where.stderr +++ b/src/test/ui/in-band-lifetimes/E0687_where.stderr @@ -12,3 +12,4 @@ LL | fn baz(x: &impl Fn(&'a u32)) {} error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0687`. diff --git a/src/test/ui/issues/issue-62480.rs b/src/test/ui/issues/issue-62480.rs index bc3e6c69a60..5c3be3e64ee 100644 --- a/src/test/ui/issues/issue-62480.rs +++ b/src/test/ui/issues/issue-62480.rs @@ -5,6 +5,8 @@ fn main() { // `propagate_through_expr` would be the closure and not the `loop`, which wouldn't be found in // `self.break_ln`. (#62480) 'a: { - || break 'a //~ ERROR `break` to unknown label + || break 'a + //~^ ERROR use of unreachable label `'a` + //~| ERROR `break` inside of a closure } } diff --git a/src/test/ui/issues/issue-62480.stderr b/src/test/ui/issues/issue-62480.stderr index de8451ad7df..17085ef908b 100644 --- a/src/test/ui/issues/issue-62480.stderr +++ b/src/test/ui/issues/issue-62480.stderr @@ -1,8 +1,22 @@ -error: `break` to unknown label +error[E0767]: use of unreachable label `'a` + --> $DIR/issue-62480.rs:8:18 + | +LL | 'a: { + | -- unreachable label defined here +LL | || break 'a + | ^^ unreachable label `'a` + | + = note: labels are unreachable through functions, closures, async blocks and modules + +error[E0267]: `break` inside of a closure --> $DIR/issue-62480.rs:8:12 | LL | || break 'a - | ^^^^^^^^ + | -- ^^^^^^^^ cannot `break` inside of a closure + | | + | enclosing closure -error: aborting due to previous error +error: aborting due to 2 previous errors +Some errors have detailed explanations: E0267, E0767. +For more information about an error, try `rustc --explain E0267`. diff --git a/src/test/ui/issues/issue-66702-break-outside-loop-val.rs b/src/test/ui/issues/issue-66702-break-outside-loop-val.rs index bd3c00d2621..05b86cbbf8f 100644 --- a/src/test/ui/issues/issue-66702-break-outside-loop-val.rs +++ b/src/test/ui/issues/issue-66702-break-outside-loop-val.rs @@ -2,6 +2,8 @@ fn main() { 'some_label: loop { - || break 'some_label (); //~ ERROR: `break` inside of a closure + || break 'some_label (); + //~^ ERROR: use of unreachable label `'some_label` + //~| ERROR: `break` inside of a closure } } diff --git a/src/test/ui/issues/issue-66702-break-outside-loop-val.stderr b/src/test/ui/issues/issue-66702-break-outside-loop-val.stderr index 83bde9775b2..f92ede311af 100644 --- a/src/test/ui/issues/issue-66702-break-outside-loop-val.stderr +++ b/src/test/ui/issues/issue-66702-break-outside-loop-val.stderr @@ -1,3 +1,13 @@ +error[E0767]: use of unreachable label `'some_label` + --> $DIR/issue-66702-break-outside-loop-val.rs:5:18 + | +LL | 'some_label: loop { + | ----------- unreachable label defined here +LL | || break 'some_label (); + | ^^^^^^^^^^^ unreachable label `'some_label` + | + = note: labels are unreachable through functions, closures, async blocks and modules + error[E0267]: `break` inside of a closure --> $DIR/issue-66702-break-outside-loop-val.rs:5:12 | @@ -6,6 +16,7 @@ LL | || break 'some_label (); | | | enclosing closure -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0267`. +Some errors have detailed explanations: E0267, E0767. +For more information about an error, try `rustc --explain E0267`. diff --git a/src/test/ui/issues/issue-73541-1.rs b/src/test/ui/issues/issue-73541-1.rs new file mode 100644 index 00000000000..7fb0d6c39ff --- /dev/null +++ b/src/test/ui/issues/issue-73541-1.rs @@ -0,0 +1,12 @@ +// edition:2018 + +fn main() { + 'a: loop { + async { + loop { + continue 'a + //~^ ERROR use of unreachable label `'a` + } + }; + } +} diff --git a/src/test/ui/issues/issue-73541-1.stderr b/src/test/ui/issues/issue-73541-1.stderr new file mode 100644 index 00000000000..80c1fdf002a --- /dev/null +++ b/src/test/ui/issues/issue-73541-1.stderr @@ -0,0 +1,14 @@ +error[E0767]: use of unreachable label `'a` + --> $DIR/issue-73541-1.rs:7:26 + | +LL | 'a: loop { + | -- unreachable label defined here +... +LL | continue 'a + | ^^ unreachable label `'a` + | + = note: labels are unreachable through functions, closures, async blocks and modules + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0767`. diff --git a/src/test/ui/issues/issue-73541-2.rs b/src/test/ui/issues/issue-73541-2.rs new file mode 100644 index 00000000000..70b4ab25376 --- /dev/null +++ b/src/test/ui/issues/issue-73541-2.rs @@ -0,0 +1,20 @@ +// edition:2018 + +async fn c() { + 'a: loop { + macro_rules! b { + () => { + continue 'a + //~^ ERROR use of unreachable label `'a` + } + } + + async { + loop { + b!(); + } + }; + } +} + +fn main() { } diff --git a/src/test/ui/issues/issue-73541-2.stderr b/src/test/ui/issues/issue-73541-2.stderr new file mode 100644 index 00000000000..75d769c4e15 --- /dev/null +++ b/src/test/ui/issues/issue-73541-2.stderr @@ -0,0 +1,18 @@ +error[E0767]: use of unreachable label `'a` + --> $DIR/issue-73541-2.rs:7:26 + | +LL | 'a: loop { + | -- unreachable label defined here +... +LL | continue 'a + | ^^ unreachable label `'a` +... +LL | b!(); + | ----- in this macro invocation + | + = note: labels are unreachable through functions, closures, async blocks and modules + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0767`. diff --git a/src/test/ui/issues/issue-73541-3.rs b/src/test/ui/issues/issue-73541-3.rs new file mode 100644 index 00000000000..02ca02da8ed --- /dev/null +++ b/src/test/ui/issues/issue-73541-3.rs @@ -0,0 +1,9 @@ +fn main() { + 'aaaaab: loop { + || { + loop { continue 'aaaaaa } + //~^ ERROR use of undeclared label `'aaaaaa` + }; + + } +} diff --git a/src/test/ui/issues/issue-73541-3.stderr b/src/test/ui/issues/issue-73541-3.stderr new file mode 100644 index 00000000000..53487aaca99 --- /dev/null +++ b/src/test/ui/issues/issue-73541-3.stderr @@ -0,0 +1,12 @@ +error[E0426]: use of undeclared label `'aaaaaa` + --> $DIR/issue-73541-3.rs:4:29 + | +LL | 'aaaaab: loop { + | ------- a label with a similar name exists but is unreachable +LL | || { +LL | loop { continue 'aaaaaa } + | ^^^^^^^ undeclared label `'aaaaaa` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0426`. diff --git a/src/test/ui/issues/issue-73541.rs b/src/test/ui/issues/issue-73541.rs new file mode 100644 index 00000000000..399a07cd3fc --- /dev/null +++ b/src/test/ui/issues/issue-73541.rs @@ -0,0 +1,9 @@ +fn main() { + 'a: loop { + || { + loop { continue 'a } + //~^ ERROR use of unreachable label `'a` + }; + + } +} diff --git a/src/test/ui/issues/issue-73541.stderr b/src/test/ui/issues/issue-73541.stderr new file mode 100644 index 00000000000..4bb466ff16c --- /dev/null +++ b/src/test/ui/issues/issue-73541.stderr @@ -0,0 +1,14 @@ +error[E0767]: use of unreachable label `'a` + --> $DIR/issue-73541.rs:4:29 + | +LL | 'a: loop { + | -- unreachable label defined here +LL | || { +LL | loop { continue 'a } + | ^^ unreachable label `'a` + | + = note: labels are unreachable through functions, closures, async blocks and modules + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0767`. diff --git a/src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.rs b/src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.rs index 19d7f019047..8deb3655158 100644 --- a/src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.rs +++ b/src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.rs @@ -1,3 +1,3 @@ fn main() { - [0].iter().flat_map(|a| [0].iter().map(|_| &a)); //~ ERROR `a` does not live long enough + [0].iter().flat_map(|a| [0].iter().map(|_| &a)); //~ ERROR closure may outlive } diff --git a/src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.stderr b/src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.stderr index cb0b481e748..34470119112 100644 --- a/src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.stderr +++ b/src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.stderr @@ -1,15 +1,21 @@ -error[E0597]: `a` does not live long enough - --> $DIR/unnamed-closure-doesnt-life-long-enough-issue-67634.rs:2:49 +error[E0373]: closure may outlive the current function, but it borrows `a`, which is owned by the current function + --> $DIR/unnamed-closure-doesnt-life-long-enough-issue-67634.rs:2:44 | LL | [0].iter().flat_map(|a| [0].iter().map(|_| &a)); - | - ^- ...but `a` will be dropped here, when the enclosing closure returns - | | | - | | `a` would have to be valid for `'_`... - | has type `&i32` + | ^^^ - `a` is borrowed here + | | + | may outlive borrowed value `a` | - = note: functions cannot return a borrow to data owned within the function's scope, functions can only return borrows to data passed as arguments - = note: to learn more, visit <https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#dangling-references> +note: closure is returned here + --> $DIR/unnamed-closure-doesnt-life-long-enough-issue-67634.rs:2:29 + | +LL | [0].iter().flat_map(|a| [0].iter().map(|_| &a)); + | ^^^^^^^^^^^^^^^^^^^^^^ +help: to force the closure to take ownership of `a` (and any other referenced variables), use the `move` keyword + | +LL | [0].iter().flat_map(|a| [0].iter().map(move |_| &a)); + | ^^^^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0597`. +For more information about this error, try `rustc --explain E0373`. diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode-1.rs b/src/test/ui/lint/lint-nonstandard-style-unicode-1.rs new file mode 100644 index 00000000000..4f90bd98c63 --- /dev/null +++ b/src/test/ui/lint/lint-nonstandard-style-unicode-1.rs @@ -0,0 +1,50 @@ +#![allow(dead_code)] + +#![forbid(non_camel_case_types)] +#![feature(non_ascii_idents)] + +// Some scripts (e.g., hiragana) don't have a concept of +// upper/lowercase + +// 1. non_camel_case_types + +// Can start with non-lowercase letter +struct Θχ; +struct ヒa; + +struct χa; +//~^ ERROR type `χa` should have an upper camel case name + +// If there's already leading or trailing underscores, they get trimmed before checking. +// This is fine: +struct _ヒb; + +// This is not: +struct __χa; +//~^ ERROR type `__χa` should have an upper camel case name + +// Besides this, we cannot have two continous underscores in the middle. + +struct 对__否; +//~^ ERROR type `对__否` should have an upper camel case name + +struct ヒ__χ; +//~^ ERROR type `ヒ__χ` should have an upper camel case name + +// also cannot have lowercase letter next to a underscore. +// so this triggers the lint: + +struct Hello_你好; +//~^ ERROR type `Hello_你好` should have an upper camel case name + +struct Hello_World; +//~^ ERROR type `Hello_World` should have an upper camel case name + +struct 你_ӟ; +//~^ ERROR type `你_ӟ` should have an upper camel case name + +// and this is ok: + +struct 你_好; + +fn main() {} diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode-1.stderr b/src/test/ui/lint/lint-nonstandard-style-unicode-1.stderr new file mode 100644 index 00000000000..37100265659 --- /dev/null +++ b/src/test/ui/lint/lint-nonstandard-style-unicode-1.stderr @@ -0,0 +1,50 @@ +error: type `χa` should have an upper camel case name + --> $DIR/lint-nonstandard-style-unicode-1.rs:15:8 + | +LL | struct χa; + | ^^ help: convert the identifier to upper camel case: `Χa` + | +note: the lint level is defined here + --> $DIR/lint-nonstandard-style-unicode-1.rs:3:11 + | +LL | #![forbid(non_camel_case_types)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: type `__χa` should have an upper camel case name + --> $DIR/lint-nonstandard-style-unicode-1.rs:23:8 + | +LL | struct __χa; + | ^^^^ help: convert the identifier to upper camel case: `Χa` + +error: type `对__否` should have an upper camel case name + --> $DIR/lint-nonstandard-style-unicode-1.rs:28:8 + | +LL | struct 对__否; + | ^^^^^^ help: convert the identifier to upper camel case: `对_否` + +error: type `ヒ__χ` should have an upper camel case name + --> $DIR/lint-nonstandard-style-unicode-1.rs:31:8 + | +LL | struct ヒ__χ; + | ^^^^^ help: convert the identifier to upper camel case: `ヒΧ` + +error: type `Hello_你好` should have an upper camel case name + --> $DIR/lint-nonstandard-style-unicode-1.rs:37:8 + | +LL | struct Hello_你好; + | ^^^^^^^^^^ help: convert the identifier to upper camel case: `Hello你好` + +error: type `Hello_World` should have an upper camel case name + --> $DIR/lint-nonstandard-style-unicode-1.rs:40:8 + | +LL | struct Hello_World; + | ^^^^^^^^^^^ help: convert the identifier to upper camel case: `HelloWorld` + +error: type `你_ӟ` should have an upper camel case name + --> $DIR/lint-nonstandard-style-unicode-1.rs:43:8 + | +LL | struct 你_ӟ; + | ^^^^ help: convert the identifier to upper camel case: `你Ӟ` + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode-2.rs b/src/test/ui/lint/lint-nonstandard-style-unicode-2.rs new file mode 100644 index 00000000000..813e0ea5c57 --- /dev/null +++ b/src/test/ui/lint/lint-nonstandard-style-unicode-2.rs @@ -0,0 +1,30 @@ +#![allow(dead_code)] + +#![forbid(non_snake_case)] +#![feature(non_ascii_idents)] + +// Some scripts (e.g., hiragana) don't have a concept of +// upper/lowercase + +// 2. non_snake_case + +// Can only use non-uppercase letters. +// So this works: + +fn 编程() {} + +// but this doesn't: + +fn Ц() {} +//~^ ERROR function `Ц` should have a snake case name + +// besides this, you cannot use continous underscores in the middle + +fn 分__隔() {} +//~^ ERROR function `分__隔` should have a snake case name + +// but you can use them both at the beginning and at the end. + +fn _______不_连_续_的_存_在_______() {} + +fn main() {} diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode-2.stderr b/src/test/ui/lint/lint-nonstandard-style-unicode-2.stderr new file mode 100644 index 00000000000..0b309e315a4 --- /dev/null +++ b/src/test/ui/lint/lint-nonstandard-style-unicode-2.stderr @@ -0,0 +1,20 @@ +error: function `Ц` should have a snake case name + --> $DIR/lint-nonstandard-style-unicode-2.rs:18:4 + | +LL | fn Ц() {} + | ^ help: convert the identifier to snake case: `ц` + | +note: the lint level is defined here + --> $DIR/lint-nonstandard-style-unicode-2.rs:3:11 + | +LL | #![forbid(non_snake_case)] + | ^^^^^^^^^^^^^^ + +error: function `分__隔` should have a snake case name + --> $DIR/lint-nonstandard-style-unicode-2.rs:23:4 + | +LL | fn 分__隔() {} + | ^^^^^^ help: convert the identifier to snake case: `分_隔` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode-3.rs b/src/test/ui/lint/lint-nonstandard-style-unicode-3.rs new file mode 100644 index 00000000000..b17c2de39a0 --- /dev/null +++ b/src/test/ui/lint/lint-nonstandard-style-unicode-3.rs @@ -0,0 +1,25 @@ +#![allow(dead_code)] + +#![forbid(non_upper_case_globals)] +#![feature(non_ascii_idents)] + +// Some scripts (e.g., hiragana) don't have a concept of +// upper/lowercase + +// 3. non_upper_case_globals + +// Can only use non-lowercase letters. +// So this works: + +static ラ: usize = 0; + +// but this doesn't: + +static τεχ: f32 = 3.14159265; +//~^ ERROR static variable `τεχ` should have an upper case name + +// This has no limit at all on underscore usages. + +static __密__封__线__内__禁__止__答__题__: bool = true; + +fn main() {} diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode-3.stderr b/src/test/ui/lint/lint-nonstandard-style-unicode-3.stderr new file mode 100644 index 00000000000..44bd5ad55ff --- /dev/null +++ b/src/test/ui/lint/lint-nonstandard-style-unicode-3.stderr @@ -0,0 +1,14 @@ +error: static variable `τεχ` should have an upper case name + --> $DIR/lint-nonstandard-style-unicode-3.rs:18:8 + | +LL | static τεχ: f32 = 3.14159265; + | ^^^ help: convert the identifier to upper case: `ΤΕΧ` + | +note: the lint level is defined here + --> $DIR/lint-nonstandard-style-unicode-3.rs:3:11 + | +LL | #![forbid(non_upper_case_globals)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode.rs b/src/test/ui/lint/lint-nonstandard-style-unicode.rs deleted file mode 100644 index 9f16cb20fb3..00000000000 --- a/src/test/ui/lint/lint-nonstandard-style-unicode.rs +++ /dev/null @@ -1,16 +0,0 @@ -// check-pass - -#![allow(dead_code)] - -#![forbid(non_camel_case_types)] -#![forbid(non_upper_case_globals)] -#![feature(non_ascii_idents)] - -// Some scripts (e.g., hiragana) don't have a concept of -// upper/lowercase - -struct ヒ; - -static ラ: usize = 0; - -pub fn main() {} diff --git a/src/test/ui/macros/doc-comment.rs b/src/test/ui/macros/doc-comment.rs new file mode 100644 index 00000000000..9de39e9b56c --- /dev/null +++ b/src/test/ui/macros/doc-comment.rs @@ -0,0 +1,25 @@ +// check-pass +// Tests that we properly handle a nested macro expansion +// involving a `#[doc]` attribute +#![deny(missing_docs)] +//! Crate docs + +macro_rules! doc_comment { + ($x:expr, $($tt:tt)*) => { + #[doc = $x] + $($tt)* + } +} + +macro_rules! make_comment { + () => { + doc_comment!("Function docs", + pub fn bar() {} + ); + } +} + + +make_comment!(); + +fn main() {} diff --git a/src/test/ui/macros/issue-68060.rs b/src/test/ui/macros/issue-68060.rs index bc70f8ffec2..8772e98b6e9 100644 --- a/src/test/ui/macros/issue-68060.rs +++ b/src/test/ui/macros/issue-68060.rs @@ -1,5 +1,3 @@ -#![feature(track_caller)] - fn main() { (0..) .map( diff --git a/src/test/ui/macros/issue-68060.stderr b/src/test/ui/macros/issue-68060.stderr index 22187c4a409..b9b2f946c59 100644 --- a/src/test/ui/macros/issue-68060.stderr +++ b/src/test/ui/macros/issue-68060.stderr @@ -1,5 +1,5 @@ error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions - --> $DIR/issue-68060.rs:6:13 + --> $DIR/issue-68060.rs:4:13 | LL | #[target_feature(enable = "")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -11,13 +11,13 @@ LL | |_| (), = help: add `#![feature(target_feature_11)]` to the crate attributes to enable error: the feature named `` is not valid for this target - --> $DIR/issue-68060.rs:6:30 + --> $DIR/issue-68060.rs:4:30 | LL | #[target_feature(enable = "")] | ^^^^^^^^^^^ `` is not valid for this target error[E0737]: `#[track_caller]` requires Rust ABI - --> $DIR/issue-68060.rs:9:13 + --> $DIR/issue-68060.rs:7:13 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ diff --git a/src/test/ui/numbers-arithmetic/saturating-float-casts-impl.rs b/src/test/ui/numbers-arithmetic/saturating-float-casts-impl.rs new file mode 100644 index 00000000000..6c3e503693c --- /dev/null +++ b/src/test/ui/numbers-arithmetic/saturating-float-casts-impl.rs @@ -0,0 +1,507 @@ +// ignore-test + +// Tests saturating float->int casts. See u128-as-f32.rs for the opposite direction. +// +// Some of these tests come from a similar file in miri, +// tests/run-pass/float.rs. Individual test cases are potentially duplicated +// with the previously existing tests, but since this runs so quickly anyway, +// we're not spending the time to figure out exactly which ones should be +// merged. + +extern crate test; + +use self::test::black_box; +use std::{f32, f64}; +#[cfg(not(target_os = "emscripten"))] +use std::{i128, u128}; +use std::{i16, i32, i64, i8, u16, u32, u64, u8}; + +macro_rules! test { + ($val:expr, $src_ty:ident -> $dest_ty:ident, $expected:expr) => ( + // black_box disables constant evaluation to test run-time conversions: + assert_eq!(black_box::<$src_ty>($val) as $dest_ty, $expected, + "run-time {} -> {}", stringify!($src_ty), stringify!($dest_ty)); + + { + const X: $src_ty = $val; + const Y: $dest_ty = X as $dest_ty; + assert_eq!(Y, $expected, + "const eval {} -> {}", stringify!($src_ty), stringify!($dest_ty)); + } + ); + + ($fval:expr, f* -> $ity:ident, $ival:expr) => ( + test!($fval, f32 -> $ity, $ival); + test!($fval, f64 -> $ity, $ival); + ) +} + +macro_rules! common_fptoi_tests { + ($fty:ident -> $($ity:ident)+) => ({ $( + test!($fty::NAN, $fty -> $ity, 0); + test!($fty::INFINITY, $fty -> $ity, $ity::MAX); + test!($fty::NEG_INFINITY, $fty -> $ity, $ity::MIN); + // These two tests are not solely float->int tests, in particular the latter relies on + // `u128::MAX as f32` not being UB. But that's okay, since this file tests int->float + // as well, the test is just slightly misplaced. + test!($ity::MIN as $fty, $fty -> $ity, $ity::MIN); + test!($ity::MAX as $fty, $fty -> $ity, $ity::MAX); + test!(0., $fty -> $ity, 0); + test!($fty::MIN_POSITIVE, $fty -> $ity, 0); + test!(-0.9, $fty -> $ity, 0); + test!(1., $fty -> $ity, 1); + test!(42., $fty -> $ity, 42); + )+ }); + + (f* -> $($ity:ident)+) => ({ + common_fptoi_tests!(f32 -> $($ity)+); + common_fptoi_tests!(f64 -> $($ity)+); + }) +} + +macro_rules! fptoui_tests { + ($fty: ident -> $($ity: ident)+) => ({ $( + test!(-0., $fty -> $ity, 0); + test!(-$fty::MIN_POSITIVE, $fty -> $ity, 0); + test!(-0.99999994, $fty -> $ity, 0); + test!(-1., $fty -> $ity, 0); + test!(-100., $fty -> $ity, 0); + test!(#[allow(overflowing_literals)] -1e50, $fty -> $ity, 0); + test!(#[allow(overflowing_literals)] -1e130, $fty -> $ity, 0); + )+ }); + + (f* -> $($ity:ident)+) => ({ + fptoui_tests!(f32 -> $($ity)+); + fptoui_tests!(f64 -> $($ity)+); + }) +} + +use std::fmt::Debug; + +// Helper function to avoid promotion so that this tests "run-time" casts, not CTFE. +#[track_caller] +#[inline(never)] +fn assert_eq<T: PartialEq + Debug>(x: T, y: T) { + assert_eq!(x, y); +} + +trait FloatToInt<Int>: Copy { + fn cast(self) -> Int; + unsafe fn cast_unchecked(self) -> Int; +} + +impl FloatToInt<i8> for f32 { + fn cast(self) -> i8 { + self as _ + } + unsafe fn cast_unchecked(self) -> i8 { + self.to_int_unchecked() + } +} +impl FloatToInt<i32> for f32 { + fn cast(self) -> i32 { + self as _ + } + unsafe fn cast_unchecked(self) -> i32 { + self.to_int_unchecked() + } +} +impl FloatToInt<u32> for f32 { + fn cast(self) -> u32 { + self as _ + } + unsafe fn cast_unchecked(self) -> u32 { + self.to_int_unchecked() + } +} +impl FloatToInt<i64> for f32 { + fn cast(self) -> i64 { + self as _ + } + unsafe fn cast_unchecked(self) -> i64 { + self.to_int_unchecked() + } +} +impl FloatToInt<u64> for f32 { + fn cast(self) -> u64 { + self as _ + } + unsafe fn cast_unchecked(self) -> u64 { + self.to_int_unchecked() + } +} + +impl FloatToInt<i8> for f64 { + fn cast(self) -> i8 { + self as _ + } + unsafe fn cast_unchecked(self) -> i8 { + self.to_int_unchecked() + } +} +impl FloatToInt<i32> for f64 { + fn cast(self) -> i32 { + self as _ + } + unsafe fn cast_unchecked(self) -> i32 { + self.to_int_unchecked() + } +} +impl FloatToInt<u32> for f64 { + fn cast(self) -> u32 { + self as _ + } + unsafe fn cast_unchecked(self) -> u32 { + self.to_int_unchecked() + } +} +impl FloatToInt<i64> for f64 { + fn cast(self) -> i64 { + self as _ + } + unsafe fn cast_unchecked(self) -> i64 { + self.to_int_unchecked() + } +} +impl FloatToInt<u64> for f64 { + fn cast(self) -> u64 { + self as _ + } + unsafe fn cast_unchecked(self) -> u64 { + self.to_int_unchecked() + } +} +// FIXME emscripten does not support i128 +#[cfg(not(target_os = "emscripten"))] +impl FloatToInt<i128> for f64 { + fn cast(self) -> i128 { + self as _ + } + unsafe fn cast_unchecked(self) -> i128 { + self.to_int_unchecked() + } +} +// FIXME emscripten does not support i128 +#[cfg(not(target_os = "emscripten"))] +impl FloatToInt<u128> for f64 { + fn cast(self) -> u128 { + self as _ + } + unsafe fn cast_unchecked(self) -> u128 { + self.to_int_unchecked() + } +} + +/// Test this cast both via `as` and via `to_int_unchecked` (i.e., it must not saturate). +#[track_caller] +#[inline(never)] +fn test_both_cast<F, I>(x: F, y: I) +where + F: FloatToInt<I>, + I: PartialEq + Debug, +{ + assert_eq!(x.cast(), y); + assert_eq!(unsafe { x.cast_unchecked() }, y); +} + +fn casts() { + // f32 -> i8 + test_both_cast::<f32, i8>(127.99, 127); + test_both_cast::<f32, i8>(-128.99, -128); + + // f32 -> i32 + test_both_cast::<f32, i32>(0.0, 0); + test_both_cast::<f32, i32>(-0.0, 0); + test_both_cast::<f32, i32>(/*0x1p-149*/ f32::from_bits(0x00000001), 0); + test_both_cast::<f32, i32>(/*-0x1p-149*/ f32::from_bits(0x80000001), 0); + test_both_cast::<f32, i32>(/*0x1.19999ap+0*/ f32::from_bits(0x3f8ccccd), 1); + test_both_cast::<f32, i32>(/*-0x1.19999ap+0*/ f32::from_bits(0xbf8ccccd), -1); + test_both_cast::<f32, i32>(1.9, 1); + test_both_cast::<f32, i32>(-1.9, -1); + test_both_cast::<f32, i32>(5.0, 5); + test_both_cast::<f32, i32>(-5.0, -5); + test_both_cast::<f32, i32>(2147483520.0, 2147483520); + test_both_cast::<f32, i32>(-2147483648.0, -2147483648); + // unrepresentable casts + assert_eq::<i32>(2147483648.0f32 as i32, i32::MAX); + assert_eq::<i32>(-2147483904.0f32 as i32, i32::MIN); + assert_eq::<i32>(f32::MAX as i32, i32::MAX); + assert_eq::<i32>(f32::MIN as i32, i32::MIN); + assert_eq::<i32>(f32::INFINITY as i32, i32::MAX); + assert_eq::<i32>(f32::NEG_INFINITY as i32, i32::MIN); + assert_eq::<i32>(f32::NAN as i32, 0); + assert_eq::<i32>((-f32::NAN) as i32, 0); + + // f32 -> u32 + test_both_cast::<f32, u32>(0.0, 0); + test_both_cast::<f32, u32>(-0.0, 0); + test_both_cast::<f32, u32>(-0.9999999, 0); + test_both_cast::<f32, u32>(/*0x1p-149*/ f32::from_bits(0x1), 0); + test_both_cast::<f32, u32>(/*-0x1p-149*/ f32::from_bits(0x80000001), 0); + test_both_cast::<f32, u32>(/*0x1.19999ap+0*/ f32::from_bits(0x3f8ccccd), 1); + test_both_cast::<f32, u32>(1.9, 1); + test_both_cast::<f32, u32>(5.0, 5); + test_both_cast::<f32, u32>(2147483648.0, 0x8000_0000); + test_both_cast::<f32, u32>(4294967040.0, 0u32.wrapping_sub(256)); + test_both_cast::<f32, u32>(/*-0x1.ccccccp-1*/ f32::from_bits(0xbf666666), 0); + test_both_cast::<f32, u32>(/*-0x1.fffffep-1*/ f32::from_bits(0xbf7fffff), 0); + test_both_cast::<f32, u32>((u32::MAX - 128) as f32, u32::MAX - 255); // rounding loss + + // unrepresentable casts: + + // rounds up and then becomes unrepresentable + assert_eq::<u32>((u32::MAX - 127) as f32 as u32, u32::MAX); + + assert_eq::<u32>(4294967296.0f32 as u32, u32::MAX); + assert_eq::<u32>(-5.0f32 as u32, 0); + assert_eq::<u32>(f32::MAX as u32, u32::MAX); + assert_eq::<u32>(f32::MIN as u32, 0); + assert_eq::<u32>(f32::INFINITY as u32, u32::MAX); + assert_eq::<u32>(f32::NEG_INFINITY as u32, 0); + assert_eq::<u32>(f32::NAN as u32, 0); + assert_eq::<u32>((-f32::NAN) as u32, 0); + + // f32 -> i64 + test_both_cast::<f32, i64>(4294967296.0, 4294967296); + test_both_cast::<f32, i64>(-4294967296.0, -4294967296); + test_both_cast::<f32, i64>(9223371487098961920.0, 9223371487098961920); + test_both_cast::<f32, i64>(-9223372036854775808.0, -9223372036854775808); + + // f64 -> i8 + test_both_cast::<f64, i8>(127.99, 127); + test_both_cast::<f64, i8>(-128.99, -128); + + // f64 -> i32 + test_both_cast::<f64, i32>(0.0, 0); + test_both_cast::<f64, i32>(-0.0, 0); + test_both_cast::<f64, i32>(/*0x1.199999999999ap+0*/ f64::from_bits(0x3ff199999999999a), 1); + test_both_cast::<f64, i32>( + /*-0x1.199999999999ap+0*/ f64::from_bits(0xbff199999999999a), + -1, + ); + test_both_cast::<f64, i32>(1.9, 1); + test_both_cast::<f64, i32>(-1.9, -1); + test_both_cast::<f64, i32>(1e8, 100_000_000); + test_both_cast::<f64, i32>(2147483647.0, 2147483647); + test_both_cast::<f64, i32>(-2147483648.0, -2147483648); + // unrepresentable casts + assert_eq::<i32>(2147483648.0f64 as i32, i32::MAX); + assert_eq::<i32>(-2147483649.0f64 as i32, i32::MIN); + + // f64 -> i64 + test_both_cast::<f64, i64>(0.0, 0); + test_both_cast::<f64, i64>(-0.0, 0); + test_both_cast::<f64, i64>(/*0x0.0000000000001p-1022*/ f64::from_bits(0x1), 0); + test_both_cast::<f64, i64>( + /*-0x0.0000000000001p-1022*/ f64::from_bits(0x8000000000000001), + 0, + ); + test_both_cast::<f64, i64>(/*0x1.199999999999ap+0*/ f64::from_bits(0x3ff199999999999a), 1); + test_both_cast::<f64, i64>( + /*-0x1.199999999999ap+0*/ f64::from_bits(0xbff199999999999a), + -1, + ); + test_both_cast::<f64, i64>(5.0, 5); + test_both_cast::<f64, i64>(5.9, 5); + test_both_cast::<f64, i64>(-5.0, -5); + test_both_cast::<f64, i64>(-5.9, -5); + test_both_cast::<f64, i64>(4294967296.0, 4294967296); + test_both_cast::<f64, i64>(-4294967296.0, -4294967296); + test_both_cast::<f64, i64>(9223372036854774784.0, 9223372036854774784); + test_both_cast::<f64, i64>(-9223372036854775808.0, -9223372036854775808); + // unrepresentable casts + assert_eq::<i64>(9223372036854775808.0f64 as i64, i64::MAX); + assert_eq::<i64>(-9223372036854777856.0f64 as i64, i64::MIN); + assert_eq::<i64>(f64::MAX as i64, i64::MAX); + assert_eq::<i64>(f64::MIN as i64, i64::MIN); + assert_eq::<i64>(f64::INFINITY as i64, i64::MAX); + assert_eq::<i64>(f64::NEG_INFINITY as i64, i64::MIN); + assert_eq::<i64>(f64::NAN as i64, 0); + assert_eq::<i64>((-f64::NAN) as i64, 0); + + // f64 -> u64 + test_both_cast::<f64, u64>(0.0, 0); + test_both_cast::<f64, u64>(-0.0, 0); + test_both_cast::<f64, u64>(-0.99999999999, 0); + test_both_cast::<f64, u64>(5.0, 5); + test_both_cast::<f64, u64>(1e16, 10000000000000000); + test_both_cast::<f64, u64>((u64::MAX - 1024) as f64, u64::MAX - 2047); // rounding loss + test_both_cast::<f64, u64>(9223372036854775808.0, 9223372036854775808); + // unrepresentable casts + assert_eq::<u64>(-5.0f64 as u64, 0); + // rounds up and then becomes unrepresentable + assert_eq::<u64>((u64::MAX - 1023) as f64 as u64, u64::MAX); + assert_eq::<u64>(18446744073709551616.0f64 as u64, u64::MAX); + assert_eq::<u64>(f64::MAX as u64, u64::MAX); + assert_eq::<u64>(f64::MIN as u64, 0); + assert_eq::<u64>(f64::INFINITY as u64, u64::MAX); + assert_eq::<u64>(f64::NEG_INFINITY as u64, 0); + assert_eq::<u64>(f64::NAN as u64, 0); + assert_eq::<u64>((-f64::NAN) as u64, 0); + + // FIXME emscripten does not support i128 + #[cfg(not(target_os = "emscripten"))] + { + // f64 -> i128 + assert_eq::<i128>(f64::MAX as i128, i128::MAX); + assert_eq::<i128>(f64::MIN as i128, i128::MIN); + + // f64 -> u128 + assert_eq::<u128>(f64::MAX as u128, u128::MAX); + assert_eq::<u128>(f64::MIN as u128, 0); + } + + // int -> f32 + assert_eq::<f32>(127i8 as f32, 127.0); + assert_eq::<f32>(2147483647i32 as f32, 2147483648.0); + assert_eq::<f32>((-2147483648i32) as f32, -2147483648.0); + assert_eq::<f32>(1234567890i32 as f32, /*0x1.26580cp+30*/ f32::from_bits(0x4e932c06)); + assert_eq::<f32>(16777217i32 as f32, 16777216.0); + assert_eq::<f32>((-16777217i32) as f32, -16777216.0); + assert_eq::<f32>(16777219i32 as f32, 16777220.0); + assert_eq::<f32>((-16777219i32) as f32, -16777220.0); + assert_eq::<f32>( + 0x7fffff4000000001i64 as f32, + /*0x1.fffffep+62*/ f32::from_bits(0x5effffff), + ); + assert_eq::<f32>( + 0x8000004000000001u64 as i64 as f32, + /*-0x1.fffffep+62*/ f32::from_bits(0xdeffffff), + ); + assert_eq::<f32>( + 0x0020000020000001i64 as f32, + /*0x1.000002p+53*/ f32::from_bits(0x5a000001), + ); + assert_eq::<f32>( + 0xffdfffffdfffffffu64 as i64 as f32, + /*-0x1.000002p+53*/ f32::from_bits(0xda000001), + ); + // FIXME emscripten does not support i128 + #[cfg(not(target_os = "emscripten"))] + { + assert_eq::<f32>(i128::MIN as f32, -170141183460469231731687303715884105728.0f32); + assert_eq::<f32>(u128::MAX as f32, f32::INFINITY); // saturation + } + + // int -> f64 + assert_eq::<f64>(127i8 as f64, 127.0); + assert_eq::<f64>(i16::MIN as f64, -32768.0f64); + assert_eq::<f64>(2147483647i32 as f64, 2147483647.0); + assert_eq::<f64>(-2147483648i32 as f64, -2147483648.0); + assert_eq::<f64>(987654321i32 as f64, 987654321.0); + assert_eq::<f64>(9223372036854775807i64 as f64, 9223372036854775807.0); + assert_eq::<f64>(-9223372036854775808i64 as f64, -9223372036854775808.0); + assert_eq::<f64>(4669201609102990i64 as f64, 4669201609102990.0); // Feigenbaum (?) + assert_eq::<f64>(9007199254740993i64 as f64, 9007199254740992.0); + assert_eq::<f64>(-9007199254740993i64 as f64, -9007199254740992.0); + assert_eq::<f64>(9007199254740995i64 as f64, 9007199254740996.0); + assert_eq::<f64>(-9007199254740995i64 as f64, -9007199254740996.0); + // FIXME emscripten does not support i128 + #[cfg(not(target_os = "emscripten"))] + { + // even that fits... + assert_eq::<f64>(u128::MAX as f64, 340282366920938463463374607431768211455.0f64); + } + + // f32 -> f64 + assert_eq::<u64>((0.0f32 as f64).to_bits(), 0.0f64.to_bits()); + assert_eq::<u64>(((-0.0f32) as f64).to_bits(), (-0.0f64).to_bits()); + assert_eq::<f64>(5.0f32 as f64, 5.0f64); + assert_eq::<f64>( + /*0x1p-149*/ f32::from_bits(0x1) as f64, + /*0x1p-149*/ f64::from_bits(0x36a0000000000000), + ); + assert_eq::<f64>( + /*-0x1p-149*/ f32::from_bits(0x80000001) as f64, + /*-0x1p-149*/ f64::from_bits(0xb6a0000000000000), + ); + assert_eq::<f64>( + /*0x1.fffffep+127*/ f32::from_bits(0x7f7fffff) as f64, + /*0x1.fffffep+127*/ f64::from_bits(0x47efffffe0000000), + ); + assert_eq::<f64>( + /*-0x1.fffffep+127*/ (-f32::from_bits(0x7f7fffff)) as f64, + /*-0x1.fffffep+127*/ -f64::from_bits(0x47efffffe0000000), + ); + assert_eq::<f64>( + /*0x1p-119*/ f32::from_bits(0x4000000) as f64, + /*0x1p-119*/ f64::from_bits(0x3880000000000000), + ); + assert_eq::<f64>( + /*0x1.8f867ep+125*/ f32::from_bits(0x7e47c33f) as f64, + 6.6382536710104395e+37, + ); + assert_eq::<f64>(f32::INFINITY as f64, f64::INFINITY); + assert_eq::<f64>(f32::NEG_INFINITY as f64, f64::NEG_INFINITY); + + // f64 -> f32 + assert_eq::<u32>((0.0f64 as f32).to_bits(), 0.0f32.to_bits()); + assert_eq::<u32>(((-0.0f64) as f32).to_bits(), (-0.0f32).to_bits()); + assert_eq::<f32>(5.0f64 as f32, 5.0f32); + assert_eq::<f32>(/*0x0.0000000000001p-1022*/ f64::from_bits(0x1) as f32, 0.0); + assert_eq::<f32>(/*-0x0.0000000000001p-1022*/ (-f64::from_bits(0x1)) as f32, -0.0); + assert_eq::<f32>( + /*0x1.fffffe0000000p-127*/ f64::from_bits(0x380fffffe0000000) as f32, + /*0x1p-149*/ f32::from_bits(0x800000), + ); + assert_eq::<f32>( + /*0x1.4eae4f7024c7p+108*/ f64::from_bits(0x46b4eae4f7024c70) as f32, + /*0x1.4eae5p+108*/ f32::from_bits(0x75a75728), + ); + assert_eq::<f32>(f64::MAX as f32, f32::INFINITY); + assert_eq::<f32>(f64::MIN as f32, f32::NEG_INFINITY); + assert_eq::<f32>(f64::INFINITY as f32, f32::INFINITY); + assert_eq::<f32>(f64::NEG_INFINITY as f32, f32::NEG_INFINITY); +} + +pub fn run() { + casts(); // from miri's tests + + common_fptoi_tests!(f* -> i8 i16 i32 i64 u8 u16 u32 u64); + fptoui_tests!(f* -> u8 u16 u32 u64); + // FIXME emscripten does not support i128 + #[cfg(not(target_os = "emscripten"))] + { + common_fptoi_tests!(f* -> i128 u128); + fptoui_tests!(f* -> u128); + } + + // The following tests cover edge cases for some integer types. + + // # u8 + test!(254., f* -> u8, 254); + test!(256., f* -> u8, 255); + + // # i8 + test!(-127., f* -> i8, -127); + test!(-129., f* -> i8, -128); + test!(126., f* -> i8, 126); + test!(128., f* -> i8, 127); + + // # i32 + // -2147483648. is i32::MIN (exactly) + test!(-2147483648., f* -> i32, i32::MIN); + // 2147483648. is i32::MAX rounded up + test!(2147483648., f32 -> i32, 2147483647); + // With 24 significand bits, floats with magnitude in [2^30 + 1, 2^31] are rounded to + // multiples of 2^7. Therefore, nextDown(round(i32::MAX)) is 2^31 - 128: + test!(2147483520., f32 -> i32, 2147483520); + // Similarly, nextUp(i32::MIN) is i32::MIN + 2^8 and nextDown(i32::MIN) is i32::MIN - 2^7 + test!(-2147483904., f* -> i32, i32::MIN); + test!(-2147483520., f* -> i32, -2147483520); + + // # u32 + // round(MAX) and nextUp(round(MAX)) + test!(4294967040., f* -> u32, 4294967040); + test!(4294967296., f* -> u32, 4294967295); + + // # u128 + #[cfg(not(target_os = "emscripten"))] + { + // float->int: + test!(f32::MAX, f32 -> u128, 0xffffff00000000000000000000000000); + // nextDown(f32::MAX) = 2^128 - 2 * 2^104 + const SECOND_LARGEST_F32: f32 = 340282326356119256160033759537265639424.; + test!(SECOND_LARGEST_F32, f32 -> u128, 0xfffffe00000000000000000000000000); + } +} diff --git a/src/test/ui/numbers-arithmetic/saturating-float-casts-wasm.rs b/src/test/ui/numbers-arithmetic/saturating-float-casts-wasm.rs new file mode 100644 index 00000000000..cad05917391 --- /dev/null +++ b/src/test/ui/numbers-arithmetic/saturating-float-casts-wasm.rs @@ -0,0 +1,13 @@ +// run-pass +// only-wasm32 +// compile-flags: -Zmir-opt-level=0 -C target-feature=+nontrapping-fptoint + +#![feature(test, stmt_expr_attributes)] +#![deny(overflowing_literals)] + +#[path = "saturating-float-casts-impl.rs"] +mod implementation; + +pub fn main() { + implementation::run(); +} diff --git a/src/test/ui/numbers-arithmetic/saturating-float-casts.rs b/src/test/ui/numbers-arithmetic/saturating-float-casts.rs index e6d0c94a02f..cc248a9bea0 100644 --- a/src/test/ui/numbers-arithmetic/saturating-float-casts.rs +++ b/src/test/ui/numbers-arithmetic/saturating-float-casts.rs @@ -1,510 +1,12 @@ // run-pass // compile-flags:-Zmir-opt-level=0 -// Tests saturating float->int casts. See u128-as-f32.rs for the opposite direction. -// -// Some of these tests come from a similar file in miri, -// tests/run-pass/float.rs. Individual test cases are potentially duplicated -// with the previously existing tests, but since this runs so quickly anyway, -// we're not spending the time to figure out exactly which ones should be -// merged. #![feature(test, stmt_expr_attributes)] -#![feature(track_caller)] #![deny(overflowing_literals)] -extern crate test; -use std::{f32, f64}; -#[cfg(not(target_os = "emscripten"))] -use std::{i128, u128}; -use std::{i16, i32, i64, i8, u16, u32, u64, u8}; -use test::black_box; - -macro_rules! test { - ($val:expr, $src_ty:ident -> $dest_ty:ident, $expected:expr) => ( - // black_box disables constant evaluation to test run-time conversions: - assert_eq!(black_box::<$src_ty>($val) as $dest_ty, $expected, - "run-time {} -> {}", stringify!($src_ty), stringify!($dest_ty)); - - { - const X: $src_ty = $val; - const Y: $dest_ty = X as $dest_ty; - assert_eq!(Y, $expected, - "const eval {} -> {}", stringify!($src_ty), stringify!($dest_ty)); - } - ); - - ($fval:expr, f* -> $ity:ident, $ival:expr) => ( - test!($fval, f32 -> $ity, $ival); - test!($fval, f64 -> $ity, $ival); - ) -} - -macro_rules! common_fptoi_tests { - ($fty:ident -> $($ity:ident)+) => ({ $( - test!($fty::NAN, $fty -> $ity, 0); - test!($fty::INFINITY, $fty -> $ity, $ity::MAX); - test!($fty::NEG_INFINITY, $fty -> $ity, $ity::MIN); - // These two tests are not solely float->int tests, in particular the latter relies on - // `u128::MAX as f32` not being UB. But that's okay, since this file tests int->float - // as well, the test is just slightly misplaced. - test!($ity::MIN as $fty, $fty -> $ity, $ity::MIN); - test!($ity::MAX as $fty, $fty -> $ity, $ity::MAX); - test!(0., $fty -> $ity, 0); - test!($fty::MIN_POSITIVE, $fty -> $ity, 0); - test!(-0.9, $fty -> $ity, 0); - test!(1., $fty -> $ity, 1); - test!(42., $fty -> $ity, 42); - )+ }); - - (f* -> $($ity:ident)+) => ({ - common_fptoi_tests!(f32 -> $($ity)+); - common_fptoi_tests!(f64 -> $($ity)+); - }) -} - -macro_rules! fptoui_tests { - ($fty: ident -> $($ity: ident)+) => ({ $( - test!(-0., $fty -> $ity, 0); - test!(-$fty::MIN_POSITIVE, $fty -> $ity, 0); - test!(-0.99999994, $fty -> $ity, 0); - test!(-1., $fty -> $ity, 0); - test!(-100., $fty -> $ity, 0); - test!(#[allow(overflowing_literals)] -1e50, $fty -> $ity, 0); - test!(#[allow(overflowing_literals)] -1e130, $fty -> $ity, 0); - )+ }); - - (f* -> $($ity:ident)+) => ({ - fptoui_tests!(f32 -> $($ity)+); - fptoui_tests!(f64 -> $($ity)+); - }) -} - -use std::fmt::Debug; - -// Helper function to avoid promotion so that this tests "run-time" casts, not CTFE. -#[track_caller] -#[inline(never)] -fn assert_eq<T: PartialEq + Debug>(x: T, y: T) { - assert_eq!(x, y); -} - -trait FloatToInt<Int>: Copy { - fn cast(self) -> Int; - unsafe fn cast_unchecked(self) -> Int; -} - -impl FloatToInt<i8> for f32 { - fn cast(self) -> i8 { - self as _ - } - unsafe fn cast_unchecked(self) -> i8 { - self.to_int_unchecked() - } -} -impl FloatToInt<i32> for f32 { - fn cast(self) -> i32 { - self as _ - } - unsafe fn cast_unchecked(self) -> i32 { - self.to_int_unchecked() - } -} -impl FloatToInt<u32> for f32 { - fn cast(self) -> u32 { - self as _ - } - unsafe fn cast_unchecked(self) -> u32 { - self.to_int_unchecked() - } -} -impl FloatToInt<i64> for f32 { - fn cast(self) -> i64 { - self as _ - } - unsafe fn cast_unchecked(self) -> i64 { - self.to_int_unchecked() - } -} -impl FloatToInt<u64> for f32 { - fn cast(self) -> u64 { - self as _ - } - unsafe fn cast_unchecked(self) -> u64 { - self.to_int_unchecked() - } -} - -impl FloatToInt<i8> for f64 { - fn cast(self) -> i8 { - self as _ - } - unsafe fn cast_unchecked(self) -> i8 { - self.to_int_unchecked() - } -} -impl FloatToInt<i32> for f64 { - fn cast(self) -> i32 { - self as _ - } - unsafe fn cast_unchecked(self) -> i32 { - self.to_int_unchecked() - } -} -impl FloatToInt<u32> for f64 { - fn cast(self) -> u32 { - self as _ - } - unsafe fn cast_unchecked(self) -> u32 { - self.to_int_unchecked() - } -} -impl FloatToInt<i64> for f64 { - fn cast(self) -> i64 { - self as _ - } - unsafe fn cast_unchecked(self) -> i64 { - self.to_int_unchecked() - } -} -impl FloatToInt<u64> for f64 { - fn cast(self) -> u64 { - self as _ - } - unsafe fn cast_unchecked(self) -> u64 { - self.to_int_unchecked() - } -} -// FIXME emscripten does not support i128 -#[cfg(not(target_os = "emscripten"))] -impl FloatToInt<i128> for f64 { - fn cast(self) -> i128 { - self as _ - } - unsafe fn cast_unchecked(self) -> i128 { - self.to_int_unchecked() - } -} -// FIXME emscripten does not support i128 -#[cfg(not(target_os = "emscripten"))] -impl FloatToInt<u128> for f64 { - fn cast(self) -> u128 { - self as _ - } - unsafe fn cast_unchecked(self) -> u128 { - self.to_int_unchecked() - } -} - -/// Test this cast both via `as` and via `to_int_unchecked` (i.e., it must not saturate). -#[track_caller] -#[inline(never)] -fn test_both_cast<F, I>(x: F, y: I) -where - F: FloatToInt<I>, - I: PartialEq + Debug, -{ - assert_eq!(x.cast(), y); - assert_eq!(unsafe { x.cast_unchecked() }, y); -} - -fn casts() { - // f32 -> i8 - test_both_cast::<f32, i8>(127.99, 127); - test_both_cast::<f32, i8>(-128.99, -128); - - // f32 -> i32 - test_both_cast::<f32, i32>(0.0, 0); - test_both_cast::<f32, i32>(-0.0, 0); - test_both_cast::<f32, i32>(/*0x1p-149*/ f32::from_bits(0x00000001), 0); - test_both_cast::<f32, i32>(/*-0x1p-149*/ f32::from_bits(0x80000001), 0); - test_both_cast::<f32, i32>(/*0x1.19999ap+0*/ f32::from_bits(0x3f8ccccd), 1); - test_both_cast::<f32, i32>(/*-0x1.19999ap+0*/ f32::from_bits(0xbf8ccccd), -1); - test_both_cast::<f32, i32>(1.9, 1); - test_both_cast::<f32, i32>(-1.9, -1); - test_both_cast::<f32, i32>(5.0, 5); - test_both_cast::<f32, i32>(-5.0, -5); - test_both_cast::<f32, i32>(2147483520.0, 2147483520); - test_both_cast::<f32, i32>(-2147483648.0, -2147483648); - // unrepresentable casts - assert_eq::<i32>(2147483648.0f32 as i32, i32::MAX); - assert_eq::<i32>(-2147483904.0f32 as i32, i32::MIN); - assert_eq::<i32>(f32::MAX as i32, i32::MAX); - assert_eq::<i32>(f32::MIN as i32, i32::MIN); - assert_eq::<i32>(f32::INFINITY as i32, i32::MAX); - assert_eq::<i32>(f32::NEG_INFINITY as i32, i32::MIN); - assert_eq::<i32>(f32::NAN as i32, 0); - assert_eq::<i32>((-f32::NAN) as i32, 0); - - // f32 -> u32 - test_both_cast::<f32, u32>(0.0, 0); - test_both_cast::<f32, u32>(-0.0, 0); - test_both_cast::<f32, u32>(-0.9999999, 0); - test_both_cast::<f32, u32>(/*0x1p-149*/ f32::from_bits(0x1), 0); - test_both_cast::<f32, u32>(/*-0x1p-149*/ f32::from_bits(0x80000001), 0); - test_both_cast::<f32, u32>(/*0x1.19999ap+0*/ f32::from_bits(0x3f8ccccd), 1); - test_both_cast::<f32, u32>(1.9, 1); - test_both_cast::<f32, u32>(5.0, 5); - test_both_cast::<f32, u32>(2147483648.0, 0x8000_0000); - test_both_cast::<f32, u32>(4294967040.0, 0u32.wrapping_sub(256)); - test_both_cast::<f32, u32>(/*-0x1.ccccccp-1*/ f32::from_bits(0xbf666666), 0); - test_both_cast::<f32, u32>(/*-0x1.fffffep-1*/ f32::from_bits(0xbf7fffff), 0); - test_both_cast::<f32, u32>((u32::MAX - 128) as f32, u32::MAX - 255); // rounding loss - - // unrepresentable casts: - - // rounds up and then becomes unrepresentable - assert_eq::<u32>((u32::MAX - 127) as f32 as u32, u32::MAX); - - assert_eq::<u32>(4294967296.0f32 as u32, u32::MAX); - assert_eq::<u32>(-5.0f32 as u32, 0); - assert_eq::<u32>(f32::MAX as u32, u32::MAX); - assert_eq::<u32>(f32::MIN as u32, 0); - assert_eq::<u32>(f32::INFINITY as u32, u32::MAX); - assert_eq::<u32>(f32::NEG_INFINITY as u32, 0); - assert_eq::<u32>(f32::NAN as u32, 0); - assert_eq::<u32>((-f32::NAN) as u32, 0); - - // f32 -> i64 - test_both_cast::<f32, i64>(4294967296.0, 4294967296); - test_both_cast::<f32, i64>(-4294967296.0, -4294967296); - test_both_cast::<f32, i64>(9223371487098961920.0, 9223371487098961920); - test_both_cast::<f32, i64>(-9223372036854775808.0, -9223372036854775808); - - // f64 -> i8 - test_both_cast::<f64, i8>(127.99, 127); - test_both_cast::<f64, i8>(-128.99, -128); - - // f64 -> i32 - test_both_cast::<f64, i32>(0.0, 0); - test_both_cast::<f64, i32>(-0.0, 0); - test_both_cast::<f64, i32>(/*0x1.199999999999ap+0*/ f64::from_bits(0x3ff199999999999a), 1); - test_both_cast::<f64, i32>( - /*-0x1.199999999999ap+0*/ f64::from_bits(0xbff199999999999a), - -1, - ); - test_both_cast::<f64, i32>(1.9, 1); - test_both_cast::<f64, i32>(-1.9, -1); - test_both_cast::<f64, i32>(1e8, 100_000_000); - test_both_cast::<f64, i32>(2147483647.0, 2147483647); - test_both_cast::<f64, i32>(-2147483648.0, -2147483648); - // unrepresentable casts - assert_eq::<i32>(2147483648.0f64 as i32, i32::MAX); - assert_eq::<i32>(-2147483649.0f64 as i32, i32::MIN); - - // f64 -> i64 - test_both_cast::<f64, i64>(0.0, 0); - test_both_cast::<f64, i64>(-0.0, 0); - test_both_cast::<f64, i64>(/*0x0.0000000000001p-1022*/ f64::from_bits(0x1), 0); - test_both_cast::<f64, i64>( - /*-0x0.0000000000001p-1022*/ f64::from_bits(0x8000000000000001), - 0, - ); - test_both_cast::<f64, i64>(/*0x1.199999999999ap+0*/ f64::from_bits(0x3ff199999999999a), 1); - test_both_cast::<f64, i64>( - /*-0x1.199999999999ap+0*/ f64::from_bits(0xbff199999999999a), - -1, - ); - test_both_cast::<f64, i64>(5.0, 5); - test_both_cast::<f64, i64>(5.9, 5); - test_both_cast::<f64, i64>(-5.0, -5); - test_both_cast::<f64, i64>(-5.9, -5); - test_both_cast::<f64, i64>(4294967296.0, 4294967296); - test_both_cast::<f64, i64>(-4294967296.0, -4294967296); - test_both_cast::<f64, i64>(9223372036854774784.0, 9223372036854774784); - test_both_cast::<f64, i64>(-9223372036854775808.0, -9223372036854775808); - // unrepresentable casts - assert_eq::<i64>(9223372036854775808.0f64 as i64, i64::MAX); - assert_eq::<i64>(-9223372036854777856.0f64 as i64, i64::MIN); - assert_eq::<i64>(f64::MAX as i64, i64::MAX); - assert_eq::<i64>(f64::MIN as i64, i64::MIN); - assert_eq::<i64>(f64::INFINITY as i64, i64::MAX); - assert_eq::<i64>(f64::NEG_INFINITY as i64, i64::MIN); - assert_eq::<i64>(f64::NAN as i64, 0); - assert_eq::<i64>((-f64::NAN) as i64, 0); - - // f64 -> u64 - test_both_cast::<f64, u64>(0.0, 0); - test_both_cast::<f64, u64>(-0.0, 0); - test_both_cast::<f64, u64>(-0.99999999999, 0); - test_both_cast::<f64, u64>(5.0, 5); - test_both_cast::<f64, u64>(1e16, 10000000000000000); - test_both_cast::<f64, u64>((u64::MAX - 1024) as f64, u64::MAX - 2047); // rounding loss - test_both_cast::<f64, u64>(9223372036854775808.0, 9223372036854775808); - // unrepresentable casts - assert_eq::<u64>(-5.0f64 as u64, 0); - // rounds up and then becomes unrepresentable - assert_eq::<u64>((u64::MAX - 1023) as f64 as u64, u64::MAX); - assert_eq::<u64>(18446744073709551616.0f64 as u64, u64::MAX); - assert_eq::<u64>(f64::MAX as u64, u64::MAX); - assert_eq::<u64>(f64::MIN as u64, 0); - assert_eq::<u64>(f64::INFINITY as u64, u64::MAX); - assert_eq::<u64>(f64::NEG_INFINITY as u64, 0); - assert_eq::<u64>(f64::NAN as u64, 0); - assert_eq::<u64>((-f64::NAN) as u64, 0); - - // FIXME emscripten does not support i128 - #[cfg(not(target_os = "emscripten"))] - { - // f64 -> i128 - assert_eq::<i128>(f64::MAX as i128, i128::MAX); - assert_eq::<i128>(f64::MIN as i128, i128::MIN); - - // f64 -> u128 - assert_eq::<u128>(f64::MAX as u128, u128::MAX); - assert_eq::<u128>(f64::MIN as u128, 0); - } - - // int -> f32 - assert_eq::<f32>(127i8 as f32, 127.0); - assert_eq::<f32>(2147483647i32 as f32, 2147483648.0); - assert_eq::<f32>((-2147483648i32) as f32, -2147483648.0); - assert_eq::<f32>(1234567890i32 as f32, /*0x1.26580cp+30*/ f32::from_bits(0x4e932c06)); - assert_eq::<f32>(16777217i32 as f32, 16777216.0); - assert_eq::<f32>((-16777217i32) as f32, -16777216.0); - assert_eq::<f32>(16777219i32 as f32, 16777220.0); - assert_eq::<f32>((-16777219i32) as f32, -16777220.0); - assert_eq::<f32>( - 0x7fffff4000000001i64 as f32, - /*0x1.fffffep+62*/ f32::from_bits(0x5effffff), - ); - assert_eq::<f32>( - 0x8000004000000001u64 as i64 as f32, - /*-0x1.fffffep+62*/ f32::from_bits(0xdeffffff), - ); - assert_eq::<f32>( - 0x0020000020000001i64 as f32, - /*0x1.000002p+53*/ f32::from_bits(0x5a000001), - ); - assert_eq::<f32>( - 0xffdfffffdfffffffu64 as i64 as f32, - /*-0x1.000002p+53*/ f32::from_bits(0xda000001), - ); - // FIXME emscripten does not support i128 - #[cfg(not(target_os = "emscripten"))] - { - assert_eq::<f32>(i128::MIN as f32, -170141183460469231731687303715884105728.0f32); - assert_eq::<f32>(u128::MAX as f32, f32::INFINITY); // saturation - } - - // int -> f64 - assert_eq::<f64>(127i8 as f64, 127.0); - assert_eq::<f64>(i16::MIN as f64, -32768.0f64); - assert_eq::<f64>(2147483647i32 as f64, 2147483647.0); - assert_eq::<f64>(-2147483648i32 as f64, -2147483648.0); - assert_eq::<f64>(987654321i32 as f64, 987654321.0); - assert_eq::<f64>(9223372036854775807i64 as f64, 9223372036854775807.0); - assert_eq::<f64>(-9223372036854775808i64 as f64, -9223372036854775808.0); - assert_eq::<f64>(4669201609102990i64 as f64, 4669201609102990.0); // Feigenbaum (?) - assert_eq::<f64>(9007199254740993i64 as f64, 9007199254740992.0); - assert_eq::<f64>(-9007199254740993i64 as f64, -9007199254740992.0); - assert_eq::<f64>(9007199254740995i64 as f64, 9007199254740996.0); - assert_eq::<f64>(-9007199254740995i64 as f64, -9007199254740996.0); - // FIXME emscripten does not support i128 - #[cfg(not(target_os = "emscripten"))] - { - // even that fits... - assert_eq::<f64>(u128::MAX as f64, 340282366920938463463374607431768211455.0f64); - } - - // f32 -> f64 - assert_eq::<u64>((0.0f32 as f64).to_bits(), 0.0f64.to_bits()); - assert_eq::<u64>(((-0.0f32) as f64).to_bits(), (-0.0f64).to_bits()); - assert_eq::<f64>(5.0f32 as f64, 5.0f64); - assert_eq::<f64>( - /*0x1p-149*/ f32::from_bits(0x1) as f64, - /*0x1p-149*/ f64::from_bits(0x36a0000000000000), - ); - assert_eq::<f64>( - /*-0x1p-149*/ f32::from_bits(0x80000001) as f64, - /*-0x1p-149*/ f64::from_bits(0xb6a0000000000000), - ); - assert_eq::<f64>( - /*0x1.fffffep+127*/ f32::from_bits(0x7f7fffff) as f64, - /*0x1.fffffep+127*/ f64::from_bits(0x47efffffe0000000), - ); - assert_eq::<f64>( - /*-0x1.fffffep+127*/ (-f32::from_bits(0x7f7fffff)) as f64, - /*-0x1.fffffep+127*/ -f64::from_bits(0x47efffffe0000000), - ); - assert_eq::<f64>( - /*0x1p-119*/ f32::from_bits(0x4000000) as f64, - /*0x1p-119*/ f64::from_bits(0x3880000000000000), - ); - assert_eq::<f64>( - /*0x1.8f867ep+125*/ f32::from_bits(0x7e47c33f) as f64, - 6.6382536710104395e+37, - ); - assert_eq::<f64>(f32::INFINITY as f64, f64::INFINITY); - assert_eq::<f64>(f32::NEG_INFINITY as f64, f64::NEG_INFINITY); - - // f64 -> f32 - assert_eq::<u32>((0.0f64 as f32).to_bits(), 0.0f32.to_bits()); - assert_eq::<u32>(((-0.0f64) as f32).to_bits(), (-0.0f32).to_bits()); - assert_eq::<f32>(5.0f64 as f32, 5.0f32); - assert_eq::<f32>(/*0x0.0000000000001p-1022*/ f64::from_bits(0x1) as f32, 0.0); - assert_eq::<f32>(/*-0x0.0000000000001p-1022*/ (-f64::from_bits(0x1)) as f32, -0.0); - assert_eq::<f32>( - /*0x1.fffffe0000000p-127*/ f64::from_bits(0x380fffffe0000000) as f32, - /*0x1p-149*/ f32::from_bits(0x800000), - ); - assert_eq::<f32>( - /*0x1.4eae4f7024c7p+108*/ f64::from_bits(0x46b4eae4f7024c70) as f32, - /*0x1.4eae5p+108*/ f32::from_bits(0x75a75728), - ); - assert_eq::<f32>(f64::MAX as f32, f32::INFINITY); - assert_eq::<f32>(f64::MIN as f32, f32::NEG_INFINITY); - assert_eq::<f32>(f64::INFINITY as f32, f32::INFINITY); - assert_eq::<f32>(f64::NEG_INFINITY as f32, f32::NEG_INFINITY); -} +#[path = "saturating-float-casts-impl.rs"] +mod implementation; pub fn main() { - casts(); // from miri's tests - - common_fptoi_tests!(f* -> i8 i16 i32 i64 u8 u16 u32 u64); - fptoui_tests!(f* -> u8 u16 u32 u64); - // FIXME emscripten does not support i128 - #[cfg(not(target_os = "emscripten"))] - { - common_fptoi_tests!(f* -> i128 u128); - fptoui_tests!(f* -> u128); - } - - // The following tests cover edge cases for some integer types. - - // # u8 - test!(254., f* -> u8, 254); - test!(256., f* -> u8, 255); - - // # i8 - test!(-127., f* -> i8, -127); - test!(-129., f* -> i8, -128); - test!(126., f* -> i8, 126); - test!(128., f* -> i8, 127); - - // # i32 - // -2147483648. is i32::MIN (exactly) - test!(-2147483648., f* -> i32, i32::MIN); - // 2147483648. is i32::MAX rounded up - test!(2147483648., f32 -> i32, 2147483647); - // With 24 significand bits, floats with magnitude in [2^30 + 1, 2^31] are rounded to - // multiples of 2^7. Therefore, nextDown(round(i32::MAX)) is 2^31 - 128: - test!(2147483520., f32 -> i32, 2147483520); - // Similarly, nextUp(i32::MIN) is i32::MIN + 2^8 and nextDown(i32::MIN) is i32::MIN - 2^7 - test!(-2147483904., f* -> i32, i32::MIN); - test!(-2147483520., f* -> i32, -2147483520); - - // # u32 - // round(MAX) and nextUp(round(MAX)) - test!(4294967040., f* -> u32, 4294967040); - test!(4294967296., f* -> u32, 4294967295); - - // # u128 - #[cfg(not(target_os = "emscripten"))] - { - // float->int: - test!(f32::MAX, f32 -> u128, 0xffffff00000000000000000000000000); - // nextDown(f32::MAX) = 2^128 - 2 * 2^104 - const SECOND_LARGEST_F32: f32 = 340282326356119256160033759537265639424.; - test!(SECOND_LARGEST_F32, f32 -> u128, 0xfffffe00000000000000000000000000); - } + implementation::run(); } diff --git a/src/test/ui/panic-handler/panic-handler-std.rs b/src/test/ui/panic-handler/panic-handler-std.rs index 0acc2722cb2..6183c886cfa 100644 --- a/src/test/ui/panic-handler/panic-handler-std.rs +++ b/src/test/ui/panic-handler/panic-handler-std.rs @@ -1,3 +1,4 @@ +// normalize-stderr-test "loaded from .*libstd-.*.rlib" -> "loaded from SYSROOT/libstd-*.rlib" // error-pattern: found duplicate lang item `panic_impl` diff --git a/src/test/ui/panic-handler/panic-handler-std.stderr b/src/test/ui/panic-handler/panic-handler-std.stderr index f71c28e5aa6..bb656089bca 100644 --- a/src/test/ui/panic-handler/panic-handler-std.stderr +++ b/src/test/ui/panic-handler/panic-handler-std.stderr @@ -1,5 +1,5 @@ error[E0152]: found duplicate lang item `panic_impl` - --> $DIR/panic-handler-std.rs:7:1 + --> $DIR/panic-handler-std.rs:8:1 | LL | / fn panic(info: PanicInfo) -> ! { LL | | loop {} @@ -7,9 +7,11 @@ LL | | } | |_^ | = note: the lang item is first defined in crate `std` (which `panic_handler_std` depends on) + = note: first definition in `std` loaded from SYSROOT/libstd-*.rlib + = note: second definition in the local crate (`panic_handler_std`) error: argument should be `&PanicInfo` - --> $DIR/panic-handler-std.rs:7:16 + --> $DIR/panic-handler-std.rs:8:16 | LL | fn panic(info: PanicInfo) -> ! { | ^^^^^^^^^ diff --git a/src/test/ui/parser/inverted-parameters.rs b/src/test/ui/parser/inverted-parameters.rs index 6f19ee9c7dc..5c4272504e0 100644 --- a/src/test/ui/parser/inverted-parameters.rs +++ b/src/test/ui/parser/inverted-parameters.rs @@ -20,7 +20,7 @@ fn pattern((i32, i32) (a, b)) {} fn fizz(i32) {} //~^ ERROR expected one of `:`, `@` -//~| HELP if this was a parameter name, give it a type +//~| HELP if this is a parameter name, give it a type //~| HELP if this is a `self` type, give it a parameter name //~| HELP if this is a type, explicitly ignore the parameter name diff --git a/src/test/ui/parser/inverted-parameters.stderr b/src/test/ui/parser/inverted-parameters.stderr index 043ff65f74e..ae180af93e3 100644 --- a/src/test/ui/parser/inverted-parameters.stderr +++ b/src/test/ui/parser/inverted-parameters.stderr @@ -39,7 +39,7 @@ help: if this is a `self` type, give it a parameter name | LL | fn fizz(self: i32) {} | ^^^^^^^^^ -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | fn fizz(i32: TypeName) {} | ^^^^^^^^^^^^^ diff --git a/src/test/ui/parser/omitted-arg-in-item-fn.stderr b/src/test/ui/parser/omitted-arg-in-item-fn.stderr index 9f138bf84ce..bc3329dcbc2 100644 --- a/src/test/ui/parser/omitted-arg-in-item-fn.stderr +++ b/src/test/ui/parser/omitted-arg-in-item-fn.stderr @@ -9,7 +9,7 @@ help: if this is a `self` type, give it a parameter name | LL | fn foo(self: x) { | ^^^^^^^ -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | fn foo(x: TypeName) { | ^^^^^^^^^^^ diff --git a/src/test/ui/parser/recover-field-extra-angle-brackets.rs b/src/test/ui/parser/recover-field-extra-angle-brackets.rs new file mode 100644 index 00000000000..5e0e00bcb5e --- /dev/null +++ b/src/test/ui/parser/recover-field-extra-angle-brackets.rs @@ -0,0 +1,14 @@ +// Tests that we recover from extra trailing angle brackets +// in a struct field + +struct BadStruct { + first: Vec<u8>>, //~ ERROR unmatched angle bracket + second: bool +} + +fn bar(val: BadStruct) { + val.first; + val.second; +} + +fn main() {} diff --git a/src/test/ui/parser/recover-field-extra-angle-brackets.stderr b/src/test/ui/parser/recover-field-extra-angle-brackets.stderr new file mode 100644 index 00000000000..318e55f6e99 --- /dev/null +++ b/src/test/ui/parser/recover-field-extra-angle-brackets.stderr @@ -0,0 +1,8 @@ +error: unmatched angle bracket + --> $DIR/recover-field-extra-angle-brackets.rs:5:19 + | +LL | first: Vec<u8>>, + | ^ help: remove extra angle bracket + +error: aborting due to previous error + diff --git a/src/test/ui/proc-macro/auxiliary/attr-cfg.rs b/src/test/ui/proc-macro/auxiliary/attr-cfg.rs index f50e18d7be3..2f0054cc14a 100644 --- a/src/test/ui/proc-macro/auxiliary/attr-cfg.rs +++ b/src/test/ui/proc-macro/auxiliary/attr-cfg.rs @@ -11,11 +11,9 @@ use proc_macro::TokenStream; pub fn attr_cfg(args: TokenStream, input: TokenStream) -> TokenStream { let input_str = input.to_string(); - assert_eq!(input_str, "fn outer() -> u8 { - #[cfg(foo)] - fn inner() -> u8 { 1 } - #[cfg(bar)] - fn inner() -> u8 { 2 } + assert_eq!(input_str, "fn outer() -> u8 +{ + #[cfg(foo)] fn inner() -> u8 { 1 } #[cfg(bar)] fn inner() -> u8 { 2 } inner() }"); diff --git a/src/test/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs b/src/test/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs index f1de3709b16..e056bd32d2d 100644 --- a/src/test/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs +++ b/src/test/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs @@ -10,14 +10,14 @@ use proc_macro::TokenStream; #[proc_macro_attribute] pub fn expect_let(attr: TokenStream, item: TokenStream) -> TokenStream { assert!(attr.to_string().is_empty()); - assert_eq!(item.to_string(), "let string = \"Hello, world!\";"); + assert_eq!(item.to_string(), "let string = \"Hello, world!\" ;"); item } #[proc_macro_attribute] pub fn expect_print_stmt(attr: TokenStream, item: TokenStream) -> TokenStream { assert!(attr.to_string().is_empty()); - assert_eq!(item.to_string(), "println!(\"{}\", string);"); + assert_eq!(item.to_string(), "println ! (\"{}\", string) ;"); item } @@ -31,7 +31,7 @@ pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream { #[proc_macro_attribute] pub fn expect_print_expr(attr: TokenStream, item: TokenStream) -> TokenStream { assert!(attr.to_string().is_empty()); - assert_eq!(item.to_string(), "println!(\"{}\", string)"); + assert_eq!(item.to_string(), "println ! (\"{}\", string)"); item } diff --git a/src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs b/src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs index d2180def5b7..213f999e9d0 100644 --- a/src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs +++ b/src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs @@ -10,14 +10,14 @@ use proc_macro::TokenStream; #[proc_macro_attribute] pub fn expect_let(attr: TokenStream, item: TokenStream) -> TokenStream { assert!(attr.to_string().is_empty()); - assert_eq!(item.to_string(), "let string = \"Hello, world!\";"); + assert_eq!(item.to_string(), "let string = \"Hello, world!\" ;"); item } #[proc_macro_attribute] pub fn expect_print_stmt(attr: TokenStream, item: TokenStream) -> TokenStream { assert!(attr.to_string().is_empty()); - assert_eq!(item.to_string(), "println!(\"{}\", string);"); + assert_eq!(item.to_string(), "println ! (\"{}\", string) ;"); item } @@ -31,7 +31,7 @@ pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream { #[proc_macro_attribute] pub fn expect_print_expr(attr: TokenStream, item: TokenStream) -> TokenStream { assert!(attr.to_string().is_empty()); - assert_eq!(item.to_string(), "println!(\"{}\", string)"); + assert_eq!(item.to_string(), "println ! (\"{}\", string)"); item } diff --git a/src/test/ui/proc-macro/auxiliary/derive-a.rs b/src/test/ui/proc-macro/auxiliary/derive-a.rs index cd2be5fd84d..79a3864bf99 100644 --- a/src/test/ui/proc-macro/auxiliary/derive-a.rs +++ b/src/test/ui/proc-macro/auxiliary/derive-a.rs @@ -10,6 +10,6 @@ use proc_macro::TokenStream; #[proc_macro_derive(A)] pub fn derive(input: TokenStream) -> TokenStream { let input = input.to_string(); - assert!(input.contains("struct A;")); + assert!(input.contains("struct A ;")); "".parse().unwrap() } diff --git a/src/test/ui/proc-macro/auxiliary/derive-atob.rs b/src/test/ui/proc-macro/auxiliary/derive-atob.rs index e78e5bb8f4c..207b7fd3203 100644 --- a/src/test/ui/proc-macro/auxiliary/derive-atob.rs +++ b/src/test/ui/proc-macro/auxiliary/derive-atob.rs @@ -10,6 +10,6 @@ use proc_macro::TokenStream; #[proc_macro_derive(AToB)] pub fn derive(input: TokenStream) -> TokenStream { let input = input.to_string(); - assert_eq!(input, "struct A;"); + assert_eq!(input, "struct A ;"); "struct B;".parse().unwrap() } diff --git a/src/test/ui/proc-macro/auxiliary/derive-b-rpass.rs b/src/test/ui/proc-macro/auxiliary/derive-b-rpass.rs index 3e6af67a9f4..641a95f78c1 100644 --- a/src/test/ui/proc-macro/auxiliary/derive-b-rpass.rs +++ b/src/test/ui/proc-macro/auxiliary/derive-b-rpass.rs @@ -10,7 +10,7 @@ use proc_macro::TokenStream; #[proc_macro_derive(B, attributes(B, C))] pub fn derive(input: TokenStream) -> TokenStream { let input = input.to_string(); - assert!(input.contains("#[B[arbitrary tokens]]")); + assert!(input.contains("#[B [arbitrary tokens]]")); assert!(input.contains("struct B {")); assert!(input.contains("#[C]")); "".parse().unwrap() diff --git a/src/test/ui/proc-macro/auxiliary/derive-ctod.rs b/src/test/ui/proc-macro/auxiliary/derive-ctod.rs index dbf44ed1b05..2efe5a91340 100644 --- a/src/test/ui/proc-macro/auxiliary/derive-ctod.rs +++ b/src/test/ui/proc-macro/auxiliary/derive-ctod.rs @@ -10,6 +10,6 @@ use proc_macro::TokenStream; #[proc_macro_derive(CToD)] pub fn derive(input: TokenStream) -> TokenStream { let input = input.to_string(); - assert_eq!(input, "struct C;"); + assert_eq!(input, "struct C ;"); "struct D;".parse().unwrap() } diff --git a/src/test/ui/proc-macro/auxiliary/derive-same-struct.rs b/src/test/ui/proc-macro/auxiliary/derive-same-struct.rs index ce7a50d2381..7598d632cb6 100644 --- a/src/test/ui/proc-macro/auxiliary/derive-same-struct.rs +++ b/src/test/ui/proc-macro/auxiliary/derive-same-struct.rs @@ -10,12 +10,12 @@ use proc_macro::TokenStream; #[proc_macro_derive(AToB)] pub fn derive1(input: TokenStream) -> TokenStream { println!("input1: {:?}", input.to_string()); - assert_eq!(input.to_string(), "struct A;"); + assert_eq!(input.to_string(), "struct A ;"); "#[derive(BToC)] struct B;".parse().unwrap() } #[proc_macro_derive(BToC)] pub fn derive2(input: TokenStream) -> TokenStream { - assert_eq!(input.to_string(), "struct B;"); + assert_eq!(input.to_string(), "struct B ;"); "struct C;".parse().unwrap() } diff --git a/src/test/ui/proc-macro/auxiliary/derive-union.rs b/src/test/ui/proc-macro/auxiliary/derive-union.rs index d950e1e773c..05883170c6c 100644 --- a/src/test/ui/proc-macro/auxiliary/derive-union.rs +++ b/src/test/ui/proc-macro/auxiliary/derive-union.rs @@ -12,7 +12,7 @@ pub fn derive(input: TokenStream) -> TokenStream { let input = input.to_string(); assert!(input.contains("#[repr(C)]")); assert!(input.contains("union Test {")); - assert!(input.contains("a: u8,")); + assert!(input.contains("a : u8,")); assert!(input.contains("}")); "".parse().unwrap() } diff --git a/src/test/ui/proc-macro/auxiliary/double.rs b/src/test/ui/proc-macro/auxiliary/double.rs index 3a2e8d04c36..99eb4e37546 100644 --- a/src/test/ui/proc-macro/auxiliary/double.rs +++ b/src/test/ui/proc-macro/auxiliary/double.rs @@ -1,15 +1,16 @@ // force-host // no-prefer-dynamic +#![feature(proc_macro_quote)] + #![crate_type = "proc-macro"] extern crate proc_macro; - -use proc_macro::TokenStream; +use proc_macro::*; // Outputs another copy of the struct. Useful for testing the tokens // seen by the proc_macro. #[proc_macro_derive(Double)] pub fn derive(input: TokenStream) -> TokenStream { - format!("mod foo {{ {} }}", input.to_string()).parse().unwrap() + quote!(mod foo { $input }) } diff --git a/src/test/ui/proc-macro/auxiliary/expand-with-a-macro.rs b/src/test/ui/proc-macro/auxiliary/expand-with-a-macro.rs index 5155a4b8558..d779d57af14 100644 --- a/src/test/ui/proc-macro/auxiliary/expand-with-a-macro.rs +++ b/src/test/ui/proc-macro/auxiliary/expand-with-a-macro.rs @@ -11,7 +11,7 @@ use proc_macro::TokenStream; #[proc_macro_derive(A)] pub fn derive(input: TokenStream) -> TokenStream { let input = input.to_string(); - assert!(input.contains("struct A;")); + assert!(input.contains("struct A ;")); r#" impl A { fn a(&self) { diff --git a/src/test/ui/proc-macro/auxiliary/make-macro.rs b/src/test/ui/proc-macro/auxiliary/make-macro.rs new file mode 100644 index 00000000000..2c21221fbb0 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/make-macro.rs @@ -0,0 +1,12 @@ +// force-host + +#[macro_export] +macro_rules! make_it { + ($name:ident) => { + #[proc_macro] + pub fn $name(input: TokenStream) -> TokenStream { + println!("Def site: {:?}", Span::def_site()); + input + } + }; +} diff --git a/src/test/ui/proc-macro/auxiliary/meta-delim.rs b/src/test/ui/proc-macro/auxiliary/meta-delim.rs new file mode 100644 index 00000000000..54e3d785726 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/meta-delim.rs @@ -0,0 +1,12 @@ +macro_rules! produce_it { + ($dollar_one:tt $foo:ident $my_name:ident) => { + #[macro_export] + macro_rules! meta_delim { + ($dollar_one ($dollar_one $my_name:ident)*) => { + stringify!($dollar_one ($dollar_one $my_name)*) + } + } + } +} + +produce_it!($my_name name); diff --git a/src/test/ui/proc-macro/auxiliary/meta-macro.rs b/src/test/ui/proc-macro/auxiliary/meta-macro.rs new file mode 100644 index 00000000000..5265c6533b4 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/meta-macro.rs @@ -0,0 +1,12 @@ +// force-host +// no-prefer-dynamic +// edition:2018 + +#![feature(proc_macro_def_site)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; +extern crate make_macro; +use proc_macro::{TokenStream, Span}; + +make_macro::make_it!(print_def_site); diff --git a/src/test/ui/proc-macro/auxiliary/nested-macro-rules.rs b/src/test/ui/proc-macro/auxiliary/nested-macro-rules.rs new file mode 100644 index 00000000000..52ebe8e7fb2 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/nested-macro-rules.rs @@ -0,0 +1,15 @@ +pub struct FirstStruct; + +#[macro_export] +macro_rules! outer_macro { + ($name:ident) => { + #[macro_export] + macro_rules! inner_macro { + ($wrapper:ident) => { + $wrapper!($name) + } + } + } +} + +outer_macro!(FirstStruct); diff --git a/src/test/ui/proc-macro/auxiliary/test-macros.rs b/src/test/ui/proc-macro/auxiliary/test-macros.rs index fb8016cd438..8682ebdd109 100644 --- a/src/test/ui/proc-macro/auxiliary/test-macros.rs +++ b/src/test/ui/proc-macro/auxiliary/test-macros.rs @@ -101,6 +101,12 @@ pub fn print_bang(input: TokenStream) -> TokenStream { print_helper(input, "BANG") } +#[proc_macro] +pub fn print_bang_consume(input: TokenStream) -> TokenStream { + print_helper(input, "BANG"); + TokenStream::new() +} + #[proc_macro_attribute] pub fn print_attr(_: TokenStream, input: TokenStream) -> TokenStream { print_helper(input, "ATTR") diff --git a/src/test/ui/proc-macro/derive-same-struct.stdout b/src/test/ui/proc-macro/derive-same-struct.stdout index 77605de5e33..7478d974140 100644 --- a/src/test/ui/proc-macro/derive-same-struct.stdout +++ b/src/test/ui/proc-macro/derive-same-struct.stdout @@ -1 +1 @@ -input1: "struct A;" +input1: "struct A ;" diff --git a/src/test/ui/proc-macro/disappearing-resolution.stderr b/src/test/ui/proc-macro/disappearing-resolution.stderr index ff7ddcde6e0..5b969549a11 100644 --- a/src/test/ui/proc-macro/disappearing-resolution.stderr +++ b/src/test/ui/proc-macro/disappearing-resolution.stderr @@ -10,11 +10,16 @@ error[E0603]: derive macro import `Empty` is private LL | use m::Empty; | ^^^^^ private derive macro import | -note: the derive macro import `Empty` is defined here +note: the derive macro import `Empty` is defined here... --> $DIR/disappearing-resolution.rs:9:9 | LL | use test_macros::Empty; | ^^^^^^^^^^^^^^^^^^ +note: ...and refers to the derive macro `Empty` which is defined here + --> $DIR/auxiliary/test-macros.rs:25:1 + | +LL | pub fn empty_derive(_: TokenStream) -> TokenStream { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ consider importing it directly error: aborting due to 2 previous errors diff --git a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout index 15433bebde9..5d93144b445 100644 --- a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout +++ b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout @@ -38,8 +38,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ span: #3 bytes(LO..HI), }, ] -PRINT-ATTR INPUT (DISPLAY): struct A(crate::S); -PRINT-ATTR RE-COLLECTED (DISPLAY): struct A($crate :: S) ; +PRINT-ATTR INPUT (DISPLAY): struct A($crate :: S) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", diff --git a/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout b/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout index 73e407918ec..e4212377626 100644 --- a/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout +++ b/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout @@ -1,5 +1,4 @@ -PRINT-ATTR INPUT (DISPLAY): struct A(identity!(crate :: S)); -PRINT-ATTR RE-COLLECTED (DISPLAY): struct A(identity ! ($crate :: S)) ; +PRINT-ATTR INPUT (DISPLAY): struct A(identity ! ($crate :: S)) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -54,8 +53,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ span: #3 bytes(LO..HI), }, ] -PRINT-ATTR INPUT (DISPLAY): struct B(identity!(::dollar_crate_external :: S)); -PRINT-ATTR RE-COLLECTED (DISPLAY): struct B(identity ! ($crate :: S)) ; +PRINT-ATTR INPUT (DISPLAY): struct B(identity ! ($crate :: S)) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", diff --git a/src/test/ui/proc-macro/dollar-crate.stdout b/src/test/ui/proc-macro/dollar-crate.stdout index e125a3e7f17..8a7406b1a3d 100644 --- a/src/test/ui/proc-macro/dollar-crate.stdout +++ b/src/test/ui/proc-macro/dollar-crate.stdout @@ -38,8 +38,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ span: #3 bytes(LO..HI), }, ] -PRINT-ATTR INPUT (DISPLAY): struct A(crate::S); -PRINT-ATTR RE-COLLECTED (DISPLAY): struct A($crate :: S) ; +PRINT-ATTR INPUT (DISPLAY): struct A($crate :: S) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -79,8 +78,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ span: #3 bytes(LO..HI), }, ] -PRINT-DERIVE INPUT (DISPLAY): struct D(crate::S); -PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D($crate :: S) ; +PRINT-DERIVE INPUT (DISPLAY): struct D($crate :: S) ; PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -160,8 +158,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ span: #13 bytes(LO..HI), }, ] -PRINT-ATTR INPUT (DISPLAY): struct A(::dollar_crate_external::S); -PRINT-ATTR RE-COLLECTED (DISPLAY): struct A($crate :: S) ; +PRINT-ATTR INPUT (DISPLAY): struct A($crate :: S) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -201,8 +198,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ span: #13 bytes(LO..HI), }, ] -PRINT-DERIVE INPUT (DISPLAY): struct D(::dollar_crate_external::S); -PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D($crate :: S) ; +PRINT-DERIVE INPUT (DISPLAY): struct D($crate :: S) ; PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", diff --git a/src/test/ui/proc-macro/input-interpolated.stdout b/src/test/ui/proc-macro/input-interpolated.stdout index 7529db3bd06..ee988d48b46 100644 --- a/src/test/ui/proc-macro/input-interpolated.stdout +++ b/src/test/ui/proc-macro/input-interpolated.stdout @@ -1,5 +1,4 @@ PRINT-BANG INPUT (DISPLAY): A -PRINT-BANG RE-COLLECTED (DISPLAY): A PRINT-BANG INPUT (DEBUG): TokenStream [ Group { delimiter: None, @@ -12,8 +11,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ span: #3 bytes(269..271), }, ] -PRINT-ATTR INPUT (DISPLAY): const A: u8 = 0; -PRINT-ATTR RE-COLLECTED (DISPLAY): const A : u8 = 0 ; +PRINT-ATTR INPUT (DISPLAY): const A : u8 = 0 ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "const", @@ -49,9 +47,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ span: #0 bytes(0..0), }, ] -PRINT-DERIVE INPUT (DISPLAY): struct A { -} -PRINT-DERIVE RE-COLLECTED (DISPLAY): struct A { } +PRINT-DERIVE INPUT (DISPLAY): struct A { } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", diff --git a/src/test/ui/proc-macro/meta-delim.rs b/src/test/ui/proc-macro/meta-delim.rs new file mode 100644 index 00000000000..964291bc678 --- /dev/null +++ b/src/test/ui/proc-macro/meta-delim.rs @@ -0,0 +1,12 @@ +// aux-build:meta-delim.rs +// edition:2018 +// run-pass + +// Tests that we can properly deserialize a macro with strange delimiters +// See https://github.com/rust-lang/rust/pull/73569#issuecomment-650860457 + +extern crate meta_delim; + +fn main() { + assert_eq!("a bunch of idents", meta_delim::meta_delim!(a bunch of idents)); +} diff --git a/src/test/ui/proc-macro/meta-macro-hygiene.rs b/src/test/ui/proc-macro/meta-macro-hygiene.rs new file mode 100644 index 00000000000..449377aed99 --- /dev/null +++ b/src/test/ui/proc-macro/meta-macro-hygiene.rs @@ -0,0 +1,13 @@ +// aux-build:make-macro.rs +// aux-build:meta-macro.rs +// edition:2018 +// compile-flags: -Z span-debug -Z unpretty=expanded,hygiene +// check-pass +// normalize-stdout-test "\d+#" -> "0#" +// ^ We don't care about symbol ids, so set them all to 0 +// in the stdout +extern crate meta_macro; + +fn main() { + meta_macro::print_def_site!(); +} diff --git a/src/test/ui/proc-macro/meta-macro-hygiene.stdout b/src/test/ui/proc-macro/meta-macro-hygiene.stdout new file mode 100644 index 00000000000..daca40eda90 --- /dev/null +++ b/src/test/ui/proc-macro/meta-macro-hygiene.stdout @@ -0,0 +1,32 @@ +Def site: $DIR/auxiliary/make-macro.rs:7:9: 10:10 (#3) +#![feature /* 0#0 */(prelude_import)] +#[prelude_import /* 0#1 */] +use std /* 0#1 */::prelude /* 0#1 */::v1 /* 0#1 */::*; +#[macro_use /* 0#1 */] +extern crate std /* 0#1 */; +// aux-build:make-macro.rs +// aux-build:meta-macro.rs +// edition:2018 +// compile-flags: -Z span-debug -Z unpretty=expanded,hygiene +// check-pass +// normalize-stdout-test "\d+#" -> "0#" +// ^ We don't care about symbol ids, so set them all to 0 +// in the stdout +extern crate meta_macro /* 0#0 */; + +fn main /* 0#0 */() { } + +/* +Expansions: +0: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Root +1: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) +2: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "meta_macro::print_def_site") + +SyntaxContexts: +#0: parent: #0, outer_mark: (ExpnId(0), Opaque) +#1: parent: #0, outer_mark: (ExpnId(1), Opaque) +#2: parent: #0, outer_mark: (ExpnId(1), Transparent) +#3: parent: #0, outer_mark: (ExpnId(2), Opaque) +#4: parent: #0, outer_mark: (ExpnId(2), Transparent) +#5: parent: #0, outer_mark: (ExpnId(2), SemiTransparent) +*/ diff --git a/src/test/ui/proc-macro/meta-macro.rs b/src/test/ui/proc-macro/meta-macro.rs new file mode 100644 index 00000000000..dbfde9e113f --- /dev/null +++ b/src/test/ui/proc-macro/meta-macro.rs @@ -0,0 +1,11 @@ +// aux-build:make-macro.rs +// aux-build:meta-macro.rs +// edition:2018 +// compile-flags: -Z span-debug +// run-pass + +extern crate meta_macro; + +fn main() { + meta_macro::print_def_site!(); +} diff --git a/src/test/ui/proc-macro/meta-macro.stdout b/src/test/ui/proc-macro/meta-macro.stdout new file mode 100644 index 00000000000..fa79f72137f --- /dev/null +++ b/src/test/ui/proc-macro/meta-macro.stdout @@ -0,0 +1 @@ +Def site: $DIR/auxiliary/make-macro.rs:7:9: 10:10 (#3) diff --git a/src/test/ui/proc-macro/nested-macro-rules.rs b/src/test/ui/proc-macro/nested-macro-rules.rs new file mode 100644 index 00000000000..2f8ef202327 --- /dev/null +++ b/src/test/ui/proc-macro/nested-macro-rules.rs @@ -0,0 +1,20 @@ +// run-pass +// aux-build:nested-macro-rules.rs +// aux-build:test-macros.rs +// compile-flags: -Z span-debug +// edition:2018 + +extern crate nested_macro_rules; +extern crate test_macros; + +use test_macros::print_bang; + +use nested_macro_rules::FirstStruct; +struct SecondStruct; + +fn main() { + nested_macro_rules::inner_macro!(print_bang); + + nested_macro_rules::outer_macro!(SecondStruct); + inner_macro!(print_bang); +} diff --git a/src/test/ui/proc-macro/nested-macro-rules.stdout b/src/test/ui/proc-macro/nested-macro-rules.stdout new file mode 100644 index 00000000000..e4cfe020324 --- /dev/null +++ b/src/test/ui/proc-macro/nested-macro-rules.stdout @@ -0,0 +1,26 @@ +PRINT-BANG INPUT (DISPLAY): FirstStruct +PRINT-BANG INPUT (DEBUG): TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "FirstStruct", + span: $DIR/auxiliary/nested-macro-rules.rs:15:14: 15:25 (#3), + }, + ], + span: $DIR/auxiliary/nested-macro-rules.rs:9:27: 9:32 (#3), + }, +] +PRINT-BANG INPUT (DISPLAY): SecondStruct +PRINT-BANG INPUT (DEBUG): TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "SecondStruct", + span: $DIR/nested-macro-rules.rs:18:38: 18:50 (#9), + }, + ], + span: $DIR/auxiliary/nested-macro-rules.rs:9:27: 9:32 (#8), + }, +] diff --git a/src/test/ui/proc-macro/nodelim-groups.rs b/src/test/ui/proc-macro/nodelim-groups.rs new file mode 100644 index 00000000000..cfcd4c0d2a6 --- /dev/null +++ b/src/test/ui/proc-macro/nodelim-groups.rs @@ -0,0 +1,19 @@ +// run-pass +// aux-build:test-macros.rs +// compile-flags: -Z span-debug +// edition:2018 +// +// Tests the pretty-printing behavior of inserting `NoDelim` groups + +extern crate test_macros; +use test_macros::print_bang_consume; + +macro_rules! expand_it { + (($val1:expr) ($val2:expr)) => { expand_it!($val1 + $val2) }; + ($val:expr) => { print_bang_consume!("hi" $val (1 + 1)) }; +} + +fn main() { + expand_it!(1 + (25) + 1); + expand_it!(("hello".len()) ("world".len())); +} diff --git a/src/test/ui/proc-macro/nodelim-groups.stdout b/src/test/ui/proc-macro/nodelim-groups.stdout new file mode 100644 index 00000000000..75a189a9fcd --- /dev/null +++ b/src/test/ui/proc-macro/nodelim-groups.stdout @@ -0,0 +1,156 @@ +PRINT-BANG INPUT (DISPLAY): "hi" 1 + (25) + 1 (1 + 1) +PRINT-BANG INPUT (DEBUG): TokenStream [ + Literal { + kind: Str, + symbol: "hi", + suffix: None, + span: $DIR/nodelim-groups.rs:13:42: 13:46 (#3), + }, + Group { + delimiter: None, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/nodelim-groups.rs:17:16: 17:17 (#0), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/nodelim-groups.rs:17:18: 17:19 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "25", + suffix: None, + span: $DIR/nodelim-groups.rs:17:21: 17:23 (#0), + }, + ], + span: $DIR/nodelim-groups.rs:17:20: 17:24 (#0), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/nodelim-groups.rs:17:25: 17:26 (#0), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/nodelim-groups.rs:17:27: 17:28 (#0), + }, + ], + span: $DIR/nodelim-groups.rs:13:47: 13:51 (#3), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/nodelim-groups.rs:13:53: 13:54 (#3), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/nodelim-groups.rs:13:55: 13:56 (#3), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/nodelim-groups.rs:13:57: 13:58 (#3), + }, + ], + span: $DIR/nodelim-groups.rs:13:52: 13:59 (#3), + }, +] +PRINT-BANG INPUT (DISPLAY): "hi" "hello".len() + "world".len() (1 + 1) +PRINT-BANG RE-COLLECTED (DISPLAY): "hi" "hello" . len() + "world" . len() (1 + 1) +PRINT-BANG INPUT (DEBUG): TokenStream [ + Literal { + kind: Str, + symbol: "hi", + suffix: None, + span: $DIR/nodelim-groups.rs:13:42: 13:46 (#8), + }, + Group { + delimiter: None, + stream: TokenStream [ + Literal { + kind: Str, + symbol: "hello", + suffix: None, + span: $DIR/nodelim-groups.rs:13:47: 13:51 (#8), + }, + Punct { + ch: '.', + spacing: Alone, + span: $DIR/nodelim-groups.rs:13:47: 13:51 (#8), + }, + Ident { + ident: "len", + span: $DIR/nodelim-groups.rs:13:47: 13:51 (#8), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/nodelim-groups.rs:13:47: 13:51 (#8), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/nodelim-groups.rs:13:47: 13:51 (#8), + }, + Literal { + kind: Str, + symbol: "world", + suffix: None, + span: $DIR/nodelim-groups.rs:13:47: 13:51 (#8), + }, + Punct { + ch: '.', + spacing: Alone, + span: $DIR/nodelim-groups.rs:13:47: 13:51 (#8), + }, + Ident { + ident: "len", + span: $DIR/nodelim-groups.rs:13:47: 13:51 (#8), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/nodelim-groups.rs:13:47: 13:51 (#8), + }, + ], + span: $DIR/nodelim-groups.rs:13:47: 13:51 (#8), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/nodelim-groups.rs:13:53: 13:54 (#8), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/nodelim-groups.rs:13:55: 13:56 (#8), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/nodelim-groups.rs:13:57: 13:58 (#8), + }, + ], + span: $DIR/nodelim-groups.rs:13:52: 13:59 (#8), + }, +] diff --git a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr index 0552847c48c..3296a2cb094 100644 --- a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr +++ b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr @@ -4,7 +4,9 @@ error: reached the recursion limit while instantiating `std::intrinsics::drop_in LL | / pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) { LL | | // Code here does not matter - this is replaced by the LL | | // real drop glue by the compiler. -LL | | drop_in_place(to_drop) +LL | | +LL | | // SAFETY: see comment above +LL | | unsafe { drop_in_place(to_drop) } LL | | } | |_^ | @@ -14,7 +16,9 @@ note: `std::intrinsics::drop_in_place` defined here LL | / pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) { LL | | // Code here does not matter - this is replaced by the LL | | // real drop glue by the compiler. -LL | | drop_in_place(to_drop) +LL | | +LL | | // SAFETY: see comment above +LL | | unsafe { drop_in_place(to_drop) } LL | | } | |_^ diff --git a/src/test/ui/resolve/resolve-label.rs b/src/test/ui/resolve/resolve-label.rs index 965ee450104..ac5410cd355 100644 --- a/src/test/ui/resolve/resolve-label.rs +++ b/src/test/ui/resolve/resolve-label.rs @@ -2,7 +2,7 @@ fn f() { 'l: loop { fn g() { loop { - break 'l; //~ ERROR use of undeclared label + break 'l; //~ ERROR use of unreachable label } } } diff --git a/src/test/ui/resolve/resolve-label.stderr b/src/test/ui/resolve/resolve-label.stderr index 72a8e443bac..5729348ef21 100644 --- a/src/test/ui/resolve/resolve-label.stderr +++ b/src/test/ui/resolve/resolve-label.stderr @@ -1,9 +1,14 @@ -error[E0426]: use of undeclared label `'l` +error[E0767]: use of unreachable label `'l` --> $DIR/resolve-label.rs:5:23 | +LL | 'l: loop { + | -- unreachable label defined here +... LL | break 'l; - | ^^ undeclared label `'l` + | ^^ unreachable label `'l` + | + = note: labels are unreachable through functions, closures, async blocks and modules error: aborting due to previous error -For more information about this error, try `rustc --explain E0426`. +For more information about this error, try `rustc --explain E0767`. diff --git a/src/test/ui/return-disjoint-regions.rs b/src/test/ui/return-disjoint-regions.rs new file mode 100644 index 00000000000..d0feb3b65e1 --- /dev/null +++ b/src/test/ui/return-disjoint-regions.rs @@ -0,0 +1,7 @@ +// See https://github.com/rust-lang/rust/pull/67911#issuecomment-576023915 +fn f<'a, 'b>(x: i32) -> (&'a i32, &'b i32) { + let y = &x; + (y, y) //~ ERROR cannot return +} + +fn main() {} diff --git a/src/test/ui/return-disjoint-regions.stderr b/src/test/ui/return-disjoint-regions.stderr new file mode 100644 index 00000000000..ed159298804 --- /dev/null +++ b/src/test/ui/return-disjoint-regions.stderr @@ -0,0 +1,11 @@ +error[E0515]: cannot return value referencing function parameter `x` + --> $DIR/return-disjoint-regions.rs:4:5 + | +LL | let y = &x; + | -- `x` is borrowed here +LL | (y, y) + | ^^^^^^ returns a value referencing data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/src/test/ui/rfc-2091-track-caller/call-chain.rs b/src/test/ui/rfc-2091-track-caller/call-chain.rs index 3f1c8f7abe8..fefb84de729 100644 --- a/src/test/ui/rfc-2091-track-caller/call-chain.rs +++ b/src/test/ui/rfc-2091-track-caller/call-chain.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(track_caller)] - use std::panic::Location; struct Foo; diff --git a/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs b/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs index edf9ba2c41a..05240908917 100644 --- a/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs +++ b/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs @@ -6,7 +6,7 @@ // run-pass // compile-flags: -Z unleash-the-miri-inside-of-you -#![feature(core_intrinsics, const_caller_location, track_caller, const_fn)] +#![feature(core_intrinsics, const_caller_location, const_fn)] type L = &'static std::panic::Location<'static>; diff --git a/src/test/ui/rfc-2091-track-caller/caller-location-intrinsic.rs b/src/test/ui/rfc-2091-track-caller/caller-location-intrinsic.rs index 090e912c1d0..f244b74e391 100644 --- a/src/test/ui/rfc-2091-track-caller/caller-location-intrinsic.rs +++ b/src/test/ui/rfc-2091-track-caller/caller-location-intrinsic.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(track_caller)] - #[inline(never)] #[track_caller] fn codegen_caller_loc() -> &'static core::panic::Location<'static> { @@ -15,13 +13,13 @@ macro_rules! caller_location_from_macro { fn main() { let loc = codegen_caller_loc(); assert_eq!(loc.file(), file!()); - assert_eq!(loc.line(), 16); + assert_eq!(loc.line(), 14); assert_eq!(loc.column(), 15); // `Location::caller()` in a macro should behave similarly to `file!` and `line!`, // i.e. point to where the macro was invoked, instead of the macro itself. let loc2 = caller_location_from_macro!(); assert_eq!(loc2.file(), file!()); - assert_eq!(loc2.line(), 23); + assert_eq!(loc2.line(), 21); assert_eq!(loc2.column(), 16); } diff --git a/src/test/ui/rfc-2091-track-caller/const-caller-location.rs b/src/test/ui/rfc-2091-track-caller/const-caller-location.rs index 0614c52c660..8030a4d967a 100644 --- a/src/test/ui/rfc-2091-track-caller/const-caller-location.rs +++ b/src/test/ui/rfc-2091-track-caller/const-caller-location.rs @@ -1,6 +1,6 @@ // run-pass -#![feature(const_fn, track_caller)] +#![feature(const_caller_location, const_fn)] use std::panic::Location; diff --git a/src/test/ui/rfc-2091-track-caller/diverging-caller-location.rs b/src/test/ui/rfc-2091-track-caller/diverging-caller-location.rs index 1fb75ef35ff..6681119557d 100644 --- a/src/test/ui/rfc-2091-track-caller/diverging-caller-location.rs +++ b/src/test/ui/rfc-2091-track-caller/diverging-caller-location.rs @@ -6,8 +6,6 @@ //! we don't inspect the location returned -- it would be difficult to distinguish between the //! explicit panic and a failed assertion. That it compiles and runs is enough for this one. -#![feature(track_caller)] - #[track_caller] fn doesnt_return() -> ! { let _location = core::panic::Location::caller(); diff --git a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs index d6560231871..6f4290e2a5e 100644 --- a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs +++ b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs @@ -1,5 +1,3 @@ -#![feature(track_caller)] - #[track_caller(1)] fn f() {} //~^^ ERROR malformed `track_caller` attribute input diff --git a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr index 8906fa59506..e7ddf8df4ab 100644 --- a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr @@ -1,5 +1,5 @@ error: malformed `track_caller` attribute input - --> $DIR/error-odd-syntax.rs:3:1 + --> $DIR/error-odd-syntax.rs:1:1 | LL | #[track_caller(1)] | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[track_caller]` diff --git a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs index 1145f7786c7..074e1ceb791 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs +++ b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs @@ -1,5 +1,3 @@ -#![feature(track_caller)] - #[track_caller] extern "C" fn f() {} //~^^ ERROR `#[track_caller]` requires Rust ABI diff --git a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr index e08c52fabd6..bcc0c8170e6 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr @@ -1,11 +1,11 @@ error[E0737]: `#[track_caller]` requires Rust ABI - --> $DIR/error-with-invalid-abi.rs:3:1 + --> $DIR/error-with-invalid-abi.rs:1:1 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ error[E0737]: `#[track_caller]` requires Rust ABI - --> $DIR/error-with-invalid-abi.rs:8:5 + --> $DIR/error-with-invalid-abi.rs:6:5 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs index f4573848333..2b110c9a325 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs +++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs @@ -1,4 +1,4 @@ -#![feature(naked_functions, track_caller)] +#![feature(naked_functions)] #[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]` #[naked] diff --git a/src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs b/src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs index 76e62b89ab8..74217f47084 100644 --- a/src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs +++ b/src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(track_caller)] - macro_rules! caller_location_from_macro { () => (core::panic::Location::caller()); } @@ -9,13 +7,13 @@ macro_rules! caller_location_from_macro { fn main() { let loc = core::panic::Location::caller(); assert_eq!(loc.file(), file!()); - assert_eq!(loc.line(), 10); + assert_eq!(loc.line(), 8); assert_eq!(loc.column(), 15); // `Location::caller()` in a macro should behave similarly to `file!` and `line!`, // i.e. point to where the macro was invoked, instead of the macro itself. let loc2 = caller_location_from_macro!(); assert_eq!(loc2.file(), file!()); - assert_eq!(loc2.line(), 17); + assert_eq!(loc2.line(), 15); assert_eq!(loc2.column(), 16); } diff --git a/src/test/ui/rfc-2091-track-caller/only-for-fns.rs b/src/test/ui/rfc-2091-track-caller/only-for-fns.rs index 0fd59b4bf49..bc0ca955280 100644 --- a/src/test/ui/rfc-2091-track-caller/only-for-fns.rs +++ b/src/test/ui/rfc-2091-track-caller/only-for-fns.rs @@ -1,5 +1,3 @@ -#![feature(track_caller)] - #[track_caller] struct S; //~^^ ERROR attribute should be applied to function diff --git a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr index c2fb8fa1eb6..6666dcfa6e5 100644 --- a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr +++ b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr @@ -1,5 +1,5 @@ error[E0739]: attribute should be applied to function - --> $DIR/only-for-fns.rs:3:1 + --> $DIR/only-for-fns.rs:1:1 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ diff --git a/src/test/ui/rfc-2091-track-caller/pass.rs b/src/test/ui/rfc-2091-track-caller/pass.rs index eef83b3d68f..ada150b25cf 100644 --- a/src/test/ui/rfc-2091-track-caller/pass.rs +++ b/src/test/ui/rfc-2091-track-caller/pass.rs @@ -1,6 +1,4 @@ // run-pass -#![feature(track_caller)] - #[track_caller] fn f() {} diff --git a/src/test/ui/rfc-2091-track-caller/track-caller-attribute.rs b/src/test/ui/rfc-2091-track-caller/track-caller-attribute.rs index 76a380ed3e3..efcc1f6942d 100644 --- a/src/test/ui/rfc-2091-track-caller/track-caller-attribute.rs +++ b/src/test/ui/rfc-2091-track-caller/track-caller-attribute.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(track_caller)] - use std::panic::Location; #[track_caller] @@ -20,21 +18,21 @@ fn nested_tracked() -> &'static Location<'static> { fn main() { let location = Location::caller(); assert_eq!(location.file(), file!()); - assert_eq!(location.line(), 21); + assert_eq!(location.line(), 19); assert_eq!(location.column(), 20); let tracked = tracked(); assert_eq!(tracked.file(), file!()); - assert_eq!(tracked.line(), 26); + assert_eq!(tracked.line(), 24); assert_eq!(tracked.column(), 19); let nested = nested_intrinsic(); assert_eq!(nested.file(), file!()); - assert_eq!(nested.line(), 13); + assert_eq!(nested.line(), 11); assert_eq!(nested.column(), 5); let contained = nested_tracked(); assert_eq!(contained.file(), file!()); - assert_eq!(contained.line(), 17); + assert_eq!(contained.line(), 15); assert_eq!(contained.column(), 5); } diff --git a/src/test/ui/rfc-2091-track-caller/track-caller-ffi.rs b/src/test/ui/rfc-2091-track-caller/track-caller-ffi.rs index 23c17d743c4..5115f687c26 100644 --- a/src/test/ui/rfc-2091-track-caller/track-caller-ffi.rs +++ b/src/test/ui/rfc-2091-track-caller/track-caller-ffi.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(track_caller)] - use std::panic::Location; extern "Rust" { @@ -30,21 +28,21 @@ mod provides { fn main() { let location = Location::caller(); assert_eq!(location.file(), file!()); - assert_eq!(location.line(), 31); + assert_eq!(location.line(), 29); assert_eq!(location.column(), 20); let tracked = unsafe { rust_track_caller_ffi_test_tracked() }; assert_eq!(tracked.file(), file!()); - assert_eq!(tracked.line(), 36); + assert_eq!(tracked.line(), 34); assert_eq!(tracked.column(), 28); let untracked = unsafe { rust_track_caller_ffi_test_untracked() }; assert_eq!(untracked.file(), file!()); - assert_eq!(untracked.line(), 26); + assert_eq!(untracked.line(), 24); assert_eq!(untracked.column(), 9); let contained = rust_track_caller_ffi_test_nested_tracked(); assert_eq!(contained.file(), file!()); - assert_eq!(contained.line(), 14); + assert_eq!(contained.line(), 12); assert_eq!(contained.column(), 14); } diff --git a/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs index b17c1efb3d3..5fcfea96d54 100644 --- a/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs +++ b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(track_caller)] - fn pass_to_ptr_call<T>(f: fn(T), x: T) { f(x); } diff --git a/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs index 8ee4d4fa168..4415d850c24 100644 --- a/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs +++ b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(track_caller)] - fn ptr_call(f: fn()) { f(); } diff --git a/src/test/ui/rfc-2091-track-caller/tracked-trait-impls.rs b/src/test/ui/rfc-2091-track-caller/tracked-trait-impls.rs index 0a5f92bb635..4db4c29e53d 100644 --- a/src/test/ui/rfc-2091-track-caller/tracked-trait-impls.rs +++ b/src/test/ui/rfc-2091-track-caller/tracked-trait-impls.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(track_caller)] - macro_rules! assert_expansion_site_is_tracked { () => {{ let location = std::panic::Location::caller(); diff --git a/src/test/ui/rfc-2565-param-attrs/auxiliary/param-attrs.rs b/src/test/ui/rfc-2565-param-attrs/auxiliary/param-attrs.rs index c537c1034b5..2a172c8458d 100644 --- a/src/test/ui/rfc-2565-param-attrs/auxiliary/param-attrs.rs +++ b/src/test/ui/rfc-2565-param-attrs/auxiliary/param-attrs.rs @@ -17,28 +17,27 @@ macro_rules! checker { } } -checker!(attr_extern, r#"extern "C" { - fn ffi(#[a1] arg1: i32, #[a2] ...); -}"#); -checker!(attr_extern_cvar, r#"unsafe extern "C" fn cvar(arg1: i32, #[a1] mut args: ...) { }"#); -checker!(attr_alias, "type Alias = fn(#[a1] u8, #[a2] ...);"); -checker!(attr_free, "fn free(#[a1] arg1: u8) { let lam = |#[a2] W(x), #[a3] y| (); }"); -checker!(attr_inherent_1, "fn inherent1(#[a1] self, #[a2] arg1: u8) { }"); -checker!(attr_inherent_2, "fn inherent2(#[a1] &self, #[a2] arg1: u8) { }"); -checker!(attr_inherent_3, "fn inherent3<'a>(#[a1] &'a mut self, #[a2] arg1: u8) { }"); -checker!(attr_inherent_4, "fn inherent4<'a>(#[a1] self: Box<Self>, #[a2] arg1: u8) { }"); -checker!(attr_inherent_issue_64682, "fn inherent5(#[a1] #[a2] arg1: u8, #[a3] arg2: u8) { }"); -checker!(attr_trait_1, "fn trait1(#[a1] self, #[a2] arg1: u8);"); -checker!(attr_trait_2, "fn trait2(#[a1] &self, #[a2] arg1: u8);"); -checker!(attr_trait_3, "fn trait3<'a>(#[a1] &'a mut self, #[a2] arg1: u8);"); -checker!(attr_trait_4, "fn trait4<'a>(#[a1] self: Box<Self>, #[a2] arg1: u8, #[a3] Vec<u8>);"); -checker!(attr_trait_issue_64682, "fn trait5(#[a1] #[a2] arg1: u8, #[a3] arg2: u8);"); -checker!(rename_params, r#"impl Foo { - fn hello(#[angery(true)] a: i32, #[a2] b: i32, #[what = "how"] c: u32) { } - fn hello2(#[a1] #[a2] a: i32, #[what = "how"] b: i32, - #[angery(true)] c: u32) { - } - fn hello_self(#[a1] #[a2] &self, #[a1] #[a2] a: i32, - #[what = "how"] b: i32, #[angery(true)] c: u32) { - } +checker!(attr_extern, r#"extern "C" { fn ffi(#[a1] arg1 : i32, #[a2] ...) ; }"#); +checker!(attr_extern_cvar, r#"unsafe extern "C" fn cvar(arg1 : i32, #[a1] mut args : ...) { }"#); +checker!(attr_alias, "type Alias = fn(#[a1] u8, #[a2] ...) ;"); +checker!(attr_free, "fn free(#[a1] arg1 : u8) { let lam = | #[a2] W(x), #[a3] y | () ; }"); +checker!(attr_inherent_1, "fn inherent1(#[a1] self, #[a2] arg1 : u8) { }"); +checker!(attr_inherent_2, "fn inherent2(#[a1] & self, #[a2] arg1 : u8) { }"); +checker!(attr_inherent_3, "fn inherent3 < 'a > (#[a1] & 'a mut self, #[a2] arg1 : u8) { }"); +checker!(attr_inherent_4, "fn inherent4 < 'a > (#[a1] self : Box < Self >, #[a2] arg1 : u8) { }"); +checker!(attr_inherent_issue_64682, "fn inherent5(#[a1] #[a2] arg1 : u8, #[a3] arg2 : u8) { }"); +checker!(attr_trait_1, "fn trait1(#[a1] self, #[a2] arg1 : u8) ;"); +checker!(attr_trait_2, "fn trait2(#[a1] & self, #[a2] arg1 : u8) ;"); +checker!(attr_trait_3, "fn trait3 < 'a > (#[a1] & 'a mut self, #[a2] arg1 : u8) ;"); +checker!(attr_trait_4, r#"fn trait4 < 'a > +(#[a1] self : Box < Self >, #[a2] arg1 : u8, #[a3] Vec < u8 >) ;"#); +checker!(attr_trait_issue_64682, "fn trait5(#[a1] #[a2] arg1 : u8, #[a3] arg2 : u8) ;"); +checker!(rename_params, r#"impl Foo +{ + fn hello(#[angery(true)] a : i32, #[a2] b : i32, #[what = "how"] c : u32) + { } fn + hello2(#[a1] #[a2] a : i32, #[what = "how"] b : i32, #[angery(true)] c : + u32) { } fn + hello_self(#[a1] #[a2] & self, #[a1] #[a2] a : i32, #[what = "how"] b : + i32, #[angery(true)] c : u32) { } }"#); diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr index 1e51567a9b1..5516d4a4c1c 100644 --- a/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr @@ -9,7 +9,7 @@ help: if this is a `self` type, give it a parameter name | LL | trait Trait2015 { fn foo(#[allow(C)] self: i32); } | ^^^^^^^^^ -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | trait Trait2015 { fn foo(#[allow(C)] i32: TypeName); } | ^^^^^^^^^^^^^ diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs new file mode 100644 index 00000000000..5c838fd719c --- /dev/null +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs @@ -0,0 +1,34 @@ +// only-x86_64 + +#![feature(target_feature_11)] + +#[target_feature(enable = "avx")] +fn foo() {} + +#[target_feature(enable = "avx")] +unsafe fn foo_unsafe() {} + +fn call(f: impl Fn()) { + f() +} + +fn call_mut(f: impl FnMut()) { + f() +} + +fn call_once(f: impl FnOnce()) { + f() +} + +fn main() { + call(foo); //~ ERROR expected a `std::ops::Fn<()>` closure, found `fn() {foo}` + call_mut(foo); //~ ERROR expected a `std::ops::FnMut<()>` closure, found `fn() {foo}` + call_once(foo); //~ ERROR expected a `std::ops::FnOnce<()>` closure, found `fn() {foo}` + + call(foo_unsafe); + //~^ ERROR expected a `std::ops::Fn<()>` closure, found `unsafe fn() {foo_unsafe}` + call_mut(foo_unsafe); + //~^ ERROR expected a `std::ops::FnMut<()>` closure, found `unsafe fn() {foo_unsafe}` + call_once(foo_unsafe); + //~^ ERROR expected a `std::ops::FnOnce<()>` closure, found `unsafe fn() {foo_unsafe}` +} diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr new file mode 100644 index 00000000000..448077b439e --- /dev/null +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr @@ -0,0 +1,81 @@ +error[E0277]: expected a `std::ops::Fn<()>` closure, found `fn() {foo}` + --> $DIR/fn-traits.rs:24:10 + | +LL | fn call(f: impl Fn()) { + | ---- required by this bound in `call` +... +LL | call(foo); + | ^^^ expected an `Fn<()>` closure, found `fn() {foo}` + | + = help: the trait `std::ops::Fn<()>` is not implemented for `fn() {foo}` + = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ } + = note: `#[target_feature]` functions do not implement the `Fn` traits + +error[E0277]: expected a `std::ops::FnMut<()>` closure, found `fn() {foo}` + --> $DIR/fn-traits.rs:25:14 + | +LL | fn call_mut(f: impl FnMut()) { + | ------- required by this bound in `call_mut` +... +LL | call_mut(foo); + | ^^^ expected an `FnMut<()>` closure, found `fn() {foo}` + | + = help: the trait `std::ops::FnMut<()>` is not implemented for `fn() {foo}` + = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ } + = note: `#[target_feature]` functions do not implement the `Fn` traits + +error[E0277]: expected a `std::ops::FnOnce<()>` closure, found `fn() {foo}` + --> $DIR/fn-traits.rs:26:15 + | +LL | fn call_once(f: impl FnOnce()) { + | -------- required by this bound in `call_once` +... +LL | call_once(foo); + | ^^^ expected an `FnOnce<()>` closure, found `fn() {foo}` + | + = help: the trait `std::ops::FnOnce<()>` is not implemented for `fn() {foo}` + = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ } + = note: `#[target_feature]` functions do not implement the `Fn` traits + +error[E0277]: expected a `std::ops::Fn<()>` closure, found `unsafe fn() {foo_unsafe}` + --> $DIR/fn-traits.rs:28:10 + | +LL | fn call(f: impl Fn()) { + | ---- required by this bound in `call` +... +LL | call(foo_unsafe); + | ^^^^^^^^^^ expected an `Fn<()>` closure, found `unsafe fn() {foo_unsafe}` + | + = help: the trait `std::ops::Fn<()>` is not implemented for `unsafe fn() {foo_unsafe}` + = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ } + = note: `#[target_feature]` functions do not implement the `Fn` traits + +error[E0277]: expected a `std::ops::FnMut<()>` closure, found `unsafe fn() {foo_unsafe}` + --> $DIR/fn-traits.rs:30:14 + | +LL | fn call_mut(f: impl FnMut()) { + | ------- required by this bound in `call_mut` +... +LL | call_mut(foo_unsafe); + | ^^^^^^^^^^ expected an `FnMut<()>` closure, found `unsafe fn() {foo_unsafe}` + | + = help: the trait `std::ops::FnMut<()>` is not implemented for `unsafe fn() {foo_unsafe}` + = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ } + = note: `#[target_feature]` functions do not implement the `Fn` traits + +error[E0277]: expected a `std::ops::FnOnce<()>` closure, found `unsafe fn() {foo_unsafe}` + --> $DIR/fn-traits.rs:32:15 + | +LL | fn call_once(f: impl FnOnce()) { + | -------- required by this bound in `call_once` +... +LL | call_once(foo_unsafe); + | ^^^^^^^^^^ expected an `FnOnce<()>` closure, found `unsafe fn() {foo_unsafe}` + | + = help: the trait `std::ops::FnOnce<()>` is not implemented for `unsafe fn() {foo_unsafe}` + = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ } + = note: `#[target_feature]` functions do not implement the `Fn` traits + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr index 116f5ddd5b4..40c3219bf27 100644 --- a/src/test/ui/span/issue-34264.stderr +++ b/src/test/ui/span/issue-34264.stderr @@ -21,7 +21,7 @@ LL | fn foo(Option<i32>, String) {} | ^ expected one of `:`, `@`, or `|` | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | fn foo(Option<i32>, String: TypeName) {} | ^^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ help: if this is a `self` type, give it a parameter name | LL | fn bar(self: x, y: usize) {} | ^^^^^^^ -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | fn bar(x: TypeName, y: usize) {} | ^^^^^^^^^^^ diff --git a/src/test/ui/suggestions/suggest-labels.stderr b/src/test/ui/suggestions/suggest-labels.stderr index 079821e6490..aac6515b527 100644 --- a/src/test/ui/suggestions/suggest-labels.stderr +++ b/src/test/ui/suggestions/suggest-labels.stderr @@ -1,35 +1,35 @@ error[E0426]: use of undeclared label `'fo` --> $DIR/suggest-labels.rs:4:15 | +LL | 'foo: loop { + | ---- a label with a similar name is reachable LL | break 'fo; | ^^^ - | -help: a label with a similar name exists in this scope - | -LL | break 'foo; - | ^^^^ + | | + | undeclared label `'fo` + | help: try using similarly named label: `'foo` error[E0426]: use of undeclared label `'bor` --> $DIR/suggest-labels.rs:8:18 | +LL | 'bar: loop { + | ---- a label with a similar name is reachable LL | continue 'bor; | ^^^^ - | -help: a label with a similar name exists in this scope - | -LL | continue 'bar; - | ^^^^ + | | + | undeclared label `'bor` + | help: try using similarly named label: `'bar` error[E0426]: use of undeclared label `'longlable` --> $DIR/suggest-labels.rs:13:19 | +LL | 'longlabel1: loop { + | ----------- a label with a similar name is reachable LL | break 'longlable; | ^^^^^^^^^^ - | -help: a label with a similar name exists in this scope - | -LL | break 'longlabel1; - | ^^^^^^^^^^^ + | | + | undeclared label `'longlable` + | help: try using similarly named label: `'longlabel1` error: aborting due to 3 previous errors diff --git a/src/test/ui/unsafe/ranged_ints_macro.rs b/src/test/ui/unsafe/ranged_ints_macro.rs new file mode 100644 index 00000000000..9192ecfe196 --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints_macro.rs @@ -0,0 +1,16 @@ +// build-pass +#![feature(rustc_attrs)] + +macro_rules! apply { + ($val:expr) => { + #[rustc_layout_scalar_valid_range_start($val)] + #[repr(transparent)] + pub(crate) struct NonZero<T>(pub(crate) T); + } +} + +apply!(1); + +fn main() { + let _x = unsafe { NonZero(1) }; +} diff --git a/src/tools/clippy/clippy_lints/src/approx_const.rs b/src/tools/clippy/clippy_lints/src/approx_const.rs index 7e6e2c7eaeb..1d511a86c90 100644 --- a/src/tools/clippy/clippy_lints/src/approx_const.rs +++ b/src/tools/clippy/clippy_lints/src/approx_const.rs @@ -60,15 +60,15 @@ const KNOWN_CONSTS: [(f64, &str, usize); 18] = [ declare_lint_pass!(ApproxConstant => [APPROX_CONSTANT]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ApproxConstant { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for ApproxConstant { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if let ExprKind::Lit(lit) = &e.kind { check_lit(cx, &lit.node, e); } } } -fn check_lit(cx: &LateContext<'_, '_>, lit: &LitKind, e: &Expr<'_>) { +fn check_lit(cx: &LateContext<'_>, lit: &LitKind, e: &Expr<'_>) { match *lit { LitKind::Float(s, LitFloatType::Suffixed(fty)) => match fty { FloatTy::F32 => check_known_consts(cx, e, s, "f32"), @@ -79,7 +79,7 @@ fn check_lit(cx: &LateContext<'_, '_>, lit: &LitKind, e: &Expr<'_>) { } } -fn check_known_consts(cx: &LateContext<'_, '_>, e: &Expr<'_>, s: symbol::Symbol, module: &str) { +fn check_known_consts(cx: &LateContext<'_>, e: &Expr<'_>, s: symbol::Symbol, module: &str) { let s = s.as_str(); if s.parse::<f64>().is_ok() { for &(constant, name, min_digits) in &KNOWN_CONSTS { diff --git a/src/tools/clippy/clippy_lints/src/arithmetic.rs b/src/tools/clippy/clippy_lints/src/arithmetic.rs index cc09b99cf1d..da60856fac9 100644 --- a/src/tools/clippy/clippy_lints/src/arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/arithmetic.rs @@ -58,8 +58,8 @@ pub struct Arithmetic { impl_lint_pass!(Arithmetic => [INTEGER_ARITHMETIC, FLOAT_ARITHMETIC]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for Arithmetic { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { if self.expr_span.is_some() { return; } @@ -111,13 +111,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic { } } - fn check_expr_post(&mut self, _: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>) { + fn check_expr_post(&mut self, _: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { if Some(expr.span) == self.expr_span { self.expr_span = None; } } - fn check_body(&mut self, cx: &LateContext<'_, '_>, body: &hir::Body<'_>) { + fn check_body(&mut self, cx: &LateContext<'_>, body: &hir::Body<'_>) { let body_owner = cx.tcx.hir().body_owner(body.id()); match cx.tcx.hir().body_owner_kind(body_owner) { @@ -135,7 +135,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic { } } - fn check_body_post(&mut self, cx: &LateContext<'_, '_>, body: &hir::Body<'_>) { + fn check_body_post(&mut self, cx: &LateContext<'_>, body: &hir::Body<'_>) { let body_owner = cx.tcx.hir().body_owner(body.id()); let body_span = cx.tcx.hir().span(body_owner); diff --git a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs index c4536b57f8a..cffe8d94e27 100644 --- a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs +++ b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs @@ -29,8 +29,8 @@ declare_clippy_lint! { declare_lint_pass!(AssertionsOnConstants => [ASSERTIONS_ON_CONSTANTS]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssertionsOnConstants { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for AssertionsOnConstants { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { let lint_true = |is_debug: bool| { span_lint_and_help( cx, @@ -114,7 +114,7 @@ enum AssertKind { /// ``` /// /// where `message` is any expression and `c` is a constant bool. -fn match_assert_with_message<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) -> Option<AssertKind> { +fn match_assert_with_message<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<AssertKind> { if_chain! { if let ExprKind::Match(ref expr, ref arms, _) = expr.kind; // matches { let _t = expr; _t } diff --git a/src/tools/clippy/clippy_lints/src/assign_ops.rs b/src/tools/clippy/clippy_lints/src/assign_ops.rs index 51a7647d320..bc6e868823f 100644 --- a/src/tools/clippy/clippy_lints/src/assign_ops.rs +++ b/src/tools/clippy/clippy_lints/src/assign_ops.rs @@ -60,9 +60,9 @@ declare_clippy_lint! { declare_lint_pass!(AssignOps => [ASSIGN_OP_PATTERN, MISREFACTORED_ASSIGN_OP]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { +impl<'tcx> LateLintPass<'tcx> for AssignOps { #[allow(clippy::too_many_lines)] - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { match &expr.kind { hir::ExprKind::AssignOp(op, lhs, rhs) => { if let hir::ExprKind::Binary(binop, l, r) = &rhs.kind { @@ -191,7 +191,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { } fn lint_misrefactored_assign_op( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, expr: &hir::Expr<'_>, op: hir::BinOp, rhs: &hir::Expr<'_>, @@ -246,7 +246,7 @@ fn is_commutative(op: hir::BinOpKind) -> bool { struct ExprVisitor<'a, 'tcx> { assignee: &'a hir::Expr<'a>, counter: u8, - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, } impl<'a, 'tcx> Visitor<'tcx> for ExprVisitor<'a, 'tcx> { diff --git a/src/tools/clippy/clippy_lints/src/atomic_ordering.rs b/src/tools/clippy/clippy_lints/src/atomic_ordering.rs index 65e1e2c519c..efd3f0f671c 100644 --- a/src/tools/clippy/clippy_lints/src/atomic_ordering.rs +++ b/src/tools/clippy/clippy_lints/src/atomic_ordering.rs @@ -52,7 +52,7 @@ const ATOMIC_TYPES: [&str; 12] = [ "AtomicUsize", ]; -fn type_is_atomic(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { +fn type_is_atomic(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { if let ty::Adt(&ty::AdtDef { did, .. }, _) = cx.tables().expr_ty(expr).kind { ATOMIC_TYPES .iter() @@ -62,13 +62,13 @@ fn type_is_atomic(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { } } -fn match_ordering_def_path(cx: &LateContext<'_, '_>, did: DefId, orderings: &[&str]) -> bool { +fn match_ordering_def_path(cx: &LateContext<'_>, did: DefId, orderings: &[&str]) -> bool { orderings .iter() .any(|ordering| match_def_path(cx, did, &["core", "sync", "atomic", "Ordering", ordering])) } -fn check_atomic_load_store(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { +fn check_atomic_load_store(cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { if let ExprKind::MethodCall(ref method_path, _, args, _) = &expr.kind; let method = method_path.ident.name.as_str(); @@ -76,7 +76,7 @@ fn check_atomic_load_store(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { if method == "load" || method == "store"; let ordering_arg = if method == "load" { &args[1] } else { &args[2] }; if let ExprKind::Path(ref ordering_qpath) = ordering_arg.kind; - if let Some(ordering_def_id) = cx.tables().qpath_res(ordering_qpath, ordering_arg.hir_id).opt_def_id(); + if let Some(ordering_def_id) = cx.qpath_res(ordering_qpath, ordering_arg.hir_id).opt_def_id(); then { if method == "load" && match_ordering_def_path(cx, ordering_def_id, &["Release", "AcqRel"]) { @@ -103,16 +103,16 @@ fn check_atomic_load_store(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { } } -fn check_memory_fence(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { +fn check_memory_fence(cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { if let ExprKind::Call(ref func, ref args) = expr.kind; if let ExprKind::Path(ref func_qpath) = func.kind; - if let Some(def_id) = cx.tables().qpath_res(func_qpath, func.hir_id).opt_def_id(); + if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); if ["fence", "compiler_fence"] .iter() .any(|func| match_def_path(cx, def_id, &["core", "sync", "atomic", func])); if let ExprKind::Path(ref ordering_qpath) = &args[0].kind; - if let Some(ordering_def_id) = cx.tables().qpath_res(ordering_qpath, args[0].hir_id).opt_def_id(); + if let Some(ordering_def_id) = cx.qpath_res(ordering_qpath, args[0].hir_id).opt_def_id(); if match_ordering_def_path(cx, ordering_def_id, &["Relaxed"]); then { span_lint_and_help( @@ -127,8 +127,8 @@ fn check_memory_fence(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AtomicOrdering { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for AtomicOrdering { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { check_atomic_load_store(cx, expr); check_memory_fence(cx, expr); } diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs index 41f125d4839..2505ff32fe5 100644 --- a/src/tools/clippy/clippy_lints/src/attrs.rs +++ b/src/tools/clippy/clippy_lints/src/attrs.rs @@ -251,8 +251,8 @@ declare_lint_pass!(Attributes => [ UNKNOWN_CLIPPY_LINTS, ]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Attributes { - fn check_attribute(&mut self, cx: &LateContext<'a, 'tcx>, attr: &'tcx Attribute) { +impl<'tcx> LateLintPass<'tcx> for Attributes { + fn check_attribute(&mut self, cx: &LateContext<'tcx>, attr: &'tcx Attribute) { if let Some(items) = &attr.meta_item_list() { if let Some(ident) = attr.ident() { match &*ident.as_str() { @@ -278,7 +278,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Attributes { } } - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'_>) { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if is_relevant_item(cx, item) { check_attrs(cx, item.span, item.ident.name, &item.attrs) } @@ -350,13 +350,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Attributes { } } - fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem<'_>) { + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) { if is_relevant_impl(cx, item) { check_attrs(cx, item.span, item.ident.name, &item.attrs) } } - fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem<'_>) { + fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { if is_relevant_trait(cx, item) { check_attrs(cx, item.span, item.ident.name, &item.attrs) } @@ -364,7 +364,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Attributes { } #[allow(clippy::single_match_else)] -fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) { +fn check_clippy_lint_names(cx: &LateContext<'_>, items: &[NestedMetaItem]) { let lint_store = cx.lints(); for lint in items { if_chain! { @@ -416,7 +416,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) { } } -fn is_relevant_item(cx: &LateContext<'_, '_>, item: &Item<'_>) -> bool { +fn is_relevant_item(cx: &LateContext<'_>, item: &Item<'_>) -> bool { if let ItemKind::Fn(_, _, eid) = item.kind { is_relevant_expr(cx, cx.tcx.body_tables(eid), &cx.tcx.hir().body(eid).value) } else { @@ -424,14 +424,14 @@ fn is_relevant_item(cx: &LateContext<'_, '_>, item: &Item<'_>) -> bool { } } -fn is_relevant_impl(cx: &LateContext<'_, '_>, item: &ImplItem<'_>) -> bool { +fn is_relevant_impl(cx: &LateContext<'_>, item: &ImplItem<'_>) -> bool { match item.kind { ImplItemKind::Fn(_, eid) => is_relevant_expr(cx, cx.tcx.body_tables(eid), &cx.tcx.hir().body(eid).value), _ => false, } } -fn is_relevant_trait(cx: &LateContext<'_, '_>, item: &TraitItem<'_>) -> bool { +fn is_relevant_trait(cx: &LateContext<'_>, item: &TraitItem<'_>) -> bool { match item.kind { TraitItemKind::Fn(_, TraitFn::Required(_)) => true, TraitItemKind::Fn(_, TraitFn::Provided(eid)) => { @@ -441,7 +441,7 @@ fn is_relevant_trait(cx: &LateContext<'_, '_>, item: &TraitItem<'_>) -> bool { } } -fn is_relevant_block(cx: &LateContext<'_, '_>, tables: &ty::TypeckTables<'_>, block: &Block<'_>) -> bool { +fn is_relevant_block(cx: &LateContext<'_>, tables: &ty::TypeckTables<'_>, block: &Block<'_>) -> bool { if let Some(stmt) = block.stmts.first() { match &stmt.kind { StmtKind::Local(_) => true, @@ -453,7 +453,7 @@ fn is_relevant_block(cx: &LateContext<'_, '_>, tables: &ty::TypeckTables<'_>, bl } } -fn is_relevant_expr(cx: &LateContext<'_, '_>, tables: &ty::TypeckTables<'_>, expr: &Expr<'_>) -> bool { +fn is_relevant_expr(cx: &LateContext<'_>, tables: &ty::TypeckTables<'_>, expr: &Expr<'_>) -> bool { match &expr.kind { ExprKind::Block(block, _) => is_relevant_block(cx, tables, block), ExprKind::Ret(Some(e)) => is_relevant_expr(cx, tables, e), @@ -473,7 +473,7 @@ fn is_relevant_expr(cx: &LateContext<'_, '_>, tables: &ty::TypeckTables<'_>, exp } } -fn check_attrs(cx: &LateContext<'_, '_>, span: Span, name: Name, attrs: &[Attribute]) { +fn check_attrs(cx: &LateContext<'_>, span: Span, name: Name, attrs: &[Attribute]) { if span.from_expansion() { return; } @@ -498,7 +498,7 @@ fn check_attrs(cx: &LateContext<'_, '_>, span: Span, name: Name, attrs: &[Attrib } } -fn check_semver(cx: &LateContext<'_, '_>, span: Span, lit: &Lit) { +fn check_semver(cx: &LateContext<'_>, span: Span, lit: &Lit) { if let LitKind::Str(is, _) = lit.kind { if Version::parse(&is.as_str()).is_ok() { return; diff --git a/src/tools/clippy/clippy_lints/src/await_holding_lock.rs b/src/tools/clippy/clippy_lints/src/await_holding_lock.rs index a88f922d8e0..20b91bc0f1b 100644 --- a/src/tools/clippy/clippy_lints/src/await_holding_lock.rs +++ b/src/tools/clippy/clippy_lints/src/await_holding_lock.rs @@ -51,8 +51,8 @@ declare_clippy_lint! { declare_lint_pass!(AwaitHoldingLock => [AWAIT_HOLDING_LOCK]); -impl LateLintPass<'_, '_> for AwaitHoldingLock { - fn check_body(&mut self, cx: &LateContext<'_, '_>, body: &'_ Body<'_>) { +impl LateLintPass<'_> for AwaitHoldingLock { + fn check_body(&mut self, cx: &LateContext<'_>, body: &'_ Body<'_>) { use AsyncGeneratorKind::{Block, Closure, Fn}; if let Some(GeneratorKind::Async(Block | Closure | Fn)) = body.generator_kind { let body_id = BodyId { @@ -65,7 +65,7 @@ impl LateLintPass<'_, '_> for AwaitHoldingLock { } } -fn check_interior_types(cx: &LateContext<'_, '_>, ty_causes: &[GeneratorInteriorTypeCause<'_>], span: Span) { +fn check_interior_types(cx: &LateContext<'_>, ty_causes: &[GeneratorInteriorTypeCause<'_>], span: Span) { for ty_cause in ty_causes { if let rustc_middle::ty::Adt(adt, _) = ty_cause.ty.kind { if is_mutex_guard(cx, adt.did) { @@ -82,7 +82,7 @@ fn check_interior_types(cx: &LateContext<'_, '_>, ty_causes: &[GeneratorInterior } } -fn is_mutex_guard(cx: &LateContext<'_, '_>, def_id: DefId) -> bool { +fn is_mutex_guard(cx: &LateContext<'_>, def_id: DefId) -> bool { match_def_path(cx, def_id, &paths::MUTEX_GUARD) || match_def_path(cx, def_id, &paths::RWLOCK_READ_GUARD) || match_def_path(cx, def_id, &paths::RWLOCK_WRITE_GUARD) diff --git a/src/tools/clippy/clippy_lints/src/bit_mask.rs b/src/tools/clippy/clippy_lints/src/bit_mask.rs index a53f3249b85..d1d177e7a4a 100644 --- a/src/tools/clippy/clippy_lints/src/bit_mask.rs +++ b/src/tools/clippy/clippy_lints/src/bit_mask.rs @@ -110,8 +110,8 @@ impl BitMask { impl_lint_pass!(BitMask => [BAD_BIT_MASK, INEFFECTIVE_BIT_MASK, VERBOSE_BIT_MASK]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BitMask { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for BitMask { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if let ExprKind::Binary(cmp, left, right) = &e.kind { if cmp.node.is_comparison() { if let Some(cmp_opt) = fetch_int_literal(cx, right) { @@ -164,7 +164,7 @@ fn invert_cmp(cmp: BinOpKind) -> BinOpKind { } } -fn check_compare(cx: &LateContext<'_, '_>, bit_op: &Expr<'_>, cmp_op: BinOpKind, cmp_value: u128, span: Span) { +fn check_compare(cx: &LateContext<'_>, bit_op: &Expr<'_>, cmp_op: BinOpKind, cmp_value: u128, span: Span) { if let ExprKind::Binary(op, left, right) = &bit_op.kind { if op.node != BinOpKind::BitAnd && op.node != BinOpKind::BitOr { return; @@ -177,7 +177,7 @@ fn check_compare(cx: &LateContext<'_, '_>, bit_op: &Expr<'_>, cmp_op: BinOpKind, #[allow(clippy::too_many_lines)] fn check_bit_mask( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, bit_op: BinOpKind, cmp_op: BinOpKind, mask_value: u128, @@ -290,7 +290,7 @@ fn check_bit_mask( } } -fn check_ineffective_lt(cx: &LateContext<'_, '_>, span: Span, m: u128, c: u128, op: &str) { +fn check_ineffective_lt(cx: &LateContext<'_>, span: Span, m: u128, c: u128, op: &str) { if c.is_power_of_two() && m < c { span_lint( cx, @@ -304,7 +304,7 @@ fn check_ineffective_lt(cx: &LateContext<'_, '_>, span: Span, m: u128, c: u128, } } -fn check_ineffective_gt(cx: &LateContext<'_, '_>, span: Span, m: u128, c: u128, op: &str) { +fn check_ineffective_gt(cx: &LateContext<'_>, span: Span, m: u128, c: u128, op: &str) { if (c + 1).is_power_of_two() && m <= c { span_lint( cx, @@ -318,7 +318,7 @@ fn check_ineffective_gt(cx: &LateContext<'_, '_>, span: Span, m: u128, c: u128, } } -fn fetch_int_literal(cx: &LateContext<'_, '_>, lit: &Expr<'_>) -> Option<u128> { +fn fetch_int_literal(cx: &LateContext<'_>, lit: &Expr<'_>) -> Option<u128> { match constant(cx, cx.tables(), lit)?.0 { Constant::Int(n) => Some(n), _ => None, diff --git a/src/tools/clippy/clippy_lints/src/blacklisted_name.rs b/src/tools/clippy/clippy_lints/src/blacklisted_name.rs index 6f26f031431..153870fb416 100644 --- a/src/tools/clippy/clippy_lints/src/blacklisted_name.rs +++ b/src/tools/clippy/clippy_lints/src/blacklisted_name.rs @@ -35,8 +35,8 @@ impl BlacklistedName { impl_lint_pass!(BlacklistedName => [BLACKLISTED_NAME]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlacklistedName { - fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat<'_>) { +impl<'tcx> LateLintPass<'tcx> for BlacklistedName { + fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) { if let PatKind::Binding(.., ident, _) = pat.kind { if self.blacklist.contains(&ident.name.to_string()) { span_lint( diff --git a/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs b/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs index 8fa9b05ca32..1b73ced89b3 100644 --- a/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs +++ b/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs @@ -45,7 +45,7 @@ declare_lint_pass!(BlocksInIfConditions => [BLOCKS_IN_IF_CONDITIONS]); struct ExVisitor<'a, 'tcx> { found_block: Option<&'tcx Expr<'tcx>>, - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, } impl<'a, 'tcx> Visitor<'tcx> for ExVisitor<'a, 'tcx> { @@ -71,8 +71,8 @@ const BRACED_EXPR_MESSAGE: &str = "omit braces around single expression conditio const COMPLEX_BLOCK_MESSAGE: &str = "in an `if` condition, avoid complex blocks or closures with blocks; \ instead, move the block or closure higher and bind it with a `let`"; -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlocksInIfConditions { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for BlocksInIfConditions { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if in_external_macro(cx.sess(), expr.span) { return; } diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs index cc399a1f8a0..32d0979e99b 100644 --- a/src/tools/clippy/clippy_lints/src/booleans.rs +++ b/src/tools/clippy/clippy_lints/src/booleans.rs @@ -55,10 +55,10 @@ const METHODS_WITH_NEGATION: [(&str, &str); 2] = [("is_some", "is_none"), ("is_e declare_lint_pass!(NonminimalBool => [NONMINIMAL_BOOL, LOGIC_BUG]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonminimalBool { +impl<'tcx> LateLintPass<'tcx> for NonminimalBool { fn check_fn( &mut self, - cx: &LateContext<'a, 'tcx>, + cx: &LateContext<'tcx>, _: FnKind<'tcx>, _: &'tcx FnDecl<'_>, body: &'tcx Body<'_>, @@ -70,13 +70,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonminimalBool { } struct NonminimalBoolVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, } use quine_mc_cluskey::Bool; struct Hir2Qmm<'a, 'tcx, 'v> { terminals: Vec<&'v Expr<'v>>, - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, } impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { @@ -155,7 +155,7 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { struct SuggestContext<'a, 'tcx, 'v> { terminals: &'v [&'v Expr<'v>], - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, output: String, } @@ -222,7 +222,7 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { } } -fn simplify_not(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<String> { +fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> { match &expr.kind { ExprKind::Binary(binop, lhs, rhs) => { if !implements_ord(cx, lhs) { @@ -268,7 +268,7 @@ fn simplify_not(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<String> { } } -fn suggest(cx: &LateContext<'_, '_>, suggestion: &Bool, terminals: &[&Expr<'_>]) -> String { +fn suggest(cx: &LateContext<'_>, suggestion: &Bool, terminals: &[&Expr<'_>]) -> String { let mut suggest_context = SuggestContext { terminals, cx, @@ -464,13 +464,13 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> { } } -fn implements_ord<'a, 'tcx>(cx: &'a LateContext<'a, 'tcx>, expr: &Expr<'_>) -> bool { +fn implements_ord<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> bool { let ty = cx.tables().expr_ty(expr); get_trait_def_id(cx, &paths::ORD).map_or(false, |id| implements_trait(cx, ty, id, &[])) } struct NotSimplificationVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, } impl<'a, 'tcx> Visitor<'tcx> for NotSimplificationVisitor<'a, 'tcx> { diff --git a/src/tools/clippy/clippy_lints/src/bytecount.rs b/src/tools/clippy/clippy_lints/src/bytecount.rs index c00bb23069b..1cdfea1f526 100644 --- a/src/tools/clippy/clippy_lints/src/bytecount.rs +++ b/src/tools/clippy/clippy_lints/src/bytecount.rs @@ -35,8 +35,8 @@ declare_clippy_lint! { declare_lint_pass!(ByteCount => [NAIVE_BYTECOUNT]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount { - fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for ByteCount { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { if let ExprKind::MethodCall(ref count, _, ref count_args, _) = expr.kind; if count.ident.name == sym!(count); diff --git a/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs b/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs index c40a387d297..76a000157df 100644 --- a/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs +++ b/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs @@ -36,7 +36,7 @@ declare_clippy_lint! { "common metadata is defined in `Cargo.toml`" } -fn missing_warning(cx: &LateContext<'_, '_>, package: &cargo_metadata::Package, field: &str) { +fn missing_warning(cx: &LateContext<'_>, package: &cargo_metadata::Package, field: &str) { let message = format!("package `{}` is missing `{}` metadata", package.name, field); span_lint(cx, CARGO_COMMON_METADATA, DUMMY_SP, &message); } @@ -56,8 +56,8 @@ fn is_empty_vec(value: &[String]) -> bool { declare_lint_pass!(CargoCommonMetadata => [CARGO_COMMON_METADATA]); -impl LateLintPass<'_, '_> for CargoCommonMetadata { - fn check_crate(&mut self, cx: &LateContext<'_, '_>, _: &Crate<'_>) { +impl LateLintPass<'_> for CargoCommonMetadata { + fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) { if !run_lints(cx, &[CARGO_COMMON_METADATA], CRATE_HIR_ID) { return; } diff --git a/src/tools/clippy/clippy_lints/src/checked_conversions.rs b/src/tools/clippy/clippy_lints/src/checked_conversions.rs index 88145015ba8..841902943f0 100644 --- a/src/tools/clippy/clippy_lints/src/checked_conversions.rs +++ b/src/tools/clippy/clippy_lints/src/checked_conversions.rs @@ -41,8 +41,8 @@ declare_clippy_lint! { declare_lint_pass!(CheckedConversions => [CHECKED_CONVERSIONS]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CheckedConversions { - fn check_expr(&mut self, cx: &LateContext<'_, '_>, item: &Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for CheckedConversions { + fn check_expr(&mut self, cx: &LateContext<'_>, item: &Expr<'_>) { let result = if_chain! { if !in_external_macro(cx.sess(), item.span); if let ExprKind::Binary(op, ref left, ref right) = &item.kind; @@ -83,7 +83,7 @@ fn single_check<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<Conversion<'tcx>> { } /// Searches for a combination of upper & lower bound checks -fn double_check<'a>(cx: &LateContext<'_, '_>, left: &'a Expr<'_>, right: &'a Expr<'_>) -> Option<Conversion<'a>> { +fn double_check<'a>(cx: &LateContext<'_>, left: &'a Expr<'_>, right: &'a Expr<'_>) -> Option<Conversion<'a>> { let upper_lower = |l, r| { let upper = check_upper_bound(l); let lower = check_lower_bound(r); @@ -112,7 +112,7 @@ enum ConversionType { impl<'a> Conversion<'a> { /// Combine multiple conversions if the are compatible - pub fn combine(self, other: Self, cx: &LateContext<'_, '_>) -> Option<Conversion<'a>> { + pub fn combine(self, other: Self, cx: &LateContext<'_>) -> Option<Conversion<'a>> { if self.is_compatible(&other, cx) { // Prefer a Conversion that contains a type-constraint Some(if self.to_type.is_some() { self } else { other }) @@ -123,7 +123,7 @@ impl<'a> Conversion<'a> { /// Checks if two conversions are compatible /// same type of conversion, same 'castee' and same 'to type' - pub fn is_compatible(&self, other: &Self, cx: &LateContext<'_, '_>) -> bool { + pub fn is_compatible(&self, other: &Self, cx: &LateContext<'_>) -> bool { (self.cvt == other.cvt) && (SpanlessEq::new(cx).eq_expr(self.expr_to_cast, other.expr_to_cast)) && (self.has_compatible_to_type(other)) diff --git a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs index 78e509d2ecd..6bbdbe957cc 100644 --- a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs +++ b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs @@ -43,9 +43,9 @@ impl_lint_pass!(CognitiveComplexity => [COGNITIVE_COMPLEXITY]); impl CognitiveComplexity { #[allow(clippy::cast_possible_truncation)] - fn check<'a, 'tcx>( + fn check<'tcx>( &mut self, - cx: &'a LateContext<'a, 'tcx>, + cx: &LateContext<'tcx>, kind: FnKind<'tcx>, decl: &'tcx FnDecl<'_>, body: &'tcx Body<'_>, @@ -112,10 +112,10 @@ impl CognitiveComplexity { } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CognitiveComplexity { +impl<'tcx> LateLintPass<'tcx> for CognitiveComplexity { fn check_fn( &mut self, - cx: &LateContext<'a, 'tcx>, + cx: &LateContext<'tcx>, kind: FnKind<'tcx>, decl: &'tcx FnDecl<'_>, body: &'tcx Body<'_>, @@ -128,10 +128,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CognitiveComplexity { } } - fn enter_lint_attrs(&mut self, cx: &LateContext<'a, 'tcx>, attrs: &'tcx [Attribute]) { + fn enter_lint_attrs(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) { self.limit.push_attrs(cx.sess(), attrs, "cognitive_complexity"); } - fn exit_lint_attrs(&mut self, cx: &LateContext<'a, 'tcx>, attrs: &'tcx [Attribute]) { + fn exit_lint_attrs(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) { self.limit.pop_attrs(cx.sess(), attrs, "cognitive_complexity"); } } diff --git a/src/tools/clippy/clippy_lints/src/comparison_chain.rs b/src/tools/clippy/clippy_lints/src/comparison_chain.rs index 9c0d33f9280..26476af4cb6 100644 --- a/src/tools/clippy/clippy_lints/src/comparison_chain.rs +++ b/src/tools/clippy/clippy_lints/src/comparison_chain.rs @@ -52,8 +52,8 @@ declare_clippy_lint! { declare_lint_pass!(ComparisonChain => [COMPARISON_CHAIN]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ComparisonChain { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for ComparisonChain { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if expr.span.from_expansion() { return; } diff --git a/src/tools/clippy/clippy_lints/src/consts.rs b/src/tools/clippy/clippy_lints/src/consts.rs index 550752396c7..2f963dfcf8b 100644 --- a/src/tools/clippy/clippy_lints/src/consts.rs +++ b/src/tools/clippy/clippy_lints/src/consts.rs @@ -172,9 +172,9 @@ pub fn lit_to_constant(lit: &LitKind, ty: Option<Ty<'_>>) -> Constant { } } -pub fn constant<'c, 'cc>( - lcx: &LateContext<'c, 'cc>, - tables: &'c ty::TypeckTables<'cc>, +pub fn constant<'tcx>( + lcx: &LateContext<'tcx>, + tables: &ty::TypeckTables<'tcx>, e: &Expr<'_>, ) -> Option<(Constant, bool)> { let mut cx = ConstEvalLateContext { @@ -187,19 +187,19 @@ pub fn constant<'c, 'cc>( cx.expr(e).map(|cst| (cst, cx.needed_resolution)) } -pub fn constant_simple<'c, 'cc>( - lcx: &LateContext<'c, 'cc>, - tables: &'c ty::TypeckTables<'cc>, +pub fn constant_simple<'tcx>( + lcx: &LateContext<'tcx>, + tables: &ty::TypeckTables<'tcx>, e: &Expr<'_>, ) -> Option<Constant> { constant(lcx, tables, e).and_then(|(cst, res)| if res { None } else { Some(cst) }) } /// Creates a `ConstEvalLateContext` from the given `LateContext` and `TypeckTables`. -pub fn constant_context<'c, 'cc>( - lcx: &'c LateContext<'c, 'cc>, - tables: &'c ty::TypeckTables<'cc>, -) -> ConstEvalLateContext<'c, 'cc> { +pub fn constant_context<'a, 'tcx>( + lcx: &'a LateContext<'tcx>, + tables: &'a ty::TypeckTables<'tcx>, +) -> ConstEvalLateContext<'a, 'tcx> { ConstEvalLateContext { lcx, tables, @@ -210,14 +210,14 @@ pub fn constant_context<'c, 'cc>( } pub struct ConstEvalLateContext<'a, 'tcx> { - lcx: &'a LateContext<'a, 'tcx>, + lcx: &'a LateContext<'tcx>, tables: &'a ty::TypeckTables<'tcx>, param_env: ty::ParamEnv<'tcx>, needed_resolution: bool, substs: SubstsRef<'tcx>, } -impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { +impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { /// Simple constant folding: Insert an expression, get a constant or none. pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant> { if let Some((ref cond, ref then, otherwise)) = higher::if_block(&e) { @@ -318,7 +318,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } /// Lookup a possibly constant expression from a `ExprKind::Path`. - fn fetch_path(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'cc>) -> Option<Constant> { + fn fetch_path(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'tcx>) -> Option<Constant> { let res = self.tables.qpath_res(qpath, id); match res { Res::Def(DefKind::Const | DefKind::AssocConst, def_id) => { diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs index efd4a31f559..1257032337a 100644 --- a/src/tools/clippy/clippy_lints/src/copies.rs +++ b/src/tools/clippy/clippy_lints/src/copies.rs @@ -151,8 +151,8 @@ declare_clippy_lint! { declare_lint_pass!(CopyAndPaste => [IFS_SAME_COND, SAME_FUNCTIONS_IN_IF_CONDITION, IF_SAME_THEN_ELSE, MATCH_SAME_ARMS]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyAndPaste { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for CopyAndPaste { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if !expr.span.from_expansion() { // skip ifs directly in else, it will be checked in the parent if if let Some(expr) = get_parent_expr(cx, expr) { @@ -173,7 +173,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyAndPaste { } /// Implementation of `IF_SAME_THEN_ELSE`. -fn lint_same_then_else(cx: &LateContext<'_, '_>, blocks: &[&Block<'_>]) { +fn lint_same_then_else(cx: &LateContext<'_>, blocks: &[&Block<'_>]) { let eq: &dyn Fn(&&Block<'_>, &&Block<'_>) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).eq_block(lhs, rhs) }; @@ -190,9 +190,9 @@ fn lint_same_then_else(cx: &LateContext<'_, '_>, blocks: &[&Block<'_>]) { } /// Implementation of `IFS_SAME_COND`. -fn lint_same_cond(cx: &LateContext<'_, '_>, conds: &[&Expr<'_>]) { +fn lint_same_cond(cx: &LateContext<'_>, conds: &[&Expr<'_>]) { let hash: &dyn Fn(&&Expr<'_>) -> u64 = &|expr| -> u64 { - let mut h = SpanlessHash::new(cx, cx.tables()); + let mut h = SpanlessHash::new(cx); h.hash_expr(expr); h.finish() }; @@ -213,9 +213,9 @@ fn lint_same_cond(cx: &LateContext<'_, '_>, conds: &[&Expr<'_>]) { } /// Implementation of `SAME_FUNCTIONS_IN_IF_CONDITION`. -fn lint_same_fns_in_if_cond(cx: &LateContext<'_, '_>, conds: &[&Expr<'_>]) { +fn lint_same_fns_in_if_cond(cx: &LateContext<'_>, conds: &[&Expr<'_>]) { let hash: &dyn Fn(&&Expr<'_>) -> u64 = &|expr| -> u64 { - let mut h = SpanlessHash::new(cx, cx.tables()); + let mut h = SpanlessHash::new(cx); h.hash_expr(expr); h.finish() }; @@ -241,7 +241,7 @@ fn lint_same_fns_in_if_cond(cx: &LateContext<'_, '_>, conds: &[&Expr<'_>]) { } /// Implementation of `MATCH_SAME_ARMS`. -fn lint_match_arms<'tcx>(cx: &LateContext<'_, 'tcx>, expr: &Expr<'_>) { +fn lint_match_arms<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) { fn same_bindings<'tcx>(lhs: &FxHashMap<Symbol, Ty<'tcx>>, rhs: &FxHashMap<Symbol, Ty<'tcx>>) -> bool { lhs.len() == rhs.len() && lhs @@ -251,7 +251,7 @@ fn lint_match_arms<'tcx>(cx: &LateContext<'_, 'tcx>, expr: &Expr<'_>) { if let ExprKind::Match(_, ref arms, MatchSource::Normal) = expr.kind { let hash = |&(_, arm): &(usize, &Arm<'_>)| -> u64 { - let mut h = SpanlessHash::new(cx, cx.tables()); + let mut h = SpanlessHash::new(cx); h.hash_expr(&arm.body); h.finish() }; @@ -309,8 +309,8 @@ fn lint_match_arms<'tcx>(cx: &LateContext<'_, 'tcx>, expr: &Expr<'_>) { } /// Returns the list of bindings in a pattern. -fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat<'_>) -> FxHashMap<Symbol, Ty<'tcx>> { - fn bindings_impl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat<'_>, map: &mut FxHashMap<Symbol, Ty<'tcx>>) { +fn bindings<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'_>) -> FxHashMap<Symbol, Ty<'tcx>> { + fn bindings_impl<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'_>, map: &mut FxHashMap<Symbol, Ty<'tcx>>) { match pat.kind { PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => bindings_impl(cx, pat, map), PatKind::TupleStruct(_, pats, _) => { diff --git a/src/tools/clippy/clippy_lints/src/copy_iterator.rs b/src/tools/clippy/clippy_lints/src/copy_iterator.rs index d79aa2ef020..34940245322 100644 --- a/src/tools/clippy/clippy_lints/src/copy_iterator.rs +++ b/src/tools/clippy/clippy_lints/src/copy_iterator.rs @@ -31,8 +31,8 @@ declare_clippy_lint! { declare_lint_pass!(CopyIterator => [COPY_ITERATOR]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyIterator { - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for CopyIterator { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if let ItemKind::Impl { of_trait: Some(ref trait_ref), .. diff --git a/src/tools/clippy/clippy_lints/src/default_trait_access.rs b/src/tools/clippy/clippy_lints/src/default_trait_access.rs index 69ae509fb23..fab95db0196 100644 --- a/src/tools/clippy/clippy_lints/src/default_trait_access.rs +++ b/src/tools/clippy/clippy_lints/src/default_trait_access.rs @@ -30,13 +30,13 @@ declare_clippy_lint! { declare_lint_pass!(DefaultTraitAccess => [DEFAULT_TRAIT_ACCESS]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for DefaultTraitAccess { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { if let ExprKind::Call(ref path, ..) = expr.kind; if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id); if let ExprKind::Path(ref qpath) = path.kind; - if let Some(def_id) = cx.tables().qpath_res(qpath, path.hir_id).opt_def_id(); + if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id(); if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD); then { match qpath { diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 1c6cc936900..d740d88a77d 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -38,8 +38,8 @@ declare_lint_pass!(Dereferencing => [ EXPLICIT_DEREF_METHODS ]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Dereferencing { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for Dereferencing { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { if !expr.span.from_expansion(); if let ExprKind::MethodCall(ref method_name, _, ref args, _) = &expr.kind; @@ -70,7 +70,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Dereferencing { } } -fn lint_deref(cx: &LateContext<'_, '_>, method_name: &str, call_expr: &Expr<'_>, var_span: Span, expr_span: Span) { +fn lint_deref(cx: &LateContext<'_>, method_name: &str, call_expr: &Expr<'_>, var_span: Span, expr_span: Span) { match method_name { "deref" => { if cx.tcx.lang_items().deref_trait().map_or(false, |id| { diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index 3cbb8fa72f7..59c62f1ae94 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -105,8 +105,8 @@ declare_clippy_lint! { declare_lint_pass!(Derive => [EXPL_IMPL_CLONE_ON_COPY, DERIVE_HASH_XOR_EQ, UNSAFE_DERIVE_DESERIALIZE]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Derive { - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for Derive { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if let ItemKind::Impl { of_trait: Some(ref trait_ref), .. @@ -127,8 +127,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Derive { } /// Implementation of the `DERIVE_HASH_XOR_EQ` lint. -fn check_hash_peq<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn check_hash_peq<'tcx>( + cx: &LateContext<'tcx>, span: Span, trait_ref: &TraitRef<'_>, ty: Ty<'tcx>, @@ -181,7 +181,7 @@ fn check_hash_peq<'a, 'tcx>( } /// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint. -fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item<'_>, trait_ref: &TraitRef<'_>, ty: Ty<'tcx>) { +fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &TraitRef<'_>, ty: Ty<'tcx>) { if match_path(&trait_ref.path, &paths::CLONE_TRAIT) { if !is_copy(cx, ty) { return; @@ -222,18 +222,18 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item<'_>, trait } /// Implementation of the `UNSAFE_DERIVE_DESERIALIZE` lint. -fn check_unsafe_derive_deserialize<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn check_unsafe_derive_deserialize<'tcx>( + cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &TraitRef<'_>, ty: Ty<'tcx>, ) { - fn item_from_def_id<'tcx>(cx: &LateContext<'_, 'tcx>, def_id: DefId) -> &'tcx Item<'tcx> { + fn item_from_def_id<'tcx>(cx: &LateContext<'tcx>, def_id: DefId) -> &'tcx Item<'tcx> { let hir_id = cx.tcx.hir().as_local_hir_id(def_id.expect_local()); cx.tcx.hir().expect_item(hir_id) } - fn has_unsafe<'tcx>(cx: &LateContext<'_, 'tcx>, item: &'tcx Item<'_>) -> bool { + fn has_unsafe<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>) -> bool { let mut visitor = UnsafeVisitor { cx, has_unsafe: false }; walk_item(&mut visitor, item); visitor.has_unsafe @@ -261,7 +261,7 @@ fn check_unsafe_derive_deserialize<'a, 'tcx>( } struct UnsafeVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, has_unsafe: bool, } diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs index 8d1e91f9adb..d52bb8961fa 100644 --- a/src/tools/clippy/clippy_lints/src/doc.rs +++ b/src/tools/clippy/clippy_lints/src/doc.rs @@ -146,12 +146,12 @@ impl DocMarkdown { impl_lint_pass!(DocMarkdown => [DOC_MARKDOWN, MISSING_SAFETY_DOC, MISSING_ERRORS_DOC, NEEDLESS_DOCTEST_MAIN]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DocMarkdown { - fn check_crate(&mut self, cx: &LateContext<'a, 'tcx>, krate: &'tcx hir::Crate<'_>) { +impl<'tcx> LateLintPass<'tcx> for DocMarkdown { + fn check_crate(&mut self, cx: &LateContext<'tcx>, krate: &'tcx hir::Crate<'_>) { check_attrs(cx, &self.valid_idents, &krate.item.attrs); } - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item<'_>) { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { let headers = check_attrs(cx, &self.valid_idents, &item.attrs); match item.kind { hir::ItemKind::Fn(ref sig, _, body_id) => { @@ -171,13 +171,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DocMarkdown { } } - fn check_item_post(&mut self, _cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item<'_>) { + fn check_item_post(&mut self, _cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { if let hir::ItemKind::Impl { .. } = item.kind { self.in_trait_impl = false; } } - fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::TraitItem<'_>) { + fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) { let headers = check_attrs(cx, &self.valid_idents, &item.attrs); if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind { if !in_external_macro(cx.tcx.sess, item.span) { @@ -186,7 +186,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DocMarkdown { } } - fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::ImplItem<'_>) { + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) { let headers = check_attrs(cx, &self.valid_idents, &item.attrs); if self.in_trait_impl || in_external_macro(cx.tcx.sess, item.span) { return; @@ -197,8 +197,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DocMarkdown { } } -fn lint_for_missing_headers<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn lint_for_missing_headers<'tcx>( + cx: &LateContext<'tcx>, hir_id: hir::HirId, span: impl Into<MultiSpan> + Copy, sig: &hir::FnSig<'_>, @@ -313,7 +313,7 @@ struct DocHeaders { errors: bool, } -fn check_attrs<'a>(cx: &LateContext<'_, '_>, valid_idents: &FxHashSet<String>, attrs: &'a [Attribute]) -> DocHeaders { +fn check_attrs<'a>(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &'a [Attribute]) -> DocHeaders { let mut doc = String::new(); let mut spans = vec![]; @@ -370,7 +370,7 @@ fn check_attrs<'a>(cx: &LateContext<'_, '_>, valid_idents: &FxHashSet<String>, a const RUST_CODE: &[&str] = &["rust", "no_run", "should_panic", "compile_fail", "edition2018"]; fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize>)>>( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, events: Events, spans: &[(usize, Span)], @@ -442,13 +442,13 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize static LEAVE_MAIN_PATTERNS: &[&str] = &["static", "fn main() {}", "extern crate", "async fn main() {"]; -fn check_code(cx: &LateContext<'_, '_>, text: &str, span: Span) { +fn check_code(cx: &LateContext<'_>, text: &str, span: Span) { if text.contains("fn main() {") && !LEAVE_MAIN_PATTERNS.iter().any(|p| text.contains(p)) { span_lint(cx, NEEDLESS_DOCTEST_MAIN, span, "needless `fn main` in doctest"); } } -fn check_text(cx: &LateContext<'_, '_>, valid_idents: &FxHashSet<String>, text: &str, span: Span) { +fn check_text(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, text: &str, span: Span) { for word in text.split(|c: char| c.is_whitespace() || c == '\'') { // Trim punctuation as in `some comment (see foo::bar).` // ^^ @@ -471,7 +471,7 @@ fn check_text(cx: &LateContext<'_, '_>, valid_idents: &FxHashSet<String>, text: } } -fn check_word(cx: &LateContext<'_, '_>, word: &str, span: Span) { +fn check_word(cx: &LateContext<'_>, word: &str, span: Span) { /// Checks if a string is camel-case, i.e., contains at least two uppercase /// letters (`Clippy` is ok) and one lower-case letter (`NASA` is ok). /// Plurals are also excluded (`IDs` is ok). diff --git a/src/tools/clippy/clippy_lints/src/double_comparison.rs b/src/tools/clippy/clippy_lints/src/double_comparison.rs index 44f85d1ea6e..5d16192b754 100644 --- a/src/tools/clippy/clippy_lints/src/double_comparison.rs +++ b/src/tools/clippy/clippy_lints/src/double_comparison.rs @@ -37,9 +37,9 @@ declare_clippy_lint! { declare_lint_pass!(DoubleComparisons => [DOUBLE_COMPARISONS]); -impl<'a, 'tcx> DoubleComparisons { +impl<'tcx> DoubleComparisons { #[allow(clippy::similar_names)] - fn check_binop(cx: &LateContext<'a, 'tcx>, op: BinOpKind, lhs: &'tcx Expr<'_>, rhs: &'tcx Expr<'_>, span: Span) { + fn check_binop(cx: &LateContext<'tcx>, op: BinOpKind, lhs: &'tcx Expr<'_>, rhs: &'tcx Expr<'_>, span: Span) { let (lkind, llhs, lrhs, rkind, rlhs, rrhs) = match (&lhs.kind, &rhs.kind) { (ExprKind::Binary(lb, llhs, lrhs), ExprKind::Binary(rb, rlhs, rrhs)) => { (lb.node, llhs, lrhs, rb.node, rlhs, rrhs) @@ -86,8 +86,8 @@ impl<'a, 'tcx> DoubleComparisons { } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DoubleComparisons { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for DoubleComparisons { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let ExprKind::Binary(ref kind, ref lhs, ref rhs) = expr.kind { Self::check_binop(cx, kind.node, lhs, rhs, expr.span); } diff --git a/src/tools/clippy/clippy_lints/src/drop_bounds.rs b/src/tools/clippy/clippy_lints/src/drop_bounds.rs index 5a7f759486e..4afbd1ed0e5 100644 --- a/src/tools/clippy/clippy_lints/src/drop_bounds.rs +++ b/src/tools/clippy/clippy_lints/src/drop_bounds.rs @@ -1,7 +1,7 @@ use crate::utils::{match_def_path, paths, span_lint}; use if_chain::if_chain; use rustc_hir::{GenericBound, GenericParam, WhereBoundPredicate, WherePredicate}; -use rustc_lint::LateLintPass; +use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { @@ -41,13 +41,13 @@ const DROP_BOUNDS_SUMMARY: &str = "Bounds of the form `T: Drop` are useless. \ declare_lint_pass!(DropBounds => [DROP_BOUNDS]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DropBounds { - fn check_generic_param(&mut self, cx: &rustc_lint::LateContext<'a, 'tcx>, p: &'tcx GenericParam<'_>) { +impl<'tcx> LateLintPass<'tcx> for DropBounds { + fn check_generic_param(&mut self, cx: &LateContext<'tcx>, p: &'tcx GenericParam<'_>) { for bound in p.bounds.iter() { lint_bound(cx, bound); } } - fn check_where_predicate(&mut self, cx: &rustc_lint::LateContext<'a, 'tcx>, p: &'tcx WherePredicate<'_>) { + fn check_where_predicate(&mut self, cx: &LateContext<'tcx>, p: &'tcx WherePredicate<'_>) { if let WherePredicate::BoundPredicate(WhereBoundPredicate { bounds, .. }) = p { for bound in *bounds { lint_bound(cx, bound); @@ -56,7 +56,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DropBounds { } } -fn lint_bound<'a, 'tcx>(cx: &rustc_lint::LateContext<'a, 'tcx>, bound: &'tcx GenericBound<'_>) { +fn lint_bound<'tcx>(cx: &LateContext<'tcx>, bound: &'tcx GenericBound<'_>) { if_chain! { if let GenericBound::Trait(t, _) = bound; if let Some(def_id) = t.trait_ref.path.res.opt_def_id(); diff --git a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs index 014873eb132..dcf772572e8 100644 --- a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs +++ b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs @@ -108,8 +108,8 @@ const FORGET_COPY_SUMMARY: &str = "calls to `std::mem::forget` with a value that declare_lint_pass!(DropForgetRef => [DROP_REF, FORGET_REF, DROP_COPY, FORGET_COPY]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DropForgetRef { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for DropForgetRef { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { if let ExprKind::Call(ref path, ref args) = expr.kind; if let ExprKind::Path(ref qpath) = path.kind; diff --git a/src/tools/clippy/clippy_lints/src/duration_subsec.rs b/src/tools/clippy/clippy_lints/src/duration_subsec.rs index 5eb320ceca2..2ded375091c 100644 --- a/src/tools/clippy/clippy_lints/src/duration_subsec.rs +++ b/src/tools/clippy/clippy_lints/src/duration_subsec.rs @@ -38,8 +38,8 @@ declare_clippy_lint! { declare_lint_pass!(DurationSubsec => [DURATION_SUBSEC]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DurationSubsec { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for DurationSubsec { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { if let ExprKind::Binary(Spanned { node: BinOpKind::Div, .. }, ref left, ref right) = expr.kind; if let ExprKind::MethodCall(ref method_path, _ , ref args, _) = left.kind; diff --git a/src/tools/clippy/clippy_lints/src/empty_enum.rs b/src/tools/clippy/clippy_lints/src/empty_enum.rs index 3bfef6f4bed..a249117d182 100644 --- a/src/tools/clippy/clippy_lints/src/empty_enum.rs +++ b/src/tools/clippy/clippy_lints/src/empty_enum.rs @@ -38,8 +38,8 @@ declare_clippy_lint! { declare_lint_pass!(EmptyEnum => [EMPTY_ENUM]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EmptyEnum { - fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for EmptyEnum { + fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { let did = cx.tcx.hir().local_def_id(item.hir_id); if let ItemKind::Enum(..) = item.kind { let ty = cx.tcx.type_of(did); diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs index e37e23b8944..4d2e17933ed 100644 --- a/src/tools/clippy/clippy_lints/src/entry.rs +++ b/src/tools/clippy/clippy_lints/src/entry.rs @@ -52,8 +52,8 @@ declare_clippy_lint! { declare_lint_pass!(HashMapPass => [MAP_ENTRY]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HashMapPass { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for HashMapPass { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let Some((ref check, ref then_block, ref else_block)) = higher::if_block(&expr) { if let ExprKind::Unary(UnOp::UnNot, ref check) = check.kind { if let Some((ty, map, key)) = check_cond(cx, check) { @@ -98,10 +98,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HashMapPass { } } -fn check_cond<'a, 'tcx, 'b>( - cx: &'a LateContext<'a, 'tcx>, - check: &'b Expr<'b>, -) -> Option<(&'static str, &'b Expr<'b>, &'b Expr<'b>)> { +fn check_cond<'a>(cx: &LateContext<'_>, check: &'a Expr<'a>) -> Option<(&'static str, &'a Expr<'a>, &'a Expr<'a>)> { if_chain! { if let ExprKind::MethodCall(ref path, _, ref params, _) = check.kind; if params.len() >= 2; @@ -127,7 +124,7 @@ fn check_cond<'a, 'tcx, 'b>( } struct InsertVisitor<'a, 'tcx, 'b> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, span: Span, ty: &'static str, map: &'b Expr<'b>, diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs index 12b62f5cf97..91214f277be 100644 --- a/src/tools/clippy/clippy_lints/src/enum_clike.rs +++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs @@ -36,9 +36,9 @@ declare_clippy_lint! { declare_lint_pass!(UnportableVariant => [ENUM_CLIKE_UNPORTABLE_VARIANT]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { +impl<'tcx> LateLintPass<'tcx> for UnportableVariant { #[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_sign_loss)] - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'_>) { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if cx.tcx.data_layout.pointer_size.bits() != 64 { return; } diff --git a/src/tools/clippy/clippy_lints/src/eq_op.rs b/src/tools/clippy/clippy_lints/src/eq_op.rs index 98757624a13..ca921dcfdfe 100644 --- a/src/tools/clippy/clippy_lints/src/eq_op.rs +++ b/src/tools/clippy/clippy_lints/src/eq_op.rs @@ -52,9 +52,9 @@ declare_clippy_lint! { declare_lint_pass!(EqOp => [EQ_OP, OP_REF]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { +impl<'tcx> LateLintPass<'tcx> for EqOp { #[allow(clippy::similar_names, clippy::too_many_lines)] - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if let ExprKind::Binary(op, ref left, ref right) = e.kind { if e.span.from_expansion() { return; diff --git a/src/tools/clippy/clippy_lints/src/erasing_op.rs b/src/tools/clippy/clippy_lints/src/erasing_op.rs index 804a9c1904b..8a268380618 100644 --- a/src/tools/clippy/clippy_lints/src/erasing_op.rs +++ b/src/tools/clippy/clippy_lints/src/erasing_op.rs @@ -29,8 +29,8 @@ declare_clippy_lint! { declare_lint_pass!(ErasingOp => [ERASING_OP]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ErasingOp { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for ErasingOp { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if e.span.from_expansion() { return; } @@ -47,7 +47,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ErasingOp { } } -fn check(cx: &LateContext<'_, '_>, e: &Expr<'_>, span: Span) { +fn check(cx: &LateContext<'_>, e: &Expr<'_>, span: Span) { if let Some(Constant::Int(0)) = constant_simple(cx, cx.tables(), e) { span_lint( cx, diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs index bb74f193a48..d40cdfcca9f 100644 --- a/src/tools/clippy/clippy_lints/src/escape.rs +++ b/src/tools/clippy/clippy_lints/src/escape.rs @@ -49,17 +49,17 @@ fn is_non_trait_box(ty: Ty<'_>) -> bool { } struct EscapeDelegate<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, set: HirIdSet, too_large_for_stack: u64, } impl_lint_pass!(BoxedLocal => [BOXED_LOCAL]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoxedLocal { +impl<'tcx> LateLintPass<'tcx> for BoxedLocal { fn check_fn( &mut self, - cx: &LateContext<'a, 'tcx>, + cx: &LateContext<'tcx>, _: intravisit::FnKind<'tcx>, _: &'tcx FnDecl<'_>, body: &'tcx Body<'_>, diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index 0ac8b95de8d..ceed6a74c4f 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -64,8 +64,8 @@ declare_clippy_lint! { declare_lint_pass!(EtaReduction => [REDUNDANT_CLOSURE, REDUNDANT_CLOSURE_FOR_METHOD_CALLS]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EtaReduction { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for EtaReduction { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if in_external_macro(cx.sess(), expr.span) { return; } @@ -81,7 +81,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EtaReduction { } } -fn check_closure(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { +fn check_closure(cx: &LateContext<'_>, expr: &Expr<'_>) { if let ExprKind::Closure(_, ref decl, eid, _, _) = expr.kind { let body = cx.tcx.hir().body(eid); let ex = &body.value; @@ -151,7 +151,7 @@ fn check_closure(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { } /// Tries to determine the type for universal function call to be used instead of the closure -fn get_ufcs_type_name(cx: &LateContext<'_, '_>, method_def_id: def_id::DefId, self_arg: &Expr<'_>) -> Option<String> { +fn get_ufcs_type_name(cx: &LateContext<'_>, method_def_id: def_id::DefId, self_arg: &Expr<'_>) -> Option<String> { let expected_type_of_self = &cx.tcx.fn_sig(method_def_id).inputs_and_output().skip_binder()[0]; let actual_type_of_self = &cx.tables().node_type(self_arg.hir_id); @@ -196,7 +196,7 @@ fn match_types(lhs: Ty<'_>, rhs: Ty<'_>) -> bool { } } -fn get_type_name(cx: &LateContext<'_, '_>, ty: Ty<'_>) -> String { +fn get_type_name(cx: &LateContext<'_>, ty: Ty<'_>) -> String { match ty.kind { ty::Adt(t, _) => cx.tcx.def_path_str(t.did), ty::Ref(_, r, _) => get_type_name(cx, &r), diff --git a/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs b/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs index 04af6c2c1f8..01b0d3c5ede 100644 --- a/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs +++ b/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs @@ -67,15 +67,15 @@ declare_clippy_lint! { declare_lint_pass!(EvalOrderDependence => [EVAL_ORDER_DEPENDENCE, DIVERGING_SUB_EXPRESSION]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for EvalOrderDependence { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { // Find a write to a local variable. match expr.kind { ExprKind::Assign(ref lhs, ..) | ExprKind::AssignOp(_, ref lhs, _) => { if let ExprKind::Path(ref qpath) = lhs.kind { if let QPath::Resolved(_, ref path) = *qpath { if path.segments.len() == 1 { - if let def::Res::Local(var) = cx.tables().qpath_res(qpath, lhs.hir_id) { + if let def::Res::Local(var) = cx.qpath_res(qpath, lhs.hir_id) { let mut visitor = ReadVisitor { cx, var, @@ -91,7 +91,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence { _ => {}, } } - fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt<'_>) { + fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { match stmt.kind { StmtKind::Local(ref local) => { if let Local { init: Some(ref e), .. } = **local { @@ -105,7 +105,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence { } struct DivergenceVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, } impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> { @@ -285,7 +285,7 @@ fn check_stmt<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, stmt: &'tcx Stmt<'_>) - /// A visitor that looks for reads from a variable. struct ReadVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, /// The ID of the variable we're looking for. var: HirId, /// The expressions where the write to the variable occurred (for reporting @@ -309,7 +309,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> { if_chain! { if let QPath::Resolved(None, ref path) = *qpath; if path.segments.len() == 1; - if let def::Res::Local(local_id) = self.cx.tables().qpath_res(qpath, expr.hir_id); + if let def::Res::Local(local_id) = self.cx.qpath_res(qpath, expr.hir_id); if local_id == self.var; // Check that this is a read, not a write. if !is_in_assignment_position(self.cx, expr); @@ -354,7 +354,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> { } /// Returns `true` if `expr` is the LHS of an assignment, like `expr = ...`. -fn is_in_assignment_position(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { +fn is_in_assignment_position(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { if let Some(parent) = get_parent_expr(cx, expr) { if let ExprKind::Assign(ref lhs, ..) = parent.kind { return lhs.hir_id == expr.hir_id; diff --git a/src/tools/clippy/clippy_lints/src/exit.rs b/src/tools/clippy/clippy_lints/src/exit.rs index 621d56185a9..7337d98c8be 100644 --- a/src/tools/clippy/clippy_lints/src/exit.rs +++ b/src/tools/clippy/clippy_lints/src/exit.rs @@ -24,8 +24,8 @@ declare_clippy_lint! { declare_lint_pass!(Exit => [EXIT]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Exit { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for Exit { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if_chain! { if let ExprKind::Call(ref path_expr, ref _args) = e.kind; if let ExprKind::Path(ref path) = path_expr.kind; diff --git a/src/tools/clippy/clippy_lints/src/explicit_write.rs b/src/tools/clippy/clippy_lints/src/explicit_write.rs index 7269e2b52c2..0240e80d814 100644 --- a/src/tools/clippy/clippy_lints/src/explicit_write.rs +++ b/src/tools/clippy/clippy_lints/src/explicit_write.rs @@ -28,8 +28,8 @@ declare_clippy_lint! { declare_lint_pass!(ExplicitWrite => [EXPLICIT_WRITE]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExplicitWrite { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for ExplicitWrite { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { // match call to unwrap if let ExprKind::MethodCall(ref unwrap_fun, _, ref unwrap_args, _) = expr.kind; diff --git a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs index 92812816461..01ed0c426d4 100644 --- a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs +++ b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs @@ -52,8 +52,8 @@ declare_clippy_lint! { declare_lint_pass!(FallibleImplFrom => [FALLIBLE_IMPL_FROM]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FallibleImplFrom { - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for FallibleImplFrom { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { // check for `impl From<???> for ..` let impl_def_id = cx.tcx.hir().local_def_id(item.hir_id); if_chain! { @@ -67,12 +67,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FallibleImplFrom { } } -fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_items: &[hir::ImplItemRef<'_>]) { +fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_items: &[hir::ImplItemRef<'_>]) { use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{Expr, ExprKind, ImplItemKind, QPath}; struct FindPanicUnwrap<'a, 'tcx> { - lcx: &'a LateContext<'a, 'tcx>, + lcx: &'a LateContext<'tcx>, tables: &'tcx ty::TypeckTables<'tcx>, result: Vec<Span>, } diff --git a/src/tools/clippy/clippy_lints/src/float_literal.rs b/src/tools/clippy/clippy_lints/src/float_literal.rs index cd3d443ec58..a3d2a949535 100644 --- a/src/tools/clippy/clippy_lints/src/float_literal.rs +++ b/src/tools/clippy/clippy_lints/src/float_literal.rs @@ -58,8 +58,8 @@ declare_clippy_lint! { declare_lint_pass!(FloatLiteral => [EXCESSIVE_PRECISION, LOSSY_FLOAT_LITERAL]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatLiteral { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for FloatLiteral { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { if_chain! { let ty = cx.tables().expr_ty(expr); if let ty::Float(fty) = ty.kind; diff --git a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs index 76713cb1afc..4efd0689267 100644 --- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs @@ -111,7 +111,7 @@ declare_lint_pass!(FloatingPointArithmetic => [ // Returns the specialized log method for a given base if base is constant // and is one of 2, 10 and e -fn get_specialized_log_method(cx: &LateContext<'_, '_>, base: &Expr<'_>) -> Option<&'static str> { +fn get_specialized_log_method(cx: &LateContext<'_>, base: &Expr<'_>) -> Option<&'static str> { if let Some((value, _)) = constant(cx, cx.tables(), base) { if F32(2.0) == value || F64(2.0) == value { return Some("log2"); @@ -126,7 +126,7 @@ fn get_specialized_log_method(cx: &LateContext<'_, '_>, base: &Expr<'_>) -> Opti } // Adds type suffixes and parenthesis to method receivers if necessary -fn prepare_receiver_sugg<'a>(cx: &LateContext<'_, '_>, mut expr: &'a Expr<'a>) -> Sugg<'a> { +fn prepare_receiver_sugg<'a>(cx: &LateContext<'_>, mut expr: &'a Expr<'a>) -> Sugg<'a> { let mut suggestion = Sugg::hir(cx, expr, ".."); if let ExprKind::Unary(UnOp::UnNeg, inner_expr) = &expr.kind { @@ -163,7 +163,7 @@ fn prepare_receiver_sugg<'a>(cx: &LateContext<'_, '_>, mut expr: &'a Expr<'a>) - suggestion.maybe_par() } -fn check_log_base(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { +fn check_log_base(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) { if let Some(method) = get_specialized_log_method(cx, &args[1]) { span_lint_and_sugg( cx, @@ -179,7 +179,7 @@ fn check_log_base(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) // TODO: Lint expressions of the form `(x + y).ln()` where y > 1 and // suggest usage of `(x + (y - 1)).ln_1p()` instead -fn check_ln1p(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { +fn check_ln1p(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) { if let ExprKind::Binary( Spanned { node: BinOpKind::Add, .. @@ -231,7 +231,7 @@ fn get_integer_from_float_constant(value: &Constant) -> Option<i32> { } } -fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { +fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) { // Check receiver if let Some((value, _)) = constant(cx, cx.tables(), &args[0]) { let method = if F32(f32_consts::E) == value || F64(f64_consts::E) == value { @@ -295,7 +295,7 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { // TODO: Lint expressions of the form `x.exp() - y` where y > 1 // and suggest usage of `x.exp_m1() - (y - 1)` instead -fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { +fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { if let ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, ref lhs, ref rhs) = expr.kind; if cx.tables().expr_ty(lhs).is_floating_point(); @@ -321,7 +321,7 @@ fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { } } -fn is_float_mul_expr<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr<'a>) -> Option<(&'a Expr<'a>, &'a Expr<'a>)> { +fn is_float_mul_expr<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(&'a Expr<'a>, &'a Expr<'a>)> { if_chain! { if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, ref lhs, ref rhs) = &expr.kind; if cx.tables().expr_ty(lhs).is_floating_point(); @@ -335,7 +335,7 @@ fn is_float_mul_expr<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr<'a>) -> Option } // TODO: Fix rust-lang/rust-clippy#4735 -fn check_mul_add(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { +fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) { if let ExprKind::Binary( Spanned { node: BinOpKind::Add, .. @@ -373,7 +373,7 @@ fn check_mul_add(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { /// test is positive or an expression which tests whether or not test /// is nonnegative. /// Used for check-custom-abs function below -fn is_testing_positive(cx: &LateContext<'_, '_>, expr: &Expr<'_>, test: &Expr<'_>) -> bool { +fn is_testing_positive(cx: &LateContext<'_>, expr: &Expr<'_>, test: &Expr<'_>) -> bool { if let ExprKind::Binary(Spanned { node: op, .. }, left, right) = expr.kind { match op { BinOpKind::Gt | BinOpKind::Ge => is_zero(cx, right) && are_exprs_equal(cx, left, test), @@ -386,7 +386,7 @@ fn is_testing_positive(cx: &LateContext<'_, '_>, expr: &Expr<'_>, test: &Expr<'_ } /// See [`is_testing_positive`] -fn is_testing_negative(cx: &LateContext<'_, '_>, expr: &Expr<'_>, test: &Expr<'_>) -> bool { +fn is_testing_negative(cx: &LateContext<'_>, expr: &Expr<'_>, test: &Expr<'_>) -> bool { if let ExprKind::Binary(Spanned { node: op, .. }, left, right) = expr.kind { match op { BinOpKind::Gt | BinOpKind::Ge => is_zero(cx, left) && are_exprs_equal(cx, right, test), @@ -398,12 +398,12 @@ fn is_testing_negative(cx: &LateContext<'_, '_>, expr: &Expr<'_>, test: &Expr<'_ } } -fn are_exprs_equal(cx: &LateContext<'_, '_>, expr1: &Expr<'_>, expr2: &Expr<'_>) -> bool { +fn are_exprs_equal(cx: &LateContext<'_>, expr1: &Expr<'_>, expr2: &Expr<'_>) -> bool { SpanlessEq::new(cx).ignore_fn().eq_expr(expr1, expr2) } /// Returns true iff expr is some zero literal -fn is_zero(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { +fn is_zero(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { match constant_simple(cx, cx.tables(), expr) { Some(Constant::Int(i)) => i == 0, Some(Constant::F32(f)) => f == 0.0, @@ -418,7 +418,7 @@ fn is_zero(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { /// one of the two expressions /// If the two expressions are not negations of each other, then it /// returns None. -fn are_negated<'a>(cx: &LateContext<'_, '_>, expr1: &'a Expr<'a>, expr2: &'a Expr<'a>) -> Option<(bool, &'a Expr<'a>)> { +fn are_negated<'a>(cx: &LateContext<'_>, expr1: &'a Expr<'a>, expr2: &'a Expr<'a>) -> Option<(bool, &'a Expr<'a>)> { if let ExprKind::Unary(UnOp::UnNeg, expr1_negated) = &expr1.kind { if are_exprs_equal(cx, expr1_negated, expr2) { return Some((false, expr2)); @@ -432,7 +432,7 @@ fn are_negated<'a>(cx: &LateContext<'_, '_>, expr1: &'a Expr<'a>, expr2: &'a Exp None } -fn check_custom_abs(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { +fn check_custom_abs(cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { if let Some((cond, body, Some(else_body))) = higher::if_block(&expr); if let ExprKind::Block(block, _) = body.kind; @@ -479,8 +479,8 @@ fn check_custom_abs(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let ExprKind::MethodCall(ref path, _, args, _) = &expr.kind { let recv_ty = cx.tables().expr_ty(&args[0]); diff --git a/src/tools/clippy/clippy_lints/src/format.rs b/src/tools/clippy/clippy_lints/src/format.rs index 58cf0027ea4..33b6bfc459f 100644 --- a/src/tools/clippy/clippy_lints/src/format.rs +++ b/src/tools/clippy/clippy_lints/src/format.rs @@ -40,8 +40,8 @@ declare_clippy_lint! { declare_lint_pass!(UselessFormat => [USELESS_FORMAT]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessFormat { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for UselessFormat { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { let span = match is_expn_of(expr.span, "format") { Some(s) if !s.from_expansion() => s, _ => return, @@ -75,11 +75,7 @@ fn span_useless_format<T: LintContext>(cx: &T, span: Span, help: &str, mut sugg: }); } -fn on_argumentv1_new<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &'tcx Expr<'_>, - arms: &'tcx [Arm<'_>], -) -> Option<String> { +fn on_argumentv1_new<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>]) -> Option<String> { if_chain! { if let ExprKind::AddrOf(BorrowKind::Ref, _, ref format_args) = expr.kind; if let ExprKind::Array(ref elems) = arms[0].body.kind; @@ -88,7 +84,7 @@ fn on_argumentv1_new<'a, 'tcx>( // matches `core::fmt::Display::fmt` if args.len() == 2; if let ExprKind::Path(ref qpath) = args[1].kind; - if let Some(did) = cx.tables().qpath_res(qpath, args[1].hir_id).opt_def_id(); + if let Some(did) = cx.qpath_res(qpath, args[1].hir_id).opt_def_id(); if match_def_path(cx, did, &paths::DISPLAY_FMT_METHOD); // check `(arg0,)` in match block if let PatKind::Tuple(ref pats, None) = arms[0].pat.kind; @@ -118,7 +114,7 @@ fn on_argumentv1_new<'a, 'tcx>( None } -fn on_new_v1<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) -> Option<String> { +fn on_new_v1<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<String> { if_chain! { if let Some(args) = match_function_call(cx, expr, &paths::FMT_ARGUMENTS_NEW_V1); if args.len() == 2; @@ -145,7 +141,7 @@ fn on_new_v1<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) -> Opti None } -fn on_new_v1_fmt<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) -> Option<String> { +fn on_new_v1_fmt<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<String> { if_chain! { if let Some(args) = match_function_call(cx, expr, &paths::FMT_ARGUMENTS_NEW_V1_FORMATTED); if args.len() == 3; diff --git a/src/tools/clippy/clippy_lints/src/functions.rs b/src/tools/clippy/clippy_lints/src/functions.rs index 1f9bd7a691b..3f030dd8422 100644 --- a/src/tools/clippy/clippy_lints/src/functions.rs +++ b/src/tools/clippy/clippy_lints/src/functions.rs @@ -190,10 +190,10 @@ impl_lint_pass!(Functions => [ MUST_USE_CANDIDATE, ]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { +impl<'tcx> LateLintPass<'tcx> for Functions { fn check_fn( &mut self, - cx: &LateContext<'a, 'tcx>, + cx: &LateContext<'tcx>, kind: intravisit::FnKind<'tcx>, decl: &'tcx hir::FnDecl<'_>, body: &'tcx hir::Body<'_>, @@ -230,7 +230,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { self.check_line_number(cx, span, body); } - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item<'_>) { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { let attr = must_use_attr(&item.attrs); if let hir::ItemKind::Fn(ref sig, ref _generics, ref body_id) = item.kind { if let Some(attr) = attr { @@ -255,7 +255,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { } } - fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::ImplItem<'_>) { + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) { if let hir::ImplItemKind::Fn(ref sig, ref body_id) = item.kind { let attr = must_use_attr(&item.attrs); if let Some(attr) = attr { @@ -278,7 +278,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { } } - fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::TraitItem<'_>) { + fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) { if let hir::TraitItemKind::Fn(ref sig, ref eid) = item.kind { // don't lint extern functions decls, it's not their fault if sig.header.abi == Abi::Rust { @@ -310,8 +310,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { } } -impl<'a, 'tcx> Functions { - fn check_arg_number(self, cx: &LateContext<'_, '_>, decl: &hir::FnDecl<'_>, fn_span: Span) { +impl<'tcx> Functions { + fn check_arg_number(self, cx: &LateContext<'_>, decl: &hir::FnDecl<'_>, fn_span: Span) { let args = decl.inputs.len() as u64; if args > self.threshold { span_lint( @@ -323,7 +323,7 @@ impl<'a, 'tcx> Functions { } } - fn check_line_number(self, cx: &LateContext<'_, '_>, span: Span, body: &'tcx hir::Body<'_>) { + fn check_line_number(self, cx: &LateContext<'_>, span: Span, body: &'tcx hir::Body<'_>) { if in_external_macro(cx.sess(), span) { return; } @@ -378,7 +378,7 @@ impl<'a, 'tcx> Functions { } fn check_raw_ptr( - cx: &LateContext<'a, 'tcx>, + cx: &LateContext<'tcx>, unsafety: hir::Unsafety, decl: &'tcx hir::FnDecl<'_>, body: &'tcx hir::Body<'_>, @@ -406,7 +406,7 @@ impl<'a, 'tcx> Functions { } fn check_needless_must_use( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, decl: &hir::FnDecl<'_>, item_id: hir::HirId, item_span: Span, @@ -443,8 +443,8 @@ fn check_needless_must_use( } } -fn check_must_use_candidate<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn check_must_use_candidate<'tcx>( + cx: &LateContext<'tcx>, decl: &'tcx hir::FnDecl<'_>, body: &'tcx hir::Body<'_>, item_span: Span, @@ -484,12 +484,12 @@ fn returns_unit(decl: &hir::FnDecl<'_>) -> bool { } } -fn has_mutable_arg(cx: &LateContext<'_, '_>, body: &hir::Body<'_>) -> bool { +fn has_mutable_arg(cx: &LateContext<'_>, body: &hir::Body<'_>) -> bool { let mut tys = FxHashSet::default(); body.params.iter().any(|param| is_mutable_pat(cx, ¶m.pat, &mut tys)) } -fn is_mutable_pat(cx: &LateContext<'_, '_>, pat: &hir::Pat<'_>, tys: &mut FxHashSet<DefId>) -> bool { +fn is_mutable_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, tys: &mut FxHashSet<DefId>) -> bool { if let hir::PatKind::Wild = pat.kind { return false; // ignore `_` patterns } @@ -508,7 +508,7 @@ fn is_mutable_pat(cx: &LateContext<'_, '_>, pat: &hir::Pat<'_>, tys: &mut FxHash static KNOWN_WRAPPER_TYS: &[&[&str]] = &[&["alloc", "rc", "Rc"], &["std", "sync", "Arc"]]; -fn is_mutable_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>, span: Span, tys: &mut FxHashSet<DefId>) -> bool { +fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, tys: &mut FxHashSet<DefId>) -> bool { match ty.kind { // primitive types are never mutable ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false, @@ -537,7 +537,7 @@ fn raw_ptr_arg(arg: &hir::Param<'_>, ty: &hir::Ty<'_>) -> Option<hir::HirId> { } struct DerefVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, ptrs: FxHashSet<hir::HirId>, tables: &'a ty::TypeckTables<'tcx>, } @@ -596,7 +596,7 @@ impl<'a, 'tcx> DerefVisitor<'a, 'tcx> { } struct StaticMutVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, mutates_static: bool, } @@ -641,7 +641,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> { } } -fn is_mutated_static(cx: &LateContext<'_, '_>, e: &hir::Expr<'_>) -> bool { +fn is_mutated_static(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> bool { use hir::ExprKind::{Field, Index, Path}; match e.kind { @@ -657,7 +657,7 @@ fn is_mutated_static(cx: &LateContext<'_, '_>, e: &hir::Expr<'_>) -> bool { } } -fn mutates_static<'a, 'tcx>(cx: &'a LateContext<'a, 'tcx>, body: &'tcx hir::Body<'_>) -> bool { +fn mutates_static<'tcx>(cx: &LateContext<'tcx>, body: &'tcx hir::Body<'_>) -> bool { let mut v = StaticMutVisitor { cx, mutates_static: false, diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs index 17dd3cd5493..92c7e66a0eb 100644 --- a/src/tools/clippy/clippy_lints/src/future_not_send.rs +++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs @@ -47,10 +47,10 @@ declare_clippy_lint! { declare_lint_pass!(FutureNotSend => [FUTURE_NOT_SEND]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FutureNotSend { +impl<'tcx> LateLintPass<'tcx> for FutureNotSend { fn check_fn( &mut self, - cx: &LateContext<'a, 'tcx>, + cx: &LateContext<'tcx>, kind: FnKind<'tcx>, decl: &'tcx FnDecl<'tcx>, _: &'tcx Body<'tcx>, diff --git a/src/tools/clippy/clippy_lints/src/get_last_with_len.rs b/src/tools/clippy/clippy_lints/src/get_last_with_len.rs index 57a7fbb5656..2d93ecc00a7 100644 --- a/src/tools/clippy/clippy_lints/src/get_last_with_len.rs +++ b/src/tools/clippy/clippy_lints/src/get_last_with_len.rs @@ -43,8 +43,8 @@ declare_clippy_lint! { declare_lint_pass!(GetLastWithLen => [GET_LAST_WITH_LEN]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for GetLastWithLen { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for GetLastWithLen { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { // Is a method call if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind; diff --git a/src/tools/clippy/clippy_lints/src/identity_op.rs b/src/tools/clippy/clippy_lints/src/identity_op.rs index 1c25e050997..dc9d636bc6d 100644 --- a/src/tools/clippy/clippy_lints/src/identity_op.rs +++ b/src/tools/clippy/clippy_lints/src/identity_op.rs @@ -28,8 +28,8 @@ declare_clippy_lint! { declare_lint_pass!(IdentityOp => [IDENTITY_OP]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for IdentityOp { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if e.span.from_expansion() { return; } @@ -58,7 +58,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp { } } -fn is_allowed(cx: &LateContext<'_, '_>, cmp: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> bool { +fn is_allowed(cx: &LateContext<'_>, cmp: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> bool { // `1 << 0` is a common pattern in bit manipulation code if_chain! { if let BinOpKind::Shl = cmp.node; @@ -73,7 +73,7 @@ fn is_allowed(cx: &LateContext<'_, '_>, cmp: BinOp, left: &Expr<'_>, right: &Exp } #[allow(clippy::cast_possible_wrap)] -fn check(cx: &LateContext<'_, '_>, e: &Expr<'_>, m: i8, span: Span, arg: Span) { +fn check(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span) { if let Some(Constant::Int(v)) = constant_simple(cx, cx.tables(), e) { let check = match cx.tables().expr_ty(e).kind { ty::Int(ity) => unsext(cx.tcx, -1_i128, ity), diff --git a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs index e357c7b3b2e..f911cb68ea5 100644 --- a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs +++ b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs @@ -40,8 +40,8 @@ declare_clippy_lint! { declare_lint_pass!(IfLetMutex => [IF_LET_MUTEX]); -impl LateLintPass<'_, '_> for IfLetMutex { - fn check_expr(&mut self, cx: &LateContext<'_, '_>, ex: &'_ Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for IfLetMutex { + fn check_expr(&mut self, cx: &LateContext<'tcx>, ex: &'tcx Expr<'tcx>) { let mut arm_visit = ArmVisitor { mutex_lock_called: false, found_mutex: None, @@ -82,13 +82,13 @@ impl LateLintPass<'_, '_> for IfLetMutex { } /// Checks if `Mutex::lock` is called in the `if let _ = expr. -pub struct OppVisitor<'tcx, 'l> { +pub struct OppVisitor<'a, 'tcx> { mutex_lock_called: bool, found_mutex: Option<&'tcx Expr<'tcx>>, - cx: &'tcx LateContext<'tcx, 'l>, + cx: &'a LateContext<'tcx>, } -impl<'tcx, 'l> Visitor<'tcx> for OppVisitor<'tcx, 'l> { +impl<'tcx> Visitor<'tcx> for OppVisitor<'_, 'tcx> { type Map = Map<'tcx>; fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { @@ -109,13 +109,13 @@ impl<'tcx, 'l> Visitor<'tcx> for OppVisitor<'tcx, 'l> { } /// Checks if `Mutex::lock` is called in any of the branches. -pub struct ArmVisitor<'tcx, 'l> { +pub struct ArmVisitor<'a, 'tcx> { mutex_lock_called: bool, found_mutex: Option<&'tcx Expr<'tcx>>, - cx: &'tcx LateContext<'tcx, 'l>, + cx: &'a LateContext<'tcx>, } -impl<'tcx, 'l> Visitor<'tcx> for ArmVisitor<'tcx, 'l> { +impl<'tcx> Visitor<'tcx> for ArmVisitor<'_, 'tcx> { type Map = Map<'tcx>; fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { @@ -135,8 +135,8 @@ impl<'tcx, 'l> Visitor<'tcx> for ArmVisitor<'tcx, 'l> { } } -impl<'tcx, 'l> ArmVisitor<'tcx, 'l> { - fn same_mutex(&self, cx: &LateContext<'_, '_>, op_mutex: &Expr<'_>) -> bool { +impl<'tcx> ArmVisitor<'_, 'tcx> { + fn same_mutex(&self, cx: &LateContext<'_>, op_mutex: &Expr<'_>) -> bool { if let Some(arm_mutex) = self.found_mutex { SpanlessEq::new(cx).eq_expr(op_mutex, arm_mutex) } else { @@ -145,7 +145,7 @@ impl<'tcx, 'l> ArmVisitor<'tcx, 'l> { } } -fn is_mutex_lock_call<'a>(cx: &LateContext<'a, '_>, expr: &'a Expr<'_>) -> Option<&'a Expr<'a>> { +fn is_mutex_lock_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { if_chain! { if let ExprKind::MethodCall(path, _span, args, _) = &expr.kind; if path.ident.to_string() == "lock"; diff --git a/src/tools/clippy/clippy_lints/src/if_let_some_result.rs b/src/tools/clippy/clippy_lints/src/if_let_some_result.rs index 3f1ae9b86d3..9e2989dc01e 100644 --- a/src/tools/clippy/clippy_lints/src/if_let_some_result.rs +++ b/src/tools/clippy/clippy_lints/src/if_let_some_result.rs @@ -37,8 +37,8 @@ declare_clippy_lint! { declare_lint_pass!(OkIfLet => [IF_LET_SOME_RESULT]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OkIfLet { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for OkIfLet { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { //begin checking variables if let ExprKind::Match(ref op, ref body, source) = expr.kind; //test if expr is a match if let MatchSource::IfLetDesugar { .. } = source; //test if it is an If Let diff --git a/src/tools/clippy/clippy_lints/src/implicit_return.rs b/src/tools/clippy/clippy_lints/src/implicit_return.rs index 5a0531ff749..22c4fef32a3 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_return.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_return.rs @@ -44,7 +44,7 @@ declare_lint_pass!(ImplicitReturn => [IMPLICIT_RETURN]); static LINT_BREAK: &str = "change `break` to `return` as shown"; static LINT_RETURN: &str = "add `return` as shown"; -fn lint(cx: &LateContext<'_, '_>, outer_span: Span, inner_span: Span, msg: &str) { +fn lint(cx: &LateContext<'_>, outer_span: Span, inner_span: Span, msg: &str) { let outer_span = outer_span.source_callsite(); let inner_span = inner_span.source_callsite(); @@ -60,7 +60,7 @@ fn lint(cx: &LateContext<'_, '_>, outer_span: Span, inner_span: Span, msg: &str) }); } -fn expr_match(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { +fn expr_match(cx: &LateContext<'_>, expr: &Expr<'_>) { match expr.kind { // loops could be using `break` instead of `return` ExprKind::Block(block, ..) | ExprKind::Loop(block, ..) => { @@ -108,7 +108,7 @@ fn expr_match(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { ExprKind::Call(expr, ..) => { if_chain! { if let ExprKind::Path(qpath) = &expr.kind; - if let Some(path_def_id) = cx.tables().qpath_res(qpath, expr.hir_id).opt_def_id(); + if let Some(path_def_id) = cx.qpath_res(qpath, expr.hir_id).opt_def_id(); if match_def_path(cx, path_def_id, &BEGIN_PANIC) || match_def_path(cx, path_def_id, &BEGIN_PANIC_FMT); then { } @@ -122,10 +122,10 @@ fn expr_match(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitReturn { +impl<'tcx> LateLintPass<'tcx> for ImplicitReturn { fn check_fn( &mut self, - cx: &LateContext<'a, 'tcx>, + cx: &LateContext<'tcx>, _: FnKind<'tcx>, _: &'tcx FnDecl<'_>, body: &'tcx Body<'_>, diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs index 1a6cb0b0c56..f38530aca0c 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs @@ -36,8 +36,8 @@ declare_clippy_lint! { declare_lint_pass!(ImplicitSaturatingSub => [IMPLICIT_SATURATING_SUB]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitSaturatingSub { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'tcx>) { +impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { if in_macro(expr.span) { return; } @@ -118,7 +118,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitSaturatingSub { } } -fn subtracts_one<'a>(cx: &LateContext<'_, '_>, expr: &Expr<'a>) -> Option<&'a Expr<'a>> { +fn subtracts_one<'a>(cx: &LateContext<'_>, expr: &Expr<'a>) -> Option<&'a Expr<'a>> { match expr.kind { ExprKind::AssignOp(ref op1, ref target, ref value) => { if_chain! { @@ -153,7 +153,7 @@ fn subtracts_one<'a>(cx: &LateContext<'_, '_>, expr: &Expr<'a>) -> Option<&'a Ex } } -fn print_lint_and_sugg(cx: &LateContext<'_, '_>, var_name: &str, expr: &Expr<'_>) { +fn print_lint_and_sugg(cx: &LateContext<'_>, var_name: &str, expr: &Expr<'_>) { span_lint_and_sugg( cx, IMPLICIT_SATURATING_SUB, diff --git a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs index c5e4abc94a8..5857a405b0c 100644 --- a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs +++ b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs @@ -85,8 +85,8 @@ declare_clippy_lint! { declare_lint_pass!(IndexingSlicing => [INDEXING_SLICING, OUT_OF_BOUNDS_INDEXING]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for IndexingSlicing { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let ExprKind::Index(ref array, ref index) = &expr.kind { let ty = cx.tables().expr_ty(array); if let Some(range) = higher::range(cx, index) { @@ -164,8 +164,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { /// Returns a tuple of options with the start and end (exclusive) values of /// the range. If the start or end is not constant, None is returned. -fn to_const_range<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn to_const_range<'tcx>( + cx: &LateContext<'tcx>, range: higher::Range<'_>, array_size: u128, ) -> (Option<u128>, Option<u128>) { diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs index 38f086c9221..3ffc2dd60d9 100644 --- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs +++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs @@ -44,8 +44,8 @@ declare_clippy_lint! { declare_lint_pass!(InfiniteIter => [INFINITE_ITER, MAYBE_INFINITE_ITER]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InfiniteIter { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for InfiniteIter { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { let (lint, msg) = match complete_infinite_iter(cx, expr) { Infinite => (INFINITE_ITER, "infinite iteration detected"), MaybeInfinite => (MAYBE_INFINITE_ITER, "possible infinite iteration detected"), @@ -140,7 +140,7 @@ const HEURISTICS: [(&str, usize, Heuristic, Finiteness); 19] = [ ("scan", 3, First, MaybeInfinite), ]; -fn is_infinite(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Finiteness { +fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { match expr.kind { ExprKind::MethodCall(ref method, _, ref args, _) => { for &(name, len, heuristic, cap) in &HEURISTICS { @@ -216,7 +216,7 @@ const INFINITE_COLLECTORS: [&[&str]; 8] = [ &paths::VEC_DEQUE, ]; -fn complete_infinite_iter(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Finiteness { +fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { match expr.kind { ExprKind::MethodCall(ref method, _, ref args, _) => { for &(name, len) in &COMPLETING_METHODS { diff --git a/src/tools/clippy/clippy_lints/src/inherent_impl.rs b/src/tools/clippy/clippy_lints/src/inherent_impl.rs index 7e2975ac2ae..bd7ca038839 100644 --- a/src/tools/clippy/clippy_lints/src/inherent_impl.rs +++ b/src/tools/clippy/clippy_lints/src/inherent_impl.rs @@ -47,8 +47,8 @@ pub struct MultipleInherentImpl { impl_lint_pass!(MultipleInherentImpl => [MULTIPLE_INHERENT_IMPL]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MultipleInherentImpl { - fn check_item(&mut self, _: &LateContext<'a, 'tcx>, item: &'tcx Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl { + fn check_item(&mut self, _: &LateContext<'tcx>, item: &'tcx Item<'_>) { if let ItemKind::Impl { ref generics, of_trait: None, @@ -64,7 +64,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MultipleInherentImpl { } } - fn check_crate_post(&mut self, cx: &LateContext<'a, 'tcx>, krate: &'tcx Crate<'_>) { + fn check_crate_post(&mut self, cx: &LateContext<'tcx>, krate: &'tcx Crate<'_>) { if let Some(item) = krate.items.values().next() { // Retrieve all inherent implementations from the crate, grouped by type for impls in cx diff --git a/src/tools/clippy/clippy_lints/src/inherent_to_string.rs b/src/tools/clippy/clippy_lints/src/inherent_to_string.rs index 289628a2752..f330fa8fab8 100644 --- a/src/tools/clippy/clippy_lints/src/inherent_to_string.rs +++ b/src/tools/clippy/clippy_lints/src/inherent_to_string.rs @@ -92,8 +92,8 @@ declare_clippy_lint! { declare_lint_pass!(InherentToString => [INHERENT_TO_STRING, INHERENT_TO_STRING_SHADOW_DISPLAY]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InherentToString { - fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx ImplItem<'_>) { +impl<'tcx> LateLintPass<'tcx> for InherentToString { + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) { if impl_item.span.from_expansion() { return; } @@ -119,7 +119,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InherentToString { } } -fn show_lint(cx: &LateContext<'_, '_>, item: &ImplItem<'_>) { +fn show_lint(cx: &LateContext<'_>, item: &ImplItem<'_>) { let display_trait_id = get_trait_def_id(cx, &paths::DISPLAY_TRAIT).expect("Failed to get trait ID of `Display`!"); // Get the real type of 'self' diff --git a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs index 475610dda47..decbee27815 100644 --- a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs +++ b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs @@ -31,15 +31,15 @@ declare_clippy_lint! { declare_lint_pass!(InlineFnWithoutBody => [INLINE_FN_WITHOUT_BODY]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InlineFnWithoutBody { - fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem<'_>) { +impl<'tcx> LateLintPass<'tcx> for InlineFnWithoutBody { + fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { if let TraitItemKind::Fn(_, TraitFn::Required(_)) = item.kind { check_attrs(cx, item.ident.name, &item.attrs); } } } -fn check_attrs(cx: &LateContext<'_, '_>, name: Symbol, attrs: &[Attribute]) { +fn check_attrs(cx: &LateContext<'_>, name: Symbol, attrs: &[Attribute]) { for attr in attrs { if !attr.check_name(sym!(inline)) { continue; diff --git a/src/tools/clippy/clippy_lints/src/integer_division.rs b/src/tools/clippy/clippy_lints/src/integer_division.rs index 83ae1c1a971..e754c7b482a 100644 --- a/src/tools/clippy/clippy_lints/src/integer_division.rs +++ b/src/tools/clippy/clippy_lints/src/integer_division.rs @@ -30,8 +30,8 @@ declare_clippy_lint! { declare_lint_pass!(IntegerDivision => [INTEGER_DIVISION]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IntegerDivision { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for IntegerDivision { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { if is_integer_division(cx, expr) { span_lint_and_help( cx, @@ -45,7 +45,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IntegerDivision { } } -fn is_integer_division<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>) -> bool { +fn is_integer_division<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) -> bool { if_chain! { if let hir::ExprKind::Binary(binop, left, right) = &expr.kind; if let hir::BinOpKind::Div = &binop.node; diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs index c9e12fc535e..c6cc174a8c9 100644 --- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs @@ -45,8 +45,8 @@ impl LargeConstArrays { impl_lint_pass!(LargeConstArrays => [LARGE_CONST_ARRAYS]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeConstArrays { - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for LargeConstArrays { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if_chain! { if !item.span.from_expansion(); if let ItemKind::Const(hir_ty, _) = &item.kind; diff --git a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs index 5bc3234e325..3c7880d74ee 100644 --- a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs +++ b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs @@ -56,8 +56,8 @@ impl LargeEnumVariant { impl_lint_pass!(LargeEnumVariant => [LARGE_ENUM_VARIANT]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { - fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant { + fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { let did = cx.tcx.hir().local_def_id(item.hir_id); if let ItemKind::Enum(ref def, _) = item.kind { let ty = cx.tcx.type_of(did); 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 0301f263489..8eb986c25ff 100644 --- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs @@ -38,8 +38,8 @@ impl LargeStackArrays { impl_lint_pass!(LargeStackArrays => [LARGE_STACK_ARRAYS]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeStackArrays { - fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for LargeStackArrays { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { if let ExprKind::Repeat(_, _) = expr.kind; if let ty::Array(element_type, cst) = cx.tables().expr_ty(expr).kind; diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index e17297e9695..26d96428771 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -70,8 +70,8 @@ declare_clippy_lint! { declare_lint_pass!(LenZero => [LEN_ZERO, LEN_WITHOUT_IS_EMPTY]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero { - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for LenZero { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if item.span.from_expansion() { return; } @@ -87,7 +87,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero { } } - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if expr.span.from_expansion() { return; } @@ -118,8 +118,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero { } } -fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item<'_>, trait_items: &[TraitItemRef]) { - fn is_named_self(cx: &LateContext<'_, '_>, item: &TraitItemRef, name: &str) -> bool { +fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items: &[TraitItemRef]) { + fn is_named_self(cx: &LateContext<'_>, item: &TraitItemRef, name: &str) -> bool { item.ident.name.as_str() == name && if let AssocItemKind::Fn { has_self } = item.kind { has_self && { @@ -132,7 +132,7 @@ fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item<'_>, trait_i } // fill the set with current and super traits - fn fill_trait_set(traitt: DefId, set: &mut FxHashSet<DefId>, cx: &LateContext<'_, '_>) { + fn fill_trait_set(traitt: DefId, set: &mut FxHashSet<DefId>, cx: &LateContext<'_>) { if set.insert(traitt) { for supertrait in rustc_trait_selection::traits::supertrait_def_ids(cx.tcx, traitt) { fill_trait_set(supertrait, set, cx); @@ -169,8 +169,8 @@ fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item<'_>, trait_i } } -fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item<'_>, impl_items: &[ImplItemRef<'_>]) { - fn is_named_self(cx: &LateContext<'_, '_>, item: &ImplItemRef<'_>, name: &str) -> bool { +fn check_impl_items(cx: &LateContext<'_>, item: &Item<'_>, impl_items: &[ImplItemRef<'_>]) { + fn is_named_self(cx: &LateContext<'_>, item: &ImplItemRef<'_>, name: &str) -> bool { item.ident.name.as_str() == name && if let AssocItemKind::Fn { has_self } = item.kind { has_self && { @@ -210,7 +210,7 @@ fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item<'_>, impl_items: &[Imp } } -fn check_cmp(cx: &LateContext<'_, '_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>, op: &str, compare_to: u32) { +fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>, op: &str, compare_to: u32) { if let (&ExprKind::MethodCall(ref method_path, _, ref args, _), &ExprKind::Lit(ref lit)) = (&method.kind, &lit.kind) { // check if we are in an is_empty() method @@ -225,7 +225,7 @@ fn check_cmp(cx: &LateContext<'_, '_>, span: Span, method: &Expr<'_>, lit: &Expr } fn check_len( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, span: Span, method_name: Symbol, args: &[Expr<'_>], @@ -259,9 +259,9 @@ fn check_len( } /// Checks if this type has an `is_empty` method. -fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { +fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { /// Special case ranges until `range_is_empty` is stabilized. See issue 3807. - fn should_skip_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { + fn should_skip_range(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { higher::range(cx, expr).map_or(false, |_| { !cx.tcx .features() @@ -272,7 +272,7 @@ fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { } /// Gets an `AssocItem` and return true if it matches `is_empty(self)`. - fn is_is_empty(cx: &LateContext<'_, '_>, item: &ty::AssocItem) -> bool { + fn is_is_empty(cx: &LateContext<'_>, item: &ty::AssocItem) -> bool { if let ty::AssocKind::Fn = item.kind { if item.ident.name.as_str() == "is_empty" { let sig = cx.tcx.fn_sig(item.def_id); @@ -287,7 +287,7 @@ fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { } /// Checks the inherent impl's items for an `is_empty(self)` method. - fn has_is_empty_impl(cx: &LateContext<'_, '_>, id: DefId) -> bool { + fn has_is_empty_impl(cx: &LateContext<'_>, id: DefId) -> bool { cx.tcx.inherent_impls(id).iter().any(|imp| { cx.tcx .associated_items(*imp) diff --git a/src/tools/clippy/clippy_lints/src/let_and_return.rs b/src/tools/clippy/clippy_lints/src/let_and_return.rs index 299202981b1..ddc41f89f8d 100644 --- a/src/tools/clippy/clippy_lints/src/let_and_return.rs +++ b/src/tools/clippy/clippy_lints/src/let_and_return.rs @@ -40,8 +40,8 @@ declare_clippy_lint! { declare_lint_pass!(LetReturn => [LET_AND_RETURN]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetReturn { - fn check_block(&mut self, cx: &LateContext<'a, 'tcx>, block: &'tcx Block<'_>) { +impl<'tcx> LateLintPass<'tcx> for LetReturn { + fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'_>) { // we need both a let-binding stmt and an expr if_chain! { if let Some(retexpr) = block.expr; @@ -86,14 +86,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetReturn { } } -fn last_statement_borrows<'tcx>(cx: &LateContext<'_, 'tcx>, expr: &'tcx Expr<'tcx>) -> bool { +fn last_statement_borrows<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { let mut visitor = BorrowVisitor { cx, borrows: false }; walk_expr(&mut visitor, expr); visitor.borrows } struct BorrowVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, borrows: bool, } @@ -107,7 +107,7 @@ impl BorrowVisitor<'_, '_> { .. }, .., - ) => self.cx.tables().qpath_res(qpath, expr.hir_id).opt_def_id(), + ) => self.cx.qpath_res(qpath, expr.hir_id).opt_def_id(), _ => None, } } diff --git a/src/tools/clippy/clippy_lints/src/let_if_seq.rs b/src/tools/clippy/clippy_lints/src/let_if_seq.rs index 7b03812b822..706c73ce66c 100644 --- a/src/tools/clippy/clippy_lints/src/let_if_seq.rs +++ b/src/tools/clippy/clippy_lints/src/let_if_seq.rs @@ -56,8 +56,8 @@ declare_clippy_lint! { declare_lint_pass!(LetIfSeq => [USELESS_LET_IF_SEQ]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { - fn check_block(&mut self, cx: &LateContext<'a, 'tcx>, block: &'tcx hir::Block<'_>) { +impl<'tcx> LateLintPass<'tcx> for LetIfSeq { + fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) { let mut it = block.stmts.iter().peekable(); while let Some(stmt) = it.next() { if_chain! { @@ -137,7 +137,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq { } struct UsedVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, id: hir::HirId, used: bool, } @@ -162,8 +162,8 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for UsedVisitor<'a, 'tcx> { } } -fn check_assign<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn check_assign<'tcx>( + cx: &LateContext<'tcx>, decl: hir::HirId, block: &'tcx hir::Block<'_>, ) -> Option<&'tcx hir::Expr<'tcx>> { @@ -197,7 +197,7 @@ fn check_assign<'a, 'tcx>( None } -fn used_in_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, id: hir::HirId, expr: &'tcx hir::Expr<'_>) -> bool { +fn used_in_expr<'tcx>(cx: &LateContext<'tcx>, id: hir::HirId, expr: &'tcx hir::Expr<'_>) -> bool { let mut v = UsedVisitor { cx, id, used: false }; intravisit::walk_expr(&mut v, expr); v.used diff --git a/src/tools/clippy/clippy_lints/src/let_underscore.rs b/src/tools/clippy/clippy_lints/src/let_underscore.rs index 0864bbe0f91..c7dda3c9928 100644 --- a/src/tools/clippy/clippy_lints/src/let_underscore.rs +++ b/src/tools/clippy/clippy_lints/src/let_underscore.rs @@ -66,8 +66,8 @@ const SYNC_GUARD_PATHS: [&[&str]; 3] = [ &paths::RWLOCK_WRITE_GUARD, ]; -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetUnderscore { - fn check_local(&mut self, cx: &LateContext<'_, '_>, local: &Local<'_>) { +impl<'tcx> LateLintPass<'tcx> for LetUnderscore { + fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) { if in_external_macro(cx.tcx.sess, local.span) { return; } diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index 6840e82d4bf..a79f94855bd 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -76,14 +76,14 @@ declare_clippy_lint! { declare_lint_pass!(Lifetimes => [NEEDLESS_LIFETIMES, EXTRA_UNUSED_LIFETIMES]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Lifetimes { - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for Lifetimes { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if let ItemKind::Fn(ref sig, ref generics, id) = item.kind { check_fn_inner(cx, &sig.decl, Some(id), generics, item.span, true); } } - fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem<'_>) { + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) { if let ImplItemKind::Fn(ref sig, id) = item.kind { let report_extra_lifetimes = trait_ref_of_method(cx, item.hir_id).is_none(); check_fn_inner( @@ -97,7 +97,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Lifetimes { } } - fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem<'_>) { + fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { if let TraitItemKind::Fn(ref sig, ref body) = item.kind { let body = match *body { TraitFn::Required(_) => None, @@ -116,8 +116,8 @@ enum RefLt { Named(Name), } -fn check_fn_inner<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn check_fn_inner<'tcx>( + cx: &LateContext<'tcx>, decl: &'tcx FnDecl<'_>, body: Option<BodyId>, generics: &'tcx Generics<'_>, @@ -177,8 +177,8 @@ fn check_fn_inner<'a, 'tcx>( } } -fn could_use_elision<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn could_use_elision<'tcx>( + cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>, body: Option<BodyId>, named_generics: &'tcx [GenericParam<'_>], @@ -296,13 +296,13 @@ fn unique_lifetimes(lts: &[RefLt]) -> usize { /// A visitor usable for `rustc_front::visit::walk_ty()`. struct RefVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, lts: Vec<RefLt>, abort: bool, } -impl<'v, 't> RefVisitor<'v, 't> { - fn new(cx: &'v LateContext<'v, 't>) -> Self { +impl<'a, 'tcx> RefVisitor<'a, 'tcx> { + fn new(cx: &'a LateContext<'tcx>) -> Self { Self { cx, lts: Vec::new(), @@ -343,7 +343,7 @@ impl<'v, 't> RefVisitor<'v, 't> { }) { let hir_id = ty.hir_id; - match self.cx.tables().qpath_res(qpath, hir_id) { + match self.cx.qpath_res(qpath, hir_id) { Res::Def(DefKind::TyAlias | DefKind::Struct, def_id) => { let generics = self.cx.tcx.generics_of(def_id); for _ in generics.params.as_slice() { @@ -412,7 +412,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> { /// Are any lifetimes mentioned in the `where` clause? If so, we don't try to /// reason about elision. -fn has_where_lifetimes<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, where_clause: &'tcx WhereClause<'_>) -> bool { +fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, where_clause: &'tcx WhereClause<'_>) -> bool { for predicate in where_clause.predicates { match *predicate { WherePredicate::RegionPredicate(..) => return true, @@ -482,7 +482,7 @@ impl<'tcx> Visitor<'tcx> for LifetimeChecker { } } -fn report_extra_lifetimes<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, func: &'tcx FnDecl<'_>, generics: &'tcx Generics<'_>) { +fn report_extra_lifetimes<'tcx>(cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>, generics: &'tcx Generics<'_>) { let hs = generics .params .iter() diff --git a/src/tools/clippy/clippy_lints/src/loops.rs b/src/tools/clippy/clippy_lints/src/loops.rs index 18b979176a0..d821b513484 100644 --- a/src/tools/clippy/clippy_lints/src/loops.rs +++ b/src/tools/clippy/clippy_lints/src/loops.rs @@ -438,9 +438,9 @@ declare_lint_pass!(Loops => [ WHILE_IMMUTABLE_CONDITION, ]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Loops { +impl<'tcx> LateLintPass<'tcx> for Loops { #[allow(clippy::too_many_lines)] - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let Some((pat, arg, body)) = higher::for_loop(expr) { // we don't want to check expanded macros // this check is not at the top of the function @@ -732,8 +732,8 @@ fn never_loop_expr_branch<'a, T: Iterator<Item = &'a Expr<'a>>>(e: &mut T, main_ .fold(NeverLoopResult::AlwaysBreak, combine_branches) } -fn check_for_loop<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn check_for_loop<'tcx>( + cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx Expr<'_>, body: &'tcx Expr<'_>, @@ -747,7 +747,7 @@ fn check_for_loop<'a, 'tcx>( detect_manual_memcpy(cx, pat, arg, body, expr); } -fn same_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, var: HirId) -> bool { +fn same_var<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, var: HirId) -> bool { if_chain! { if let ExprKind::Path(qpath) = &expr.kind; if let QPath::Resolved(None, path) = qpath; @@ -794,7 +794,7 @@ struct FixedOffsetVar<'hir> { offset: Offset, } -fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'_>) -> bool { +fn is_slice_like<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'_>) -> bool { let is_slice = match ty.kind { ty::Ref(_, subty, _) => is_slice_like(cx, subty), ty::Slice(..) | ty::Array(..) => true, @@ -814,8 +814,8 @@ fn fetch_cloned_expr<'tcx>(expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> { } } -fn get_offset<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, idx: &Expr<'_>, var: HirId) -> Option<Offset> { - fn extract_offset<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &Expr<'_>, var: HirId) -> Option<String> { +fn get_offset<'tcx>(cx: &LateContext<'tcx>, idx: &Expr<'_>, var: HirId) -> Option<Offset> { + fn extract_offset<'tcx>(cx: &LateContext<'tcx>, e: &Expr<'_>, var: HirId) -> Option<String> { match &e.kind { ExprKind::Lit(l) => match l.node { ast::LitKind::Int(x, _ty) => Some(x.to_string()), @@ -880,8 +880,8 @@ fn get_assignments<'tcx>(body: &'tcx Expr<'tcx>) -> impl Iterator<Item = Option< iter_a.into_iter().flatten().chain(iter_b.into_iter()) } -fn build_manual_memcpy_suggestion<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn build_manual_memcpy_suggestion<'tcx>( + cx: &LateContext<'tcx>, start: &Expr<'_>, end: &Expr<'_>, limits: ast::RangeLimits, @@ -961,8 +961,8 @@ fn build_manual_memcpy_suggestion<'a, 'tcx>( } /// Checks for for loops that sequentially copy items from one slice-like /// object to another. -fn detect_manual_memcpy<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn detect_manual_memcpy<'tcx>( + cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx Expr<'_>, body: &'tcx Expr<'_>, @@ -1024,8 +1024,8 @@ fn detect_manual_memcpy<'a, 'tcx>( /// Checks for looping over a range and then indexing a sequence with it. /// The iteratee must be a range literal. #[allow(clippy::too_many_lines)] -fn check_for_loop_range<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn check_for_loop_range<'tcx>( + cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx Expr<'_>, body: &'tcx Expr<'_>, @@ -1205,7 +1205,7 @@ fn is_len_call(expr: &Expr<'_>, var: Name) -> bool { } fn is_end_eq_array_len<'tcx>( - cx: &LateContext<'_, 'tcx>, + cx: &LateContext<'tcx>, end: &Expr<'_>, limits: ast::RangeLimits, indexed_ty: Ty<'tcx>, @@ -1226,7 +1226,7 @@ fn is_end_eq_array_len<'tcx>( false } -fn lint_iter_method(cx: &LateContext<'_, '_>, args: &[Expr<'_>], arg: &Expr<'_>, method_name: &str) { +fn lint_iter_method(cx: &LateContext<'_>, args: &[Expr<'_>], arg: &Expr<'_>, method_name: &str) { let mut applicability = Applicability::MachineApplicable; let object = snippet_with_applicability(cx, args[0].span, "_", &mut applicability); let muta = if method_name == "iter_mut" { "mut " } else { "" }; @@ -1242,7 +1242,7 @@ fn lint_iter_method(cx: &LateContext<'_, '_>, args: &[Expr<'_>], arg: &Expr<'_>, ) } -fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>, expr: &Expr<'_>) { +fn check_for_loop_arg(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>, expr: &Expr<'_>) { let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used if let ExprKind::MethodCall(ref method, _, ref args, _) = arg.kind { // just the receiver, no arguments @@ -1299,7 +1299,7 @@ fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>, e } /// Checks for `for` loops over `Option`s and `Result`s. -fn check_arg_type(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>) { +fn check_arg_type(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>) { let ty = cx.tables().expr_ty(arg); if is_type_diagnostic_item(cx, ty, sym!(option_type)) { span_lint_and_help( @@ -1338,8 +1338,8 @@ fn check_arg_type(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>) { } } -fn check_for_loop_explicit_counter<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn check_for_loop_explicit_counter<'tcx>( + cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx Expr<'_>, body: &'tcx Expr<'_>, @@ -1403,7 +1403,7 @@ fn check_for_loop_explicit_counter<'a, 'tcx>( /// If `arg` was the argument to a `for` loop, return the "cleanest" way of writing the /// actual `Iterator` that the loop uses. -fn make_iterator_snippet(cx: &LateContext<'_, '_>, arg: &Expr<'_>, applic_ref: &mut Applicability) -> String { +fn make_iterator_snippet(cx: &LateContext<'_>, arg: &Expr<'_>, applic_ref: &mut Applicability) -> String { let impls_iterator = get_trait_def_id(cx, &paths::ITERATOR) .map_or(false, |id| implements_trait(cx, cx.tables().expr_ty(arg), id, &[])); if impls_iterator { @@ -1437,8 +1437,8 @@ fn make_iterator_snippet(cx: &LateContext<'_, '_>, arg: &Expr<'_>, applic_ref: & } /// Checks for the `FOR_KV_MAP` lint. -fn check_for_loop_over_map_kv<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn check_for_loop_over_map_kv<'tcx>( + cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx Expr<'_>, body: &'tcx Expr<'_>, @@ -1490,7 +1490,7 @@ fn check_for_loop_over_map_kv<'a, 'tcx>( } struct MutatePairDelegate<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, hir_id_low: Option<HirId>, hir_id_high: Option<HirId>, span_low: Option<Span>, @@ -1531,7 +1531,7 @@ impl MutatePairDelegate<'_, '_> { } } -fn check_for_mut_range_bound(cx: &LateContext<'_, '_>, arg: &Expr<'_>, body: &Expr<'_>) { +fn check_for_mut_range_bound(cx: &LateContext<'_>, arg: &Expr<'_>, body: &Expr<'_>) { if let Some(higher::Range { start: Some(start), end: Some(end), @@ -1547,7 +1547,7 @@ fn check_for_mut_range_bound(cx: &LateContext<'_, '_>, arg: &Expr<'_>, body: &Ex } } -fn mut_warn_with_span(cx: &LateContext<'_, '_>, span: Option<Span>) { +fn mut_warn_with_span(cx: &LateContext<'_>, span: Option<Span>) { if let Some(sp) = span { span_lint( cx, @@ -1558,7 +1558,7 @@ fn mut_warn_with_span(cx: &LateContext<'_, '_>, span: Option<Span>) { } } -fn check_for_mutability(cx: &LateContext<'_, '_>, bound: &Expr<'_>) -> Option<HirId> { +fn check_for_mutability(cx: &LateContext<'_>, bound: &Expr<'_>) -> Option<HirId> { if_chain! { if let ExprKind::Path(ref qpath) = bound.kind; if let QPath::Resolved(None, _) = *qpath; @@ -1580,8 +1580,8 @@ fn check_for_mutability(cx: &LateContext<'_, '_>, bound: &Expr<'_>) -> Option<Hi None } -fn check_for_mutation<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn check_for_mutation<'tcx>( + cx: &LateContext<'tcx>, body: &Expr<'_>, bound_ids: &[Option<HirId>], ) -> (Option<Span>, Option<Span>) { @@ -1609,7 +1609,7 @@ fn pat_is_wild<'tcx>(pat: &'tcx PatKind<'_>, body: &'tcx Expr<'_>) -> bool { } struct LocalUsedVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, local: HirId, used: bool, } @@ -1632,7 +1632,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LocalUsedVisitor<'a, 'tcx> { struct VarVisitor<'a, 'tcx> { /// context reference - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, /// var name to look for as index var: HirId, /// indexed variables that are used mutably @@ -1803,7 +1803,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { } } -fn is_used_inside<'a, 'tcx>(cx: &'a LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>, container: &'tcx Expr<'_>) -> bool { +fn is_used_inside<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, container: &'tcx Expr<'_>) -> bool { let def_id = match var_def_id(cx, expr) { Some(id) => id, None => return false, @@ -1816,7 +1816,7 @@ fn is_used_inside<'a, 'tcx>(cx: &'a LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>, false } -fn is_iterator_used_after_while_let<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, iter_expr: &'tcx Expr<'_>) -> bool { +fn is_iterator_used_after_while_let<'tcx>(cx: &LateContext<'tcx>, iter_expr: &'tcx Expr<'_>) -> bool { let def_id = match var_def_id(cx, iter_expr) { Some(id) => id, None => return false, @@ -1835,7 +1835,7 @@ fn is_iterator_used_after_while_let<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, iter_e } struct VarUsedAfterLoopVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, def_id: HirId, iter_expr_id: HirId, past_while_let: bool, @@ -1863,7 +1863,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarUsedAfterLoopVisitor<'a, 'tcx> { /// Returns `true` if the type of expr is one that provides `IntoIterator` impls /// for `&T` and `&mut T`, such as `Vec`. #[rustfmt::skip] -fn is_ref_iterable_type(cx: &LateContext<'_, '_>, e: &Expr<'_>) -> bool { +fn is_ref_iterable_type(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { // no walk_ptrs_ty: calling iter() on a reference can make sense because it // will allow further borrows afterwards let ty = cx.tables().expr_ty(e); @@ -1878,7 +1878,7 @@ fn is_ref_iterable_type(cx: &LateContext<'_, '_>, e: &Expr<'_>) -> bool { match_type(cx, ty, &paths::BTREESET) } -fn is_iterable_array<'tcx>(ty: Ty<'tcx>, cx: &LateContext<'_, 'tcx>) -> bool { +fn is_iterable_array<'tcx>(ty: Ty<'tcx>, cx: &LateContext<'tcx>) -> bool { // IntoIterator is currently only implemented for array sizes <= 32 in rustc match ty.kind { ty::Array(_, n) => { @@ -1946,7 +1946,7 @@ enum VarState { /// Scan a for loop for variables that are incremented exactly once. struct IncrementVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, // context reference + cx: &'a LateContext<'tcx>, // context reference states: FxHashMap<HirId, VarState>, // incremented variables depth: u32, // depth of conditional expressions done: bool, @@ -2004,8 +2004,8 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> { /// Checks whether a variable is initialized to zero at the start of a loop. struct InitializeVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, // context reference - end_expr: &'tcx Expr<'tcx>, // the for loop. Stop scanning here. + cx: &'a LateContext<'tcx>, // context reference + end_expr: &'tcx Expr<'tcx>, // the for loop. Stop scanning here. var_id: HirId, state: VarState, name: Option<Name>, @@ -2094,7 +2094,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { } } -fn var_def_id(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<HirId> { +fn var_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<HirId> { if let ExprKind::Path(ref qpath) = expr.kind { let path_res = qpath_res(cx, qpath, expr.hir_id); if let Res::Local(hir_id) = path_res { @@ -2118,7 +2118,7 @@ fn is_conditional(expr: &Expr<'_>) -> bool { } } -fn is_nested(cx: &LateContext<'_, '_>, match_expr: &Expr<'_>, iter_expr: &Expr<'_>) -> bool { +fn is_nested(cx: &LateContext<'_>, match_expr: &Expr<'_>, iter_expr: &Expr<'_>) -> bool { if_chain! { if let Some(loop_block) = get_enclosing_block(cx, match_expr.hir_id); let parent_node = cx.tcx.hir().get_parent_node(loop_block.hir_id); @@ -2130,7 +2130,7 @@ fn is_nested(cx: &LateContext<'_, '_>, match_expr: &Expr<'_>, iter_expr: &Expr<' false } -fn is_loop_nested(cx: &LateContext<'_, '_>, loop_expr: &Expr<'_>, iter_expr: &Expr<'_>) -> bool { +fn is_loop_nested(cx: &LateContext<'_>, loop_expr: &Expr<'_>, iter_expr: &Expr<'_>) -> bool { let mut id = loop_expr.hir_id; let iter_name = if let Some(name) = path_name(iter_expr) { name @@ -2240,7 +2240,7 @@ fn path_name(e: &Expr<'_>) -> Option<Name> { None } -fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr<'_>, expr: &'tcx Expr<'_>) { +fn check_infinite_loop<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, expr: &'tcx Expr<'_>) { if constant(cx, cx.tables(), cond).is_some() { // A pure constant condition (e.g., `while false`) is not linted. return; @@ -2321,7 +2321,7 @@ impl<'tcx> Visitor<'tcx> for HasBreakOrReturnVisitor { /// Note: In some cases such as `self`, there are no mutable annotation, /// All variables definition IDs are collected struct VarCollectorVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, ids: FxHashSet<HirId>, def_ids: FxHashMap<def_id::DefId, bool>, skip: bool, @@ -2369,7 +2369,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> { const NEEDLESS_COLLECT_MSG: &str = "avoid using `collect()` when not needed"; -fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'a, 'tcx>) { +fn check_needless_collect<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) { if_chain! { if let ExprKind::MethodCall(ref method, _, ref args, _) = expr.kind; if let ExprKind::MethodCall(ref chain_method, _, _, _) = args[0].kind; diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs index b845b20d2c0..065c7c042d3 100644 --- a/src/tools/clippy/clippy_lints/src/macro_use.rs +++ b/src/tools/clippy/clippy_lints/src/macro_use.rs @@ -44,7 +44,7 @@ pub struct MacroRefData { } impl MacroRefData { - pub fn new(name: String, callee: Span, cx: &LateContext<'_, '_>) -> Self { + pub fn new(name: String, callee: Span, cx: &LateContext<'_>) -> Self { let mut path = cx.sess().source_map().span_to_filename(callee).to_string(); // std lib paths are <::std::module::file type> @@ -72,7 +72,7 @@ pub struct MacroUseImports { impl_lint_pass!(MacroUseImports => [MACRO_USE_IMPORTS]); impl MacroUseImports { - fn push_unique_macro(&mut self, cx: &LateContext<'_, '_>, span: Span) { + fn push_unique_macro(&mut self, cx: &LateContext<'_>, span: Span) { let call_site = span.source_callsite(); let name = snippet(cx, cx.sess().source_map().span_until_char(call_site, '!'), "_"); if let Some(callee) = span.source_callee() { @@ -89,7 +89,7 @@ impl MacroUseImports { } } - fn push_unique_macro_pat_ty(&mut self, cx: &LateContext<'_, '_>, span: Span) { + fn push_unique_macro_pat_ty(&mut self, cx: &LateContext<'_>, span: Span) { let call_site = span.source_callsite(); let name = snippet(cx, cx.sess().source_map().span_until_char(call_site, '!'), "_"); if let Some(callee) = span.source_callee() { @@ -102,8 +102,8 @@ impl MacroUseImports { } } -impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports { - fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for MacroUseImports { + fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { if_chain! { if cx.sess().opts.edition == Edition::Edition2018; if let hir::ItemKind::Use(path, _kind) = &item.kind; @@ -127,33 +127,33 @@ impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports { } } } - fn check_attribute(&mut self, cx: &LateContext<'_, '_>, attr: &ast::Attribute) { + fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) { if in_macro(attr.span) { self.push_unique_macro(cx, attr.span); } } - fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) { if in_macro(expr.span) { self.push_unique_macro(cx, expr.span); } } - fn check_stmt(&mut self, cx: &LateContext<'_, '_>, stmt: &hir::Stmt<'_>) { + fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &hir::Stmt<'_>) { if in_macro(stmt.span) { self.push_unique_macro(cx, stmt.span); } } - fn check_pat(&mut self, cx: &LateContext<'_, '_>, pat: &hir::Pat<'_>) { + fn check_pat(&mut self, cx: &LateContext<'_>, pat: &hir::Pat<'_>) { if in_macro(pat.span) { self.push_unique_macro_pat_ty(cx, pat.span); } } - fn check_ty(&mut self, cx: &LateContext<'_, '_>, ty: &hir::Ty<'_>) { + fn check_ty(&mut self, cx: &LateContext<'_>, ty: &hir::Ty<'_>) { if in_macro(ty.span) { self.push_unique_macro_pat_ty(cx, ty.span); } } #[allow(clippy::too_many_lines)] - fn check_crate_post(&mut self, cx: &LateContext<'_, '_>, _krate: &hir::Crate<'_>) { + fn check_crate_post(&mut self, cx: &LateContext<'_>, _krate: &hir::Crate<'_>) { let mut used = FxHashMap::default(); let mut check_dup = vec![]; for (import, span) in &self.imports { diff --git a/src/tools/clippy/clippy_lints/src/main_recursion.rs b/src/tools/clippy/clippy_lints/src/main_recursion.rs index 8a0e47a3d31..eceae706e4f 100644 --- a/src/tools/clippy/clippy_lints/src/main_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/main_recursion.rs @@ -31,12 +31,12 @@ pub struct MainRecursion { impl_lint_pass!(MainRecursion => [MAIN_RECURSION]); -impl LateLintPass<'_, '_> for MainRecursion { - fn check_crate(&mut self, _: &LateContext<'_, '_>, krate: &Crate<'_>) { +impl LateLintPass<'_> for MainRecursion { + fn check_crate(&mut self, _: &LateContext<'_>, krate: &Crate<'_>) { self.has_no_std_attr = is_no_std_crate(krate); } - fn check_expr_post(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) { + fn check_expr_post(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { if self.has_no_std_attr { return; } diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs index 03ab274d9ca..c19fb148cda 100644 --- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs +++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs @@ -38,10 +38,10 @@ declare_clippy_lint! { declare_lint_pass!(ManualAsyncFn => [MANUAL_ASYNC_FN]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ManualAsyncFn { +impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn { fn check_fn( &mut self, - cx: &LateContext<'a, 'tcx>, + cx: &LateContext<'tcx>, kind: FnKind<'tcx>, decl: &'tcx FnDecl<'_>, body: &'tcx Body<'_>, @@ -97,7 +97,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ManualAsyncFn { } } -fn future_trait_ref<'tcx>(cx: &LateContext<'_, 'tcx>, ty: &'tcx Ty<'tcx>) -> Option<&'tcx TraitRef<'tcx>> { +fn future_trait_ref<'tcx>(cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) -> Option<&'tcx TraitRef<'tcx>> { if_chain! { if let TyKind::OpaqueDef(item_id, _) = ty.kind; let item = cx.tcx.hir().item(item_id.id); @@ -129,7 +129,7 @@ fn future_output_ty<'tcx>(trait_ref: &'tcx TraitRef<'tcx>) -> Option<&'tcx Ty<'t None } -fn desugared_async_block<'tcx>(cx: &LateContext<'_, 'tcx>, block: &'tcx Block<'tcx>) -> Option<&'tcx Body<'tcx>> { +fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) -> Option<&'tcx Body<'tcx>> { if_chain! { if let Some(block_expr) = block.expr; if let Some(args) = match_function_call(cx, block_expr, &FUTURE_FROM_GENERATOR); @@ -145,7 +145,7 @@ fn desugared_async_block<'tcx>(cx: &LateContext<'_, 'tcx>, block: &'tcx Block<'t None } -fn suggested_ret(cx: &LateContext<'_, '_>, output: &Ty<'_>) -> Option<(&'static str, String)> { +fn suggested_ret(cx: &LateContext<'_>, output: &Ty<'_>) -> Option<(&'static str, String)> { match output.kind { TyKind::Tup(tys) if tys.is_empty() => { let sugg = "remove the return type"; diff --git a/src/tools/clippy/clippy_lints/src/map_clone.rs b/src/tools/clippy/clippy_lints/src/map_clone.rs index 9109de9458f..905a3f3ca71 100644 --- a/src/tools/clippy/clippy_lints/src/map_clone.rs +++ b/src/tools/clippy/clippy_lints/src/map_clone.rs @@ -42,8 +42,8 @@ declare_clippy_lint! { declare_lint_pass!(MapClone => [MAP_CLONE]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MapClone { - fn check_expr(&mut self, cx: &LateContext<'_, '_>, e: &hir::Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for MapClone { + fn check_expr(&mut self, cx: &LateContext<'_>, e: &hir::Expr<'_>) { if e.span.from_expansion() { return; } @@ -106,7 +106,7 @@ fn ident_eq(name: Ident, path: &hir::Expr<'_>) -> bool { } } -fn lint_needless_cloning(cx: &LateContext<'_, '_>, root: Span, receiver: Span) { +fn lint_needless_cloning(cx: &LateContext<'_>, root: Span, receiver: Span) { span_lint_and_sugg( cx, MAP_CLONE, @@ -118,7 +118,7 @@ fn lint_needless_cloning(cx: &LateContext<'_, '_>, root: Span, receiver: Span) { ) } -fn lint(cx: &LateContext<'_, '_>, replace: Span, root: Span, copied: bool) { +fn lint(cx: &LateContext<'_>, replace: Span, root: Span, copied: bool) { let mut applicability = Applicability::MachineApplicable; if copied { span_lint_and_sugg( diff --git a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs index a4550f707ee..316a71c5005 100644 --- a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs +++ b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs @@ -100,7 +100,7 @@ fn is_unit_type(ty: Ty<'_>) -> bool { } } -fn is_unit_function(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>) -> bool { +fn is_unit_function(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { let ty = cx.tables().expr_ty(expr); if let ty::FnDef(id, _) = ty.kind { @@ -111,7 +111,7 @@ fn is_unit_function(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>) -> bool { false } -fn is_unit_expression(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>) -> bool { +fn is_unit_expression(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { is_unit_type(cx.tables().expr_ty(expr)) } @@ -119,7 +119,7 @@ fn is_unit_expression(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>) -> bool { /// semicolons, which causes problems when generating a suggestion. Given an /// expression that evaluates to '()' or '!', recursively remove useless braces /// and semi-colons until is suitable for including in the suggestion template -fn reduce_unit_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a hir::Expr<'_>) -> Option<Span> { +fn reduce_unit_expression<'a>(cx: &LateContext<'_>, expr: &'a hir::Expr<'_>) -> Option<Span> { if !is_unit_expression(cx, expr) { return None; } @@ -160,10 +160,10 @@ fn reduce_unit_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a hir::Expr<'_>) } } -fn unit_closure<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &'a hir::Expr<'a>, -) -> Option<(&'tcx hir::Param<'tcx>, &'a hir::Expr<'a>)> { +fn unit_closure<'tcx>( + cx: &LateContext<'tcx>, + expr: &hir::Expr<'_>, +) -> Option<(&'tcx hir::Param<'tcx>, &'tcx hir::Expr<'tcx>)> { if let hir::ExprKind::Closure(_, ref decl, inner_expr_id, _, _) = expr.kind { let body = cx.tcx.hir().body(inner_expr_id); let body_expr = &body.value; @@ -186,7 +186,7 @@ fn unit_closure<'a, 'tcx>( /// `y` => `_y` /// /// Anything else will return `a`. -fn let_binding_name(cx: &LateContext<'_, '_>, var_arg: &hir::Expr<'_>) -> String { +fn let_binding_name(cx: &LateContext<'_>, var_arg: &hir::Expr<'_>) -> String { match &var_arg.kind { hir::ExprKind::Field(_, _) => snippet(cx, var_arg.span, "_").replace(".", "_"), hir::ExprKind::Path(_) => format!("_{}", snippet(cx, var_arg.span, "")), @@ -202,7 +202,7 @@ fn suggestion_msg(function_type: &str, map_type: &str) -> String { ) } -fn lint_map_unit_fn(cx: &LateContext<'_, '_>, stmt: &hir::Stmt<'_>, expr: &hir::Expr<'_>, map_args: &[hir::Expr<'_>]) { +fn lint_map_unit_fn(cx: &LateContext<'_>, stmt: &hir::Stmt<'_>, expr: &hir::Expr<'_>, map_args: &[hir::Expr<'_>]) { let var_arg = &map_args[0]; let (map_type, variant, lint) = if is_type_diagnostic_item(cx, cx.tables().expr_ty(var_arg), sym!(option_type)) { @@ -258,8 +258,8 @@ fn lint_map_unit_fn(cx: &LateContext<'_, '_>, stmt: &hir::Stmt<'_>, expr: &hir:: } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MapUnit { - fn check_stmt(&mut self, cx: &LateContext<'_, '_>, stmt: &hir::Stmt<'_>) { +impl<'tcx> LateLintPass<'tcx> for MapUnit { + fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &hir::Stmt<'_>) { if stmt.span.from_expansion() { return; } diff --git a/src/tools/clippy/clippy_lints/src/match_on_vec_items.rs b/src/tools/clippy/clippy_lints/src/match_on_vec_items.rs index 4a025e0621f..0003aa94a03 100644 --- a/src/tools/clippy/clippy_lints/src/match_on_vec_items.rs +++ b/src/tools/clippy/clippy_lints/src/match_on_vec_items.rs @@ -44,8 +44,8 @@ declare_clippy_lint! { declare_lint_pass!(MatchOnVecItems => [MATCH_ON_VEC_ITEMS]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MatchOnVecItems { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'tcx>) { +impl<'tcx> LateLintPass<'tcx> for MatchOnVecItems { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { if_chain! { if !in_external_macro(cx.sess(), expr.span); if let ExprKind::Match(ref match_expr, _, MatchSource::Normal) = expr.kind; @@ -73,7 +73,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MatchOnVecItems { } } -fn is_vec_indexing<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { +fn is_vec_indexing<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { if_chain! { if let ExprKind::Index(ref array, ref index) = expr.kind; if is_vector(cx, array); @@ -87,13 +87,13 @@ fn is_vec_indexing<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'tcx>) None } -fn is_vector(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { +fn is_vector(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { let ty = cx.tables().expr_ty(expr); let ty = walk_ptrs_ty(ty); is_type_diagnostic_item(cx, ty, sym!(vec_type)) } -fn is_full_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { +fn is_full_range(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { let ty = cx.tables().expr_ty(expr); let ty = walk_ptrs_ty(ty); match_type(cx, ty, &utils::paths::RANGE_FULL) diff --git a/src/tools/clippy/clippy_lints/src/matches.rs b/src/tools/clippy/clippy_lints/src/matches.rs index 0c91d8885d9..b754a45aa40 100644 --- a/src/tools/clippy/clippy_lints/src/matches.rs +++ b/src/tools/clippy/clippy_lints/src/matches.rs @@ -430,8 +430,8 @@ impl_lint_pass!(Matches => [ REST_PAT_IN_FULLY_BOUND_STRUCTS ]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Matches { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for Matches { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if in_external_macro(cx.sess(), expr.span) { return; } @@ -455,7 +455,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Matches { } } - fn check_local(&mut self, cx: &LateContext<'a, 'tcx>, local: &'tcx Local<'_>) { + fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'_>) { if_chain! { if !in_external_macro(cx.sess(), local.span); if !in_macro(local.span); @@ -491,7 +491,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Matches { } } - fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat<'_>) { + fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) { if_chain! { if !in_external_macro(cx.sess(), pat.span); if !in_macro(pat.span); @@ -518,7 +518,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Matches { } #[rustfmt::skip] -fn check_single_match(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) { +fn check_single_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) { if arms.len() == 2 && arms[0].guard.is_none() && arms[1].guard.is_none() { if in_macro(expr.span) { // Don't lint match expressions present in @@ -549,7 +549,7 @@ fn check_single_match(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>], } fn check_single_match_single_pattern( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>, @@ -561,7 +561,7 @@ fn check_single_match_single_pattern( } fn report_single_match_single_pattern( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>, @@ -590,7 +590,7 @@ fn report_single_match_single_pattern( } fn check_single_match_opt_like( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>, @@ -630,7 +630,7 @@ fn check_single_match_opt_like( } } -fn check_match_bool(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) { +fn check_match_bool(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) { // Type of expression is `bool`. if cx.tables().expr_ty(ex).kind == ty::Bool { span_lint_and_then( @@ -694,7 +694,7 @@ fn check_match_bool(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>], e } } -fn check_overlapping_arms<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ex: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>]) { +fn check_overlapping_arms<'tcx>(cx: &LateContext<'tcx>, ex: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>]) { if arms.len() >= 2 && cx.tables().expr_ty(ex).is_integral() { let ranges = all_ranges(cx, arms, cx.tables().expr_ty(ex)); let type_ranges = type_ranges(&ranges); @@ -713,7 +713,7 @@ fn check_overlapping_arms<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ex: &'tcx Expr<' } } -fn check_wild_err_arm(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>]) { +fn check_wild_err_arm(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) { let ex_ty = walk_ptrs_ty(cx.tables().expr_ty(ex)); if is_type_diagnostic_item(cx, ex_ty, sym!(result_type)) { for arm in arms { @@ -754,7 +754,7 @@ fn check_wild_err_arm(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>]) } } -fn check_wild_enum_match(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>]) { +fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) { let ty = cx.tables().expr_ty(ex); if !ty.is_enum() { // If there isn't a nice closed set of possible values that can be conveniently enumerated, @@ -884,7 +884,7 @@ fn is_panic_block(block: &Block<'_>) -> bool { } } -fn check_match_ref_pats(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) { +fn check_match_ref_pats(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) { if has_only_ref_pats(arms) { let mut suggs = Vec::with_capacity(arms.len() + 1); let (title, msg) = if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, ref inner) = ex.kind { @@ -919,7 +919,7 @@ fn check_match_ref_pats(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_> } } -fn check_match_as_ref(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) { +fn check_match_as_ref(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) { if arms.len() == 2 && arms[0].guard.is_none() && arms[1].guard.is_none() { let arm_ref: Option<BindingAnnotation> = if is_none_arm(&arms[0]) { is_ref_some_arm(&arms[1]) @@ -971,7 +971,7 @@ fn check_match_as_ref(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>], } } -fn check_wild_in_or_pats(cx: &LateContext<'_, '_>, arms: &[Arm<'_>]) { +fn check_wild_in_or_pats(cx: &LateContext<'_>, arms: &[Arm<'_>]) { for arm in arms { if let PatKind::Or(ref fields) = arm.pat.kind { // look for multiple fields in this arm that contains at least one Wild pattern @@ -989,7 +989,7 @@ fn check_wild_in_or_pats(cx: &LateContext<'_, '_>, arms: &[Arm<'_>]) { } } -fn check_match_single_binding<'a>(cx: &LateContext<'_, 'a>, ex: &Expr<'a>, arms: &[Arm<'_>], expr: &Expr<'_>) { +fn check_match_single_binding<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], expr: &Expr<'_>) { if in_macro(expr.span) || arms.len() != 1 || is_refutable(cx, arms[0].pat) { return; } @@ -1085,7 +1085,7 @@ fn check_match_single_binding<'a>(cx: &LateContext<'_, 'a>, ex: &Expr<'a>, arms: } /// Returns true if the `ex` match expression is in a local (`let`) statement -fn opt_parent_let<'a>(cx: &LateContext<'_, 'a>, ex: &Expr<'a>) -> Option<&'a Local<'a>> { +fn opt_parent_let<'a>(cx: &LateContext<'a>, ex: &Expr<'a>) -> Option<&'a Local<'a>> { if_chain! { let map = &cx.tcx.hir(); if let Some(Node::Expr(parent_arm_expr)) = map.find(map.get_parent_node(ex.hir_id)); @@ -1098,11 +1098,7 @@ fn opt_parent_let<'a>(cx: &LateContext<'_, 'a>, ex: &Expr<'a>) -> Option<&'a Loc } /// Gets all arms that are unbounded `PatRange`s. -fn all_ranges<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - arms: &'tcx [Arm<'_>], - ty: Ty<'tcx>, -) -> Vec<SpannedRange<Constant>> { +fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) -> Vec<SpannedRange<Constant>> { arms.iter() .flat_map(|arm| { if let Arm { diff --git a/src/tools/clippy/clippy_lints/src/mem_discriminant.rs b/src/tools/clippy/clippy_lints/src/mem_discriminant.rs index d315c5ef89a..06c56851303 100644 --- a/src/tools/clippy/clippy_lints/src/mem_discriminant.rs +++ b/src/tools/clippy/clippy_lints/src/mem_discriminant.rs @@ -29,13 +29,13 @@ declare_clippy_lint! { declare_lint_pass!(MemDiscriminant => [MEM_DISCRIMINANT_NON_ENUM]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemDiscriminant { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for MemDiscriminant { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { if let ExprKind::Call(ref func, ref func_args) = expr.kind; // is `mem::discriminant` if let ExprKind::Path(ref func_qpath) = func.kind; - if let Some(def_id) = cx.tables().qpath_res(func_qpath, func.hir_id).opt_def_id(); + if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); if match_def_path(cx, def_id, &paths::MEM_DISCRIMINANT); // type is non-enum let ty_param = cx.tables().node_substs(func.hir_id).type_at(0); diff --git a/src/tools/clippy/clippy_lints/src/mem_forget.rs b/src/tools/clippy/clippy_lints/src/mem_forget.rs index 1821bd9135f..b895ba324c7 100644 --- a/src/tools/clippy/clippy_lints/src/mem_forget.rs +++ b/src/tools/clippy/clippy_lints/src/mem_forget.rs @@ -25,8 +25,8 @@ declare_clippy_lint! { declare_lint_pass!(MemForget => [MEM_FORGET]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemForget { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for MemForget { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if let ExprKind::Call(ref path_expr, ref args) = e.kind { if let ExprKind::Path(ref qpath) = path_expr.kind { if let Some(def_id) = qpath_res(cx, qpath, path_expr.hir_id).opt_def_id() { diff --git a/src/tools/clippy/clippy_lints/src/mem_replace.rs b/src/tools/clippy/clippy_lints/src/mem_replace.rs index 16d31fc8346..25f332cdcc2 100644 --- a/src/tools/clippy/clippy_lints/src/mem_replace.rs +++ b/src/tools/clippy/clippy_lints/src/mem_replace.rs @@ -97,7 +97,7 @@ declare_clippy_lint! { declare_lint_pass!(MemReplace => [MEM_REPLACE_OPTION_WITH_NONE, MEM_REPLACE_WITH_UNINIT, MEM_REPLACE_WITH_DEFAULT]); -fn check_replace_option_with_none(cx: &LateContext<'_, '_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) { +fn check_replace_option_with_none(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) { if let ExprKind::Path(ref replacement_qpath) = src.kind { // Check that second argument is `Option::None` if match_qpath(replacement_qpath, &paths::OPTION_NONE) { @@ -135,7 +135,7 @@ fn check_replace_option_with_none(cx: &LateContext<'_, '_>, src: &Expr<'_>, dest } } -fn check_replace_with_uninit(cx: &LateContext<'_, '_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) { +fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) { if_chain! { // check if replacement is mem::MaybeUninit::uninit().assume_init() if let Some(method_def_id) = cx.tables().type_dependent_def_id(src.hir_id); @@ -162,7 +162,7 @@ fn check_replace_with_uninit(cx: &LateContext<'_, '_>, src: &Expr<'_>, dest: &Ex if let ExprKind::Call(ref repl_func, ref repl_args) = src.kind; if repl_args.is_empty(); if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind; - if let Some(repl_def_id) = cx.tables().qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id(); + if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id(); then { if cx.tcx.is_diagnostic_item(sym::mem_uninitialized, repl_def_id) { let mut applicability = Applicability::MachineApplicable; @@ -193,12 +193,12 @@ fn check_replace_with_uninit(cx: &LateContext<'_, '_>, src: &Expr<'_>, dest: &Ex } } -fn check_replace_with_default(cx: &LateContext<'_, '_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) { +fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) { if let ExprKind::Call(ref repl_func, _) = src.kind { if_chain! { if !in_external_macro(cx.tcx.sess, expr_span); if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind; - if let Some(repl_def_id) = cx.tables().qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id(); + if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id(); if match_def_path(cx, repl_def_id, &paths::DEFAULT_TRAIT_METHOD); then { span_lint_and_then( @@ -224,13 +224,13 @@ fn check_replace_with_default(cx: &LateContext<'_, '_>, src: &Expr<'_>, dest: &E } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemReplace { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for MemReplace { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { // Check that `expr` is a call to `mem::replace()` if let ExprKind::Call(ref func, ref func_args) = expr.kind; if let ExprKind::Path(ref func_qpath) = func.kind; - if let Some(def_id) = cx.tables().qpath_res(func_qpath, func.hir_id).opt_def_id(); + if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); if match_def_path(cx, def_id, &paths::MEM_REPLACE); if let [dest, src] = &**func_args; then { diff --git a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs index 092702c8b8c..fcf7b509ead 100644 --- a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs @@ -77,7 +77,7 @@ pub(crate) trait BindInsteadOfMap { } fn lint_closure_autofixable( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>], closure_expr: &hir::Expr<'_>, @@ -120,7 +120,7 @@ pub(crate) trait BindInsteadOfMap { } } - fn lint_closure(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, closure_expr: &hir::Expr<'_>) { + fn lint_closure(cx: &LateContext<'_>, expr: &hir::Expr<'_>, closure_expr: &hir::Expr<'_>) { let mut suggs = Vec::new(); let can_sugg = find_all_ret_expressions(cx, closure_expr, |ret_expr| { if_chain! { @@ -156,7 +156,7 @@ pub(crate) trait BindInsteadOfMap { } /// Lint use of `_.and_then(|x| Some(y))` for `Option`s - fn lint(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { + fn lint(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { if !match_type(cx, cx.tables().expr_ty(&args[0]), Self::TYPE_QPATH) { return; } @@ -216,7 +216,7 @@ fn contains_try(expr: &hir::Expr<'_>) -> bool { visitor.found } -fn find_all_ret_expressions<'hir, F>(_cx: &LateContext<'_, '_>, expr: &'hir hir::Expr<'hir>, callback: F) -> bool +fn find_all_ret_expressions<'hir, F>(_cx: &LateContext<'_>, expr: &'hir hir::Expr<'hir>, callback: F) -> bool where F: FnMut(&'hir hir::Expr<'hir>) -> bool, { diff --git a/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs b/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs index d29b9adcb7d..1c0018a5b95 100644 --- a/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs +++ b/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs @@ -9,7 +9,7 @@ use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; /// Checks for the `INEFFICIENT_TO_STRING` lint -pub fn lint<'tcx>(cx: &LateContext<'_, 'tcx>, expr: &hir::Expr<'_>, arg: &hir::Expr<'_>, arg_ty: Ty<'tcx>) { +pub fn lint<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, arg: &hir::Expr<'_>, arg_ty: Ty<'tcx>) { if_chain! { if let Some(to_string_meth_did) = cx.tables().type_dependent_def_id(expr.hir_id); if match_def_path(cx, to_string_meth_did, &paths::TO_STRING_METHOD); @@ -45,7 +45,7 @@ pub fn lint<'tcx>(cx: &LateContext<'_, 'tcx>, expr: &hir::Expr<'_>, arg: &hir::E /// Returns whether `ty` specializes `ToString`. /// Currently, these are `str`, `String`, and `Cow<'_, str>`. -fn specializes_tostring(cx: &LateContext<'_, '_>, ty: Ty<'_>) -> bool { +fn specializes_tostring(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { if let ty::Str = ty.kind { return true; } diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs b/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs index eb02314f468..9c04b6d57b9 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs @@ -6,7 +6,7 @@ use rustc_hir as hir; use rustc_lint::LateContext; use rustc_target::abi::LayoutOf; -pub fn lint(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, args: &[&[hir::Expr<'_>]], arith: &str) { +pub fn lint(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[&[hir::Expr<'_>]], arith: &str) { let unwrap_arg = &args[0][1]; let arith_lhs = &args[1][0]; let arith_rhs = &args[1][1]; @@ -85,7 +85,7 @@ enum MinMax { Max, } -fn is_min_or_max<'tcx>(cx: &LateContext<'_, 'tcx>, expr: &hir::Expr<'_>) -> Option<MinMax> { +fn is_min_or_max<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) -> Option<MinMax> { // `T::max_value()` `T::min_value()` inherent methods if_chain! { if let hir::ExprKind::Call(func, args) = &expr.kind; diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index c4e707ecf03..216db12f011 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -1357,9 +1357,9 @@ declare_lint_pass!(Methods => [ OPTION_AS_REF_DEREF, ]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { +impl<'tcx> LateLintPass<'tcx> for Methods { #[allow(clippy::too_many_lines)] - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { if in_macro(expr.span) { return; } @@ -1471,7 +1471,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { } } - fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx hir::ImplItem<'_>) { + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) { if in_external_macro(cx.sess(), impl_item.span) { return; } @@ -1585,8 +1585,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { /// Checks for the `OR_FUN_CALL` lint. #[allow(clippy::too_many_lines)] -fn lint_or_fun_call<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn lint_or_fun_call<'tcx>( + cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, method_span: Span, name: &str, @@ -1594,7 +1594,7 @@ fn lint_or_fun_call<'a, 'tcx>( ) { // Searches an expression for method calls or function calls that aren't ctors struct FunCallFinder<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, found: bool, } @@ -1625,7 +1625,7 @@ fn lint_or_fun_call<'a, 'tcx>( /// Checks for `unwrap_or(T::new())` or `unwrap_or(T::default())`. fn check_unwrap_or_default( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, name: &str, fun: &hir::Expr<'_>, self_expr: &hir::Expr<'_>, @@ -1667,8 +1667,8 @@ fn lint_or_fun_call<'a, 'tcx>( /// Checks for `*or(foo())`. #[allow(clippy::too_many_arguments)] - fn check_general_case<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, + fn check_general_case<'tcx>( + cx: &LateContext<'tcx>, name: &str, method_span: Span, fun_span: Span, @@ -1769,7 +1769,7 @@ fn lint_or_fun_call<'a, 'tcx>( /// Checks for the `EXPECT_FUN_CALL` lint. #[allow(clippy::too_many_lines)] fn lint_expect_fun_call( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_span: Span, name: &str, @@ -1777,7 +1777,7 @@ fn lint_expect_fun_call( ) { // Strip `&`, `as_ref()` and `as_str()` off `arg` until we're left with either a `String` or // `&str` - fn get_arg_root<'a>(cx: &LateContext<'_, '_>, arg: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { + fn get_arg_root<'a>(cx: &LateContext<'_>, arg: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { let mut arg_root = arg; loop { arg_root = match &arg_root.kind { @@ -1804,7 +1804,7 @@ fn lint_expect_fun_call( // Only `&'static str` or `String` can be used directly in the `panic!`. Other types should be // converted to string. - fn requires_to_string(cx: &LateContext<'_, '_>, arg: &hir::Expr<'_>) -> bool { + fn requires_to_string(cx: &LateContext<'_>, arg: &hir::Expr<'_>) -> bool { let arg_ty = cx.tables().expr_ty(arg); if is_type_diagnostic_item(cx, arg_ty, sym!(string_type)) { return false; @@ -1819,12 +1819,12 @@ fn lint_expect_fun_call( // Check if an expression could have type `&'static str`, knowing that it // has type `&str` for some lifetime. - fn can_be_static_str(cx: &LateContext<'_, '_>, arg: &hir::Expr<'_>) -> bool { + fn can_be_static_str(cx: &LateContext<'_>, arg: &hir::Expr<'_>) -> bool { match arg.kind { hir::ExprKind::Lit(_) => true, hir::ExprKind::Call(fun, _) => { if let hir::ExprKind::Path(ref p) = fun.kind { - match cx.tables().qpath_res(p, fun.hir_id) { + match cx.qpath_res(p, fun.hir_id) { hir::def::Res::Def(hir::def::DefKind::Fn | hir::def::DefKind::AssocFn, def_id) => matches!( cx.tcx.fn_sig(def_id).output().skip_binder().kind, ty::Ref(ty::ReStatic, ..) @@ -1844,7 +1844,7 @@ fn lint_expect_fun_call( ty::Ref(ty::ReStatic, ..) ) }), - hir::ExprKind::Path(ref p) => match cx.tables().qpath_res(p, arg.hir_id) { + hir::ExprKind::Path(ref p) => match cx.qpath_res(p, arg.hir_id) { hir::def::Res::Def(hir::def::DefKind::Const | hir::def::DefKind::Static, _) => true, _ => false, }, @@ -1853,7 +1853,7 @@ fn lint_expect_fun_call( } fn generate_format_arg_snippet( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, a: &hir::Expr<'_>, applicability: &mut Applicability, ) -> Vec<String> { @@ -1956,7 +1956,7 @@ fn lint_expect_fun_call( } /// Checks for the `CLONE_ON_COPY` lint. -fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, arg: &hir::Expr<'_>, arg_ty: Ty<'_>) { +fn lint_clone_on_copy(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr<'_>, arg_ty: Ty<'_>) { let ty = cx.tables().expr_ty(expr); if let ty::Ref(_, inner, _) = arg_ty.kind { if let ty::Ref(_, innermost, _) = inner.kind { @@ -2050,7 +2050,7 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, arg: &hir: } } -fn lint_clone_on_ref_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, arg: &hir::Expr<'_>) { +fn lint_clone_on_ref_ptr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr<'_>) { let obj_ty = walk_ptrs_ty(cx.tables().expr_ty(arg)); if let ty::Adt(_, subst) = obj_ty.kind { @@ -2081,7 +2081,7 @@ fn lint_clone_on_ref_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, arg: &h } } -fn lint_string_extend(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { +fn lint_string_extend(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { let arg = &args[1]; if let Some(arglists) = method_chain_args(arg, &["chars"]) { let target = &arglists[0][0]; @@ -2112,14 +2112,14 @@ fn lint_string_extend(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, args: &[hi } } -fn lint_extend(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { +fn lint_extend(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { let obj_ty = walk_ptrs_ty(cx.tables().expr_ty(&args[0])); if is_type_diagnostic_item(cx, obj_ty, sym!(string_type)) { lint_string_extend(cx, expr, args); } } -fn lint_cstring_as_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, source: &hir::Expr<'_>, unwrap: &hir::Expr<'_>) { +fn lint_cstring_as_ptr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, source: &hir::Expr<'_>, unwrap: &hir::Expr<'_>) { if_chain! { let source_type = cx.tables().expr_ty(source); if let ty::Adt(def, substs) = source_type.kind; @@ -2139,11 +2139,7 @@ fn lint_cstring_as_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, source: & } } -fn lint_iter_cloned_collect<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &hir::Expr<'_>, - iter_args: &'tcx [hir::Expr<'_>], -) { +fn lint_iter_cloned_collect<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, iter_args: &'tcx [hir::Expr<'_>]) { if_chain! { if is_type_diagnostic_item(cx, cx.tables().expr_ty(expr), sym!(vec_type)); if let Some(slice) = derefs_to_slice(cx, &iter_args[0], cx.tables().expr_ty(&iter_args[0])); @@ -2164,9 +2160,9 @@ fn lint_iter_cloned_collect<'a, 'tcx>( } } -fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, fold_args: &[hir::Expr<'_>], fold_span: Span) { +fn lint_unnecessary_fold(cx: &LateContext<'_>, expr: &hir::Expr<'_>, fold_args: &[hir::Expr<'_>], fold_span: Span) { fn check_fold_with_op( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, expr: &hir::Expr<'_>, fold_args: &[hir::Expr<'_>], fold_span: Span, @@ -2251,7 +2247,7 @@ fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, fold_ar } } -fn lint_step_by<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &hir::Expr<'_>, args: &'tcx [hir::Expr<'_>]) { +fn lint_step_by<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, args: &'tcx [hir::Expr<'_>]) { if match_trait_method(cx, expr, &paths::ITERATOR) { if let Some((Constant::Int(0), _)) = constant(cx, cx.tables(), &args[1]) { span_lint( @@ -2264,7 +2260,7 @@ fn lint_step_by<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &hir::Expr<'_>, args } } -fn lint_iter_next<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>, iter_args: &'tcx [hir::Expr<'_>]) { +fn lint_iter_next<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, iter_args: &'tcx [hir::Expr<'_>]) { let caller_expr = &iter_args[0]; // Skip lint if the `iter().next()` expression is a for loop argument, @@ -2318,8 +2314,8 @@ fn lint_iter_next<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_ } } -fn lint_iter_nth<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn lint_iter_nth<'tcx>( + cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, nth_and_iter_args: &[&'tcx [hir::Expr<'tcx>]], is_mut: bool, @@ -2348,7 +2344,7 @@ fn lint_iter_nth<'a, 'tcx>( ); } -fn lint_iter_nth_zero<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &hir::Expr<'_>, nth_args: &'tcx [hir::Expr<'_>]) { +fn lint_iter_nth_zero<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, nth_args: &'tcx [hir::Expr<'_>]) { if_chain! { if match_trait_method(cx, expr, &paths::ITERATOR); if let Some((Constant::Int(0), _)) = constant(cx, cx.tables(), &nth_args[1]); @@ -2367,12 +2363,7 @@ fn lint_iter_nth_zero<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &hir::Expr<'_> } } -fn lint_get_unwrap<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &hir::Expr<'_>, - get_args: &'tcx [hir::Expr<'_>], - is_mut: bool, -) { +fn lint_get_unwrap<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, get_args: &'tcx [hir::Expr<'_>], is_mut: bool) { // Note: we don't want to lint `get_mut().unwrap` for `HashMap` or `BTreeMap`, // because they do not implement `IndexMut` let mut applicability = Applicability::MachineApplicable; @@ -2445,7 +2436,7 @@ fn lint_get_unwrap<'a, 'tcx>( ); } -fn lint_iter_skip_next(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>) { +fn lint_iter_skip_next(cx: &LateContext<'_>, expr: &hir::Expr<'_>) { // lint if caller of skip is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { span_lint_and_help( @@ -2459,12 +2450,12 @@ fn lint_iter_skip_next(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>) { } } -fn derefs_to_slice<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn derefs_to_slice<'tcx>( + cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, ty: Ty<'tcx>, ) -> Option<&'tcx hir::Expr<'tcx>> { - fn may_slice<'a>(cx: &LateContext<'_, 'a>, ty: Ty<'a>) -> bool { + fn may_slice<'a>(cx: &LateContext<'a>, ty: Ty<'a>) -> bool { match ty.kind { ty::Slice(_) => true, ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()), @@ -2504,7 +2495,7 @@ fn derefs_to_slice<'a, 'tcx>( } /// lint use of `unwrap()` for `Option`s and `Result`s -fn lint_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, unwrap_args: &[hir::Expr<'_>]) { +fn lint_unwrap(cx: &LateContext<'_>, expr: &hir::Expr<'_>, unwrap_args: &[hir::Expr<'_>]) { let obj_ty = walk_ptrs_ty(cx.tables().expr_ty(&unwrap_args[0])); let mess = if is_type_diagnostic_item(cx, obj_ty, sym!(option_type)) { @@ -2532,7 +2523,7 @@ fn lint_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, unwrap_args: &[hi } /// lint use of `expect()` for `Option`s and `Result`s -fn lint_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, expect_args: &[hir::Expr<'_>]) { +fn lint_expect(cx: &LateContext<'_>, expr: &hir::Expr<'_>, expect_args: &[hir::Expr<'_>]) { let obj_ty = walk_ptrs_ty(cx.tables().expr_ty(&expect_args[0])); let mess = if is_type_diagnostic_item(cx, obj_ty, sym!(option_type)) { @@ -2556,7 +2547,7 @@ fn lint_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, expect_args: &[hi } /// lint use of `ok().expect()` for `Result`s -fn lint_ok_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, ok_args: &[hir::Expr<'_>]) { +fn lint_ok_expect(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ok_args: &[hir::Expr<'_>]) { if_chain! { // lint if the caller of `ok()` is a `Result` if is_type_diagnostic_item(cx, cx.tables().expr_ty(&ok_args[0]), sym!(result_type)); @@ -2578,7 +2569,7 @@ fn lint_ok_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, ok_args: &[hir } /// lint use of `map().flatten()` for `Iterators` and 'Options' -fn lint_map_flatten<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>, map_args: &'tcx [hir::Expr<'_>]) { +fn lint_map_flatten<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map_args: &'tcx [hir::Expr<'_>]) { // lint if caller of `.map().flatten()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `map(..).flatten()` on an `Iterator`. \ @@ -2617,8 +2608,8 @@ fn lint_map_flatten<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr< } /// lint use of `map().unwrap_or_else()` for `Option`s and `Result`s -fn lint_map_unwrap_or_else<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn lint_map_unwrap_or_else<'tcx>( + cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map_args: &'tcx [hir::Expr<'_>], unwrap_args: &'tcx [hir::Expr<'_>], @@ -2674,11 +2665,7 @@ fn lint_map_unwrap_or_else<'a, 'tcx>( } /// lint use of `_.map_or(None, _)` for `Option`s and `Result`s -fn lint_map_or_none<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &'tcx hir::Expr<'_>, - map_or_args: &'tcx [hir::Expr<'_>], -) { +fn lint_map_or_none<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map_or_args: &'tcx [hir::Expr<'_>]) { let is_option = is_type_diagnostic_item(cx, cx.tables().expr_ty(&map_or_args[0]), sym!(option_type)); let is_result = is_type_diagnostic_item(cx, cx.tables().expr_ty(&map_or_args[0]), sym!(result_type)); @@ -2748,11 +2735,7 @@ fn lint_map_or_none<'a, 'tcx>( } /// lint use of `filter().next()` for `Iterators` -fn lint_filter_next<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &'tcx hir::Expr<'_>, - filter_args: &'tcx [hir::Expr<'_>], -) { +fn lint_filter_next<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, filter_args: &'tcx [hir::Expr<'_>]) { // lint if caller of `.filter().next()` is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling \ @@ -2775,8 +2758,8 @@ fn lint_filter_next<'a, 'tcx>( } /// lint use of `skip_while().next()` for `Iterators` -fn lint_skip_while_next<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn lint_skip_while_next<'tcx>( + cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, _skip_while_args: &'tcx [hir::Expr<'_>], ) { @@ -2794,8 +2777,8 @@ fn lint_skip_while_next<'a, 'tcx>( } /// lint use of `filter().map()` for `Iterators` -fn lint_filter_map<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn lint_filter_map<'tcx>( + cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, _filter_args: &'tcx [hir::Expr<'_>], _map_args: &'tcx [hir::Expr<'_>], @@ -2809,11 +2792,7 @@ fn lint_filter_map<'a, 'tcx>( } /// lint use of `filter_map().next()` for `Iterators` -fn lint_filter_map_next<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &'tcx hir::Expr<'_>, - filter_args: &'tcx [hir::Expr<'_>], -) { +fn lint_filter_map_next<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, filter_args: &'tcx [hir::Expr<'_>]) { if match_trait_method(cx, expr, &paths::ITERATOR) { let msg = "called `filter_map(p).next()` on an `Iterator`. This is more succinctly expressed by calling \ `.find_map(p)` instead."; @@ -2834,8 +2813,8 @@ fn lint_filter_map_next<'a, 'tcx>( } /// lint use of `find().map()` for `Iterators` -fn lint_find_map<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn lint_find_map<'tcx>( + cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, _find_args: &'tcx [hir::Expr<'_>], map_args: &'tcx [hir::Expr<'_>], @@ -2849,8 +2828,8 @@ fn lint_find_map<'a, 'tcx>( } /// lint use of `filter_map().map()` for `Iterators` -fn lint_filter_map_map<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn lint_filter_map_map<'tcx>( + cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, _filter_args: &'tcx [hir::Expr<'_>], _map_args: &'tcx [hir::Expr<'_>], @@ -2864,8 +2843,8 @@ fn lint_filter_map_map<'a, 'tcx>( } /// lint use of `filter().flat_map()` for `Iterators` -fn lint_filter_flat_map<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn lint_filter_flat_map<'tcx>( + cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, _filter_args: &'tcx [hir::Expr<'_>], _map_args: &'tcx [hir::Expr<'_>], @@ -2880,8 +2859,8 @@ fn lint_filter_flat_map<'a, 'tcx>( } /// lint use of `filter_map().flat_map()` for `Iterators` -fn lint_filter_map_flat_map<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn lint_filter_map_flat_map<'tcx>( + cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, _filter_args: &'tcx [hir::Expr<'_>], _map_args: &'tcx [hir::Expr<'_>], @@ -2896,8 +2875,8 @@ fn lint_filter_map_flat_map<'a, 'tcx>( } /// lint use of `flat_map` for `Iterators` where `flatten` would be sufficient -fn lint_flat_map_identity<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn lint_flat_map_identity<'tcx>( + cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, flat_map_args: &'tcx [hir::Expr<'_>], flat_map_span: Span, @@ -2945,8 +2924,8 @@ fn lint_flat_map_identity<'a, 'tcx>( } /// lint searching an Iterator followed by `is_some()` -fn lint_search_is_some<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn lint_search_is_some<'tcx>( + cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, search_method: &str, search_args: &'tcx [hir::Expr<'_>], @@ -3010,7 +2989,7 @@ struct BinaryExprInfo<'a> { } /// Checks for the `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints. -fn lint_binary_expr_with_method_call(cx: &LateContext<'_, '_>, info: &mut BinaryExprInfo<'_>) { +fn lint_binary_expr_with_method_call(cx: &LateContext<'_>, info: &mut BinaryExprInfo<'_>) { macro_rules! lint_with_both_lhs_and_rhs { ($func:ident, $cx:expr, $info:ident) => { if !$func($cx, $info) { @@ -3030,7 +3009,7 @@ fn lint_binary_expr_with_method_call(cx: &LateContext<'_, '_>, info: &mut Binary /// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints. fn lint_chars_cmp( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, info: &BinaryExprInfo<'_>, chain_methods: &[&str], lint: &'static Lint, @@ -3073,12 +3052,12 @@ fn lint_chars_cmp( } /// Checks for the `CHARS_NEXT_CMP` lint. -fn lint_chars_next_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool { +fn lint_chars_next_cmp<'tcx>(cx: &LateContext<'tcx>, info: &BinaryExprInfo<'_>) -> bool { lint_chars_cmp(cx, info, &["chars", "next"], CHARS_NEXT_CMP, "starts_with") } /// Checks for the `CHARS_LAST_CMP` lint. -fn lint_chars_last_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool { +fn lint_chars_last_cmp<'tcx>(cx: &LateContext<'tcx>, info: &BinaryExprInfo<'_>) -> bool { if lint_chars_cmp(cx, info, &["chars", "last"], CHARS_LAST_CMP, "ends_with") { true } else { @@ -3087,8 +3066,8 @@ fn lint_chars_last_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprIn } /// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints with `unwrap()`. -fn lint_chars_cmp_with_unwrap<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn lint_chars_cmp_with_unwrap<'tcx>( + cx: &LateContext<'tcx>, info: &BinaryExprInfo<'_>, chain_methods: &[&str], lint: &'static Lint, @@ -3122,12 +3101,12 @@ fn lint_chars_cmp_with_unwrap<'a, 'tcx>( } /// Checks for the `CHARS_NEXT_CMP` lint with `unwrap()`. -fn lint_chars_next_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool { +fn lint_chars_next_cmp_with_unwrap<'tcx>(cx: &LateContext<'tcx>, info: &BinaryExprInfo<'_>) -> bool { lint_chars_cmp_with_unwrap(cx, info, &["chars", "next", "unwrap"], CHARS_NEXT_CMP, "starts_with") } /// Checks for the `CHARS_LAST_CMP` lint with `unwrap()`. -fn lint_chars_last_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool { +fn lint_chars_last_cmp_with_unwrap<'tcx>(cx: &LateContext<'tcx>, info: &BinaryExprInfo<'_>) -> bool { if lint_chars_cmp_with_unwrap(cx, info, &["chars", "last", "unwrap"], CHARS_LAST_CMP, "ends_with") { true } else { @@ -3136,11 +3115,7 @@ fn lint_chars_last_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: & } /// lint for length-1 `str`s for methods in `PATTERN_METHODS` -fn lint_single_char_pattern<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - _expr: &'tcx hir::Expr<'_>, - arg: &'tcx hir::Expr<'_>, -) { +fn lint_single_char_pattern<'tcx>(cx: &LateContext<'tcx>, _expr: &'tcx hir::Expr<'_>, arg: &'tcx hir::Expr<'_>) { if_chain! { if let hir::ExprKind::Lit(lit) = &arg.kind; if let ast::LitKind::Str(r, style) = lit.node; @@ -3171,7 +3146,7 @@ fn lint_single_char_pattern<'a, 'tcx>( } /// Checks for the `USELESS_ASREF` lint. -fn lint_asref(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, call_name: &str, as_ref_args: &[hir::Expr<'_>]) { +fn lint_asref(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str, as_ref_args: &[hir::Expr<'_>]) { // when we get here, we've already checked that the call name is "as_ref" or "as_mut" // check if the call is to the actual `AsRef` or `AsMut` trait if match_trait_method(cx, expr, &paths::ASREF_TRAIT) || match_trait_method(cx, expr, &paths::ASMUT_TRAIT) { @@ -3206,7 +3181,7 @@ fn lint_asref(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, call_name: &str, a } } -fn ty_has_iter_method(cx: &LateContext<'_, '_>, self_ref_ty: Ty<'_>) -> Option<(&'static str, &'static str)> { +fn ty_has_iter_method(cx: &LateContext<'_>, self_ref_ty: Ty<'_>) -> Option<(&'static str, &'static str)> { has_iter_method(cx, self_ref_ty).map(|ty_name| { let mutbl = match self_ref_ty.kind { ty::Ref(_, _, mutbl) => mutbl, @@ -3220,7 +3195,7 @@ fn ty_has_iter_method(cx: &LateContext<'_, '_>, self_ref_ty: Ty<'_>) -> Option<( }) } -fn lint_into_iter(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, self_ref_ty: Ty<'_>, method_span: Span) { +fn lint_into_iter(cx: &LateContext<'_>, expr: &hir::Expr<'_>, self_ref_ty: Ty<'_>, method_span: Span) { if !match_trait_method(cx, expr, &paths::INTO_ITERATOR) { return; } @@ -3241,7 +3216,7 @@ fn lint_into_iter(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, self_ref_ty: T } /// lint for `MaybeUninit::uninit().assume_init()` (we already have the latter) -fn lint_maybe_uninit(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, outer: &hir::Expr<'_>) { +fn lint_maybe_uninit(cx: &LateContext<'_>, expr: &hir::Expr<'_>, outer: &hir::Expr<'_>) { if_chain! { if let hir::ExprKind::Call(ref callee, ref args) = expr.kind; if args.is_empty(); @@ -3259,7 +3234,7 @@ fn lint_maybe_uninit(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, outer: &hir } } -fn is_maybe_uninit_ty_valid(cx: &LateContext<'_, '_>, ty: Ty<'_>) -> bool { +fn is_maybe_uninit_ty_valid(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { match ty.kind { ty::Array(ref component, _) => is_maybe_uninit_ty_valid(cx, component), ty::Tuple(ref types) => types.types().all(|ty| is_maybe_uninit_ty_valid(cx, ty)), @@ -3268,7 +3243,7 @@ fn is_maybe_uninit_ty_valid(cx: &LateContext<'_, '_>, ty: Ty<'_>) -> bool { } } -fn lint_suspicious_map(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>) { +fn lint_suspicious_map(cx: &LateContext<'_>, expr: &hir::Expr<'_>) { span_lint_and_help( cx, SUSPICIOUS_MAP, @@ -3280,8 +3255,8 @@ fn lint_suspicious_map(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>) { } /// lint use of `_.as_ref().map(Deref::deref)` for `Option`s -fn lint_option_as_ref_deref<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn lint_option_as_ref_deref<'tcx>( + cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, as_ref_args: &[hir::Expr<'_>], map_args: &[hir::Expr<'_>], @@ -3317,7 +3292,7 @@ fn lint_option_as_ref_deref<'a, 'tcx>( if_chain! { if args.len() == 1; if let hir::ExprKind::Path(qpath) = &args[0].kind; - if let hir::def::Res::Local(local_id) = cx.tables().qpath_res(qpath, args[0].hir_id); + if let hir::def::Res::Local(local_id) = cx.qpath_res(qpath, args[0].hir_id); if closure_body.params[0].pat.hir_id == local_id; let adj = cx.tables().expr_adjustments(&args[0]).iter().map(|x| &x.kind).collect::<Box<[_]>>(); if let [ty::adjustment::Adjust::Deref(None), ty::adjustment::Adjust::Borrow(_)] = *adj; @@ -3334,7 +3309,7 @@ fn lint_option_as_ref_deref<'a, 'tcx>( if let hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner1) = inner.kind; if let hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner2) = inner1.kind; if let hir::ExprKind::Path(ref qpath) = inner2.kind; - if let hir::def::Res::Local(local_id) = cx.tables().qpath_res(qpath, inner2.hir_id); + if let hir::def::Res::Local(local_id) = cx.qpath_res(qpath, inner2.hir_id); then { closure_body.params[0].pat.hir_id == local_id } else { @@ -3376,7 +3351,7 @@ fn lint_option_as_ref_deref<'a, 'tcx>( } /// Given a `Result<T, E>` type, return its error type (`E`). -fn get_error_type<'a>(cx: &LateContext<'_, '_>, ty: Ty<'a>) -> Option<Ty<'a>> { +fn get_error_type<'a>(cx: &LateContext<'_>, ty: Ty<'a>) -> Option<Ty<'a>> { match ty.kind { ty::Adt(_, substs) if is_type_diagnostic_item(cx, ty, sym!(result_type)) => substs.types().nth(1), _ => None, @@ -3384,7 +3359,7 @@ fn get_error_type<'a>(cx: &LateContext<'_, '_>, ty: Ty<'a>) -> Option<Ty<'a>> { } /// This checks whether a given type is known to implement Debug. -fn has_debug_impl<'a, 'b>(ty: Ty<'a>, cx: &LateContext<'b, 'a>) -> bool { +fn has_debug_impl<'tcx>(ty: Ty<'tcx>, cx: &LateContext<'tcx>) -> bool { cx.tcx .get_diagnostic_item(sym::debug_trait) .map_or(false, |debug| implements_trait(cx, ty, debug, &[])) @@ -3477,8 +3452,8 @@ enum SelfKind { } impl SelfKind { - fn matches<'a>(self, cx: &LateContext<'_, 'a>, parent_ty: Ty<'a>, ty: Ty<'a>) -> bool { - fn matches_value<'a>(cx: &LateContext<'_, 'a>, parent_ty: Ty<'_>, ty: Ty<'_>) -> bool { + fn matches<'a>(self, cx: &LateContext<'a>, parent_ty: Ty<'a>, ty: Ty<'a>) -> bool { + fn matches_value<'a>(cx: &LateContext<'a>, parent_ty: Ty<'_>, ty: Ty<'_>) -> bool { if ty == parent_ty { true } else if ty.is_box() { @@ -3494,12 +3469,7 @@ impl SelfKind { } } - fn matches_ref<'a>( - cx: &LateContext<'_, 'a>, - mutability: hir::Mutability, - parent_ty: Ty<'a>, - ty: Ty<'a>, - ) -> bool { + fn matches_ref<'a>(cx: &LateContext<'a>, mutability: hir::Mutability, parent_ty: Ty<'a>, ty: Ty<'a>) -> bool { if let ty::Ref(_, t, m) = ty.kind { return m == mutability && t == parent_ty; } @@ -3563,7 +3533,7 @@ enum OutType { } impl OutType { - fn matches(self, cx: &LateContext<'_, '_>, ty: &hir::FnRetTy<'_>) -> bool { + fn matches(self, cx: &LateContext<'_>, ty: &hir::FnRetTy<'_>) -> bool { let is_unit = |ty: &hir::Ty<'_>| SpanlessEq::new(cx).eq_ty_kind(&ty.kind, &hir::TyKind::Tup(&[])); match (self, ty) { (Self::Unit, &hir::FnRetTy::DefaultReturn(_)) => true, @@ -3614,7 +3584,7 @@ fn contains_return(expr: &hir::Expr<'_>) -> bool { visitor.found } -fn check_pointer_offset(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { +fn check_pointer_offset(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { if_chain! { if args.len() == 2; if let ty::RawPtr(ty::TypeAndMut { ref ty, .. }) = cx.tables().expr_ty(&args[0]).kind; @@ -3626,7 +3596,7 @@ fn check_pointer_offset(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, args: &[ } } -fn lint_filetype_is_file(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { +fn lint_filetype_is_file(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { let ty = cx.tables().expr_ty(&args[0]); if !match_type(cx, ty, &paths::FILE_TYPE) { diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs index 7f4529a5870..672eb75c57f 100644 --- a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -12,8 +12,8 @@ use rustc_span::symbol::Symbol; use super::MAP_UNWRAP_OR; /// lint use of `map().unwrap_or()` for `Option`s -pub(super) fn lint<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +pub(super) fn lint<'tcx>( + cx: &LateContext<'tcx>, expr: &rustc_hir::Expr<'_>, map_args: &'tcx [rustc_hir::Expr<'_>], unwrap_args: &'tcx [rustc_hir::Expr<'_>], @@ -87,7 +87,7 @@ pub(super) fn lint<'a, 'tcx>( } struct UnwrapVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, identifiers: FxHashSet<Symbol>, } @@ -105,7 +105,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrapVisitor<'a, 'tcx> { } struct MapExprVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, identifiers: FxHashSet<Symbol>, found_identifier: bool, } diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs index 88243a88d9d..fdcba110542 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -11,7 +11,7 @@ use if_chain::if_chain; use super::UNNECESSARY_FILTER_MAP; -pub(super) fn lint(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { +pub(super) fn lint(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { if !match_trait_method(cx, expr, &paths::ITERATOR) { return; } @@ -52,11 +52,7 @@ pub(super) fn lint(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, args: &[hir:: } // returns (found_mapping, found_filtering) -fn check_expression<'a, 'tcx>( - cx: &'a LateContext<'a, 'tcx>, - arg_id: hir::HirId, - expr: &'tcx hir::Expr<'_>, -) -> (bool, bool) { +fn check_expression<'tcx>(cx: &LateContext<'tcx>, arg_id: hir::HirId, expr: &'tcx hir::Expr<'_>) -> (bool, bool) { match &expr.kind { hir::ExprKind::Call(ref func, ref args) => { if_chain! { @@ -65,7 +61,7 @@ fn check_expression<'a, 'tcx>( if match_qpath(path, &paths::OPTION_SOME) { if_chain! { if let hir::ExprKind::Path(path) = &args[0].kind; - if let Res::Local(ref local) = cx.tables().qpath_res(path, args[0].hir_id); + if let Res::Local(ref local) = cx.qpath_res(path, args[0].hir_id); then { if arg_id == *local { return (false, false) @@ -104,7 +100,7 @@ fn check_expression<'a, 'tcx>( } struct ReturnVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, arg_id: hir::HirId, // Found a non-None return that isn't Some(input) found_mapping: bool, @@ -113,7 +109,7 @@ struct ReturnVisitor<'a, 'tcx> { } impl<'a, 'tcx> ReturnVisitor<'a, 'tcx> { - fn new(cx: &'a LateContext<'a, 'tcx>, arg_id: hir::HirId) -> ReturnVisitor<'a, 'tcx> { + fn new(cx: &'a LateContext<'tcx>, arg_id: hir::HirId) -> ReturnVisitor<'a, 'tcx> { ReturnVisitor { cx, arg_id, diff --git a/src/tools/clippy/clippy_lints/src/minmax.rs b/src/tools/clippy/clippy_lints/src/minmax.rs index 8e6f3925d66..0a2d577396a 100644 --- a/src/tools/clippy/clippy_lints/src/minmax.rs +++ b/src/tools/clippy/clippy_lints/src/minmax.rs @@ -27,8 +27,8 @@ declare_clippy_lint! { declare_lint_pass!(MinMaxPass => [MIN_MAX]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MinMaxPass { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for MinMaxPass { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let Some((outer_max, outer_c, oe)) = min_max(cx, expr) { if let Some((inner_max, inner_c, ie)) = min_max(cx, oe) { if outer_max == inner_max { @@ -59,7 +59,7 @@ enum MinMax { Max, } -fn min_max<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr<'a>) -> Option<(MinMax, Constant, &'a Expr<'a>)> { +fn min_max<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(MinMax, Constant, &'a Expr<'a>)> { if let ExprKind::Call(ref path, ref args) = expr.kind { if let ExprKind::Path(ref qpath) = path.kind { cx.tables() @@ -82,11 +82,7 @@ fn min_max<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr<'a>) -> Option<(MinMax, } } -fn fetch_const<'a>( - cx: &LateContext<'_, '_>, - args: &'a [Expr<'a>], - m: MinMax, -) -> Option<(MinMax, Constant, &'a Expr<'a>)> { +fn fetch_const<'a>(cx: &LateContext<'_>, args: &'a [Expr<'a>], m: MinMax) -> Option<(MinMax, Constant, &'a Expr<'a>)> { if args.len() != 2 { return None; } diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs index 99cd864cae4..d7e1a62a19d 100644 --- a/src/tools/clippy/clippy_lints/src/misc.rs +++ b/src/tools/clippy/clippy_lints/src/misc.rs @@ -260,10 +260,10 @@ declare_lint_pass!(MiscLints => [ FLOAT_CMP_CONST ]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MiscLints { +impl<'tcx> LateLintPass<'tcx> for MiscLints { fn check_fn( &mut self, - cx: &LateContext<'a, 'tcx>, + cx: &LateContext<'tcx>, k: FnKind<'tcx>, decl: &'tcx FnDecl<'_>, body: &'tcx Body<'_>, @@ -287,7 +287,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MiscLints { } } - fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt<'_>) { + fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { if_chain! { if let StmtKind::Local(ref local) = stmt.kind; if let PatKind::Binding(an, .., name, None) = local.pat.kind; @@ -360,7 +360,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MiscLints { }; } - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { match expr.kind { ExprKind::Cast(ref e, ref ty) => { check_cast(cx, expr.span, e, ty); @@ -436,7 +436,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MiscLints { binding != "_result" && // FIXME: #944 is_used(cx, expr) && // don't lint if the declaration is in a macro - non_macro_local(cx, cx.tables().qpath_res(qpath, expr.hir_id)) + non_macro_local(cx, cx.qpath_res(qpath, expr.hir_id)) { Some(binding) } else { @@ -493,7 +493,7 @@ fn get_lint_and_message( } } -fn check_nan(cx: &LateContext<'_, '_>, expr: &Expr<'_>, cmp_expr: &Expr<'_>) { +fn check_nan(cx: &LateContext<'_>, expr: &Expr<'_>, cmp_expr: &Expr<'_>) { if_chain! { if !in_constant(cx, cmp_expr.hir_id); if let Some((value, _)) = constant(cx, cx.tables(), expr); @@ -516,7 +516,7 @@ fn check_nan(cx: &LateContext<'_, '_>, expr: &Expr<'_>, cmp_expr: &Expr<'_>) { } } -fn is_named_constant<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) -> bool { +fn is_named_constant<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool { if let Some((_, res)) = constant(cx, cx.tables(), expr) { res } else { @@ -524,7 +524,7 @@ fn is_named_constant<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) } } -fn is_allowed<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) -> bool { +fn is_allowed<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool { match constant(cx, cx.tables(), expr) { Some((Constant::F32(f), _)) => f == 0.0 || f.is_infinite(), Some((Constant::F64(f), _)) => f == 0.0 || f.is_infinite(), @@ -538,7 +538,7 @@ fn is_allowed<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) -> boo } // Return true if `expr` is the result of `signum()` invoked on a float value. -fn is_signum(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { +fn is_signum(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { // The negation of a signum is still a signum if let ExprKind::Unary(UnOp::UnNeg, ref child_expr) = expr.kind { return is_signum(cx, &child_expr); @@ -556,7 +556,7 @@ fn is_signum(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { false } -fn is_float(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { +fn is_float(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { let value = &walk_ptrs_ty(cx.tables().expr_ty(expr)).kind; if let ty::Array(arr_ty, _) = value { @@ -566,11 +566,11 @@ fn is_float(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { matches!(value, ty::Float(_)) } -fn is_array(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { +fn is_array(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { matches!(&walk_ptrs_ty(cx.tables().expr_ty(expr)).kind, ty::Array(_, _)) } -fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr<'_>, other: &Expr<'_>) { +fn check_to_owned(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>) { let (arg_ty, snip) = match expr.kind { ExprKind::MethodCall(.., ref args, _) if args.len() == 1 => { if match_trait_method(cx, expr, &paths::TO_STRING) || match_trait_method(cx, expr, &paths::TO_OWNED) { @@ -655,7 +655,7 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr<'_>, other: &Expr<'_>) { /// Heuristic to see if an expression is used. Should be compatible with /// `unused_variables`'s idea /// of what it means for an expression to be "used". -fn is_used(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { +fn is_used(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { if let Some(parent) = get_parent_expr(cx, expr) { match parent.kind { ExprKind::Assign(_, ref rhs, _) | ExprKind::AssignOp(_, _, ref rhs) => { @@ -686,7 +686,7 @@ fn in_attributes_expansion(expr: &Expr<'_>) -> bool { } /// Tests whether `res` is a variable defined outside a macro. -fn non_macro_local(cx: &LateContext<'_, '_>, res: def::Res) -> bool { +fn non_macro_local(cx: &LateContext<'_>, res: def::Res) -> bool { if let def::Res::Local(id) = res { !cx.tcx.hir().span(id).from_expansion() } else { @@ -694,7 +694,7 @@ fn non_macro_local(cx: &LateContext<'_, '_>, res: def::Res) -> bool { } } -fn check_cast(cx: &LateContext<'_, '_>, span: Span, e: &Expr<'_>, ty: &Ty<'_>) { +fn check_cast(cx: &LateContext<'_>, span: Span, e: &Expr<'_>, ty: &Ty<'_>) { if_chain! { if let TyKind::Ptr(ref mut_ty) = ty.kind; if let ExprKind::Lit(ref lit) = e.kind; diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs index 9cfc8d19134..bdce1bf1521 100644 --- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs +++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs @@ -71,10 +71,10 @@ declare_clippy_lint! { declare_lint_pass!(MissingConstForFn => [MISSING_CONST_FOR_FN]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingConstForFn { +impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { fn check_fn( &mut self, - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, kind: FnKind<'_>, _: &FnDecl<'_>, _: &Body<'_>, @@ -130,7 +130,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingConstForFn { /// Returns true if any of the method parameters is a type that implements `Drop`. The method /// can't be made const then, because `drop` can't be const-evaluated. -fn method_accepts_dropable(cx: &LateContext<'_, '_>, param_tys: &[hir::Ty<'_>]) -> bool { +fn method_accepts_dropable(cx: &LateContext<'_>, param_tys: &[hir::Ty<'_>]) -> bool { // If any of the params are dropable, return true param_tys.iter().any(|hir_ty| { let ty_ty = hir_ty_to_ty(cx.tcx, hir_ty); diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs index 0fd1e87f9e4..06e0f43c10b 100644 --- a/src/tools/clippy/clippy_lints/src/missing_doc.rs +++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs @@ -69,13 +69,7 @@ impl MissingDoc { } } - fn check_missing_docs_attrs( - &self, - cx: &LateContext<'_, '_>, - attrs: &[ast::Attribute], - sp: Span, - desc: &'static str, - ) { + fn check_missing_docs_attrs(&self, cx: &LateContext<'_>, attrs: &[ast::Attribute], sp: Span, desc: &'static str) { // If we're building a test harness, then warning about // documentation is probably not really relevant right now. if cx.sess().opts.test { @@ -107,8 +101,8 @@ impl MissingDoc { impl_lint_pass!(MissingDoc => [MISSING_DOCS_IN_PRIVATE_ITEMS]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { - fn enter_lint_attrs(&mut self, _: &LateContext<'a, 'tcx>, attrs: &'tcx [ast::Attribute]) { +impl<'tcx> LateLintPass<'tcx> for MissingDoc { + fn enter_lint_attrs(&mut self, _: &LateContext<'tcx>, attrs: &'tcx [ast::Attribute]) { let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| { attr.check_name(sym!(doc)) @@ -120,15 +114,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { self.doc_hidden_stack.push(doc_hidden); } - fn exit_lint_attrs(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx [ast::Attribute]) { + fn exit_lint_attrs(&mut self, _: &LateContext<'tcx>, _: &'tcx [ast::Attribute]) { self.doc_hidden_stack.pop().expect("empty doc_hidden_stack"); } - fn check_crate(&mut self, cx: &LateContext<'a, 'tcx>, krate: &'tcx hir::Crate<'_>) { + fn check_crate(&mut self, cx: &LateContext<'tcx>, krate: &'tcx hir::Crate<'_>) { self.check_missing_docs_attrs(cx, &krate.item.attrs, krate.item.span, "crate"); } - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx hir::Item<'_>) { + fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) { let desc = match it.kind { hir::ItemKind::Const(..) => "a constant", hir::ItemKind::Enum(..) => "an enum", @@ -161,7 +155,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { self.check_missing_docs_attrs(cx, &it.attrs, it.span, desc); } - fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, trait_item: &'tcx hir::TraitItem<'_>) { + fn check_trait_item(&mut self, cx: &LateContext<'tcx>, trait_item: &'tcx hir::TraitItem<'_>) { let desc = match trait_item.kind { hir::TraitItemKind::Const(..) => "an associated constant", hir::TraitItemKind::Fn(..) => "a trait method", @@ -171,7 +165,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { self.check_missing_docs_attrs(cx, &trait_item.attrs, trait_item.span, desc); } - fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx hir::ImplItem<'_>) { + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) { // If the method is an impl for a trait, don't doc. let def_id = cx.tcx.hir().local_def_id(impl_item.hir_id); match cx.tcx.associated_item(def_id).container { @@ -191,13 +185,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { self.check_missing_docs_attrs(cx, &impl_item.attrs, impl_item.span, desc); } - fn check_struct_field(&mut self, cx: &LateContext<'a, 'tcx>, sf: &'tcx hir::StructField<'_>) { + fn check_struct_field(&mut self, cx: &LateContext<'tcx>, sf: &'tcx hir::StructField<'_>) { if !sf.is_positional() { self.check_missing_docs_attrs(cx, &sf.attrs, sf.span, "a struct field"); } } - fn check_variant(&mut self, cx: &LateContext<'a, 'tcx>, v: &'tcx hir::Variant<'_>) { + fn check_variant(&mut self, cx: &LateContext<'tcx>, v: &'tcx hir::Variant<'_>) { self.check_missing_docs_attrs(cx, &v.attrs, v.span, "a variant"); } } diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index 1802470b184..bf80b62afe6 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -56,7 +56,7 @@ declare_clippy_lint! { "detects missing `#[inline]` attribute for public callables (functions, trait methods, methods...)" } -fn check_missing_inline_attrs(cx: &LateContext<'_, '_>, attrs: &[ast::Attribute], sp: Span, desc: &'static str) { +fn check_missing_inline_attrs(cx: &LateContext<'_>, attrs: &[ast::Attribute], sp: Span, desc: &'static str) { let has_inline = attrs.iter().any(|a| a.check_name(sym!(inline))); if !has_inline { span_lint( @@ -68,7 +68,7 @@ fn check_missing_inline_attrs(cx: &LateContext<'_, '_>, attrs: &[ast::Attribute] } } -fn is_executable(cx: &LateContext<'_, '_>) -> bool { +fn is_executable(cx: &LateContext<'_>) -> bool { use rustc_session::config::CrateType; cx.tcx.sess.crate_types().iter().any(|t: &CrateType| match t { @@ -79,8 +79,8 @@ fn is_executable(cx: &LateContext<'_, '_>) -> bool { declare_lint_pass!(MissingInline => [MISSING_INLINE_IN_PUBLIC_ITEMS]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx hir::Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for MissingInline { + fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) { if rustc_middle::lint::in_external_macro(cx.sess(), it.span) || is_executable(cx) { return; } @@ -129,7 +129,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { }; } - fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx hir::ImplItem<'_>) { + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) { use rustc_middle::ty::{ImplContainer, TraitContainer}; if rustc_middle::lint::in_external_macro(cx.sess(), impl_item.span) || is_executable(cx) { return; diff --git a/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs b/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs index f76e4721e1f..59ccc6333fd 100644 --- a/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs @@ -36,7 +36,7 @@ struct OperandInfo { is_integral: bool, } -fn analyze_operand(operand: &Expr<'_>, cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<OperandInfo> { +fn analyze_operand(operand: &Expr<'_>, cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<OperandInfo> { match constant(cx, cx.tables(), operand) { Some((Constant::Int(v), _)) => match cx.tables().expr_ty(expr).kind { ty::Int(ity) => { @@ -79,8 +79,8 @@ fn might_have_negative_value(t: &ty::TyS<'_>) -> bool { t.is_signed() || t.is_floating_point() } -fn check_const_operands<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn check_const_operands<'tcx>( + cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, lhs_operand: &OperandInfo, rhs_operand: &OperandInfo, @@ -105,7 +105,7 @@ fn check_const_operands<'a, 'tcx>( } } -fn check_non_const_operands<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>, operand: &Expr<'_>) { +fn check_non_const_operands<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, operand: &Expr<'_>) { let operand_type = cx.tables().expr_ty(operand); if might_have_negative_value(operand_type) { span_lint_and_then( @@ -123,8 +123,8 @@ fn check_non_const_operands<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Ex } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ModuloArithmetic { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for ModuloArithmetic { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { match &expr.kind { ExprKind::Binary(op, lhs, rhs) | ExprKind::AssignOp(op, lhs, rhs) => { if let BinOpKind::Rem = op.node { diff --git a/src/tools/clippy/clippy_lints/src/multiple_crate_versions.rs b/src/tools/clippy/clippy_lints/src/multiple_crate_versions.rs index 6c42014b4c8..c1773cef7a8 100644 --- a/src/tools/clippy/clippy_lints/src/multiple_crate_versions.rs +++ b/src/tools/clippy/clippy_lints/src/multiple_crate_versions.rs @@ -36,8 +36,8 @@ declare_clippy_lint! { declare_lint_pass!(MultipleCrateVersions => [MULTIPLE_CRATE_VERSIONS]); -impl LateLintPass<'_, '_> for MultipleCrateVersions { - fn check_crate(&mut self, cx: &LateContext<'_, '_>, _: &Crate<'_>) { +impl LateLintPass<'_> for MultipleCrateVersions { + fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) { if !run_lints(cx, &[MULTIPLE_CRATE_VERSIONS], CRATE_HIR_ID) { return; } diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs index 755b196c698..d8fb8a4bb77 100644 --- a/src/tools/clippy/clippy_lints/src/mut_key.rs +++ b/src/tools/clippy/clippy_lints/src/mut_key.rs @@ -51,14 +51,14 @@ declare_clippy_lint! { declare_lint_pass!(MutableKeyType => [ MUTABLE_KEY_TYPE ]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableKeyType { - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item<'tcx>) { +impl<'tcx> LateLintPass<'tcx> for MutableKeyType { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { if let hir::ItemKind::Fn(ref sig, ..) = item.kind { check_sig(cx, item.hir_id, &sig.decl); } } - fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::ImplItem<'tcx>) { + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'tcx>) { if let hir::ImplItemKind::Fn(ref sig, ..) = item.kind { if trait_ref_of_method(cx, item.hir_id).is_none() { check_sig(cx, item.hir_id, &sig.decl); @@ -66,13 +66,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableKeyType { } } - fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::TraitItem<'tcx>) { + fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'tcx>) { if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind { check_sig(cx, item.hir_id, &sig.decl); } } - fn check_local(&mut self, cx: &LateContext<'_, '_>, local: &hir::Local<'_>) { + fn check_local(&mut self, cx: &LateContext<'_>, local: &hir::Local<'_>) { if let hir::PatKind::Wild = local.pat.kind { return; } @@ -80,7 +80,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableKeyType { } } -fn check_sig<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item_hir_id: hir::HirId, decl: &hir::FnDecl<'_>) { +fn check_sig<'tcx>(cx: &LateContext<'tcx>, item_hir_id: hir::HirId, decl: &hir::FnDecl<'_>) { let fn_def_id = cx.tcx.hir().local_def_id(item_hir_id); let fn_sig = cx.tcx.fn_sig(fn_def_id); for (hir_ty, ty) in decl.inputs.iter().zip(fn_sig.inputs().skip_binder().iter()) { @@ -95,7 +95,7 @@ fn check_sig<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item_hir_id: hir::HirId, decl // 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<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, ty: Ty<'tcx>) { +fn check_ty<'tcx>(cx: &LateContext<'tcx>, span: Span, ty: Ty<'tcx>) { let ty = walk_ptrs_ty(ty); if let Adt(def, substs) = ty.kind { if [&paths::HASHMAP, &paths::BTREEMAP, &paths::HASHSET, &paths::BTREESET] @@ -108,7 +108,7 @@ fn check_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, ty: Ty<'tcx>) { } } -fn is_mutable_type<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>, span: Span) -> bool { +fn is_mutable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span) -> bool { match ty.kind { RawPtr(TypeAndMut { ty: inner_ty, mutbl }) | Ref(_, inner_ty, mutbl) => { mutbl == hir::Mutability::Mut || is_mutable_type(cx, inner_ty, span) diff --git a/src/tools/clippy/clippy_lints/src/mut_mut.rs b/src/tools/clippy/clippy_lints/src/mut_mut.rs index 6aa77b4df83..259b4c73d76 100644 --- a/src/tools/clippy/clippy_lints/src/mut_mut.rs +++ b/src/tools/clippy/clippy_lints/src/mut_mut.rs @@ -28,12 +28,12 @@ declare_clippy_lint! { declare_lint_pass!(MutMut => [MUT_MUT]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutMut { - fn check_block(&mut self, cx: &LateContext<'a, 'tcx>, block: &'tcx hir::Block<'_>) { +impl<'tcx> LateLintPass<'tcx> for MutMut { + fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) { intravisit::walk_block(&mut MutVisitor { cx }, block); } - fn check_ty(&mut self, cx: &LateContext<'a, 'tcx>, ty: &'tcx hir::Ty<'_>) { + fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx hir::Ty<'_>) { use rustc_hir::intravisit::Visitor; MutVisitor { cx }.visit_ty(ty); @@ -41,7 +41,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutMut { } pub struct MutVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, } impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { diff --git a/src/tools/clippy/clippy_lints/src/mut_reference.rs b/src/tools/clippy/clippy_lints/src/mut_reference.rs index dbe257069c3..53341b6eba7 100644 --- a/src/tools/clippy/clippy_lints/src/mut_reference.rs +++ b/src/tools/clippy/clippy_lints/src/mut_reference.rs @@ -29,8 +29,8 @@ declare_clippy_lint! { declare_lint_pass!(UnnecessaryMutPassed => [UNNECESSARY_MUT_PASSED]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnecessaryMutPassed { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { match e.kind { ExprKind::Call(ref fn_expr, ref arguments) => { if let ExprKind::Path(ref path) = fn_expr.kind { @@ -53,12 +53,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnecessaryMutPassed { } } -fn check_arguments<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - arguments: &[Expr<'_>], - type_definition: Ty<'tcx>, - name: &str, -) { +fn check_arguments<'tcx>(cx: &LateContext<'tcx>, arguments: &[Expr<'_>], type_definition: Ty<'tcx>, name: &str) { match type_definition.kind { ty::FnDef(..) | ty::FnPtr(_) => { let parameters = type_definition.fn_sig(cx.tcx).skip_binder().inputs(); diff --git a/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs index 45db5140711..78d2356748f 100644 --- a/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs +++ b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs @@ -35,8 +35,8 @@ declare_lint_pass!(DebugAssertWithMutCall => [DEBUG_ASSERT_WITH_MUT_CALL]); const DEBUG_MACRO_NAMES: [&str; 3] = ["debug_assert", "debug_assert_eq", "debug_assert_ne"]; -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DebugAssertWithMutCall { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for DebugAssertWithMutCall { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { for dmn in &DEBUG_MACRO_NAMES { if is_direct_expn_of(e.span, dmn).is_some() { if let Some(span) = extract_call(cx, e) { @@ -53,7 +53,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DebugAssertWithMutCall { } //HACK(hellow554): remove this when #4694 is implemented -fn extract_call<'a, 'tcx>(cx: &'a LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) -> Option<Span> { +fn extract_call<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> Option<Span> { if_chain! { if let ExprKind::Block(ref block, _) = e.kind; if block.stmts.len() == 1; @@ -102,13 +102,13 @@ fn extract_call<'a, 'tcx>(cx: &'a LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) -> O } struct MutArgVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, expr_span: Option<Span>, found: bool, } impl<'a, 'tcx> MutArgVisitor<'a, 'tcx> { - fn new(cx: &'a LateContext<'a, 'tcx>) -> Self { + fn new(cx: &'a LateContext<'tcx>) -> Self { Self { cx, expr_span: None, diff --git a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs index c227dc54f29..1a821491fca 100644 --- a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs +++ b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs @@ -64,8 +64,8 @@ declare_clippy_lint! { declare_lint_pass!(Mutex => [MUTEX_ATOMIC, MUTEX_INTEGER]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Mutex { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for Mutex { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { let ty = cx.tables().expr_ty(expr); if let ty::Adt(_, subst) = ty.kind { if is_type_diagnostic_item(cx, ty, sym!(mutex_type)) { diff --git a/src/tools/clippy/clippy_lints/src/needless_bool.rs b/src/tools/clippy/clippy_lints/src/needless_bool.rs index 653f9e2ae86..e15376b9326 100644 --- a/src/tools/clippy/clippy_lints/src/needless_bool.rs +++ b/src/tools/clippy/clippy_lints/src/needless_bool.rs @@ -67,8 +67,8 @@ declare_clippy_lint! { declare_lint_pass!(NeedlessBool => [NEEDLESS_BOOL]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for NeedlessBool { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { use self::Expression::{Bool, RetBool}; if let Some((ref pred, ref then_block, Some(ref else_expr))) = higher::if_block(&e) { let reduce = |ret, not| { @@ -127,8 +127,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool { declare_lint_pass!(BoolComparison => [BOOL_COMPARISON]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for BoolComparison { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if e.span.from_expansion() { return; } @@ -218,7 +218,7 @@ fn one_side_is_unary_not<'tcx>(left_side: &'tcx Expr<'_>, right_side: &'tcx Expr } fn check_comparison<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, + cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, left_true: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &str)>, left_false: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &str)>, @@ -285,7 +285,7 @@ fn check_comparison<'a, 'tcx>( } fn suggest_bool_comparison<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, + cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, expr: &Expr<'_>, mut applicability: Applicability, diff --git a/src/tools/clippy/clippy_lints/src/needless_borrow.rs b/src/tools/clippy/clippy_lints/src/needless_borrow.rs index 6bb06defb70..1bea93fcb75 100644 --- a/src/tools/clippy/clippy_lints/src/needless_borrow.rs +++ b/src/tools/clippy/clippy_lints/src/needless_borrow.rs @@ -40,8 +40,8 @@ pub struct NeedlessBorrow { impl_lint_pass!(NeedlessBorrow => [NEEDLESS_BORROW]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for NeedlessBorrow { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if e.span.from_expansion() || self.derived_item.is_some() { return; } @@ -79,7 +79,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { } } } - fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat<'_>) { + fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) { if pat.span.from_expansion() || self.derived_item.is_some() { return; } @@ -111,14 +111,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { } } - fn check_item(&mut self, _: &LateContext<'a, 'tcx>, item: &'tcx Item<'_>) { + fn check_item(&mut self, _: &LateContext<'tcx>, item: &'tcx Item<'_>) { if item.attrs.iter().any(|a| a.check_name(sym!(automatically_derived))) { debug_assert!(self.derived_item.is_none()); self.derived_item = Some(item.hir_id); } } - fn check_item_post(&mut self, _: &LateContext<'a, 'tcx>, item: &'tcx Item<'_>) { + fn check_item_post(&mut self, _: &LateContext<'tcx>, item: &'tcx Item<'_>) { if let Some(id) = self.derived_item { if item.hir_id == id { self.derived_item = None; diff --git a/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs b/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs index e56489c6d43..85184fdea47 100644 --- a/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs +++ b/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs @@ -52,8 +52,8 @@ declare_clippy_lint! { declare_lint_pass!(NeedlessBorrowedRef => [NEEDLESS_BORROWED_REFERENCE]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrowedRef { - fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat<'_>) { +impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowedRef { + fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) { if pat.span.from_expansion() { // OK, simple enough, lints doesn't check in macro. return; 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 6954f0cc683..bc70c675ad6 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 @@ -64,11 +64,11 @@ macro_rules! need { }; } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { +impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { #[allow(clippy::too_many_lines)] fn check_fn( &mut self, - cx: &LateContext<'a, 'tcx>, + cx: &LateContext<'tcx>, kind: FnKind<'tcx>, decl: &'tcx FnDecl<'_>, body: &'tcx Body<'_>, diff --git a/src/tools/clippy/clippy_lints/src/needless_update.rs b/src/tools/clippy/clippy_lints/src/needless_update.rs index 9b556dbb854..6ec73041604 100644 --- a/src/tools/clippy/clippy_lints/src/needless_update.rs +++ b/src/tools/clippy/clippy_lints/src/needless_update.rs @@ -44,8 +44,8 @@ declare_clippy_lint! { declare_lint_pass!(NeedlessUpdate => [NEEDLESS_UPDATE]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessUpdate { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for NeedlessUpdate { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let ExprKind::Struct(_, ref fields, Some(ref base)) = expr.kind { let ty = cx.tables().expr_ty(expr); if let ty::Adt(def, _) = ty.kind { diff --git a/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index 0f56daa3659..1be766d8e8d 100644 --- a/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -45,8 +45,8 @@ declare_clippy_lint! { declare_lint_pass!(NoNegCompOpForPartialOrd => [NEG_CMP_OP_ON_PARTIAL_ORD]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NoNegCompOpForPartialOrd { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for NoNegCompOpForPartialOrd { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { if !in_external_macro(cx.sess(), expr.span); diff --git a/src/tools/clippy/clippy_lints/src/neg_multiply.rs b/src/tools/clippy/clippy_lints/src/neg_multiply.rs index a9ce01b67b0..1346145da32 100644 --- a/src/tools/clippy/clippy_lints/src/neg_multiply.rs +++ b/src/tools/clippy/clippy_lints/src/neg_multiply.rs @@ -26,8 +26,8 @@ declare_clippy_lint! { declare_lint_pass!(NegMultiply => [NEG_MULTIPLY]); #[allow(clippy::match_same_arms)] -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NegMultiply { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for NegMultiply { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if let ExprKind::Binary(ref op, ref left, ref right) = e.kind { if BinOpKind::Mul == op.node { match (&left.kind, &right.kind) { @@ -41,7 +41,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NegMultiply { } } -fn check_mul(cx: &LateContext<'_, '_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) { +fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) { if_chain! { if let ExprKind::Lit(ref l) = lit.kind; if let Constant::Int(1) = consts::lit_to_constant(&l.node, cx.tables().expr_ty_opt(lit)); diff --git a/src/tools/clippy/clippy_lints/src/new_without_default.rs b/src/tools/clippy/clippy_lints/src/new_without_default.rs index 42200385932..2597f5f6f17 100644 --- a/src/tools/clippy/clippy_lints/src/new_without_default.rs +++ b/src/tools/clippy/clippy_lints/src/new_without_default.rs @@ -56,9 +56,9 @@ pub struct NewWithoutDefault { impl_lint_pass!(NewWithoutDefault => [NEW_WITHOUT_DEFAULT]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { +impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault { #[allow(clippy::too_many_lines)] - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item<'_>) { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { if let hir::ItemKind::Impl { of_trait: None, items, .. } = item.kind diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs index 5fdc656580f..95283dae714 100644 --- a/src/tools/clippy/clippy_lints/src/no_effect.rs +++ b/src/tools/clippy/clippy_lints/src/no_effect.rs @@ -42,7 +42,7 @@ declare_clippy_lint! { "outer expressions with no effect" } -fn has_no_effect(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { +fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { if expr.span.from_expansion() { return false; } @@ -87,8 +87,8 @@ fn has_no_effect(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { declare_lint_pass!(NoEffect => [NO_EFFECT, UNNECESSARY_OPERATION]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NoEffect { - fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt<'_>) { +impl<'tcx> LateLintPass<'tcx> for NoEffect { + fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { if let StmtKind::Semi(ref expr) = stmt.kind { if has_no_effect(cx, expr) { span_lint(cx, NO_EFFECT, stmt.span, "statement with no effect"); @@ -119,7 +119,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NoEffect { } } -fn reduce_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr<'a>) -> Option<Vec<&'a Expr<'a>>> { +fn reduce_expression<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<Vec<&'a Expr<'a>>> { if expr.span.from_expansion() { return None; } 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 21d7a7439f2..c11a2ff9ee0 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -109,7 +109,7 @@ impl Source { } } -fn verify_ty_bound<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>, source: Source) { +fn verify_ty_bound<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, source: Source) { if ty.is_freeze(cx.tcx.at(DUMMY_SP), cx.param_env) || is_copy(cx, ty) { // An `UnsafeCell` is `!Copy`, and an `UnsafeCell` is also the only type which // is `!Freeze`, thus if our type is `Copy` we can be sure it must be `Freeze` @@ -141,15 +141,15 @@ fn verify_ty_bound<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>, source: S declare_lint_pass!(NonCopyConst => [DECLARE_INTERIOR_MUTABLE_CONST, BORROW_INTERIOR_MUTABLE_CONST]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst { - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for NonCopyConst { + fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx Item<'_>) { if let ItemKind::Const(hir_ty, ..) = &it.kind { let ty = hir_ty_to_ty(cx.tcx, hir_ty); verify_ty_bound(cx, ty, Source::Item { item: it.span }); } } - fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, trait_item: &'tcx TraitItem<'_>) { + fn check_trait_item(&mut self, cx: &LateContext<'tcx>, trait_item: &'tcx TraitItem<'_>) { if let TraitItemKind::Const(hir_ty, ..) = &trait_item.kind { let ty = hir_ty_to_ty(cx.tcx, hir_ty); verify_ty_bound( @@ -163,7 +163,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst { } } - fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx ImplItem<'_>) { + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) { if let ImplItemKind::Const(hir_ty, ..) = &impl_item.kind { let item_hir_id = cx.tcx.hir().get_parent_node(impl_item.hir_id); let item = cx.tcx.hir().expect_item(item_hir_id); @@ -182,7 +182,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst { } } - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let ExprKind::Path(qpath) = &expr.kind { // Only lint if we use the const item inside a function. if in_constant(cx, expr.hir_id) { diff --git a/src/tools/clippy/clippy_lints/src/open_options.rs b/src/tools/clippy/clippy_lints/src/open_options.rs index 2467a14cea1..2b83efa84f6 100644 --- a/src/tools/clippy/clippy_lints/src/open_options.rs +++ b/src/tools/clippy/clippy_lints/src/open_options.rs @@ -27,8 +27,8 @@ declare_clippy_lint! { declare_lint_pass!(OpenOptions => [NONSENSICAL_OPEN_OPTIONS]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OpenOptions { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for OpenOptions { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if let ExprKind::MethodCall(ref path, _, ref arguments, _) = e.kind { let obj_ty = walk_ptrs_ty(cx.tables().expr_ty(&arguments[0])); if path.ident.name == sym!(open) && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) { @@ -56,7 +56,7 @@ enum OpenOption { Append, } -fn get_open_options(cx: &LateContext<'_, '_>, argument: &Expr<'_>, options: &mut Vec<(OpenOption, Argument)>) { +fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec<(OpenOption, Argument)>) { if let ExprKind::MethodCall(ref path, _, ref arguments, _) = argument.kind { let obj_ty = walk_ptrs_ty(cx.tables().expr_ty(&arguments[0])); @@ -107,7 +107,7 @@ fn get_open_options(cx: &LateContext<'_, '_>, argument: &Expr<'_>, options: &mut } } -fn check_open_options(cx: &LateContext<'_, '_>, options: &[(OpenOption, Argument)], span: Span) { +fn check_open_options(cx: &LateContext<'_>, options: &[(OpenOption, Argument)], span: Span) { let (mut create, mut append, mut truncate, mut read, mut write) = (false, false, false, false, false); let (mut create_arg, mut append_arg, mut truncate_arg, mut read_arg, mut write_arg) = (false, false, false, false, false); diff --git a/src/tools/clippy/clippy_lints/src/overflow_check_conditional.rs b/src/tools/clippy/clippy_lints/src/overflow_check_conditional.rs index 5984b09120d..0850f88df44 100644 --- a/src/tools/clippy/clippy_lints/src/overflow_check_conditional.rs +++ b/src/tools/clippy/clippy_lints/src/overflow_check_conditional.rs @@ -25,9 +25,9 @@ declare_clippy_lint! { declare_lint_pass!(OverflowCheckConditional => [OVERFLOW_CHECK_CONDITIONAL]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OverflowCheckConditional { +impl<'tcx> LateLintPass<'tcx> for OverflowCheckConditional { // a + b < a, a > a + b, a < a - b, a - b > a - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { let eq = |l, r| SpanlessEq::new(cx).eq_path_segment(l, r); if_chain! { if let ExprKind::Binary(ref op, ref first, ref second) = expr.kind; diff --git a/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs b/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs index 2cd9200ddb2..10f4694640e 100644 --- a/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs +++ b/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs @@ -91,8 +91,8 @@ declare_clippy_lint! { declare_lint_pass!(PanicUnimplemented => [PANIC_PARAMS, UNIMPLEMENTED, UNREACHABLE, TODO, PANIC]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PanicUnimplemented { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for PanicUnimplemented { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { if let ExprKind::Block(ref block, _) = expr.kind; if let Some(ref ex) = block.expr; @@ -136,7 +136,7 @@ fn get_outer_span(expr: &Expr<'_>) -> Span { } } -fn match_panic(params: &[Expr<'_>], expr: &Expr<'_>, cx: &LateContext<'_, '_>) { +fn match_panic(params: &[Expr<'_>], expr: &Expr<'_>, cx: &LateContext<'_>) { if_chain! { if let ExprKind::Lit(ref lit) = params[0].kind; if is_direct_expn_of(expr.span, "panic").is_some(); diff --git a/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs b/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs index 1445df41c45..19d355e64ca 100644 --- a/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs +++ b/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs @@ -30,8 +30,8 @@ declare_clippy_lint! { declare_lint_pass!(PartialEqNeImpl => [PARTIALEQ_NE_IMPL]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PartialEqNeImpl { - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for PartialEqNeImpl { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if_chain! { if let ItemKind::Impl{ of_trait: Some(ref trait_ref), items: impl_items, .. } = item.kind; if !is_automatically_derived(&*item.attrs); diff --git a/src/tools/clippy/clippy_lints/src/path_buf_push_overwrite.rs b/src/tools/clippy/clippy_lints/src/path_buf_push_overwrite.rs index f26a5258782..48e60954279 100644 --- a/src/tools/clippy/clippy_lints/src/path_buf_push_overwrite.rs +++ b/src/tools/clippy/clippy_lints/src/path_buf_push_overwrite.rs @@ -40,8 +40,8 @@ declare_clippy_lint! { declare_lint_pass!(PathBufPushOverwrite => [PATH_BUF_PUSH_OVERWRITE]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PathBufPushOverwrite { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for PathBufPushOverwrite { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind; if path.ident.name == sym!(push); diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index c77b44e0c99..7b6bd69ffca 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -108,14 +108,14 @@ declare_clippy_lint! { declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Ptr { - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for Ptr { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if let ItemKind::Fn(ref sig, _, body_id) = item.kind { check_fn(cx, &sig.decl, item.hir_id, Some(body_id)); } } - fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem<'_>) { + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) { if let ImplItemKind::Fn(ref sig, body_id) = item.kind { let parent_item = cx.tcx.hir().get_parent_item(item.hir_id); if let Some(Node::Item(it)) = cx.tcx.hir().find(parent_item) { @@ -127,7 +127,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Ptr { } } - fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem<'_>) { + fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { if let TraitItemKind::Fn(ref sig, ref trait_method) = item.kind { let body_id = if let TraitFn::Provided(b) = *trait_method { Some(b) @@ -138,7 +138,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Ptr { } } - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let ExprKind::Binary(ref op, ref l, ref r) = expr.kind { if (op.node == BinOpKind::Eq || op.node == BinOpKind::Ne) && (is_null_path(l) || is_null_path(r)) { span_lint( @@ -153,7 +153,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Ptr { } #[allow(clippy::too_many_lines)] -fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id: Option<BodyId>) { +fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id: Option<BodyId>) { let fn_def_id = cx.tcx.hir().local_def_id(fn_id); let sig = cx.tcx.fn_sig(fn_def_id); let fn_ty = sig.skip_binder(); diff --git a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs index b35a7e64bff..61e186a4b46 100644 --- a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs +++ b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs @@ -43,8 +43,8 @@ declare_clippy_lint! { declare_lint_pass!(PtrOffsetWithCast => [PTR_OFFSET_WITH_CAST]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PtrOffsetWithCast { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for PtrOffsetWithCast { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { // Check if the expressions is a ptr.offset or ptr.wrapping_offset method call let (receiver_expr, arg_expr, method) = match expr_as_ptr_offset_call(cx, expr) { Some(call_arg) => call_arg, @@ -75,7 +75,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PtrOffsetWithCast { } // If the given expression is a cast from a usize, return the lhs of the cast -fn expr_as_cast_from_usize<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { +fn expr_as_cast_from_usize<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { if let ExprKind::Cast(ref cast_lhs_expr, _) = expr.kind { if is_expr_ty_usize(cx, &cast_lhs_expr) { return Some(cast_lhs_expr); @@ -86,8 +86,8 @@ fn expr_as_cast_from_usize<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Exp // If the given expression is a ptr::offset or ptr::wrapping_offset method call, return the // receiver, the arg of the method call, and the method. -fn expr_as_ptr_offset_call<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn expr_as_ptr_offset_call<'tcx>( + cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, ) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>, Method)> { if let ExprKind::MethodCall(ref path_segment, _, ref args, _) = expr.kind { @@ -104,17 +104,17 @@ fn expr_as_ptr_offset_call<'a, 'tcx>( } // Is the type of the expression a usize? -fn is_expr_ty_usize<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>) -> bool { +fn is_expr_ty_usize<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> bool { cx.tables().expr_ty(expr) == cx.tcx.types.usize } // Is the type of the expression a raw pointer? -fn is_expr_ty_raw_ptr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>) -> bool { +fn is_expr_ty_raw_ptr<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> bool { cx.tables().expr_ty(expr).is_unsafe_ptr() } -fn build_suggestion<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn build_suggestion<'tcx>( + cx: &LateContext<'tcx>, method: Method, receiver_expr: &Expr<'_>, cast_lhs_expr: &Expr<'_>, diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index 4a6395da01c..cc9c2f19607 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -47,7 +47,7 @@ impl QuestionMark { /// ``` /// /// If it matches, it will suggest to use the question mark operator instead - fn check_is_none_and_early_return_none(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { + fn check_is_none_and_early_return_none(cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { if let Some((if_expr, body, else_)) = higher::if_block(&expr); if let ExprKind::MethodCall(segment, _, args, _) = &if_expr.kind; @@ -93,7 +93,7 @@ impl QuestionMark { } } - fn check_if_let_some_and_early_return_none(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { + fn check_if_let_some_and_early_return_none(cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { if let ExprKind::Match(subject, arms, source) = &expr.kind; if *source == MatchSource::IfLetDesugar { contains_else_clause: true }; @@ -134,19 +134,19 @@ impl QuestionMark { } } - fn moves_by_default(cx: &LateContext<'_, '_>, expression: &Expr<'_>) -> bool { + fn moves_by_default(cx: &LateContext<'_>, expression: &Expr<'_>) -> bool { let expr_ty = cx.tables().expr_ty(expression); !expr_ty.is_copy_modulo_regions(cx.tcx.at(expression.span), cx.param_env) } - fn is_option(cx: &LateContext<'_, '_>, expression: &Expr<'_>) -> bool { + fn is_option(cx: &LateContext<'_>, expression: &Expr<'_>) -> bool { let expr_ty = cx.tables().expr_ty(expression); is_type_diagnostic_item(cx, expr_ty, sym!(option_type)) } - fn expression_returns_none(cx: &LateContext<'_, '_>, expression: &Expr<'_>) -> bool { + fn expression_returns_none(cx: &LateContext<'_>, expression: &Expr<'_>) -> bool { match expression.kind { ExprKind::Block(ref block, _) => { if let Some(return_expression) = Self::return_expression(block) { @@ -158,7 +158,7 @@ impl QuestionMark { ExprKind::Ret(Some(ref expr)) => Self::expression_returns_none(cx, expr), ExprKind::Path(ref qp) => { if let Res::Def(DefKind::Ctor(def::CtorOf::Variant, def::CtorKind::Const), def_id) = - cx.tables().qpath_res(qp, expression.hir_id) + cx.qpath_res(qp, expression.hir_id) { return match_def_path(cx, def_id, &paths::OPTION_NONE); } @@ -196,8 +196,8 @@ impl QuestionMark { } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for QuestionMark { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for QuestionMark { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { Self::check_is_none_and_early_return_none(cx, expr); Self::check_if_let_some_and_early_return_none(cx, expr); } diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs index 43ef236a924..c164ec9aaf1 100644 --- a/src/tools/clippy/clippy_lints/src/ranges.rs +++ b/src/tools/clippy/clippy_lints/src/ranges.rs @@ -127,8 +127,8 @@ declare_lint_pass!(Ranges => [ REVERSED_EMPTY_RANGES, ]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Ranges { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for Ranges { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind { let name = path.ident.as_str(); if name == "zip" && args.len() == 2 { @@ -166,7 +166,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Ranges { } // exclusive range plus one: `x..(y+1)` -fn check_exclusive_range_plus_one(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { +fn check_exclusive_range_plus_one(cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { if let Some(higher::Range { start, @@ -215,7 +215,7 @@ fn check_exclusive_range_plus_one(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { } // inclusive range minus one: `x..=(y-1)` -fn check_inclusive_range_minus_one(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { +fn check_inclusive_range_minus_one(cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::Closed }) = higher::range(cx, expr); if let Some(y) = y_minus_one(cx, end); @@ -240,8 +240,8 @@ fn check_inclusive_range_minus_one(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { } } -fn check_reversed_empty_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { - fn inside_indexing_expr(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { +fn check_reversed_empty_range(cx: &LateContext<'_>, expr: &Expr<'_>) { + fn inside_indexing_expr(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { matches!( get_parent_expr(cx, expr), Some(Expr { @@ -251,7 +251,7 @@ fn check_reversed_empty_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { ) } - fn is_for_loop_arg(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { + fn is_for_loop_arg(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { let mut cur_expr = expr; while let Some(parent_expr) = get_parent_expr(cx, cur_expr) { match higher::for_loop(parent_expr) { @@ -320,7 +320,7 @@ fn check_reversed_empty_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { } } -fn y_plus_one<'t>(cx: &LateContext<'_, '_>, expr: &'t Expr<'_>) -> Option<&'t Expr<'t>> { +fn y_plus_one<'t>(cx: &LateContext<'_>, expr: &'t Expr<'_>) -> Option<&'t Expr<'t>> { match expr.kind { ExprKind::Binary( Spanned { @@ -341,7 +341,7 @@ fn y_plus_one<'t>(cx: &LateContext<'_, '_>, expr: &'t Expr<'_>) -> Option<&'t Ex } } -fn y_minus_one<'t>(cx: &LateContext<'_, '_>, expr: &'t Expr<'_>) -> Option<&'t Expr<'t>> { +fn y_minus_one<'t>(cx: &LateContext<'_>, expr: &'t Expr<'_>) -> Option<&'t Expr<'t>> { match expr.kind { ExprKind::Binary( Spanned { diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs index d563eb886ae..fda7480194d 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs @@ -66,11 +66,11 @@ declare_clippy_lint! { declare_lint_pass!(RedundantClone => [REDUNDANT_CLONE]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { +impl<'tcx> LateLintPass<'tcx> for RedundantClone { #[allow(clippy::too_many_lines)] fn check_fn( &mut self, - cx: &LateContext<'a, 'tcx>, + cx: &LateContext<'tcx>, _: FnKind<'tcx>, _: &'tcx FnDecl<'_>, body: &'tcx Body<'_>, @@ -273,7 +273,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { /// If `kind` is `y = func(x: &T)` where `T: !Copy`, returns `(DefId of func, x, T, y)`. fn is_call_with_ref_arg<'tcx>( - cx: &LateContext<'_, 'tcx>, + cx: &LateContext<'tcx>, mir: &'tcx mir::Body<'tcx>, kind: &'tcx mir::TerminatorKind<'tcx>, ) -> Option<(def_id::DefId, mir::Local, Ty<'tcx>, mir::Local)> { @@ -297,7 +297,7 @@ type CannotMoveOut = bool; /// Finds the first `to = (&)from`, and returns /// ``Some((from, whether `from` cannot be moved out))``. fn find_stmt_assigns_to<'tcx>( - cx: &LateContext<'_, 'tcx>, + cx: &LateContext<'tcx>, mir: &mir::Body<'tcx>, to_local: mir::Local, by_ref: bool, @@ -331,7 +331,7 @@ fn find_stmt_assigns_to<'tcx>( /// /// Also reports whether given `place` cannot be moved out. fn base_local_and_movability<'tcx>( - cx: &LateContext<'_, 'tcx>, + cx: &LateContext<'tcx>, mir: &mir::Body<'tcx>, place: mir::Place<'tcx>, ) -> Option<(mir::Local, CannotMoveOut)> { @@ -459,11 +459,11 @@ impl BottomValue for MaybeStorageLive { struct PossibleBorrowerVisitor<'a, 'tcx> { possible_borrower: TransitiveRelation<mir::Local>, body: &'a mir::Body<'tcx>, - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, } impl<'a, 'tcx> PossibleBorrowerVisitor<'a, 'tcx> { - fn new(cx: &'a LateContext<'a, 'tcx>, body: &'a mir::Body<'tcx>) -> Self { + fn new(cx: &'a LateContext<'tcx>, body: &'a mir::Body<'tcx>) -> Self { Self { possible_borrower: TransitiveRelation::default(), cx, @@ -473,7 +473,7 @@ impl<'a, 'tcx> PossibleBorrowerVisitor<'a, 'tcx> { fn into_map( self, - cx: &LateContext<'a, 'tcx>, + cx: &LateContext<'tcx>, maybe_live: ResultsCursor<'tcx, 'tcx, MaybeStorageLive>, ) -> PossibleBorrowerMap<'a, 'tcx> { let mut map = FxHashMap::default(); diff --git a/src/tools/clippy/clippy_lints/src/redundant_pattern_matching.rs b/src/tools/clippy/clippy_lints/src/redundant_pattern_matching.rs index 3c528a295b0..d8d16efb978 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_pattern_matching.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_pattern_matching.rs @@ -47,8 +47,8 @@ declare_clippy_lint! { declare_lint_pass!(RedundantPatternMatching => [REDUNDANT_PATTERN_MATCHING]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantPatternMatching { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for RedundantPatternMatching { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let ExprKind::Match(op, arms, ref match_source) = &expr.kind { match match_source { MatchSource::Normal => find_sugg_for_match(cx, expr, op, arms), @@ -60,14 +60,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantPatternMatching { } } -fn find_sugg_for_if_let<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn find_sugg_for_if_let<'tcx>( + cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op: &Expr<'_>, arms: &[Arm<'_>], keyword: &'static str, ) { - fn find_suggestion(cx: &LateContext<'_, '_>, hir_id: HirId, path: &QPath<'_>) -> Option<&'static str> { + fn find_suggestion(cx: &LateContext<'_>, hir_id: HirId, path: &QPath<'_>) -> Option<&'static str> { if match_qpath(path, &paths::RESULT_OK) && can_suggest(cx, hir_id, sym!(result_type), "is_ok") { return Some("is_ok()"); } @@ -138,7 +138,7 @@ fn find_sugg_for_if_let<'a, 'tcx>( ); } -fn find_sugg_for_match<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>, op: &Expr<'_>, arms: &[Arm<'_>]) { +fn find_sugg_for_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op: &Expr<'_>, arms: &[Arm<'_>]) { if arms.len() == 2 { let node_pair = (&arms[0].pat.kind, &arms[1].pat.kind); @@ -237,7 +237,7 @@ fn find_good_method_for_match<'a>( } } -fn can_suggest(cx: &LateContext<'_, '_>, hir_id: HirId, diag_item: Symbol, name: &str) -> bool { +fn can_suggest(cx: &LateContext<'_>, hir_id: HirId, diag_item: Symbol, name: &str) -> bool { if !in_constant(cx, hir_id) { return true; } diff --git a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs index 6fc07f91660..acd9047ace6 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs @@ -39,8 +39,8 @@ pub struct RedundantPubCrate { impl_lint_pass!(RedundantPubCrate => [REDUNDANT_PUB_CRATE]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantPubCrate { - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'tcx>) { +impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { if let VisibilityKind::Crate { .. } = item.vis.node { if !cx.access_levels.is_exported(item.hir_id) { if let Some(false) = self.is_exported.last() { @@ -70,7 +70,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantPubCrate { } } - fn check_item_post(&mut self, _cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'tcx>) { + fn check_item_post(&mut self, _cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { if let ItemKind::Mod { .. } = item.kind { self.is_exported.pop().expect("unbalanced check_item/check_item_post"); } diff --git a/src/tools/clippy/clippy_lints/src/regex.rs b/src/tools/clippy/clippy_lints/src/regex.rs index 9c54c3cbac0..b67abad6ccb 100644 --- a/src/tools/clippy/clippy_lints/src/regex.rs +++ b/src/tools/clippy/clippy_lints/src/regex.rs @@ -73,12 +73,12 @@ pub struct Regex { impl_lint_pass!(Regex => [INVALID_REGEX, REGEX_MACRO, TRIVIAL_REGEX]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Regex { - fn check_crate(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx Crate<'_>) { +impl<'tcx> LateLintPass<'tcx> for Regex { + fn check_crate(&mut self, _: &LateContext<'tcx>, _: &'tcx Crate<'_>) { self.spans.clear(); } - fn check_block(&mut self, cx: &LateContext<'a, 'tcx>, block: &'tcx Block<'_>) { + fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'_>) { if_chain! { if self.last.is_none(); if let Some(ref expr) = block.expr; @@ -100,18 +100,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Regex { } } - fn check_block_post(&mut self, _: &LateContext<'a, 'tcx>, block: &'tcx Block<'_>) { + fn check_block_post(&mut self, _: &LateContext<'tcx>, block: &'tcx Block<'_>) { if self.last.map_or(false, |id| block.hir_id == id) { self.last = None; } } - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { if let ExprKind::Call(ref fun, ref args) = expr.kind; if let ExprKind::Path(ref qpath) = fun.kind; if args.len() == 1; - if let Some(def_id) = cx.tables().qpath_res(qpath, fun.hir_id).opt_def_id(); + if let Some(def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id(); then { if match_def_path(cx, def_id, &paths::REGEX_NEW) || match_def_path(cx, def_id, &paths::REGEX_BUILDER_NEW) { @@ -139,7 +139,7 @@ fn str_span(base: Span, c: regex_syntax::ast::Span, offset: u16) -> Span { Span::new(start, end, base.ctxt()) } -fn const_str<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) -> Option<String> { +fn const_str<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> Option<String> { constant(cx, cx.tables(), e).and_then(|(c, _)| match c { Constant::Str(s) => Some(s), _ => None, @@ -185,7 +185,7 @@ fn is_trivial_regex(s: ®ex_syntax::hir::Hir) -> Option<&'static str> { } } -fn check_set<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>, utf8: bool) { +fn check_set<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) { if_chain! { if let ExprKind::AddrOf(BorrowKind::Ref, _, ref expr) = expr.kind; if let ExprKind::Array(exprs) = expr.kind; @@ -197,7 +197,7 @@ fn check_set<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>, utf8: b } } -fn check_regex<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>, utf8: bool) { +fn check_regex<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) { let mut parser = regex_syntax::ParserBuilder::new() .unicode(utf8) .allow_invalid_utf8(!utf8) diff --git a/src/tools/clippy/clippy_lints/src/serde_api.rs b/src/tools/clippy/clippy_lints/src/serde_api.rs index 6820d1620bd..339a7cf3bf5 100644 --- a/src/tools/clippy/clippy_lints/src/serde_api.rs +++ b/src/tools/clippy/clippy_lints/src/serde_api.rs @@ -20,8 +20,8 @@ declare_clippy_lint! { declare_lint_pass!(SerdeAPI => [SERDE_API_MISUSE]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SerdeAPI { - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for SerdeAPI { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if let ItemKind::Impl { of_trait: Some(ref trait_ref), items, diff --git a/src/tools/clippy/clippy_lints/src/shadow.rs b/src/tools/clippy/clippy_lints/src/shadow.rs index 4780249bcb8..7da47ee4ff9 100644 --- a/src/tools/clippy/clippy_lints/src/shadow.rs +++ b/src/tools/clippy/clippy_lints/src/shadow.rs @@ -96,10 +96,10 @@ declare_clippy_lint! { declare_lint_pass!(Shadow => [SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Shadow { +impl<'tcx> LateLintPass<'tcx> for Shadow { fn check_fn( &mut self, - cx: &LateContext<'a, 'tcx>, + cx: &LateContext<'tcx>, _: FnKind<'tcx>, decl: &'tcx FnDecl<'_>, body: &'tcx Body<'_>, @@ -113,7 +113,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Shadow { } } -fn check_fn<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, decl: &'tcx FnDecl<'_>, body: &'tcx Body<'_>) { +fn check_fn<'tcx>(cx: &LateContext<'tcx>, decl: &'tcx FnDecl<'_>, body: &'tcx Body<'_>) { let mut bindings = Vec::with_capacity(decl.inputs.len()); for arg in iter_input_pats(decl, body) { if let PatKind::Binding(.., ident, _) = arg.pat.kind { @@ -123,7 +123,7 @@ fn check_fn<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, decl: &'tcx FnDecl<'_>, body: check_expr(cx, &body.value, &mut bindings); } -fn check_block<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, block: &'tcx Block<'_>, bindings: &mut Vec<(Name, Span)>) { +fn check_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'_>, bindings: &mut Vec<(Name, Span)>) { let len = bindings.len(); for stmt in block.stmts { match stmt.kind { @@ -138,7 +138,7 @@ fn check_block<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, block: &'tcx Block<'_>, bin bindings.truncate(len); } -fn check_local<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, local: &'tcx Local<'_>, bindings: &mut Vec<(Name, Span)>) { +fn check_local<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>, bindings: &mut Vec<(Name, Span)>) { if in_external_macro(cx.sess(), local.span) { return; } @@ -163,7 +163,7 @@ fn check_local<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, local: &'tcx Local<'_>, bin } } -fn is_binding(cx: &LateContext<'_, '_>, pat_id: HirId) -> bool { +fn is_binding(cx: &LateContext<'_>, pat_id: HirId) -> bool { let var_ty = cx.tables().node_type_opt(pat_id); if let Some(var_ty) = var_ty { match var_ty.kind { @@ -175,8 +175,8 @@ fn is_binding(cx: &LateContext<'_, '_>, pat_id: HirId) -> bool { } } -fn check_pat<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn check_pat<'tcx>( + cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, init: Option<&'tcx Expr<'_>>, span: Span, @@ -259,8 +259,8 @@ fn check_pat<'a, 'tcx>( } } -fn lint_shadow<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn lint_shadow<'tcx>( + cx: &LateContext<'tcx>, name: Name, span: Span, pattern_span: Span, @@ -326,7 +326,7 @@ fn lint_shadow<'a, 'tcx>( } } -fn check_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>, bindings: &mut Vec<(Name, Span)>) { +fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut Vec<(Name, Span)>) { if in_external_macro(cx.sess(), expr.span) { return; } @@ -362,7 +362,7 @@ fn check_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>, bindin } } -fn check_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: &'tcx Ty<'_>, bindings: &mut Vec<(Name, Span)>) { +fn check_ty<'tcx>(cx: &LateContext<'tcx>, ty: &'tcx Ty<'_>, bindings: &mut Vec<(Name, Span)>) { match ty.kind { TyKind::Slice(ref sty) => check_ty(cx, sty, bindings), TyKind::Array(ref fty, ref anon_const) => { 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 44c9cc19cfb..96f6881556c 100644 --- a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs +++ b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs @@ -65,8 +65,8 @@ enum InitializationType<'tcx> { Resize(&'tcx Expr<'tcx>), } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SlowVectorInit { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for SlowVectorInit { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { // Matches initialization on reassignements. For example: `vec = Vec::with_capacity(100)` if_chain! { if let ExprKind::Assign(ref left, ref right, _) = expr.kind; @@ -90,7 +90,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SlowVectorInit { } } - fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt<'_>) { + fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { // Matches statements which initializes vectors. For example: `let mut vec = Vec::with_capacity(10)` if_chain! { if let StmtKind::Local(ref local) = stmt.kind; @@ -130,7 +130,7 @@ impl SlowVectorInit { } /// Search initialization for the given vector - fn search_initialization<'tcx>(cx: &LateContext<'_, 'tcx>, vec_alloc: VecAllocation<'tcx>, parent_node: HirId) { + fn search_initialization<'tcx>(cx: &LateContext<'tcx>, vec_alloc: VecAllocation<'tcx>, parent_node: HirId) { let enclosing_body = get_enclosing_block(cx, parent_node); if enclosing_body.is_none() { @@ -152,7 +152,7 @@ impl SlowVectorInit { } fn lint_initialization<'tcx>( - cx: &LateContext<'_, 'tcx>, + cx: &LateContext<'tcx>, initialization: &InitializationType<'tcx>, vec_alloc: &VecAllocation<'_>, ) { @@ -168,7 +168,7 @@ impl SlowVectorInit { } fn emit_lint<'tcx>( - cx: &LateContext<'_, 'tcx>, + cx: &LateContext<'tcx>, slow_fill: &Expr<'_>, vec_alloc: &VecAllocation<'_>, msg: &str, @@ -190,7 +190,7 @@ impl SlowVectorInit { /// `VectorInitializationVisitor` searches for unsafe or slow vector initializations for the given /// vector. struct VectorInitializationVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, /// Contains the information. vec_alloc: VecAllocation<'tcx>, diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs index ef66850358e..89aa6a4edd6 100644 --- a/src/tools/clippy/clippy_lints/src/strings.rs +++ b/src/tools/clippy/clippy_lints/src/strings.rs @@ -86,8 +86,8 @@ declare_clippy_lint! { declare_lint_pass!(StringAdd => [STRING_ADD, STRING_ADD_ASSIGN]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringAdd { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for StringAdd { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if in_external_macro(cx.sess(), e.span) { return; } @@ -133,11 +133,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringAdd { } } -fn is_string(cx: &LateContext<'_, '_>, e: &Expr<'_>) -> bool { +fn is_string(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { is_type_diagnostic_item(cx, walk_ptrs_ty(cx.tables().expr_ty(e)), sym!(string_type)) } -fn is_add(cx: &LateContext<'_, '_>, src: &Expr<'_>, target: &Expr<'_>) -> bool { +fn is_add(cx: &LateContext<'_>, src: &Expr<'_>, target: &Expr<'_>) -> bool { match src.kind { ExprKind::Binary( Spanned { @@ -158,8 +158,8 @@ const MAX_LENGTH_BYTE_STRING_LIT: usize = 32; declare_lint_pass!(StringLitAsBytes => [STRING_LIT_AS_BYTES]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { use crate::utils::{snippet, snippet_with_applicability}; use rustc_ast::ast::LitKind; diff --git a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs index cf71c3144a2..6d1d083fa8d 100644 --- a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs +++ b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs @@ -52,8 +52,8 @@ declare_clippy_lint! { declare_lint_pass!(SuspiciousImpl => [SUSPICIOUS_ARITHMETIC_IMPL, SUSPICIOUS_OP_ASSIGN_IMPL]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { if let hir::ExprKind::Binary(binop, _, _) | hir::ExprKind::AssignOp(binop, ..) = expr.kind { match binop.node { hir::BinOpKind::Eq @@ -147,7 +147,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { } fn check_binop( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, expr: &hir::Expr<'_>, binop: hir::BinOpKind, traits: &[&'static str], diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs index 7fdc872c01f..eb7d3583920 100644 --- a/src/tools/clippy/clippy_lints/src/swap.rs +++ b/src/tools/clippy/clippy_lints/src/swap.rs @@ -65,15 +65,15 @@ declare_clippy_lint! { declare_lint_pass!(Swap => [MANUAL_SWAP, ALMOST_SWAPPED]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Swap { - fn check_block(&mut self, cx: &LateContext<'a, 'tcx>, block: &'tcx Block<'_>) { +impl<'tcx> LateLintPass<'tcx> for Swap { + fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'_>) { check_manual_swap(cx, block); check_suspicious_swap(cx, block); } } /// Implementation of the `MANUAL_SWAP` lint. -fn check_manual_swap(cx: &LateContext<'_, '_>, block: &Block<'_>) { +fn check_manual_swap(cx: &LateContext<'_>, block: &Block<'_>) { for w in block.stmts.windows(3) { if_chain! { // let t = foo(); @@ -190,7 +190,7 @@ enum Slice<'a> { } /// Checks if both expressions are index operations into "slice-like" types. -fn check_for_slice<'a>(cx: &LateContext<'_, '_>, lhs1: &'a Expr<'_>, lhs2: &'a Expr<'_>) -> Slice<'a> { +fn check_for_slice<'a>(cx: &LateContext<'_>, lhs1: &'a Expr<'_>, lhs2: &'a Expr<'_>) -> Slice<'a> { if let ExprKind::Index(ref lhs1, ref idx1) = lhs1.kind { if let ExprKind::Index(ref lhs2, ref idx2) = lhs2.kind { if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, lhs2) { @@ -213,7 +213,7 @@ fn check_for_slice<'a>(cx: &LateContext<'_, '_>, lhs1: &'a Expr<'_>, lhs2: &'a E } /// Implementation of the `ALMOST_SWAPPED` lint. -fn check_suspicious_swap(cx: &LateContext<'_, '_>, block: &Block<'_>) { +fn check_suspicious_swap(cx: &LateContext<'_>, block: &Block<'_>) { for w in block.stmts.windows(2) { if_chain! { if let StmtKind::Semi(ref first) = w[0].kind; diff --git a/src/tools/clippy/clippy_lints/src/temporary_assignment.rs b/src/tools/clippy/clippy_lints/src/temporary_assignment.rs index f2bbf19bea9..509bbfd27c1 100644 --- a/src/tools/clippy/clippy_lints/src/temporary_assignment.rs +++ b/src/tools/clippy/clippy_lints/src/temporary_assignment.rs @@ -22,11 +22,11 @@ declare_clippy_lint! { "assignments to temporaries" } -fn is_temporary(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { +fn is_temporary(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { match &expr.kind { ExprKind::Struct(..) | ExprKind::Tup(..) => true, ExprKind::Path(qpath) => { - if let Res::Def(DefKind::Const, ..) = cx.tables().qpath_res(qpath, expr.hir_id) { + if let Res::Def(DefKind::Const, ..) = cx.qpath_res(qpath, expr.hir_id) { true } else { false @@ -38,8 +38,8 @@ fn is_temporary(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { declare_lint_pass!(TemporaryAssignment => [TEMPORARY_ASSIGNMENT]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TemporaryAssignment { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for TemporaryAssignment { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let ExprKind::Assign(target, ..) = &expr.kind { let mut base = target; while let ExprKind::Field(f, _) | ExprKind::Index(f, _) = &base.kind { diff --git a/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs b/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs index 1efba3580fe..4157103a574 100644 --- a/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs +++ b/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs @@ -31,8 +31,8 @@ declare_clippy_lint! { declare_lint_pass!(ToDigitIsSome => [TO_DIGIT_IS_SOME]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ToDigitIsSome { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for ToDigitIsSome { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { if_chain! { if let hir::ExprKind::MethodCall(is_some_path, _, is_some_args, _) = &expr.kind; if is_some_path.ident.name.as_str() == "is_some"; @@ -56,7 +56,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ToDigitIsSome { if_chain! { if let [char_arg, radix_arg] = &**to_digit_args; if let hir::ExprKind::Path(to_digits_path) = &to_digits_call.kind; - if let to_digits_call_res = cx.tables().qpath_res(to_digits_path, to_digits_call.hir_id); + if let to_digits_call_res = cx.qpath_res(to_digits_path, to_digits_call.hir_id); if let Some(to_digits_def_id) = to_digits_call_res.opt_def_id(); if match_def_path(cx, to_digits_def_id, &["core", "char", "methods", "<impl char>", "to_digit"]); then { diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs index 1b233b8302f..9eb2079c3ca 100644 --- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs +++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs @@ -31,13 +31,13 @@ declare_clippy_lint! { impl_lint_pass!(TraitBounds => [TYPE_REPETITION_IN_BOUNDS]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TraitBounds { - fn check_generics(&mut self, cx: &LateContext<'a, 'tcx>, gen: &'tcx Generics<'_>) { +impl<'tcx> LateLintPass<'tcx> for TraitBounds { + fn check_generics(&mut self, cx: &LateContext<'tcx>, gen: &'tcx Generics<'_>) { if in_macro(gen.span) { return; } let hash = |ty| -> u64 { - let mut hasher = SpanlessHash::new(cx, cx.tables()); + let mut hasher = SpanlessHash::new(cx); hasher.hash_ty(ty); hasher.finish() }; diff --git a/src/tools/clippy/clippy_lints/src/transmute.rs b/src/tools/clippy/clippy_lints/src/transmute.rs index 9b134494947..5f76d5c46ef 100644 --- a/src/tools/clippy/clippy_lints/src/transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute.rs @@ -293,13 +293,13 @@ static COLLECTIONS: &[&[&str]] = &[ &paths::HASHSET, &paths::HASHMAP, ]; -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { +impl<'tcx> LateLintPass<'tcx> for Transmute { #[allow(clippy::similar_names, clippy::too_many_lines)] - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if_chain! { if let ExprKind::Call(ref path_expr, ref args) = e.kind; if let ExprKind::Path(ref qpath) = path_expr.kind; - if let Some(def_id) = cx.tables().qpath_res(qpath, path_expr.hir_id).opt_def_id(); + if let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id(); if match_def_path(cx, def_id, &paths::TRANSMUTE); then { let from_ty = cx.tables().expr_ty(&args[0]); @@ -613,7 +613,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { /// the type's `ToString` implementation. In weird cases it could lead to types /// with invalid `'_` /// lifetime, but it should be rare. -fn get_type_snippet(cx: &LateContext<'_, '_>, path: &QPath<'_>, to_ref_ty: Ty<'_>) -> String { +fn get_type_snippet(cx: &LateContext<'_>, path: &QPath<'_>, to_ref_ty: Ty<'_>) -> String { let seg = last_path_segment(path); if_chain! { if let Some(ref params) = seg.args; @@ -633,7 +633,7 @@ fn get_type_snippet(cx: &LateContext<'_, '_>, path: &QPath<'_>, to_ref_ty: Ty<'_ // check if the component types of the transmuted collection and the result have different ABI, // size or alignment -fn is_layout_incompatible<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, from: Ty<'tcx>, to: Ty<'tcx>) -> bool { +fn is_layout_incompatible<'tcx>(cx: &LateContext<'tcx>, from: Ty<'tcx>, to: Ty<'tcx>) -> bool { let empty_param_env = ty::ParamEnv::empty(); // check if `from` and `to` are normalizable to avoid ICE (#4968) if !(is_normalizable(cx, empty_param_env, from) && is_normalizable(cx, empty_param_env, to)) { diff --git a/src/tools/clippy/clippy_lints/src/transmuting_null.rs b/src/tools/clippy/clippy_lints/src/transmuting_null.rs index 3351488a45c..2f03c6db42d 100644 --- a/src/tools/clippy/clippy_lints/src/transmuting_null.rs +++ b/src/tools/clippy/clippy_lints/src/transmuting_null.rs @@ -29,8 +29,8 @@ declare_lint_pass!(TransmutingNull => [TRANSMUTING_NULL]); const LINT_MSG: &str = "transmuting a known null pointer into a reference."; -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TransmutingNull { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for TransmutingNull { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if in_external_macro(cx.sess(), expr.span) { return; } diff --git a/src/tools/clippy/clippy_lints/src/trivially_copy_pass_by_ref.rs b/src/tools/clippy/clippy_lints/src/trivially_copy_pass_by_ref.rs index 146ac4b09d5..6a2b05e3e6d 100644 --- a/src/tools/clippy/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/src/tools/clippy/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -73,7 +73,7 @@ impl<'tcx> TriviallyCopyPassByRef { Self { limit } } - fn check_poly_fn(&mut self, cx: &LateContext<'_, 'tcx>, hir_id: HirId, decl: &FnDecl<'_>, span: Option<Span>) { + fn check_poly_fn(&mut self, cx: &LateContext<'tcx>, hir_id: HirId, decl: &FnDecl<'_>, span: Option<Span>) { let fn_def_id = cx.tcx.hir().local_def_id(hir_id); let fn_sig = cx.tcx.fn_sig(fn_def_id); @@ -125,8 +125,8 @@ impl<'tcx> TriviallyCopyPassByRef { impl_lint_pass!(TriviallyCopyPassByRef => [TRIVIALLY_COPY_PASS_BY_REF]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { - fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::TraitItem<'_>) { +impl<'tcx> LateLintPass<'tcx> for TriviallyCopyPassByRef { + fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) { if item.span.from_expansion() { return; } @@ -138,7 +138,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { fn check_fn( &mut self, - cx: &LateContext<'a, 'tcx>, + cx: &LateContext<'tcx>, kind: FnKind<'tcx>, decl: &'tcx FnDecl<'_>, _body: &'tcx Body<'_>, diff --git a/src/tools/clippy/clippy_lints/src/try_err.rs b/src/tools/clippy/clippy_lints/src/try_err.rs index e129dd84d15..208d248faa5 100644 --- a/src/tools/clippy/clippy_lints/src/try_err.rs +++ b/src/tools/clippy/clippy_lints/src/try_err.rs @@ -43,8 +43,8 @@ declare_clippy_lint! { declare_lint_pass!(TryErr => [TRY_ERR]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TryErr { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for TryErr { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { // Looks for a structure like this: // match ::std::ops::Try::into_result(Err(5)) { // ::std::result::Result::Err(err) => @@ -97,7 +97,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TryErr { // In order to determine whether to suggest `.into()` or not, we need to find the error type the // function returns. To do that, we look for the From::from call (see tree above), and capture // its output type. -fn find_err_return_type<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx ExprKind<'_>) -> Option<Ty<'tcx>> { +fn find_err_return_type<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx ExprKind<'_>) -> Option<Ty<'tcx>> { if let ExprKind::Match(_, ref arms, MatchSource::TryDesugar) = expr { arms.iter().find_map(|ty| find_err_return_type_arm(cx, ty)) } else { @@ -106,7 +106,7 @@ fn find_err_return_type<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx ExprKi } // Check for From::from in one of the match arms. -fn find_err_return_type_arm<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arm: &'tcx Arm<'_>) -> Option<Ty<'tcx>> { +fn find_err_return_type_arm<'tcx>(cx: &LateContext<'tcx>, arm: &'tcx Arm<'_>) -> Option<Ty<'tcx>> { if_chain! { if let ExprKind::Ret(Some(ref err_ret)) = arm.body.kind; if let ExprKind::Call(ref from_error_path, ref from_error_args) = err_ret.kind; diff --git a/src/tools/clippy/clippy_lints/src/types.rs b/src/tools/clippy/clippy_lints/src/types.rs index ecfb6ee2a7d..b1345f0de5e 100644 --- a/src/tools/clippy/clippy_lints/src/types.rs +++ b/src/tools/clippy/clippy_lints/src/types.rs @@ -218,16 +218,8 @@ pub struct Types { impl_lint_pass!(Types => [BOX_VEC, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX, REDUNDANT_ALLOCATION]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Types { - fn check_fn( - &mut self, - cx: &LateContext<'_, '_>, - _: FnKind<'_>, - decl: &FnDecl<'_>, - _: &Body<'_>, - _: Span, - id: HirId, - ) { +impl<'tcx> LateLintPass<'tcx> for Types { + fn check_fn(&mut self, cx: &LateContext<'_>, _: FnKind<'_>, decl: &FnDecl<'_>, _: &Body<'_>, _: Span, id: HirId) { // Skip trait implementations; see issue #605. if let Some(hir::Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_item(id)) { if let ItemKind::Impl { of_trait: Some(_), .. } = item.kind { @@ -238,11 +230,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Types { self.check_fn_decl(cx, decl); } - fn check_struct_field(&mut self, cx: &LateContext<'_, '_>, field: &hir::StructField<'_>) { + fn check_struct_field(&mut self, cx: &LateContext<'_>, field: &hir::StructField<'_>) { self.check_ty(cx, &field.ty, false); } - fn check_trait_item(&mut self, cx: &LateContext<'_, '_>, item: &TraitItem<'_>) { + fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &TraitItem<'_>) { match item.kind { TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => self.check_ty(cx, ty, false), TraitItemKind::Fn(ref sig, _) => self.check_fn_decl(cx, &sig.decl), @@ -250,7 +242,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Types { } } - fn check_local(&mut self, cx: &LateContext<'_, '_>, local: &Local<'_>) { + fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) { if let Some(ref ty) = local.ty { self.check_ty(cx, ty, true); } @@ -258,7 +250,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Types { } /// Checks if `qpath` has last segment with type parameter matching `path` -fn match_type_parameter(cx: &LateContext<'_, '_>, qpath: &QPath<'_>, path: &[&str]) -> Option<Span> { +fn match_type_parameter(cx: &LateContext<'_>, qpath: &QPath<'_>, path: &[&str]) -> Option<Span> { let last = last_path_segment(qpath); if_chain! { if let Some(ref params) = last.args; @@ -277,7 +269,7 @@ fn match_type_parameter(cx: &LateContext<'_, '_>, qpath: &QPath<'_>, path: &[&st None } -fn match_borrows_parameter(_cx: &LateContext<'_, '_>, qpath: &QPath<'_>) -> Option<Span> { +fn match_borrows_parameter(_cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<Span> { let last = last_path_segment(qpath); if_chain! { if let Some(ref params) = last.args; @@ -299,7 +291,7 @@ impl Types { Self { vec_box_size_threshold } } - fn check_fn_decl(&mut self, cx: &LateContext<'_, '_>, decl: &FnDecl<'_>) { + fn check_fn_decl(&mut self, cx: &LateContext<'_>, decl: &FnDecl<'_>) { for input in decl.inputs { self.check_ty(cx, input, false); } @@ -315,7 +307,7 @@ impl Types { /// The parameter `is_local` distinguishes the context of the type; types from /// local bindings should only be checked for the `BORROWED_BOX` lint. #[allow(clippy::too_many_lines)] - fn check_ty(&mut self, cx: &LateContext<'_, '_>, hir_ty: &hir::Ty<'_>, is_local: bool) { + fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, is_local: bool) { if hir_ty.span.from_expansion() { return; } @@ -501,7 +493,7 @@ impl Types { fn check_ty_rptr( &mut self, - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, is_local: bool, lt: &Lifetime, @@ -600,8 +592,8 @@ declare_clippy_lint! { declare_lint_pass!(LetUnitValue => [LET_UNIT_VALUE]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetUnitValue { - fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt<'_>) { +impl<'tcx> LateLintPass<'tcx> for LetUnitValue { + fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { if let StmtKind::Local(ref local) = stmt.kind { if is_unit(cx.tables().pat_ty(&local.pat)) { if in_external_macro(cx.sess(), stmt.span) || local.pat.span.from_expansion() { @@ -681,8 +673,8 @@ declare_clippy_lint! { declare_lint_pass!(UnitCmp => [UNIT_CMP]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitCmp { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'tcx>) { +impl<'tcx> LateLintPass<'tcx> for UnitCmp { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { if expr.span.from_expansion() { if let Some(callee) = expr.span.source_callee() { if let ExpnKind::Macro(MacroKind::Bang, symbol) = callee.kind { @@ -754,8 +746,8 @@ declare_clippy_lint! { declare_lint_pass!(UnitArg => [UNIT_ARG]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for UnitArg { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if expr.span.from_expansion() { return; } @@ -802,7 +794,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg { } } -fn lint_unit_args(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args_to_recover: &[&Expr<'_>]) { +fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Expr<'_>]) { let mut applicability = Applicability::MachineApplicable; let (singular, plural) = if args_to_recover.len() > 1 { ("", "s") @@ -1168,7 +1160,7 @@ fn is_isize_or_usize(typ: Ty<'_>) -> bool { } } -fn span_precision_loss_lint(cx: &LateContext<'_, '_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to_f64: bool) { +fn span_precision_loss_lint(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to_f64: bool) { let mantissa_nbits = if cast_to_f64 { 52 } else { 23 }; let arch_dependent = is_isize_or_usize(cast_from) && cast_to_f64; let arch_dependent_str = "on targets with 64-bit wide pointers "; @@ -1204,7 +1196,7 @@ fn should_strip_parens(op: &Expr<'_>, snip: &str) -> bool { false } -fn span_lossless_lint(cx: &LateContext<'_, '_>, expr: &Expr<'_>, op: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) { +fn span_lossless_lint(cx: &LateContext<'_>, expr: &Expr<'_>, op: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) { // Do not suggest using From in consts/statics until it is valid to do so (see #2267). if in_constant(cx, expr.hir_id) { return; @@ -1244,7 +1236,7 @@ enum ArchSuffix { None, } -fn check_loss_of_sign(cx: &LateContext<'_, '_>, expr: &Expr<'_>, op: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) { +fn check_loss_of_sign(cx: &LateContext<'_>, expr: &Expr<'_>, op: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) { if !cast_from.is_signed() || cast_to.is_signed() { return; } @@ -1291,7 +1283,7 @@ fn check_loss_of_sign(cx: &LateContext<'_, '_>, expr: &Expr<'_>, op: &Expr<'_>, ); } -fn check_truncation_and_wrapping(cx: &LateContext<'_, '_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) { +fn check_truncation_and_wrapping(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) { let arch_64_suffix = " on targets with 64-bit wide pointers"; let arch_32_suffix = " on targets with 32-bit wide pointers"; let cast_unsigned_to_signed = !cast_from.is_signed() && cast_to.is_signed(); @@ -1362,7 +1354,7 @@ fn check_truncation_and_wrapping(cx: &LateContext<'_, '_>, expr: &Expr<'_>, cast } } -fn check_lossless(cx: &LateContext<'_, '_>, expr: &Expr<'_>, op: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) { +fn check_lossless(cx: &LateContext<'_>, expr: &Expr<'_>, op: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) { let cast_signed_to_unsigned = cast_from.is_signed() && !cast_to.is_signed(); let from_nbits = int_ty_to_nbits(cast_from, cx.tcx); let to_nbits = int_ty_to_nbits(cast_to, cx.tcx); @@ -1386,7 +1378,7 @@ declare_lint_pass!(Casts => [ // Check if the given type is either `core::ffi::c_void` or // one of the platform specific `libc::<platform>::c_void` of libc. -fn is_c_void(cx: &LateContext<'_, '_>, ty: Ty<'_>) -> bool { +fn is_c_void(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { if let ty::Adt(adt, _) = ty.kind { let names = cx.get_def_path(adt.did); @@ -1410,8 +1402,8 @@ fn fp_ty_mantissa_nbits(typ: Ty<'_>) -> u32 { } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Casts { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for Casts { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if expr.span.from_expansion() { return; } @@ -1467,7 +1459,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Casts { } fn lint_numeric_casts<'tcx>( - cx: &LateContext<'_, 'tcx>, + cx: &LateContext<'tcx>, expr: &Expr<'tcx>, cast_expr: &Expr<'_>, cast_from: Ty<'tcx>, @@ -1528,7 +1520,7 @@ fn lint_numeric_casts<'tcx>( } } -fn lint_cast_ptr_alignment<'tcx>(cx: &LateContext<'_, 'tcx>, expr: &Expr<'_>, cast_from: Ty<'tcx>, cast_to: Ty<'tcx>) { +fn lint_cast_ptr_alignment<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, cast_from: Ty<'tcx>, cast_to: Ty<'tcx>) { if_chain! { if let ty::RawPtr(from_ptr_ty) = &cast_from.kind; if let ty::RawPtr(to_ptr_ty) = &cast_to.kind; @@ -1557,7 +1549,7 @@ fn lint_cast_ptr_alignment<'tcx>(cx: &LateContext<'_, 'tcx>, expr: &Expr<'_>, ca } fn lint_fn_to_numeric_cast( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_from: Ty<'_>, @@ -1637,10 +1629,10 @@ impl TypeComplexity { impl_lint_pass!(TypeComplexity => [TYPE_COMPLEXITY]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexity { +impl<'tcx> LateLintPass<'tcx> for TypeComplexity { fn check_fn( &mut self, - cx: &LateContext<'a, 'tcx>, + cx: &LateContext<'tcx>, _: FnKind<'tcx>, decl: &'tcx FnDecl<'_>, _: &'tcx Body<'_>, @@ -1650,12 +1642,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexity { self.check_fndecl(cx, decl); } - fn check_struct_field(&mut self, cx: &LateContext<'a, 'tcx>, field: &'tcx hir::StructField<'_>) { + fn check_struct_field(&mut self, cx: &LateContext<'tcx>, field: &'tcx hir::StructField<'_>) { // enum variants are also struct fields now self.check_type(cx, &field.ty); } - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'_>) { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { match item.kind { ItemKind::Static(ref ty, _, _) | ItemKind::Const(ref ty, _) => self.check_type(cx, ty), // functions, enums, structs, impls and traits are covered @@ -1663,7 +1655,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexity { } } - fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem<'_>) { + fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { match item.kind { TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => self.check_type(cx, ty), TraitItemKind::Fn(FnSig { ref decl, .. }, TraitFn::Required(_)) => self.check_fndecl(cx, decl), @@ -1672,7 +1664,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexity { } } - fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem<'_>) { + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) { match item.kind { ImplItemKind::Const(ref ty, _) | ImplItemKind::TyAlias(ref ty) => self.check_type(cx, ty), // methods are covered by check_fn @@ -1680,15 +1672,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexity { } } - fn check_local(&mut self, cx: &LateContext<'a, 'tcx>, local: &'tcx Local<'_>) { + fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'_>) { if let Some(ref ty) = local.ty { self.check_type(cx, ty); } } } -impl<'a, 'tcx> TypeComplexity { - fn check_fndecl(&self, cx: &LateContext<'a, 'tcx>, decl: &'tcx FnDecl<'_>) { +impl<'tcx> TypeComplexity { + fn check_fndecl(&self, cx: &LateContext<'tcx>, decl: &'tcx FnDecl<'_>) { for arg in decl.inputs { self.check_type(cx, arg); } @@ -1697,7 +1689,7 @@ impl<'a, 'tcx> TypeComplexity { } } - fn check_type(&self, cx: &LateContext<'_, '_>, ty: &hir::Ty<'_>) { + fn check_type(&self, cx: &LateContext<'_>, ty: &hir::Ty<'_>) { if ty.span.from_expansion() { return; } @@ -1797,8 +1789,8 @@ declare_clippy_lint! { declare_lint_pass!(CharLitAsU8 => [CHAR_LIT_AS_U8]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CharLitAsU8 { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for CharLitAsU8 { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { if !expr.span.from_expansion(); if let ExprKind::Cast(e, _) = &expr.kind; @@ -1878,7 +1870,7 @@ enum AbsurdComparisonResult { InequalityImpossible, } -fn is_cast_between_fixed_and_target<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'tcx>) -> bool { +fn is_cast_between_fixed_and_target<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { if let ExprKind::Cast(ref cast_exp, _) = expr.kind { let precast_ty = cx.tables().expr_ty(cast_exp); let cast_ty = cx.tables().expr_ty(expr); @@ -1889,8 +1881,8 @@ fn is_cast_between_fixed_and_target<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: false } -fn detect_absurd_comparison<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn detect_absurd_comparison<'tcx>( + cx: &LateContext<'tcx>, op: BinOpKind, lhs: &'tcx Expr<'_>, rhs: &'tcx Expr<'_>, @@ -1936,7 +1928,7 @@ fn detect_absurd_comparison<'a, 'tcx>( }) } -fn detect_extreme_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) -> Option<ExtremeExpr<'tcx>> { +fn detect_extreme_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<ExtremeExpr<'tcx>> { use crate::types::ExtremeType::{Maximum, Minimum}; let ty = cx.tables().expr_ty(expr); @@ -1960,8 +1952,8 @@ fn detect_extreme_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_ Some(ExtremeExpr { which, expr }) } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AbsurdExtremeComparisons { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for AbsurdExtremeComparisons { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { use crate::types::AbsurdComparisonResult::{AlwaysFalse, AlwaysTrue, InequalityImpossible}; use crate::types::ExtremeType::{Maximum, Minimum}; @@ -2069,7 +2061,7 @@ impl Ord for FullInt { } } -fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr<'_>) -> Option<(FullInt, FullInt)> { +fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_>, expr: &'a Expr<'_>) -> Option<(FullInt, FullInt)> { if let ExprKind::Cast(ref cast_exp, _) = expr.kind { let pre_cast_ty = cx.tables().expr_ty(cast_exp); let cast_ty = cx.tables().expr_ty(expr); @@ -2101,7 +2093,7 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr<'_>) } } -fn node_as_const_fullint<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) -> Option<FullInt> { +fn node_as_const_fullint<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<FullInt> { let val = constant(cx, cx.tables(), expr)?.0; if let Constant::Int(const_int) = val { match cx.tables().expr_ty(expr).kind { @@ -2114,7 +2106,7 @@ fn node_as_const_fullint<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr< } } -fn err_upcast_comparison(cx: &LateContext<'_, '_>, span: Span, expr: &Expr<'_>, always: bool) { +fn err_upcast_comparison(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, always: bool) { if let ExprKind::Cast(ref cast_val, _) = expr.kind { span_lint( cx, @@ -2129,8 +2121,8 @@ fn err_upcast_comparison(cx: &LateContext<'_, '_>, span: Span, expr: &Expr<'_>, } } -fn upcast_comparison_bounds_err<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn upcast_comparison_bounds_err<'tcx>( + cx: &LateContext<'tcx>, span: Span, rel: comparisons::Rel, lhs_bounds: Option<(FullInt, FullInt)>, @@ -2187,8 +2179,8 @@ fn upcast_comparison_bounds_err<'a, 'tcx>( } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidUpcastComparisons { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for InvalidUpcastComparisons { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let ExprKind::Binary(ref cmp, ref lhs, ref rhs) = expr.kind { let normalized = comparisons::normalize_comparison(cmp.node, lhs, rhs); let (rel, normalized_lhs, normalized_rhs) = if let Some(val) = normalized { @@ -2243,13 +2235,13 @@ declare_clippy_lint! { declare_lint_pass!(ImplicitHasher => [IMPLICIT_HASHER]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { +impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { #[allow(clippy::cast_possible_truncation, clippy::too_many_lines)] - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'_>) { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { use rustc_span::BytePos; - fn suggestion<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, + fn suggestion<'tcx>( + cx: &LateContext<'tcx>, diag: &mut DiagnosticBuilder<'_>, generics_span: Span, generics_suggestion_span: Span, @@ -2393,7 +2385,7 @@ enum ImplicitHasherType<'tcx> { impl<'tcx> ImplicitHasherType<'tcx> { /// Checks that `ty` is a target type without a `BuildHasher`. - fn new<'a>(cx: &LateContext<'a, 'tcx>, hir_ty: &hir::Ty<'_>) -> Option<Self> { + fn new(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'_>) -> Option<Self> { if let TyKind::Path(QPath::Resolved(None, ref path)) = hir_ty.kind { let params: Vec<_> = path .segments @@ -2461,12 +2453,12 @@ impl<'tcx> ImplicitHasherType<'tcx> { } struct ImplicitHasherTypeVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, found: Vec<ImplicitHasherType<'tcx>>, } impl<'a, 'tcx> ImplicitHasherTypeVisitor<'a, 'tcx> { - fn new(cx: &'a LateContext<'a, 'tcx>) -> Self { + fn new(cx: &'a LateContext<'tcx>) -> Self { Self { cx, found: vec![] } } } @@ -2489,17 +2481,17 @@ impl<'a, 'tcx> Visitor<'tcx> for ImplicitHasherTypeVisitor<'a, 'tcx> { /// Looks for default-hasher-dependent constructors like `HashMap::new`. struct ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, - body: &'a TypeckTables<'tcx>, + cx: &'a LateContext<'tcx>, + maybe_typeck_tables: Option<&'tcx TypeckTables<'tcx>>, target: &'b ImplicitHasherType<'tcx>, suggestions: BTreeMap<Span, String>, } impl<'a, 'b, 'tcx> ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> { - fn new(cx: &'a LateContext<'a, 'tcx>, target: &'b ImplicitHasherType<'tcx>) -> Self { + fn new(cx: &'a LateContext<'tcx>, target: &'b ImplicitHasherType<'tcx>) -> Self { Self { cx, - body: cx.tables(), + maybe_typeck_tables: cx.maybe_typeck_tables(), target, suggestions: BTreeMap::new(), } @@ -2510,10 +2502,9 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'a, 'b, 't type Map = Map<'tcx>; fn visit_body(&mut self, body: &'tcx Body<'_>) { - let prev_body = self.body; - self.body = self.cx.tcx.body_tables(body.id()); + let old_maybe_typeck_tables = self.maybe_typeck_tables.replace(self.cx.tcx.body_tables(body.id())); walk_body(self, body); - self.body = prev_body; + self.maybe_typeck_tables = old_maybe_typeck_tables; } fn visit_expr(&mut self, e: &'tcx Expr<'_>) { @@ -2522,7 +2513,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'a, 'b, 't if let ExprKind::Path(QPath::TypeRelative(ref ty, ref method)) = fun.kind; if let TyKind::Path(QPath::Resolved(None, ty_path)) = ty.kind; then { - if !TyS::same_type(self.target.ty(), self.body.expr_ty(e)) { + if !TyS::same_type(self.target.ty(), self.maybe_typeck_tables.unwrap().expr_ty(e)) { return; } @@ -2600,8 +2591,8 @@ declare_clippy_lint! { declare_lint_pass!(RefToMut => [CAST_REF_TO_MUT]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RefToMut { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for RefToMut { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { if let ExprKind::Unary(UnOp::UnDeref, e) = &expr.kind; if let ExprKind::Cast(e, t) = &e.kind; diff --git a/src/tools/clippy/clippy_lints/src/unicode.rs b/src/tools/clippy/clippy_lints/src/unicode.rs index d073c197656..d8c57f0e7ae 100644 --- a/src/tools/clippy/clippy_lints/src/unicode.rs +++ b/src/tools/clippy/clippy_lints/src/unicode.rs @@ -65,8 +65,8 @@ declare_clippy_lint! { declare_lint_pass!(Unicode => [ZERO_WIDTH_SPACE, NON_ASCII_LITERAL, UNICODE_NOT_NFC]); -impl LateLintPass<'_, '_> for Unicode { - fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &'_ Expr<'_>) { +impl LateLintPass<'_> for Unicode { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) { if let ExprKind::Lit(ref lit) = expr.kind { if let LitKind::Str(_, _) = lit.node { check_str(cx, lit.span, expr.hir_id) @@ -89,7 +89,7 @@ fn escape<T: Iterator<Item = char>>(s: T) -> String { result } -fn check_str(cx: &LateContext<'_, '_>, span: Span, id: HirId) { +fn check_str(cx: &LateContext<'_>, span: Span, id: HirId) { let string = snippet(cx, span, ""); if string.contains('\u{200B}') { span_lint_and_sugg( diff --git a/src/tools/clippy/clippy_lints/src/unnamed_address.rs b/src/tools/clippy/clippy_lints/src/unnamed_address.rs index 53e47f09ae5..b9aa202b328 100644 --- a/src/tools/clippy/clippy_lints/src/unnamed_address.rs +++ b/src/tools/clippy/clippy_lints/src/unnamed_address.rs @@ -55,8 +55,8 @@ declare_clippy_lint! { declare_lint_pass!(UnnamedAddress => [FN_ADDRESS_COMPARISONS, VTABLE_ADDRESS_COMPARISONS]); -impl LateLintPass<'_, '_> for UnnamedAddress { - fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) { +impl LateLintPass<'_> for UnnamedAddress { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { fn is_comparison(binop: BinOpKind) -> bool { match binop { BinOpKind::Eq | BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ne | BinOpKind::Ge | BinOpKind::Gt => true, @@ -64,14 +64,14 @@ impl LateLintPass<'_, '_> for UnnamedAddress { } } - fn is_trait_ptr(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { + fn is_trait_ptr(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { match cx.tables().expr_ty_adjusted(expr).kind { ty::RawPtr(ty::TypeAndMut { ty, .. }) => ty.is_trait(), _ => false, } } - fn is_fn_def(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { + fn is_fn_def(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { if let ty::FnDef(..) = cx.tables().expr_ty(expr).kind { true } else { @@ -98,7 +98,7 @@ impl LateLintPass<'_, '_> for UnnamedAddress { if_chain! { if let ExprKind::Call(ref func, [ref _left, ref _right]) = expr.kind; if let ExprKind::Path(ref func_qpath) = func.kind; - if let Some(def_id) = cx.tables().qpath_res(func_qpath, func.hir_id).opt_def_id(); + if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); if match_def_path(cx, def_id, &paths::PTR_EQ) || match_def_path(cx, def_id, &paths::RC_PTR_EQ) || match_def_path(cx, def_id, &paths::ARC_PTR_EQ); diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs b/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs index bb68e50b331..d940776817c 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs @@ -67,7 +67,7 @@ struct SortByKeyDetection { /// Detect if the two expressions are mirrored (identical, except one /// contains a and the other replaces it with b) fn mirrored_exprs( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, a_expr: &Expr<'_>, a_ident: &Ident, b_expr: &Expr<'_>, @@ -171,7 +171,7 @@ fn mirrored_exprs( } } -fn detect_lint(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<LintTrigger> { +fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<LintTrigger> { if_chain! { if let ExprKind::MethodCall(name_ident, _, args, _) = &expr.kind; if let name = name_ident.ident.name.to_ident_string(); @@ -225,8 +225,8 @@ fn detect_lint(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<LintTrigger> } } -impl LateLintPass<'_, '_> for UnnecessarySortBy { - fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) { +impl LateLintPass<'_> for UnnecessarySortBy { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { match detect_lint(cx, expr) { Some(LintTrigger::SortByKey(trigger)) => utils::span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs index 5f4b5fd9dd9..1580f657d77 100644 --- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs +++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs @@ -32,8 +32,8 @@ declare_clippy_lint! { declare_lint_pass!(UnusedIoAmount => [UNUSED_IO_AMOUNT]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount { - fn check_stmt(&mut self, cx: &LateContext<'_, '_>, s: &hir::Stmt<'_>) { +impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount { + fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) { let expr = match s.kind { hir::StmtKind::Semi(ref expr) | hir::StmtKind::Expr(ref expr) => &**expr, _ => return, @@ -64,7 +64,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount { } } -fn check_method_call(cx: &LateContext<'_, '_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>) { +fn check_method_call(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>) { if let hir::ExprKind::MethodCall(ref path, _, _, _) = call.kind { let symbol = &*path.ident.as_str(); let read_trait = match_trait_method(cx, call, &paths::IO_READ); diff --git a/src/tools/clippy/clippy_lints/src/unused_self.rs b/src/tools/clippy/clippy_lints/src/unused_self.rs index 3d5e2f9fd21..da7517125c1 100644 --- a/src/tools/clippy/clippy_lints/src/unused_self.rs +++ b/src/tools/clippy/clippy_lints/src/unused_self.rs @@ -39,8 +39,8 @@ declare_clippy_lint! { declare_lint_pass!(UnusedSelf => [UNUSED_SELF]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedSelf { - fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &ImplItem<'_>) { +impl<'tcx> LateLintPass<'tcx> for UnusedSelf { + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &ImplItem<'_>) { if impl_item.span.from_expansion() { return; } @@ -80,7 +80,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedSelf { } struct UnusedSelfVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, uses_self: bool, self_hir_id: &'a HirId, } diff --git a/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs index be55982f905..56ff62eca03 100644 --- a/src/tools/clippy/clippy_lints/src/unwrap.rs +++ b/src/tools/clippy/clippy_lints/src/unwrap.rs @@ -68,7 +68,7 @@ declare_clippy_lint! { /// Visitor that keeps track of which variables are unwrappable. struct UnwrappableVariablesVisitor<'a, 'tcx> { unwrappables: Vec<UnwrapInfo<'tcx>>, - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, } /// Contains information about whether a variable can be unwrapped. #[derive(Copy, Clone, Debug)] @@ -85,17 +85,17 @@ struct UnwrapInfo<'tcx> { /// Collects the information about unwrappable variables from an if condition /// The `invert` argument tells us whether the condition is negated. -fn collect_unwrap_info<'a, 'tcx>( - cx: &'a LateContext<'a, 'tcx>, +fn collect_unwrap_info<'tcx>( + cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, branch: &'tcx Expr<'_>, invert: bool, ) -> Vec<UnwrapInfo<'tcx>> { - fn is_relevant_option_call(cx: &LateContext<'_, '_>, ty: Ty<'_>, method_name: &str) -> bool { + fn is_relevant_option_call(cx: &LateContext<'_>, ty: Ty<'_>, method_name: &str) -> bool { is_type_diagnostic_item(cx, ty, sym!(option_type)) && ["is_some", "is_none"].contains(&method_name) } - fn is_relevant_result_call(cx: &LateContext<'_, '_>, ty: Ty<'_>, method_name: &str) -> bool { + fn is_relevant_result_call(cx: &LateContext<'_>, ty: Ty<'_>, method_name: &str) -> bool { is_type_diagnostic_item(cx, ty, sym!(result_type)) && ["is_ok", "is_err"].contains(&method_name) } @@ -209,10 +209,10 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { declare_lint_pass!(Unwrap => [PANICKING_UNWRAP, UNNECESSARY_UNWRAP]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Unwrap { +impl<'tcx> LateLintPass<'tcx> for Unwrap { fn check_fn( &mut self, - cx: &LateContext<'a, 'tcx>, + cx: &LateContext<'tcx>, kind: FnKind<'tcx>, decl: &'tcx FnDecl<'_>, body: &'tcx Body<'_>, diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs index f8e1aff33e7..f85db1e2006 100644 --- a/src/tools/clippy/clippy_lints/src/use_self.rs +++ b/src/tools/clippy/clippy_lints/src/use_self.rs @@ -57,7 +57,7 @@ declare_lint_pass!(UseSelf => [USE_SELF]); const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element"; -fn span_use_self_lint(cx: &LateContext<'_, '_>, path: &Path<'_>, last_segment: Option<&PathSegment<'_>>) { +fn span_use_self_lint(cx: &LateContext<'_>, path: &Path<'_>, last_segment: Option<&PathSegment<'_>>) { let last_segment = last_segment.unwrap_or_else(|| path.segments.last().expect(SEGMENTS_MSG)); // Path segments only include actual path, no methods or fields. @@ -83,7 +83,7 @@ fn span_use_self_lint(cx: &LateContext<'_, '_>, path: &Path<'_>, last_segment: O // FIXME: always use this (more correct) visitor, not just in method signatures. struct SemanticUseSelfVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, self_ty: Ty<'tcx>, } @@ -110,8 +110,8 @@ impl<'a, 'tcx> Visitor<'tcx> for SemanticUseSelfVisitor<'a, 'tcx> { } } -fn check_trait_method_impl_decl<'a, 'tcx>( - cx: &'a LateContext<'a, 'tcx>, +fn check_trait_method_impl_decl<'tcx>( + cx: &LateContext<'tcx>, impl_item: &ImplItem<'_>, impl_decl: &'tcx FnDecl<'_>, impl_trait_ref: ty::TraitRef<'tcx>, @@ -157,8 +157,8 @@ fn check_trait_method_impl_decl<'a, 'tcx>( } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for UseSelf { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if in_external_macro(cx.sess(), item.span) { return; } @@ -211,7 +211,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { struct UseSelfVisitor<'a, 'tcx> { item_path: &'a Path<'a>, - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, } impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> { diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs index 5d150ad4f03..69c0b092520 100644 --- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs +++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs @@ -40,8 +40,8 @@ pub struct UselessConversion { impl_lint_pass!(UselessConversion => [USELESS_CONVERSION]); #[allow(clippy::too_many_lines)] -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for UselessConversion { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if e.span.from_expansion() { return; } @@ -121,7 +121,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion { if_chain! { if args.len() == 1; if let ExprKind::Path(ref qpath) = path.kind; - if let Some(def_id) = cx.tables().qpath_res(qpath, path.hir_id).opt_def_id(); + if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id(); let a = cx.tables().expr_ty(e); let b = cx.tables().expr_ty(&args[0]); @@ -173,7 +173,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion { } } - fn check_expr_post(&mut self, _: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) { + fn check_expr_post(&mut self, _: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if Some(&e.hir_id) == self.try_desugar_arm.last() { self.try_desugar_arm.pop(); } diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 910b665ccb7..128fa87a162 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -64,8 +64,8 @@ fn done() { println!("}}"); } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Author { - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for Author { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { if !has_attr(cx.sess(), &item.attrs) { return; } @@ -74,7 +74,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Author { done(); } - fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::ImplItem<'_>) { + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) { if !has_attr(cx.sess(), &item.attrs) { return; } @@ -83,7 +83,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Author { done(); } - fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::TraitItem<'_>) { + fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) { if !has_attr(cx.sess(), &item.attrs) { return; } @@ -92,7 +92,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Author { done(); } - fn check_variant(&mut self, cx: &LateContext<'a, 'tcx>, var: &'tcx hir::Variant<'_>) { + fn check_variant(&mut self, cx: &LateContext<'tcx>, var: &'tcx hir::Variant<'_>) { if !has_attr(cx.sess(), &var.attrs) { return; } @@ -102,7 +102,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Author { done(); } - fn check_struct_field(&mut self, cx: &LateContext<'a, 'tcx>, field: &'tcx hir::StructField<'_>) { + fn check_struct_field(&mut self, cx: &LateContext<'tcx>, field: &'tcx hir::StructField<'_>) { if !has_attr(cx.sess(), &field.attrs) { return; } @@ -111,7 +111,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Author { done(); } - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { if !has_attr(cx.sess(), &expr.attrs) { return; } @@ -120,7 +120,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Author { done(); } - fn check_arm(&mut self, cx: &LateContext<'a, 'tcx>, arm: &'tcx hir::Arm<'_>) { + fn check_arm(&mut self, cx: &LateContext<'tcx>, arm: &'tcx hir::Arm<'_>) { if !has_attr(cx.sess(), &arm.attrs) { return; } @@ -129,7 +129,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Author { done(); } - fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx hir::Stmt<'_>) { + fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx hir::Stmt<'_>) { if !has_attr(cx.sess(), stmt.kind.attrs()) { return; } @@ -138,7 +138,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Author { done(); } - fn check_foreign_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::ForeignItem<'_>) { + fn check_foreign_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ForeignItem<'_>) { if !has_attr(cx.sess(), &item.attrs) { return; } diff --git a/src/tools/clippy/clippy_lints/src/utils/diagnostics.rs b/src/tools/clippy/clippy_lints/src/utils/diagnostics.rs index f6d87c8532e..e4e65b5f4d4 100644 --- a/src/tools/clippy/clippy_lints/src/utils/diagnostics.rs +++ b/src/tools/clippy/clippy_lints/src/utils/diagnostics.rs @@ -138,7 +138,7 @@ where }); } -pub fn span_lint_hir(cx: &LateContext<'_, '_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: &str) { +pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: &str) { cx.tcx.struct_span_lint_hir(lint, hir_id, sp, |diag| { let mut diag = diag.build(msg); docs_link(&mut diag, lint); @@ -147,7 +147,7 @@ pub fn span_lint_hir(cx: &LateContext<'_, '_>, lint: &'static Lint, hir_id: HirI } pub fn span_lint_hir_and_then( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, diff --git a/src/tools/clippy/clippy_lints/src/utils/higher.rs b/src/tools/clippy/clippy_lints/src/utils/higher.rs index 0e78f35a129..eb7ac2447e4 100644 --- a/src/tools/clippy/clippy_lints/src/utils/higher.rs +++ b/src/tools/clippy/clippy_lints/src/utils/higher.rs @@ -47,7 +47,7 @@ pub struct Range<'a> { } /// Higher a `hir` range to something similar to `ast::ExprKind::Range`. -pub fn range<'a, 'b, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'b hir::Expr<'_>) -> Option<Range<'b>> { +pub fn range<'a, 'tcx>(cx: &LateContext<'tcx>, expr: &'a hir::Expr<'_>) -> Option<Range<'a>> { /// Finds the field named `name` in the field. Always return `Some` for /// convenience. fn get_field<'c>(name: &str, fields: &'c [hir::Field<'_>]) -> Option<&'c hir::Expr<'c>> { @@ -257,12 +257,12 @@ pub enum VecArgs<'a> { /// Returns the arguments of the `vec!` macro if this expression was expanded /// from `vec!`. -pub fn vec_macro<'e>(cx: &LateContext<'_, '_>, expr: &'e hir::Expr<'_>) -> Option<VecArgs<'e>> { +pub fn vec_macro<'e>(cx: &LateContext<'_>, expr: &'e hir::Expr<'_>) -> Option<VecArgs<'e>> { if_chain! { if let hir::ExprKind::Call(ref fun, ref args) = expr.kind; if let hir::ExprKind::Path(ref qpath) = fun.kind; if is_expn_of(fun.span, "vec").is_some(); - if let Some(fun_def_id) = cx.tables().qpath_res(qpath, fun.hir_id).opt_def_id(); + if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id(); then { return if match_def_path(cx, fun_def_id, &paths::VEC_FROM_ELEM) && args.len() == 2 { // `vec![elem; size]` case diff --git a/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs b/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs index a74ab18a063..ae58f0a1521 100644 --- a/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs +++ b/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs @@ -21,27 +21,26 @@ use std::hash::Hash; /// Note that some expressions kinds are not considered but could be added. pub struct SpanlessEq<'a, 'tcx> { /// Context used to evaluate constant expressions. - cx: &'a LateContext<'a, 'tcx>, - tables: &'a TypeckTables<'tcx>, + cx: &'a LateContext<'tcx>, + maybe_typeck_tables: Option<&'tcx TypeckTables<'tcx>>, /// If is true, never consider as equal expressions containing function /// calls. ignore_fn: bool, } impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { - pub fn new(cx: &'a LateContext<'a, 'tcx>) -> Self { + pub fn new(cx: &'a LateContext<'tcx>) -> Self { Self { cx, - tables: cx.tables(), + maybe_typeck_tables: cx.maybe_typeck_tables(), ignore_fn: false, } } pub fn ignore_fn(self) -> Self { Self { - cx: self.cx, - tables: self.cx.tables(), ignore_fn: true, + ..self } } @@ -72,12 +71,14 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { return false; } - if let (Some(l), Some(r)) = ( - constant_simple(self.cx, self.tables, left), - constant_simple(self.cx, self.tables, right), - ) { - if l == r { - return true; + if let Some(tables) = self.maybe_typeck_tables { + if let (Some(l), Some(r)) = ( + constant_simple(self.cx, tables, left), + constant_simple(self.cx, tables, right), + ) { + if l == r { + return true; + } } } @@ -271,18 +272,18 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { match (left, right) { (&TyKind::Slice(ref l_vec), &TyKind::Slice(ref r_vec)) => self.eq_ty(l_vec, r_vec), (&TyKind::Array(ref lt, ref ll_id), &TyKind::Array(ref rt, ref rl_id)) => { - let full_table = self.tables; + let old_maybe_typeck_tables = self.maybe_typeck_tables; let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(ll_id.body)); - self.tables = self.cx.tcx.body_tables(ll_id.body); + self.maybe_typeck_tables = Some(self.cx.tcx.body_tables(ll_id.body)); let ll = celcx.expr(&self.cx.tcx.hir().body(ll_id.body).value); let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(rl_id.body)); - self.tables = self.cx.tcx.body_tables(rl_id.body); + self.maybe_typeck_tables = Some(self.cx.tcx.body_tables(rl_id.body)); let rl = celcx.expr(&self.cx.tcx.hir().body(rl_id.body).value); let eq_ty = self.eq_ty(lt, rt); - self.tables = full_table; + self.maybe_typeck_tables = old_maybe_typeck_tables; eq_ty && ll == rl }, (&TyKind::Ptr(ref l_mut), &TyKind::Ptr(ref r_mut)) => { @@ -346,16 +347,16 @@ pub fn over<X>(left: &[X], right: &[X], mut eq_fn: impl FnMut(&X, &X) -> bool) - /// All expressions kind are hashed, but some might have a weaker hash. pub struct SpanlessHash<'a, 'tcx> { /// Context used to evaluate constant expressions. - cx: &'a LateContext<'a, 'tcx>, - tables: &'a TypeckTables<'tcx>, + cx: &'a LateContext<'tcx>, + maybe_typeck_tables: Option<&'tcx TypeckTables<'tcx>>, s: StableHasher, } impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { - pub fn new(cx: &'a LateContext<'a, 'tcx>, tables: &'a TypeckTables<'tcx>) -> Self { + pub fn new(cx: &'a LateContext<'tcx>) -> Self { Self { cx, - tables, + maybe_typeck_tables: cx.maybe_typeck_tables(), s: StableHasher::new(), } } @@ -384,7 +385,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { #[allow(clippy::many_single_char_names, clippy::too_many_lines)] pub fn hash_expr(&mut self, e: &Expr<'_>) { - let simple_const = constant_simple(self.cx, self.tables, e); + let simple_const = self + .maybe_typeck_tables + .and_then(|tables| constant_simple(self.cx, tables, e)); // const hashing may result in the same hash as some unrelated node, so add a sort of // discriminant depending on which path we're choosing next @@ -599,7 +602,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_name(path.ident.name); }, } - // self.cx.tables.qpath_res(p, id).hash(&mut self.s); + // self.maybe_typeck_tables.unwrap().qpath_res(p, id).hash(&mut self.s); } pub fn hash_path(&mut self, p: &Path<'_>) { @@ -728,9 +731,8 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { pub fn hash_body(&mut self, body_id: BodyId) { // swap out TypeckTables when hashing a body - let old_tables = self.tables; - self.tables = self.cx.tcx.body_tables(body_id); + let old_maybe_typeck_tables = self.maybe_typeck_tables.replace(self.cx.tcx.body_tables(body_id)); self.hash_expr(&self.cx.tcx.hir().body(body_id).value); - self.tables = old_tables; + self.maybe_typeck_tables = old_maybe_typeck_tables; } } diff --git a/src/tools/clippy/clippy_lints/src/utils/inspector.rs b/src/tools/clippy/clippy_lints/src/utils/inspector.rs index 3f5659c3d8c..fbd103323e3 100644 --- a/src/tools/clippy/clippy_lints/src/utils/inspector.rs +++ b/src/tools/clippy/clippy_lints/src/utils/inspector.rs @@ -31,15 +31,15 @@ declare_clippy_lint! { declare_lint_pass!(DeepCodeInspector => [DEEP_CODE_INSPECTION]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DeepCodeInspector { - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for DeepCodeInspector { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { if !has_attr(cx.sess(), &item.attrs) { return; } print_item(cx, item); } - fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::ImplItem<'_>) { + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) { if !has_attr(cx.sess(), &item.attrs) { return; } @@ -65,14 +65,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DeepCodeInspector { hir::ImplItemKind::TyAlias(_) => println!("associated type"), } } - // fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx + // fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx // hir::TraitItem) { // if !has_attr(&item.attrs) { // return; // } // } // - // fn check_variant(&mut self, cx: &LateContext<'a, 'tcx>, var: &'tcx + // fn check_variant(&mut self, cx: &LateContext<'tcx>, var: &'tcx // hir::Variant, _: // &hir::Generics) { // if !has_attr(&var.node.attrs) { @@ -80,7 +80,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DeepCodeInspector { // } // } // - // fn check_struct_field(&mut self, cx: &LateContext<'a, 'tcx>, field: &'tcx + // fn check_struct_field(&mut self, cx: &LateContext<'tcx>, field: &'tcx // hir::StructField) { // if !has_attr(&field.attrs) { // return; @@ -88,14 +88,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DeepCodeInspector { // } // - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { if !has_attr(cx.sess(), &expr.attrs) { return; } print_expr(cx, expr, 0); } - fn check_arm(&mut self, cx: &LateContext<'a, 'tcx>, arm: &'tcx hir::Arm<'_>) { + fn check_arm(&mut self, cx: &LateContext<'tcx>, arm: &'tcx hir::Arm<'_>) { if !has_attr(cx.sess(), &arm.attrs) { return; } @@ -108,7 +108,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DeepCodeInspector { print_expr(cx, &arm.body, 1); } - fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx hir::Stmt<'_>) { + fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx hir::Stmt<'_>) { if !has_attr(cx.sess(), stmt.kind.attrs()) { return; } @@ -126,7 +126,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DeepCodeInspector { hir::StmtKind::Expr(ref e) | hir::StmtKind::Semi(ref e) => print_expr(cx, e, 0), } } - // fn check_foreign_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx + // fn check_foreign_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx // hir::ForeignItem) { // if !has_attr(&item.attrs) { // return; @@ -141,7 +141,7 @@ fn has_attr(sess: &Session, attrs: &[Attribute]) -> bool { #[allow(clippy::similar_names)] #[allow(clippy::too_many_lines)] -fn print_expr(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, indent: usize) { +fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) { let ind = " ".repeat(indent); println!("{}+", ind); println!("{}ty: {}", ind, cx.tables().expr_ty(expr)); @@ -348,7 +348,7 @@ fn print_expr(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, indent: usize) { } } -fn print_item(cx: &LateContext<'_, '_>, item: &hir::Item<'_>) { +fn print_item(cx: &LateContext<'_>, item: &hir::Item<'_>) { let did = cx.tcx.hir().local_def_id(item.hir_id); println!("item `{}`", item.ident.name); match item.vis.node { @@ -425,7 +425,7 @@ fn print_item(cx: &LateContext<'_, '_>, item: &hir::Item<'_>) { #[allow(clippy::similar_names)] #[allow(clippy::too_many_lines)] -fn print_pat(cx: &LateContext<'_, '_>, pat: &hir::Pat<'_>, indent: usize) { +fn print_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, indent: usize) { let ind = " ".repeat(indent); println!("{}+", ind); match pat.kind { @@ -537,7 +537,7 @@ fn print_pat(cx: &LateContext<'_, '_>, pat: &hir::Pat<'_>, indent: usize) { } } -fn print_guard(cx: &LateContext<'_, '_>, guard: &hir::Guard<'_>, indent: usize) { +fn print_guard(cx: &LateContext<'_>, guard: &hir::Guard<'_>, indent: usize) { let ind = " ".repeat(indent); println!("{}+", ind); match guard { diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs index 38468181d02..38cb764adde 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs @@ -251,8 +251,8 @@ pub struct LintWithoutLintPass { impl_lint_pass!(LintWithoutLintPass => [DEFAULT_LINT, LINT_WITHOUT_LINT_PASS]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'_>) { +impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if !run_lints(cx, &[DEFAULT_LINT], item.hir_id) { return; } @@ -310,7 +310,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { } } - fn check_crate_post(&mut self, cx: &LateContext<'a, 'tcx>, _: &'tcx Crate<'_>) { + fn check_crate_post(&mut self, cx: &LateContext<'tcx>, _: &'tcx Crate<'_>) { if !run_lints(cx, &[LINT_WITHOUT_LINT_PASS], CRATE_HIR_ID) { return; } @@ -337,7 +337,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { } } -fn is_lint_ref_type<'tcx>(cx: &LateContext<'_, 'tcx>, ty: &Ty<'_>) -> bool { +fn is_lint_ref_type<'tcx>(cx: &LateContext<'tcx>, ty: &Ty<'_>) -> bool { if let TyKind::Rptr( _, MutTy { @@ -347,7 +347,7 @@ fn is_lint_ref_type<'tcx>(cx: &LateContext<'_, 'tcx>, ty: &Ty<'_>) -> bool { ) = ty.kind { if let TyKind::Path(ref path) = inner.kind { - if let Res::Def(DefKind::Struct, def_id) = cx.tables().qpath_res(path, inner.hir_id) { + if let Res::Def(DefKind::Struct, def_id) = cx.qpath_res(path, inner.hir_id) { return match_def_path(cx, def_id, &paths::LINT); } } @@ -358,7 +358,7 @@ fn is_lint_ref_type<'tcx>(cx: &LateContext<'_, 'tcx>, ty: &Ty<'_>) -> bool { struct LintCollector<'a, 'tcx> { output: &'a mut FxHashSet<Symbol>, - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, } impl<'a, 'tcx> Visitor<'tcx> for LintCollector<'a, 'tcx> { @@ -395,8 +395,8 @@ impl CompilerLintFunctions { impl_lint_pass!(CompilerLintFunctions => [COMPILER_LINT_FUNCTIONS]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CompilerLintFunctions { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for CompilerLintFunctions { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if !run_lints(cx, &[COMPILER_LINT_FUNCTIONS], expr.hir_id) { return; } @@ -424,8 +424,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CompilerLintFunctions { declare_lint_pass!(OuterExpnDataPass => [OUTER_EXPN_EXPN_DATA]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OuterExpnDataPass { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for OuterExpnDataPass { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { if !run_lints(cx, &[OUTER_EXPN_EXPN_DATA], expr.hir_id) { return; } @@ -474,8 +474,8 @@ fn is_trigger_fn(fn_kind: FnKind<'_>) -> bool { declare_lint_pass!(CollapsibleCalls => [COLLAPSIBLE_SPAN_LINT_CALLS]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CollapsibleCalls { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { if !run_lints(cx, &[COLLAPSIBLE_SPAN_LINT_CALLS], expr.hir_id) { return; } @@ -529,10 +529,7 @@ struct AndThenSnippets<'a> { msg: Cow<'a, str>, } -fn get_and_then_snippets<'a, 'hir>( - cx: &LateContext<'_, '_>, - and_then_snippets: &'hir [Expr<'hir>], -) -> AndThenSnippets<'a> { +fn get_and_then_snippets<'a, 'hir>(cx: &LateContext<'_>, and_then_snippets: &'hir [Expr<'hir>]) -> AndThenSnippets<'a> { let cx_snippet = snippet(cx, and_then_snippets[0].span, "cx"); let lint_snippet = snippet(cx, and_then_snippets[1].span, ".."); let span_snippet = snippet(cx, and_then_snippets[2].span, "span"); @@ -553,7 +550,7 @@ struct SpanSuggestionSnippets<'a> { } fn span_suggestion_snippets<'a, 'hir>( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, span_call_args: &'hir [Expr<'hir>], ) -> SpanSuggestionSnippets<'a> { let help_snippet = snippet(cx, span_call_args[2].span, r#""...""#); @@ -568,7 +565,7 @@ fn span_suggestion_snippets<'a, 'hir>( } fn suggest_suggestion( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, expr: &Expr<'_>, and_then_snippets: &AndThenSnippets<'_>, span_suggestion_snippets: &SpanSuggestionSnippets<'_>, @@ -594,7 +591,7 @@ fn suggest_suggestion( } fn suggest_help( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, expr: &Expr<'_>, and_then_snippets: &AndThenSnippets<'_>, help: &str, @@ -626,7 +623,7 @@ fn suggest_help( } fn suggest_note( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, expr: &Expr<'_>, and_then_snippets: &AndThenSnippets<'_>, note: &str, diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs index 69ec4b7ad6d..99ba7d64331 100644 --- a/src/tools/clippy/clippy_lints/src/utils/mod.rs +++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs @@ -70,7 +70,7 @@ pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool { /// // Do something /// } /// ``` -pub fn in_constant(cx: &LateContext<'_, '_>, id: HirId) -> bool { +pub fn in_constant(cx: &LateContext<'_>, id: HirId) -> bool { let parent_id = cx.tcx.hir().get_parent_item(id); match cx.tcx.hir().get(parent_id) { Node::Item(&Item { @@ -134,7 +134,7 @@ pub fn is_wild<'tcx>(pat: &impl std::ops::Deref<Target = Pat<'tcx>>) -> bool { } /// Checks if type is struct, enum or union type with the given def path. -pub fn match_type(cx: &LateContext<'_, '_>, ty: Ty<'_>, path: &[&str]) -> bool { +pub fn match_type(cx: &LateContext<'_>, ty: Ty<'_>, path: &[&str]) -> bool { match ty.kind { ty::Adt(adt, _) => match_def_path(cx, adt.did, path), _ => false, @@ -142,7 +142,7 @@ pub fn match_type(cx: &LateContext<'_, '_>, ty: Ty<'_>, path: &[&str]) -> bool { } /// Checks if the type is equal to a diagnostic item -pub fn is_type_diagnostic_item(cx: &LateContext<'_, '_>, ty: Ty<'_>, diag_item: Symbol) -> bool { +pub fn is_type_diagnostic_item(cx: &LateContext<'_>, ty: Ty<'_>, diag_item: Symbol) -> bool { match ty.kind { ty::Adt(adt, _) => cx.tcx.is_diagnostic_item(diag_item, adt.did), _ => false, @@ -150,7 +150,7 @@ pub fn is_type_diagnostic_item(cx: &LateContext<'_, '_>, ty: Ty<'_>, diag_item: } /// Checks if the method call given in `expr` belongs to the given trait. -pub fn match_trait_method(cx: &LateContext<'_, '_>, expr: &Expr<'_>, path: &[&str]) -> bool { +pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str]) -> bool { let def_id = cx.tables().type_dependent_def_id(expr.hir_id).unwrap(); let trt_id = cx.tcx.trait_of_item(def_id); if let Some(trt_id) = trt_id { @@ -249,7 +249,7 @@ pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool { } /// Gets the definition associated to a path. -pub fn path_to_res(cx: &LateContext<'_, '_>, path: &[&str]) -> Option<def::Res> { +pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Option<def::Res> { let crates = cx.tcx.crates(); let krate = crates .iter() @@ -285,7 +285,7 @@ pub fn path_to_res(cx: &LateContext<'_, '_>, path: &[&str]) -> Option<def::Res> } } -pub fn qpath_res(cx: &LateContext<'_, '_>, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res { +pub fn qpath_res(cx: &LateContext<'_>, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res { match qpath { hir::QPath::Resolved(_, path) => path.res, hir::QPath::TypeRelative(..) => { @@ -302,7 +302,7 @@ pub fn qpath_res(cx: &LateContext<'_, '_>, qpath: &hir::QPath<'_>, id: hir::HirI /// Convenience function to get the `DefId` of a trait by path. /// It could be a trait or trait alias. -pub fn get_trait_def_id(cx: &LateContext<'_, '_>, path: &[&str]) -> Option<DefId> { +pub fn get_trait_def_id(cx: &LateContext<'_>, path: &[&str]) -> Option<DefId> { let res = match path_to_res(cx, path) { Some(res) => res, None => return None, @@ -317,8 +317,8 @@ pub fn get_trait_def_id(cx: &LateContext<'_, '_>, path: &[&str]) -> Option<DefId /// Checks whether a type implements a trait. /// See also `get_trait_def_id`. -pub fn implements_trait<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +pub fn implements_trait<'tcx>( + cx: &LateContext<'tcx>, ty: Ty<'tcx>, trait_id: DefId, ty_params: &[GenericArg<'tcx>], @@ -347,7 +347,7 @@ pub fn implements_trait<'a, 'tcx>( /// } /// } /// ``` -pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'_, 'tcx>, hir_id: HirId) -> Option<&'tcx TraitRef<'tcx>> { +pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx TraitRef<'tcx>> { // Get the implemented trait for the current function let parent_impl = cx.tcx.hir().get_parent_item(hir_id); if_chain! { @@ -360,7 +360,7 @@ pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'_, 'tcx>, hir_id: HirId) -> O } /// Checks whether this type implements `Drop`. -pub fn has_drop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { +pub fn has_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { match ty.ty_adt_def() { Some(def) => def.has_dtor(cx.tcx), None => false, @@ -426,14 +426,14 @@ pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option<Vec } /// Returns `true` if the provided `def_id` is an entrypoint to a program. -pub fn is_entrypoint_fn(cx: &LateContext<'_, '_>, def_id: DefId) -> bool { +pub fn is_entrypoint_fn(cx: &LateContext<'_>, def_id: DefId) -> bool { cx.tcx .entry_fn(LOCAL_CRATE) .map_or(false, |(entry_fn_def_id, _)| def_id == entry_fn_def_id.to_def_id()) } /// Gets the name of the item the expression is in, if available. -pub fn get_item_name(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<Name> { +pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Name> { let parent_id = cx.tcx.hir().get_parent_item(expr.hir_id); match cx.tcx.hir().find(parent_id) { Some( @@ -717,7 +717,7 @@ fn trim_multiline_inner(s: Cow<'_, str>, ignore_first: bool, indent: Option<usiz } /// Gets the parent expression, if any –- this is useful to constrain a lint. -pub fn get_parent_expr<'c>(cx: &'c LateContext<'_, '_>, e: &Expr<'_>) -> Option<&'c Expr<'c>> { +pub fn get_parent_expr<'c>(cx: &'c LateContext<'_>, e: &Expr<'_>) -> Option<&'c Expr<'c>> { let map = &cx.tcx.hir(); let hir_id = e.hir_id; let parent_id = map.get_parent_node(hir_id); @@ -733,7 +733,7 @@ pub fn get_parent_expr<'c>(cx: &'c LateContext<'_, '_>, e: &Expr<'_>) -> Option< }) } -pub fn get_enclosing_block<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, hir_id: HirId) -> Option<&'tcx Block<'tcx>> { +pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Block<'tcx>> { let map = &cx.tcx.hir(); let enclosing_node = map .get_enclosing_scope(hir_id) @@ -789,7 +789,7 @@ pub fn walk_ptrs_ty_depth(ty: Ty<'_>) -> (Ty<'_>, usize) { /// Checks whether the given expression is a constant integer of the given value. /// unlike `is_integer_literal`, this version does const folding -pub fn is_integer_const(cx: &LateContext<'_, '_>, e: &Expr<'_>, value: u128) -> bool { +pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool { if is_integer_literal(e, value) { return true; } @@ -823,7 +823,7 @@ pub fn is_integer_literal(expr: &Expr<'_>, value: u128) -> bool { /// /// See `rustc_middle::ty::adjustment::Adjustment` and `rustc_typeck::check::coercion` for more /// information on adjustments and coercions. -pub fn is_adjusted(cx: &LateContext<'_, '_>, e: &Expr<'_>) -> bool { +pub fn is_adjusted(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { cx.tables().adjustments().get(e.hir_id).is_some() } @@ -876,29 +876,29 @@ pub fn is_direct_expn_of(span: Span, name: &str) -> Option<Span> { } /// Convenience function to get the return type of a function. -pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: hir::HirId) -> Ty<'tcx> { +pub fn return_ty<'tcx>(cx: &LateContext<'tcx>, fn_item: hir::HirId) -> Ty<'tcx> { let fn_def_id = cx.tcx.hir().local_def_id(fn_item); let ret_ty = cx.tcx.fn_sig(fn_def_id).output(); cx.tcx.erase_late_bound_regions(&ret_ty) } /// Returns `true` if the given type is an `unsafe` function. -pub fn type_is_unsafe_function<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { +pub fn type_is_unsafe_function<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { match ty.kind { ty::FnDef(..) | ty::FnPtr(_) => ty.fn_sig(cx.tcx).unsafety() == Unsafety::Unsafe, _ => false, } } -pub fn is_copy<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { +pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { ty.is_copy_modulo_regions(cx.tcx.at(DUMMY_SP), cx.param_env) } /// Checks if an expression is constructing a tuple-like enum variant or struct -pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { +pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { if let ExprKind::Call(ref fun, _) = expr.kind { if let ExprKind::Path(ref qp) = fun.kind { - let res = cx.tables().qpath_res(qp, fun.hir_id); + let res = cx.qpath_res(qp, fun.hir_id); return match res { def::Res::Def(DefKind::Variant | DefKind::Ctor(..), ..) => true, def::Res::Def(_, def_id) => cx.tcx.is_promotable_const_fn(def_id), @@ -911,15 +911,15 @@ pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_, '_>, expr: &Exp /// Returns `true` if a pattern is refutable. // TODO: should be implemented using rustc/mir_build/hair machinery -pub fn is_refutable(cx: &LateContext<'_, '_>, pat: &Pat<'_>) -> bool { - fn is_enum_variant(cx: &LateContext<'_, '_>, qpath: &QPath<'_>, id: HirId) -> bool { +pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool { + fn is_enum_variant(cx: &LateContext<'_>, qpath: &QPath<'_>, id: HirId) -> bool { matches!( - cx.tables().qpath_res(qpath, id), + cx.qpath_res(qpath, id), def::Res::Def(DefKind::Variant, ..) | Res::Def(DefKind::Ctor(def::CtorOf::Variant, _), _) ) } - fn are_refutable<'a, I: Iterator<Item = &'a Pat<'a>>>(cx: &LateContext<'_, '_>, mut i: I) -> bool { + fn are_refutable<'a, I: Iterator<Item = &'a Pat<'a>>>(cx: &LateContext<'_>, mut i: I) -> bool { i.any(|pat| is_refutable(cx, pat)) } @@ -1050,7 +1050,7 @@ pub fn is_try<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { /// Returns `true` if the lint is allowed in the current context /// /// Useful for skipping long running code when it's unnecessary -pub fn is_allowed(cx: &LateContext<'_, '_>, lint: &'static Lint, id: HirId) -> bool { +pub fn is_allowed(cx: &LateContext<'_>, lint: &'static Lint, id: HirId) -> bool { cx.tcx.lint_level_at_node(lint, id).0 == Level::Allow } @@ -1135,7 +1135,7 @@ pub fn any_parent_is_automatically_derived(tcx: TyCtxt<'_>, node: HirId) -> bool } /// Returns true if ty has `iter` or `iter_mut` methods -pub fn has_iter_method(cx: &LateContext<'_, '_>, probably_ref_ty: Ty<'_>) -> Option<&'static str> { +pub fn has_iter_method(cx: &LateContext<'_>, probably_ref_ty: Ty<'_>) -> Option<&'static str> { // FIXME: instead of this hard-coded list, we should check if `<adt>::iter` // exists and has the desired signature. Unfortunately FnCtxt is not exported // so we can't use its `lookup_method` method. @@ -1182,15 +1182,15 @@ pub fn has_iter_method(cx: &LateContext<'_, '_>, probably_ref_ty: Ty<'_>) -> Opt /// ```rust,ignore /// if let Some(args) = match_function_call(cx, begin_panic_call, &paths::BEGIN_PANIC); /// ``` -pub fn match_function_call<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +pub fn match_function_call<'tcx>( + cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, path: &[&str], ) -> Option<&'tcx [Expr<'tcx>]> { if_chain! { if let ExprKind::Call(ref fun, ref args) = expr.kind; if let ExprKind::Path(ref qpath) = fun.kind; - if let Some(fun_def_id) = cx.tables().qpath_res(qpath, fun.hir_id).opt_def_id(); + if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id(); if match_def_path(cx, fun_def_id, path); then { return Some(&args) @@ -1201,14 +1201,14 @@ pub fn match_function_call<'a, 'tcx>( /// Checks if `Ty` is normalizable. This function is useful /// to avoid crashes on `layout_of`. -pub fn is_normalizable<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { +pub fn is_normalizable<'tcx>(cx: &LateContext<'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { cx.tcx.infer_ctxt().enter(|infcx| { let cause = rustc_middle::traits::ObligationCause::dummy(); infcx.at(&cause, param_env).normalize(&ty).is_ok() }) } -pub fn match_def_path<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, did: DefId, syms: &[&str]) -> bool { +pub fn match_def_path<'tcx>(cx: &LateContext<'tcx>, did: DefId, syms: &[&str]) -> bool { // We have to convert `syms` to `&[Symbol]` here because rustc's `match_def_path` // accepts only that. We should probably move to Symbols in Clippy as well. let syms = syms.iter().map(|p| Symbol::intern(p)).collect::<Vec<Symbol>>(); @@ -1250,7 +1250,7 @@ pub fn if_sequence<'tcx>( (conds, blocks) } -pub fn parent_node_is_if_expr<'a, 'b>(expr: &Expr<'_>, cx: &LateContext<'a, 'b>) -> bool { +pub fn parent_node_is_if_expr(expr: &Expr<'_>, cx: &LateContext<'_>) -> bool { let map = cx.tcx.hir(); let parent_id = map.get_parent_node(expr.hir_id); let parent_node = map.get(parent_id); @@ -1275,7 +1275,7 @@ pub fn must_use_attr(attrs: &[Attribute]) -> Option<&Attribute> { } // Returns whether the type has #[must_use] attribute -pub fn is_must_use_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { +pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { match ty.kind { ty::Adt(ref adt, _) => must_use_attr(&cx.tcx.get_attrs(adt.did)).is_some(), ty::Foreign(ref did) => must_use_attr(&cx.tcx.get_attrs(*did)).is_some(), @@ -1313,11 +1313,11 @@ pub fn is_must_use_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> boo } // check if expr is calling method or function with #[must_use] attribyte -pub fn is_must_use_func_call(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { +pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { let did = match expr.kind { ExprKind::Call(ref path, _) => if_chain! { if let ExprKind::Path(ref qpath) = path.kind; - if let def::Res::Def(_, did) = cx.tables().qpath_res(qpath, path.hir_id); + if let def::Res::Def(_, did) = cx.qpath_res(qpath, path.hir_id); then { Some(did) } else { @@ -1352,7 +1352,7 @@ pub fn is_no_std_crate(krate: &Crate<'_>) -> bool { /// fn f() {} /// } /// ``` -pub fn is_trait_impl_item(cx: &LateContext<'_, '_>, hir_id: HirId) -> bool { +pub fn is_trait_impl_item(cx: &LateContext<'_>, hir_id: HirId) -> bool { if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) { matches!(item.kind, ItemKind::Impl{ of_trait: Some(_), .. }) } else { @@ -1369,7 +1369,7 @@ pub fn is_trait_impl_item(cx: &LateContext<'_, '_>, hir_id: HirId) -> bool { /// for _ in 2i32 {} /// } /// ``` -pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_, '_>, did: DefId) -> bool { +pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool { use rustc_trait_selection::traits; let predicates = cx.tcx @@ -1385,7 +1385,7 @@ pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_, '_>, did: DefId) -> bool ) } -pub fn run_lints(cx: &LateContext<'_, '_>, lints: &[&'static Lint], id: HirId) -> bool { +pub fn run_lints(cx: &LateContext<'_>, lints: &[&'static Lint], id: HirId) -> bool { lints.iter().any(|lint| { matches!( cx.tcx.lint_level_at_node(lint, id), diff --git a/src/tools/clippy/clippy_lints/src/utils/ptr.rs b/src/tools/clippy/clippy_lints/src/utils/ptr.rs index ee336ecc58d..bd2c619f000 100644 --- a/src/tools/clippy/clippy_lints/src/utils/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/utils/ptr.rs @@ -7,7 +7,7 @@ use rustc_span::{Span, Symbol}; use std::borrow::Cow; pub fn get_spans( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, opt_body_id: Option<BodyId>, idx: usize, replacements: &[(&'static str, &'static str)], @@ -22,8 +22,8 @@ pub fn get_spans( } } -fn extract_clone_suggestions<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, +fn extract_clone_suggestions<'tcx>( + cx: &LateContext<'tcx>, name: Symbol, replace: &[(&'static str, &'static str)], body: &'tcx Body<'_>, @@ -44,7 +44,7 @@ fn extract_clone_suggestions<'a, 'tcx>( } struct PtrCloneVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, + cx: &'a LateContext<'tcx>, name: Symbol, replace: &'a [(&'static str, &'static str)], spans: Vec<(Span, Cow<'static, str>)>, diff --git a/src/tools/clippy/clippy_lints/src/utils/sugg.rs b/src/tools/clippy/clippy_lints/src/utils/sugg.rs index e919b1522d8..d05e81b9505 100644 --- a/src/tools/clippy/clippy_lints/src/utils/sugg.rs +++ b/src/tools/clippy/clippy_lints/src/utils/sugg.rs @@ -39,7 +39,7 @@ impl Display for Sugg<'_> { #[allow(clippy::wrong_self_convention)] // ok, because of the function `as_ty` method impl<'a> Sugg<'a> { /// Prepare a suggestion from an expression. - pub fn hir_opt(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>) -> Option<Self> { + pub fn hir_opt(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Self> { snippet_opt(cx, expr.span).map(|snippet| { let snippet = Cow::Owned(snippet); Self::hir_from_snippet(cx, expr, snippet) @@ -48,7 +48,7 @@ impl<'a> Sugg<'a> { /// Convenience function around `hir_opt` for suggestions with a default /// text. - pub fn hir(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, default: &'a str) -> Self { + pub fn hir(cx: &LateContext<'_>, expr: &hir::Expr<'_>, default: &'a str) -> Self { Self::hir_opt(cx, expr).unwrap_or_else(|| Sugg::NonParen(Cow::Borrowed(default))) } @@ -60,7 +60,7 @@ impl<'a> Sugg<'a> { /// to /// `HasPlaceholders` pub fn hir_with_applicability( - cx: &LateContext<'_, '_>, + cx: &LateContext<'_>, expr: &hir::Expr<'_>, default: &'a str, applicability: &mut Applicability, @@ -77,7 +77,7 @@ impl<'a> Sugg<'a> { } /// Same as `hir`, but will use the pre expansion span if the `expr` was in a macro. - pub fn hir_with_macro_callsite(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, default: &'a str) -> Self { + pub fn hir_with_macro_callsite(cx: &LateContext<'_>, expr: &hir::Expr<'_>, default: &'a str) -> Self { let snippet = snippet_with_macro_callsite(cx, expr.span, default); Self::hir_from_snippet(cx, expr, snippet) @@ -85,7 +85,7 @@ impl<'a> Sugg<'a> { /// Generate a suggestion for an expression with the given snippet. This is used by the `hir_*` /// function variants of `Sugg`, since these use different snippet functions. - fn hir_from_snippet(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, snippet: Cow<'a, str>) -> Self { + fn hir_from_snippet(cx: &LateContext<'_>, expr: &hir::Expr<'_>, snippet: Cow<'a, str>) -> Self { if let Some(range) = higher::range(cx, expr) { let op = match range.limits { ast::RangeLimits::HalfOpen => AssocOp::DotDot, diff --git a/src/tools/clippy/clippy_lints/src/utils/usage.rs b/src/tools/clippy/clippy_lints/src/utils/usage.rs index d280fe4ab4e..53d3a241f58 100644 --- a/src/tools/clippy/clippy_lints/src/utils/usage.rs +++ b/src/tools/clippy/clippy_lints/src/utils/usage.rs @@ -11,7 +11,7 @@ use rustc_span::symbol::{Ident, Symbol}; use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; /// Returns a set of mutated local variable IDs, or `None` if mutations could not be determined. -pub fn mutated_variables<'a, 'tcx>(expr: &'tcx Expr<'_>, cx: &'a LateContext<'a, 'tcx>) -> Option<FxHashSet<HirId>> { +pub fn mutated_variables<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> Option<FxHashSet<HirId>> { let mut delegate = MutVarsDelegate { used_mutably: FxHashSet::default(), skip: false, @@ -27,11 +27,7 @@ pub fn mutated_variables<'a, 'tcx>(expr: &'tcx Expr<'_>, cx: &'a LateContext<'a, Some(delegate.used_mutably) } -pub fn is_potentially_mutated<'a, 'tcx>( - variable: &'tcx Path<'_>, - expr: &'tcx Expr<'_>, - cx: &'a LateContext<'a, 'tcx>, -) -> bool { +pub fn is_potentially_mutated<'tcx>(variable: &'tcx Path<'_>, expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> bool { if let Res::Local(id) = variable.res { mutated_variables(expr, cx).map_or(true, |mutated| mutated.contains(&id)) } else { diff --git a/src/tools/clippy/clippy_lints/src/vec.rs b/src/tools/clippy/clippy_lints/src/vec.rs index 080785b177d..e1043c36e0a 100644 --- a/src/tools/clippy/clippy_lints/src/vec.rs +++ b/src/tools/clippy/clippy_lints/src/vec.rs @@ -33,8 +33,8 @@ declare_clippy_lint! { declare_lint_pass!(UselessVec => [USELESS_VEC]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessVec { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for UselessVec { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { // search for `&vec![_]` expressions where the adjusted type is `&[_]` if_chain! { if let ty::Ref(_, ty, _) = cx.tables().expr_ty_adjusted(expr).kind; @@ -66,7 +66,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessVec { } } -fn check_vec_macro<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, vec_args: &higher::VecArgs<'tcx>, span: Span) { +fn check_vec_macro<'tcx>(cx: &LateContext<'tcx>, vec_args: &higher::VecArgs<'tcx>, span: Span) { let mut applicability = Applicability::MachineApplicable; let snippet = match *vec_args { higher::VecArgs::Repeat(elem, len) => { diff --git a/src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs b/src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs index bb315e64e5d..cc5e21a7ca6 100644 --- a/src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs +++ b/src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs @@ -28,8 +28,8 @@ declare_clippy_lint! { declare_lint_pass!(VecResizeToZero => [VEC_RESIZE_TO_ZERO]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VecResizeToZero { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for VecResizeToZero { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { if let hir::ExprKind::MethodCall(path_segment, _, ref args, _) = expr.kind; if let Some(method_def_id) = cx.tables().type_dependent_def_id(expr.hir_id); diff --git a/src/tools/clippy/clippy_lints/src/verbose_file_reads.rs b/src/tools/clippy/clippy_lints/src/verbose_file_reads.rs index 85f92084574..b06fe36da63 100644 --- a/src/tools/clippy/clippy_lints/src/verbose_file_reads.rs +++ b/src/tools/clippy/clippy_lints/src/verbose_file_reads.rs @@ -33,8 +33,8 @@ declare_clippy_lint! { declare_lint_pass!(VerboseFileReads => [VERBOSE_FILE_READS]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VerboseFileReads { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'tcx>) { +impl<'tcx> LateLintPass<'tcx> for VerboseFileReads { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { if is_file_read_to_end(cx, expr) { span_lint_and_help( cx, @@ -57,7 +57,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VerboseFileReads { } } -fn is_file_read_to_end<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'tcx>) -> bool { +fn is_file_read_to_end<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { if_chain! { if let ExprKind::MethodCall(method_name, _, exprs, _) = expr.kind; if method_name.ident.as_str() == "read_to_end"; @@ -71,7 +71,7 @@ fn is_file_read_to_end<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'t false } -fn is_file_read_to_string<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'tcx>) -> bool { +fn is_file_read_to_string<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { if_chain! { if let ExprKind::MethodCall(method_name, _, exprs, _) = expr.kind; if method_name.ident.as_str() == "read_to_string"; diff --git a/src/tools/clippy/clippy_lints/src/wildcard_dependencies.rs b/src/tools/clippy/clippy_lints/src/wildcard_dependencies.rs index 511518082be..cd1864f461d 100644 --- a/src/tools/clippy/clippy_lints/src/wildcard_dependencies.rs +++ b/src/tools/clippy/clippy_lints/src/wildcard_dependencies.rs @@ -28,8 +28,8 @@ declare_clippy_lint! { declare_lint_pass!(WildcardDependencies => [WILDCARD_DEPENDENCIES]); -impl LateLintPass<'_, '_> for WildcardDependencies { - fn check_crate(&mut self, cx: &LateContext<'_, '_>, _: &Crate<'_>) { +impl LateLintPass<'_> for WildcardDependencies { + fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) { if !run_lints(cx, &[WILDCARD_DEPENDENCIES], CRATE_HIR_ID) { return; } diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs index 79f7705e281..e7eb7c2e980 100644 --- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs +++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs @@ -101,8 +101,8 @@ impl WildcardImports { impl_lint_pass!(WildcardImports => [ENUM_GLOB_USE, WILDCARD_IMPORTS]); -impl LateLintPass<'_, '_> for WildcardImports { - fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &Item<'_>) { +impl LateLintPass<'_> for WildcardImports { + fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { if is_test_module_or_function(item) { self.test_modules_deep = self.test_modules_deep.saturating_add(1); } @@ -180,7 +180,7 @@ impl LateLintPass<'_, '_> for WildcardImports { } } - fn check_item_post(&mut self, _: &LateContext<'_, '_>, item: &Item<'_>) { + fn check_item_post(&mut self, _: &LateContext<'_>, item: &Item<'_>) { if is_test_module_or_function(item) { self.test_modules_deep = self.test_modules_deep.saturating_sub(1); } diff --git a/src/tools/clippy/clippy_lints/src/zero_div_zero.rs b/src/tools/clippy/clippy_lints/src/zero_div_zero.rs index f0cf17c3b95..1e011ea9cba 100644 --- a/src/tools/clippy/clippy_lints/src/zero_div_zero.rs +++ b/src/tools/clippy/clippy_lints/src/zero_div_zero.rs @@ -27,8 +27,8 @@ declare_clippy_lint! { declare_lint_pass!(ZeroDiv => [ZERO_DIVIDED_BY_ZERO]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ZeroDiv { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { +impl<'tcx> LateLintPass<'tcx> for ZeroDiv { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { // check for instances of 0.0/0.0 if_chain! { if let ExprKind::Binary(ref op, ref left, ref right) = expr.kind; diff --git a/src/tools/clippy/doc/common_tools_writing_lints.md b/src/tools/clippy/doc/common_tools_writing_lints.md index d06e359bc7a..412ff99314d 100644 --- a/src/tools/clippy/doc/common_tools_writing_lints.md +++ b/src/tools/clippy/doc/common_tools_writing_lints.md @@ -28,8 +28,8 @@ that gives you access to the underlying structure [`TyS`][TyS]. Example of use: ```rust -impl LateLintPass<'_, '_> for MyStructLint { - fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) { +impl LateLintPass<'_> for MyStructLint { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { // Get type of `expr` let ty = cx.tables().expr_ty(expr); // Match its kind to enter its type @@ -56,8 +56,8 @@ Two noticeable items here: Starting with an `expr`, you can check whether it is calling a specific method `some_method`: ```rust -impl LateLintPass<'_, '_> for MyStructLint { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>) { +impl LateLintPass<'_> for MyStructLint { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { if_chain! { // Check our expr is calling a method if let hir::ExprKind::MethodCall(path, _, _args) = &expr.kind; @@ -78,8 +78,8 @@ There are two ways to do this, depending if the target trait is part of lang ite ```rust use crate::utils::{implements_trait, match_trait_method, paths}; -impl LateLintPass<'_, '_> for MyStructLint { - fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) { +impl LateLintPass<'_> for MyStructLint { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { // 1. Using expression and Clippy's convenient method // we use `match_trait_method` function from Clippy's toolbox if match_trait_method(cx, expr, &paths::INTO) { @@ -112,8 +112,8 @@ To check if our type defines a method called `some_method`: ```rust use crate::utils::{is_type_diagnostic_item, return_ty}; -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MyTypeImpl { - fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx ImplItem<'_>) { +impl<'tcx> LateLintPass<'tcx> for MyTypeImpl { + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) { if_chain! { // Check if item is a method/function if let ImplItemKind::Fn(ref signature, _) = impl_item.kind; diff --git a/src/tools/clippy/tests/ui/outer_expn_data.fixed b/src/tools/clippy/tests/ui/outer_expn_data.fixed index 999a19b289e..b0b3498f057 100644 --- a/src/tools/clippy/tests/ui/outer_expn_data.fixed +++ b/src/tools/clippy/tests/ui/outer_expn_data.fixed @@ -19,8 +19,8 @@ declare_lint! { declare_lint_pass!(Pass => [TEST_LINT]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { - fn check_expr(&mut self, _cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { +impl<'tcx> LateLintPass<'tcx> for Pass { + fn check_expr(&mut self, _cx: &LateContext<'tcx>, expr: &'tcx Expr) { let _ = expr.span.ctxt().outer_expn_data(); } } diff --git a/src/tools/clippy/tests/ui/outer_expn_data.rs b/src/tools/clippy/tests/ui/outer_expn_data.rs index 5405d475d1a..55a3fed00d0 100644 --- a/src/tools/clippy/tests/ui/outer_expn_data.rs +++ b/src/tools/clippy/tests/ui/outer_expn_data.rs @@ -19,8 +19,8 @@ declare_lint! { declare_lint_pass!(Pass => [TEST_LINT]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { - fn check_expr(&mut self, _cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { +impl<'tcx> LateLintPass<'tcx> for Pass { + fn check_expr(&mut self, _cx: &LateContext<'tcx>, expr: &'tcx Expr) { let _ = expr.span.ctxt().outer_expn().expn_data(); } } diff --git a/src/tools/miri b/src/tools/miri -Subproject 59619775ee44a5e0c875efffc4ca55ae96fca7d +Subproject fd8101247749c5be6850d5cb5096f01a1867e5b diff --git a/triagebot.toml b/triagebot.toml index 73ca7abfed3..51a29553fdb 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -92,7 +92,7 @@ message_on_remove = "Issue #{number}'s prioritization request has been removed." [notify-zulip."I-nominated"] required_labels = ["T-compiler"] zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts -topic = "I-prioritize #{number} {title}" +topic = "I-nominated #{number} {title}" message_on_add = """\ @*WG-prioritization/alerts* #{number} has been nominated for discussion in `T-compiler` meeting. |
