From 4e6b55e9b8d64af5d14ed5465fdcf54c62ef3b8b Mon Sep 17 00:00:00 2001 From: josh rotenberg Date: Tue, 15 Jun 2021 22:05:44 -0700 Subject: Initial commit for the Clippy Book --- book/src/development/adding_lints.md | 670 +++++++++++++++++++++++++++++++++++ 1 file changed, 670 insertions(+) create mode 100644 book/src/development/adding_lints.md (limited to 'book/src/development/adding_lints.md') diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md new file mode 100644 index 00000000000..5a06afedbf4 --- /dev/null +++ b/book/src/development/adding_lints.md @@ -0,0 +1,670 @@ +# Adding a new lint + +You are probably here because you want to add a new lint to Clippy. If this is +the first time you're contributing to Clippy, this document guides you through +creating an example lint from scratch. + +To get started, we will create a lint that detects functions called `foo`, +because that's clearly a non-descriptive name. + +- [Adding a new lint](#adding-a-new-lint) + - [Setup](#setup) + - [Getting Started](#getting-started) + - [Testing](#testing) + - [Rustfix tests](#rustfix-tests) + - [Edition 2018 tests](#edition-2018-tests) + - [Testing manually](#testing-manually) + - [Lint declaration](#lint-declaration) + - [Lint passes](#lint-passes) + - [Emitting a lint](#emitting-a-lint) + - [Adding the lint logic](#adding-the-lint-logic) + - [Specifying the lint's minimum supported Rust version (MSRV)](#specifying-the-lints-minimum-supported-rust-version-msrv) + - [Author lint](#author-lint) + - [Documentation](#documentation) + - [Running rustfmt](#running-rustfmt) + - [Debugging](#debugging) + - [PR Checklist](#pr-checklist) + - [Adding configuration to a lint](#adding-configuration-to-a-lint) + - [Cheatsheet](#cheatsheet) + +## Setup + +See the [Basics](basics.md#get-the-code) documentation. + +## Getting Started + +There is a bit of boilerplate code that needs to be set up when creating a new +lint. Fortunately, you can use the clippy dev tools to handle this for you. We +are naming our new lint `foo_functions` (lints are generally written in snake +case), and we don't need type information so it will have an early pass type +(more on this later on). If you're not sure if the name you chose fits the lint, +take a look at our [lint naming guidelines][lint_naming]. To get started on this +lint you can run `cargo dev new_lint --name=foo_functions --pass=early +--category=pedantic` (category will default to nursery if not provided). This +command will create two files: `tests/ui/foo_functions.rs` and +`clippy_lints/src/foo_functions.rs`, as well as run `cargo dev update_lints` to +register the new lint. For cargo lints, two project hierarchies (fail/pass) will +be created by default under `tests/ui-cargo`. + +Next, we'll open up these files and add our lint! + +## Testing + +Let's write some tests first that we can execute while we iterate on our lint. + +Clippy uses UI tests for testing. UI tests check that the output of Clippy is +exactly as expected. Each test is just a plain Rust file that contains the code +we want to check. The output of Clippy is compared against a `.stderr` file. +Note that you don't have to create this file yourself, we'll get to +generating the `.stderr` files further down. + +We start by opening the test file created at `tests/ui/foo_functions.rs`. + +Update the file with some examples to get started: + +```rust +#![warn(clippy::foo_functions)] + +// Impl methods +struct A; +impl A { + pub fn fo(&self) {} + pub fn foo(&self) {} + pub fn food(&self) {} +} + +// Default trait methods +trait B { + fn fo(&self) {} + fn foo(&self) {} + fn food(&self) {} +} + +// Plain functions +fn fo() {} +fn foo() {} +fn food() {} + +fn main() { + // We also don't want to lint method calls + foo(); + let a = A; + a.foo(); +} +``` + +Now we can run the test with `TESTNAME=foo_functions cargo uitest`, +currently this test is meaningless though. + +While we are working on implementing our lint, we can keep running the UI +test. That allows us to check if the output is turning into what we want. + +Once we are satisfied with the output, we need to run +`cargo dev bless` to update the `.stderr` file for our lint. +Please note that, we should run `TESTNAME=foo_functions cargo uitest` +every time before running `cargo dev bless`. +Running `TESTNAME=foo_functions cargo uitest` should pass then. When we commit +our lint, we need to commit the generated `.stderr` files, too. In general, you +should only commit files changed by `cargo dev bless` for the +specific lint you are creating/editing. Note that if the generated files are +empty, they should be removed. + +Note that you can run multiple test files by specifying a comma separated list: +`TESTNAME=foo_functions,test2,test3`. + +### Cargo lints + +For cargo lints, the process of testing differs in that we are interested in +the `Cargo.toml` manifest file. We also need a minimal crate associated +with that manifest. + +If our new lint is named e.g. `foo_categories`, after running `cargo dev new_lint` +we will find by default two new crates, each with its manifest file: + +* `tests/ui-cargo/foo_categories/fail/Cargo.toml`: this file should cause the new lint to raise an error. +* `tests/ui-cargo/foo_categories/pass/Cargo.toml`: this file should not trigger the lint. + +If you need more cases, you can copy one of those crates (under `foo_categories`) and rename it. + +The process of generating the `.stderr` file is the same, and prepending the `TESTNAME` +variable to `cargo uitest` works too. + +## Rustfix tests + +If the lint you are working on is making use of structured suggestions, the +test file should include a `// run-rustfix` comment at the top. This will +additionally run [rustfix] for that test. Rustfix will apply the suggestions +from the lint to the code of the test file and compare that to the contents of +a `.fixed` file. + +Use `cargo dev bless` to automatically generate the +`.fixed` file after running the tests. + +[rustfix]: https://github.com/rust-lang/rustfix + +## Edition 2018 tests + +Some features require the 2018 edition to work (e.g. `async_await`), but +compile-test tests run on the 2015 edition by default. To change this behavior +add `// edition:2018` at the top of the test file (note that it's space-sensitive). + +## Testing manually + +Manually testing against an example file can be useful if you have added some +`println!`s and the test suite output becomes unreadable. To try Clippy with +your local modifications, run + +``` +env __CLIPPY_INTERNAL_TESTS=true cargo run --bin clippy-driver -- -L ./target/debug input.rs +``` + +from the working copy root. With tests in place, let's have a look at +implementing our lint now. + +## Lint declaration + +Let's start by opening the new file created in the `clippy_lints` crate +at `clippy_lints/src/foo_functions.rs`. That's the crate where all the +lint code is. This file has already imported some initial things we will need: + +```rust +use rustc_lint::{EarlyLintPass, EarlyContext}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_ast::ast::*; +``` + +The next step is to update the lint declaration. Lints are declared using the +[`declare_clippy_lint!`][declare_clippy_lint] macro, and we just need to update +the auto-generated lint declaration to have a real description, something like this: + +```rust +declare_clippy_lint! { + /// **What it does:** + /// + /// **Why is this bad?** + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// // example code + /// ``` + pub FOO_FUNCTIONS, + pedantic, + "function named `foo`, which is not a descriptive name" +} +``` + +* The section of lines prefixed with `///` constitutes the lint documentation + section. This is the default documentation style and will be displayed + [like this][example_lint_page]. To render and open this documentation locally + in a browser, run `cargo dev serve`. +* `FOO_FUNCTIONS` is the name of our lint. Be sure to follow the + [lint naming guidelines][lint_naming] here when naming your lint. + In short, the name should state the thing that is being checked for and + read well when used with `allow`/`warn`/`deny`. +* `pedantic` sets the lint level to `Allow`. + The exact mapping can be found [here][category_level_mapping] +* The last part should be a text that explains what exactly is wrong with the + code + +The rest of this file contains an empty implementation for our lint pass, +which in this case is `EarlyLintPass` and should look like this: + +```rust +// clippy_lints/src/foo_functions.rs + +// .. imports and lint declaration .. + +declare_lint_pass!(FooFunctions => [FOO_FUNCTIONS]); + +impl EarlyLintPass for FooFunctions {} +``` + +Normally after declaring the lint, we have to run `cargo dev update_lints`, +which updates some files, so Clippy knows about the new lint. Since we used +`cargo dev new_lint ...` to generate the lint declaration, this was done +automatically. While `update_lints` automates most of the things, it doesn't +automate everything. We will have to register our lint pass manually in the +`register_plugins` function in `clippy_lints/src/lib.rs`: + +```rust +store.register_early_pass(|| box foo_functions::FooFunctions); +``` + +As one may expect, there is a corresponding `register_late_pass` method +available as well. Without a call to one of `register_early_pass` or +`register_late_pass`, the lint pass in question will not be run. + +One reason that `cargo dev` does not automate this step is that multiple lints +can use the same lint pass, so registering the lint pass may already be done +when adding a new lint. Another reason that this step is not automated is that +the order that the passes are registered determines the order the passes +actually run, which in turn affects the order that any emitted lints are output +in. + +[declare_clippy_lint]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L60 +[example_lint_page]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure +[lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints +[category_level_mapping]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L110 + +## Lint passes + +Writing a lint that only checks for the name of a function means that we only +have to deal with the AST and don't have to deal with the type system at all. +This is good, because it makes writing this particular lint less complicated. + +We have to make this decision with every new Clippy lint. It boils down to using +either [`EarlyLintPass`][early_lint_pass] or [`LateLintPass`][late_lint_pass]. + +In short, the `LateLintPass` has access to type information while the +`EarlyLintPass` doesn't. If you don't need access to type information, use the +`EarlyLintPass`. The `EarlyLintPass` is also faster. However linting speed +hasn't really been a concern with Clippy so far. + +Since we don't need type information for checking the function name, we used +`--pass=early` when running the new lint automation and all the imports were +added accordingly. + +[early_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.EarlyLintPass.html +[late_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html + +## Emitting a lint + +With UI tests and the lint declaration in place, we can start working on the +implementation of the lint logic. + +Let's start by implementing the `EarlyLintPass` for our `FooFunctions`: + +```rust +impl EarlyLintPass for FooFunctions { + fn check_fn(&mut self, cx: &EarlyContext<'_>, fn_kind: FnKind<'_>, span: Span, _: NodeId) { + // TODO: Emit lint here + } +} +``` + +We implement the [`check_fn`][check_fn] method from the +[`EarlyLintPass`][early_lint_pass] trait. This gives us access to various +information about the function that is currently being checked. More on that in +the next section. Let's worry about the details later and emit our lint for +*every* function definition first. + +Depending on how complex we want our lint message to be, we can choose from a +variety of lint emission functions. They can all be found in +[`clippy_utils/src/diagnostics.rs`][diagnostics]. + +`span_lint_and_help` seems most appropriate in this case. It allows us to +provide an extra help message and we can't really suggest a better name +automatically. This is how it looks: + +```rust +impl EarlyLintPass for FooFunctions { + fn check_fn(&mut self, cx: &EarlyContext<'_>, fn_kind: FnKind<'_>, span: Span, _: NodeId) { + span_lint_and_help( + cx, + FOO_FUNCTIONS, + span, + "function named `foo`", + None, + "consider using a more meaningful name" + ); + } +} +``` + +Running our UI test should now produce output that contains the lint message. + +According to [the rustc-dev-guide], the text should be matter of fact and avoid +capitalization and periods, unless multiple sentences are needed. +When code or an identifier must appear in a message or label, it should be +surrounded with single grave accents \`. + +[check_fn]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.EarlyLintPass.html#method.check_fn +[diagnostics]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_utils/src/diagnostics.rs +[the rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/diagnostics.html + +## Adding the lint logic + +Writing the logic for your lint will most likely be different from our example, +so this section is kept rather short. + +Using the [`check_fn`][check_fn] method gives us access to [`FnKind`][fn_kind] +that has the [`FnKind::Fn`] variant. It provides access to the name of the +function/method via an [`Ident`][ident]. + +With that we can expand our `check_fn` method to: + +```rust +impl EarlyLintPass for FooFunctions { + fn check_fn(&mut self, cx: &EarlyContext<'_>, fn_kind: FnKind<'_>, span: Span, _: NodeId) { + if is_foo_fn(fn_kind) { + span_lint_and_help( + cx, + FOO_FUNCTIONS, + span, + "function named `foo`", + None, + "consider using a more meaningful name" + ); + } + } +} +``` + +We separate the lint conditional from the lint emissions because it makes the +code a bit easier to read. In some cases this separation would also allow to +write some unit tests (as opposed to only UI tests) for the separate function. + +In our example, `is_foo_fn` looks like: + +```rust +// use statements, impl EarlyLintPass, check_fn, .. + +fn is_foo_fn(fn_kind: FnKind<'_>) -> bool { + match fn_kind { + FnKind::Fn(_, ident, ..) => { + // check if `fn` name is `foo` + ident.name.as_str() == "foo" + } + // ignore closures + FnKind::Closure(..) => false + } +} +``` + +Now we should also run the full test suite with `cargo test`. At this point +running `cargo test` should produce the expected output. Remember to run +`cargo dev bless` to update the `.stderr` file. + +`cargo test` (as opposed to `cargo uitest`) will also ensure that our lint +implementation is not violating any Clippy lints itself. + +That should be it for the lint implementation. Running `cargo test` should now +pass. + +[fn_kind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/visit/enum.FnKind.html +[`FnKind::Fn`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/visit/enum.FnKind.html#variant.Fn +[ident]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/symbol/struct.Ident.html + +## Specifying the lint's minimum supported Rust version (MSRV) + +Sometimes a lint makes suggestions that require a certain version of Rust. For example, the `manual_strip` lint suggests +using `str::strip_prefix` and `str::strip_suffix` which is only available after Rust 1.45. In such cases, you need to +ensure that the MSRV configured for the project is >= the MSRV of the required Rust feature. If multiple features are +required, just use the one with a lower MSRV. + +First, add an MSRV alias for the required feature in [`clippy_utils::msrvs`](/clippy_utils/src/msrvs.rs). This can be +accessed later as `msrvs::STR_STRIP_PREFIX`, for example. + +```rust +msrv_aliases! { + .. + 1,45,0 { STR_STRIP_PREFIX } +} +``` + +In order to access the project-configured MSRV, you need to have an `msrv` field in the LintPass struct, and a +constructor to initialize the field. The `msrv` value is passed to the constructor in `clippy_lints/lib.rs`. + +```rust +pub struct ManualStrip { + msrv: Option, +} + +impl ManualStrip { + #[must_use] + pub fn new(msrv: Option) -> Self { + Self { msrv } + } +} +``` + +The project's MSRV can then be matched against the feature MSRV in the LintPass +using the `meets_msrv` utility function. + +``` rust +if !meets_msrv(self.msrv.as_ref(), &msrvs::STR_STRIP_PREFIX) { + return; +} +``` + +The project's MSRV can also be specified as an inner attribute, which overrides +the value from `clippy.toml`. This can be accounted for using the +`extract_msrv_attr!(LintContext)` macro and passing +`LateContext`/`EarlyContext`. + +```rust +impl<'tcx> LateLintPass<'tcx> for ManualStrip { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + ... + } + extract_msrv_attr!(LateContext); +} +``` + +Once the `msrv` is added to the lint, a relevant test case should be added to +`tests/ui/min_rust_version_attr.rs` which verifies that the lint isn't emitted +if the project's MSRV is lower. + +As a last step, the lint should be added to the lint documentation. This is done +in `clippy_lints/src/utils/conf.rs`: + +```rust +define_Conf! { + /// Lint: LIST, OF, LINTS, . The minimum rust version that the project supports + (msrv: Option = None), + ... +} +``` + +## Author lint + +If you have trouble implementing your lint, there is also the internal `author` +lint to generate Clippy code that detects the offending pattern. It does not +work for all of the Rust syntax, but can give a good starting point. + +The quickest way to use it, is the +[Rust playground: play.rust-lang.org][author_example]. +Put the code you want to lint into the editor and add the `#[clippy::author]` +attribute above the item. Then run Clippy via `Tools -> Clippy` and you should +see the generated code in the output below. + +[Here][author_example] is an example on the playground. + +If the command was executed successfully, you can copy the code over to where +you are implementing your lint. + +[author_example]: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=9a12cb60e5c6ad4e3003ac6d5e63cf55 + +## Documentation + +The final thing before submitting our PR is to add some documentation to our +lint declaration. + +Please document your lint with a doc comment akin to the following: + +```rust +declare_clippy_lint! { + /// **What it does:** Checks for ... (describe what the lint matches). + /// + /// **Why is this bad?** Supply the reason for linting the code. + /// + /// **Known problems:** None. (Or describe where it could go wrong.) + /// + /// **Example:** + /// + /// ```rust,ignore + /// // Bad + /// Insert a short example of code that triggers the lint + /// + /// // Good + /// Insert a short example of improved code that doesn't trigger the lint + /// ``` + pub FOO_FUNCTIONS, + pedantic, + "function named `foo`, which is not a descriptive name" +} +``` + +Once your lint is merged, this documentation will show up in the [lint +list][lint_list]. + +[lint_list]: https://rust-lang.github.io/rust-clippy/master/index.html + +## Running rustfmt + +[Rustfmt] is a tool for formatting Rust code according to style guidelines. +Your code has to be formatted by `rustfmt` before a PR can be merged. +Clippy uses nightly `rustfmt` in the CI. + +It can be installed via `rustup`: + +```bash +rustup component add rustfmt --toolchain=nightly +``` + +Use `cargo dev fmt` to format the whole codebase. Make sure that `rustfmt` is +installed for the nightly toolchain. + +[Rustfmt]: https://github.com/rust-lang/rustfmt + +## Debugging + +If you want to debug parts of your lint implementation, you can use the [`dbg!`] +macro anywhere in your code. Running the tests should then include the debug +output in the `stdout` part. + +[`dbg!`]: https://doc.rust-lang.org/std/macro.dbg.html + +## PR Checklist + +Before submitting your PR make sure you followed all of the basic requirements: + + + +- \[ ] Followed [lint naming conventions][lint_naming] +- \[ ] Added passing UI tests (including committed `.stderr` file) +- \[ ] `cargo test` passes locally +- \[ ] Executed `cargo dev update_lints` +- \[ ] Added lint documentation +- \[ ] Run `cargo dev fmt` + +## Adding configuration to a lint + +Clippy supports the configuration of lints values using a `clippy.toml` file in the workspace +directory. Adding a configuration to a lint can be useful for thresholds or to constrain some +behavior that can be seen as a false positive for some users. Adding a configuration is done +in the following steps: + +1. Adding a new configuration entry to [clippy_utils::conf](/clippy_utils/src/conf.rs) + like this: + ```rust + /// Lint: LINT_NAME. + (configuration_ident: Type = DefaultValue), + ``` + The configuration value and identifier should usually be the same. The doc comment will be + automatically added to the lint documentation. +2. Adding the configuration value to the lint impl struct: + 1. This first requires the definition of a lint impl struct. Lint impl structs are usually + generated with the `declare_lint_pass!` macro. This struct needs to be defined manually + to add some kind of metadata to it: + ```rust + // Generated struct definition + declare_lint_pass!(StructName => [ + LINT_NAME + ]); + + // New manual definition struct + #[derive(Copy, Clone)] + pub struct StructName {} + + impl_lint_pass!(StructName => [ + LINT_NAME + ]); + ``` + + 2. Next add the configuration value and a corresponding creation method like this: + ```rust + #[derive(Copy, Clone)] + pub struct StructName { + configuration_ident: Type, + } + + // ... + + impl StructName { + pub fn new(configuration_ident: Type) -> Self { + Self { + configuration_ident, + } + } + } + ``` +3. Passing the configuration value to the lint impl struct: + + First find the struct construction in the [clippy_lints lib file](/clippy_lints/src/lib.rs). + The configuration value is now cloned or copied into a local value that is then passed to the + impl struct like this: + ```rust + // Default generated registration: + store.register_*_pass(|| box module::StructName); + + // New registration with configuration value + let configuration_ident = conf.configuration_ident.clone(); + store.register_*_pass(move || box module::StructName::new(configuration_ident)); + ``` + + Congratulations the work is almost done. The configuration value can now be accessed + in the linting code via `self.configuration_ident`. + +4. Adding tests: + 1. The default configured value can be tested like any normal lint in [`tests/ui`](/tests/ui). + 2. The configuration itself will be tested separately in [`tests/ui-toml`](/tests/ui-toml). + Simply add a new subfolder with a fitting name. This folder contains a `clippy.toml` file + with the configuration value and a rust file that should be linted by Clippy. The test can + otherwise be written as usual. + +## Cheatsheet + +Here are some pointers to things you are likely going to need for every lint: + +* [Clippy utils][utils] - Various helper functions. Maybe the function you need + is already in here (`implements_trait`, `match_def_path`, `snippet`, etc) +* [Clippy diagnostics][diagnostics] +* [The `if_chain` macro][if_chain] +* [`from_expansion`][from_expansion] and [`in_external_macro`][in_external_macro] +* [`Span`][span] +* [`Applicability`][applicability] +* [Common tools for writing lints](common_tools_writing_lints.md) helps with common operations +* [The rustc-dev-guide][rustc-dev-guide] explains a lot of internal compiler concepts +* [The nightly rustc docs][nightly_docs] which has been linked to throughout + this guide + +For `EarlyLintPass` lints: + +* [`EarlyLintPass`][early_lint_pass] +* [`rustc_ast::ast`][ast] + +For `LateLintPass` lints: + +* [`LateLintPass`][late_lint_pass] +* [`Ty::TyKind`][ty] + +While most of Clippy's lint utils are documented, most of rustc's internals lack +documentation currently. This is unfortunate, but in most cases you can probably +get away with copying things from existing similar lints. If you are stuck, +don't hesitate to ask on [Zulip] or in the issue/PR. + +[utils]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_utils/src/lib.rs +[if_chain]: https://docs.rs/if_chain/*/if_chain/ +[from_expansion]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html#method.from_expansion +[in_external_macro]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/lint/fn.in_external_macro.html +[span]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html +[applicability]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/enum.Applicability.html +[rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/ +[nightly_docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ +[ast]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/index.html +[ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/sty/index.html +[Zulip]: https://rust-lang.zulipchat.com/#narrow/stream/clippy -- cgit 1.4.1-3-g733a5 From af385799e0d5483170973a79110bdb1ce2949579 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 21 Jan 2022 16:55:26 +0100 Subject: Move internal documentation to book --- book/src/development/adding_lints.md | 125 ++-- book/src/development/basics.md | 12 +- book/src/development/common_tools_writing_lints.md | 253 +++++--- book/src/infrastructure/changelog_update.md | 2 +- book/src/infrastructure/release.md | 21 + doc/adding_lints.md | 697 --------------------- doc/backport.md | 71 --- doc/basics.md | 174 ----- doc/changelog_update.md | 97 --- doc/common_tools_writing_lints.md | 266 -------- doc/release.md | 145 ----- doc/roadmap-2021.md | 235 ------- 12 files changed, 263 insertions(+), 1835 deletions(-) delete mode 100644 doc/adding_lints.md delete mode 100644 doc/backport.md delete mode 100644 doc/basics.md delete mode 100644 doc/changelog_update.md delete mode 100644 doc/common_tools_writing_lints.md delete mode 100644 doc/release.md delete mode 100644 doc/roadmap-2021.md (limited to 'book/src/development/adding_lints.md') diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md index 5a06afedbf4..3e0b1c5c4f7 100644 --- a/book/src/development/adding_lints.md +++ b/book/src/development/adding_lints.md @@ -11,21 +11,24 @@ because that's clearly a non-descriptive name. - [Setup](#setup) - [Getting Started](#getting-started) - [Testing](#testing) + - [Cargo lints](#cargo-lints) - [Rustfix tests](#rustfix-tests) - [Edition 2018 tests](#edition-2018-tests) - [Testing manually](#testing-manually) - [Lint declaration](#lint-declaration) + - [Lint registration](#lint-registration) - [Lint passes](#lint-passes) - [Emitting a lint](#emitting-a-lint) - [Adding the lint logic](#adding-the-lint-logic) - [Specifying the lint's minimum supported Rust version (MSRV)](#specifying-the-lints-minimum-supported-rust-version-msrv) - [Author lint](#author-lint) + - [Print HIR lint](#print-hir-lint) - [Documentation](#documentation) - [Running rustfmt](#running-rustfmt) - [Debugging](#debugging) - [PR Checklist](#pr-checklist) - [Adding configuration to a lint](#adding-configuration-to-a-lint) - - [Cheatsheet](#cheatsheet) + - [Cheat Sheet](#cheat-sheet) ## Setup @@ -42,9 +45,9 @@ take a look at our [lint naming guidelines][lint_naming]. To get started on this lint you can run `cargo dev new_lint --name=foo_functions --pass=early --category=pedantic` (category will default to nursery if not provided). This command will create two files: `tests/ui/foo_functions.rs` and -`clippy_lints/src/foo_functions.rs`, as well as run `cargo dev update_lints` to -register the new lint. For cargo lints, two project hierarchies (fail/pass) will -be created by default under `tests/ui-cargo`. +`clippy_lints/src/foo_functions.rs`, as well as +[registering the lint](#lint-registration). For cargo lints, two project +hierarchies (fail/pass) will be created by default under `tests/ui-cargo`. Next, we'll open up these files and add our lint! @@ -155,7 +158,7 @@ Manually testing against an example file can be useful if you have added some your local modifications, run ``` -env __CLIPPY_INTERNAL_TESTS=true cargo run --bin clippy-driver -- -L ./target/debug input.rs +cargo dev lint input.rs ``` from the working copy root. With tests in place, let's have a look at @@ -179,17 +182,15 @@ the auto-generated lint declaration to have a real description, something like t ```rust declare_clippy_lint! { - /// **What it does:** + /// ### What it does /// - /// **Why is this bad?** - /// - /// **Known problems:** None. - /// - /// **Example:** + /// ### Why is this bad? /// + /// ### Example /// ```rust /// // example code /// ``` + #[clippy::version = "1.29.0"] pub FOO_FUNCTIONS, pedantic, "function named `foo`, which is not a descriptive name" @@ -200,6 +201,10 @@ declare_clippy_lint! { section. This is the default documentation style and will be displayed [like this][example_lint_page]. To render and open this documentation locally in a browser, run `cargo dev serve`. +* The `#[clippy::version]` attribute will be rendered as part of the lint documentation. + The value should be set to the current Rust version that the lint is developed in, + it can be retrieved by running `rustc -vV` in the rust-clippy directory. The version + is listed under *release*. (Use the version without the `-nightly`) suffix. * `FOO_FUNCTIONS` is the name of our lint. Be sure to follow the [lint naming guidelines][lint_naming] here when naming your lint. In short, the name should state the thing that is being checked for and @@ -222,32 +227,34 @@ declare_lint_pass!(FooFunctions => [FOO_FUNCTIONS]); impl EarlyLintPass for FooFunctions {} ``` -Normally after declaring the lint, we have to run `cargo dev update_lints`, -which updates some files, so Clippy knows about the new lint. Since we used -`cargo dev new_lint ...` to generate the lint declaration, this was done -automatically. While `update_lints` automates most of the things, it doesn't -automate everything. We will have to register our lint pass manually in the -`register_plugins` function in `clippy_lints/src/lib.rs`: +[declare_clippy_lint]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L60 +[example_lint_page]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure +[lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints +[category_level_mapping]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L110 + +## Lint registration + +When using `cargo dev new_lint`, the lint is automatically registered and +nothing more has to be done. + +When declaring a new lint by hand and `cargo dev update_lints` is used, the lint +pass may have to be registered manually in the `register_plugins` function in +`clippy_lints/src/lib.rs`: ```rust -store.register_early_pass(|| box foo_functions::FooFunctions); +store.register_early_pass(|| Box::new(foo_functions::FooFunctions)); ``` As one may expect, there is a corresponding `register_late_pass` method available as well. Without a call to one of `register_early_pass` or `register_late_pass`, the lint pass in question will not be run. -One reason that `cargo dev` does not automate this step is that multiple lints -can use the same lint pass, so registering the lint pass may already be done -when adding a new lint. Another reason that this step is not automated is that -the order that the passes are registered determines the order the passes -actually run, which in turn affects the order that any emitted lints are output -in. - -[declare_clippy_lint]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L60 -[example_lint_page]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure -[lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints -[category_level_mapping]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L110 +One reason that `cargo dev update_lints` does not automate this step is that +multiple lints can use the same lint pass, so registering the lint pass may +already be done when adding a new lint. Another reason that this step is not +automated is that the order that the passes are registered determines the order +the passes actually run, which in turn affects the order that any emitted lints +are output in. ## Lint passes @@ -425,7 +432,7 @@ The project's MSRV can then be matched against the feature MSRV in the LintPass using the `meets_msrv` utility function. ``` rust -if !meets_msrv(self.msrv.as_ref(), &msrvs::STR_STRIP_PREFIX) { +if !meets_msrv(self.msrv, msrvs::STR_STRIP_PREFIX) { return; } ``` @@ -478,6 +485,19 @@ you are implementing your lint. [author_example]: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=9a12cb60e5c6ad4e3003ac6d5e63cf55 +## Print HIR lint + +To implement a lint, it's helpful to first understand the internal representation +that rustc uses. Clippy has the `#[clippy::dump]` attribute that prints the +[_High-Level Intermediate Representation (HIR)_] of the item, statement, or +expression that the attribute is attached to. To attach the attribute to expressions +you often need to enable `#![feature(stmt_expr_attributes)]`. + +[Here][print_hir_example] you can find an example, just select _Tools_ and run _Clippy_. + +[_High-Level Intermediate Representation (HIR)_]: https://rustc-dev-guide.rust-lang.org/hir.html +[print_hir_example]: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=daf14db3a7f39ca467cd1b86c34b9afb + ## Documentation The final thing before submitting our PR is to add some documentation to our @@ -487,21 +507,23 @@ Please document your lint with a doc comment akin to the following: ```rust declare_clippy_lint! { - /// **What it does:** Checks for ... (describe what the lint matches). + /// ### What it does + /// Checks for ... (describe what the lint matches). /// - /// **Why is this bad?** Supply the reason for linting the code. + /// ### Why is this bad? + /// Supply the reason for linting the code. /// - /// **Known problems:** None. (Or describe where it could go wrong.) - /// - /// **Example:** + /// ### Example /// /// ```rust,ignore - /// // Bad - /// Insert a short example of code that triggers the lint - /// - /// // Good - /// Insert a short example of improved code that doesn't trigger the lint + /// // A short example of code that triggers the lint /// ``` + /// + /// Use instead: + /// ```rust,ignore + /// // A short example of improved code that doesn't trigger the lint + /// ``` + #[clippy::version = "1.29.0"] pub FOO_FUNCTIONS, pedantic, "function named `foo`, which is not a descriptive name" @@ -558,14 +580,16 @@ directory. Adding a configuration to a lint can be useful for thresholds or to c behavior that can be seen as a false positive for some users. Adding a configuration is done in the following steps: -1. Adding a new configuration entry to [clippy_utils::conf](/clippy_utils/src/conf.rs) +1. Adding a new configuration entry to [clippy_lints::utils::conf](/clippy_lints/src/utils/conf.rs) like this: ```rust - /// Lint: LINT_NAME. + /// Lint: LINT_NAME. + /// + /// (configuration_ident: Type = DefaultValue), ``` - The configuration value and identifier should usually be the same. The doc comment will be - automatically added to the lint documentation. + The doc comment is automatically added to the documentation of the listed lints. The default + value will be formatted using the `Debug` implementation of the type. 2. Adding the configuration value to the lint impl struct: 1. This first requires the definition of a lint impl struct. Lint impl structs are usually generated with the `declare_lint_pass!` macro. This struct needs to be defined manually @@ -626,14 +650,14 @@ in the following steps: with the configuration value and a rust file that should be linted by Clippy. The test can otherwise be written as usual. -## Cheatsheet +## Cheat Sheet Here are some pointers to things you are likely going to need for every lint: * [Clippy utils][utils] - Various helper functions. Maybe the function you need - is already in here (`implements_trait`, `match_def_path`, `snippet`, etc) + is already in here ([`is_type_diagnostic_item`], [`implements_trait`], [`snippet`], etc) * [Clippy diagnostics][diagnostics] -* [The `if_chain` macro][if_chain] +* [Let chains][let-chains] * [`from_expansion`][from_expansion] and [`in_external_macro`][in_external_macro] * [`Span`][span] * [`Applicability`][applicability] @@ -657,8 +681,11 @@ documentation currently. This is unfortunate, but in most cases you can probably get away with copying things from existing similar lints. If you are stuck, don't hesitate to ask on [Zulip] or in the issue/PR. -[utils]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_utils/src/lib.rs -[if_chain]: https://docs.rs/if_chain/*/if_chain/ +[utils]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/index.html +[`is_type_diagnostic_item`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/ty/fn.is_type_diagnostic_item.html +[`implements_trait`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/ty/fn.implements_trait.html +[`snippet`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/source/fn.snippet.html +[let-chains]: https://github.com/rust-lang/rust/pull/94927 [from_expansion]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html#method.from_expansion [in_external_macro]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/lint/fn.in_external_macro.html [span]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html diff --git a/book/src/development/basics.md b/book/src/development/basics.md index aaf31158f58..57a90a924ec 100644 --- a/book/src/development/basics.md +++ b/book/src/development/basics.md @@ -91,15 +91,18 @@ cargo dev fmt cargo dev update_lints # create a new lint and register it cargo dev new_lint +# automatically formatting all code before each commit +cargo dev setup git-hook # (experimental) Setup Clippy to work with IntelliJ-Rust -cargo dev ide_setup +cargo dev setup intellij ``` +More about intellij command usage and reasons [here](../CONTRIBUTING.md#intellij-rust) ## lintcheck `cargo lintcheck` will build and run clippy on a fixed set of crates and generate a log of the results. -You can `git diff` the updated log against its previous version and +You can `git diff` the updated log against its previous version and see what impact your lint made on a small set of crates. -If you add a new lint, please audit the resulting warnings and make sure +If you add a new lint, please audit the resulting warnings and make sure there are no false positives and that the suggestions are valid. Refer to the tools [README] for more details. @@ -167,6 +170,5 @@ rustup component add clippy > [proxies](https://rust-lang.github.io/rustup/concepts/proxies.html). That is, `~/.cargo/bin/cargo-clippy` and > `~/.cargo/bin/clippy-driver` should be hard or soft links to `~/.cargo/bin/rustup`. You can repair these by running > `rustup update`. - - + [glossary]: https://rustc-dev-guide.rust-lang.org/appendix/glossary.html diff --git a/book/src/development/common_tools_writing_lints.md b/book/src/development/common_tools_writing_lints.md index 0a85f650011..1d1aee0da2c 100644 --- a/book/src/development/common_tools_writing_lints.md +++ b/book/src/development/common_tools_writing_lints.md @@ -4,17 +4,19 @@ You may need following tooltips to catch up with common operations. - [Common tools for writing lints](#common-tools-for-writing-lints) - [Retrieving the type of an expression](#retrieving-the-type-of-an-expression) - - [Checking if an expression is calling a specific method](#checking-if-an-expr-is-calling-a-specific-method) + - [Checking if an expr is calling a specific method](#checking-if-an-expr-is-calling-a-specific-method) + - [Checking for a specific type](#checking-for-a-specific-type) - [Checking if a type implements a specific trait](#checking-if-a-type-implements-a-specific-trait) - [Checking if a type defines a specific method](#checking-if-a-type-defines-a-specific-method) - - [Dealing with macros](#dealing-with-macros) + - [Dealing with macros](#dealing-with-macros-and-expansions) Useful Rustc dev guide links: - [Stages of compilation](https://rustc-dev-guide.rust-lang.org/compiler-src.html#the-main-stages-of-compilation) +- [Diagnostic items](https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-items.html) - [Type checking](https://rustc-dev-guide.rust-lang.org/type-checking.html) - [Ty module](https://rustc-dev-guide.rust-lang.org/ty.html) -# Retrieving the type of an expression +## Retrieving the type of an expression Sometimes you may want to retrieve the type `Ty` of an expression `Expr`, for example to answer following questions: @@ -24,7 +26,7 @@ Sometimes you may want to retrieve the type `Ty` of an expression `Expr`, for ex - does it implement a trait? This operation is performed using the [`expr_ty()`][expr_ty] method from the [`TypeckResults`][TypeckResults] struct, -that gives you access to the underlying structure [`TyS`][TyS]. +that gives you access to the underlying structure [`Ty`][Ty]. Example of use: ```rust @@ -53,42 +55,81 @@ Two noticeable items here: created by type checking step, it includes useful information such as types of expressions, ways to resolve methods and so on. -# Checking if an expr is calling a specific method +## Checking if an expr is calling a specific method Starting with an `expr`, you can check whether it is calling a specific method `some_method`: ```rust -impl LateLintPass<'_> for MyStructLint { +impl<'tcx> LateLintPass<'tcx> 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; + // Check our expr is calling a method + if let hir::ExprKind::MethodCall(path, _, [_self_arg, ..]) = &expr.kind // Check the name of this method is `some_method` - if path.ident.name == sym!(some_method); - then { + && path.ident.name == sym!(some_method) + // Optionally, check the type of the self argument. + // - See "Checking for a specific type" + { // ... - } } } } ``` -# Checking if a type implements a specific trait +## Checking for a specific type -There are two ways to do this, depending if the target trait is part of lang items. +There are three ways to check if an expression type is a specific type we want to check for. +All of these methods only check for the base type, generic arguments have to be checked separately. ```rust -use clippy_utils::{implements_trait, match_trait_method, paths}; +use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item}; +use clippy_utils::{paths, match_def_path}; +use rustc_span::symbol::sym; +use rustc_hir::LangItem; 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) { - // `expr` implements `Into` trait + // Getting the expression type + let ty = cx.typeck_results().expr_ty(expr); + + // 1. Using diagnostic items + // The last argument is the diagnostic item to check for + if is_type_diagnostic_item(cx, ty, sym::Option) { + // The type is an `Option` + } + + // 2. Using lang items + if is_type_lang_item(cx, ty, LangItem::RangeFull) { + // The type is a full range like `.drain(..)` + } + + // 3. Using the type path + // This method should be avoided if possible + if match_def_path(cx, def_id, &paths::RESULT) { + // The type is a `core::result::Result` + } + } +} +``` + +Prefer using diagnostic items and lang items where possible. + +## Checking if a type implements a specific trait + +There are three ways to do this, depending on if the target trait has a diagnostic item, lang item or neither. + +```rust +use clippy_utils::{implements_trait, is_trait_method, match_trait_method, paths}; +use rustc_span::symbol::sym; + +impl LateLintPass<'_> for MyStructLint { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + // 1. Using diagnostic items with the expression + // we use `is_trait_method` function from Clippy's utils + if is_trait_method(cx, expr, sym::Iterator) { + // method call in `expr` belongs to `Iterator` trait } - // 2. Using type context `TyCtxt` + // 2. Using lang items with the expression type let ty = cx.typeck_results().expr_ty(expr); if cx.tcx.lang_items() // we are looking for the `DefId` of `Drop` trait in lang items @@ -97,102 +138,125 @@ impl LateLintPass<'_> for MyStructLint { .map_or(false, |id| implements_trait(cx, ty, id, &[])) { // `expr` implements `Drop` trait } + + // 3. Using the type path with the expression + // we use `match_trait_method` function from Clippy's utils + // (This method should be avoided if possible) + if match_trait_method(cx, expr, &paths::INTO) { + // `expr` implements `Into` trait + } } } ``` -> Prefer using lang items, if the target trait is available there. - -A list of defined paths for Clippy can be found in [paths.rs][paths] +> Prefer using diagnostic and lang items, if the target trait has one. We access lang items through the type context `tcx`. `tcx` is of type [`TyCtxt`][TyCtxt] and is defined in the `rustc_middle` crate. +A list of defined paths for Clippy can be found in [paths.rs][paths] -# Checking if a type defines a specific method +## Checking if a type defines a specific method To check if our type defines a method called `some_method`: ```rust -use clippy_utils::{is_type_diagnostic_item, return_ty}; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::return_ty; 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; + // Check if item is a method/function + if let ImplItemKind::Fn(ref signature, _) = impl_item.kind // Check the method is named `some_method` - if impl_item.ident.name == sym!(some_method); + && impl_item.ident.name == sym!(some_method) // We can also check it has a parameter `self` - if signature.decl.implicit_self.has_implicit_self(); + && signature.decl.implicit_self.has_implicit_self() // We can go further and even check if its return type is `String` - if is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id), sym!(string_type)); - then { - // ... - } + && is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id), sym!(string_type)) + { + // ... } } } ``` -# Dealing with macros - -There are several helpers in [`clippy_utils`][utils] to deal with macros: - -- `in_macro()`: detect if the given span is expanded by a macro - -You may want to use this for example to not start linting in any macro. - -```rust -macro_rules! foo { - ($param:expr) => { - match $param { - "bar" => println!("whatever"), - _ => () - } - }; -} - -foo!("bar"); - -// if we lint the `match` of `foo` call and test its span -assert_eq!(in_macro(match_span), true); -``` - -- `in_external_macro()`: detect if the given span is from an external macro, defined in a foreign crate - -You may want to use it for example to not start linting in macros from other crates - -```rust -#[macro_use] -extern crate a_crate_with_macros; - -// `foo` is defined in `a_crate_with_macros` -foo!("bar"); - -// if we lint the `match` of `foo` call and test its span -assert_eq!(in_external_macro(cx.sess(), match_span), true); -``` - -- `differing_macro_contexts()`: returns true if the two given spans are not from the same context - -```rust -macro_rules! m { - ($a:expr, $b:expr) => { - if $a.is_some() { - $b; - } - } -} - -let x: Option = Some(42); -m!(x, x.unwrap()); - -// These spans are not from the same context -// x.is_some() is from inside the macro -// x.unwrap() is from outside the macro -assert_eq!(differing_macro_contexts(x_is_some_span, x_unwrap_span), true); -``` - -[TyS]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyS.html +## Dealing with macros and expansions + +Keep in mind that macros are already expanded and desugaring is already applied +to the code representation that you are working with in Clippy. This unfortunately causes a lot of +false positives because macro expansions are "invisible" unless you actively check for them. +Generally speaking, code with macro expansions should just be ignored by Clippy because that code can be +dynamic in ways that are difficult or impossible to see. +Use the following functions to deal with macros: + +- `span.from_expansion()`: detects if a span is from macro expansion or desugaring. + Checking this is a common first step in a lint. + + ```rust + if expr.span.from_expansion() { + // just forget it + return; + } + ``` + +- `span.ctxt()`: the span's context represents whether it is from expansion, and if so, which macro call expanded it. + It is sometimes useful to check if the context of two spans are equal. + + ```rust + // expands to `1 + 0`, but don't lint + 1 + mac!() + ``` + ```rust + if left.span.ctxt() != right.span.ctxt() { + // the coder most likely cannot modify this expression + return; + } + ``` + Note: Code that is not from expansion is in the "root" context. So any spans where `from_expansion` returns `true` can + be assumed to have the same context. And so just using `span.from_expansion()` is often good enough. + + +- `in_external_macro(span)`: detect if the given span is from a macro defined in a foreign crate. + If you want the lint to work with macro-generated code, this is the next line of defense to avoid macros + not defined in the current crate. It doesn't make sense to lint code that the coder can't change. + + You may want to use it for example to not start linting in macros from other crates + + ```rust + #[macro_use] + extern crate a_crate_with_macros; + + // `foo` is defined in `a_crate_with_macros` + foo!("bar"); + + // if we lint the `match` of `foo` call and test its span + assert_eq!(in_external_macro(cx.sess(), match_span), true); + ``` + +- `span.ctxt()`: the span's context represents whether it is from expansion, and if so, what expanded it + +One thing `SpanContext` is useful for is to check if two spans are in the same context. For example, +in `a == b`, `a` and `b` have the same context. In a `macro_rules!` with `a == $b`, `$b` is expanded to some +expression with a different context from `a`. + + ```rust + macro_rules! m { + ($a:expr, $b:expr) => { + if $a.is_some() { + $b; + } + } + } + + let x: Option = Some(42); + m!(x, x.unwrap()); + + // These spans are not from the same context + // x.is_some() is from inside the macro + // x.unwrap() is from outside the macro + assert_eq!(x_is_some_span.ctxt(), x_unwrap_span.ctxt()); + ``` + +[Ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html [TyKind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html [TypeckResults]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html [expr_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.expr_ty @@ -200,4 +264,3 @@ assert_eq!(differing_macro_contexts(x_is_some_span, x_unwrap_span), true); [TyCtxt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html [pat_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TypeckResults.html#method.pat_ty [paths]: ../clippy_utils/src/paths.rs -[utils]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_utils/src/lib.rs diff --git a/book/src/infrastructure/changelog_update.md b/book/src/infrastructure/changelog_update.md index 115848c4804..0cbad2c0924 100644 --- a/book/src/infrastructure/changelog_update.md +++ b/book/src/infrastructure/changelog_update.md @@ -32,7 +32,7 @@ bullet points might be helpful: need to check out the Rust release tag of the stable release. [Link][rust_stable_tools] -Usually you want to wirte the changelog of the **upcoming stable release**. Make +Usually you want to write the changelog of the **upcoming stable release**. Make sure though, that `beta` was already branched in the Rust repository. To find the commit hash, issue the following command when in a `rust-lang/rust` checkout: diff --git a/book/src/infrastructure/release.md b/book/src/infrastructure/release.md index afe3033c288..c4f8f989384 100644 --- a/book/src/infrastructure/release.md +++ b/book/src/infrastructure/release.md @@ -121,4 +121,25 @@ happened a stable backport, make sure to re-merge those changes just as with the For this see the document on [how to update the changelog]. +If you don't have time to do a complete changelog update right away, just update +the following parts: + +- Remove the `(beta)` from the new stable version: + + ```markdown + ## Rust 1.XX (beta) -> ## Rust 1.XX + ``` + +- Update the release date line of the new stable version: + + ```markdown + Current beta, release 20YY-MM-DD -> Current stable, released 20YY-MM-DD + ``` + +- Update the release date line of the previous stable version: + + ```markdown + Current stable, released 20YY-MM-DD -> Released 20YY-MM-DD + ``` + [how to update the changelog]: https://github.com/rust-lang/rust-clippy/blob/master/doc/changelog_update.md diff --git a/doc/adding_lints.md b/doc/adding_lints.md deleted file mode 100644 index 3e0b1c5c4f7..00000000000 --- a/doc/adding_lints.md +++ /dev/null @@ -1,697 +0,0 @@ -# Adding a new lint - -You are probably here because you want to add a new lint to Clippy. If this is -the first time you're contributing to Clippy, this document guides you through -creating an example lint from scratch. - -To get started, we will create a lint that detects functions called `foo`, -because that's clearly a non-descriptive name. - -- [Adding a new lint](#adding-a-new-lint) - - [Setup](#setup) - - [Getting Started](#getting-started) - - [Testing](#testing) - - [Cargo lints](#cargo-lints) - - [Rustfix tests](#rustfix-tests) - - [Edition 2018 tests](#edition-2018-tests) - - [Testing manually](#testing-manually) - - [Lint declaration](#lint-declaration) - - [Lint registration](#lint-registration) - - [Lint passes](#lint-passes) - - [Emitting a lint](#emitting-a-lint) - - [Adding the lint logic](#adding-the-lint-logic) - - [Specifying the lint's minimum supported Rust version (MSRV)](#specifying-the-lints-minimum-supported-rust-version-msrv) - - [Author lint](#author-lint) - - [Print HIR lint](#print-hir-lint) - - [Documentation](#documentation) - - [Running rustfmt](#running-rustfmt) - - [Debugging](#debugging) - - [PR Checklist](#pr-checklist) - - [Adding configuration to a lint](#adding-configuration-to-a-lint) - - [Cheat Sheet](#cheat-sheet) - -## Setup - -See the [Basics](basics.md#get-the-code) documentation. - -## Getting Started - -There is a bit of boilerplate code that needs to be set up when creating a new -lint. Fortunately, you can use the clippy dev tools to handle this for you. We -are naming our new lint `foo_functions` (lints are generally written in snake -case), and we don't need type information so it will have an early pass type -(more on this later on). If you're not sure if the name you chose fits the lint, -take a look at our [lint naming guidelines][lint_naming]. To get started on this -lint you can run `cargo dev new_lint --name=foo_functions --pass=early ---category=pedantic` (category will default to nursery if not provided). This -command will create two files: `tests/ui/foo_functions.rs` and -`clippy_lints/src/foo_functions.rs`, as well as -[registering the lint](#lint-registration). For cargo lints, two project -hierarchies (fail/pass) will be created by default under `tests/ui-cargo`. - -Next, we'll open up these files and add our lint! - -## Testing - -Let's write some tests first that we can execute while we iterate on our lint. - -Clippy uses UI tests for testing. UI tests check that the output of Clippy is -exactly as expected. Each test is just a plain Rust file that contains the code -we want to check. The output of Clippy is compared against a `.stderr` file. -Note that you don't have to create this file yourself, we'll get to -generating the `.stderr` files further down. - -We start by opening the test file created at `tests/ui/foo_functions.rs`. - -Update the file with some examples to get started: - -```rust -#![warn(clippy::foo_functions)] - -// Impl methods -struct A; -impl A { - pub fn fo(&self) {} - pub fn foo(&self) {} - pub fn food(&self) {} -} - -// Default trait methods -trait B { - fn fo(&self) {} - fn foo(&self) {} - fn food(&self) {} -} - -// Plain functions -fn fo() {} -fn foo() {} -fn food() {} - -fn main() { - // We also don't want to lint method calls - foo(); - let a = A; - a.foo(); -} -``` - -Now we can run the test with `TESTNAME=foo_functions cargo uitest`, -currently this test is meaningless though. - -While we are working on implementing our lint, we can keep running the UI -test. That allows us to check if the output is turning into what we want. - -Once we are satisfied with the output, we need to run -`cargo dev bless` to update the `.stderr` file for our lint. -Please note that, we should run `TESTNAME=foo_functions cargo uitest` -every time before running `cargo dev bless`. -Running `TESTNAME=foo_functions cargo uitest` should pass then. When we commit -our lint, we need to commit the generated `.stderr` files, too. In general, you -should only commit files changed by `cargo dev bless` for the -specific lint you are creating/editing. Note that if the generated files are -empty, they should be removed. - -Note that you can run multiple test files by specifying a comma separated list: -`TESTNAME=foo_functions,test2,test3`. - -### Cargo lints - -For cargo lints, the process of testing differs in that we are interested in -the `Cargo.toml` manifest file. We also need a minimal crate associated -with that manifest. - -If our new lint is named e.g. `foo_categories`, after running `cargo dev new_lint` -we will find by default two new crates, each with its manifest file: - -* `tests/ui-cargo/foo_categories/fail/Cargo.toml`: this file should cause the new lint to raise an error. -* `tests/ui-cargo/foo_categories/pass/Cargo.toml`: this file should not trigger the lint. - -If you need more cases, you can copy one of those crates (under `foo_categories`) and rename it. - -The process of generating the `.stderr` file is the same, and prepending the `TESTNAME` -variable to `cargo uitest` works too. - -## Rustfix tests - -If the lint you are working on is making use of structured suggestions, the -test file should include a `// run-rustfix` comment at the top. This will -additionally run [rustfix] for that test. Rustfix will apply the suggestions -from the lint to the code of the test file and compare that to the contents of -a `.fixed` file. - -Use `cargo dev bless` to automatically generate the -`.fixed` file after running the tests. - -[rustfix]: https://github.com/rust-lang/rustfix - -## Edition 2018 tests - -Some features require the 2018 edition to work (e.g. `async_await`), but -compile-test tests run on the 2015 edition by default. To change this behavior -add `// edition:2018` at the top of the test file (note that it's space-sensitive). - -## Testing manually - -Manually testing against an example file can be useful if you have added some -`println!`s and the test suite output becomes unreadable. To try Clippy with -your local modifications, run - -``` -cargo dev lint input.rs -``` - -from the working copy root. With tests in place, let's have a look at -implementing our lint now. - -## Lint declaration - -Let's start by opening the new file created in the `clippy_lints` crate -at `clippy_lints/src/foo_functions.rs`. That's the crate where all the -lint code is. This file has already imported some initial things we will need: - -```rust -use rustc_lint::{EarlyLintPass, EarlyContext}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_ast::ast::*; -``` - -The next step is to update the lint declaration. Lints are declared using the -[`declare_clippy_lint!`][declare_clippy_lint] macro, and we just need to update -the auto-generated lint declaration to have a real description, something like this: - -```rust -declare_clippy_lint! { - /// ### What it does - /// - /// ### Why is this bad? - /// - /// ### Example - /// ```rust - /// // example code - /// ``` - #[clippy::version = "1.29.0"] - pub FOO_FUNCTIONS, - pedantic, - "function named `foo`, which is not a descriptive name" -} -``` - -* The section of lines prefixed with `///` constitutes the lint documentation - section. This is the default documentation style and will be displayed - [like this][example_lint_page]. To render and open this documentation locally - in a browser, run `cargo dev serve`. -* The `#[clippy::version]` attribute will be rendered as part of the lint documentation. - The value should be set to the current Rust version that the lint is developed in, - it can be retrieved by running `rustc -vV` in the rust-clippy directory. The version - is listed under *release*. (Use the version without the `-nightly`) suffix. -* `FOO_FUNCTIONS` is the name of our lint. Be sure to follow the - [lint naming guidelines][lint_naming] here when naming your lint. - In short, the name should state the thing that is being checked for and - read well when used with `allow`/`warn`/`deny`. -* `pedantic` sets the lint level to `Allow`. - The exact mapping can be found [here][category_level_mapping] -* The last part should be a text that explains what exactly is wrong with the - code - -The rest of this file contains an empty implementation for our lint pass, -which in this case is `EarlyLintPass` and should look like this: - -```rust -// clippy_lints/src/foo_functions.rs - -// .. imports and lint declaration .. - -declare_lint_pass!(FooFunctions => [FOO_FUNCTIONS]); - -impl EarlyLintPass for FooFunctions {} -``` - -[declare_clippy_lint]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L60 -[example_lint_page]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure -[lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints -[category_level_mapping]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L110 - -## Lint registration - -When using `cargo dev new_lint`, the lint is automatically registered and -nothing more has to be done. - -When declaring a new lint by hand and `cargo dev update_lints` is used, the lint -pass may have to be registered manually in the `register_plugins` function in -`clippy_lints/src/lib.rs`: - -```rust -store.register_early_pass(|| Box::new(foo_functions::FooFunctions)); -``` - -As one may expect, there is a corresponding `register_late_pass` method -available as well. Without a call to one of `register_early_pass` or -`register_late_pass`, the lint pass in question will not be run. - -One reason that `cargo dev update_lints` does not automate this step is that -multiple lints can use the same lint pass, so registering the lint pass may -already be done when adding a new lint. Another reason that this step is not -automated is that the order that the passes are registered determines the order -the passes actually run, which in turn affects the order that any emitted lints -are output in. - -## Lint passes - -Writing a lint that only checks for the name of a function means that we only -have to deal with the AST and don't have to deal with the type system at all. -This is good, because it makes writing this particular lint less complicated. - -We have to make this decision with every new Clippy lint. It boils down to using -either [`EarlyLintPass`][early_lint_pass] or [`LateLintPass`][late_lint_pass]. - -In short, the `LateLintPass` has access to type information while the -`EarlyLintPass` doesn't. If you don't need access to type information, use the -`EarlyLintPass`. The `EarlyLintPass` is also faster. However linting speed -hasn't really been a concern with Clippy so far. - -Since we don't need type information for checking the function name, we used -`--pass=early` when running the new lint automation and all the imports were -added accordingly. - -[early_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.EarlyLintPass.html -[late_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html - -## Emitting a lint - -With UI tests and the lint declaration in place, we can start working on the -implementation of the lint logic. - -Let's start by implementing the `EarlyLintPass` for our `FooFunctions`: - -```rust -impl EarlyLintPass for FooFunctions { - fn check_fn(&mut self, cx: &EarlyContext<'_>, fn_kind: FnKind<'_>, span: Span, _: NodeId) { - // TODO: Emit lint here - } -} -``` - -We implement the [`check_fn`][check_fn] method from the -[`EarlyLintPass`][early_lint_pass] trait. This gives us access to various -information about the function that is currently being checked. More on that in -the next section. Let's worry about the details later and emit our lint for -*every* function definition first. - -Depending on how complex we want our lint message to be, we can choose from a -variety of lint emission functions. They can all be found in -[`clippy_utils/src/diagnostics.rs`][diagnostics]. - -`span_lint_and_help` seems most appropriate in this case. It allows us to -provide an extra help message and we can't really suggest a better name -automatically. This is how it looks: - -```rust -impl EarlyLintPass for FooFunctions { - fn check_fn(&mut self, cx: &EarlyContext<'_>, fn_kind: FnKind<'_>, span: Span, _: NodeId) { - span_lint_and_help( - cx, - FOO_FUNCTIONS, - span, - "function named `foo`", - None, - "consider using a more meaningful name" - ); - } -} -``` - -Running our UI test should now produce output that contains the lint message. - -According to [the rustc-dev-guide], the text should be matter of fact and avoid -capitalization and periods, unless multiple sentences are needed. -When code or an identifier must appear in a message or label, it should be -surrounded with single grave accents \`. - -[check_fn]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.EarlyLintPass.html#method.check_fn -[diagnostics]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_utils/src/diagnostics.rs -[the rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/diagnostics.html - -## Adding the lint logic - -Writing the logic for your lint will most likely be different from our example, -so this section is kept rather short. - -Using the [`check_fn`][check_fn] method gives us access to [`FnKind`][fn_kind] -that has the [`FnKind::Fn`] variant. It provides access to the name of the -function/method via an [`Ident`][ident]. - -With that we can expand our `check_fn` method to: - -```rust -impl EarlyLintPass for FooFunctions { - fn check_fn(&mut self, cx: &EarlyContext<'_>, fn_kind: FnKind<'_>, span: Span, _: NodeId) { - if is_foo_fn(fn_kind) { - span_lint_and_help( - cx, - FOO_FUNCTIONS, - span, - "function named `foo`", - None, - "consider using a more meaningful name" - ); - } - } -} -``` - -We separate the lint conditional from the lint emissions because it makes the -code a bit easier to read. In some cases this separation would also allow to -write some unit tests (as opposed to only UI tests) for the separate function. - -In our example, `is_foo_fn` looks like: - -```rust -// use statements, impl EarlyLintPass, check_fn, .. - -fn is_foo_fn(fn_kind: FnKind<'_>) -> bool { - match fn_kind { - FnKind::Fn(_, ident, ..) => { - // check if `fn` name is `foo` - ident.name.as_str() == "foo" - } - // ignore closures - FnKind::Closure(..) => false - } -} -``` - -Now we should also run the full test suite with `cargo test`. At this point -running `cargo test` should produce the expected output. Remember to run -`cargo dev bless` to update the `.stderr` file. - -`cargo test` (as opposed to `cargo uitest`) will also ensure that our lint -implementation is not violating any Clippy lints itself. - -That should be it for the lint implementation. Running `cargo test` should now -pass. - -[fn_kind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/visit/enum.FnKind.html -[`FnKind::Fn`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/visit/enum.FnKind.html#variant.Fn -[ident]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/symbol/struct.Ident.html - -## Specifying the lint's minimum supported Rust version (MSRV) - -Sometimes a lint makes suggestions that require a certain version of Rust. For example, the `manual_strip` lint suggests -using `str::strip_prefix` and `str::strip_suffix` which is only available after Rust 1.45. In such cases, you need to -ensure that the MSRV configured for the project is >= the MSRV of the required Rust feature. If multiple features are -required, just use the one with a lower MSRV. - -First, add an MSRV alias for the required feature in [`clippy_utils::msrvs`](/clippy_utils/src/msrvs.rs). This can be -accessed later as `msrvs::STR_STRIP_PREFIX`, for example. - -```rust -msrv_aliases! { - .. - 1,45,0 { STR_STRIP_PREFIX } -} -``` - -In order to access the project-configured MSRV, you need to have an `msrv` field in the LintPass struct, and a -constructor to initialize the field. The `msrv` value is passed to the constructor in `clippy_lints/lib.rs`. - -```rust -pub struct ManualStrip { - msrv: Option, -} - -impl ManualStrip { - #[must_use] - pub fn new(msrv: Option) -> Self { - Self { msrv } - } -} -``` - -The project's MSRV can then be matched against the feature MSRV in the LintPass -using the `meets_msrv` utility function. - -``` rust -if !meets_msrv(self.msrv, msrvs::STR_STRIP_PREFIX) { - return; -} -``` - -The project's MSRV can also be specified as an inner attribute, which overrides -the value from `clippy.toml`. This can be accounted for using the -`extract_msrv_attr!(LintContext)` macro and passing -`LateContext`/`EarlyContext`. - -```rust -impl<'tcx> LateLintPass<'tcx> for ManualStrip { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - ... - } - extract_msrv_attr!(LateContext); -} -``` - -Once the `msrv` is added to the lint, a relevant test case should be added to -`tests/ui/min_rust_version_attr.rs` which verifies that the lint isn't emitted -if the project's MSRV is lower. - -As a last step, the lint should be added to the lint documentation. This is done -in `clippy_lints/src/utils/conf.rs`: - -```rust -define_Conf! { - /// Lint: LIST, OF, LINTS, . The minimum rust version that the project supports - (msrv: Option = None), - ... -} -``` - -## Author lint - -If you have trouble implementing your lint, there is also the internal `author` -lint to generate Clippy code that detects the offending pattern. It does not -work for all of the Rust syntax, but can give a good starting point. - -The quickest way to use it, is the -[Rust playground: play.rust-lang.org][author_example]. -Put the code you want to lint into the editor and add the `#[clippy::author]` -attribute above the item. Then run Clippy via `Tools -> Clippy` and you should -see the generated code in the output below. - -[Here][author_example] is an example on the playground. - -If the command was executed successfully, you can copy the code over to where -you are implementing your lint. - -[author_example]: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=9a12cb60e5c6ad4e3003ac6d5e63cf55 - -## Print HIR lint - -To implement a lint, it's helpful to first understand the internal representation -that rustc uses. Clippy has the `#[clippy::dump]` attribute that prints the -[_High-Level Intermediate Representation (HIR)_] of the item, statement, or -expression that the attribute is attached to. To attach the attribute to expressions -you often need to enable `#![feature(stmt_expr_attributes)]`. - -[Here][print_hir_example] you can find an example, just select _Tools_ and run _Clippy_. - -[_High-Level Intermediate Representation (HIR)_]: https://rustc-dev-guide.rust-lang.org/hir.html -[print_hir_example]: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=daf14db3a7f39ca467cd1b86c34b9afb - -## Documentation - -The final thing before submitting our PR is to add some documentation to our -lint declaration. - -Please document your lint with a doc comment akin to the following: - -```rust -declare_clippy_lint! { - /// ### What it does - /// Checks for ... (describe what the lint matches). - /// - /// ### Why is this bad? - /// Supply the reason for linting the code. - /// - /// ### Example - /// - /// ```rust,ignore - /// // A short example of code that triggers the lint - /// ``` - /// - /// Use instead: - /// ```rust,ignore - /// // A short example of improved code that doesn't trigger the lint - /// ``` - #[clippy::version = "1.29.0"] - pub FOO_FUNCTIONS, - pedantic, - "function named `foo`, which is not a descriptive name" -} -``` - -Once your lint is merged, this documentation will show up in the [lint -list][lint_list]. - -[lint_list]: https://rust-lang.github.io/rust-clippy/master/index.html - -## Running rustfmt - -[Rustfmt] is a tool for formatting Rust code according to style guidelines. -Your code has to be formatted by `rustfmt` before a PR can be merged. -Clippy uses nightly `rustfmt` in the CI. - -It can be installed via `rustup`: - -```bash -rustup component add rustfmt --toolchain=nightly -``` - -Use `cargo dev fmt` to format the whole codebase. Make sure that `rustfmt` is -installed for the nightly toolchain. - -[Rustfmt]: https://github.com/rust-lang/rustfmt - -## Debugging - -If you want to debug parts of your lint implementation, you can use the [`dbg!`] -macro anywhere in your code. Running the tests should then include the debug -output in the `stdout` part. - -[`dbg!`]: https://doc.rust-lang.org/std/macro.dbg.html - -## PR Checklist - -Before submitting your PR make sure you followed all of the basic requirements: - - - -- \[ ] Followed [lint naming conventions][lint_naming] -- \[ ] Added passing UI tests (including committed `.stderr` file) -- \[ ] `cargo test` passes locally -- \[ ] Executed `cargo dev update_lints` -- \[ ] Added lint documentation -- \[ ] Run `cargo dev fmt` - -## Adding configuration to a lint - -Clippy supports the configuration of lints values using a `clippy.toml` file in the workspace -directory. Adding a configuration to a lint can be useful for thresholds or to constrain some -behavior that can be seen as a false positive for some users. Adding a configuration is done -in the following steps: - -1. Adding a new configuration entry to [clippy_lints::utils::conf](/clippy_lints/src/utils/conf.rs) - like this: - ```rust - /// Lint: LINT_NAME. - /// - /// - (configuration_ident: Type = DefaultValue), - ``` - The doc comment is automatically added to the documentation of the listed lints. The default - value will be formatted using the `Debug` implementation of the type. -2. Adding the configuration value to the lint impl struct: - 1. This first requires the definition of a lint impl struct. Lint impl structs are usually - generated with the `declare_lint_pass!` macro. This struct needs to be defined manually - to add some kind of metadata to it: - ```rust - // Generated struct definition - declare_lint_pass!(StructName => [ - LINT_NAME - ]); - - // New manual definition struct - #[derive(Copy, Clone)] - pub struct StructName {} - - impl_lint_pass!(StructName => [ - LINT_NAME - ]); - ``` - - 2. Next add the configuration value and a corresponding creation method like this: - ```rust - #[derive(Copy, Clone)] - pub struct StructName { - configuration_ident: Type, - } - - // ... - - impl StructName { - pub fn new(configuration_ident: Type) -> Self { - Self { - configuration_ident, - } - } - } - ``` -3. Passing the configuration value to the lint impl struct: - - First find the struct construction in the [clippy_lints lib file](/clippy_lints/src/lib.rs). - The configuration value is now cloned or copied into a local value that is then passed to the - impl struct like this: - ```rust - // Default generated registration: - store.register_*_pass(|| box module::StructName); - - // New registration with configuration value - let configuration_ident = conf.configuration_ident.clone(); - store.register_*_pass(move || box module::StructName::new(configuration_ident)); - ``` - - Congratulations the work is almost done. The configuration value can now be accessed - in the linting code via `self.configuration_ident`. - -4. Adding tests: - 1. The default configured value can be tested like any normal lint in [`tests/ui`](/tests/ui). - 2. The configuration itself will be tested separately in [`tests/ui-toml`](/tests/ui-toml). - Simply add a new subfolder with a fitting name. This folder contains a `clippy.toml` file - with the configuration value and a rust file that should be linted by Clippy. The test can - otherwise be written as usual. - -## Cheat Sheet - -Here are some pointers to things you are likely going to need for every lint: - -* [Clippy utils][utils] - Various helper functions. Maybe the function you need - is already in here ([`is_type_diagnostic_item`], [`implements_trait`], [`snippet`], etc) -* [Clippy diagnostics][diagnostics] -* [Let chains][let-chains] -* [`from_expansion`][from_expansion] and [`in_external_macro`][in_external_macro] -* [`Span`][span] -* [`Applicability`][applicability] -* [Common tools for writing lints](common_tools_writing_lints.md) helps with common operations -* [The rustc-dev-guide][rustc-dev-guide] explains a lot of internal compiler concepts -* [The nightly rustc docs][nightly_docs] which has been linked to throughout - this guide - -For `EarlyLintPass` lints: - -* [`EarlyLintPass`][early_lint_pass] -* [`rustc_ast::ast`][ast] - -For `LateLintPass` lints: - -* [`LateLintPass`][late_lint_pass] -* [`Ty::TyKind`][ty] - -While most of Clippy's lint utils are documented, most of rustc's internals lack -documentation currently. This is unfortunate, but in most cases you can probably -get away with copying things from existing similar lints. If you are stuck, -don't hesitate to ask on [Zulip] or in the issue/PR. - -[utils]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/index.html -[`is_type_diagnostic_item`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/ty/fn.is_type_diagnostic_item.html -[`implements_trait`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/ty/fn.implements_trait.html -[`snippet`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/source/fn.snippet.html -[let-chains]: https://github.com/rust-lang/rust/pull/94927 -[from_expansion]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html#method.from_expansion -[in_external_macro]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/lint/fn.in_external_macro.html -[span]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html -[applicability]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/enum.Applicability.html -[rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/ -[nightly_docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ -[ast]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/index.html -[ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/sty/index.html -[Zulip]: https://rust-lang.zulipchat.com/#narrow/stream/clippy diff --git a/doc/backport.md b/doc/backport.md deleted file mode 100644 index 15f3d1f0806..00000000000 --- a/doc/backport.md +++ /dev/null @@ -1,71 +0,0 @@ -# Backport Changes - -Sometimes it is necessary to backport changes to the beta release of Clippy. -Backports in Clippy are rare and should be approved by the Clippy team. For -example, a backport is done, if a crucial ICE was fixed or a lint is broken to a -point, that it has to be disabled, before landing on stable. - -Backports are done to the `beta` branch of Clippy. Backports to stable Clippy -releases basically don't exist, since this would require a Rust point release, -which is almost never justifiable for a Clippy fix. - - -## Backport the changes - -Backports are done on the beta branch of the Clippy repository. - -```bash -# Assuming the current directory corresponds to the Clippy repository -$ git checkout beta -$ git checkout -b backport -$ git cherry-pick # `` is the commit hash of the commit(s), that should be backported -$ git push origin backport -``` - -Now you should test that the backport passes all the tests in the Rust -repository. You can do this with: - -```bash -# Assuming the current directory corresponds to the Rust repository -$ git checkout beta -$ git subtree pull -p src/tools/clippy https://github.com//rust-clippy backport -$ ./x.py test src/tools/clippy -``` - -Should the test fail, you can fix Clippy directly in the Rust repository. This -has to be first applied to the Clippy beta branch and then again synced to the -Rust repository, though. The easiest way to do this is: - -```bash -# In the Rust repository -$ git diff --patch --relative=src/tools/clippy > clippy.patch -# In the Clippy repository -$ git apply /path/to/clippy.patch -$ git add -u -$ git commit -m "Fix rustup fallout" -$ git push origin backport -``` - -After this, you can open a PR to the `beta` branch of the Clippy repository. - - -## Update Clippy in the Rust Repository - -This step must be done, **after** the PR of the previous step was merged. - -After the backport landed in the Clippy repository, the branch has to be synced -back to the beta branch of the Rust repository. - -```bash -# Assuming the current directory corresponds to the Rust repository -$ git checkout beta -$ git checkout -b clippy_backport -$ git subtree pull -p src/tools/clippy https://github.com/rust-lang/rust-clippy beta -$ git push origin clippy_backport -``` - -Make sure to test the backport in the Rust repository before opening a PR. This -is done with `./x.py test src/tools/clippy`. If that passes all tests, open a PR -to the `beta` branch of the Rust repository. In this PR you should tag the -Clippy team member, that agreed to the backport or the `@rust-lang/clippy` team. -Make sure to add `[beta]` to the title of the PR. diff --git a/doc/basics.md b/doc/basics.md deleted file mode 100644 index 57a90a924ec..00000000000 --- a/doc/basics.md +++ /dev/null @@ -1,174 +0,0 @@ -# Basics for hacking on Clippy - -This document explains the basics for hacking on Clippy. Besides others, this -includes how to build and test Clippy. For a more in depth description on -the codebase take a look at [Adding Lints] or [Common Tools]. - -[Adding Lints]: https://github.com/rust-lang/rust-clippy/blob/master/doc/adding_lints.md -[Common Tools]: https://github.com/rust-lang/rust-clippy/blob/master/doc/common_tools_writing_lints.md - -- [Basics for hacking on Clippy](#basics-for-hacking-on-clippy) - - [Get the Code](#get-the-code) - - [Building and Testing](#building-and-testing) - - [`cargo dev`](#cargo-dev) - - [lintcheck](#lintcheck) - - [PR](#pr) - - [Common Abbreviations](#common-abbreviations) - - [Install from source](#install-from-source) - -## Get the Code - -First, make sure you have checked out the latest version of Clippy. If this is -your first time working on Clippy, create a fork of the repository and clone it -afterwards with the following command: - -```bash -git clone git@github.com:/rust-clippy -``` - -If you've already cloned Clippy in the past, update it to the latest version: - -```bash -# If the upstream remote has not been added yet -git remote add upstream https://github.com/rust-lang/rust-clippy -# upstream has to be the remote of the rust-lang/rust-clippy repo -git fetch upstream -# make sure that you are on the master branch -git checkout master -# rebase your master branch on the upstream master -git rebase upstream/master -# push to the master branch of your fork -git push -``` - -## Building and Testing - -You can build and test Clippy like every other Rust project: - -```bash -cargo build # builds Clippy -cargo test # tests Clippy -``` - -Since Clippy's test suite is pretty big, there are some commands that only run a -subset of Clippy's tests: - -```bash -# only run UI tests -cargo uitest -# only run UI tests starting with `test_` -TESTNAME="test_" cargo uitest -# only run dogfood tests -cargo test --test dogfood -``` - -If the output of a [UI test] differs from the expected output, you can update the -reference file with: - -```bash -cargo dev bless -``` - -For example, this is necessary, if you fix a typo in an error message of a lint -or if you modify a test file to add a test case. - -_Note:_ This command may update more files than you intended. In that case only -commit the files you wanted to update. - -[UI test]: https://rustc-dev-guide.rust-lang.org/tests/adding.html#guide-to-the-ui-tests - -## `cargo dev` - -Clippy has some dev tools to make working on Clippy more convenient. These tools -can be accessed through the `cargo dev` command. Available tools are listed -below. To get more information about these commands, just call them with -`--help`. - -```bash -# formats the whole Clippy codebase and all tests -cargo dev fmt -# register or update lint names/groups/... -cargo dev update_lints -# create a new lint and register it -cargo dev new_lint -# automatically formatting all code before each commit -cargo dev setup git-hook -# (experimental) Setup Clippy to work with IntelliJ-Rust -cargo dev setup intellij -``` -More about intellij command usage and reasons [here](../CONTRIBUTING.md#intellij-rust) - -## lintcheck -`cargo lintcheck` will build and run clippy on a fixed set of crates and generate a log of the results. -You can `git diff` the updated log against its previous version and -see what impact your lint made on a small set of crates. -If you add a new lint, please audit the resulting warnings and make sure -there are no false positives and that the suggestions are valid. - -Refer to the tools [README] for more details. - -[README]: https://github.com/rust-lang/rust-clippy/blob/master/lintcheck/README.md -## PR - -We follow a rustc no merge-commit policy. -See . - -## Common Abbreviations - -| Abbreviation | Meaning | -| ------------ | -------------------------------------- | -| UB | Undefined Behavior | -| FP | False Positive | -| FN | False Negative | -| ICE | Internal Compiler Error | -| AST | Abstract Syntax Tree | -| MIR | Mid-Level Intermediate Representation | -| HIR | High-Level Intermediate Representation | -| TCX | Type context | - -This is a concise list of abbreviations that can come up during Clippy development. An extensive -general list can be found in the [rustc-dev-guide glossary][glossary]. Always feel free to ask if -an abbreviation or meaning is unclear to you. - -## Install from source - -If you are hacking on Clippy and want to install it from source, do the following: - -First, take note of the toolchain [override](https://rust-lang.github.io/rustup/overrides.html) in `/rust-toolchain`. -We will use this override to install Clippy into the right toolchain. - -> Tip: You can view the active toolchain for the current directory with `rustup show active-toolchain`. - -From the Clippy project root, run the following command to build the Clippy binaries and copy them into the -toolchain directory. This will override the currently installed Clippy component. - -```terminal -cargo build --release --bin cargo-clippy --bin clippy-driver -Zunstable-options --out-dir "$(rustc --print=sysroot)/bin" -``` - -Now you may run `cargo clippy` in any project, using the toolchain where you just installed Clippy. - -```terminal -cd my-project -cargo +nightly-2021-07-01 clippy -``` - -...or `clippy-driver` - -```terminal -clippy-driver +nightly-2021-07-01 -``` - -If you need to restore the default Clippy installation, run the following (from the Clippy project root). - -```terminal -rustup component remove clippy -rustup component add clippy -``` - -> **DO NOT** install using `cargo install --path . --force` since this will overwrite rustup -> [proxies](https://rust-lang.github.io/rustup/concepts/proxies.html). That is, `~/.cargo/bin/cargo-clippy` and -> `~/.cargo/bin/clippy-driver` should be hard or soft links to `~/.cargo/bin/rustup`. You can repair these by running -> `rustup update`. - -[glossary]: https://rustc-dev-guide.rust-lang.org/appendix/glossary.html diff --git a/doc/changelog_update.md b/doc/changelog_update.md deleted file mode 100644 index 0cbad2c0924..00000000000 --- a/doc/changelog_update.md +++ /dev/null @@ -1,97 +0,0 @@ -# Changelog Update - -If you want to help with updating the [changelog][changelog], you're in the right place. - -## When to update - -Typos and other small fixes/additions are _always_ welcome. - -Special care needs to be taken when it comes to updating the changelog for a new -Rust release. For that purpose, the changelog is ideally updated during the week -before an upcoming stable release. You can find the release dates on the [Rust -Forge][forge]. - -Most of the time we only need to update the changelog for minor Rust releases. It's -been very rare that Clippy changes were included in a patch release. - -## Changelog update walkthrough - -### 1. Finding the relevant Clippy commits - -Each Rust release ships with its own version of Clippy. The Clippy subtree can -be found in the `tools` directory of the Rust repository. - -Depending on the current time and what exactly you want to update, the following -bullet points might be helpful: - -* When writing the release notes for the **upcoming stable release** you need to check - out the Clippy commit of the current Rust `beta` branch. [Link][rust_beta_tools] -* When writing the release notes for the **upcoming beta release**, you need to check - out the Clippy commit of the current Rust `master`. [Link][rust_master_tools] -* When writing the (forgotten) release notes for a **past stable release**, you - need to check out the Rust release tag of the stable release. - [Link][rust_stable_tools] - -Usually you want to write the changelog of the **upcoming stable release**. Make -sure though, that `beta` was already branched in the Rust repository. - -To find the commit hash, issue the following command when in a `rust-lang/rust` checkout: -``` -git log --oneline -- src/tools/clippy/ | grep -o "Merge commit '[a-f0-9]*' into .*" | head -1 | sed -e "s/Merge commit '\([a-f0-9]*\)' into .*/\1/g" -``` - -### 2. Fetching the PRs between those commits - -Once you've got the correct commit range, run - - util/fetch_prs_between.sh commit1 commit2 > changes.txt - -and open that file in your editor of choice. - -When updating the changelog it's also a good idea to make sure that `commit1` is -already correct in the current changelog. - -### 3. Authoring the final changelog - -The above script should have dumped all the relevant PRs to the file you -specified. It should have filtered out most of the irrelevant PRs -already, but it's a good idea to do a manual cleanup pass where you look for -more irrelevant PRs. If you're not sure about some PRs, just leave them in for -the review and ask for feedback. - -With the PRs filtered, you can start to take each PR and move the -`changelog: ` content to `CHANGELOG.md`. Adapt the wording as you see fit but -try to keep it somewhat coherent. - -The order should roughly be: - -1. New lints -2. Moves or deprecations of lints -3. Changes that expand what code existing lints cover -4. False positive fixes -5. Suggestion fixes/improvements -6. ICE fixes -7. Documentation improvements -8. Others - -As section headers, we use: - -``` -### New Lints -### Moves and Deprecations -### Enhancements -### False Positive Fixes -### Suggestion Fixes/Improvements -### ICE Fixes -### Documentation Improvements -### Others -``` - -Please also be sure to update the Beta/Unreleased sections at the top with the -relevant commit ranges. - -[changelog]: https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md -[forge]: https://forge.rust-lang.org/ -[rust_master_tools]: https://github.com/rust-lang/rust/tree/master/src/tools/clippy -[rust_beta_tools]: https://github.com/rust-lang/rust/tree/beta/src/tools/clippy -[rust_stable_tools]: https://github.com/rust-lang/rust/releases diff --git a/doc/common_tools_writing_lints.md b/doc/common_tools_writing_lints.md deleted file mode 100644 index 1d1aee0da2c..00000000000 --- a/doc/common_tools_writing_lints.md +++ /dev/null @@ -1,266 +0,0 @@ -# Common tools for writing lints - -You may need following tooltips to catch up with common operations. - -- [Common tools for writing lints](#common-tools-for-writing-lints) - - [Retrieving the type of an expression](#retrieving-the-type-of-an-expression) - - [Checking if an expr is calling a specific method](#checking-if-an-expr-is-calling-a-specific-method) - - [Checking for a specific type](#checking-for-a-specific-type) - - [Checking if a type implements a specific trait](#checking-if-a-type-implements-a-specific-trait) - - [Checking if a type defines a specific method](#checking-if-a-type-defines-a-specific-method) - - [Dealing with macros](#dealing-with-macros-and-expansions) - -Useful Rustc dev guide links: -- [Stages of compilation](https://rustc-dev-guide.rust-lang.org/compiler-src.html#the-main-stages-of-compilation) -- [Diagnostic items](https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-items.html) -- [Type checking](https://rustc-dev-guide.rust-lang.org/type-checking.html) -- [Ty module](https://rustc-dev-guide.rust-lang.org/ty.html) - -## Retrieving the type of an expression - -Sometimes you may want to retrieve the type `Ty` of an expression `Expr`, for example to answer following questions: - -- which type does this expression correspond to (using its [`TyKind`][TyKind])? -- is it a sized type? -- is it a primitive type? -- does it implement a trait? - -This operation is performed using the [`expr_ty()`][expr_ty] method from the [`TypeckResults`][TypeckResults] struct, -that gives you access to the underlying structure [`Ty`][Ty]. - -Example of use: -```rust -impl LateLintPass<'_> for MyStructLint { - fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { - // Get type of `expr` - let ty = cx.typeck_results().expr_ty(expr); - // Match its kind to enter its type - match ty.kind { - ty::Adt(adt_def, _) if adt_def.is_struct() => println!("Our `expr` is a struct!"), - _ => () - } - } -} -``` - -Similarly in [`TypeckResults`][TypeckResults] methods, you have the [`pat_ty()`][pat_ty] method -to retrieve a type from a pattern. - -Two noticeable items here: -- `cx` is the lint context [`LateContext`][LateContext]. The two most useful - data structures in this context are `tcx` and the `TypeckResults` returned by - `LateContext::typeck_results`, allowing us to jump to type definitions and - other compilation stages such as HIR. -- `typeck_results`'s return value is [`TypeckResults`][TypeckResults] and is - created by type checking step, it includes useful information such as types - of expressions, ways to resolve methods and so on. - -## Checking if an expr is calling a specific method - -Starting with an `expr`, you can check whether it is calling a specific method `some_method`: - -```rust -impl<'tcx> LateLintPass<'tcx> for MyStructLint { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { - // Check our expr is calling a method - if let hir::ExprKind::MethodCall(path, _, [_self_arg, ..]) = &expr.kind - // Check the name of this method is `some_method` - && path.ident.name == sym!(some_method) - // Optionally, check the type of the self argument. - // - See "Checking for a specific type" - { - // ... - } - } -} -``` - -## Checking for a specific type - -There are three ways to check if an expression type is a specific type we want to check for. -All of these methods only check for the base type, generic arguments have to be checked separately. - -```rust -use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item}; -use clippy_utils::{paths, match_def_path}; -use rustc_span::symbol::sym; -use rustc_hir::LangItem; - -impl LateLintPass<'_> for MyStructLint { - fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { - // Getting the expression type - let ty = cx.typeck_results().expr_ty(expr); - - // 1. Using diagnostic items - // The last argument is the diagnostic item to check for - if is_type_diagnostic_item(cx, ty, sym::Option) { - // The type is an `Option` - } - - // 2. Using lang items - if is_type_lang_item(cx, ty, LangItem::RangeFull) { - // The type is a full range like `.drain(..)` - } - - // 3. Using the type path - // This method should be avoided if possible - if match_def_path(cx, def_id, &paths::RESULT) { - // The type is a `core::result::Result` - } - } -} -``` - -Prefer using diagnostic items and lang items where possible. - -## Checking if a type implements a specific trait - -There are three ways to do this, depending on if the target trait has a diagnostic item, lang item or neither. - -```rust -use clippy_utils::{implements_trait, is_trait_method, match_trait_method, paths}; -use rustc_span::symbol::sym; - -impl LateLintPass<'_> for MyStructLint { - fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { - // 1. Using diagnostic items with the expression - // we use `is_trait_method` function from Clippy's utils - if is_trait_method(cx, expr, sym::Iterator) { - // method call in `expr` belongs to `Iterator` trait - } - - // 2. Using lang items with the expression type - let ty = cx.typeck_results().expr_ty(expr); - if cx.tcx.lang_items() - // we are looking for the `DefId` of `Drop` trait in lang items - .drop_trait() - // then we use it with our type `ty` by calling `implements_trait` from Clippy's utils - .map_or(false, |id| implements_trait(cx, ty, id, &[])) { - // `expr` implements `Drop` trait - } - - // 3. Using the type path with the expression - // we use `match_trait_method` function from Clippy's utils - // (This method should be avoided if possible) - if match_trait_method(cx, expr, &paths::INTO) { - // `expr` implements `Into` trait - } - } -} -``` - -> Prefer using diagnostic and lang items, if the target trait has one. - -We access lang items through the type context `tcx`. `tcx` is of type [`TyCtxt`][TyCtxt] and is defined in the `rustc_middle` crate. -A list of defined paths for Clippy can be found in [paths.rs][paths] - -## Checking if a type defines a specific method - -To check if our type defines a method called `some_method`: - -```rust -use clippy_utils::ty::is_type_diagnostic_item; -use clippy_utils::return_ty; - -impl<'tcx> LateLintPass<'tcx> for MyTypeImpl { - fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) { - // Check if item is a method/function - if let ImplItemKind::Fn(ref signature, _) = impl_item.kind - // Check the method is named `some_method` - && impl_item.ident.name == sym!(some_method) - // We can also check it has a parameter `self` - && signature.decl.implicit_self.has_implicit_self() - // We can go further and even check if its return type is `String` - && is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id), sym!(string_type)) - { - // ... - } - } -} -``` - -## Dealing with macros and expansions - -Keep in mind that macros are already expanded and desugaring is already applied -to the code representation that you are working with in Clippy. This unfortunately causes a lot of -false positives because macro expansions are "invisible" unless you actively check for them. -Generally speaking, code with macro expansions should just be ignored by Clippy because that code can be -dynamic in ways that are difficult or impossible to see. -Use the following functions to deal with macros: - -- `span.from_expansion()`: detects if a span is from macro expansion or desugaring. - Checking this is a common first step in a lint. - - ```rust - if expr.span.from_expansion() { - // just forget it - return; - } - ``` - -- `span.ctxt()`: the span's context represents whether it is from expansion, and if so, which macro call expanded it. - It is sometimes useful to check if the context of two spans are equal. - - ```rust - // expands to `1 + 0`, but don't lint - 1 + mac!() - ``` - ```rust - if left.span.ctxt() != right.span.ctxt() { - // the coder most likely cannot modify this expression - return; - } - ``` - Note: Code that is not from expansion is in the "root" context. So any spans where `from_expansion` returns `true` can - be assumed to have the same context. And so just using `span.from_expansion()` is often good enough. - - -- `in_external_macro(span)`: detect if the given span is from a macro defined in a foreign crate. - If you want the lint to work with macro-generated code, this is the next line of defense to avoid macros - not defined in the current crate. It doesn't make sense to lint code that the coder can't change. - - You may want to use it for example to not start linting in macros from other crates - - ```rust - #[macro_use] - extern crate a_crate_with_macros; - - // `foo` is defined in `a_crate_with_macros` - foo!("bar"); - - // if we lint the `match` of `foo` call and test its span - assert_eq!(in_external_macro(cx.sess(), match_span), true); - ``` - -- `span.ctxt()`: the span's context represents whether it is from expansion, and if so, what expanded it - -One thing `SpanContext` is useful for is to check if two spans are in the same context. For example, -in `a == b`, `a` and `b` have the same context. In a `macro_rules!` with `a == $b`, `$b` is expanded to some -expression with a different context from `a`. - - ```rust - macro_rules! m { - ($a:expr, $b:expr) => { - if $a.is_some() { - $b; - } - } - } - - let x: Option = Some(42); - m!(x, x.unwrap()); - - // These spans are not from the same context - // x.is_some() is from inside the macro - // x.unwrap() is from outside the macro - assert_eq!(x_is_some_span.ctxt(), x_unwrap_span.ctxt()); - ``` - -[Ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html -[TyKind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html -[TypeckResults]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html -[expr_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.expr_ty -[LateContext]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LateContext.html -[TyCtxt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html -[pat_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TypeckResults.html#method.pat_ty -[paths]: ../clippy_utils/src/paths.rs diff --git a/doc/release.md b/doc/release.md deleted file mode 100644 index c4f8f989384..00000000000 --- a/doc/release.md +++ /dev/null @@ -1,145 +0,0 @@ -# Release a new Clippy Version - -_NOTE: This document is probably only relevant to you, if you're a member of the -Clippy team._ - -Clippy is released together with stable Rust releases. The dates for these -releases can be found at the [Rust Forge]. This document explains the necessary -steps to create a Clippy release. - -1. [Remerge the `beta` branch](#remerge-the-beta-branch) -2. [Update the `beta` branch](#update-the-beta-branch) -3. [Find the Clippy commit](#find-the-clippy-commit) -4. [Tag the stable commit](#tag-the-stable-commit) -5. [Update `CHANGELOG.md`](#update-changelogmd) - -_NOTE: This document is for stable Rust releases, not for point releases. For -point releases, step 1. and 2. should be enough._ - -[Rust Forge]: https://forge.rust-lang.org/ - - -## Remerge the `beta` branch - -This step is only necessary, if since the last release something was backported -to the beta Rust release. The remerge is then necessary, to make sure that the -Clippy commit, that was used by the now stable Rust release, persists in the -tree of the Clippy repository. - -To find out if this step is necessary run - -```bash -# Assumes that the local master branch is up-to-date -$ git fetch upstream -$ git branch master --contains upstream/beta -``` - -If this command outputs `master`, this step is **not** necessary. - -```bash -# Assuming `HEAD` is the current `master` branch of rust-lang/rust-clippy -$ git checkout -b backport_remerge -$ git merge upstream/beta -$ git diff # This diff has to be empty, otherwise something with the remerge failed -$ git push origin backport_remerge # This can be pushed to your fork -``` - -After this, open a PR to the master branch. In this PR, the commit hash of the -`HEAD` of the `beta` branch must exists. In addition to that, no files should -be changed by this PR. - - -## Update the `beta` branch - -This step must be done **after** the PR of the previous step was merged. - -First, the Clippy commit of the `beta` branch of the Rust repository has to be -determined. - -```bash -# Assuming the current directory corresponds to the Rust repository -$ git checkout beta -$ BETA_SHA=$(git log --oneline -- src/tools/clippy/ | grep -o "Merge commit '[a-f0-9]*' into .*" | head -1 | sed -e "s/Merge commit '\([a-f0-9]*\)' into .*/\1/g") -``` - -After finding the Clippy commit, the `beta` branch in the Clippy repository can -be updated. - -```bash -# Assuming the current directory corresponds to the Clippy repository -$ git checkout beta -$ git reset --hard $BETA_SHA -$ git push upstream beta -``` - - -## Find the Clippy commit - -The first step is to tag the Clippy commit, that is included in the stable Rust -release. This commit can be found in the Rust repository. - -```bash -# Assuming the current directory corresponds to the Rust repository -$ git fetch upstream # `upstream` is the `rust-lang/rust` remote -$ git checkout 1.XX.0 # XX should be exchanged with the corresponding version -$ SHA=$(git log --oneline -- src/tools/clippy/ | grep -o "Merge commit '[a-f0-9]*' into .*" | head -1 | sed -e "s/Merge commit '\([a-f0-9]*\)' into .*/\1/g") -``` - - -## Tag the stable commit - -After finding the Clippy commit, it can be tagged with the release number. - -```bash -# Assuming the current directory corresponds to the Clippy repository -$ git checkout $SHA -$ git tag rust-1.XX.0 # XX should be exchanged with the corresponding version -$ git push upstream rust-1.XX.0 # `upstream` is the `rust-lang/rust-clippy` remote -``` - -After this, the release should be available on the Clippy [release page]. - -[release page]: https://github.com/rust-lang/rust-clippy/releases - -## Update the `stable` branch - -At this step you should have already checked out the commit of the `rust-1.XX.0` -tag. Updating the stable branch from here is as easy as: - -```bash -# Assuming the current directory corresponds to the Clippy repository and the -# commit of the just created rust-1.XX.0 tag is checked out. -$ git push upstream rust-1.XX.0:stable # `upstream` is the `rust-lang/rust-clippy` remote -``` - -_NOTE: Usually there are no stable backports for Clippy, so this update should -be possible without force pushing or anything like this. If there should have -happened a stable backport, make sure to re-merge those changes just as with the -`beta` branch._ - -## Update `CHANGELOG.md` - -For this see the document on [how to update the changelog]. - -If you don't have time to do a complete changelog update right away, just update -the following parts: - -- Remove the `(beta)` from the new stable version: - - ```markdown - ## Rust 1.XX (beta) -> ## Rust 1.XX - ``` - -- Update the release date line of the new stable version: - - ```markdown - Current beta, release 20YY-MM-DD -> Current stable, released 20YY-MM-DD - ``` - -- Update the release date line of the previous stable version: - - ```markdown - Current stable, released 20YY-MM-DD -> Released 20YY-MM-DD - ``` - -[how to update the changelog]: https://github.com/rust-lang/rust-clippy/blob/master/doc/changelog_update.md diff --git a/doc/roadmap-2021.md b/doc/roadmap-2021.md deleted file mode 100644 index fe8b080f56f..00000000000 --- a/doc/roadmap-2021.md +++ /dev/null @@ -1,235 +0,0 @@ -# Roadmap 2021 - -# Summary - -This Roadmap lays out the plans for Clippy in 2021: - -- Improving usability and reliability -- Improving experience of contributors and maintainers -- Develop and specify processes - -Members of the Clippy team will be assigned tasks from one or more of these -topics. The team member is then responsible to complete the assigned tasks. This -can either be done by implementing them or by providing mentorship to interested -contributors. - -# Motivation - -With the ongoing growth of the Rust language and with that of the whole -ecosystem, also Clippy gets more and more users and contributors. This is good -for the project, but also brings challenges along. Some of these challenges are: - -- More issues about reliability or usability are popping up -- Traffic is hard to handle for a small team -- Bigger projects don't get completed due to the lack of processes and/or time - of the team members - -Additionally, according to the [Rust Roadmap 2021], clear processes should be -defined by every team and unified across teams. This Roadmap is the first step -towards this. - -[Rust Roadmap 2021]: https://github.com/rust-lang/rfcs/pull/3037 - -# Explanation - -This section will explain the things that should be done in 2021. It is -important to note, that this document focuses on the "What?", not the "How?". -The later will be addressed in follow-up tracking issue, with an assigned team -member. - -The following is split up in two major sections. The first section covers the -user facing plans, the second section the internal plans. - -## User Facing - -Clippy should be as pleasant to use and configure as possible. This section -covers plans that should be implemented to improve the situation of Clippy in -this regard. - -### Usability - -In the following, plans to improve the usability are covered. - -#### No Output After `cargo check` - -Currently when `cargo clippy` is run after `cargo check`, it does not produce -any output. This is especially problematic since `rust-analyzer` is on the rise -and it uses `cargo check` for checking code. A fix is already implemented, but -it still has to be pushed over the finish line. This also includes the -stabilization of the `cargo clippy --fix` command or the support of multi-span -suggestions in `rustfix`. - -- [#4612](https://github.com/rust-lang/rust-clippy/issues/4612) - -#### `lints.toml` Configuration - -This is something that comes up every now and then: a reusable configuration -file, where lint levels can be defined. Discussions about this often lead to -nothing specific or to "we need an RFC for this". And this is exactly what needs -to be done. Get together with the cargo team and write an RFC and implement such -a configuration file somehow and somewhere. - -- [#3164](https://github.com/rust-lang/rust-clippy/issues/3164) -- [cargo#5034](https://github.com/rust-lang/cargo/issues/5034) -- [IRLO](https://internals.rust-lang.org/t/proposal-cargo-lint-configuration/9135/8) - -#### Lint Groups - -There are more and more issues about managing lints in Clippy popping up. Lints -are hard to implement with a guarantee of no/few false positives (FPs). One way -to address this might be to introduce more lint groups to give users the ability -to better manage lints, or improve the process of classifying lints, so that -disabling lints due to FPs becomes rare. It is important to note, that Clippy -lints are less conservative than `rustc` lints, which won't change in the -future. - -- [#5537](https://github.com/rust-lang/rust-clippy/issues/5537) -- [#6366](https://github.com/rust-lang/rust-clippy/issues/6366) - -### Reliability - -In the following, plans to improve the reliability are covered. - -#### False Positive Rate - -In the worst case, new lints are only available in nightly for 2 weeks, before -hitting beta and ultimately stable. This and the fact that fewer people use -nightly Rust nowadays makes it more probable that a lint with many FPs hits -stable. This leads to annoyed users, that will disable these new lints in the -best case and to more annoyed users, that will stop using Clippy in the worst. -A process should be developed and implemented to prevent this from happening. - -- [#6429](https://github.com/rust-lang/rust-clippy/issues/6429) - -## Internal - -(The end of) 2020 has shown, that Clippy has to think about the available -resources, especially regarding management and maintenance of the project. This -section address issues affecting team members and contributors. - -### Management - -In 2020 Clippy achieved over 1000 open issues with regularly between 25-35 open -PRs. This is simultaneously a win and a loss. More issues and PRs means more -people are interested in Clippy and in contributing to it. On the other hand, it -means for team members more work and for contributors longer wait times for -reviews. The following will describe plans how to improve the situation for both -team members and contributors. - -#### Clear Expectations for Team Members - -According to the [Rust Roadmap 2021], a document specifying what it means to be -a member of the team should be produced. This should not put more pressure on -the team members, but rather help them and interested folks to know what the -expectations are. With this it should also be easier to recruit new team members -and may encourage people to get in touch, if they're interested to join. - -#### Scaling up the Team - -More people means less work for each individual. Together with the document -about expectations for team members, a document defining the process of how to -join the team should be produced. This can also increase the stability of the -team, in case of current members dropping out (temporarily). There can also be -different roles in the team, like people triaging vs. people reviewing. - -#### Regular Meetings - -Other teams have regular meetings. Clippy is big enough that it might be worth -to also do them. Especially if more people join the team, this can be important -for sync-ups. Besides the asynchronous communication, that works well for -working on separate lints, a meeting adds a synchronous alternative at a known -time. This is especially helpful if there are bigger things that need to be -discussed (like the projects in this roadmap). For starters bi-weekly meetings -before Rust syncs might make sense. - -#### Triaging - -To get a handle on the influx of open issues, a process for triaging issues and -PRs should be developed. Officially, Clippy follows the Rust triage process, but -currently no one enforces it. This can be improved by sharing triage teams -across projects or by implementing dashboards / tools which simplify triaging. - -### Development - -Improving the developer and contributor experience is something the Clippy team -works on regularly. Though, some things might need special attention and -planing. These topics are listed in the following. - -#### Process for New and Existing Lints - -As already mentioned above, classifying new lints gets quite hard, because the -probability of a buggy lint getting into stable is quite high. A process should -be implemented on how to classify lints. In addition, a test system should be -developed to find out which lints are currently problematic in real world code -to fix or disable them. - -- [#6429 (comment)](https://github.com/rust-lang/rust-clippy/issues/6429#issuecomment-741056379) -- [#6429 (comment)](https://github.com/rust-lang/rust-clippy/issues/6429#issuecomment-741153345) - -#### Processes - -Related to the point before, a process for suggesting and discussing major -changes should be implemented. It's also not clearly defined when a lint should -be enabled or disabled by default. This can also be improved by the test system -mentioned above. - -#### Dev-Tools - -There's already `cargo dev` which makes Clippy development easier and more -pleasant. This can still be expanded, so that it covers more areas of the -development process. - -- [#5394](https://github.com/rust-lang/rust-clippy/issues/5394) - -#### Contributor Guide - -Similar to a Clippy Book, which describes how to use Clippy, a book about how to -contribute to Clippy might be helpful for new and existing contributors. There's -already the `doc` directory in the Clippy repo, this can be turned into a -`mdbook`. - -#### `rustc` integration - -Recently Clippy was integrated with `git subtree` into the `rust-lang/rust` -repository. This made syncing between the two repositories easier. A -`#[non_exhaustive]` list of things that still can be improved is: - -1. Use the same `rustfmt` version and configuration as `rustc`. -2. Make `cargo dev` work in the Rust repo, just as it works in the Clippy repo. - E.g. `cargo dev bless` or `cargo dev update_lints`. And even add more things - to it that might be useful for the Rust repo, e.g. `cargo dev deprecate`. -3. Easier sync process. The `subtree` situation is not ideal. - -## Prioritization - -The most pressing issues for users of Clippy are of course the user facing -issues. So there should be a priority on those issues, but without losing track -of the internal issues listed in this document. - -Getting the FP rate of warn/deny-by-default lints under control should have the -highest priority. Other user facing issues should also get a high priority, but -shouldn't be in the way of addressing internal issues. - -To better manage the upcoming projects, the basic internal processes, like -meetings, tracking issues and documentation, should be established as soon as -possible. They might even be necessary to properly manage the projects, -regarding the user facing issues. - -# Prior Art - -## Rust Roadmap - -Rust's roadmap process was established by [RFC 1728] in 2016. Since then every -year a roadmap was published, that defined the bigger plans for the coming -years. This years roadmap can be found [here][Rust Roadmap 2021]. - -[RFC 1728]: https://rust-lang.github.io/rfcs/1728-north-star.html - -# Drawbacks - -## Big Roadmap - -This roadmap is pretty big and not all items listed in this document might be -addressed during 2021. Because this is the first roadmap for Clippy, having open -tasks at the end of 2021 is fine, but they should be revisited in the 2022 -roadmap. -- cgit 1.4.1-3-g733a5 From d6b013ff9e5bbacfb6140f194b1700c2602f0bab Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 21 Jan 2022 17:27:57 +0100 Subject: Reformat internal docs This reformats all the internal docs, so that the md files use at most 80 characters per line. This is the usual formatting of md files. We allow 120 chars per line in CI though. --- book/src/development/adding_lints.md | 323 +++++++++++---------- book/src/development/basics.md | 72 +++-- book/src/development/common_tools_writing_lints.md | 131 +++++---- book/src/infrastructure/book.md | 36 ++- book/src/infrastructure/changelog_update.md | 39 +-- book/src/infrastructure/release.md | 26 +- 6 files changed, 340 insertions(+), 287 deletions(-) (limited to 'book/src/development/adding_lints.md') diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md index 3e0b1c5c4f7..7ffada8aef1 100644 --- a/book/src/development/adding_lints.md +++ b/book/src/development/adding_lints.md @@ -45,9 +45,9 @@ take a look at our [lint naming guidelines][lint_naming]. To get started on this lint you can run `cargo dev new_lint --name=foo_functions --pass=early --category=pedantic` (category will default to nursery if not provided). This command will create two files: `tests/ui/foo_functions.rs` and -`clippy_lints/src/foo_functions.rs`, as well as -[registering the lint](#lint-registration). For cargo lints, two project -hierarchies (fail/pass) will be created by default under `tests/ui-cargo`. +`clippy_lints/src/foo_functions.rs`, as well as [registering the +lint](#lint-registration). For cargo lints, two project hierarchies (fail/pass) +will be created by default under `tests/ui-cargo`. Next, we'll open up these files and add our lint! @@ -58,8 +58,8 @@ Let's write some tests first that we can execute while we iterate on our lint. Clippy uses UI tests for testing. UI tests check that the output of Clippy is exactly as expected. Each test is just a plain Rust file that contains the code we want to check. The output of Clippy is compared against a `.stderr` file. -Note that you don't have to create this file yourself, we'll get to -generating the `.stderr` files further down. +Note that you don't have to create this file yourself, we'll get to generating +the `.stderr` files further down. We start by opening the test file created at `tests/ui/foo_functions.rs`. @@ -96,52 +96,54 @@ fn main() { } ``` -Now we can run the test with `TESTNAME=foo_functions cargo uitest`, -currently this test is meaningless though. +Now we can run the test with `TESTNAME=foo_functions cargo uitest`, currently +this test is meaningless though. -While we are working on implementing our lint, we can keep running the UI -test. That allows us to check if the output is turning into what we want. +While we are working on implementing our lint, we can keep running the UI test. +That allows us to check if the output is turning into what we want. -Once we are satisfied with the output, we need to run -`cargo dev bless` to update the `.stderr` file for our lint. -Please note that, we should run `TESTNAME=foo_functions cargo uitest` -every time before running `cargo dev bless`. -Running `TESTNAME=foo_functions cargo uitest` should pass then. When we commit -our lint, we need to commit the generated `.stderr` files, too. In general, you -should only commit files changed by `cargo dev bless` for the +Once we are satisfied with the output, we need to run `cargo dev bless` to +update the `.stderr` file for our lint. Please note that, we should run +`TESTNAME=foo_functions cargo uitest` every time before running `cargo dev +bless`. Running `TESTNAME=foo_functions cargo uitest` should pass then. When we +commit our lint, we need to commit the generated `.stderr` files, too. In +general, you should only commit files changed by `cargo dev bless` for the specific lint you are creating/editing. Note that if the generated files are empty, they should be removed. -Note that you can run multiple test files by specifying a comma separated list: -`TESTNAME=foo_functions,test2,test3`. +> _Note:_ you can run multiple test files by specifying a comma separated list: +> `TESTNAME=foo_functions,test2,test3`. ### Cargo lints -For cargo lints, the process of testing differs in that we are interested in -the `Cargo.toml` manifest file. We also need a minimal crate associated -with that manifest. +For cargo lints, the process of testing differs in that we are interested in the +`Cargo.toml` manifest file. We also need a minimal crate associated with that +manifest. -If our new lint is named e.g. `foo_categories`, after running `cargo dev new_lint` -we will find by default two new crates, each with its manifest file: +If our new lint is named e.g. `foo_categories`, after running `cargo dev +new_lint` we will find by default two new crates, each with its manifest file: -* `tests/ui-cargo/foo_categories/fail/Cargo.toml`: this file should cause the new lint to raise an error. -* `tests/ui-cargo/foo_categories/pass/Cargo.toml`: this file should not trigger the lint. +* `tests/ui-cargo/foo_categories/fail/Cargo.toml`: this file should cause the + new lint to raise an error. +* `tests/ui-cargo/foo_categories/pass/Cargo.toml`: this file should not trigger + the lint. -If you need more cases, you can copy one of those crates (under `foo_categories`) and rename it. +If you need more cases, you can copy one of those crates (under +`foo_categories`) and rename it. -The process of generating the `.stderr` file is the same, and prepending the `TESTNAME` -variable to `cargo uitest` works too. +The process of generating the `.stderr` file is the same, and prepending the +`TESTNAME` variable to `cargo uitest` works too. ## Rustfix tests -If the lint you are working on is making use of structured suggestions, the -test file should include a `// run-rustfix` comment at the top. This will +If the lint you are working on is making use of structured suggestions, the test +file should include a `// run-rustfix` comment at the top. This will additionally run [rustfix] for that test. Rustfix will apply the suggestions -from the lint to the code of the test file and compare that to the contents of -a `.fixed` file. +from the lint to the code of the test file and compare that to the contents of a +`.fixed` file. -Use `cargo dev bless` to automatically generate the -`.fixed` file after running the tests. +Use `cargo dev bless` to automatically generate the `.fixed` file after running +the tests. [rustfix]: https://github.com/rust-lang/rustfix @@ -149,7 +151,8 @@ Use `cargo dev bless` to automatically generate the Some features require the 2018 edition to work (e.g. `async_await`), but compile-test tests run on the 2015 edition by default. To change this behavior -add `// edition:2018` at the top of the test file (note that it's space-sensitive). +add `// edition:2018` at the top of the test file (note that it's +space-sensitive). ## Testing manually @@ -166,9 +169,9 @@ implementing our lint now. ## Lint declaration -Let's start by opening the new file created in the `clippy_lints` crate -at `clippy_lints/src/foo_functions.rs`. That's the crate where all the -lint code is. This file has already imported some initial things we will need: +Let's start by opening the new file created in the `clippy_lints` crate at +`clippy_lints/src/foo_functions.rs`. That's the crate where all the lint code +is. This file has already imported some initial things we will need: ```rust use rustc_lint::{EarlyLintPass, EarlyContext}; @@ -178,7 +181,8 @@ use rustc_ast::ast::*; The next step is to update the lint declaration. Lints are declared using the [`declare_clippy_lint!`][declare_clippy_lint] macro, and we just need to update -the auto-generated lint declaration to have a real description, something like this: +the auto-generated lint declaration to have a real description, something like +this: ```rust declare_clippy_lint! { @@ -198,24 +202,25 @@ declare_clippy_lint! { ``` * The section of lines prefixed with `///` constitutes the lint documentation - section. This is the default documentation style and will be displayed - [like this][example_lint_page]. To render and open this documentation locally - in a browser, run `cargo dev serve`. -* The `#[clippy::version]` attribute will be rendered as part of the lint documentation. - The value should be set to the current Rust version that the lint is developed in, - it can be retrieved by running `rustc -vV` in the rust-clippy directory. The version - is listed under *release*. (Use the version without the `-nightly`) suffix. -* `FOO_FUNCTIONS` is the name of our lint. Be sure to follow the - [lint naming guidelines][lint_naming] here when naming your lint. - In short, the name should state the thing that is being checked for and - read well when used with `allow`/`warn`/`deny`. -* `pedantic` sets the lint level to `Allow`. - The exact mapping can be found [here][category_level_mapping] + section. This is the default documentation style and will be displayed [like + this][example_lint_page]. To render and open this documentation locally in a + browser, run `cargo dev serve`. +* The `#[clippy::version]` attribute will be rendered as part of the lint + documentation. The value should be set to the current Rust version that the + lint is developed in, it can be retrieved by running `rustc -vV` in the + rust-clippy directory. The version is listed under *release*. (Use the version + without the `-nightly`) suffix. +* `FOO_FUNCTIONS` is the name of our lint. Be sure to follow the [lint naming + guidelines][lint_naming] here when naming your lint. In short, the name should + state the thing that is being checked for and read well when used with + `allow`/`warn`/`deny`. +* `pedantic` sets the lint level to `Allow`. The exact mapping can be found + [here][category_level_mapping] * The last part should be a text that explains what exactly is wrong with the code -The rest of this file contains an empty implementation for our lint pass, -which in this case is `EarlyLintPass` and should look like this: +The rest of this file contains an empty implementation for our lint pass, which +in this case is `EarlyLintPass` and should look like this: ```rust // clippy_lints/src/foo_functions.rs @@ -324,9 +329,9 @@ impl EarlyLintPass for FooFunctions { Running our UI test should now produce output that contains the lint message. According to [the rustc-dev-guide], the text should be matter of fact and avoid -capitalization and periods, unless multiple sentences are needed. -When code or an identifier must appear in a message or label, it should be -surrounded with single grave accents \`. +capitalization and periods, unless multiple sentences are needed. When code or +an identifier must appear in a message or label, it should be surrounded with +single grave accents \`. [check_fn]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.EarlyLintPass.html#method.check_fn [diagnostics]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_utils/src/diagnostics.rs @@ -382,8 +387,8 @@ fn is_foo_fn(fn_kind: FnKind<'_>) -> bool { ``` Now we should also run the full test suite with `cargo test`. At this point -running `cargo test` should produce the expected output. Remember to run -`cargo dev bless` to update the `.stderr` file. +running `cargo test` should produce the expected output. Remember to run `cargo +dev bless` to update the `.stderr` file. `cargo test` (as opposed to `cargo uitest`) will also ensure that our lint implementation is not violating any Clippy lints itself. @@ -397,13 +402,16 @@ pass. ## Specifying the lint's minimum supported Rust version (MSRV) -Sometimes a lint makes suggestions that require a certain version of Rust. For example, the `manual_strip` lint suggests -using `str::strip_prefix` and `str::strip_suffix` which is only available after Rust 1.45. In such cases, you need to -ensure that the MSRV configured for the project is >= the MSRV of the required Rust feature. If multiple features are -required, just use the one with a lower MSRV. +Sometimes a lint makes suggestions that require a certain version of Rust. For +example, the `manual_strip` lint suggests using `str::strip_prefix` and +`str::strip_suffix` which is only available after Rust 1.45. In such cases, you +need to ensure that the MSRV configured for the project is >= the MSRV of the +required Rust feature. If multiple features are required, just use the one with +a lower MSRV. -First, add an MSRV alias for the required feature in [`clippy_utils::msrvs`](/clippy_utils/src/msrvs.rs). This can be -accessed later as `msrvs::STR_STRIP_PREFIX`, for example. +First, add an MSRV alias for the required feature in +[`clippy_utils::msrvs`](/clippy_utils/src/msrvs.rs). This can be accessed later +as `msrvs::STR_STRIP_PREFIX`, for example. ```rust msrv_aliases! { @@ -412,8 +420,9 @@ msrv_aliases! { } ``` -In order to access the project-configured MSRV, you need to have an `msrv` field in the LintPass struct, and a -constructor to initialize the field. The `msrv` value is passed to the constructor in `clippy_lints/lib.rs`. +In order to access the project-configured MSRV, you need to have an `msrv` field +in the LintPass struct, and a constructor to initialize the field. The `msrv` +value is passed to the constructor in `clippy_lints/lib.rs`. ```rust pub struct ManualStrip { @@ -472,11 +481,10 @@ If you have trouble implementing your lint, there is also the internal `author` lint to generate Clippy code that detects the offending pattern. It does not work for all of the Rust syntax, but can give a good starting point. -The quickest way to use it, is the -[Rust playground: play.rust-lang.org][author_example]. -Put the code you want to lint into the editor and add the `#[clippy::author]` -attribute above the item. Then run Clippy via `Tools -> Clippy` and you should -see the generated code in the output below. +The quickest way to use it, is the [Rust playground: +play.rust-lang.org][author_example]. Put the code you want to lint into the +editor and add the `#[clippy::author]` attribute above the item. Then run Clippy +via `Tools -> Clippy` and you should see the generated code in the output below. [Here][author_example] is an example on the playground. @@ -487,13 +495,15 @@ you are implementing your lint. ## Print HIR lint -To implement a lint, it's helpful to first understand the internal representation -that rustc uses. Clippy has the `#[clippy::dump]` attribute that prints the -[_High-Level Intermediate Representation (HIR)_] of the item, statement, or -expression that the attribute is attached to. To attach the attribute to expressions -you often need to enable `#![feature(stmt_expr_attributes)]`. +To implement a lint, it's helpful to first understand the internal +representation that rustc uses. Clippy has the `#[clippy::dump]` attribute that +prints the [_High-Level Intermediate Representation (HIR)_] of the item, +statement, or expression that the attribute is attached to. To attach the +attribute to expressions you often need to enable +`#![feature(stmt_expr_attributes)]`. -[Here][print_hir_example] you can find an example, just select _Tools_ and run _Clippy_. +[Here][print_hir_example] you can find an example, just select _Tools_ and run +_Clippy_. [_High-Level Intermediate Representation (HIR)_]: https://rustc-dev-guide.rust-lang.org/hir.html [print_hir_example]: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=daf14db3a7f39ca467cd1b86c34b9afb @@ -518,7 +528,7 @@ declare_clippy_lint! { /// ```rust,ignore /// // A short example of code that triggers the lint /// ``` - /// + /// /// Use instead: /// ```rust,ignore /// // A short example of improved code that doesn't trigger the lint @@ -537,9 +547,9 @@ list][lint_list]. ## Running rustfmt -[Rustfmt] is a tool for formatting Rust code according to style guidelines. -Your code has to be formatted by `rustfmt` before a PR can be merged. -Clippy uses nightly `rustfmt` in the CI. +[Rustfmt] is a tool for formatting Rust code according to style guidelines. Your +code has to be formatted by `rustfmt` before a PR can be merged. Clippy uses +nightly `rustfmt` in the CI. It can be installed via `rustup`: @@ -575,94 +585,105 @@ Before submitting your PR make sure you followed all of the basic requirements: ## Adding configuration to a lint -Clippy supports the configuration of lints values using a `clippy.toml` file in the workspace -directory. Adding a configuration to a lint can be useful for thresholds or to constrain some -behavior that can be seen as a false positive for some users. Adding a configuration is done -in the following steps: +Clippy supports the configuration of lints values using a `clippy.toml` file in +the workspace directory. Adding a configuration to a lint can be useful for +thresholds or to constrain some behavior that can be seen as a false positive +for some users. Adding a configuration is done in the following steps: -1. Adding a new configuration entry to [clippy_lints::utils::conf](/clippy_lints/src/utils/conf.rs) - like this: - ```rust - /// Lint: LINT_NAME. - /// - /// - (configuration_ident: Type = DefaultValue), - ``` - The doc comment is automatically added to the documentation of the listed lints. The default - value will be formatted using the `Debug` implementation of the type. -2. Adding the configuration value to the lint impl struct: - 1. This first requires the definition of a lint impl struct. Lint impl structs are usually - generated with the `declare_lint_pass!` macro. This struct needs to be defined manually - to add some kind of metadata to it: - ```rust - // Generated struct definition - declare_lint_pass!(StructName => [ - LINT_NAME - ]); - - // New manual definition struct - #[derive(Copy, Clone)] - pub struct StructName {} - - impl_lint_pass!(StructName => [ - LINT_NAME - ]); - ``` - - 2. Next add the configuration value and a corresponding creation method like this: - ```rust - #[derive(Copy, Clone)] - pub struct StructName { - configuration_ident: Type, - } +1. Adding a new configuration entry to + [clippy_lints::utils::conf](/clippy_lints/src/utils/conf.rs) like this: - // ... + ```rust + /// Lint: LINT_NAME. + /// + /// + (configuration_ident: Type = DefaultValue), + ``` - impl StructName { - pub fn new(configuration_ident: Type) -> Self { - Self { - configuration_ident, - } - } - } - ``` + The doc comment is automatically added to the documentation of the listed + lints. The default value will be formatted using the `Debug` implementation + of the type. +2. Adding the configuration value to the lint impl struct: + 1. This first requires the definition of a lint impl struct. Lint impl + structs are usually generated with the `declare_lint_pass!` macro. This + struct needs to be defined manually to add some kind of metadata to it: + ```rust + // Generated struct definition + declare_lint_pass!(StructName => [ + LINT_NAME + ]); + + // New manual definition struct + #[derive(Copy, Clone)] + pub struct StructName {} + + impl_lint_pass!(StructName => [ + LINT_NAME + ]); + ``` + + 2. Next add the configuration value and a corresponding creation method like + this: + ```rust + #[derive(Copy, Clone)] + pub struct StructName { + configuration_ident: Type, + } + + // ... + + impl StructName { + pub fn new(configuration_ident: Type) -> Self { + Self { + configuration_ident, + } + } + } + ``` 3. Passing the configuration value to the lint impl struct: - First find the struct construction in the [clippy_lints lib file](/clippy_lints/src/lib.rs). - The configuration value is now cloned or copied into a local value that is then passed to the - impl struct like this: - ```rust - // Default generated registration: - store.register_*_pass(|| box module::StructName); + First find the struct construction in the [clippy_lints lib + file](/clippy_lints/src/lib.rs). The configuration value is now cloned or + copied into a local value that is then passed to the impl struct like this: + + ```rust + // Default generated registration: + store.register_*_pass(|| box module::StructName); - // New registration with configuration value - let configuration_ident = conf.configuration_ident.clone(); - store.register_*_pass(move || box module::StructName::new(configuration_ident)); - ``` + // New registration with configuration value + let configuration_ident = conf.configuration_ident.clone(); + store.register_*_pass(move || box module::StructName::new(configuration_ident)); + ``` - Congratulations the work is almost done. The configuration value can now be accessed - in the linting code via `self.configuration_ident`. + Congratulations the work is almost done. The configuration value can now be + accessed in the linting code via `self.configuration_ident`. 4. Adding tests: - 1. The default configured value can be tested like any normal lint in [`tests/ui`](/tests/ui). - 2. The configuration itself will be tested separately in [`tests/ui-toml`](/tests/ui-toml). - Simply add a new subfolder with a fitting name. This folder contains a `clippy.toml` file - with the configuration value and a rust file that should be linted by Clippy. The test can - otherwise be written as usual. + 1. The default configured value can be tested like any normal lint in + [`tests/ui`](/tests/ui). + 2. The configuration itself will be tested separately in + [`tests/ui-toml`](/tests/ui-toml). Simply add a new subfolder with a + fitting name. This folder contains a `clippy.toml` file with the + configuration value and a rust file that should be linted by Clippy. The + test can otherwise be written as usual. ## Cheat Sheet Here are some pointers to things you are likely going to need for every lint: * [Clippy utils][utils] - Various helper functions. Maybe the function you need - is already in here ([`is_type_diagnostic_item`], [`implements_trait`], [`snippet`], etc) + is already in here ([`is_type_diagnostic_item`], [`implements_trait`], + [`snippet`], etc) * [Clippy diagnostics][diagnostics] * [Let chains][let-chains] -* [`from_expansion`][from_expansion] and [`in_external_macro`][in_external_macro] +* [`from_expansion`][from_expansion] and + [`in_external_macro`][in_external_macro] * [`Span`][span] * [`Applicability`][applicability] -* [Common tools for writing lints](common_tools_writing_lints.md) helps with common operations -* [The rustc-dev-guide][rustc-dev-guide] explains a lot of internal compiler concepts +* [Common tools for writing lints](common_tools_writing_lints.md) helps with + common operations +* [The rustc-dev-guide][rustc-dev-guide] explains a lot of internal compiler + concepts * [The nightly rustc docs][nightly_docs] which has been linked to throughout this guide diff --git a/book/src/development/basics.md b/book/src/development/basics.md index 57a90a924ec..78c429ea013 100644 --- a/book/src/development/basics.md +++ b/book/src/development/basics.md @@ -1,8 +1,8 @@ # Basics for hacking on Clippy This document explains the basics for hacking on Clippy. Besides others, this -includes how to build and test Clippy. For a more in depth description on -the codebase take a look at [Adding Lints] or [Common Tools]. +includes how to build and test Clippy. For a more in depth description on the +codebase take a look at [Adding Lints] or [Common Tools]. [Adding Lints]: https://github.com/rust-lang/rust-clippy/blob/master/doc/adding_lints.md [Common Tools]: https://github.com/rust-lang/rust-clippy/blob/master/doc/common_tools_writing_lints.md @@ -62,8 +62,8 @@ TESTNAME="test_" cargo uitest cargo test --test dogfood ``` -If the output of a [UI test] differs from the expected output, you can update the -reference file with: +If the output of a [UI test] differs from the expected output, you can update +the reference file with: ```bash cargo dev bless @@ -72,8 +72,8 @@ cargo dev bless For example, this is necessary, if you fix a typo in an error message of a lint or if you modify a test file to add a test case. -_Note:_ This command may update more files than you intended. In that case only -commit the files you wanted to update. +> _Note:_ This command may update more files than you intended. In that case +> only commit the files you wanted to update. [UI test]: https://rustc-dev-guide.rust-lang.org/tests/adding.html#guide-to-the-ui-tests @@ -96,22 +96,26 @@ cargo dev setup git-hook # (experimental) Setup Clippy to work with IntelliJ-Rust cargo dev setup intellij ``` -More about intellij command usage and reasons [here](../CONTRIBUTING.md#intellij-rust) + +More about intellij command usage and reasons +[here](../CONTRIBUTING.md#intellij-rust) ## lintcheck -`cargo lintcheck` will build and run clippy on a fixed set of crates and generate a log of the results. -You can `git diff` the updated log against its previous version and -see what impact your lint made on a small set of crates. -If you add a new lint, please audit the resulting warnings and make sure -there are no false positives and that the suggestions are valid. + +`cargo lintcheck` will build and run clippy on a fixed set of crates and +generate a log of the results. You can `git diff` the updated log against its +previous version and see what impact your lint made on a small set of crates. +If you add a new lint, please audit the resulting warnings and make sure there +are no false positives and that the suggestions are valid. Refer to the tools [README] for more details. [README]: https://github.com/rust-lang/rust-clippy/blob/master/lintcheck/README.md + ## PR -We follow a rustc no merge-commit policy. -See . +We follow a rustc no merge-commit policy. See +. ## Common Abbreviations @@ -126,27 +130,34 @@ See . | HIR | High-Level Intermediate Representation | | TCX | Type context | -This is a concise list of abbreviations that can come up during Clippy development. An extensive -general list can be found in the [rustc-dev-guide glossary][glossary]. Always feel free to ask if -an abbreviation or meaning is unclear to you. +This is a concise list of abbreviations that can come up during Clippy +development. An extensive general list can be found in the [rustc-dev-guide +glossary][glossary]. Always feel free to ask if an abbreviation or meaning is +unclear to you. ## Install from source -If you are hacking on Clippy and want to install it from source, do the following: +If you are hacking on Clippy and want to install it from source, do the +following: -First, take note of the toolchain [override](https://rust-lang.github.io/rustup/overrides.html) in `/rust-toolchain`. -We will use this override to install Clippy into the right toolchain. +First, take note of the toolchain +[override](https://rust-lang.github.io/rustup/overrides.html) in +`/rust-toolchain`. We will use this override to install Clippy into the right +toolchain. -> Tip: You can view the active toolchain for the current directory with `rustup show active-toolchain`. +> Tip: You can view the active toolchain for the current directory with `rustup +> show active-toolchain`. -From the Clippy project root, run the following command to build the Clippy binaries and copy them into the -toolchain directory. This will override the currently installed Clippy component. +From the Clippy project root, run the following command to build the Clippy +binaries and copy them into the toolchain directory. This will override the +currently installed Clippy component. ```terminal cargo build --release --bin cargo-clippy --bin clippy-driver -Zunstable-options --out-dir "$(rustc --print=sysroot)/bin" ``` -Now you may run `cargo clippy` in any project, using the toolchain where you just installed Clippy. +Now you may run `cargo clippy` in any project, using the toolchain where you +just installed Clippy. ```terminal cd my-project @@ -159,16 +170,19 @@ cargo +nightly-2021-07-01 clippy clippy-driver +nightly-2021-07-01 ``` -If you need to restore the default Clippy installation, run the following (from the Clippy project root). +If you need to restore the default Clippy installation, run the following (from +the Clippy project root). ```terminal rustup component remove clippy rustup component add clippy ``` -> **DO NOT** install using `cargo install --path . --force` since this will overwrite rustup -> [proxies](https://rust-lang.github.io/rustup/concepts/proxies.html). That is, `~/.cargo/bin/cargo-clippy` and -> `~/.cargo/bin/clippy-driver` should be hard or soft links to `~/.cargo/bin/rustup`. You can repair these by running -> `rustup update`. +> **DO NOT** install using `cargo install --path . --force` since this will +> overwrite rustup +> [proxies](https://rust-lang.github.io/rustup/concepts/proxies.html). That is, +> `~/.cargo/bin/cargo-clippy` and `~/.cargo/bin/clippy-driver` should be hard or +> soft links to `~/.cargo/bin/rustup`. You can repair these by running `rustup +> update`. [glossary]: https://rustc-dev-guide.rust-lang.org/appendix/glossary.html diff --git a/book/src/development/common_tools_writing_lints.md b/book/src/development/common_tools_writing_lints.md index 1d1aee0da2c..e1ed89262f6 100644 --- a/book/src/development/common_tools_writing_lints.md +++ b/book/src/development/common_tools_writing_lints.md @@ -18,15 +18,17 @@ Useful Rustc dev guide links: ## Retrieving the type of an expression -Sometimes you may want to retrieve the type `Ty` of an expression `Expr`, for example to answer following questions: +Sometimes you may want to retrieve the type `Ty` of an expression `Expr`, for +example to answer following questions: - which type does this expression correspond to (using its [`TyKind`][TyKind])? - is it a sized type? - is it a primitive type? - does it implement a trait? -This operation is performed using the [`expr_ty()`][expr_ty] method from the [`TypeckResults`][TypeckResults] struct, -that gives you access to the underlying structure [`Ty`][Ty]. +This operation is performed using the [`expr_ty()`][expr_ty] method from the +[`TypeckResults`][TypeckResults] struct, that gives you access to the underlying +structure [`Ty`][Ty]. Example of use: ```rust @@ -43,8 +45,8 @@ impl LateLintPass<'_> for MyStructLint { } ``` -Similarly in [`TypeckResults`][TypeckResults] methods, you have the [`pat_ty()`][pat_ty] method -to retrieve a type from a pattern. +Similarly in [`TypeckResults`][TypeckResults] methods, you have the +[`pat_ty()`][pat_ty] method to retrieve a type from a pattern. Two noticeable items here: - `cx` is the lint context [`LateContext`][LateContext]. The two most useful @@ -52,12 +54,13 @@ Two noticeable items here: `LateContext::typeck_results`, allowing us to jump to type definitions and other compilation stages such as HIR. - `typeck_results`'s return value is [`TypeckResults`][TypeckResults] and is - created by type checking step, it includes useful information such as types - of expressions, ways to resolve methods and so on. + created by type checking step, it includes useful information such as types of + expressions, ways to resolve methods and so on. ## Checking if an expr is calling a specific method -Starting with an `expr`, you can check whether it is calling a specific method `some_method`: +Starting with an `expr`, you can check whether it is calling a specific method +`some_method`: ```rust impl<'tcx> LateLintPass<'tcx> for MyStructLint { @@ -77,8 +80,9 @@ impl<'tcx> LateLintPass<'tcx> for MyStructLint { ## Checking for a specific type -There are three ways to check if an expression type is a specific type we want to check for. -All of these methods only check for the base type, generic arguments have to be checked separately. +There are three ways to check if an expression type is a specific type we want +to check for. All of these methods only check for the base type, generic +arguments have to be checked separately. ```rust use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item}; @@ -115,7 +119,8 @@ Prefer using diagnostic items and lang items where possible. ## Checking if a type implements a specific trait -There are three ways to do this, depending on if the target trait has a diagnostic item, lang item or neither. +There are three ways to do this, depending on if the target trait has a +diagnostic item, lang item or neither. ```rust use clippy_utils::{implements_trait, is_trait_method, match_trait_method, paths}; @@ -151,8 +156,9 @@ impl LateLintPass<'_> for MyStructLint { > Prefer using diagnostic and lang items, if the target trait has one. -We access lang items through the type context `tcx`. `tcx` is of type [`TyCtxt`][TyCtxt] and is defined in the `rustc_middle` crate. -A list of defined paths for Clippy can be found in [paths.rs][paths] +We access lang items through the type context `tcx`. `tcx` is of type +[`TyCtxt`][TyCtxt] and is defined in the `rustc_middle` crate. A list of defined +paths for Clippy can be found in [paths.rs][paths] ## Checking if a type defines a specific method @@ -182,14 +188,15 @@ impl<'tcx> LateLintPass<'tcx> for MyTypeImpl { ## Dealing with macros and expansions Keep in mind that macros are already expanded and desugaring is already applied -to the code representation that you are working with in Clippy. This unfortunately causes a lot of -false positives because macro expansions are "invisible" unless you actively check for them. -Generally speaking, code with macro expansions should just be ignored by Clippy because that code can be -dynamic in ways that are difficult or impossible to see. -Use the following functions to deal with macros: +to the code representation that you are working with in Clippy. This +unfortunately causes a lot of false positives because macro expansions are +"invisible" unless you actively check for them. Generally speaking, code with +macro expansions should just be ignored by Clippy because that code can be +dynamic in ways that are difficult or impossible to see. Use the following +functions to deal with macros: -- `span.from_expansion()`: detects if a span is from macro expansion or desugaring. - Checking this is a common first step in a lint. +- `span.from_expansion()`: detects if a span is from macro expansion or + desugaring. Checking this is a common first step in a lint. ```rust if expr.span.from_expansion() { @@ -198,45 +205,51 @@ Use the following functions to deal with macros: } ``` -- `span.ctxt()`: the span's context represents whether it is from expansion, and if so, which macro call expanded it. - It is sometimes useful to check if the context of two spans are equal. - - ```rust - // expands to `1 + 0`, but don't lint - 1 + mac!() - ``` - ```rust - if left.span.ctxt() != right.span.ctxt() { - // the coder most likely cannot modify this expression - return; - } - ``` - Note: Code that is not from expansion is in the "root" context. So any spans where `from_expansion` returns `true` can - be assumed to have the same context. And so just using `span.from_expansion()` is often good enough. - - -- `in_external_macro(span)`: detect if the given span is from a macro defined in a foreign crate. - If you want the lint to work with macro-generated code, this is the next line of defense to avoid macros - not defined in the current crate. It doesn't make sense to lint code that the coder can't change. - - You may want to use it for example to not start linting in macros from other crates - - ```rust - #[macro_use] - extern crate a_crate_with_macros; - - // `foo` is defined in `a_crate_with_macros` - foo!("bar"); - - // if we lint the `match` of `foo` call and test its span - assert_eq!(in_external_macro(cx.sess(), match_span), true); - ``` - -- `span.ctxt()`: the span's context represents whether it is from expansion, and if so, what expanded it - -One thing `SpanContext` is useful for is to check if two spans are in the same context. For example, -in `a == b`, `a` and `b` have the same context. In a `macro_rules!` with `a == $b`, `$b` is expanded to some -expression with a different context from `a`. +- `span.ctxt()`: the span's context represents whether it is from expansion, and + if so, which macro call expanded it. It is sometimes useful to check if the + context of two spans are equal. + + ```rust + // expands to `1 + 0`, but don't lint + 1 + mac!() + ``` + ```rust + if left.span.ctxt() != right.span.ctxt() { + // the coder most likely cannot modify this expression + return; + } + ``` + > Note: Code that is not from expansion is in the "root" context. So any spans + > where `from_expansion` returns `true` can be assumed to have the same + > context. And so just using `span.from_expansion()` is often good enough. + + +- `in_external_macro(span)`: detect if the given span is from a macro defined in + a foreign crate. If you want the lint to work with macro-generated code, this + is the next line of defense to avoid macros not defined in the current crate. + It doesn't make sense to lint code that the coder can't change. + + You may want to use it for example to not start linting in macros from other + crates + + ```rust + #[macro_use] + extern crate a_crate_with_macros; + + // `foo` is defined in `a_crate_with_macros` + foo!("bar"); + + // if we lint the `match` of `foo` call and test its span + assert_eq!(in_external_macro(cx.sess(), match_span), true); + ``` + +- `span.ctxt()`: the span's context represents whether it is from expansion, and + if so, what expanded it + + One thing `SpanContext` is useful for is to check if two spans are in the same + context. For example, in `a == b`, `a` and `b` have the same context. In a + `macro_rules!` with `a == $b`, `$b` is expanded to some expression with a + different context from `a`. ```rust macro_rules! m { diff --git a/book/src/infrastructure/book.md b/book/src/infrastructure/book.md index 056d54b6792..b62314c6735 100644 --- a/book/src/infrastructure/book.md +++ b/book/src/infrastructure/book.md @@ -1,38 +1,42 @@ # The Clippy Book -This document explains how to make additions and changes to the Clippy book, the guide to Clippy that you're reading -right now. The Clippy book is formatted with [Markdown](https://www.markdownguide.org) and generated -by [mdbook](https://github.com/rust-lang/mdBook). +This document explains how to make additions and changes to the Clippy book, the +guide to Clippy that you're reading right now. The Clippy book is formatted with +[Markdown](https://www.markdownguide.org) and generated by +[mdbook](https://github.com/rust-lang/mdBook). - [Get mdbook](#get-mdbook) - [Make changes](#make-changes) ## Get mdbook -While not strictly necessary since the book source is simply Markdown text files, having mdbook locally will allow you -to build, test and serve the book locally to view changes before you commit them to the repository. You likely already -have -`cargo` installed, so the easiest option is to simply: +While not strictly necessary since the book source is simply Markdown text +files, having mdbook locally will allow you to build, test and serve the book +locally to view changes before you commit them to the repository. You likely +already have `cargo` installed, so the easiest option is to simply: ```shell cargo install mdbook ``` -See the mdbook [installation](https://github.com/rust-lang/mdBook#installation) instructions for other options. +See the mdbook [installation](https://github.com/rust-lang/mdBook#installation) +instructions for other options. ## Make changes -The book's [src](https://github.com/joshrotenberg/rust-clippy/tree/clippy_guide/book/src) directory contains all of the -markdown files used to generate the book. If you want to see your changes in real time, you can use the mdbook `serve` -command to run a web server locally that will automatically update changes as they are made. From the top level of -your `rust-clippy` -directory: +The book's +[src](https://github.com/joshrotenberg/rust-clippy/tree/clippy_guide/book/src) +directory contains all of the markdown files used to generate the book. If you +want to see your changes in real time, you can use the mdbook `serve` command to +run a web server locally that will automatically update changes as they are +made. From the top level of your `rust-clippy` directory: ```shell mdbook serve book --open ``` -Then navigate to `http://localhost:3000` to see the generated book. While the server is running, changes you make will -automatically be updated. +Then navigate to `http://localhost:3000` to see the generated book. While the +server is running, changes you make will automatically be updated. -For more information, see the mdbook [guide](https://rust-lang.github.io/mdBook/). +For more information, see the mdbook +[guide](https://rust-lang.github.io/mdBook/). diff --git a/book/src/infrastructure/changelog_update.md b/book/src/infrastructure/changelog_update.md index 0cbad2c0924..e560f4c6a3e 100644 --- a/book/src/infrastructure/changelog_update.md +++ b/book/src/infrastructure/changelog_update.md @@ -1,6 +1,6 @@ # Changelog Update -If you want to help with updating the [changelog][changelog], you're in the right place. +If you want to help with updating the [changelog], you're in the right place. ## When to update @@ -11,8 +11,8 @@ Rust release. For that purpose, the changelog is ideally updated during the week before an upcoming stable release. You can find the release dates on the [Rust Forge][forge]. -Most of the time we only need to update the changelog for minor Rust releases. It's -been very rare that Clippy changes were included in a patch release. +Most of the time we only need to update the changelog for minor Rust releases. +It's been very rare that Clippy changes were included in a patch release. ## Changelog update walkthrough @@ -24,10 +24,12 @@ be found in the `tools` directory of the Rust repository. Depending on the current time and what exactly you want to update, the following bullet points might be helpful: -* When writing the release notes for the **upcoming stable release** you need to check - out the Clippy commit of the current Rust `beta` branch. [Link][rust_beta_tools] -* When writing the release notes for the **upcoming beta release**, you need to check - out the Clippy commit of the current Rust `master`. [Link][rust_master_tools] +* When writing the release notes for the **upcoming stable release** you need to + check out the Clippy commit of the current Rust `beta` branch. + [Link][rust_beta_tools] +* When writing the release notes for the **upcoming beta release**, you need to + check out the Clippy commit of the current Rust `master`. + [Link][rust_master_tools] * When writing the (forgotten) release notes for a **past stable release**, you need to check out the Rust release tag of the stable release. [Link][rust_stable_tools] @@ -35,7 +37,8 @@ bullet points might be helpful: Usually you want to write the changelog of the **upcoming stable release**. Make sure though, that `beta` was already branched in the Rust repository. -To find the commit hash, issue the following command when in a `rust-lang/rust` checkout: +To find the commit hash, issue the following command when in a `rust-lang/rust` +checkout: ``` git log --oneline -- src/tools/clippy/ | grep -o "Merge commit '[a-f0-9]*' into .*" | head -1 | sed -e "s/Merge commit '\([a-f0-9]*\)' into .*/\1/g" ``` @@ -44,7 +47,9 @@ git log --oneline -- src/tools/clippy/ | grep -o "Merge commit '[a-f0-9]*' into Once you've got the correct commit range, run - util/fetch_prs_between.sh commit1 commit2 > changes.txt +``` +util/fetch_prs_between.sh commit1 commit2 > changes.txt +``` and open that file in your editor of choice. @@ -54,14 +59,14 @@ already correct in the current changelog. ### 3. Authoring the final changelog The above script should have dumped all the relevant PRs to the file you -specified. It should have filtered out most of the irrelevant PRs -already, but it's a good idea to do a manual cleanup pass where you look for -more irrelevant PRs. If you're not sure about some PRs, just leave them in for -the review and ask for feedback. - -With the PRs filtered, you can start to take each PR and move the -`changelog: ` content to `CHANGELOG.md`. Adapt the wording as you see fit but -try to keep it somewhat coherent. +specified. It should have filtered out most of the irrelevant PRs already, but +it's a good idea to do a manual cleanup pass where you look for more irrelevant +PRs. If you're not sure about some PRs, just leave them in for the review and +ask for feedback. + +With the PRs filtered, you can start to take each PR and move the `changelog: ` +content to `CHANGELOG.md`. Adapt the wording as you see fit but try to keep it +somewhat coherent. The order should roughly be: diff --git a/book/src/infrastructure/release.md b/book/src/infrastructure/release.md index c4f8f989384..7c2fd29b5f9 100644 --- a/book/src/infrastructure/release.md +++ b/book/src/infrastructure/release.md @@ -1,7 +1,7 @@ # Release a new Clippy Version -_NOTE: This document is probably only relevant to you, if you're a member of the -Clippy team._ +> _NOTE:_ This document is probably only relevant to you, if you're a member of +> the Clippy team. Clippy is released together with stable Rust releases. The dates for these releases can be found at the [Rust Forge]. This document explains the necessary @@ -13,12 +13,11 @@ steps to create a Clippy release. 4. [Tag the stable commit](#tag-the-stable-commit) 5. [Update `CHANGELOG.md`](#update-changelogmd) -_NOTE: This document is for stable Rust releases, not for point releases. For -point releases, step 1. and 2. should be enough._ +> _NOTE:_ This document is for stable Rust releases, not for point releases. For +> point releases, step 1. and 2. should be enough. [Rust Forge]: https://forge.rust-lang.org/ - ## Remerge the `beta` branch This step is only necessary, if since the last release something was backported @@ -45,9 +44,8 @@ $ git push origin backport_remerge # This can be pushed to your fork ``` After this, open a PR to the master branch. In this PR, the commit hash of the -`HEAD` of the `beta` branch must exists. In addition to that, no files should -be changed by this PR. - +`HEAD` of the `beta` branch must exists. In addition to that, no files should be +changed by this PR. ## Update the `beta` branch @@ -72,7 +70,6 @@ $ git reset --hard $BETA_SHA $ git push upstream beta ``` - ## Find the Clippy commit The first step is to tag the Clippy commit, that is included in the stable Rust @@ -85,7 +82,6 @@ $ git checkout 1.XX.0 # XX should be exchanged with the corresponding version $ SHA=$(git log --oneline -- src/tools/clippy/ | grep -o "Merge commit '[a-f0-9]*' into .*" | head -1 | sed -e "s/Merge commit '\([a-f0-9]*\)' into .*/\1/g") ``` - ## Tag the stable commit After finding the Clippy commit, it can be tagged with the release number. @@ -112,10 +108,10 @@ tag. Updating the stable branch from here is as easy as: $ git push upstream rust-1.XX.0:stable # `upstream` is the `rust-lang/rust-clippy` remote ``` -_NOTE: Usually there are no stable backports for Clippy, so this update should -be possible without force pushing or anything like this. If there should have -happened a stable backport, make sure to re-merge those changes just as with the -`beta` branch._ +> _NOTE:_ Usually there are no stable backports for Clippy, so this update +> should be possible without force pushing or anything like this. If there +> should have happened a stable backport, make sure to re-merge those changes +> just as with the `beta` branch. ## Update `CHANGELOG.md` @@ -142,4 +138,4 @@ the following parts: Current stable, released 20YY-MM-DD -> Released 20YY-MM-DD ``` -[how to update the changelog]: https://github.com/rust-lang/rust-clippy/blob/master/doc/changelog_update.md +[how to update the changelog]: changelog_update.md -- cgit 1.4.1-3-g733a5 From b374e0f696b2fc7d9d2e252096a463dc780b45c6 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 21 Jan 2022 17:29:18 +0100 Subject: Remove Edition 2018 tests section from adding lints doc The UI tests now use the latest edition by default. Testing on older editions should almost never be necessary, so I don't see a need to document this. --- book/src/development/adding_lints.md | 7 ------- 1 file changed, 7 deletions(-) (limited to 'book/src/development/adding_lints.md') diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md index 7ffada8aef1..3da07fcb968 100644 --- a/book/src/development/adding_lints.md +++ b/book/src/development/adding_lints.md @@ -147,13 +147,6 @@ the tests. [rustfix]: https://github.com/rust-lang/rustfix -## Edition 2018 tests - -Some features require the 2018 edition to work (e.g. `async_await`), but -compile-test tests run on the 2015 edition by default. To change this behavior -add `// edition:2018` at the top of the test file (note that it's -space-sensitive). - ## Testing manually Manually testing against an example file can be useful if you have added some -- cgit 1.4.1-3-g733a5 From 83191964990e9ea62200257b81902281c03dd4e7 Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Tue, 26 Jul 2022 20:23:50 -0400 Subject: Document `--type` flag --- book/src/development/adding_lints.md | 45 ++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 10 deletions(-) (limited to 'book/src/development/adding_lints.md') diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md index d06297f2e07..da781eb970d 100644 --- a/book/src/development/adding_lints.md +++ b/book/src/development/adding_lints.md @@ -10,6 +10,10 @@ because that's clearly a non-descriptive name. - [Adding a new lint](#adding-a-new-lint) - [Setup](#setup) - [Getting Started](#getting-started) + - [Defining Our Lint](#defining-our-lint) + - [Standalone](#standalone) + - [Specific Type](#specific-type) + - [Tests Location](#tests-location) - [Testing](#testing) - [Cargo lints](#cargo-lints) - [Rustfix tests](#rustfix-tests) @@ -36,17 +40,38 @@ See the [Basics](basics.md#get-the-code) documentation. ## Getting Started There is a bit of boilerplate code that needs to be set up when creating a new -lint. Fortunately, you can use the clippy dev tools to handle this for you. We +lint. Fortunately, you can use the Clippy dev tools to handle this for you. We are naming our new lint `foo_functions` (lints are generally written in snake -case), and we don't need type information so it will have an early pass type -(more on this later on). If you're not sure if the name you chose fits the lint, -take a look at our [lint naming guidelines][lint_naming]. To get started on this -lint you can run `cargo dev new_lint --name=foo_functions --pass=early ---category=pedantic` (category will default to nursery if not provided). This -command will create two files: `tests/ui/foo_functions.rs` and -`clippy_lints/src/foo_functions.rs`, as well as [registering the -lint](#lint-registration). For cargo lints, two project hierarchies (fail/pass) -will be created by default under `tests/ui-cargo`. +case), and we don't need type information, so it will have an early pass type +(more on this later). If you're unsure if the name you chose fits the lint, +take a look at our [lint naming guidelines][lint_naming]. + +## Defining Our Lint +To get started, there are two ways to define our lint. + +### Standalone +Command: `cargo dev new_lint --name=foo_functions --pass=early --category=pedantic` +(category will default to nursery if not provided) + +This command will create a new file: `clippy_lints/src/foo_functions.rs`, as well +as [register the lint](#lint-registration). + +### Specific Type +Command: `cargo dev new_lint --name=foo_functions --type=functions --category=pedantic` + +This command will create a new file: `clippy_lints/src/{type}/foo_functions.rs`. + +Notice how this command has a `--type` flag instead of `--pass`. Unlike a standalone +definition, this lint won't be registered in the traditional sense. Instead, you will +call your lint from within the type's lint pass, found in `clippy_lints/src/{type}/mod.rs`. + +A "type" is just the name of a directory in `clippy_lints/src`, like `functions` in +the example command. These are groupings of lints with common behaviors, so if your +lint falls into one, it would be best to add it to that type. + +### Tests Location +Both commands will create a file: `tests/ui/foo_functions.rs`. For cargo lints, +two project hierarchies (fail/pass) will be created by default under `tests/ui-cargo`. Next, we'll open up these files and add our lint! -- cgit 1.4.1-3-g733a5 From 6d8959ea8374376ee38c972c61e8bfdacb71724f Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Fri, 16 Sep 2022 21:04:38 +0000 Subject: Add `#[allow(unused)]` to test in `cargo dev new_lint` --- book/src/development/adding_lints.md | 1 + clippy_dev/src/new_lint.rs | 1 + 2 files changed, 2 insertions(+) (limited to 'book/src/development/adding_lints.md') diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md index da781eb970d..b1e843bc7f4 100644 --- a/book/src/development/adding_lints.md +++ b/book/src/development/adding_lints.md @@ -90,6 +90,7 @@ We start by opening the test file created at `tests/ui/foo_functions.rs`. Update the file with some examples to get started: ```rust +#![allow(unused)] #![warn(clippy::foo_functions)] // Impl methods diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index be05e67d724..9a68c6e775d 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -186,6 +186,7 @@ pub(crate) fn get_stabilization_version() -> String { fn get_test_file_contents(lint_name: &str, header_commands: Option<&str>) -> String { let mut contents = format!( indoc! {" + #![allow(unused)] #![warn(clippy::{})] fn main() {{ -- cgit 1.4.1-3-g733a5 From 815876d93f75c4d20c52cdd32f1a521ce306be63 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Fri, 21 Oct 2022 21:35:39 +0000 Subject: Move MSRV tests into the lint specific test files --- book/src/development/adding_lints.md | 23 +- tests/ui/cast_abs_to_unsigned.fixed | 18 +- tests/ui/cast_abs_to_unsigned.rs | 18 +- tests/ui/cast_abs_to_unsigned.stderr | 42 ++-- tests/ui/cast_lossless_bool.fixed | 13 ++ tests/ui/cast_lossless_bool.rs | 13 ++ tests/ui/cast_lossless_bool.stderr | 34 +-- tests/ui/cfg_attr_rustfmt.fixed | 16 +- tests/ui/cfg_attr_rustfmt.rs | 16 +- tests/ui/cfg_attr_rustfmt.stderr | 8 +- tests/ui/checked_conversions.fixed | 16 ++ tests/ui/checked_conversions.rs | 16 ++ tests/ui/checked_conversions.stderr | 40 ++-- tests/ui/cloned_instead_of_copied.fixed | 24 +++ tests/ui/cloned_instead_of_copied.rs | 24 +++ tests/ui/cloned_instead_of_copied.stderr | 30 ++- tests/ui/err_expect.fixed | 17 ++ tests/ui/err_expect.rs | 17 ++ tests/ui/err_expect.stderr | 10 +- tests/ui/filter_map_next_fixable.fixed | 16 ++ tests/ui/filter_map_next_fixable.rs | 16 ++ tests/ui/filter_map_next_fixable.stderr | 10 +- tests/ui/from_over_into.fixed | 25 +++ tests/ui/from_over_into.rs | 25 +++ tests/ui/from_over_into.stderr | 23 +- tests/ui/manual_clamp.rs | 27 +++ tests/ui/manual_clamp.stderr | 85 +++++--- tests/ui/manual_rem_euclid.fixed | 30 +++ tests/ui/manual_rem_euclid.rs | 30 +++ tests/ui/manual_rem_euclid.stderr | 30 ++- tests/ui/manual_strip.rs | 19 ++ tests/ui/manual_strip.stderr | 47 ++-- tests/ui/map_unwrap_or.rs | 20 +- tests/ui/map_unwrap_or.stderr | 30 +-- tests/ui/match_expr_like_matches_macro.fixed | 16 ++ tests/ui/match_expr_like_matches_macro.rs | 19 ++ tests/ui/match_expr_like_matches_macro.stderr | 38 ++-- tests/ui/mem_replace.fixed | 18 +- tests/ui/mem_replace.rs | 18 +- tests/ui/mem_replace.stderr | 46 ++-- tests/ui/min_rust_version_attr.rs | 239 ++------------------- tests/ui/min_rust_version_attr.stderr | 46 ++-- tests/ui/min_rust_version_invalid_attr.rs | 14 ++ tests/ui/min_rust_version_invalid_attr.stderr | 44 +++- tests/ui/min_rust_version_multiple_inner_attr.rs | 11 - .../ui/min_rust_version_multiple_inner_attr.stderr | 38 ---- tests/ui/min_rust_version_no_patch.rs | 14 -- tests/ui/min_rust_version_outer_attr.rs | 4 - tests/ui/min_rust_version_outer_attr.stderr | 8 - tests/ui/missing_const_for_fn/could_be_const.rs | 12 ++ .../ui/missing_const_for_fn/could_be_const.stderr | 12 +- tests/ui/option_as_ref_deref.fixed | 17 +- tests/ui/option_as_ref_deref.rs | 17 +- tests/ui/option_as_ref_deref.stderr | 42 ++-- tests/ui/range_contains.fixed | 26 ++- tests/ui/range_contains.rs | 26 ++- tests/ui/range_contains.stderr | 48 +++-- tests/ui/redundant_field_names.fixed | 16 ++ tests/ui/redundant_field_names.rs | 16 ++ tests/ui/redundant_field_names.stderr | 22 +- tests/ui/redundant_static_lifetimes.fixed | 13 ++ tests/ui/redundant_static_lifetimes.rs | 13 ++ tests/ui/redundant_static_lifetimes.stderr | 40 ++-- tests/ui/unnested_or_patterns.fixed | 16 +- tests/ui/unnested_or_patterns.rs | 16 +- tests/ui/unnested_or_patterns.stderr | 13 +- tests/ui/use_self.fixed | 33 +++ tests/ui/use_self.rs | 33 +++ tests/ui/use_self.stderr | 90 ++++---- 69 files changed, 1290 insertions(+), 632 deletions(-) delete mode 100644 tests/ui/min_rust_version_multiple_inner_attr.rs delete mode 100644 tests/ui/min_rust_version_multiple_inner_attr.stderr delete mode 100644 tests/ui/min_rust_version_no_patch.rs delete mode 100644 tests/ui/min_rust_version_outer_attr.rs delete mode 100644 tests/ui/min_rust_version_outer_attr.stderr (limited to 'book/src/development/adding_lints.md') diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md index b1e843bc7f4..3c3f368a529 100644 --- a/book/src/development/adding_lints.md +++ b/book/src/development/adding_lints.md @@ -478,8 +478,27 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip { ``` Once the `msrv` is added to the lint, a relevant test case should be added to -`tests/ui/min_rust_version_attr.rs` which verifies that the lint isn't emitted -if the project's MSRV is lower. +the lint's test file, `tests/ui/manual_strip.rs` in this example. It should +have a case for the version below the MSRV and one with the same contents but +for the MSRV version itself. + +```rust +#![feature(custom_inner_attributes)] + +... + +fn msrv_1_44() { + #![clippy::msrv = "1.44"] + + /* something that would trigger the lint */ +} + +fn msrv_1_45() { + #![clippy::msrv = "1.45"] + + /* something that would trigger the lint */ +} +``` As a last step, the lint should be added to the lint documentation. This is done in `clippy_lints/src/utils/conf.rs`: diff --git a/tests/ui/cast_abs_to_unsigned.fixed b/tests/ui/cast_abs_to_unsigned.fixed index a37f3fec20f..e6bf944c7a5 100644 --- a/tests/ui/cast_abs_to_unsigned.fixed +++ b/tests/ui/cast_abs_to_unsigned.fixed @@ -1,6 +1,8 @@ // run-rustfix + +#![feature(custom_inner_attributes)] #![warn(clippy::cast_abs_to_unsigned)] -#![allow(clippy::uninlined_format_args)] +#![allow(clippy::uninlined_format_args, unused)] fn main() { let x: i32 = -42; @@ -30,3 +32,17 @@ fn main() { let _ = (x as i64 - y as i64).unsigned_abs() as u32; } + +fn msrv_1_50() { + #![clippy::msrv = "1.50"] + + let x: i32 = 10; + assert_eq!(10u32, x.abs() as u32); +} + +fn msrv_1_51() { + #![clippy::msrv = "1.51"] + + let x: i32 = 10; + assert_eq!(10u32, x.unsigned_abs()); +} diff --git a/tests/ui/cast_abs_to_unsigned.rs b/tests/ui/cast_abs_to_unsigned.rs index 5706930af5a..c87320b5209 100644 --- a/tests/ui/cast_abs_to_unsigned.rs +++ b/tests/ui/cast_abs_to_unsigned.rs @@ -1,6 +1,8 @@ // run-rustfix + +#![feature(custom_inner_attributes)] #![warn(clippy::cast_abs_to_unsigned)] -#![allow(clippy::uninlined_format_args)] +#![allow(clippy::uninlined_format_args, unused)] fn main() { let x: i32 = -42; @@ -30,3 +32,17 @@ fn main() { let _ = (x as i64 - y as i64).abs() as u32; } + +fn msrv_1_50() { + #![clippy::msrv = "1.50"] + + let x: i32 = 10; + assert_eq!(10u32, x.abs() as u32); +} + +fn msrv_1_51() { + #![clippy::msrv = "1.51"] + + let x: i32 = 10; + assert_eq!(10u32, x.abs() as u32); +} diff --git a/tests/ui/cast_abs_to_unsigned.stderr b/tests/ui/cast_abs_to_unsigned.stderr index 7cea11c183d..1b39c554b03 100644 --- a/tests/ui/cast_abs_to_unsigned.stderr +++ b/tests/ui/cast_abs_to_unsigned.stderr @@ -1,5 +1,5 @@ error: casting the result of `i32::abs()` to u32 - --> $DIR/cast_abs_to_unsigned.rs:7:18 + --> $DIR/cast_abs_to_unsigned.rs:9:18 | LL | let y: u32 = x.abs() as u32; | ^^^^^^^^^^^^^^ help: replace with: `x.unsigned_abs()` @@ -7,100 +7,106 @@ LL | let y: u32 = x.abs() as u32; = note: `-D clippy::cast-abs-to-unsigned` implied by `-D warnings` error: casting the result of `i32::abs()` to usize - --> $DIR/cast_abs_to_unsigned.rs:11:20 + --> $DIR/cast_abs_to_unsigned.rs:13:20 | LL | let _: usize = a.abs() as usize; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `i32::abs()` to usize - --> $DIR/cast_abs_to_unsigned.rs:12:20 + --> $DIR/cast_abs_to_unsigned.rs:14:20 | LL | let _: usize = a.abs() as _; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `i32::abs()` to usize - --> $DIR/cast_abs_to_unsigned.rs:13:13 + --> $DIR/cast_abs_to_unsigned.rs:15:13 | LL | let _ = a.abs() as usize; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `i64::abs()` to usize - --> $DIR/cast_abs_to_unsigned.rs:16:13 + --> $DIR/cast_abs_to_unsigned.rs:18:13 | LL | let _ = a.abs() as usize; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `i64::abs()` to u8 - --> $DIR/cast_abs_to_unsigned.rs:17:13 + --> $DIR/cast_abs_to_unsigned.rs:19:13 | LL | let _ = a.abs() as u8; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `i64::abs()` to u16 - --> $DIR/cast_abs_to_unsigned.rs:18:13 + --> $DIR/cast_abs_to_unsigned.rs:20:13 | LL | let _ = a.abs() as u16; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `i64::abs()` to u32 - --> $DIR/cast_abs_to_unsigned.rs:19:13 + --> $DIR/cast_abs_to_unsigned.rs:21:13 | LL | let _ = a.abs() as u32; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `i64::abs()` to u64 - --> $DIR/cast_abs_to_unsigned.rs:20:13 + --> $DIR/cast_abs_to_unsigned.rs:22:13 | LL | let _ = a.abs() as u64; | ^^^^^^^^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `i64::abs()` to u128 - --> $DIR/cast_abs_to_unsigned.rs:21:13 + --> $DIR/cast_abs_to_unsigned.rs:23:13 | LL | let _ = a.abs() as u128; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `isize::abs()` to usize - --> $DIR/cast_abs_to_unsigned.rs:24:13 + --> $DIR/cast_abs_to_unsigned.rs:26:13 | LL | let _ = a.abs() as usize; | ^^^^^^^^^^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `isize::abs()` to u8 - --> $DIR/cast_abs_to_unsigned.rs:25:13 + --> $DIR/cast_abs_to_unsigned.rs:27:13 | LL | let _ = a.abs() as u8; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `isize::abs()` to u16 - --> $DIR/cast_abs_to_unsigned.rs:26:13 + --> $DIR/cast_abs_to_unsigned.rs:28:13 | LL | let _ = a.abs() as u16; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `isize::abs()` to u32 - --> $DIR/cast_abs_to_unsigned.rs:27:13 + --> $DIR/cast_abs_to_unsigned.rs:29:13 | LL | let _ = a.abs() as u32; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `isize::abs()` to u64 - --> $DIR/cast_abs_to_unsigned.rs:28:13 + --> $DIR/cast_abs_to_unsigned.rs:30:13 | LL | let _ = a.abs() as u64; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `isize::abs()` to u128 - --> $DIR/cast_abs_to_unsigned.rs:29:13 + --> $DIR/cast_abs_to_unsigned.rs:31:13 | LL | let _ = a.abs() as u128; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `i64::abs()` to u32 - --> $DIR/cast_abs_to_unsigned.rs:31:13 + --> $DIR/cast_abs_to_unsigned.rs:33:13 | LL | let _ = (x as i64 - y as i64).abs() as u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `(x as i64 - y as i64).unsigned_abs()` -error: aborting due to 17 previous errors +error: casting the result of `i32::abs()` to u32 + --> $DIR/cast_abs_to_unsigned.rs:47:23 + | +LL | assert_eq!(10u32, x.abs() as u32); + | ^^^^^^^^^^^^^^ help: replace with: `x.unsigned_abs()` + +error: aborting due to 18 previous errors diff --git a/tests/ui/cast_lossless_bool.fixed b/tests/ui/cast_lossless_bool.fixed index 9e2da45c378..af13b755e31 100644 --- a/tests/ui/cast_lossless_bool.fixed +++ b/tests/ui/cast_lossless_bool.fixed @@ -1,5 +1,6 @@ // run-rustfix +#![feature(custom_inner_attributes)] #![allow(dead_code)] #![warn(clippy::cast_lossless)] @@ -40,3 +41,15 @@ mod cast_lossless_in_impl { } } } + +fn msrv_1_27() { + #![clippy::msrv = "1.27"] + + let _ = true as u8; +} + +fn msrv_1_28() { + #![clippy::msrv = "1.28"] + + let _ = u8::from(true); +} diff --git a/tests/ui/cast_lossless_bool.rs b/tests/ui/cast_lossless_bool.rs index b6f6c59a01f..3b06af899c6 100644 --- a/tests/ui/cast_lossless_bool.rs +++ b/tests/ui/cast_lossless_bool.rs @@ -1,5 +1,6 @@ // run-rustfix +#![feature(custom_inner_attributes)] #![allow(dead_code)] #![warn(clippy::cast_lossless)] @@ -40,3 +41,15 @@ mod cast_lossless_in_impl { } } } + +fn msrv_1_27() { + #![clippy::msrv = "1.27"] + + let _ = true as u8; +} + +fn msrv_1_28() { + #![clippy::msrv = "1.28"] + + let _ = true as u8; +} diff --git a/tests/ui/cast_lossless_bool.stderr b/tests/ui/cast_lossless_bool.stderr index 6b148336011..768b033d10a 100644 --- a/tests/ui/cast_lossless_bool.stderr +++ b/tests/ui/cast_lossless_bool.stderr @@ -1,5 +1,5 @@ error: casting `bool` to `u8` is more cleanly stated with `u8::from(_)` - --> $DIR/cast_lossless_bool.rs:8:13 + --> $DIR/cast_lossless_bool.rs:9:13 | LL | let _ = true as u8; | ^^^^^^^^^^ help: try: `u8::from(true)` @@ -7,76 +7,82 @@ LL | let _ = true as u8; = note: `-D clippy::cast-lossless` implied by `-D warnings` error: casting `bool` to `u16` is more cleanly stated with `u16::from(_)` - --> $DIR/cast_lossless_bool.rs:9:13 + --> $DIR/cast_lossless_bool.rs:10:13 | LL | let _ = true as u16; | ^^^^^^^^^^^ help: try: `u16::from(true)` error: casting `bool` to `u32` is more cleanly stated with `u32::from(_)` - --> $DIR/cast_lossless_bool.rs:10:13 + --> $DIR/cast_lossless_bool.rs:11:13 | LL | let _ = true as u32; | ^^^^^^^^^^^ help: try: `u32::from(true)` error: casting `bool` to `u64` is more cleanly stated with `u64::from(_)` - --> $DIR/cast_lossless_bool.rs:11:13 + --> $DIR/cast_lossless_bool.rs:12:13 | LL | let _ = true as u64; | ^^^^^^^^^^^ help: try: `u64::from(true)` error: casting `bool` to `u128` is more cleanly stated with `u128::from(_)` - --> $DIR/cast_lossless_bool.rs:12:13 + --> $DIR/cast_lossless_bool.rs:13:13 | LL | let _ = true as u128; | ^^^^^^^^^^^^ help: try: `u128::from(true)` error: casting `bool` to `usize` is more cleanly stated with `usize::from(_)` - --> $DIR/cast_lossless_bool.rs:13:13 + --> $DIR/cast_lossless_bool.rs:14:13 | LL | let _ = true as usize; | ^^^^^^^^^^^^^ help: try: `usize::from(true)` error: casting `bool` to `i8` is more cleanly stated with `i8::from(_)` - --> $DIR/cast_lossless_bool.rs:15:13 + --> $DIR/cast_lossless_bool.rs:16:13 | LL | let _ = true as i8; | ^^^^^^^^^^ help: try: `i8::from(true)` error: casting `bool` to `i16` is more cleanly stated with `i16::from(_)` - --> $DIR/cast_lossless_bool.rs:16:13 + --> $DIR/cast_lossless_bool.rs:17:13 | LL | let _ = true as i16; | ^^^^^^^^^^^ help: try: `i16::from(true)` error: casting `bool` to `i32` is more cleanly stated with `i32::from(_)` - --> $DIR/cast_lossless_bool.rs:17:13 + --> $DIR/cast_lossless_bool.rs:18:13 | LL | let _ = true as i32; | ^^^^^^^^^^^ help: try: `i32::from(true)` error: casting `bool` to `i64` is more cleanly stated with `i64::from(_)` - --> $DIR/cast_lossless_bool.rs:18:13 + --> $DIR/cast_lossless_bool.rs:19:13 | LL | let _ = true as i64; | ^^^^^^^^^^^ help: try: `i64::from(true)` error: casting `bool` to `i128` is more cleanly stated with `i128::from(_)` - --> $DIR/cast_lossless_bool.rs:19:13 + --> $DIR/cast_lossless_bool.rs:20:13 | LL | let _ = true as i128; | ^^^^^^^^^^^^ help: try: `i128::from(true)` error: casting `bool` to `isize` is more cleanly stated with `isize::from(_)` - --> $DIR/cast_lossless_bool.rs:20:13 + --> $DIR/cast_lossless_bool.rs:21:13 | LL | let _ = true as isize; | ^^^^^^^^^^^^^ help: try: `isize::from(true)` error: casting `bool` to `u16` is more cleanly stated with `u16::from(_)` - --> $DIR/cast_lossless_bool.rs:23:13 + --> $DIR/cast_lossless_bool.rs:24:13 | LL | let _ = (true | false) as u16; | ^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::from(true | false)` -error: aborting due to 13 previous errors +error: casting `bool` to `u8` is more cleanly stated with `u8::from(_)` + --> $DIR/cast_lossless_bool.rs:54:13 + | +LL | let _ = true as u8; + | ^^^^^^^^^^ help: try: `u8::from(true)` + +error: aborting due to 14 previous errors diff --git a/tests/ui/cfg_attr_rustfmt.fixed b/tests/ui/cfg_attr_rustfmt.fixed index 061a4ab9b2e..8a5645b22ed 100644 --- a/tests/ui/cfg_attr_rustfmt.fixed +++ b/tests/ui/cfg_attr_rustfmt.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![feature(stmt_expr_attributes)] +#![feature(stmt_expr_attributes, custom_inner_attributes)] #![allow(unused, clippy::no_effect, clippy::unnecessary_operation)] #![warn(clippy::deprecated_cfg_attr)] @@ -29,3 +29,17 @@ mod foo { pub fn f() {} } + +fn msrv_1_29() { + #![clippy::msrv = "1.29"] + + #[cfg_attr(rustfmt, rustfmt::skip)] + 1+29; +} + +fn msrv_1_30() { + #![clippy::msrv = "1.30"] + + #[rustfmt::skip] + 1+30; +} diff --git a/tests/ui/cfg_attr_rustfmt.rs b/tests/ui/cfg_attr_rustfmt.rs index 035169fab85..2fb140efae7 100644 --- a/tests/ui/cfg_attr_rustfmt.rs +++ b/tests/ui/cfg_attr_rustfmt.rs @@ -1,5 +1,5 @@ // run-rustfix -#![feature(stmt_expr_attributes)] +#![feature(stmt_expr_attributes, custom_inner_attributes)] #![allow(unused, clippy::no_effect, clippy::unnecessary_operation)] #![warn(clippy::deprecated_cfg_attr)] @@ -29,3 +29,17 @@ mod foo { pub fn f() {} } + +fn msrv_1_29() { + #![clippy::msrv = "1.29"] + + #[cfg_attr(rustfmt, rustfmt::skip)] + 1+29; +} + +fn msrv_1_30() { + #![clippy::msrv = "1.30"] + + #[cfg_attr(rustfmt, rustfmt::skip)] + 1+30; +} diff --git a/tests/ui/cfg_attr_rustfmt.stderr b/tests/ui/cfg_attr_rustfmt.stderr index c1efd47db90..08df7b2b39a 100644 --- a/tests/ui/cfg_attr_rustfmt.stderr +++ b/tests/ui/cfg_attr_rustfmt.stderr @@ -12,5 +12,11 @@ error: `cfg_attr` is deprecated for rustfmt and got replaced by tool attributes LL | #[cfg_attr(rustfmt, rustfmt_skip)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#[rustfmt::skip]` -error: aborting due to 2 previous errors +error: `cfg_attr` is deprecated for rustfmt and got replaced by tool attributes + --> $DIR/cfg_attr_rustfmt.rs:43:5 + | +LL | #[cfg_attr(rustfmt, rustfmt::skip)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#[rustfmt::skip]` + +error: aborting due to 3 previous errors diff --git a/tests/ui/checked_conversions.fixed b/tests/ui/checked_conversions.fixed index cb7100bc9ef..f936957cb40 100644 --- a/tests/ui/checked_conversions.fixed +++ b/tests/ui/checked_conversions.fixed @@ -1,7 +1,9 @@ // run-rustfix +#![feature(custom_inner_attributes)] #![allow( clippy::cast_lossless, + unused, // Int::max_value will be deprecated in the future deprecated, )] @@ -76,4 +78,18 @@ pub const fn issue_8898(i: u32) -> bool { i <= i32::MAX as u32 } +fn msrv_1_33() { + #![clippy::msrv = "1.33"] + + let value: i64 = 33; + let _ = value <= (u32::MAX as i64) && value >= 0; +} + +fn msrv_1_34() { + #![clippy::msrv = "1.34"] + + let value: i64 = 34; + let _ = u32::try_from(value).is_ok(); +} + fn main() {} diff --git a/tests/ui/checked_conversions.rs b/tests/ui/checked_conversions.rs index ed4e0692388..77aec713ff3 100644 --- a/tests/ui/checked_conversions.rs +++ b/tests/ui/checked_conversions.rs @@ -1,7 +1,9 @@ // run-rustfix +#![feature(custom_inner_attributes)] #![allow( clippy::cast_lossless, + unused, // Int::max_value will be deprecated in the future deprecated, )] @@ -76,4 +78,18 @@ pub const fn issue_8898(i: u32) -> bool { i <= i32::MAX as u32 } +fn msrv_1_33() { + #![clippy::msrv = "1.33"] + + let value: i64 = 33; + let _ = value <= (u32::MAX as i64) && value >= 0; +} + +fn msrv_1_34() { + #![clippy::msrv = "1.34"] + + let value: i64 = 34; + let _ = value <= (u32::MAX as i64) && value >= 0; +} + fn main() {} diff --git a/tests/ui/checked_conversions.stderr b/tests/ui/checked_conversions.stderr index 2e518040561..b2bf7af8daf 100644 --- a/tests/ui/checked_conversions.stderr +++ b/tests/ui/checked_conversions.stderr @@ -1,5 +1,5 @@ error: checked cast can be simplified - --> $DIR/checked_conversions.rs:15:13 + --> $DIR/checked_conversions.rs:17:13 | LL | let _ = value <= (u32::max_value() as i64) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u32::try_from(value).is_ok()` @@ -7,94 +7,100 @@ LL | let _ = value <= (u32::max_value() as i64) && value >= 0; = note: `-D clippy::checked-conversions` implied by `-D warnings` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:16:13 + --> $DIR/checked_conversions.rs:18:13 | LL | let _ = value <= (u32::MAX as i64) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u32::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:20:13 + --> $DIR/checked_conversions.rs:22:13 | LL | let _ = value <= i64::from(u16::max_value()) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:21:13 + --> $DIR/checked_conversions.rs:23:13 | LL | let _ = value <= i64::from(u16::MAX) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:25:13 + --> $DIR/checked_conversions.rs:27:13 | LL | let _ = value <= (u8::max_value() as isize) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u8::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:26:13 + --> $DIR/checked_conversions.rs:28:13 | LL | let _ = value <= (u8::MAX as isize) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u8::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:32:13 + --> $DIR/checked_conversions.rs:34:13 | LL | let _ = value <= (i32::max_value() as i64) && value >= (i32::min_value() as i64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:33:13 + --> $DIR/checked_conversions.rs:35:13 | LL | let _ = value <= (i32::MAX as i64) && value >= (i32::MIN as i64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:37:13 + --> $DIR/checked_conversions.rs:39:13 | LL | let _ = value <= i64::from(i16::max_value()) && value >= i64::from(i16::min_value()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i16::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:38:13 + --> $DIR/checked_conversions.rs:40:13 | LL | let _ = value <= i64::from(i16::MAX) && value >= i64::from(i16::MIN); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i16::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:44:13 + --> $DIR/checked_conversions.rs:46:13 | LL | let _ = value <= i32::max_value() as u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:45:13 + --> $DIR/checked_conversions.rs:47:13 | LL | let _ = value <= i32::MAX as u32; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:49:13 + --> $DIR/checked_conversions.rs:51:13 | LL | let _ = value <= isize::max_value() as usize && value as i32 == 5; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `isize::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:50:13 + --> $DIR/checked_conversions.rs:52:13 | LL | let _ = value <= isize::MAX as usize && value as i32 == 5; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `isize::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:54:13 + --> $DIR/checked_conversions.rs:56:13 | LL | let _ = value <= u16::max_value() as u32 && value as i32 == 5; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:55:13 + --> $DIR/checked_conversions.rs:57:13 | LL | let _ = value <= u16::MAX as u32 && value as i32 == 5; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()` -error: aborting due to 16 previous errors +error: checked cast can be simplified + --> $DIR/checked_conversions.rs:92:13 + | +LL | let _ = value <= (u32::MAX as i64) && value >= 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u32::try_from(value).is_ok()` + +error: aborting due to 17 previous errors diff --git a/tests/ui/cloned_instead_of_copied.fixed b/tests/ui/cloned_instead_of_copied.fixed index 4eb999e18e6..42ed232d100 100644 --- a/tests/ui/cloned_instead_of_copied.fixed +++ b/tests/ui/cloned_instead_of_copied.fixed @@ -1,5 +1,8 @@ // run-rustfix + +#![feature(custom_inner_attributes)] #![warn(clippy::cloned_instead_of_copied)] +#![allow(unused)] fn main() { // yay @@ -13,3 +16,24 @@ fn main() { let _ = [String::new()].iter().cloned(); let _ = Some(&String::new()).cloned(); } + +fn msrv_1_34() { + #![clippy::msrv = "1.34"] + + let _ = [1].iter().cloned(); + let _ = Some(&1).cloned(); +} + +fn msrv_1_35() { + #![clippy::msrv = "1.35"] + + let _ = [1].iter().cloned(); + let _ = Some(&1).copied(); // Option::copied needs 1.35 +} + +fn msrv_1_36() { + #![clippy::msrv = "1.36"] + + let _ = [1].iter().copied(); // Iterator::copied needs 1.36 + let _ = Some(&1).copied(); +} diff --git a/tests/ui/cloned_instead_of_copied.rs b/tests/ui/cloned_instead_of_copied.rs index 894496c0ebb..471bd9654cc 100644 --- a/tests/ui/cloned_instead_of_copied.rs +++ b/tests/ui/cloned_instead_of_copied.rs @@ -1,5 +1,8 @@ // run-rustfix + +#![feature(custom_inner_attributes)] #![warn(clippy::cloned_instead_of_copied)] +#![allow(unused)] fn main() { // yay @@ -13,3 +16,24 @@ fn main() { let _ = [String::new()].iter().cloned(); let _ = Some(&String::new()).cloned(); } + +fn msrv_1_34() { + #![clippy::msrv = "1.34"] + + let _ = [1].iter().cloned(); + let _ = Some(&1).cloned(); +} + +fn msrv_1_35() { + #![clippy::msrv = "1.35"] + + let _ = [1].iter().cloned(); + let _ = Some(&1).cloned(); // Option::copied needs 1.35 +} + +fn msrv_1_36() { + #![clippy::msrv = "1.36"] + + let _ = [1].iter().cloned(); // Iterator::copied needs 1.36 + let _ = Some(&1).cloned(); +} diff --git a/tests/ui/cloned_instead_of_copied.stderr b/tests/ui/cloned_instead_of_copied.stderr index e0707d32146..914c9a91e83 100644 --- a/tests/ui/cloned_instead_of_copied.stderr +++ b/tests/ui/cloned_instead_of_copied.stderr @@ -1,5 +1,5 @@ error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:6:24 + --> $DIR/cloned_instead_of_copied.rs:9:24 | LL | let _ = [1].iter().cloned(); | ^^^^^^ help: try: `copied` @@ -7,28 +7,46 @@ LL | let _ = [1].iter().cloned(); = note: `-D clippy::cloned-instead-of-copied` implied by `-D warnings` error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:7:31 + --> $DIR/cloned_instead_of_copied.rs:10:31 | LL | let _ = vec!["hi"].iter().cloned(); | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:8:22 + --> $DIR/cloned_instead_of_copied.rs:11:22 | LL | let _ = Some(&1).cloned(); | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:9:34 + --> $DIR/cloned_instead_of_copied.rs:12:34 | LL | let _ = Box::new([1].iter()).cloned(); | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:10:32 + --> $DIR/cloned_instead_of_copied.rs:13:32 | LL | let _ = Box::new(Some(&1)).cloned(); | ^^^^^^ help: try: `copied` -error: aborting due to 5 previous errors +error: used `cloned` where `copied` could be used instead + --> $DIR/cloned_instead_of_copied.rs:31:22 + | +LL | let _ = Some(&1).cloned(); // Option::copied needs 1.35 + | ^^^^^^ help: try: `copied` + +error: used `cloned` where `copied` could be used instead + --> $DIR/cloned_instead_of_copied.rs:37:24 + | +LL | let _ = [1].iter().cloned(); // Iterator::copied needs 1.36 + | ^^^^^^ help: try: `copied` + +error: used `cloned` where `copied` could be used instead + --> $DIR/cloned_instead_of_copied.rs:38:22 + | +LL | let _ = Some(&1).cloned(); + | ^^^^^^ help: try: `copied` + +error: aborting due to 8 previous errors diff --git a/tests/ui/err_expect.fixed b/tests/ui/err_expect.fixed index 7e18d70bae4..3bac738acd6 100644 --- a/tests/ui/err_expect.fixed +++ b/tests/ui/err_expect.fixed @@ -1,5 +1,8 @@ // run-rustfix +#![feature(custom_inner_attributes)] +#![allow(unused)] + struct MyTypeNonDebug; #[derive(Debug)] @@ -12,3 +15,17 @@ fn main() { let test_non_debug: Result = Ok(MyTypeNonDebug); test_non_debug.err().expect("Testing non debug type"); } + +fn msrv_1_16() { + #![clippy::msrv = "1.16"] + + let x: Result = Ok(16); + x.err().expect("16"); +} + +fn msrv_1_17() { + #![clippy::msrv = "1.17"] + + let x: Result = Ok(17); + x.expect_err("17"); +} diff --git a/tests/ui/err_expect.rs b/tests/ui/err_expect.rs index bf8c3c9fb8c..6e7c47d9ad3 100644 --- a/tests/ui/err_expect.rs +++ b/tests/ui/err_expect.rs @@ -1,5 +1,8 @@ // run-rustfix +#![feature(custom_inner_attributes)] +#![allow(unused)] + struct MyTypeNonDebug; #[derive(Debug)] @@ -12,3 +15,17 @@ fn main() { let test_non_debug: Result = Ok(MyTypeNonDebug); test_non_debug.err().expect("Testing non debug type"); } + +fn msrv_1_16() { + #![clippy::msrv = "1.16"] + + let x: Result = Ok(16); + x.err().expect("16"); +} + +fn msrv_1_17() { + #![clippy::msrv = "1.17"] + + let x: Result = Ok(17); + x.err().expect("17"); +} diff --git a/tests/ui/err_expect.stderr b/tests/ui/err_expect.stderr index ffd97e00a5c..91a6cf8de65 100644 --- a/tests/ui/err_expect.stderr +++ b/tests/ui/err_expect.stderr @@ -1,10 +1,16 @@ error: called `.err().expect()` on a `Result` value - --> $DIR/err_expect.rs:10:16 + --> $DIR/err_expect.rs:13:16 | LL | test_debug.err().expect("Testing debug type"); | ^^^^^^^^^^^^ help: try: `expect_err` | = note: `-D clippy::err-expect` implied by `-D warnings` -error: aborting due to previous error +error: called `.err().expect()` on a `Result` value + --> $DIR/err_expect.rs:30:7 + | +LL | x.err().expect("17"); + | ^^^^^^^^^^^^ help: try: `expect_err` + +error: aborting due to 2 previous errors diff --git a/tests/ui/filter_map_next_fixable.fixed b/tests/ui/filter_map_next_fixable.fixed index c3992d7e92c..41828ddd7ac 100644 --- a/tests/ui/filter_map_next_fixable.fixed +++ b/tests/ui/filter_map_next_fixable.fixed @@ -1,6 +1,8 @@ // run-rustfix +#![feature(custom_inner_attributes)] #![warn(clippy::all, clippy::pedantic)] +#![allow(unused)] fn main() { let a = ["1", "lol", "3", "NaN", "5"]; @@ -8,3 +10,17 @@ fn main() { let element: Option = a.iter().find_map(|s| s.parse().ok()); assert_eq!(element, Some(1)); } + +fn msrv_1_29() { + #![clippy::msrv = "1.29"] + + let a = ["1", "lol", "3", "NaN", "5"]; + let _: Option = a.iter().filter_map(|s| s.parse().ok()).next(); +} + +fn msrv_1_30() { + #![clippy::msrv = "1.30"] + + let a = ["1", "lol", "3", "NaN", "5"]; + let _: Option = a.iter().find_map(|s| s.parse().ok()); +} diff --git a/tests/ui/filter_map_next_fixable.rs b/tests/ui/filter_map_next_fixable.rs index 447219a9683..be492a81b45 100644 --- a/tests/ui/filter_map_next_fixable.rs +++ b/tests/ui/filter_map_next_fixable.rs @@ -1,6 +1,8 @@ // run-rustfix +#![feature(custom_inner_attributes)] #![warn(clippy::all, clippy::pedantic)] +#![allow(unused)] fn main() { let a = ["1", "lol", "3", "NaN", "5"]; @@ -8,3 +10,17 @@ fn main() { let element: Option = a.iter().filter_map(|s| s.parse().ok()).next(); assert_eq!(element, Some(1)); } + +fn msrv_1_29() { + #![clippy::msrv = "1.29"] + + let a = ["1", "lol", "3", "NaN", "5"]; + let _: Option = a.iter().filter_map(|s| s.parse().ok()).next(); +} + +fn msrv_1_30() { + #![clippy::msrv = "1.30"] + + let a = ["1", "lol", "3", "NaN", "5"]; + let _: Option = a.iter().filter_map(|s| s.parse().ok()).next(); +} diff --git a/tests/ui/filter_map_next_fixable.stderr b/tests/ui/filter_map_next_fixable.stderr index 3bb062ffd7a..e789efeabd5 100644 --- a/tests/ui/filter_map_next_fixable.stderr +++ b/tests/ui/filter_map_next_fixable.stderr @@ -1,10 +1,16 @@ error: called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find_map(..)` instead - --> $DIR/filter_map_next_fixable.rs:8:32 + --> $DIR/filter_map_next_fixable.rs:10:32 | LL | let element: Option = a.iter().filter_map(|s| s.parse().ok()).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `a.iter().find_map(|s| s.parse().ok())` | = note: `-D clippy::filter-map-next` implied by `-D warnings` -error: aborting due to previous error +error: called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find_map(..)` instead + --> $DIR/filter_map_next_fixable.rs:25:26 + | +LL | let _: Option = a.iter().filter_map(|s| s.parse().ok()).next(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `a.iter().find_map(|s| s.parse().ok())` + +error: aborting due to 2 previous errors diff --git a/tests/ui/from_over_into.fixed b/tests/ui/from_over_into.fixed index e66dc43b047..1cf49ca45f4 100644 --- a/tests/ui/from_over_into.fixed +++ b/tests/ui/from_over_into.fixed @@ -1,5 +1,6 @@ // run-rustfix +#![feature(custom_inner_attributes)] #![warn(clippy::from_over_into)] #![allow(unused)] @@ -59,4 +60,28 @@ impl From for A { } } +fn msrv_1_40() { + #![clippy::msrv = "1.40"] + + struct FromOverInto(Vec); + + impl Into> for Vec { + fn into(self) -> FromOverInto { + FromOverInto(self) + } + } +} + +fn msrv_1_41() { + #![clippy::msrv = "1.41"] + + struct FromOverInto(Vec); + + impl From> for FromOverInto { + fn from(val: Vec) -> Self { + FromOverInto(val) + } + } +} + fn main() {} diff --git a/tests/ui/from_over_into.rs b/tests/ui/from_over_into.rs index 74c7be6af79..d30f3c3fc92 100644 --- a/tests/ui/from_over_into.rs +++ b/tests/ui/from_over_into.rs @@ -1,5 +1,6 @@ // run-rustfix +#![feature(custom_inner_attributes)] #![warn(clippy::from_over_into)] #![allow(unused)] @@ -59,4 +60,28 @@ impl From for A { } } +fn msrv_1_40() { + #![clippy::msrv = "1.40"] + + struct FromOverInto(Vec); + + impl Into> for Vec { + fn into(self) -> FromOverInto { + FromOverInto(self) + } + } +} + +fn msrv_1_41() { + #![clippy::msrv = "1.41"] + + struct FromOverInto(Vec); + + impl Into> for Vec { + fn into(self) -> FromOverInto { + FromOverInto(self) + } + } +} + fn main() {} diff --git a/tests/ui/from_over_into.stderr b/tests/ui/from_over_into.stderr index 6cf83e25807..9c2a7c04c36 100644 --- a/tests/ui/from_over_into.stderr +++ b/tests/ui/from_over_into.stderr @@ -1,5 +1,5 @@ error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> $DIR/from_over_into.rs:9:1 + --> $DIR/from_over_into.rs:10:1 | LL | impl Into for String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL ~ StringWrapper(val) | error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> $DIR/from_over_into.rs:17:1 + --> $DIR/from_over_into.rs:18:1 | LL | impl Into for String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL ~ SelfType(String::new()) | error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> $DIR/from_over_into.rs:32:1 + --> $DIR/from_over_into.rs:33:1 | LL | impl Into for X { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL ~ let _: X = val; | error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> $DIR/from_over_into.rs:44:1 + --> $DIR/from_over_into.rs:45:1 | LL | impl core::convert::Into for crate::ExplicitPaths { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -58,5 +58,18 @@ LL ~ val.0 = false; LL ~ val.0 | -error: aborting due to 4 previous errors +error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true + --> $DIR/from_over_into.rs:80:5 + | +LL | impl Into> for Vec { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: replace the `Into` implentation with `From>` + | +LL ~ impl From> for FromOverInto { +LL ~ fn from(val: Vec) -> Self { +LL ~ FromOverInto(val) + | + +error: aborting due to 5 previous errors diff --git a/tests/ui/manual_clamp.rs b/tests/ui/manual_clamp.rs index 54fd888af99..331fd29b74e 100644 --- a/tests/ui/manual_clamp.rs +++ b/tests/ui/manual_clamp.rs @@ -1,3 +1,4 @@ +#![feature(custom_inner_attributes)] #![warn(clippy::manual_clamp)] #![allow( unused, @@ -302,3 +303,29 @@ fn dont_tell_me_what_to_do() { fn cmp_min_max(input: i32) -> i32 { input * 3 } + +fn msrv_1_49() { + #![clippy::msrv = "1.49"] + + let (input, min, max) = (0, -1, 2); + let _ = if input < min { + min + } else if input > max { + max + } else { + input + }; +} + +fn msrv_1_50() { + #![clippy::msrv = "1.50"] + + let (input, min, max) = (0, -1, 2); + let _ = if input < min { + min + } else if input > max { + max + } else { + input + }; +} diff --git a/tests/ui/manual_clamp.stderr b/tests/ui/manual_clamp.stderr index 0604f8606c3..70abe28091c 100644 --- a/tests/ui/manual_clamp.stderr +++ b/tests/ui/manual_clamp.stderr @@ -1,5 +1,5 @@ error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:76:5 + --> $DIR/manual_clamp.rs:77:5 | LL | / if x9 < min { LL | | x9 = min; @@ -13,7 +13,7 @@ LL | | } = note: `-D clippy::manual-clamp` implied by `-D warnings` error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:91:5 + --> $DIR/manual_clamp.rs:92:5 | LL | / if x11 > max { LL | | x11 = max; @@ -26,7 +26,7 @@ LL | | } = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:99:5 + --> $DIR/manual_clamp.rs:100:5 | LL | / if min > x12 { LL | | x12 = min; @@ -39,7 +39,7 @@ LL | | } = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:107:5 + --> $DIR/manual_clamp.rs:108:5 | LL | / if max < x13 { LL | | x13 = max; @@ -52,7 +52,7 @@ LL | | } = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:161:5 + --> $DIR/manual_clamp.rs:162:5 | LL | / if max < x33 { LL | | x33 = max; @@ -65,7 +65,7 @@ LL | | } = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:21:14 + --> $DIR/manual_clamp.rs:22:14 | LL | let x0 = if max < input { | ______________^ @@ -80,7 +80,7 @@ LL | | }; = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:29:14 + --> $DIR/manual_clamp.rs:30:14 | LL | let x1 = if input > max { | ______________^ @@ -95,7 +95,7 @@ LL | | }; = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:37:14 + --> $DIR/manual_clamp.rs:38:14 | LL | let x2 = if input < min { | ______________^ @@ -110,7 +110,7 @@ LL | | }; = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:45:14 + --> $DIR/manual_clamp.rs:46:14 | LL | let x3 = if min > input { | ______________^ @@ -125,7 +125,7 @@ LL | | }; = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:53:14 + --> $DIR/manual_clamp.rs:54:14 | LL | let x4 = input.max(min).min(max); | ^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(min, max)` @@ -133,7 +133,7 @@ LL | let x4 = input.max(min).min(max); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:55:14 + --> $DIR/manual_clamp.rs:56:14 | LL | let x5 = input.min(max).max(min); | ^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(min, max)` @@ -141,7 +141,7 @@ LL | let x5 = input.min(max).max(min); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:57:14 + --> $DIR/manual_clamp.rs:58:14 | LL | let x6 = match input { | ______________^ @@ -154,7 +154,7 @@ LL | | }; = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:63:14 + --> $DIR/manual_clamp.rs:64:14 | LL | let x7 = match input { | ______________^ @@ -167,7 +167,7 @@ LL | | }; = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:69:14 + --> $DIR/manual_clamp.rs:70:14 | LL | let x8 = match input { | ______________^ @@ -180,7 +180,7 @@ LL | | }; = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:83:15 + --> $DIR/manual_clamp.rs:84:15 | LL | let x10 = match input { | _______________^ @@ -193,7 +193,7 @@ LL | | }; = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:114:15 + --> $DIR/manual_clamp.rs:115:15 | LL | let x14 = if input > CONST_MAX { | _______________^ @@ -208,7 +208,7 @@ LL | | }; = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:123:19 + --> $DIR/manual_clamp.rs:124:19 | LL | let x15 = if input > max { | ___________________^ @@ -224,7 +224,7 @@ LL | | }; = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:134:19 + --> $DIR/manual_clamp.rs:135:19 | LL | let x16 = cmp_max(cmp_min(input, CONST_MAX), CONST_MIN); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -232,7 +232,7 @@ LL | let x16 = cmp_max(cmp_min(input, CONST_MAX), CONST_MIN); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:135:19 + --> $DIR/manual_clamp.rs:136:19 | LL | let x17 = cmp_min(cmp_max(input, CONST_MIN), CONST_MAX); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -240,7 +240,7 @@ LL | let x17 = cmp_min(cmp_max(input, CONST_MIN), CONST_MAX); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:136:19 + --> $DIR/manual_clamp.rs:137:19 | LL | let x18 = cmp_max(CONST_MIN, cmp_min(input, CONST_MAX)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -248,7 +248,7 @@ LL | let x18 = cmp_max(CONST_MIN, cmp_min(input, CONST_MAX)); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:137:19 + --> $DIR/manual_clamp.rs:138:19 | LL | let x19 = cmp_min(CONST_MAX, cmp_max(input, CONST_MIN)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -256,7 +256,7 @@ LL | let x19 = cmp_min(CONST_MAX, cmp_max(input, CONST_MIN)); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:138:19 + --> $DIR/manual_clamp.rs:139:19 | LL | let x20 = cmp_max(cmp_min(CONST_MAX, input), CONST_MIN); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -264,7 +264,7 @@ LL | let x20 = cmp_max(cmp_min(CONST_MAX, input), CONST_MIN); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:139:19 + --> $DIR/manual_clamp.rs:140:19 | LL | let x21 = cmp_min(cmp_max(CONST_MIN, input), CONST_MAX); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -272,7 +272,7 @@ LL | let x21 = cmp_min(cmp_max(CONST_MIN, input), CONST_MAX); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:140:19 + --> $DIR/manual_clamp.rs:141:19 | LL | let x22 = cmp_max(CONST_MIN, cmp_min(CONST_MAX, input)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -280,7 +280,7 @@ LL | let x22 = cmp_max(CONST_MIN, cmp_min(CONST_MAX, input)); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:141:19 + --> $DIR/manual_clamp.rs:142:19 | LL | let x23 = cmp_min(CONST_MAX, cmp_max(CONST_MIN, input)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -288,7 +288,7 @@ LL | let x23 = cmp_min(CONST_MAX, cmp_max(CONST_MIN, input)); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:143:19 + --> $DIR/manual_clamp.rs:144:19 | LL | let x24 = f64::max(f64::min(input, CONST_F64_MAX), CONST_F64_MIN); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)` @@ -297,7 +297,7 @@ LL | let x24 = f64::max(f64::min(input, CONST_F64_MAX), CONST_F64_MIN); = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:144:19 + --> $DIR/manual_clamp.rs:145:19 | LL | let x25 = f64::min(f64::max(input, CONST_F64_MIN), CONST_F64_MAX); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)` @@ -306,7 +306,7 @@ LL | let x25 = f64::min(f64::max(input, CONST_F64_MIN), CONST_F64_MAX); = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:145:19 + --> $DIR/manual_clamp.rs:146:19 | LL | let x26 = f64::max(CONST_F64_MIN, f64::min(input, CONST_F64_MAX)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)` @@ -315,7 +315,7 @@ LL | let x26 = f64::max(CONST_F64_MIN, f64::min(input, CONST_F64_MAX)); = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:146:19 + --> $DIR/manual_clamp.rs:147:19 | LL | let x27 = f64::min(CONST_F64_MAX, f64::max(input, CONST_F64_MIN)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)` @@ -324,7 +324,7 @@ LL | let x27 = f64::min(CONST_F64_MAX, f64::max(input, CONST_F64_MIN)); = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:147:19 + --> $DIR/manual_clamp.rs:148:19 | LL | let x28 = f64::max(f64::min(CONST_F64_MAX, input), CONST_F64_MIN); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)` @@ -333,7 +333,7 @@ LL | let x28 = f64::max(f64::min(CONST_F64_MAX, input), CONST_F64_MIN); = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:148:19 + --> $DIR/manual_clamp.rs:149:19 | LL | let x29 = f64::min(f64::max(CONST_F64_MIN, input), CONST_F64_MAX); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)` @@ -342,7 +342,7 @@ LL | let x29 = f64::min(f64::max(CONST_F64_MIN, input), CONST_F64_MAX); = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:149:19 + --> $DIR/manual_clamp.rs:150:19 | LL | let x30 = f64::max(CONST_F64_MIN, f64::min(CONST_F64_MAX, input)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)` @@ -351,7 +351,7 @@ LL | let x30 = f64::max(CONST_F64_MIN, f64::min(CONST_F64_MAX, input)); = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:150:19 + --> $DIR/manual_clamp.rs:151:19 | LL | let x31 = f64::min(CONST_F64_MAX, f64::max(CONST_F64_MIN, input)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)` @@ -360,7 +360,7 @@ LL | let x31 = f64::min(CONST_F64_MAX, f64::max(CONST_F64_MIN, input)); = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:153:5 + --> $DIR/manual_clamp.rs:154:5 | LL | / if x32 < min { LL | | x32 = min; @@ -371,5 +371,20 @@ LL | | } | = note: clamp will panic if max < min -error: aborting due to 34 previous errors +error: clamp-like pattern without using clamp function + --> $DIR/manual_clamp.rs:324:13 + | +LL | let _ = if input < min { + | _____________^ +LL | | min +LL | | } else if input > max { +LL | | max +LL | | } else { +LL | | input +LL | | }; + | |_____^ help: replace with clamp: `input.clamp(min, max)` + | + = note: clamp will panic if max < min + +error: aborting due to 35 previous errors diff --git a/tests/ui/manual_rem_euclid.fixed b/tests/ui/manual_rem_euclid.fixed index 5601c96c10b..b942fbfe930 100644 --- a/tests/ui/manual_rem_euclid.fixed +++ b/tests/ui/manual_rem_euclid.fixed @@ -1,6 +1,7 @@ // run-rustfix // aux-build:macro_rules.rs +#![feature(custom_inner_attributes)] #![warn(clippy::manual_rem_euclid)] #[macro_use] @@ -53,3 +54,32 @@ pub fn rem_euclid_4(num: i32) -> i32 { pub const fn const_rem_euclid_4(num: i32) -> i32 { num.rem_euclid(4) } + +pub fn msrv_1_37() { + #![clippy::msrv = "1.37"] + + let x: i32 = 10; + let _: i32 = ((x % 4) + 4) % 4; +} + +pub fn msrv_1_38() { + #![clippy::msrv = "1.38"] + + let x: i32 = 10; + let _: i32 = x.rem_euclid(4); +} + +// For const fns: +pub const fn msrv_1_51() { + #![clippy::msrv = "1.51"] + + let x: i32 = 10; + let _: i32 = ((x % 4) + 4) % 4; +} + +pub const fn msrv_1_52() { + #![clippy::msrv = "1.52"] + + let x: i32 = 10; + let _: i32 = x.rem_euclid(4); +} diff --git a/tests/ui/manual_rem_euclid.rs b/tests/ui/manual_rem_euclid.rs index 52135be26b7..7462d532169 100644 --- a/tests/ui/manual_rem_euclid.rs +++ b/tests/ui/manual_rem_euclid.rs @@ -1,6 +1,7 @@ // run-rustfix // aux-build:macro_rules.rs +#![feature(custom_inner_attributes)] #![warn(clippy::manual_rem_euclid)] #[macro_use] @@ -53,3 +54,32 @@ pub fn rem_euclid_4(num: i32) -> i32 { pub const fn const_rem_euclid_4(num: i32) -> i32 { ((num % 4) + 4) % 4 } + +pub fn msrv_1_37() { + #![clippy::msrv = "1.37"] + + let x: i32 = 10; + let _: i32 = ((x % 4) + 4) % 4; +} + +pub fn msrv_1_38() { + #![clippy::msrv = "1.38"] + + let x: i32 = 10; + let _: i32 = ((x % 4) + 4) % 4; +} + +// For const fns: +pub const fn msrv_1_51() { + #![clippy::msrv = "1.51"] + + let x: i32 = 10; + let _: i32 = ((x % 4) + 4) % 4; +} + +pub const fn msrv_1_52() { + #![clippy::msrv = "1.52"] + + let x: i32 = 10; + let _: i32 = ((x % 4) + 4) % 4; +} diff --git a/tests/ui/manual_rem_euclid.stderr b/tests/ui/manual_rem_euclid.stderr index a237fd0213c..d51bac03b56 100644 --- a/tests/ui/manual_rem_euclid.stderr +++ b/tests/ui/manual_rem_euclid.stderr @@ -1,5 +1,5 @@ error: manual `rem_euclid` implementation - --> $DIR/manual_rem_euclid.rs:19:18 + --> $DIR/manual_rem_euclid.rs:20:18 | LL | let _: i32 = ((value % 4) + 4) % 4; | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)` @@ -7,31 +7,31 @@ LL | let _: i32 = ((value % 4) + 4) % 4; = note: `-D clippy::manual-rem-euclid` implied by `-D warnings` error: manual `rem_euclid` implementation - --> $DIR/manual_rem_euclid.rs:20:18 + --> $DIR/manual_rem_euclid.rs:21:18 | LL | let _: i32 = (4 + (value % 4)) % 4; | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)` error: manual `rem_euclid` implementation - --> $DIR/manual_rem_euclid.rs:21:18 + --> $DIR/manual_rem_euclid.rs:22:18 | LL | let _: i32 = (value % 4 + 4) % 4; | ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)` error: manual `rem_euclid` implementation - --> $DIR/manual_rem_euclid.rs:22:18 + --> $DIR/manual_rem_euclid.rs:23:18 | LL | let _: i32 = (4 + value % 4) % 4; | ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)` error: manual `rem_euclid` implementation - --> $DIR/manual_rem_euclid.rs:23:22 + --> $DIR/manual_rem_euclid.rs:24:22 | LL | let _: i32 = 1 + (4 + value % 4) % 4; | ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)` error: manual `rem_euclid` implementation - --> $DIR/manual_rem_euclid.rs:12:22 + --> $DIR/manual_rem_euclid.rs:13:22 | LL | let _: i32 = ((value % 4) + 4) % 4; | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)` @@ -42,16 +42,28 @@ LL | internal_rem_euclid!(); = note: this error originates in the macro `internal_rem_euclid` (in Nightly builds, run with -Z macro-backtrace for more info) error: manual `rem_euclid` implementation - --> $DIR/manual_rem_euclid.rs:49:5 + --> $DIR/manual_rem_euclid.rs:50:5 | LL | ((num % 4) + 4) % 4 | ^^^^^^^^^^^^^^^^^^^ help: consider using: `num.rem_euclid(4)` error: manual `rem_euclid` implementation - --> $DIR/manual_rem_euclid.rs:54:5 + --> $DIR/manual_rem_euclid.rs:55:5 | LL | ((num % 4) + 4) % 4 | ^^^^^^^^^^^^^^^^^^^ help: consider using: `num.rem_euclid(4)` -error: aborting due to 8 previous errors +error: manual `rem_euclid` implementation + --> $DIR/manual_rem_euclid.rs:69:18 + | +LL | let _: i32 = ((x % 4) + 4) % 4; + | ^^^^^^^^^^^^^^^^^ help: consider using: `x.rem_euclid(4)` + +error: manual `rem_euclid` implementation + --> $DIR/manual_rem_euclid.rs:84:18 + | +LL | let _: i32 = ((x % 4) + 4) % 4; + | ^^^^^^^^^^^^^^^^^ help: consider using: `x.rem_euclid(4)` + +error: aborting due to 10 previous errors diff --git a/tests/ui/manual_strip.rs b/tests/ui/manual_strip.rs index cbb84eb5c7e..85009d78558 100644 --- a/tests/ui/manual_strip.rs +++ b/tests/ui/manual_strip.rs @@ -1,3 +1,4 @@ +#![feature(custom_inner_attributes)] #![warn(clippy::manual_strip)] fn main() { @@ -64,3 +65,21 @@ fn main() { s4[2..].to_string(); } } + +fn msrv_1_44() { + #![clippy::msrv = "1.44"] + + let s = "abc"; + if s.starts_with('a') { + s[1..].to_string(); + } +} + +fn msrv_1_45() { + #![clippy::msrv = "1.45"] + + let s = "abc"; + if s.starts_with('a') { + s[1..].to_string(); + } +} diff --git a/tests/ui/manual_strip.stderr b/tests/ui/manual_strip.stderr index 2191ccb85dd..ad2a362f3e7 100644 --- a/tests/ui/manual_strip.stderr +++ b/tests/ui/manual_strip.stderr @@ -1,11 +1,11 @@ error: stripping a prefix manually - --> $DIR/manual_strip.rs:7:24 + --> $DIR/manual_strip.rs:8:24 | LL | str::to_string(&s["ab".len()..]); | ^^^^^^^^^^^^^^^^ | note: the prefix was tested here - --> $DIR/manual_strip.rs:6:5 + --> $DIR/manual_strip.rs:7:5 | LL | if s.starts_with("ab") { | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -21,13 +21,13 @@ LL ~ .to_string(); | error: stripping a suffix manually - --> $DIR/manual_strip.rs:15:24 + --> $DIR/manual_strip.rs:16:24 | LL | str::to_string(&s[..s.len() - "bc".len()]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the suffix was tested here - --> $DIR/manual_strip.rs:14:5 + --> $DIR/manual_strip.rs:15:5 | LL | if s.ends_with("bc") { | ^^^^^^^^^^^^^^^^^^^^^ @@ -42,13 +42,13 @@ LL ~ .to_string(); | error: stripping a prefix manually - --> $DIR/manual_strip.rs:24:24 + --> $DIR/manual_strip.rs:25:24 | LL | str::to_string(&s[1..]); | ^^^^^^^ | note: the prefix was tested here - --> $DIR/manual_strip.rs:23:5 + --> $DIR/manual_strip.rs:24:5 | LL | if s.starts_with('a') { | ^^^^^^^^^^^^^^^^^^^^^^ @@ -60,13 +60,13 @@ LL ~ .to_string(); | error: stripping a prefix manually - --> $DIR/manual_strip.rs:31:24 + --> $DIR/manual_strip.rs:32:24 | LL | str::to_string(&s[prefix.len()..]); | ^^^^^^^^^^^^^^^^^^ | note: the prefix was tested here - --> $DIR/manual_strip.rs:30:5 + --> $DIR/manual_strip.rs:31:5 | LL | if s.starts_with(prefix) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -77,13 +77,13 @@ LL ~ str::to_string(); | error: stripping a prefix manually - --> $DIR/manual_strip.rs:37:24 + --> $DIR/manual_strip.rs:38:24 | LL | str::to_string(&s[PREFIX.len()..]); | ^^^^^^^^^^^^^^^^^^ | note: the prefix was tested here - --> $DIR/manual_strip.rs:36:5 + --> $DIR/manual_strip.rs:37:5 | LL | if s.starts_with(PREFIX) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -95,13 +95,13 @@ LL ~ str::to_string(); | error: stripping a prefix manually - --> $DIR/manual_strip.rs:44:24 + --> $DIR/manual_strip.rs:45:24 | LL | str::to_string(&TARGET[prefix.len()..]); | ^^^^^^^^^^^^^^^^^^^^^^^ | note: the prefix was tested here - --> $DIR/manual_strip.rs:43:5 + --> $DIR/manual_strip.rs:44:5 | LL | if TARGET.starts_with(prefix) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -112,13 +112,13 @@ LL ~ str::to_string(); | error: stripping a prefix manually - --> $DIR/manual_strip.rs:50:9 + --> $DIR/manual_strip.rs:51:9 | LL | s1[2..].to_uppercase(); | ^^^^^^^ | note: the prefix was tested here - --> $DIR/manual_strip.rs:49:5 + --> $DIR/manual_strip.rs:50:5 | LL | if s1.starts_with("ab") { | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -128,5 +128,22 @@ LL ~ if let Some() = s1.strip_prefix("ab") { LL ~ .to_uppercase(); | -error: aborting due to 7 previous errors +error: stripping a prefix manually + --> $DIR/manual_strip.rs:83:9 + | +LL | s[1..].to_string(); + | ^^^^^^ + | +note: the prefix was tested here + --> $DIR/manual_strip.rs:82:5 + | +LL | if s.starts_with('a') { + | ^^^^^^^^^^^^^^^^^^^^^^ +help: try using the `strip_prefix` method + | +LL ~ if let Some() = s.strip_prefix('a') { +LL ~ .to_string(); + | + +error: aborting due to 8 previous errors diff --git a/tests/ui/map_unwrap_or.rs b/tests/ui/map_unwrap_or.rs index 5429fb4e454..396b22a9abb 100644 --- a/tests/ui/map_unwrap_or.rs +++ b/tests/ui/map_unwrap_or.rs @@ -1,6 +1,8 @@ // aux-build:option_helpers.rs + +#![feature(custom_inner_attributes)] #![warn(clippy::map_unwrap_or)] -#![allow(clippy::uninlined_format_args)] +#![allow(clippy::uninlined_format_args, clippy::unnecessary_lazy_evaluations)] #[macro_use] extern crate option_helpers; @@ -79,3 +81,19 @@ fn main() { option_methods(); result_methods(); } + +fn msrv_1_40() { + #![clippy::msrv = "1.40"] + + let res: Result = Ok(1); + + let _ = res.map(|x| x + 1).unwrap_or_else(|_e| 0); +} + +fn msrv_1_41() { + #![clippy::msrv = "1.41"] + + let res: Result = Ok(1); + + let _ = res.map(|x| x + 1).unwrap_or_else(|_e| 0); +} diff --git a/tests/ui/map_unwrap_or.stderr b/tests/ui/map_unwrap_or.stderr index abc9c1ece32..d17d24a403e 100644 --- a/tests/ui/map_unwrap_or.stderr +++ b/tests/ui/map_unwrap_or.stderr @@ -1,5 +1,5 @@ error: called `map().unwrap_or()` on an `Option` value. This can be done more directly by calling `map_or(, )` instead - --> $DIR/map_unwrap_or.rs:16:13 + --> $DIR/map_unwrap_or.rs:18:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -15,7 +15,7 @@ LL + let _ = opt.map_or(0, |x| x + 1); | error: called `map().unwrap_or()` on an `Option` value. This can be done more directly by calling `map_or(, )` instead - --> $DIR/map_unwrap_or.rs:20:13 + --> $DIR/map_unwrap_or.rs:22:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -33,7 +33,7 @@ LL ~ ); | error: called `map().unwrap_or()` on an `Option` value. This can be done more directly by calling `map_or(, )` instead - --> $DIR/map_unwrap_or.rs:24:13 + --> $DIR/map_unwrap_or.rs:26:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -50,7 +50,7 @@ LL ~ }, |x| x + 1); | error: called `map().unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then()` instead - --> $DIR/map_unwrap_or.rs:29:13 + --> $DIR/map_unwrap_or.rs:31:13 | LL | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -62,7 +62,7 @@ LL + let _ = opt.and_then(|x| Some(x + 1)); | error: called `map().unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then()` instead - --> $DIR/map_unwrap_or.rs:31:13 + --> $DIR/map_unwrap_or.rs:33:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -80,7 +80,7 @@ LL ~ ); | error: called `map().unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then()` instead - --> $DIR/map_unwrap_or.rs:35:13 + --> $DIR/map_unwrap_or.rs:37:13 | LL | let _ = opt | _____________^ @@ -95,7 +95,7 @@ LL + .and_then(|x| Some(x + 1)); | error: called `map().unwrap_or()` on an `Option` value. This can be done more directly by calling `map_or(, )` instead - --> $DIR/map_unwrap_or.rs:46:13 + --> $DIR/map_unwrap_or.rs:48:13 | LL | let _ = Some("prefix").map(|p| format!("{}.", p)).unwrap_or(id); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -107,7 +107,7 @@ LL + let _ = Some("prefix").map_or(id, |p| format!("{}.", p)); | error: called `map().unwrap_or_else()` on an `Option` value. This can be done more directly by calling `map_or_else(, )` instead - --> $DIR/map_unwrap_or.rs:50:13 + --> $DIR/map_unwrap_or.rs:52:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -117,7 +117,7 @@ LL | | ).unwrap_or_else(|| 0); | |__________________________^ error: called `map().unwrap_or_else()` on an `Option` value. This can be done more directly by calling `map_or_else(, )` instead - --> $DIR/map_unwrap_or.rs:54:13 + --> $DIR/map_unwrap_or.rs:56:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -127,7 +127,7 @@ LL | | ); | |_________^ error: called `map().unwrap_or_else()` on a `Result` value. This can be done more directly by calling `.map_or_else(, )` instead - --> $DIR/map_unwrap_or.rs:66:13 + --> $DIR/map_unwrap_or.rs:68:13 | LL | let _ = res.map(|x| { | _____________^ @@ -137,7 +137,7 @@ LL | | ).unwrap_or_else(|_e| 0); | |____________________________^ error: called `map().unwrap_or_else()` on a `Result` value. This can be done more directly by calling `.map_or_else(, )` instead - --> $DIR/map_unwrap_or.rs:70:13 + --> $DIR/map_unwrap_or.rs:72:13 | LL | let _ = res.map(|x| x + 1) | _____________^ @@ -146,5 +146,11 @@ LL | | 0 LL | | }); | |__________^ -error: aborting due to 11 previous errors +error: called `map().unwrap_or_else()` on a `Result` value. This can be done more directly by calling `.map_or_else(, )` instead + --> $DIR/map_unwrap_or.rs:98:13 + | +LL | let _ = res.map(|x| x + 1).unwrap_or_else(|_e| 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `res.map_or_else(|_e| 0, |x| x + 1)` + +error: aborting due to 12 previous errors diff --git a/tests/ui/match_expr_like_matches_macro.fixed b/tests/ui/match_expr_like_matches_macro.fixed index 95ca571d07b..2498007694c 100644 --- a/tests/ui/match_expr_like_matches_macro.fixed +++ b/tests/ui/match_expr_like_matches_macro.fixed @@ -1,5 +1,6 @@ // run-rustfix +#![feature(custom_inner_attributes)] #![warn(clippy::match_like_matches_macro)] #![allow(unreachable_patterns, dead_code, clippy::equatable_if_let)] @@ -193,3 +194,18 @@ fn main() { _ => false, }; } + +fn msrv_1_41() { + #![clippy::msrv = "1.41"] + + let _y = match Some(5) { + Some(0) => true, + _ => false, + }; +} + +fn msrv_1_42() { + #![clippy::msrv = "1.42"] + + let _y = matches!(Some(5), Some(0)); +} diff --git a/tests/ui/match_expr_like_matches_macro.rs b/tests/ui/match_expr_like_matches_macro.rs index 3b9c8cadadc..b4e48499bd0 100644 --- a/tests/ui/match_expr_like_matches_macro.rs +++ b/tests/ui/match_expr_like_matches_macro.rs @@ -1,5 +1,6 @@ // run-rustfix +#![feature(custom_inner_attributes)] #![warn(clippy::match_like_matches_macro)] #![allow(unreachable_patterns, dead_code, clippy::equatable_if_let)] @@ -234,3 +235,21 @@ fn main() { _ => false, }; } + +fn msrv_1_41() { + #![clippy::msrv = "1.41"] + + let _y = match Some(5) { + Some(0) => true, + _ => false, + }; +} + +fn msrv_1_42() { + #![clippy::msrv = "1.42"] + + let _y = match Some(5) { + Some(0) => true, + _ => false, + }; +} diff --git a/tests/ui/match_expr_like_matches_macro.stderr b/tests/ui/match_expr_like_matches_macro.stderr index e94555e2744..f1d1c23aeb0 100644 --- a/tests/ui/match_expr_like_matches_macro.stderr +++ b/tests/ui/match_expr_like_matches_macro.stderr @@ -1,5 +1,5 @@ error: match expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:10:14 + --> $DIR/match_expr_like_matches_macro.rs:11:14 | LL | let _y = match x { | ______________^ @@ -11,7 +11,7 @@ LL | | }; = note: `-D clippy::match-like-matches-macro` implied by `-D warnings` error: match expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:16:14 + --> $DIR/match_expr_like_matches_macro.rs:17:14 | LL | let _w = match x { | ______________^ @@ -21,7 +21,7 @@ LL | | }; | |_____^ help: try this: `matches!(x, Some(_))` error: redundant pattern matching, consider using `is_none()` - --> $DIR/match_expr_like_matches_macro.rs:22:14 + --> $DIR/match_expr_like_matches_macro.rs:23:14 | LL | let _z = match x { | ______________^ @@ -33,7 +33,7 @@ LL | | }; = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` error: match expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:28:15 + --> $DIR/match_expr_like_matches_macro.rs:29:15 | LL | let _zz = match x { | _______________^ @@ -43,13 +43,13 @@ LL | | }; | |_____^ help: try this: `!matches!(x, Some(r) if r == 0)` error: if let .. else expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:34:16 + --> $DIR/match_expr_like_matches_macro.rs:35:16 | LL | let _zzz = if let Some(5) = x { true } else { false }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `matches!(x, Some(5))` error: match expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:58:20 + --> $DIR/match_expr_like_matches_macro.rs:59:20 | LL | let _ans = match x { | ____________________^ @@ -60,7 +60,7 @@ LL | | }; | |_________^ help: try this: `matches!(x, E::A(_) | E::B(_))` error: match expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:68:20 + --> $DIR/match_expr_like_matches_macro.rs:69:20 | LL | let _ans = match x { | ____________________^ @@ -73,7 +73,7 @@ LL | | }; | |_________^ help: try this: `matches!(x, E::A(_) | E::B(_))` error: match expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:78:20 + --> $DIR/match_expr_like_matches_macro.rs:79:20 | LL | let _ans = match x { | ____________________^ @@ -84,7 +84,7 @@ LL | | }; | |_________^ help: try this: `!matches!(x, E::B(_) | E::C)` error: match expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:138:18 + --> $DIR/match_expr_like_matches_macro.rs:139:18 | LL | let _z = match &z { | __________________^ @@ -94,7 +94,7 @@ LL | | }; | |_________^ help: try this: `matches!(z, Some(3))` error: match expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:147:18 + --> $DIR/match_expr_like_matches_macro.rs:148:18 | LL | let _z = match &z { | __________________^ @@ -104,7 +104,7 @@ LL | | }; | |_________^ help: try this: `matches!(&z, Some(3))` error: match expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:164:21 + --> $DIR/match_expr_like_matches_macro.rs:165:21 | LL | let _ = match &z { | _____________________^ @@ -114,7 +114,7 @@ LL | | }; | |_____________^ help: try this: `matches!(&z, AnEnum::X)` error: match expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:178:20 + --> $DIR/match_expr_like_matches_macro.rs:179:20 | LL | let _res = match &val { | ____________________^ @@ -124,7 +124,7 @@ LL | | }; | |_________^ help: try this: `matches!(&val, &Some(ref _a))` error: match expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:190:20 + --> $DIR/match_expr_like_matches_macro.rs:191:20 | LL | let _res = match &val { | ____________________^ @@ -133,5 +133,15 @@ LL | | _ => false, LL | | }; | |_________^ help: try this: `matches!(&val, &Some(ref _a))` -error: aborting due to 13 previous errors +error: match expression looks like `matches!` macro + --> $DIR/match_expr_like_matches_macro.rs:251:14 + | +LL | let _y = match Some(5) { + | ______________^ +LL | | Some(0) => true, +LL | | _ => false, +LL | | }; + | |_____^ help: try this: `matches!(Some(5), Some(0))` + +error: aborting due to 14 previous errors diff --git a/tests/ui/mem_replace.fixed b/tests/ui/mem_replace.fixed index b609ba65946..ae237395b95 100644 --- a/tests/ui/mem_replace.fixed +++ b/tests/ui/mem_replace.fixed @@ -1,5 +1,7 @@ // run-rustfix -#![allow(unused_imports)] + +#![feature(custom_inner_attributes)] +#![allow(unused)] #![warn( clippy::all, clippy::style, @@ -77,3 +79,17 @@ fn main() { replace_with_default(); dont_lint_primitive(); } + +fn msrv_1_39() { + #![clippy::msrv = "1.39"] + + let mut s = String::from("foo"); + let _ = std::mem::replace(&mut s, String::default()); +} + +fn msrv_1_40() { + #![clippy::msrv = "1.40"] + + let mut s = String::from("foo"); + let _ = std::mem::take(&mut s); +} diff --git a/tests/ui/mem_replace.rs b/tests/ui/mem_replace.rs index 93f6dcdec83..3202e99e0be 100644 --- a/tests/ui/mem_replace.rs +++ b/tests/ui/mem_replace.rs @@ -1,5 +1,7 @@ // run-rustfix -#![allow(unused_imports)] + +#![feature(custom_inner_attributes)] +#![allow(unused)] #![warn( clippy::all, clippy::style, @@ -77,3 +79,17 @@ fn main() { replace_with_default(); dont_lint_primitive(); } + +fn msrv_1_39() { + #![clippy::msrv = "1.39"] + + let mut s = String::from("foo"); + let _ = std::mem::replace(&mut s, String::default()); +} + +fn msrv_1_40() { + #![clippy::msrv = "1.40"] + + let mut s = String::from("foo"); + let _ = std::mem::replace(&mut s, String::default()); +} diff --git a/tests/ui/mem_replace.stderr b/tests/ui/mem_replace.stderr index 90dc6c95f85..dd8a50dab90 100644 --- a/tests/ui/mem_replace.stderr +++ b/tests/ui/mem_replace.stderr @@ -1,5 +1,5 @@ error: replacing an `Option` with `None` - --> $DIR/mem_replace.rs:15:13 + --> $DIR/mem_replace.rs:17:13 | LL | let _ = mem::replace(&mut an_option, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()` @@ -7,13 +7,13 @@ LL | let _ = mem::replace(&mut an_option, None); = note: `-D clippy::mem-replace-option-with-none` implied by `-D warnings` error: replacing an `Option` with `None` - --> $DIR/mem_replace.rs:17:13 + --> $DIR/mem_replace.rs:19:13 | LL | let _ = mem::replace(an_option, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:22:13 + --> $DIR/mem_replace.rs:24:13 | LL | let _ = std::mem::replace(&mut s, String::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut s)` @@ -21,100 +21,106 @@ LL | let _ = std::mem::replace(&mut s, String::default()); = note: `-D clippy::mem-replace-with-default` implied by `-D warnings` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:25:13 + --> $DIR/mem_replace.rs:27:13 | LL | let _ = std::mem::replace(s, String::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(s)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:26:13 + --> $DIR/mem_replace.rs:28:13 | LL | let _ = std::mem::replace(s, Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(s)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:29:13 + --> $DIR/mem_replace.rs:31:13 | LL | let _ = std::mem::replace(&mut v, Vec::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:30:13 + --> $DIR/mem_replace.rs:32:13 | LL | let _ = std::mem::replace(&mut v, Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:31:13 + --> $DIR/mem_replace.rs:33:13 | LL | let _ = std::mem::replace(&mut v, Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:32:13 + --> $DIR/mem_replace.rs:34:13 | LL | let _ = std::mem::replace(&mut v, vec![]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:35:13 + --> $DIR/mem_replace.rs:37:13 | LL | let _ = std::mem::replace(&mut hash_map, HashMap::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut hash_map)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:38:13 + --> $DIR/mem_replace.rs:40:13 | LL | let _ = std::mem::replace(&mut btree_map, BTreeMap::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut btree_map)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:41:13 + --> $DIR/mem_replace.rs:43:13 | LL | let _ = std::mem::replace(&mut vd, VecDeque::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut vd)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:44:13 + --> $DIR/mem_replace.rs:46:13 | LL | let _ = std::mem::replace(&mut hash_set, HashSet::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut hash_set)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:47:13 + --> $DIR/mem_replace.rs:49:13 | LL | let _ = std::mem::replace(&mut btree_set, BTreeSet::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut btree_set)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:50:13 + --> $DIR/mem_replace.rs:52:13 | LL | let _ = std::mem::replace(&mut list, LinkedList::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut list)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:53:13 + --> $DIR/mem_replace.rs:55:13 | LL | let _ = std::mem::replace(&mut binary_heap, BinaryHeap::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut binary_heap)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:56:13 + --> $DIR/mem_replace.rs:58:13 | LL | let _ = std::mem::replace(&mut tuple, (vec![], BinaryHeap::new())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut tuple)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:59:13 + --> $DIR/mem_replace.rs:61:13 | LL | let _ = std::mem::replace(&mut refstr, ""); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut refstr)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:62:13 + --> $DIR/mem_replace.rs:64:13 | LL | let _ = std::mem::replace(&mut slice, &[]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut slice)` -error: aborting due to 19 previous errors +error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` + --> $DIR/mem_replace.rs:94:13 + | +LL | let _ = std::mem::replace(&mut s, String::default()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut s)` + +error: aborting due to 20 previous errors diff --git a/tests/ui/min_rust_version_attr.rs b/tests/ui/min_rust_version_attr.rs index c4c6391bb4c..cd148063bf0 100644 --- a/tests/ui/min_rust_version_attr.rs +++ b/tests/ui/min_rust_version_attr.rs @@ -1,240 +1,29 @@ #![allow(clippy::redundant_clone)] #![feature(custom_inner_attributes)] -#![clippy::msrv = "1.0.0"] -use std::ops::{Deref, RangeFrom}; +fn main() {} -fn approx_const() { +fn just_under_msrv() { + #![clippy::msrv = "1.42.0"] let log2_10 = 3.321928094887362; - let log10_2 = 0.301029995663981; } -fn cloned_instead_of_copied() { - let _ = [1].iter().cloned(); -} - -fn option_as_ref_deref() { - let mut opt = Some(String::from("123")); - - let _ = opt.as_ref().map(String::as_str); - let _ = opt.as_ref().map(|x| x.as_str()); - let _ = opt.as_mut().map(String::as_mut_str); - let _ = opt.as_mut().map(|x| x.as_mut_str()); -} - -fn match_like_matches() { - let _y = match Some(5) { - Some(0) => true, - _ => false, - }; -} - -fn match_same_arms() { - match (1, 2, 3) { - (1, .., 3) => 42, - (.., 3) => 42, //~ ERROR match arms have same body - _ => 0, - }; -} - -fn match_same_arms2() { - let _ = match Some(42) { - Some(_) => 24, - None => 24, //~ ERROR match arms have same body - }; -} - -pub fn manual_strip_msrv() { - let s = "hello, world!"; - if s.starts_with("hello, ") { - assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!"); - } -} - -pub fn redundant_fieldnames() { - let start = 0; - let _ = RangeFrom { start: start }; -} - -pub fn redundant_static_lifetime() { - const VAR_ONE: &'static str = "Test constant #1"; -} - -pub fn checked_conversion() { - let value: i64 = 42; - let _ = value <= (u32::max_value() as i64) && value >= 0; - let _ = value <= (u32::MAX as i64) && value >= 0; -} - -pub struct FromOverInto(String); - -impl Into for String { - fn into(self) -> FromOverInto { - FromOverInto(self) - } -} - -pub fn filter_map_next() { - let a = ["1", "lol", "3", "NaN", "5"]; - - #[rustfmt::skip] - let _: Option = vec![1, 2, 3, 4, 5, 6] - .into_iter() - .filter_map(|x| { - if x == 2 { - Some(x * 2) - } else { - None - } - }) - .next(); -} - -#[allow(clippy::no_effect)] -#[allow(clippy::short_circuit_statement)] -#[allow(clippy::unnecessary_operation)] -pub fn manual_range_contains() { - let x = 5; - x >= 8 && x < 12; -} - -pub fn use_self() { - struct Foo; - - impl Foo { - fn new() -> Foo { - Foo {} - } - fn test() -> Foo { - Foo::new() - } - } -} - -fn replace_with_default() { - let mut s = String::from("foo"); - let _ = std::mem::replace(&mut s, String::default()); -} - -fn map_unwrap_or() { - let opt = Some(1); - - // Check for `option.map(_).unwrap_or(_)` use. - // Single line case. - let _ = opt - .map(|x| x + 1) - // Should lint even though this call is on a separate line. - .unwrap_or(0); -} - -// Could be const -fn missing_const_for_fn() -> i32 { - 1 -} - -fn unnest_or_patterns() { - struct TS(u8, u8); - if let TS(0, x) | TS(1, x) = TS(0, 0) {} -} - -#[cfg_attr(rustfmt, rustfmt_skip)] -fn deprecated_cfg_attr() {} - -#[warn(clippy::cast_lossless)] -fn int_from_bool() -> u8 { - true as u8 -} - -fn err_expect() { - let x: Result = Ok(10); - x.err().expect("Testing expect_err"); -} - -fn cast_abs_to_unsigned() { - let x: i32 = 10; - assert_eq!(10u32, x.abs() as u32); -} - -fn manual_rem_euclid() { - let x: i32 = 10; - let _: i32 = ((x % 4) + 4) % 4; -} - -fn manual_clamp() { - let (input, min, max) = (0, -1, 2); - let _ = if input < min { - min - } else if input > max { - max - } else { - input - }; -} - -fn main() { - filter_map_next(); - checked_conversion(); - redundant_fieldnames(); - redundant_static_lifetime(); - option_as_ref_deref(); - match_like_matches(); - match_same_arms(); - match_same_arms2(); - manual_strip_msrv(); - manual_range_contains(); - use_self(); - replace_with_default(); - map_unwrap_or(); - missing_const_for_fn(); - unnest_or_patterns(); - int_from_bool(); - err_expect(); - cast_abs_to_unsigned(); - manual_rem_euclid(); - manual_clamp(); +fn meets_msrv() { + #![clippy::msrv = "1.43.0"] + let log2_10 = 3.321928094887362; } -mod just_under_msrv { - #![feature(custom_inner_attributes)] +fn just_above_msrv() { #![clippy::msrv = "1.44.0"] - - fn main() { - let s = "hello, world!"; - if s.starts_with("hello, ") { - assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!"); - } - } -} - -mod meets_msrv { - #![feature(custom_inner_attributes)] - #![clippy::msrv = "1.45.0"] - - fn main() { - let s = "hello, world!"; - if s.starts_with("hello, ") { - assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!"); - } - } + let log2_10 = 3.321928094887362; } -mod just_above_msrv { - #![feature(custom_inner_attributes)] - #![clippy::msrv = "1.46.0"] - - fn main() { - let s = "hello, world!"; - if s.starts_with("hello, ") { - assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!"); - } - } +fn no_patch_under() { + #![clippy::msrv = "1.42"] + let log2_10 = 3.321928094887362; } -mod const_rem_euclid { - #![feature(custom_inner_attributes)] - #![clippy::msrv = "1.50.0"] - - pub const fn const_rem_euclid_4(num: i32) -> i32 { - ((num % 4) + 4) % 4 - } +fn no_patch_meets() { + #![clippy::msrv = "1.43"] + let log2_10 = 3.321928094887362; } diff --git a/tests/ui/min_rust_version_attr.stderr b/tests/ui/min_rust_version_attr.stderr index d1cffc26a83..68aa5874819 100644 --- a/tests/ui/min_rust_version_attr.stderr +++ b/tests/ui/min_rust_version_attr.stderr @@ -1,37 +1,27 @@ -error: stripping a prefix manually - --> $DIR/min_rust_version_attr.rs:216:24 +error: approximate value of `f{32, 64}::consts::LOG2_10` found + --> $DIR/min_rust_version_attr.rs:13:19 | -LL | assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!"); - | ^^^^^^^^^^^^^^^^^^^^ - | -note: the prefix was tested here - --> $DIR/min_rust_version_attr.rs:215:9 - | -LL | if s.starts_with("hello, ") { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: `-D clippy::manual-strip` implied by `-D warnings` -help: try using the `strip_prefix` method - | -LL ~ if let Some() = s.strip_prefix("hello, ") { -LL ~ assert_eq!(.to_uppercase(), "WORLD!"); +LL | let log2_10 = 3.321928094887362; + | ^^^^^^^^^^^^^^^^^ | + = help: consider using the constant directly + = note: `#[deny(clippy::approx_constant)]` on by default -error: stripping a prefix manually - --> $DIR/min_rust_version_attr.rs:228:24 +error: approximate value of `f{32, 64}::consts::LOG2_10` found + --> $DIR/min_rust_version_attr.rs:18:19 | -LL | assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!"); - | ^^^^^^^^^^^^^^^^^^^^ +LL | let log2_10 = 3.321928094887362; + | ^^^^^^^^^^^^^^^^^ | -note: the prefix was tested here - --> $DIR/min_rust_version_attr.rs:227:9 - | -LL | if s.starts_with("hello, ") { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: try using the `strip_prefix` method + = help: consider using the constant directly + +error: approximate value of `f{32, 64}::consts::LOG2_10` found + --> $DIR/min_rust_version_attr.rs:28:19 | -LL ~ if let Some() = s.strip_prefix("hello, ") { -LL ~ assert_eq!(.to_uppercase(), "WORLD!"); +LL | let log2_10 = 3.321928094887362; + | ^^^^^^^^^^^^^^^^^ | + = help: consider using the constant directly -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/min_rust_version_invalid_attr.rs b/tests/ui/min_rust_version_invalid_attr.rs index f20841891a7..02892f329af 100644 --- a/tests/ui/min_rust_version_invalid_attr.rs +++ b/tests/ui/min_rust_version_invalid_attr.rs @@ -2,3 +2,17 @@ #![clippy::msrv = "invalid.version"] fn main() {} + +#[clippy::msrv = "invalid.version"] +fn outer_attr() {} + +mod multiple { + #![clippy::msrv = "1.40"] + #![clippy::msrv = "=1.35.0"] + #![clippy::msrv = "1.10.1"] + + mod foo { + #![clippy::msrv = "1"] + #![clippy::msrv = "1.0.0"] + } +} diff --git a/tests/ui/min_rust_version_invalid_attr.stderr b/tests/ui/min_rust_version_invalid_attr.stderr index 6ff88ca56f8..93370a0fa9c 100644 --- a/tests/ui/min_rust_version_invalid_attr.stderr +++ b/tests/ui/min_rust_version_invalid_attr.stderr @@ -4,5 +4,47 @@ error: `invalid.version` is not a valid Rust version LL | #![clippy::msrv = "invalid.version"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: `msrv` cannot be an outer attribute + --> $DIR/min_rust_version_invalid_attr.rs:6:1 + | +LL | #[clippy::msrv = "invalid.version"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `msrv` is defined multiple times + --> $DIR/min_rust_version_invalid_attr.rs:11:5 + | +LL | #![clippy::msrv = "=1.35.0"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first definition found here + --> $DIR/min_rust_version_invalid_attr.rs:10:5 + | +LL | #![clippy::msrv = "1.40"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `msrv` is defined multiple times + --> $DIR/min_rust_version_invalid_attr.rs:12:5 + | +LL | #![clippy::msrv = "1.10.1"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first definition found here + --> $DIR/min_rust_version_invalid_attr.rs:10:5 + | +LL | #![clippy::msrv = "1.40"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `msrv` is defined multiple times + --> $DIR/min_rust_version_invalid_attr.rs:16:9 + | +LL | #![clippy::msrv = "1.0.0"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first definition found here + --> $DIR/min_rust_version_invalid_attr.rs:15:9 + | +LL | #![clippy::msrv = "1"] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors diff --git a/tests/ui/min_rust_version_multiple_inner_attr.rs b/tests/ui/min_rust_version_multiple_inner_attr.rs deleted file mode 100644 index e882d5ccf91..00000000000 --- a/tests/ui/min_rust_version_multiple_inner_attr.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![feature(custom_inner_attributes)] -#![clippy::msrv = "1.40"] -#![clippy::msrv = "=1.35.0"] -#![clippy::msrv = "1.10.1"] - -mod foo { - #![clippy::msrv = "1"] - #![clippy::msrv = "1.0.0"] -} - -fn main() {} diff --git a/tests/ui/min_rust_version_multiple_inner_attr.stderr b/tests/ui/min_rust_version_multiple_inner_attr.stderr deleted file mode 100644 index e3ff6605cde..00000000000 --- a/tests/ui/min_rust_version_multiple_inner_attr.stderr +++ /dev/null @@ -1,38 +0,0 @@ -error: `msrv` is defined multiple times - --> $DIR/min_rust_version_multiple_inner_attr.rs:3:1 - | -LL | #![clippy::msrv = "=1.35.0"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: first definition found here - --> $DIR/min_rust_version_multiple_inner_attr.rs:2:1 - | -LL | #![clippy::msrv = "1.40"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: `msrv` is defined multiple times - --> $DIR/min_rust_version_multiple_inner_attr.rs:4:1 - | -LL | #![clippy::msrv = "1.10.1"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: first definition found here - --> $DIR/min_rust_version_multiple_inner_attr.rs:2:1 - | -LL | #![clippy::msrv = "1.40"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: `msrv` is defined multiple times - --> $DIR/min_rust_version_multiple_inner_attr.rs:8:5 - | -LL | #![clippy::msrv = "1.0.0"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: first definition found here - --> $DIR/min_rust_version_multiple_inner_attr.rs:7:5 - | -LL | #![clippy::msrv = "1"] - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors - diff --git a/tests/ui/min_rust_version_no_patch.rs b/tests/ui/min_rust_version_no_patch.rs deleted file mode 100644 index 98fffe1e351..00000000000 --- a/tests/ui/min_rust_version_no_patch.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![allow(clippy::redundant_clone)] -#![feature(custom_inner_attributes)] -#![clippy::msrv = "1.0"] - -fn manual_strip_msrv() { - let s = "hello, world!"; - if s.starts_with("hello, ") { - assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!"); - } -} - -fn main() { - manual_strip_msrv() -} diff --git a/tests/ui/min_rust_version_outer_attr.rs b/tests/ui/min_rust_version_outer_attr.rs deleted file mode 100644 index 551948bd72e..00000000000 --- a/tests/ui/min_rust_version_outer_attr.rs +++ /dev/null @@ -1,4 +0,0 @@ -#![feature(custom_inner_attributes)] - -#[clippy::msrv = "invalid.version"] -fn main() {} diff --git a/tests/ui/min_rust_version_outer_attr.stderr b/tests/ui/min_rust_version_outer_attr.stderr deleted file mode 100644 index 579ee7a87d2..00000000000 --- a/tests/ui/min_rust_version_outer_attr.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: `msrv` cannot be an outer attribute - --> $DIR/min_rust_version_outer_attr.rs:3:1 - | -LL | #[clippy::msrv = "invalid.version"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/tests/ui/missing_const_for_fn/could_be_const.rs b/tests/ui/missing_const_for_fn/could_be_const.rs index 88f6935d224..b85e8878491 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.rs +++ b/tests/ui/missing_const_for_fn/could_be_const.rs @@ -77,5 +77,17 @@ mod const_fn_stabilized_before_msrv { } } +fn msrv_1_45() -> i32 { + #![clippy::msrv = "1.45"] + + 45 +} + +fn msrv_1_46() -> i32 { + #![clippy::msrv = "1.46"] + + 46 +} + // Should not be const fn main() {} diff --git a/tests/ui/missing_const_for_fn/could_be_const.stderr b/tests/ui/missing_const_for_fn/could_be_const.stderr index 3eb52b68274..f8e221c82f1 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.stderr +++ b/tests/ui/missing_const_for_fn/could_be_const.stderr @@ -81,5 +81,15 @@ LL | | byte.is_ascii_digit(); LL | | } | |_____^ -error: aborting due to 10 previous errors +error: this could be a `const fn` + --> $DIR/could_be_const.rs:86:1 + | +LL | / fn msrv_1_46() -> i32 { +LL | | #![clippy::msrv = "1.46"] +LL | | +LL | | 46 +LL | | } + | |_^ + +error: aborting due to 11 previous errors diff --git a/tests/ui/option_as_ref_deref.fixed b/tests/ui/option_as_ref_deref.fixed index 07d7f0b45b0..bc376d0d7fb 100644 --- a/tests/ui/option_as_ref_deref.fixed +++ b/tests/ui/option_as_ref_deref.fixed @@ -1,6 +1,7 @@ // run-rustfix -#![allow(unused_imports, clippy::redundant_clone)] +#![feature(custom_inner_attributes)] +#![allow(unused, clippy::redundant_clone)] #![warn(clippy::option_as_ref_deref)] use std::ffi::{CString, OsString}; @@ -42,3 +43,17 @@ fn main() { // Issue #5927 let _ = opt.as_deref(); } + +fn msrv_1_39() { + #![clippy::msrv = "1.39"] + + let opt = Some(String::from("123")); + let _ = opt.as_ref().map(String::as_str); +} + +fn msrv_1_40() { + #![clippy::msrv = "1.40"] + + let opt = Some(String::from("123")); + let _ = opt.as_deref(); +} diff --git a/tests/ui/option_as_ref_deref.rs b/tests/ui/option_as_ref_deref.rs index 6ae059c9425..ba3a2eedc22 100644 --- a/tests/ui/option_as_ref_deref.rs +++ b/tests/ui/option_as_ref_deref.rs @@ -1,6 +1,7 @@ // run-rustfix -#![allow(unused_imports, clippy::redundant_clone)] +#![feature(custom_inner_attributes)] +#![allow(unused, clippy::redundant_clone)] #![warn(clippy::option_as_ref_deref)] use std::ffi::{CString, OsString}; @@ -45,3 +46,17 @@ fn main() { // Issue #5927 let _ = opt.as_ref().map(std::ops::Deref::deref); } + +fn msrv_1_39() { + #![clippy::msrv = "1.39"] + + let opt = Some(String::from("123")); + let _ = opt.as_ref().map(String::as_str); +} + +fn msrv_1_40() { + #![clippy::msrv = "1.40"] + + let opt = Some(String::from("123")); + let _ = opt.as_ref().map(String::as_str); +} diff --git a/tests/ui/option_as_ref_deref.stderr b/tests/ui/option_as_ref_deref.stderr index 62f28232475..7de8b3b6ba4 100644 --- a/tests/ui/option_as_ref_deref.stderr +++ b/tests/ui/option_as_ref_deref.stderr @@ -1,5 +1,5 @@ error: called `.as_ref().map(Deref::deref)` on an Option value. This can be done more directly by calling `opt.clone().as_deref()` instead - --> $DIR/option_as_ref_deref.rs:13:13 + --> $DIR/option_as_ref_deref.rs:14:13 | LL | let _ = opt.clone().as_ref().map(Deref::deref).map(str::len); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.clone().as_deref()` @@ -7,7 +7,7 @@ LL | let _ = opt.clone().as_ref().map(Deref::deref).map(str::len); = note: `-D clippy::option-as-ref-deref` implied by `-D warnings` error: called `.as_ref().map(Deref::deref)` on an Option value. This can be done more directly by calling `opt.clone().as_deref()` instead - --> $DIR/option_as_ref_deref.rs:16:13 + --> $DIR/option_as_ref_deref.rs:17:13 | LL | let _ = opt.clone() | _____________^ @@ -17,94 +17,100 @@ LL | | ) | |_________^ help: try using as_deref instead: `opt.clone().as_deref()` error: called `.as_mut().map(DerefMut::deref_mut)` on an Option value. This can be done more directly by calling `opt.as_deref_mut()` instead - --> $DIR/option_as_ref_deref.rs:22:13 + --> $DIR/option_as_ref_deref.rs:23:13 | LL | let _ = opt.as_mut().map(DerefMut::deref_mut); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()` error: called `.as_ref().map(String::as_str)` on an Option value. This can be done more directly by calling `opt.as_deref()` instead - --> $DIR/option_as_ref_deref.rs:24:13 + --> $DIR/option_as_ref_deref.rs:25:13 | LL | let _ = opt.as_ref().map(String::as_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` error: called `.as_ref().map(|x| x.as_str())` on an Option value. This can be done more directly by calling `opt.as_deref()` instead - --> $DIR/option_as_ref_deref.rs:25:13 + --> $DIR/option_as_ref_deref.rs:26:13 | LL | let _ = opt.as_ref().map(|x| x.as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` error: called `.as_mut().map(String::as_mut_str)` on an Option value. This can be done more directly by calling `opt.as_deref_mut()` instead - --> $DIR/option_as_ref_deref.rs:26:13 + --> $DIR/option_as_ref_deref.rs:27:13 | LL | let _ = opt.as_mut().map(String::as_mut_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()` error: called `.as_mut().map(|x| x.as_mut_str())` on an Option value. This can be done more directly by calling `opt.as_deref_mut()` instead - --> $DIR/option_as_ref_deref.rs:27:13 + --> $DIR/option_as_ref_deref.rs:28:13 | LL | let _ = opt.as_mut().map(|x| x.as_mut_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()` error: called `.as_ref().map(CString::as_c_str)` on an Option value. This can be done more directly by calling `Some(CString::new(vec![]).unwrap()).as_deref()` instead - --> $DIR/option_as_ref_deref.rs:28:13 + --> $DIR/option_as_ref_deref.rs:29:13 | LL | let _ = Some(CString::new(vec![]).unwrap()).as_ref().map(CString::as_c_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(CString::new(vec![]).unwrap()).as_deref()` error: called `.as_ref().map(OsString::as_os_str)` on an Option value. This can be done more directly by calling `Some(OsString::new()).as_deref()` instead - --> $DIR/option_as_ref_deref.rs:29:13 + --> $DIR/option_as_ref_deref.rs:30:13 | LL | let _ = Some(OsString::new()).as_ref().map(OsString::as_os_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(OsString::new()).as_deref()` error: called `.as_ref().map(PathBuf::as_path)` on an Option value. This can be done more directly by calling `Some(PathBuf::new()).as_deref()` instead - --> $DIR/option_as_ref_deref.rs:30:13 + --> $DIR/option_as_ref_deref.rs:31:13 | LL | let _ = Some(PathBuf::new()).as_ref().map(PathBuf::as_path); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(PathBuf::new()).as_deref()` error: called `.as_ref().map(Vec::as_slice)` on an Option value. This can be done more directly by calling `Some(Vec::<()>::new()).as_deref()` instead - --> $DIR/option_as_ref_deref.rs:31:13 + --> $DIR/option_as_ref_deref.rs:32:13 | LL | let _ = Some(Vec::<()>::new()).as_ref().map(Vec::as_slice); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(Vec::<()>::new()).as_deref()` error: called `.as_mut().map(Vec::as_mut_slice)` on an Option value. This can be done more directly by calling `Some(Vec::<()>::new()).as_deref_mut()` instead - --> $DIR/option_as_ref_deref.rs:32:13 + --> $DIR/option_as_ref_deref.rs:33:13 | LL | let _ = Some(Vec::<()>::new()).as_mut().map(Vec::as_mut_slice); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `Some(Vec::<()>::new()).as_deref_mut()` error: called `.as_ref().map(|x| x.deref())` on an Option value. This can be done more directly by calling `opt.as_deref()` instead - --> $DIR/option_as_ref_deref.rs:34:13 + --> $DIR/option_as_ref_deref.rs:35:13 | LL | let _ = opt.as_ref().map(|x| x.deref()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` error: called `.as_mut().map(|x| x.deref_mut())` on an Option value. This can be done more directly by calling `opt.clone().as_deref_mut()` instead - --> $DIR/option_as_ref_deref.rs:35:13 + --> $DIR/option_as_ref_deref.rs:36:13 | LL | let _ = opt.clone().as_mut().map(|x| x.deref_mut()).map(|x| x.len()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.clone().as_deref_mut()` error: called `.as_ref().map(|x| &**x)` on an Option value. This can be done more directly by calling `opt.as_deref()` instead - --> $DIR/option_as_ref_deref.rs:42:13 + --> $DIR/option_as_ref_deref.rs:43:13 | LL | let _ = opt.as_ref().map(|x| &**x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` error: called `.as_mut().map(|x| &mut **x)` on an Option value. This can be done more directly by calling `opt.as_deref_mut()` instead - --> $DIR/option_as_ref_deref.rs:43:13 + --> $DIR/option_as_ref_deref.rs:44:13 | LL | let _ = opt.as_mut().map(|x| &mut **x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()` error: called `.as_ref().map(std::ops::Deref::deref)` on an Option value. This can be done more directly by calling `opt.as_deref()` instead - --> $DIR/option_as_ref_deref.rs:46:13 + --> $DIR/option_as_ref_deref.rs:47:13 | LL | let _ = opt.as_ref().map(std::ops::Deref::deref); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` -error: aborting due to 17 previous errors +error: called `.as_ref().map(String::as_str)` on an Option value. This can be done more directly by calling `opt.as_deref()` instead + --> $DIR/option_as_ref_deref.rs:61:13 + | +LL | let _ = opt.as_ref().map(String::as_str); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` + +error: aborting due to 18 previous errors diff --git a/tests/ui/range_contains.fixed b/tests/ui/range_contains.fixed index 85d021b2f25..824f00cb99e 100644 --- a/tests/ui/range_contains.fixed +++ b/tests/ui/range_contains.fixed @@ -1,10 +1,12 @@ // run-rustfix -#[warn(clippy::manual_range_contains)] -#[allow(unused)] -#[allow(clippy::no_effect)] -#[allow(clippy::short_circuit_statement)] -#[allow(clippy::unnecessary_operation)] +#![feature(custom_inner_attributes)] +#![warn(clippy::manual_range_contains)] +#![allow(unused)] +#![allow(clippy::no_effect)] +#![allow(clippy::short_circuit_statement)] +#![allow(clippy::unnecessary_operation)] + fn main() { let x = 9_i32; @@ -62,3 +64,17 @@ fn main() { pub const fn in_range(a: i32) -> bool { 3 <= a && a <= 20 } + +fn msrv_1_34() { + #![clippy::msrv = "1.34"] + + let x = 5; + x >= 8 && x < 34; +} + +fn msrv_1_35() { + #![clippy::msrv = "1.35"] + + let x = 5; + (8..35).contains(&x); +} diff --git a/tests/ui/range_contains.rs b/tests/ui/range_contains.rs index 9a7a75dc132..df925eeadfe 100644 --- a/tests/ui/range_contains.rs +++ b/tests/ui/range_contains.rs @@ -1,10 +1,12 @@ // run-rustfix -#[warn(clippy::manual_range_contains)] -#[allow(unused)] -#[allow(clippy::no_effect)] -#[allow(clippy::short_circuit_statement)] -#[allow(clippy::unnecessary_operation)] +#![feature(custom_inner_attributes)] +#![warn(clippy::manual_range_contains)] +#![allow(unused)] +#![allow(clippy::no_effect)] +#![allow(clippy::short_circuit_statement)] +#![allow(clippy::unnecessary_operation)] + fn main() { let x = 9_i32; @@ -62,3 +64,17 @@ fn main() { pub const fn in_range(a: i32) -> bool { 3 <= a && a <= 20 } + +fn msrv_1_34() { + #![clippy::msrv = "1.34"] + + let x = 5; + x >= 8 && x < 34; +} + +fn msrv_1_35() { + #![clippy::msrv = "1.35"] + + let x = 5; + x >= 8 && x < 35; +} diff --git a/tests/ui/range_contains.stderr b/tests/ui/range_contains.stderr index 936859db5a1..9689e665b05 100644 --- a/tests/ui/range_contains.stderr +++ b/tests/ui/range_contains.stderr @@ -1,5 +1,5 @@ error: manual `Range::contains` implementation - --> $DIR/range_contains.rs:12:5 + --> $DIR/range_contains.rs:14:5 | LL | x >= 8 && x < 12; | ^^^^^^^^^^^^^^^^ help: use: `(8..12).contains(&x)` @@ -7,118 +7,124 @@ LL | x >= 8 && x < 12; = note: `-D clippy::manual-range-contains` implied by `-D warnings` error: manual `Range::contains` implementation - --> $DIR/range_contains.rs:13:5 + --> $DIR/range_contains.rs:15:5 | LL | x < 42 && x >= 21; | ^^^^^^^^^^^^^^^^^ help: use: `(21..42).contains(&x)` error: manual `Range::contains` implementation - --> $DIR/range_contains.rs:14:5 + --> $DIR/range_contains.rs:16:5 | LL | 100 > x && 1 <= x; | ^^^^^^^^^^^^^^^^^ help: use: `(1..100).contains(&x)` error: manual `RangeInclusive::contains` implementation - --> $DIR/range_contains.rs:17:5 + --> $DIR/range_contains.rs:19:5 | LL | x >= 9 && x <= 99; | ^^^^^^^^^^^^^^^^^ help: use: `(9..=99).contains(&x)` error: manual `RangeInclusive::contains` implementation - --> $DIR/range_contains.rs:18:5 + --> $DIR/range_contains.rs:20:5 | LL | x <= 33 && x >= 1; | ^^^^^^^^^^^^^^^^^ help: use: `(1..=33).contains(&x)` error: manual `RangeInclusive::contains` implementation - --> $DIR/range_contains.rs:19:5 + --> $DIR/range_contains.rs:21:5 | LL | 999 >= x && 1 <= x; | ^^^^^^^^^^^^^^^^^^ help: use: `(1..=999).contains(&x)` error: manual `!Range::contains` implementation - --> $DIR/range_contains.rs:22:5 + --> $DIR/range_contains.rs:24:5 | LL | x < 8 || x >= 12; | ^^^^^^^^^^^^^^^^ help: use: `!(8..12).contains(&x)` error: manual `!Range::contains` implementation - --> $DIR/range_contains.rs:23:5 + --> $DIR/range_contains.rs:25:5 | LL | x >= 42 || x < 21; | ^^^^^^^^^^^^^^^^^ help: use: `!(21..42).contains(&x)` error: manual `!Range::contains` implementation - --> $DIR/range_contains.rs:24:5 + --> $DIR/range_contains.rs:26:5 | LL | 100 <= x || 1 > x; | ^^^^^^^^^^^^^^^^^ help: use: `!(1..100).contains(&x)` error: manual `!RangeInclusive::contains` implementation - --> $DIR/range_contains.rs:27:5 + --> $DIR/range_contains.rs:29:5 | LL | x < 9 || x > 99; | ^^^^^^^^^^^^^^^ help: use: `!(9..=99).contains(&x)` error: manual `!RangeInclusive::contains` implementation - --> $DIR/range_contains.rs:28:5 + --> $DIR/range_contains.rs:30:5 | LL | x > 33 || x < 1; | ^^^^^^^^^^^^^^^ help: use: `!(1..=33).contains(&x)` error: manual `!RangeInclusive::contains` implementation - --> $DIR/range_contains.rs:29:5 + --> $DIR/range_contains.rs:31:5 | LL | 999 < x || 1 > x; | ^^^^^^^^^^^^^^^^ help: use: `!(1..=999).contains(&x)` error: manual `Range::contains` implementation - --> $DIR/range_contains.rs:44:5 + --> $DIR/range_contains.rs:46:5 | LL | y >= 0. && y < 1.; | ^^^^^^^^^^^^^^^^^ help: use: `(0. ..1.).contains(&y)` error: manual `!RangeInclusive::contains` implementation - --> $DIR/range_contains.rs:45:5 + --> $DIR/range_contains.rs:47:5 | LL | y < 0. || y > 1.; | ^^^^^^^^^^^^^^^^ help: use: `!(0. ..=1.).contains(&y)` error: manual `RangeInclusive::contains` implementation - --> $DIR/range_contains.rs:48:5 + --> $DIR/range_contains.rs:50:5 | LL | x >= -10 && x <= 10; | ^^^^^^^^^^^^^^^^^^^ help: use: `(-10..=10).contains(&x)` error: manual `RangeInclusive::contains` implementation - --> $DIR/range_contains.rs:50:5 + --> $DIR/range_contains.rs:52:5 | LL | y >= -3. && y <= 3.; | ^^^^^^^^^^^^^^^^^^^ help: use: `(-3. ..=3.).contains(&y)` error: manual `RangeInclusive::contains` implementation - --> $DIR/range_contains.rs:55:30 + --> $DIR/range_contains.rs:57:30 | LL | (x >= 0) && (x <= 10) && (z >= 0) && (z <= 10); | ^^^^^^^^^^^^^^^^^^^^^ help: use: `(0..=10).contains(&z)` error: manual `RangeInclusive::contains` implementation - --> $DIR/range_contains.rs:55:5 + --> $DIR/range_contains.rs:57:5 | LL | (x >= 0) && (x <= 10) && (z >= 0) && (z <= 10); | ^^^^^^^^^^^^^^^^^^^^^ help: use: `(0..=10).contains(&x)` error: manual `!Range::contains` implementation - --> $DIR/range_contains.rs:56:29 + --> $DIR/range_contains.rs:58:29 | LL | (x < 0) || (x >= 10) || (z < 0) || (z >= 10); | ^^^^^^^^^^^^^^^^^^^^ help: use: `!(0..10).contains(&z)` error: manual `!Range::contains` implementation - --> $DIR/range_contains.rs:56:5 + --> $DIR/range_contains.rs:58:5 | LL | (x < 0) || (x >= 10) || (z < 0) || (z >= 10); | ^^^^^^^^^^^^^^^^^^^^ help: use: `!(0..10).contains(&x)` -error: aborting due to 20 previous errors +error: manual `Range::contains` implementation + --> $DIR/range_contains.rs:79:5 + | +LL | x >= 8 && x < 35; + | ^^^^^^^^^^^^^^^^ help: use: `(8..35).contains(&x)` + +error: aborting due to 21 previous errors diff --git a/tests/ui/redundant_field_names.fixed b/tests/ui/redundant_field_names.fixed index 5b4b8eeedd4..34ab552cb1d 100644 --- a/tests/ui/redundant_field_names.fixed +++ b/tests/ui/redundant_field_names.fixed @@ -1,4 +1,6 @@ // run-rustfix + +#![feature(custom_inner_attributes)] #![warn(clippy::redundant_field_names)] #![allow(clippy::no_effect, dead_code, unused_variables)] @@ -69,3 +71,17 @@ fn issue_3476() { S { foo: foo:: }; } + +fn msrv_1_16() { + #![clippy::msrv = "1.16"] + + let start = 0; + let _ = RangeFrom { start: start }; +} + +fn msrv_1_17() { + #![clippy::msrv = "1.17"] + + let start = 0; + let _ = RangeFrom { start }; +} diff --git a/tests/ui/redundant_field_names.rs b/tests/ui/redundant_field_names.rs index 3f97b80c568..a051b1f96f0 100644 --- a/tests/ui/redundant_field_names.rs +++ b/tests/ui/redundant_field_names.rs @@ -1,4 +1,6 @@ // run-rustfix + +#![feature(custom_inner_attributes)] #![warn(clippy::redundant_field_names)] #![allow(clippy::no_effect, dead_code, unused_variables)] @@ -69,3 +71,17 @@ fn issue_3476() { S { foo: foo:: }; } + +fn msrv_1_16() { + #![clippy::msrv = "1.16"] + + let start = 0; + let _ = RangeFrom { start: start }; +} + +fn msrv_1_17() { + #![clippy::msrv = "1.17"] + + let start = 0; + let _ = RangeFrom { start: start }; +} diff --git a/tests/ui/redundant_field_names.stderr b/tests/ui/redundant_field_names.stderr index 7976292df22..8b82e062b93 100644 --- a/tests/ui/redundant_field_names.stderr +++ b/tests/ui/redundant_field_names.stderr @@ -1,5 +1,5 @@ error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:34:9 + --> $DIR/redundant_field_names.rs:36:9 | LL | gender: gender, | ^^^^^^^^^^^^^^ help: replace it with: `gender` @@ -7,40 +7,46 @@ LL | gender: gender, = note: `-D clippy::redundant-field-names` implied by `-D warnings` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:35:9 + --> $DIR/redundant_field_names.rs:37:9 | LL | age: age, | ^^^^^^^^ help: replace it with: `age` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:56:25 + --> $DIR/redundant_field_names.rs:58:25 | LL | let _ = RangeFrom { start: start }; | ^^^^^^^^^^^^ help: replace it with: `start` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:57:23 + --> $DIR/redundant_field_names.rs:59:23 | LL | let _ = RangeTo { end: end }; | ^^^^^^^^ help: replace it with: `end` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:58:21 + --> $DIR/redundant_field_names.rs:60:21 | LL | let _ = Range { start: start, end: end }; | ^^^^^^^^^^^^ help: replace it with: `start` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:58:35 + --> $DIR/redundant_field_names.rs:60:35 | LL | let _ = Range { start: start, end: end }; | ^^^^^^^^ help: replace it with: `end` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:60:32 + --> $DIR/redundant_field_names.rs:62:32 | LL | let _ = RangeToInclusive { end: end }; | ^^^^^^^^ help: replace it with: `end` -error: aborting due to 7 previous errors +error: redundant field names in struct initialization + --> $DIR/redundant_field_names.rs:86:25 + | +LL | let _ = RangeFrom { start: start }; + | ^^^^^^^^^^^^ help: replace it with: `start` + +error: aborting due to 8 previous errors diff --git a/tests/ui/redundant_static_lifetimes.fixed b/tests/ui/redundant_static_lifetimes.fixed index acc8f1e25b6..42110dbe81e 100644 --- a/tests/ui/redundant_static_lifetimes.fixed +++ b/tests/ui/redundant_static_lifetimes.fixed @@ -1,5 +1,6 @@ // run-rustfix +#![feature(custom_inner_attributes)] #![allow(unused)] #[derive(Debug)] @@ -54,3 +55,15 @@ impl Foo { impl Bar for Foo { const TRAIT_VAR: &'static str = "foo"; } + +fn msrv_1_16() { + #![clippy::msrv = "1.16"] + + static V: &'static u8 = &16; +} + +fn msrv_1_17() { + #![clippy::msrv = "1.17"] + + static V: &u8 = &17; +} diff --git a/tests/ui/redundant_static_lifetimes.rs b/tests/ui/redundant_static_lifetimes.rs index f2f0f78659c..bc5200bc862 100644 --- a/tests/ui/redundant_static_lifetimes.rs +++ b/tests/ui/redundant_static_lifetimes.rs @@ -1,5 +1,6 @@ // run-rustfix +#![feature(custom_inner_attributes)] #![allow(unused)] #[derive(Debug)] @@ -54,3 +55,15 @@ impl Foo { impl Bar for Foo { const TRAIT_VAR: &'static str = "foo"; } + +fn msrv_1_16() { + #![clippy::msrv = "1.16"] + + static V: &'static u8 = &16; +} + +fn msrv_1_17() { + #![clippy::msrv = "1.17"] + + static V: &'static u8 = &17; +} diff --git a/tests/ui/redundant_static_lifetimes.stderr b/tests/ui/redundant_static_lifetimes.stderr index 649831f9c06..735113460d2 100644 --- a/tests/ui/redundant_static_lifetimes.stderr +++ b/tests/ui/redundant_static_lifetimes.stderr @@ -1,5 +1,5 @@ error: constants have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:8:17 + --> $DIR/redundant_static_lifetimes.rs:9:17 | LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static. | -^^^^^^^---- help: consider removing `'static`: `&str` @@ -7,94 +7,100 @@ LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removin = note: `-D clippy::redundant-static-lifetimes` implied by `-D warnings` error: constants have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:12:21 + --> $DIR/redundant_static_lifetimes.rs:13:21 | LL | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: constants have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:14:32 + --> $DIR/redundant_static_lifetimes.rs:15:32 | LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: constants have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:14:47 + --> $DIR/redundant_static_lifetimes.rs:15:47 | LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: constants have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:16:17 + --> $DIR/redundant_static_lifetimes.rs:17:17 | LL | const VAR_SIX: &'static u8 = &5; | -^^^^^^^--- help: consider removing `'static`: `&u8` error: constants have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:18:20 + --> $DIR/redundant_static_lifetimes.rs:19:20 | LL | const VAR_HEIGHT: &'static Foo = &Foo {}; | -^^^^^^^---- help: consider removing `'static`: `&Foo` error: constants have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:20:19 + --> $DIR/redundant_static_lifetimes.rs:21:19 | LL | const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR Consider removing 'static. | -^^^^^^^----- help: consider removing `'static`: `&[u8]` error: constants have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:22:19 + --> $DIR/redundant_static_lifetimes.rs:23:19 | LL | const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static. | -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)` error: constants have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:24:19 + --> $DIR/redundant_static_lifetimes.rs:25:19 | LL | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. | -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]` error: statics have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:26:25 + --> $DIR/redundant_static_lifetimes.rs:27:25 | LL | static STATIC_VAR_ONE: &'static str = "Test static #1"; // ERROR Consider removing 'static. | -^^^^^^^---- help: consider removing `'static`: `&str` error: statics have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:30:29 + --> $DIR/redundant_static_lifetimes.rs:31:29 | LL | static STATIC_VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: statics have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:32:25 + --> $DIR/redundant_static_lifetimes.rs:33:25 | LL | static STATIC_VAR_SIX: &'static u8 = &5; | -^^^^^^^--- help: consider removing `'static`: `&u8` error: statics have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:34:28 + --> $DIR/redundant_static_lifetimes.rs:35:28 | LL | static STATIC_VAR_HEIGHT: &'static Foo = &Foo {}; | -^^^^^^^---- help: consider removing `'static`: `&Foo` error: statics have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:36:27 + --> $DIR/redundant_static_lifetimes.rs:37:27 | LL | static STATIC_VAR_SLICE: &'static [u8] = b"Test static #3"; // ERROR Consider removing 'static. | -^^^^^^^----- help: consider removing `'static`: `&[u8]` error: statics have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:38:27 + --> $DIR/redundant_static_lifetimes.rs:39:27 | LL | static STATIC_VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static. | -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)` error: statics have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:40:27 + --> $DIR/redundant_static_lifetimes.rs:41:27 | LL | static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. | -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]` -error: aborting due to 16 previous errors +error: statics have by default a `'static` lifetime + --> $DIR/redundant_static_lifetimes.rs:68:16 + | +LL | static V: &'static u8 = &17; + | -^^^^^^^--- help: consider removing `'static`: `&u8` + +error: aborting due to 17 previous errors diff --git a/tests/ui/unnested_or_patterns.fixed b/tests/ui/unnested_or_patterns.fixed index c223b5bc711..9786c7b1212 100644 --- a/tests/ui/unnested_or_patterns.fixed +++ b/tests/ui/unnested_or_patterns.fixed @@ -1,9 +1,9 @@ // run-rustfix -#![feature(box_patterns)] +#![feature(box_patterns, custom_inner_attributes)] #![warn(clippy::unnested_or_patterns)] #![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::upper_case_acronyms)] -#![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)] +#![allow(unreachable_patterns, irrefutable_let_patterns, unused)] fn main() { // Should be ignored by this lint, as nesting requires more characters. @@ -33,3 +33,15 @@ fn main() { if let S { x: 0 | 1, y } = (S { x: 0, y: 1 }) {} if let S { x: 0, y, .. } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} } + +fn msrv_1_52() { + #![clippy::msrv = "1.52"] + + if let [1] | [52] = [0] {} +} + +fn msrv_1_53() { + #![clippy::msrv = "1.53"] + + if let [1 | 53] = [0] {} +} diff --git a/tests/ui/unnested_or_patterns.rs b/tests/ui/unnested_or_patterns.rs index 04cd11036e4..f57322396d4 100644 --- a/tests/ui/unnested_or_patterns.rs +++ b/tests/ui/unnested_or_patterns.rs @@ -1,9 +1,9 @@ // run-rustfix -#![feature(box_patterns)] +#![feature(box_patterns, custom_inner_attributes)] #![warn(clippy::unnested_or_patterns)] #![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::upper_case_acronyms)] -#![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)] +#![allow(unreachable_patterns, irrefutable_let_patterns, unused)] fn main() { // Should be ignored by this lint, as nesting requires more characters. @@ -33,3 +33,15 @@ fn main() { if let S { x: 0, y } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} if let S { x: 0, y, .. } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} } + +fn msrv_1_52() { + #![clippy::msrv = "1.52"] + + if let [1] | [52] = [0] {} +} + +fn msrv_1_53() { + #![clippy::msrv = "1.53"] + + if let [1] | [53] = [0] {} +} diff --git a/tests/ui/unnested_or_patterns.stderr b/tests/ui/unnested_or_patterns.stderr index 453c66cbba8..fbc12fff0b0 100644 --- a/tests/ui/unnested_or_patterns.stderr +++ b/tests/ui/unnested_or_patterns.stderr @@ -175,5 +175,16 @@ help: nest the patterns LL | if let S { x: 0 | 1, y } = (S { x: 0, y: 1 }) {} | ~~~~~~~~~~~~~~~~~ -error: aborting due to 16 previous errors +error: unnested or-patterns + --> $DIR/unnested_or_patterns.rs:46:12 + | +LL | if let [1] | [53] = [0] {} + | ^^^^^^^^^^ + | +help: nest the patterns + | +LL | if let [1 | 53] = [0] {} + | ~~~~~~~~ + +error: aborting due to 17 previous errors diff --git a/tests/ui/use_self.fixed b/tests/ui/use_self.fixed index 37986187da1..3b54fe9d5ff 100644 --- a/tests/ui/use_self.fixed +++ b/tests/ui/use_self.fixed @@ -1,6 +1,7 @@ // run-rustfix // aux-build:proc_macro_derive.rs +#![feature(custom_inner_attributes)] #![warn(clippy::use_self)] #![allow(dead_code, unreachable_code)] #![allow( @@ -617,3 +618,35 @@ mod issue6902 { Bar = 1, } } + +fn msrv_1_36() { + #![clippy::msrv = "1.36"] + + enum E { + A, + } + + impl E { + fn foo(self) { + match self { + E::A => {}, + } + } + } +} + +fn msrv_1_37() { + #![clippy::msrv = "1.37"] + + enum E { + A, + } + + impl E { + fn foo(self) { + match self { + Self::A => {}, + } + } + } +} diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index 1b2b3337c92..bf87633cd2d 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -1,6 +1,7 @@ // run-rustfix // aux-build:proc_macro_derive.rs +#![feature(custom_inner_attributes)] #![warn(clippy::use_self)] #![allow(dead_code, unreachable_code)] #![allow( @@ -617,3 +618,35 @@ mod issue6902 { Bar = 1, } } + +fn msrv_1_36() { + #![clippy::msrv = "1.36"] + + enum E { + A, + } + + impl E { + fn foo(self) { + match self { + E::A => {}, + } + } + } +} + +fn msrv_1_37() { + #![clippy::msrv = "1.37"] + + enum E { + A, + } + + impl E { + fn foo(self) { + match self { + E::A => {}, + } + } + } +} diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index f06bb959b3b..16fb0609242 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -1,5 +1,5 @@ error: unnecessary structure name repetition - --> $DIR/use_self.rs:22:21 + --> $DIR/use_self.rs:23:21 | LL | fn new() -> Foo { | ^^^ help: use the applicable keyword: `Self` @@ -7,244 +7,250 @@ LL | fn new() -> Foo { = note: `-D clippy::use-self` implied by `-D warnings` error: unnecessary structure name repetition - --> $DIR/use_self.rs:23:13 + --> $DIR/use_self.rs:24:13 | LL | Foo {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:25:22 + --> $DIR/use_self.rs:26:22 | LL | fn test() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:26:13 + --> $DIR/use_self.rs:27:13 | LL | Foo::new() | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:31:25 + --> $DIR/use_self.rs:32:25 | LL | fn default() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:32:13 + --> $DIR/use_self.rs:33:13 | LL | Foo::new() | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:97:24 + --> $DIR/use_self.rs:98:24 | LL | fn bad(foos: &[Foo]) -> impl Iterator { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:97:55 + --> $DIR/use_self.rs:98:55 | LL | fn bad(foos: &[Foo]) -> impl Iterator { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:112:13 + --> $DIR/use_self.rs:113:13 | LL | TS(0) | ^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:147:29 + --> $DIR/use_self.rs:148:29 | LL | fn bar() -> Bar { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:148:21 + --> $DIR/use_self.rs:149:21 | LL | Bar { foo: Foo {} } | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:159:21 + --> $DIR/use_self.rs:160:21 | LL | fn baz() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:160:13 + --> $DIR/use_self.rs:161:13 | LL | Foo {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:177:21 + --> $DIR/use_self.rs:178:21 | LL | let _ = Enum::B(42); | ^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:178:21 + --> $DIR/use_self.rs:179:21 | LL | let _ = Enum::C { field: true }; | ^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:179:21 + --> $DIR/use_self.rs:180:21 | LL | let _ = Enum::A; | ^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:221:13 + --> $DIR/use_self.rs:222:13 | LL | nested::A::fun_1(); | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:222:13 + --> $DIR/use_self.rs:223:13 | LL | nested::A::A; | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:224:13 + --> $DIR/use_self.rs:225:13 | LL | nested::A {}; | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:243:13 + --> $DIR/use_self.rs:244:13 | LL | TestStruct::from_something() | ^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:257:25 + --> $DIR/use_self.rs:258:25 | LL | async fn g() -> S { | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:258:13 + --> $DIR/use_self.rs:259:13 | LL | S {} | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:262:16 + --> $DIR/use_self.rs:263:16 | LL | &p[S::A..S::B] | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:262:22 + --> $DIR/use_self.rs:263:22 | LL | &p[S::A..S::B] | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:285:29 + --> $DIR/use_self.rs:286:29 | LL | fn foo(value: T) -> Foo { | ^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:286:13 + --> $DIR/use_self.rs:287:13 | LL | Foo:: { value } | ^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:458:13 + --> $DIR/use_self.rs:459:13 | LL | A::new::(submod::B {}) | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:495:13 + --> $DIR/use_self.rs:496:13 | LL | S2::new() | ^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:532:17 + --> $DIR/use_self.rs:533:17 | LL | Foo::Bar => unimplemented!(), | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:533:17 + --> $DIR/use_self.rs:534:17 | LL | Foo::Baz => unimplemented!(), | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:539:20 + --> $DIR/use_self.rs:540:20 | LL | if let Foo::Bar = self { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:563:17 + --> $DIR/use_self.rs:564:17 | LL | Something::Num(n) => *n, | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:564:17 + --> $DIR/use_self.rs:565:17 | LL | Something::TupleNums(n, _m) => *n, | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:565:17 + --> $DIR/use_self.rs:566:17 | LL | Something::StructNums { one, two: _ } => *one, | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:571:17 + --> $DIR/use_self.rs:572:17 | LL | crate::issue8845::Something::Num(n) => *n, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:572:17 + --> $DIR/use_self.rs:573:17 | LL | crate::issue8845::Something::TupleNums(n, _m) => *n, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:573:17 + --> $DIR/use_self.rs:574:17 | LL | crate::issue8845::Something::StructNums { one, two: _ } => *one, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:589:17 + --> $DIR/use_self.rs:590:17 | LL | let Foo(x) = self; | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:594:17 + --> $DIR/use_self.rs:595:17 | LL | let crate::issue8845::Foo(x) = self; | ^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:601:17 + --> $DIR/use_self.rs:602:17 | LL | let Bar { x, .. } = self; | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:606:17 + --> $DIR/use_self.rs:607:17 | LL | let crate::issue8845::Bar { x, .. } = self; | ^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` -error: aborting due to 41 previous errors +error: unnecessary structure name repetition + --> $DIR/use_self.rs:648:17 + | +LL | E::A => {}, + | ^ help: use the applicable keyword: `Self` + +error: aborting due to 42 previous errors -- cgit 1.4.1-3-g733a5 From 637139d2ff4202f9296777f8f4750bcc233b09f8 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Mon, 21 Nov 2022 14:37:51 +0000 Subject: Add `clippy_utils::msrv::Msrv` to keep track of the current MSRV --- book/src/development/adding_lints.md | 8 +- clippy_dev/src/new_lint.rs | 16 ++- clippy_lints/src/almost_complete_letter_range.rs | 11 +-- clippy_lints/src/approx_const.rs | 8 +- clippy_lints/src/attrs.rs | 12 +-- clippy_lints/src/casts/cast_abs_to_unsigned.rs | 7 +- clippy_lints/src/casts/cast_lossless.rs | 16 +-- .../src/casts/cast_slice_different_sizes.rs | 8 +- .../src/casts/cast_slice_from_raw_parts.rs | 14 +-- clippy_lints/src/casts/mod.rs | 22 ++--- clippy_lints/src/casts/ptr_as_ptr.rs | 7 +- clippy_lints/src/checked_conversions.rs | 10 +- clippy_lints/src/dereference.rs | 18 ++-- clippy_lints/src/format_args.rs | 10 +- clippy_lints/src/from_over_into.rs | 10 +- clippy_lints/src/if_then_some_else_none.rs | 14 ++- clippy_lints/src/index_refutable_slice.rs | 11 +-- clippy_lints/src/instant_subtraction.rs | 18 ++-- clippy_lints/src/lib.rs | 108 +++++++-------------- clippy_lints/src/manual_bits.rs | 10 +- clippy_lints/src/manual_clamp.rs | 33 +++---- clippy_lints/src/manual_is_ascii_check.rs | 15 ++- clippy_lints/src/manual_let_else.rs | 10 +- clippy_lints/src/manual_non_exhaustive.rs | 16 +-- clippy_lints/src/manual_rem_euclid.rs | 12 +-- clippy_lints/src/manual_retain.rs | 24 ++--- clippy_lints/src/manual_strip.rs | 10 +- clippy_lints/src/matches/mod.rs | 14 ++- clippy_lints/src/mem_replace.rs | 10 +- .../src/methods/cloned_instead_of_copied.rs | 10 +- clippy_lints/src/methods/err_expect.rs | 8 +- clippy_lints/src/methods/filter_map_next.rs | 8 +- clippy_lints/src/methods/is_digit_ascii_radix.rs | 9 +- clippy_lints/src/methods/map_clone.rs | 16 +-- clippy_lints/src/methods/map_unwrap_or.rs | 7 +- clippy_lints/src/methods/mod.rs | 36 +++---- clippy_lints/src/methods/option_as_ref_deref.rs | 8 +- clippy_lints/src/methods/str_splitn.rs | 8 +- clippy_lints/src/methods/unnecessary_to_owned.rs | 9 +- clippy_lints/src/missing_const_for_fn.rs | 14 ++- clippy_lints/src/ranges.rs | 10 +- clippy_lints/src/redundant_field_names.rs | 9 +- clippy_lints/src/redundant_static_lifetimes.rs | 9 +- clippy_lints/src/transmute/mod.rs | 8 +- clippy_lints/src/transmute/transmute_ptr_to_ref.rs | 10 +- clippy_lints/src/unnested_or_patterns.rs | 17 ++-- clippy_lints/src/use_self.rs | 14 +-- .../src/utils/internal_lints/msrv_attr_impl.rs | 2 +- clippy_utils/src/lib.rs | 33 ++----- clippy_utils/src/msrvs.rs | 101 +++++++++++++++++++ clippy_utils/src/paths.rs | 4 +- clippy_utils/src/qualify_min_const_fn.rs | 18 ++-- tests/ui-internal/invalid_msrv_attr_impl.fixed | 4 +- tests/ui-internal/invalid_msrv_attr_impl.rs | 4 +- tests/ui/min_rust_version_attr.rs | 23 +++++ tests/ui/min_rust_version_attr.stderr | 18 +++- 56 files changed, 466 insertions(+), 433 deletions(-) (limited to 'book/src/development/adding_lints.md') diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md index 3c3f368a529..29d0d45dcc9 100644 --- a/book/src/development/adding_lints.md +++ b/book/src/development/adding_lints.md @@ -443,22 +443,22 @@ value is passed to the constructor in `clippy_lints/lib.rs`. ```rust pub struct ManualStrip { - msrv: Option, + msrv: Msrv, } impl ManualStrip { #[must_use] - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv } } } ``` The project's MSRV can then be matched against the feature MSRV in the LintPass -using the `meets_msrv` utility function. +using the `Msrv::meets` method. ``` rust -if !meets_msrv(self.msrv, msrvs::STR_STRIP_PREFIX) { +if !self.msrv.meets(msrvs::STR_STRIP_PREFIX) { return; } ``` diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index 9e15f1504fa..ec7f1dd0d84 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -120,7 +120,7 @@ fn add_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> { let new_lint = if enable_msrv { format!( - "store.register_{lint_pass}_pass(move |{ctor_arg}| Box::new({module_name}::{camel_name}::new(msrv)));\n ", + "store.register_{lint_pass}_pass(move |{ctor_arg}| Box::new({module_name}::{camel_name}::new(msrv())));\n ", lint_pass = lint.pass, ctor_arg = if lint.pass == "late" { "_" } else { "" }, module_name = lint.name, @@ -238,10 +238,9 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String { result.push_str(&if enable_msrv { formatdoc!( r#" - use clippy_utils::msrvs; + use clippy_utils::msrvs::{{self, Msrv}}; {pass_import} use rustc_lint::{{{context_import}, {pass_type}, LintContext}}; - use rustc_semver::RustcVersion; use rustc_session::{{declare_tool_lint, impl_lint_pass}}; "# @@ -263,12 +262,12 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String { formatdoc!( r#" pub struct {name_camel} {{ - msrv: Option, + msrv: Msrv, }} impl {name_camel} {{ #[must_use] - pub fn new(msrv: Option) -> Self {{ + pub fn new(msrv: Msrv) -> Self {{ Self {{ msrv }} }} }} @@ -357,15 +356,14 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R let _ = writedoc!( lint_file_contents, r#" - use clippy_utils::{{meets_msrv, msrvs}}; + use clippy_utils::msrvs::{{self, Msrv}}; use rustc_lint::{{{context_import}, LintContext}}; - use rustc_semver::RustcVersion; use super::{name_upper}; // TODO: Adjust the parameters as necessary - pub(super) fn check(cx: &{context_import}, msrv: Option) {{ - if !meets_msrv(msrv, todo!("Add a new entry in `clippy_utils/src/msrvs`")) {{ + pub(super) fn check(cx: &{context_import}, msrv: &Msrv) {{ + if !msrv.meets(todo!("Add a new entry in `clippy_utils/src/msrvs`")) {{ return; }} todo!(); diff --git a/clippy_lints/src/almost_complete_letter_range.rs b/clippy_lints/src/almost_complete_letter_range.rs index 073e4af1318..3cf8ba0a521 100644 --- a/clippy_lints/src/almost_complete_letter_range.rs +++ b/clippy_lints/src/almost_complete_letter_range.rs @@ -1,11 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{trim_span, walk_span_to_context}; -use clippy_utils::{meets_msrv, msrvs}; use rustc_ast::ast::{Expr, ExprKind, LitKind, Pat, PatKind, RangeEnd, RangeLimits}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::Span; @@ -33,10 +32,10 @@ declare_clippy_lint! { impl_lint_pass!(AlmostCompleteLetterRange => [ALMOST_COMPLETE_LETTER_RANGE]); pub struct AlmostCompleteLetterRange { - msrv: Option, + msrv: Msrv, } impl AlmostCompleteLetterRange { - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv } } } @@ -46,7 +45,7 @@ impl EarlyLintPass for AlmostCompleteLetterRange { let ctxt = e.span.ctxt(); let sugg = if let Some(start) = walk_span_to_context(start.span, ctxt) && let Some(end) = walk_span_to_context(end.span, ctxt) - && meets_msrv(self.msrv, msrvs::RANGE_INCLUSIVE) + && self.msrv.meets(msrvs::RANGE_INCLUSIVE) { Some((trim_span(cx.sess().source_map(), start.between(end)), "..=")) } else { @@ -60,7 +59,7 @@ impl EarlyLintPass for AlmostCompleteLetterRange { if let PatKind::Range(Some(start), Some(end), kind) = &p.kind && matches!(kind.node, RangeEnd::Excluded) { - let sugg = if meets_msrv(self.msrv, msrvs::RANGE_INCLUSIVE) { + let sugg = if self.msrv.meets(msrvs::RANGE_INCLUSIVE) { "..=" } else { "..." diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index 724490fb495..ccf82f132f4 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::{meets_msrv, msrvs}; +use clippy_utils::msrvs::{self, Msrv}; use rustc_ast::ast::{FloatTy, LitFloatType, LitKind}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -63,12 +63,12 @@ const KNOWN_CONSTS: [(f64, &str, usize, Option); 19] = [ ]; pub struct ApproxConstant { - msrv: Option, + msrv: Msrv, } impl ApproxConstant { #[must_use] - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv } } @@ -87,7 +87,7 @@ impl ApproxConstant { let s = s.as_str(); if s.parse::().is_ok() { for &(constant, name, min_digits, msrv) in &KNOWN_CONSTS { - if is_approx_const(constant, s, min_digits) && msrv.map_or(true, |msrv| meets_msrv(self.msrv, msrv)) { + if is_approx_const(constant, s, min_digits) && msrv.map_or(true, |msrv| self.msrv.meets(msrv)) { span_lint_and_help( cx, APPROX_CONSTANT, diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index ecf8e83375d..54364f9dab2 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -2,9 +2,8 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::macros::{is_panic, macro_backtrace}; -use clippy_utils::msrvs; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{first_line_of_span, is_present_in_source, snippet_opt, without_block_comments}; -use clippy_utils::{extract_msrv_attr, meets_msrv}; use if_chain::if_chain; use rustc_ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem}; use rustc_errors::Applicability; @@ -14,7 +13,6 @@ use rustc_hir::{ use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty; -use rustc_semver::RustcVersion; use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; use rustc_span::symbol::Symbol; @@ -599,7 +597,7 @@ fn is_word(nmi: &NestedMetaItem, expected: Symbol) -> bool { } pub struct EarlyAttributes { - pub msrv: Option, + pub msrv: Msrv, } impl_lint_pass!(EarlyAttributes => [ @@ -614,7 +612,7 @@ impl EarlyLintPass for EarlyAttributes { } fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) { - check_deprecated_cfg_attr(cx, attr, self.msrv); + check_deprecated_cfg_attr(cx, attr, &self.msrv); check_mismatched_target_os(cx, attr); } @@ -654,9 +652,9 @@ fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::It } } -fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute, msrv: Option) { +fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &Msrv) { if_chain! { - if meets_msrv(msrv, msrvs::TOOL_ATTRIBUTES); + if msrv.meets(msrvs::TOOL_ATTRIBUTES); // check cfg_attr if attr.has_name(sym::cfg_attr); if let Some(items) = attr.meta_item_list(); diff --git a/clippy_lints/src/casts/cast_abs_to_unsigned.rs b/clippy_lints/src/casts/cast_abs_to_unsigned.rs index 3f1edabe6c5..44226298333 100644 --- a/clippy_lints/src/casts/cast_abs_to_unsigned.rs +++ b/clippy_lints/src/casts/cast_abs_to_unsigned.rs @@ -1,11 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::sugg::Sugg; -use clippy_utils::{meets_msrv, msrvs}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; -use rustc_semver::RustcVersion; use super::CAST_ABS_TO_UNSIGNED; @@ -15,9 +14,9 @@ pub(super) fn check( cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>, - msrv: Option, + msrv: &Msrv, ) { - if meets_msrv(msrv, msrvs::UNSIGNED_ABS) + if msrv.meets(msrvs::UNSIGNED_ABS) && let ty::Int(from) = cast_from.kind() && let ty::Uint(to) = cast_to.kind() && let ExprKind::MethodCall(method_path, receiver, ..) = cast_expr.kind diff --git a/clippy_lints/src/casts/cast_lossless.rs b/clippy_lints/src/casts/cast_lossless.rs index 13c403234da..cf07e050ccc 100644 --- a/clippy_lints/src/casts/cast_lossless.rs +++ b/clippy_lints/src/casts/cast_lossless.rs @@ -1,12 +1,12 @@ use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::in_constant; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_opt; use clippy_utils::ty::is_isize_or_usize; -use clippy_utils::{in_constant, meets_msrv, msrvs}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, FloatTy, Ty}; -use rustc_semver::RustcVersion; use super::{utils, CAST_LOSSLESS}; @@ -16,7 +16,7 @@ pub(super) fn check( cast_op: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>, - msrv: Option, + msrv: &Msrv, ) { if !should_lint(cx, expr, cast_from, cast_to, msrv) { return; @@ -57,13 +57,7 @@ pub(super) fn check( ); } -fn should_lint( - cx: &LateContext<'_>, - expr: &Expr<'_>, - cast_from: Ty<'_>, - cast_to: Ty<'_>, - msrv: Option, -) -> bool { +fn should_lint(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>, msrv: &Msrv) -> bool { // 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 false; @@ -89,7 +83,7 @@ fn should_lint( }; !is_isize_or_usize(cast_from) && from_nbits < to_nbits }, - (false, true) if matches!(cast_from.kind(), ty::Bool) && meets_msrv(msrv, msrvs::FROM_BOOL) => true, + (false, true) if matches!(cast_from.kind(), ty::Bool) && msrv.meets(msrvs::FROM_BOOL) => true, (_, _) => { matches!(cast_from.kind(), ty::Float(FloatTy::F32)) && matches!(cast_to.kind(), ty::Float(FloatTy::F64)) }, diff --git a/clippy_lints/src/casts/cast_slice_different_sizes.rs b/clippy_lints/src/casts/cast_slice_different_sizes.rs index d31d10d22b9..e862f13e69f 100644 --- a/clippy_lints/src/casts/cast_slice_different_sizes.rs +++ b/clippy_lints/src/casts/cast_slice_different_sizes.rs @@ -1,16 +1,16 @@ -use clippy_utils::{diagnostics::span_lint_and_then, meets_msrv, msrvs, source}; +use clippy_utils::msrvs::{self, Msrv}; +use clippy_utils::{diagnostics::span_lint_and_then, source}; use if_chain::if_chain; use rustc_ast::Mutability; use rustc_hir::{Expr, ExprKind, Node}; use rustc_lint::LateContext; use rustc_middle::ty::{self, layout::LayoutOf, Ty, TypeAndMut}; -use rustc_semver::RustcVersion; use super::CAST_SLICE_DIFFERENT_SIZES; -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: Option) { +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: &Msrv) { // suggestion is invalid if `ptr::slice_from_raw_parts` does not exist - if !meets_msrv(msrv, msrvs::PTR_SLICE_RAW_PARTS) { + if !msrv.meets(msrvs::PTR_SLICE_RAW_PARTS) { return; } diff --git a/clippy_lints/src/casts/cast_slice_from_raw_parts.rs b/clippy_lints/src/casts/cast_slice_from_raw_parts.rs index 284ef165998..627b795d6ed 100644 --- a/clippy_lints/src/casts/cast_slice_from_raw_parts.rs +++ b/clippy_lints/src/casts/cast_slice_from_raw_parts.rs @@ -1,12 +1,12 @@ use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::{match_def_path, meets_msrv, msrvs, paths}; +use clippy_utils::{match_def_path, paths}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{def_id::DefId, Expr, ExprKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; -use rustc_semver::RustcVersion; use super::CAST_SLICE_FROM_RAW_PARTS; @@ -25,15 +25,9 @@ fn raw_parts_kind(cx: &LateContext<'_>, did: DefId) -> Option { } } -pub(super) fn check( - cx: &LateContext<'_>, - expr: &Expr<'_>, - cast_expr: &Expr<'_>, - cast_to: Ty<'_>, - msrv: Option, -) { +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_to: Ty<'_>, msrv: &Msrv) { if_chain! { - if meets_msrv(msrv, msrvs::PTR_SLICE_RAW_PARTS); + if msrv.meets(msrvs::PTR_SLICE_RAW_PARTS); if let ty::RawPtr(ptrty) = cast_to.kind(); if let ty::Slice(_) = ptrty.ty.kind(); if let ExprKind::Call(fun, [ptr_arg, len_arg]) = cast_expr.peel_blocks().kind; diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index 7148b5e6ebf..c6d505c4a18 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -21,11 +21,11 @@ mod ptr_as_ptr; mod unnecessary_cast; mod utils; -use clippy_utils::{is_hir_ty_cfg_dependant, meets_msrv, msrvs}; +use clippy_utils::is_hir_ty_cfg_dependant; +use clippy_utils::msrvs::{self, Msrv}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; declare_clippy_lint! { @@ -648,12 +648,12 @@ declare_clippy_lint! { } pub struct Casts { - msrv: Option, + msrv: Msrv, } impl Casts { #[must_use] - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv } } } @@ -686,7 +686,7 @@ impl_lint_pass!(Casts => [ impl<'tcx> LateLintPass<'tcx> for Casts { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if !in_external_macro(cx.sess(), expr.span) { - ptr_as_ptr::check(cx, expr, self.msrv); + ptr_as_ptr::check(cx, expr, &self.msrv); } if expr.span.from_expansion() { @@ -705,7 +705,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts { if unnecessary_cast::check(cx, expr, cast_expr, cast_from, cast_to) { return; } - cast_slice_from_raw_parts::check(cx, expr, cast_expr, cast_to, self.msrv); + cast_slice_from_raw_parts::check(cx, expr, cast_expr, cast_to, &self.msrv); as_ptr_cast_mut::check(cx, expr, cast_expr, cast_to); fn_to_numeric_cast_any::check(cx, expr, cast_expr, cast_from, cast_to); fn_to_numeric_cast::check(cx, expr, cast_expr, cast_from, cast_to); @@ -717,16 +717,16 @@ impl<'tcx> LateLintPass<'tcx> for Casts { cast_possible_wrap::check(cx, expr, cast_from, cast_to); cast_precision_loss::check(cx, expr, cast_from, cast_to); cast_sign_loss::check(cx, expr, cast_expr, cast_from, cast_to); - cast_abs_to_unsigned::check(cx, expr, cast_expr, cast_from, cast_to, self.msrv); + cast_abs_to_unsigned::check(cx, expr, cast_expr, cast_from, cast_to, &self.msrv); cast_nan_to_int::check(cx, expr, cast_expr, cast_from, cast_to); } - cast_lossless::check(cx, expr, cast_expr, cast_from, cast_to, self.msrv); + cast_lossless::check(cx, expr, cast_expr, cast_from, cast_to, &self.msrv); cast_enum_constructor::check(cx, expr, cast_expr, cast_from); } as_underscore::check(cx, expr, cast_to_hir); - if meets_msrv(self.msrv, msrvs::BORROW_AS_PTR) { + if self.msrv.meets(msrvs::BORROW_AS_PTR) { borrow_as_ptr::check(cx, expr, cast_expr, cast_to_hir); } } @@ -734,8 +734,8 @@ impl<'tcx> LateLintPass<'tcx> for Casts { cast_ref_to_mut::check(cx, expr); cast_ptr_alignment::check(cx, expr); char_lit_as_u8::check(cx, expr); - ptr_as_ptr::check(cx, expr, self.msrv); - cast_slice_different_sizes::check(cx, expr, self.msrv); + ptr_as_ptr::check(cx, expr, &self.msrv); + cast_slice_different_sizes::check(cx, expr, &self.msrv); } extract_msrv_attr!(LateContext); diff --git a/clippy_lints/src/casts/ptr_as_ptr.rs b/clippy_lints/src/casts/ptr_as_ptr.rs index c2b9253ec35..43d75a03235 100644 --- a/clippy_lints/src/casts/ptr_as_ptr.rs +++ b/clippy_lints/src/casts/ptr_as_ptr.rs @@ -1,19 +1,18 @@ use std::borrow::Cow; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::sugg::Sugg; -use clippy_utils::{meets_msrv, msrvs}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, Mutability, TyKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, TypeAndMut}; -use rustc_semver::RustcVersion; use super::PTR_AS_PTR; -pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: Option) { - if !meets_msrv(msrv, msrvs::POINTER_CAST) { +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) { + if !msrv.meets(msrvs::POINTER_CAST) { return; } diff --git a/clippy_lints/src/checked_conversions.rs b/clippy_lints/src/checked_conversions.rs index 78e9921f036..9102a89e377 100644 --- a/clippy_lints/src/checked_conversions.rs +++ b/clippy_lints/src/checked_conversions.rs @@ -1,14 +1,14 @@ //! lint on manually implemented checked conversions that could be transformed into `try_from` use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::{in_constant, is_integer_literal, meets_msrv, msrvs, SpanlessEq}; +use clippy_utils::{in_constant, is_integer_literal, SpanlessEq}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, QPath, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; declare_clippy_lint! { @@ -37,12 +37,12 @@ declare_clippy_lint! { } pub struct CheckedConversions { - msrv: Option, + msrv: Msrv, } impl CheckedConversions { #[must_use] - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv } } } @@ -51,7 +51,7 @@ impl_lint_pass!(CheckedConversions => [CHECKED_CONVERSIONS]); impl<'tcx> LateLintPass<'tcx> for CheckedConversions { fn check_expr(&mut self, cx: &LateContext<'_>, item: &Expr<'_>) { - if !meets_msrv(self.msrv, msrvs::TRY_FROM) { + if !self.msrv.meets(msrvs::TRY_FROM) { return; } diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index 0eee7f23982..faa8467d266 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -1,12 +1,13 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then}; use clippy_utils::mir::{enclosing_mir, expr_local, local_assignments, used_exactly_once, PossibleBorrowerMap}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::sugg::has_enclosing_paren; use clippy_utils::ty::{expr_sig, is_copy, peel_mid_ty_refs, ty_sig, variant_of_res}; use clippy_utils::{ - fn_def_id, get_parent_expr, get_parent_expr_for_hir, is_lint_allowed, meets_msrv, msrvs, path_to_local, - walk_to_expr_usage, + fn_def_id, get_parent_expr, get_parent_expr_for_hir, is_lint_allowed, path_to_local, walk_to_expr_usage, }; + use rustc_ast::util::parser::{PREC_POSTFIX, PREC_PREFIX}; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::graph::iterate::{CycleDetector, TriColorDepthFirstSearch}; @@ -28,7 +29,6 @@ use rustc_middle::ty::{ self, Binder, BoundVariableKind, EarlyBinder, FnSig, GenericArgKind, List, ParamTy, PredicateKind, ProjectionPredicate, Ty, TyCtxt, TypeVisitable, TypeckResults, }; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP}; use rustc_trait_selection::infer::InferCtxtExt as _; @@ -181,12 +181,12 @@ pub struct Dereferencing<'tcx> { possible_borrowers: Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>, // `IntoIterator` for arrays requires Rust 1.53. - msrv: Option, + msrv: Msrv, } impl<'tcx> Dereferencing<'tcx> { #[must_use] - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv, ..Dereferencing::default() @@ -286,7 +286,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { match (self.state.take(), kind) { (None, kind) => { let expr_ty = typeck.expr_ty(expr); - let (position, adjustments) = walk_parents(cx, &mut self.possible_borrowers, expr, self.msrv); + let (position, adjustments) = walk_parents(cx, &mut self.possible_borrowers, expr, &self.msrv); match kind { RefOp::Deref => { if let Position::FieldAccess { @@ -698,7 +698,7 @@ fn walk_parents<'tcx>( cx: &LateContext<'tcx>, possible_borrowers: &mut Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>, e: &'tcx Expr<'_>, - msrv: Option, + msrv: &Msrv, ) -> (Position, &'tcx [Adjustment<'tcx>]) { let mut adjustments = [].as_slice(); let mut precedence = 0i8; @@ -1082,7 +1082,7 @@ fn needless_borrow_impl_arg_position<'tcx>( param_ty: ParamTy, mut expr: &Expr<'tcx>, precedence: i8, - msrv: Option, + msrv: &Msrv, ) -> Position { let destruct_trait_def_id = cx.tcx.lang_items().destruct_trait(); let sized_trait_def_id = cx.tcx.lang_items().sized_trait(); @@ -1182,7 +1182,7 @@ fn needless_borrow_impl_arg_position<'tcx>( && let ty::Param(param_ty) = trait_predicate.self_ty().kind() && let GenericArgKind::Type(ty) = substs_with_referent_ty[param_ty.index as usize].unpack() && ty.is_array() - && !meets_msrv(msrv, msrvs::ARRAY_INTO_ITERATOR) + && !msrv.meets(msrvs::ARRAY_INTO_ITERATOR) { return false; } diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs index a73453bf027..ec45be558f1 100644 --- a/clippy_lints/src/format_args.rs +++ b/clippy_lints/src/format_args.rs @@ -1,11 +1,12 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::is_diag_trait_item; use clippy_utils::macros::FormatParamKind::{Implicit, Named, Numbered, Starred}; use clippy_utils::macros::{ is_format_macro, is_panic, root_macro_call, Count, FormatArg, FormatArgsExpn, FormatParam, FormatParamUsage, }; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_opt; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; -use clippy_utils::{is_diag_trait_item, meets_msrv, msrvs}; use if_chain::if_chain; use itertools::Itertools; use rustc_errors::Applicability; @@ -13,7 +14,6 @@ use rustc_hir::{Expr, ExprKind, HirId, QPath}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty::adjustment::{Adjust, Adjustment}; use rustc_middle::ty::Ty; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::def_id::DefId; use rustc_span::edition::Edition::Edition2021; @@ -158,12 +158,12 @@ impl_lint_pass!(FormatArgs => [ ]); pub struct FormatArgs { - msrv: Option, + msrv: Msrv, } impl FormatArgs { #[must_use] - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv } } } @@ -188,7 +188,7 @@ impl<'tcx> LateLintPass<'tcx> for FormatArgs { check_format_in_format_args(cx, outermost_expn_data.call_site, name, arg.param.value); check_to_string_in_format_args(cx, name, arg.param.value); } - if meets_msrv(self.msrv, msrvs::FORMAT_ARGS_CAPTURE) { + if self.msrv.meets(msrvs::FORMAT_ARGS_CAPTURE) { check_uninlined_args(cx, &format_args, outermost_expn_data.call_site, macro_def_id); } } diff --git a/clippy_lints/src/from_over_into.rs b/clippy_lints/src/from_over_into.rs index 95eda4ea882..7ff4a05fcdd 100644 --- a/clippy_lints/src/from_over_into.rs +++ b/clippy_lints/src/from_over_into.rs @@ -1,7 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::macros::span_is_local; +use clippy_utils::msrvs::{self, Msrv}; +use clippy_utils::path_def_id; use clippy_utils::source::snippet_opt; -use clippy_utils::{meets_msrv, msrvs, path_def_id}; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_path, Visitor}; use rustc_hir::{ @@ -10,7 +11,6 @@ use rustc_hir::{ }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter::OnlyBodies; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::symbol::{kw, sym}; use rustc_span::{Span, Symbol}; @@ -49,12 +49,12 @@ declare_clippy_lint! { } pub struct FromOverInto { - msrv: Option, + msrv: Msrv, } impl FromOverInto { #[must_use] - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { FromOverInto { msrv } } } @@ -63,7 +63,7 @@ impl_lint_pass!(FromOverInto => [FROM_OVER_INTO]); impl<'tcx> LateLintPass<'tcx> for FromOverInto { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - if !meets_msrv(self.msrv, msrvs::RE_REBALANCING_COHERENCE) || !span_is_local(item.span) { + if !self.msrv.meets(msrvs::RE_REBALANCING_COHERENCE) || !span_is_local(item.span) { return; } diff --git a/clippy_lints/src/if_then_some_else_none.rs b/clippy_lints/src/if_then_some_else_none.rs index 0d6718c168a..9cadaaa493e 100644 --- a/clippy_lints/src/if_then_some_else_none.rs +++ b/clippy_lints/src/if_then_some_else_none.rs @@ -1,14 +1,12 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::eager_or_lazy::switch_to_eager_eval; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_macro_callsite; -use clippy_utils::{ - contains_return, higher, is_else_clause, is_res_lang_ctor, meets_msrv, msrvs, path_res, peel_blocks, -}; +use clippy_utils::{contains_return, higher, is_else_clause, is_res_lang_ctor, path_res, peel_blocks}; use rustc_hir::LangItem::{OptionNone, OptionSome}; use rustc_hir::{Expr, ExprKind, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; declare_clippy_lint! { @@ -47,12 +45,12 @@ declare_clippy_lint! { } pub struct IfThenSomeElseNone { - msrv: Option, + msrv: Msrv, } impl IfThenSomeElseNone { #[must_use] - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv } } } @@ -61,7 +59,7 @@ impl_lint_pass!(IfThenSomeElseNone => [IF_THEN_SOME_ELSE_NONE]); impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - if !meets_msrv(self.msrv, msrvs::BOOL_THEN) { + if !self.msrv.meets(msrvs::BOOL_THEN) { return; } @@ -94,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone { } else { format!("{{ /* snippet */ {arg_snip} }}") }; - let method_name = if switch_to_eager_eval(cx, expr) && meets_msrv(self.msrv, msrvs::BOOL_THEN_SOME) { + let method_name = if switch_to_eager_eval(cx, expr) && self.msrv.meets(msrvs::BOOL_THEN_SOME) { "then_some" } else { method_body.insert_str(0, "|| "); diff --git a/clippy_lints/src/index_refutable_slice.rs b/clippy_lints/src/index_refutable_slice.rs index 0d5099bde6d..ee5f10da5b8 100644 --- a/clippy_lints/src/index_refutable_slice.rs +++ b/clippy_lints/src/index_refutable_slice.rs @@ -1,8 +1,9 @@ use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::IfLet; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::ty::is_copy; -use clippy_utils::{is_expn_of, is_lint_allowed, meets_msrv, msrvs, path_to_local}; +use clippy_utils::{is_expn_of, is_lint_allowed, path_to_local}; use if_chain::if_chain; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_errors::Applicability; @@ -11,7 +12,6 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::ty; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::{symbol::Ident, Span}; @@ -51,14 +51,13 @@ declare_clippy_lint! { "avoid indexing on slices which could be destructed" } -#[derive(Copy, Clone)] pub struct IndexRefutableSlice { max_suggested_slice: u64, - msrv: Option, + msrv: Msrv, } impl IndexRefutableSlice { - pub fn new(max_suggested_slice_pattern_length: u64, msrv: Option) -> Self { + pub fn new(max_suggested_slice_pattern_length: u64, msrv: Msrv) -> Self { Self { max_suggested_slice: max_suggested_slice_pattern_length, msrv, @@ -74,7 +73,7 @@ impl<'tcx> LateLintPass<'tcx> for IndexRefutableSlice { if !expr.span.from_expansion() || is_expn_of(expr.span, "if_chain").is_some(); if let Some(IfLet {let_pat, if_then, ..}) = IfLet::hir(cx, expr); if !is_lint_allowed(cx, INDEX_REFUTABLE_SLICE, expr.hir_id); - if meets_msrv(self.msrv, msrvs::SLICE_PATTERNS); + if self.msrv.meets(msrvs::SLICE_PATTERNS); let found_slices = find_slice_values(cx, let_pat); if !found_slices.is_empty(); diff --git a/clippy_lints/src/instant_subtraction.rs b/clippy_lints/src/instant_subtraction.rs index 60754b224fc..dd1b23e7d9d 100644 --- a/clippy_lints/src/instant_subtraction.rs +++ b/clippy_lints/src/instant_subtraction.rs @@ -1,13 +1,11 @@ -use clippy_utils::{ - diagnostics::{self, span_lint_and_sugg}, - meets_msrv, msrvs, source, - sugg::Sugg, - ty, -}; +use clippy_utils::diagnostics::{self, span_lint_and_sugg}; +use clippy_utils::msrvs::{self, Msrv}; +use clippy_utils::source; +use clippy_utils::sugg::Sugg; +use clippy_utils::ty; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::{source_map::Spanned, sym}; @@ -68,12 +66,12 @@ declare_clippy_lint! { } pub struct InstantSubtraction { - msrv: Option, + msrv: Msrv, } impl InstantSubtraction { #[must_use] - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv } } } @@ -101,7 +99,7 @@ impl LateLintPass<'_> for InstantSubtraction { } else { if_chain! { if !expr.span.from_expansion(); - if meets_msrv(self.msrv, msrvs::TRY_FROM); + if self.msrv.meets(msrvs::TRY_FROM); if is_an_instant(cx, lhs); if is_a_duration(cx, rhs); diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3ab5031696d..46acc9679f5 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -52,10 +52,9 @@ extern crate declare_clippy_lint; use std::io; use std::path::PathBuf; -use clippy_utils::parse_msrv; +use clippy_utils::msrvs::Msrv; use rustc_data_structures::fx::FxHashSet; use rustc_lint::{Lint, LintId}; -use rustc_semver::RustcVersion; use rustc_session::Session; #[cfg(feature = "internal")] @@ -322,48 +321,10 @@ pub use crate::utils::conf::{lookup_conf_file, Conf}; /// Used in `./src/driver.rs`. pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, sess: &Session, conf: &Conf) { // NOTE: Do not add any more pre-expansion passes. These should be removed eventually. + let msrv = Msrv::read(&conf.msrv, sess); + let msrv = move || msrv.clone(); - let msrv = conf.msrv.as_ref().and_then(|s| { - parse_msrv(s, None, None).or_else(|| { - sess.err(format!( - "error reading Clippy's configuration file. `{s}` is not a valid Rust version" - )); - None - }) - }); - - store.register_pre_expansion_pass(move || Box::new(attrs::EarlyAttributes { msrv })); -} - -fn read_msrv(conf: &Conf, sess: &Session) -> Option { - let cargo_msrv = std::env::var("CARGO_PKG_RUST_VERSION") - .ok() - .and_then(|v| parse_msrv(&v, None, None)); - let clippy_msrv = conf.msrv.as_ref().and_then(|s| { - parse_msrv(s, None, None).or_else(|| { - sess.err(format!( - "error reading Clippy's configuration file. `{s}` is not a valid Rust version" - )); - None - }) - }); - - if let Some(cargo_msrv) = cargo_msrv { - if let Some(clippy_msrv) = clippy_msrv { - // if both files have an msrv, let's compare them and emit a warning if they differ - if clippy_msrv != cargo_msrv { - sess.warn(format!( - "the MSRV in `clippy.toml` and `Cargo.toml` differ; using `{clippy_msrv}` from `clippy.toml`" - )); - } - - Some(clippy_msrv) - } else { - Some(cargo_msrv) - } - } else { - clippy_msrv - } + store.register_pre_expansion_pass(move || Box::new(attrs::EarlyAttributes { msrv: msrv() })); } #[doc(hidden)] @@ -595,43 +556,44 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(non_octal_unix_permissions::NonOctalUnixPermissions)); store.register_early_pass(|| Box::new(unnecessary_self_imports::UnnecessarySelfImports)); - let msrv = read_msrv(conf, sess); + let msrv = Msrv::read(&conf.msrv, sess); + let msrv = move || msrv.clone(); let avoid_breaking_exported_api = conf.avoid_breaking_exported_api; let allow_expect_in_tests = conf.allow_expect_in_tests; let allow_unwrap_in_tests = conf.allow_unwrap_in_tests; - store.register_late_pass(move |_| Box::new(approx_const::ApproxConstant::new(msrv))); + store.register_late_pass(move |_| Box::new(approx_const::ApproxConstant::new(msrv()))); store.register_late_pass(move |_| { Box::new(methods::Methods::new( avoid_breaking_exported_api, - msrv, + msrv(), allow_expect_in_tests, allow_unwrap_in_tests, )) }); - store.register_late_pass(move |_| Box::new(matches::Matches::new(msrv))); + store.register_late_pass(move |_| Box::new(matches::Matches::new(msrv()))); let matches_for_let_else = conf.matches_for_let_else; - store.register_late_pass(move |_| Box::new(manual_let_else::ManualLetElse::new(msrv, matches_for_let_else))); - store.register_early_pass(move || Box::new(manual_non_exhaustive::ManualNonExhaustiveStruct::new(msrv))); - store.register_late_pass(move |_| Box::new(manual_non_exhaustive::ManualNonExhaustiveEnum::new(msrv))); - store.register_late_pass(move |_| Box::new(manual_strip::ManualStrip::new(msrv))); - store.register_early_pass(move || Box::new(redundant_static_lifetimes::RedundantStaticLifetimes::new(msrv))); - store.register_early_pass(move || Box::new(redundant_field_names::RedundantFieldNames::new(msrv))); - store.register_late_pass(move |_| Box::new(checked_conversions::CheckedConversions::new(msrv))); - store.register_late_pass(move |_| Box::new(mem_replace::MemReplace::new(msrv))); - store.register_late_pass(move |_| Box::new(ranges::Ranges::new(msrv))); - store.register_late_pass(move |_| Box::new(from_over_into::FromOverInto::new(msrv))); - store.register_late_pass(move |_| Box::new(use_self::UseSelf::new(msrv))); - store.register_late_pass(move |_| Box::new(missing_const_for_fn::MissingConstForFn::new(msrv))); + store.register_late_pass(move |_| Box::new(manual_let_else::ManualLetElse::new(msrv(), matches_for_let_else))); + store.register_early_pass(move || Box::new(manual_non_exhaustive::ManualNonExhaustiveStruct::new(msrv()))); + store.register_late_pass(move |_| Box::new(manual_non_exhaustive::ManualNonExhaustiveEnum::new(msrv()))); + store.register_late_pass(move |_| Box::new(manual_strip::ManualStrip::new(msrv()))); + store.register_early_pass(move || Box::new(redundant_static_lifetimes::RedundantStaticLifetimes::new(msrv()))); + store.register_early_pass(move || Box::new(redundant_field_names::RedundantFieldNames::new(msrv()))); + store.register_late_pass(move |_| Box::new(checked_conversions::CheckedConversions::new(msrv()))); + store.register_late_pass(move |_| Box::new(mem_replace::MemReplace::new(msrv()))); + store.register_late_pass(move |_| Box::new(ranges::Ranges::new(msrv()))); + store.register_late_pass(move |_| Box::new(from_over_into::FromOverInto::new(msrv()))); + store.register_late_pass(move |_| Box::new(use_self::UseSelf::new(msrv()))); + store.register_late_pass(move |_| Box::new(missing_const_for_fn::MissingConstForFn::new(msrv()))); store.register_late_pass(move |_| Box::new(needless_question_mark::NeedlessQuestionMark)); - store.register_late_pass(move |_| Box::new(casts::Casts::new(msrv))); - store.register_early_pass(move || Box::new(unnested_or_patterns::UnnestedOrPatterns::new(msrv))); + store.register_late_pass(move |_| Box::new(casts::Casts::new(msrv()))); + store.register_early_pass(move || Box::new(unnested_or_patterns::UnnestedOrPatterns::new(msrv()))); store.register_late_pass(|_| Box::new(size_of_in_element_count::SizeOfInElementCount)); store.register_late_pass(|_| Box::new(same_name_method::SameNameMethod)); let max_suggested_slice_pattern_length = conf.max_suggested_slice_pattern_length; store.register_late_pass(move |_| { Box::new(index_refutable_slice::IndexRefutableSlice::new( max_suggested_slice_pattern_length, - msrv, + msrv(), )) }); store.register_late_pass(|_| Box::::default()); @@ -648,7 +610,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(borrow_deref_ref::BorrowDerefRef)); store.register_late_pass(|_| Box::new(no_effect::NoEffect)); store.register_late_pass(|_| Box::new(temporary_assignment::TemporaryAssignment)); - store.register_late_pass(move |_| Box::new(transmute::Transmute::new(msrv))); + store.register_late_pass(move |_| Box::new(transmute::Transmute::new(msrv()))); let cognitive_complexity_threshold = conf.cognitive_complexity_threshold; store.register_late_pass(move |_| { Box::new(cognitive_complexity::CognitiveComplexity::new( @@ -806,7 +768,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(move |_| Box::new(wildcard_imports::WildcardImports::new(warn_on_all_wildcard_imports))); store.register_late_pass(|_| Box::::default()); store.register_late_pass(|_| Box::new(unnamed_address::UnnamedAddress)); - store.register_late_pass(move |_| Box::new(dereference::Dereferencing::new(msrv))); + store.register_late_pass(move |_| Box::new(dereference::Dereferencing::new(msrv()))); store.register_late_pass(|_| Box::new(option_if_let_else::OptionIfLetElse)); store.register_late_pass(|_| Box::new(future_not_send::FutureNotSend)); store.register_late_pass(|_| Box::new(if_let_mutex::IfLetMutex)); @@ -840,7 +802,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::::default()); store.register_late_pass(|_| Box::new(redundant_slicing::RedundantSlicing)); store.register_late_pass(|_| Box::new(from_str_radix_10::FromStrRadix10)); - store.register_late_pass(move |_| Box::new(if_then_some_else_none::IfThenSomeElseNone::new(msrv))); + store.register_late_pass(move |_| Box::new(if_then_some_else_none::IfThenSomeElseNone::new(msrv()))); store.register_late_pass(|_| Box::new(bool_assert_comparison::BoolAssertComparison)); store.register_early_pass(move || Box::new(module_style::ModStyle)); store.register_late_pass(|_| Box::new(unused_async::UnusedAsync)); @@ -865,14 +827,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: )) }); store.register_late_pass(move |_| Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks)); - store.register_late_pass(move |_| Box::new(format_args::FormatArgs::new(msrv))); + store.register_late_pass(move |_| Box::new(format_args::FormatArgs::new(msrv()))); store.register_late_pass(|_| Box::new(trailing_empty_array::TrailingEmptyArray)); store.register_early_pass(|| Box::new(octal_escapes::OctalEscapes)); store.register_late_pass(|_| Box::new(needless_late_init::NeedlessLateInit)); store.register_late_pass(|_| Box::new(return_self_not_must_use::ReturnSelfNotMustUse)); store.register_late_pass(|_| Box::new(init_numbered_fields::NumberedFields)); store.register_early_pass(|| Box::new(single_char_lifetime_names::SingleCharLifetimeNames)); - store.register_late_pass(move |_| Box::new(manual_bits::ManualBits::new(msrv))); + store.register_late_pass(move |_| Box::new(manual_bits::ManualBits::new(msrv()))); store.register_late_pass(|_| Box::new(default_union_representation::DefaultUnionRepresentation)); store.register_late_pass(|_| Box::::default()); let allow_dbg_in_tests = conf.allow_dbg_in_tests; @@ -896,20 +858,20 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(rc_clone_in_vec_init::RcCloneInVecInit)); store.register_early_pass(|| Box::::default()); store.register_early_pass(|| Box::new(unused_rounding::UnusedRounding)); - store.register_early_pass(move || Box::new(almost_complete_letter_range::AlmostCompleteLetterRange::new(msrv))); + store.register_early_pass(move || Box::new(almost_complete_letter_range::AlmostCompleteLetterRange::new(msrv()))); store.register_late_pass(|_| Box::new(swap_ptr_to_ref::SwapPtrToRef)); store.register_late_pass(|_| Box::new(mismatching_type_param_order::TypeParamMismatch)); store.register_late_pass(|_| Box::new(read_zero_byte_vec::ReadZeroByteVec)); store.register_late_pass(|_| Box::new(default_instead_of_iter_empty::DefaultIterEmpty)); - store.register_late_pass(move |_| Box::new(manual_rem_euclid::ManualRemEuclid::new(msrv))); - store.register_late_pass(move |_| Box::new(manual_retain::ManualRetain::new(msrv))); + store.register_late_pass(move |_| Box::new(manual_rem_euclid::ManualRemEuclid::new(msrv()))); + store.register_late_pass(move |_| Box::new(manual_retain::ManualRetain::new(msrv()))); let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold; store.register_late_pass(move |_| Box::new(operators::Operators::new(verbose_bit_mask_threshold))); store.register_late_pass(|_| Box::new(invalid_utf8_in_unchecked::InvalidUtf8InUnchecked)); store.register_late_pass(|_| Box::::default()); - store.register_late_pass(move |_| Box::new(instant_subtraction::InstantSubtraction::new(msrv))); + store.register_late_pass(move |_| Box::new(instant_subtraction::InstantSubtraction::new(msrv()))); store.register_late_pass(|_| Box::new(partialeq_to_none::PartialeqToNone)); - store.register_late_pass(move |_| Box::new(manual_clamp::ManualClamp::new(msrv))); + store.register_late_pass(move |_| Box::new(manual_clamp::ManualClamp::new(msrv()))); store.register_late_pass(|_| Box::new(manual_string_new::ManualStringNew)); store.register_late_pass(|_| Box::new(unused_peekable::UnusedPeekable)); store.register_early_pass(|| Box::new(multi_assignments::MultiAssignments)); @@ -920,7 +882,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(missing_trait_methods::MissingTraitMethods)); store.register_late_pass(|_| Box::new(from_raw_with_void_ptr::FromRawWithVoidPtr)); store.register_late_pass(|_| Box::new(suspicious_xor_used_as_pow::ConfusingXorAndPow)); - store.register_late_pass(move |_| Box::new(manual_is_ascii_check::ManualIsAsciiCheck::new(msrv))); + store.register_late_pass(move |_| Box::new(manual_is_ascii_check::ManualIsAsciiCheck::new(msrv()))); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/manual_bits.rs b/clippy_lints/src/manual_bits.rs index 6655c92b1da..462d73cf0b9 100644 --- a/clippy_lints/src/manual_bits.rs +++ b/clippy_lints/src/manual_bits.rs @@ -1,12 +1,12 @@ use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::get_parent_expr; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::{get_parent_expr, meets_msrv, msrvs}; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, GenericArg, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, Ty}; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::sym; @@ -34,12 +34,12 @@ declare_clippy_lint! { #[derive(Clone)] pub struct ManualBits { - msrv: Option, + msrv: Msrv, } impl ManualBits { #[must_use] - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv } } } @@ -48,7 +48,7 @@ impl_lint_pass!(ManualBits => [MANUAL_BITS]); impl<'tcx> LateLintPass<'tcx> for ManualBits { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if !meets_msrv(self.msrv, msrvs::MANUAL_BITS) { + if !self.msrv.meets(msrvs::MANUAL_BITS) { return; } diff --git a/clippy_lints/src/manual_clamp.rs b/clippy_lints/src/manual_clamp.rs index 02dc8755dd6..bb6d628af3b 100644 --- a/clippy_lints/src/manual_clamp.rs +++ b/clippy_lints/src/manual_clamp.rs @@ -1,28 +1,25 @@ +use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; +use clippy_utils::higher::If; +use clippy_utils::msrvs::{self, Msrv}; +use clippy_utils::sugg::Sugg; +use clippy_utils::ty::implements_trait; +use clippy_utils::visitors::is_const_evaluatable; +use clippy_utils::MaybePath; +use clippy_utils::{ + eq_expr_value, is_diag_trait_item, is_trait_method, path_res, path_to_local_id, peel_blocks, peel_blocks_with_stmt, +}; use itertools::Itertools; +use rustc_errors::Applicability; use rustc_errors::Diagnostic; use rustc_hir::{ def::Res, Arm, BinOpKind, Block, Expr, ExprKind, Guard, HirId, PatKind, PathSegment, PrimTy, QPath, StmtKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::{symbol::sym, Span}; use std::ops::Deref; -use clippy_utils::{ - diagnostics::{span_lint_and_then, span_lint_hir_and_then}, - eq_expr_value, - higher::If, - is_diag_trait_item, is_trait_method, meets_msrv, msrvs, path_res, path_to_local_id, peel_blocks, - peel_blocks_with_stmt, - sugg::Sugg, - ty::implements_trait, - visitors::is_const_evaluatable, - MaybePath, -}; -use rustc_errors::Applicability; - declare_clippy_lint! { /// ### What it does /// Identifies good opportunities for a clamp function from std or core, and suggests using it. @@ -87,11 +84,11 @@ declare_clippy_lint! { impl_lint_pass!(ManualClamp => [MANUAL_CLAMP]); pub struct ManualClamp { - msrv: Option, + msrv: Msrv, } impl ManualClamp { - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv } } } @@ -114,7 +111,7 @@ struct InputMinMax<'tcx> { impl<'tcx> LateLintPass<'tcx> for ManualClamp { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - if !meets_msrv(self.msrv, msrvs::CLAMP) { + if !self.msrv.meets(msrvs::CLAMP) { return; } if !expr.span.from_expansion() { @@ -130,7 +127,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualClamp { } fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) { - if !meets_msrv(self.msrv, msrvs::CLAMP) { + if !self.msrv.meets(msrvs::CLAMP) { return; } for suggestion in is_two_if_pattern(cx, block) { diff --git a/clippy_lints/src/manual_is_ascii_check.rs b/clippy_lints/src/manual_is_ascii_check.rs index bb8c142f8e4..5ab049d8d13 100644 --- a/clippy_lints/src/manual_is_ascii_check.rs +++ b/clippy_lints/src/manual_is_ascii_check.rs @@ -1,15 +1,12 @@ +use clippy_utils::msrvs::{self, Msrv}; +use clippy_utils::{diagnostics::span_lint_and_sugg, in_constant, macros::root_macro_call, source::snippet}; use rustc_ast::LitKind::{Byte, Char}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, PatKind, RangeEnd}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::{def_id::DefId, sym}; -use clippy_utils::{ - diagnostics::span_lint_and_sugg, in_constant, macros::root_macro_call, meets_msrv, msrvs, source::snippet, -}; - declare_clippy_lint! { /// ### What it does /// Suggests to use dedicated built-in methods, @@ -45,12 +42,12 @@ declare_clippy_lint! { impl_lint_pass!(ManualIsAsciiCheck => [MANUAL_IS_ASCII_CHECK]); pub struct ManualIsAsciiCheck { - msrv: Option, + msrv: Msrv, } impl ManualIsAsciiCheck { #[must_use] - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv } } } @@ -70,11 +67,11 @@ enum CharRange { impl<'tcx> LateLintPass<'tcx> for ManualIsAsciiCheck { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if !meets_msrv(self.msrv, msrvs::IS_ASCII_DIGIT) { + if !self.msrv.meets(msrvs::IS_ASCII_DIGIT) { return; } - if in_constant(cx, expr.hir_id) && !meets_msrv(self.msrv, msrvs::IS_ASCII_DIGIT_CONST) { + if in_constant(cx, expr.hir_id) && !self.msrv.meets(msrvs::IS_ASCII_DIGIT_CONST) { return; } diff --git a/clippy_lints/src/manual_let_else.rs b/clippy_lints/src/manual_let_else.rs index 1846596fa4c..20f06830952 100644 --- a/clippy_lints/src/manual_let_else.rs +++ b/clippy_lints/src/manual_let_else.rs @@ -1,16 +1,16 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::IfLetOrMatch; +use clippy_utils::msrvs::{self, Msrv}; +use clippy_utils::peel_blocks; use clippy_utils::source::snippet_opt; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::visitors::{for_each_expr, Descend}; -use clippy_utils::{meets_msrv, msrvs, peel_blocks}; use if_chain::if_chain; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, MatchSource, Pat, PatKind, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::symbol::sym; use rustc_span::Span; @@ -50,13 +50,13 @@ declare_clippy_lint! { } pub struct ManualLetElse { - msrv: Option, + msrv: Msrv, matches_behaviour: MatchLintBehaviour, } impl ManualLetElse { #[must_use] - pub fn new(msrv: Option, matches_behaviour: MatchLintBehaviour) -> Self { + pub fn new(msrv: Msrv, matches_behaviour: MatchLintBehaviour) -> Self { Self { msrv, matches_behaviour, @@ -69,7 +69,7 @@ impl_lint_pass!(ManualLetElse => [MANUAL_LET_ELSE]); impl<'tcx> LateLintPass<'tcx> for ManualLetElse { fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &'tcx Stmt<'tcx>) { let if_let_or_match = if_chain! { - if meets_msrv(self.msrv, msrvs::LET_ELSE); + if self.msrv.meets(msrvs::LET_ELSE); if !in_external_macro(cx.sess(), stmt.span); if let StmtKind::Local(local) = stmt.kind; if let Some(init) = local.init; diff --git a/clippy_lints/src/manual_non_exhaustive.rs b/clippy_lints/src/manual_non_exhaustive.rs index 6a42275322b..d32fa1121f4 100644 --- a/clippy_lints/src/manual_non_exhaustive.rs +++ b/clippy_lints/src/manual_non_exhaustive.rs @@ -1,6 +1,7 @@ use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; +use clippy_utils::is_doc_hidden; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_opt; -use clippy_utils::{is_doc_hidden, meets_msrv, msrvs}; use rustc_ast::ast::{self, VisibilityKind}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; @@ -8,7 +9,6 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::{self as hir, Expr, ExprKind, QPath}; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; use rustc_middle::ty::DefIdTree; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::{sym, Span}; @@ -63,12 +63,12 @@ declare_clippy_lint! { #[expect(clippy::module_name_repetitions)] pub struct ManualNonExhaustiveStruct { - msrv: Option, + msrv: Msrv, } impl ManualNonExhaustiveStruct { #[must_use] - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv } } } @@ -77,14 +77,14 @@ impl_lint_pass!(ManualNonExhaustiveStruct => [MANUAL_NON_EXHAUSTIVE]); #[expect(clippy::module_name_repetitions)] pub struct ManualNonExhaustiveEnum { - msrv: Option, + msrv: Msrv, constructed_enum_variants: FxHashSet<(DefId, DefId)>, potential_enums: Vec<(LocalDefId, LocalDefId, Span, Span)>, } impl ManualNonExhaustiveEnum { #[must_use] - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv, constructed_enum_variants: FxHashSet::default(), @@ -97,7 +97,7 @@ impl_lint_pass!(ManualNonExhaustiveEnum => [MANUAL_NON_EXHAUSTIVE]); impl EarlyLintPass for ManualNonExhaustiveStruct { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { - if !meets_msrv(self.msrv, msrvs::NON_EXHAUSTIVE) { + if !self.msrv.meets(msrvs::NON_EXHAUSTIVE) { return; } @@ -149,7 +149,7 @@ impl EarlyLintPass for ManualNonExhaustiveStruct { impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { - if !meets_msrv(self.msrv, msrvs::NON_EXHAUSTIVE) { + if !self.msrv.meets(msrvs::NON_EXHAUSTIVE) { return; } diff --git a/clippy_lints/src/manual_rem_euclid.rs b/clippy_lints/src/manual_rem_euclid.rs index 6f25a2ed8e4..8d447c37150 100644 --- a/clippy_lints/src/manual_rem_euclid.rs +++ b/clippy_lints/src/manual_rem_euclid.rs @@ -1,12 +1,12 @@ use clippy_utils::consts::{constant_full_int, FullInt}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::{in_constant, meets_msrv, msrvs, path_to_local}; +use clippy_utils::{in_constant, path_to_local}; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, Node, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; declare_clippy_lint! { @@ -34,12 +34,12 @@ declare_clippy_lint! { } pub struct ManualRemEuclid { - msrv: Option, + msrv: Msrv, } impl ManualRemEuclid { #[must_use] - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv } } } @@ -48,11 +48,11 @@ impl_lint_pass!(ManualRemEuclid => [MANUAL_REM_EUCLID]); impl<'tcx> LateLintPass<'tcx> for ManualRemEuclid { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if !meets_msrv(self.msrv, msrvs::REM_EUCLID) { + if !self.msrv.meets(msrvs::REM_EUCLID) { return; } - if in_constant(cx, expr.hir_id) && !meets_msrv(self.msrv, msrvs::REM_EUCLID_CONST) { + if in_constant(cx, expr.hir_id) && !self.msrv.meets(msrvs::REM_EUCLID_CONST) { return; } diff --git a/clippy_lints/src/manual_retain.rs b/clippy_lints/src/manual_retain.rs index 3181bc86d17..4907f02b5a3 100644 --- a/clippy_lints/src/manual_retain.rs +++ b/clippy_lints/src/manual_retain.rs @@ -1,8 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{get_parent_expr, match_def_path, paths, SpanlessEq}; -use clippy_utils::{meets_msrv, msrvs}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -50,12 +50,12 @@ declare_clippy_lint! { } pub struct ManualRetain { - msrv: Option, + msrv: Msrv, } impl ManualRetain { #[must_use] - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv } } } @@ -71,9 +71,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualRetain { && let hir::ExprKind::MethodCall(_, target_expr, [], _) = &collect_expr.kind && let Some(collect_def_id) = cx.typeck_results().type_dependent_def_id(collect_expr.hir_id) && match_def_path(cx, collect_def_id, &paths::CORE_ITER_COLLECT) { - check_into_iter(cx, parent_expr, left_expr, target_expr, self.msrv); - check_iter(cx, parent_expr, left_expr, target_expr, self.msrv); - check_to_owned(cx, parent_expr, left_expr, target_expr, self.msrv); + check_into_iter(cx, parent_expr, left_expr, target_expr, &self.msrv); + check_iter(cx, parent_expr, left_expr, target_expr, &self.msrv); + check_to_owned(cx, parent_expr, left_expr, target_expr, &self.msrv); } } @@ -85,7 +85,7 @@ fn check_into_iter( parent_expr: &hir::Expr<'_>, left_expr: &hir::Expr<'_>, target_expr: &hir::Expr<'_>, - msrv: Option, + msrv: &Msrv, ) { if let hir::ExprKind::MethodCall(_, into_iter_expr, [_], _) = &target_expr.kind && let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id) @@ -104,7 +104,7 @@ fn check_iter( parent_expr: &hir::Expr<'_>, left_expr: &hir::Expr<'_>, target_expr: &hir::Expr<'_>, - msrv: Option, + msrv: &Msrv, ) { if let hir::ExprKind::MethodCall(_, filter_expr, [], _) = &target_expr.kind && let Some(copied_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id) @@ -127,9 +127,9 @@ fn check_to_owned( parent_expr: &hir::Expr<'_>, left_expr: &hir::Expr<'_>, target_expr: &hir::Expr<'_>, - msrv: Option, + msrv: &Msrv, ) { - if meets_msrv(msrv, msrvs::STRING_RETAIN) + if msrv.meets(msrvs::STRING_RETAIN) && let hir::ExprKind::MethodCall(_, filter_expr, [], _) = &target_expr.kind && let Some(to_owned_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id) && match_def_path(cx, to_owned_def_id, &paths::TO_OWNED_METHOD) @@ -215,10 +215,10 @@ fn match_acceptable_def_path(cx: &LateContext<'_>, collect_def_id: DefId) -> boo .any(|&method| match_def_path(cx, collect_def_id, method)) } -fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, msrv: Option) -> bool { +fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, msrv: &Msrv) -> bool { let expr_ty = cx.typeck_results().expr_ty(expr).peel_refs(); ACCEPTABLE_TYPES.iter().any(|(ty, acceptable_msrv)| { is_type_diagnostic_item(cx, expr_ty, *ty) - && acceptable_msrv.map_or(true, |acceptable_msrv| meets_msrv(msrv, acceptable_msrv)) + && acceptable_msrv.map_or(true, |acceptable_msrv| msrv.meets(acceptable_msrv)) }) } diff --git a/clippy_lints/src/manual_strip.rs b/clippy_lints/src/manual_strip.rs index 0976940afac..de166b9765f 100644 --- a/clippy_lints/src/manual_strip.rs +++ b/clippy_lints/src/manual_strip.rs @@ -1,8 +1,9 @@ use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; use clippy_utils::usage::mutated_variables; -use clippy_utils::{eq_expr_value, higher, match_def_path, meets_msrv, msrvs, paths}; +use clippy_utils::{eq_expr_value, higher, match_def_path, paths}; use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_hir::def::Res; @@ -11,7 +12,6 @@ use rustc_hir::BinOpKind; use rustc_hir::{BorrowKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Spanned; use rustc_span::Span; @@ -48,12 +48,12 @@ declare_clippy_lint! { } pub struct ManualStrip { - msrv: Option, + msrv: Msrv, } impl ManualStrip { #[must_use] - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv } } } @@ -68,7 +68,7 @@ enum StripKind { impl<'tcx> LateLintPass<'tcx> for ManualStrip { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if !meets_msrv(self.msrv, msrvs::STR_STRIP_PREFIX) { + if !self.msrv.meets(msrvs::STR_STRIP_PREFIX) { return; } diff --git a/clippy_lints/src/matches/mod.rs b/clippy_lints/src/matches/mod.rs index 7d8171ead89..7b15a307fec 100644 --- a/clippy_lints/src/matches/mod.rs +++ b/clippy_lints/src/matches/mod.rs @@ -23,13 +23,13 @@ mod single_match; mod try_err; mod wild_in_or_pats; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{snippet_opt, walk_span_to_context}; -use clippy_utils::{higher, in_constant, is_span_match, meets_msrv, msrvs}; +use clippy_utils::{higher, in_constant, is_span_match}; use rustc_hir::{Arm, Expr, ExprKind, Local, MatchSource, Pat}; use rustc_lexer::{tokenize, TokenKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::{Span, SpanData, SyntaxContext}; @@ -930,13 +930,13 @@ declare_clippy_lint! { #[derive(Default)] pub struct Matches { - msrv: Option, + msrv: Msrv, infallible_destructuring_match_linted: bool, } impl Matches { #[must_use] - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv, ..Matches::default() @@ -1000,9 +1000,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches { if !from_expansion && !contains_cfg_arm(cx, expr, ex, arms) { if source == MatchSource::Normal { - if !(meets_msrv(self.msrv, msrvs::MATCHES_MACRO) - && match_like_matches::check_match(cx, expr, ex, arms)) - { + if !(self.msrv.meets(msrvs::MATCHES_MACRO) && match_like_matches::check_match(cx, expr, ex, arms)) { match_same_arms::check(cx, arms); } @@ -1034,7 +1032,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches { collapsible_match::check_if_let(cx, if_let.let_pat, if_let.if_then, if_let.if_else); if !from_expansion { if let Some(else_expr) = if_let.if_else { - if meets_msrv(self.msrv, msrvs::MATCHES_MACRO) { + if self.msrv.meets(msrvs::MATCHES_MACRO) { match_like_matches::check_if_let( cx, expr, diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index 0c4d9f100f7..35024ec1224 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -1,14 +1,14 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{snippet, snippet_with_applicability}; use clippy_utils::ty::is_non_aggregate_primitive_type; -use clippy_utils::{is_default_equivalent, is_res_lang_ctor, meets_msrv, msrvs, path_res}; +use clippy_utils::{is_default_equivalent, is_res_lang_ctor, path_res}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::LangItem::OptionNone; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; use rustc_span::symbol::sym; @@ -227,12 +227,12 @@ fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr< } pub struct MemReplace { - msrv: Option, + msrv: Msrv, } impl MemReplace { #[must_use] - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv } } } @@ -248,7 +248,7 @@ impl<'tcx> LateLintPass<'tcx> for MemReplace { then { check_replace_option_with_none(cx, src, dest, expr.span); check_replace_with_uninit(cx, src, dest, expr.span); - if meets_msrv(self.msrv, msrvs::MEM_TAKE) { + if self.msrv.meets(msrvs::MEM_TAKE) { check_replace_with_default(cx, src, dest, expr.span); } } diff --git a/clippy_lints/src/methods/cloned_instead_of_copied.rs b/clippy_lints/src/methods/cloned_instead_of_copied.rs index e9aeab2d5b6..4e6ec61f6a8 100644 --- a/clippy_lints/src/methods/cloned_instead_of_copied.rs +++ b/clippy_lints/src/methods/cloned_instead_of_copied.rs @@ -1,25 +1,25 @@ use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_trait_method; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::ty::{get_iterator_item_ty, is_copy}; -use clippy_utils::{is_trait_method, meets_msrv, msrvs}; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; use rustc_middle::ty; -use rustc_semver::RustcVersion; use rustc_span::{sym, Span}; use super::CLONED_INSTEAD_OF_COPIED; -pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span: Span, msrv: Option) { +pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span: Span, msrv: &Msrv) { let recv_ty = cx.typeck_results().expr_ty_adjusted(recv); let inner_ty = match recv_ty.kind() { // `Option` -> `T` ty::Adt(adt, subst) - if cx.tcx.is_diagnostic_item(sym::Option, adt.did()) && meets_msrv(msrv, msrvs::OPTION_COPIED) => + if cx.tcx.is_diagnostic_item(sym::Option, adt.did()) && msrv.meets(msrvs::OPTION_COPIED) => { subst.type_at(0) }, - _ if is_trait_method(cx, expr, sym::Iterator) && meets_msrv(msrv, msrvs::ITERATOR_COPIED) => { + _ if is_trait_method(cx, expr, sym::Iterator) && msrv.meets(msrvs::ITERATOR_COPIED) => { match get_iterator_item_ty(cx, recv_ty) { // ::Item Some(ty) => ty, diff --git a/clippy_lints/src/methods/err_expect.rs b/clippy_lints/src/methods/err_expect.rs index 720d9a68c85..ae03da0d3f9 100644 --- a/clippy_lints/src/methods/err_expect.rs +++ b/clippy_lints/src/methods/err_expect.rs @@ -1,27 +1,27 @@ use super::ERR_EXPECT; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::ty::has_debug_impl; -use clippy_utils::{meets_msrv, msrvs, ty::is_type_diagnostic_item}; +use clippy_utils::ty::is_type_diagnostic_item; use rustc_errors::Applicability; use rustc_lint::LateContext; use rustc_middle::ty; use rustc_middle::ty::Ty; -use rustc_semver::RustcVersion; use rustc_span::{sym, Span}; pub(super) fn check( cx: &LateContext<'_>, _expr: &rustc_hir::Expr<'_>, recv: &rustc_hir::Expr<'_>, - msrv: Option, expect_span: Span, err_span: Span, + msrv: &Msrv, ) { if_chain! { if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result); // Test the version to make sure the lint can be showed (expect_err has been // introduced in rust 1.17.0 : https://github.com/rust-lang/rust/pull/38982) - if meets_msrv(msrv, msrvs::EXPECT_ERR); + if msrv.meets(msrvs::EXPECT_ERR); // Grabs the `Result` type let result_type = cx.typeck_results().expr_ty(recv); diff --git a/clippy_lints/src/methods/filter_map_next.rs b/clippy_lints/src/methods/filter_map_next.rs index ddf8a1f09b8..175e04f8ac0 100644 --- a/clippy_lints/src/methods/filter_map_next.rs +++ b/clippy_lints/src/methods/filter_map_next.rs @@ -1,10 +1,10 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; +use clippy_utils::is_trait_method; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; -use clippy_utils::{is_trait_method, meets_msrv, msrvs}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; -use rustc_semver::RustcVersion; use rustc_span::sym; use super::FILTER_MAP_NEXT; @@ -14,10 +14,10 @@ pub(super) fn check<'tcx>( expr: &'tcx hir::Expr<'_>, recv: &'tcx hir::Expr<'_>, arg: &'tcx hir::Expr<'_>, - msrv: Option, + msrv: &Msrv, ) { if is_trait_method(cx, expr, sym::Iterator) { - if !meets_msrv(msrv, msrvs::ITERATOR_FIND_MAP) { + if !msrv.meets(msrvs::ITERATOR_FIND_MAP) { return; } diff --git a/clippy_lints/src/methods/is_digit_ascii_radix.rs b/clippy_lints/src/methods/is_digit_ascii_radix.rs index 304024e8066..301aff5ae6a 100644 --- a/clippy_lints/src/methods/is_digit_ascii_radix.rs +++ b/clippy_lints/src/methods/is_digit_ascii_radix.rs @@ -1,23 +1,22 @@ //! Lint for `c.is_digit(10)` use super::IS_DIGIT_ASCII_RADIX; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::{ - consts::constant_full_int, consts::FullInt, diagnostics::span_lint_and_sugg, meets_msrv, msrvs, - source::snippet_with_applicability, + consts::constant_full_int, consts::FullInt, diagnostics::span_lint_and_sugg, source::snippet_with_applicability, }; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; -use rustc_semver::RustcVersion; pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, self_arg: &'tcx Expr<'_>, radix: &'tcx Expr<'_>, - msrv: Option, + msrv: &Msrv, ) { - if !meets_msrv(msrv, msrvs::IS_ASCII_DIGIT) { + if !msrv.meets(msrvs::IS_ASCII_DIGIT) { return; } diff --git a/clippy_lints/src/methods/map_clone.rs b/clippy_lints/src/methods/map_clone.rs index 6bc783c6d50..52cc1e0464b 100644 --- a/clippy_lints/src/methods/map_clone.rs +++ b/clippy_lints/src/methods/map_clone.rs @@ -1,7 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::{is_copy, is_type_diagnostic_item}; -use clippy_utils::{is_diag_trait_item, meets_msrv, msrvs, peel_blocks}; +use clippy_utils::{is_diag_trait_item, peel_blocks}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; @@ -9,19 +10,12 @@ use rustc_lint::LateContext; use rustc_middle::mir::Mutability; use rustc_middle::ty; use rustc_middle::ty::adjustment::Adjust; -use rustc_semver::RustcVersion; use rustc_span::symbol::Ident; use rustc_span::{sym, Span}; use super::MAP_CLONE; -pub(super) fn check( - cx: &LateContext<'_>, - e: &hir::Expr<'_>, - recv: &hir::Expr<'_>, - arg: &hir::Expr<'_>, - msrv: Option, -) { +pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>, msrv: &Msrv) { if_chain! { if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id); if cx.tcx.impl_of_method(method_id) @@ -97,10 +91,10 @@ fn lint_needless_cloning(cx: &LateContext<'_>, root: Span, receiver: Span) { ); } -fn lint_explicit_closure(cx: &LateContext<'_>, replace: Span, root: Span, is_copy: bool, msrv: Option) { +fn lint_explicit_closure(cx: &LateContext<'_>, replace: Span, root: Span, is_copy: bool, msrv: &Msrv) { let mut applicability = Applicability::MachineApplicable; - let (message, sugg_method) = if is_copy && meets_msrv(msrv, msrvs::ITERATOR_COPIED) { + let (message, sugg_method) = if is_copy && msrv.meets(msrvs::ITERATOR_COPIED) { ("you are using an explicit closure for copying elements", "copied") } else { ("you are using an explicit closure for cloning elements", "cloned") diff --git a/clippy_lints/src/methods/map_unwrap_or.rs b/clippy_lints/src/methods/map_unwrap_or.rs index 74fdead216b..3122f72ee91 100644 --- a/clippy_lints/src/methods/map_unwrap_or.rs +++ b/clippy_lints/src/methods/map_unwrap_or.rs @@ -1,12 +1,11 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::usage::mutated_variables; -use clippy_utils::{meets_msrv, msrvs}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; -use rustc_semver::RustcVersion; use rustc_span::symbol::sym; use super::MAP_UNWRAP_OR; @@ -19,13 +18,13 @@ pub(super) fn check<'tcx>( recv: &'tcx hir::Expr<'_>, map_arg: &'tcx hir::Expr<'_>, unwrap_arg: &'tcx hir::Expr<'_>, - msrv: Option, + msrv: &Msrv, ) -> bool { // lint if the caller of `map()` is an `Option` let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option); let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result); - if is_result && !meets_msrv(msrv, msrvs::RESULT_MAP_OR_ELSE) { + if is_result && !msrv.meets(msrvs::RESULT_MAP_OR_ELSE) { return false; } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index acb3b20a61b..c5451195727 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -104,8 +104,9 @@ mod zst_offset; use bind_instead_of_map::BindInsteadOfMap; use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::ty::{contains_ty_adt_constructor_opaque, implements_trait, is_copy, is_type_diagnostic_item}; -use clippy_utils::{contains_return, is_bool, is_trait_method, iter_input_pats, meets_msrv, msrvs, return_ty}; +use clippy_utils::{contains_return, is_bool, is_trait_method, iter_input_pats, return_ty}; use if_chain::if_chain; use rustc_hir as hir; use rustc_hir::{Expr, ExprKind, TraitItem, TraitItemKind}; @@ -113,7 +114,6 @@ use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, TraitRef, Ty}; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::{sym, Span}; @@ -3163,7 +3163,7 @@ declare_clippy_lint! { pub struct Methods { avoid_breaking_exported_api: bool, - msrv: Option, + msrv: Msrv, allow_expect_in_tests: bool, allow_unwrap_in_tests: bool, } @@ -3172,7 +3172,7 @@ impl Methods { #[must_use] pub fn new( avoid_breaking_exported_api: bool, - msrv: Option, + msrv: Msrv, allow_expect_in_tests: bool, allow_unwrap_in_tests: bool, ) -> Self { @@ -3325,7 +3325,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { single_char_add_str::check(cx, expr, receiver, args); into_iter_on_ref::check(cx, expr, method_span, method_call.ident.name, receiver); single_char_pattern::check(cx, expr, method_call.ident.name, receiver, args); - unnecessary_to_owned::check(cx, expr, method_call.ident.name, receiver, args, self.msrv); + unnecessary_to_owned::check(cx, expr, method_call.ident.name, receiver, args, &self.msrv); }, hir::ExprKind::Binary(op, lhs, rhs) if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne => { let mut info = BinaryExprInfo { @@ -3501,7 +3501,7 @@ impl Methods { ("as_mut", []) => useless_asref::check(cx, expr, "as_mut", recv), ("as_ref", []) => useless_asref::check(cx, expr, "as_ref", recv), ("assume_init", []) => uninit_assumed_init::check(cx, expr, recv), - ("cloned", []) => cloned_instead_of_copied::check(cx, expr, recv, span, self.msrv), + ("cloned", []) => cloned_instead_of_copied::check(cx, expr, recv, span, &self.msrv), ("collect", []) if is_trait_method(cx, expr, sym::Iterator) => { needless_collect::check(cx, span, expr, recv, call_span); match method_call(recv) { @@ -3512,7 +3512,7 @@ impl Methods { map_collect_result_unit::check(cx, expr, m_recv, m_arg); }, Some(("take", take_self_arg, [take_arg], _, _)) => { - if meets_msrv(self.msrv, msrvs::STR_REPEAT) { + if self.msrv.meets(msrvs::STR_REPEAT) { manual_str_repeat::check(cx, expr, recv, take_self_arg, take_arg); } }, @@ -3539,7 +3539,7 @@ impl Methods { }, ("expect", [_]) => match method_call(recv) { Some(("ok", recv, [], _, _)) => ok_expect::check(cx, expr, recv), - Some(("err", recv, [], err_span, _)) => err_expect::check(cx, expr, recv, self.msrv, span, err_span), + Some(("err", recv, [], err_span, _)) => err_expect::check(cx, expr, recv, span, err_span, &self.msrv), _ => expect_used::check(cx, expr, recv, false, self.allow_expect_in_tests), }, ("expect_err", [_]) => expect_used::check(cx, expr, recv, true, self.allow_expect_in_tests), @@ -3578,7 +3578,7 @@ impl Methods { unit_hash::check(cx, expr, recv, arg); }, ("is_file", []) => filetype_is_file::check(cx, expr, recv), - ("is_digit", [radix]) => is_digit_ascii_radix::check(cx, expr, recv, radix, self.msrv), + ("is_digit", [radix]) => is_digit_ascii_radix::check(cx, expr, recv, radix, &self.msrv), ("is_none", []) => check_is_some_is_none(cx, expr, recv, false), ("is_some", []) => check_is_some_is_none(cx, expr, recv, true), ("iter" | "iter_mut" | "into_iter", []) => { @@ -3601,7 +3601,7 @@ impl Methods { }, (name @ ("map" | "map_err"), [m_arg]) => { if name == "map" { - map_clone::check(cx, expr, recv, m_arg, self.msrv); + map_clone::check(cx, expr, recv, m_arg, &self.msrv); if let Some((map_name @ ("iter" | "into_iter"), recv2, _, _, _)) = method_call(recv) { iter_kv_map::check(cx, map_name, expr, recv2, m_arg); } @@ -3610,8 +3610,8 @@ impl Methods { } if let Some((name, recv2, args, span2,_)) = method_call(recv) { match (name, args) { - ("as_mut", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, true, self.msrv), - ("as_ref", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, false, self.msrv), + ("as_mut", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, true, &self.msrv), + ("as_ref", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, false, &self.msrv), ("filter", [f_arg]) => { filter_map::check(cx, expr, recv2, f_arg, span2, recv, m_arg, span, false); }, @@ -3632,7 +3632,7 @@ impl Methods { match (name2, args2) { ("cloned", []) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, false), ("filter", [arg]) => filter_next::check(cx, expr, recv2, arg), - ("filter_map", [arg]) => filter_map_next::check(cx, expr, recv2, arg, self.msrv), + ("filter_map", [arg]) => filter_map_next::check(cx, expr, recv2, arg, &self.msrv), ("iter", []) => iter_next_slice::check(cx, expr, recv2), ("skip", [arg]) => iter_skip_next::check(cx, expr, recv2, arg), ("skip_while", [_]) => skip_while_next::check(cx, expr), @@ -3680,10 +3680,10 @@ impl Methods { vec_resize_to_zero::check(cx, expr, count_arg, default_arg, span); }, ("seek", [arg]) => { - if meets_msrv(self.msrv, msrvs::SEEK_FROM_CURRENT) { + if self.msrv.meets(msrvs::SEEK_FROM_CURRENT) { seek_from_current::check(cx, expr, recv, arg); } - if meets_msrv(self.msrv, msrvs::SEEK_REWIND) { + if self.msrv.meets(msrvs::SEEK_REWIND) { seek_to_start_instead_of_rewind::check(cx, expr, recv, arg, span); } }, @@ -3699,7 +3699,7 @@ impl Methods { ("splitn" | "rsplitn", [count_arg, pat_arg]) => { if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg) { suspicious_splitn::check(cx, name, expr, recv, count); - str_splitn::check(cx, name, expr, recv, pat_arg, count, self.msrv); + str_splitn::check(cx, name, expr, recv, pat_arg, count, &self.msrv); } }, ("splitn_mut" | "rsplitn_mut", [count_arg, _]) => { @@ -3717,7 +3717,7 @@ impl Methods { }, ("take", []) => needless_option_take::check(cx, expr, recv), ("then", [arg]) => { - if !meets_msrv(self.msrv, msrvs::BOOL_THEN_SOME) { + if !self.msrv.meets(msrvs::BOOL_THEN_SOME) { return; } unnecessary_lazy_eval::check(cx, expr, recv, arg, "then_some"); @@ -3760,7 +3760,7 @@ impl Methods { }, ("unwrap_or_else", [u_arg]) => match method_call(recv) { Some(("map", recv, [map_arg], _, _)) - if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, self.msrv) => {}, + if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, &self.msrv) => {}, _ => { unwrap_or_else_default::check(cx, expr, recv, u_arg); unnecessary_lazy_eval::check(cx, expr, recv, u_arg, "unwrap_or"); diff --git a/clippy_lints/src/methods/option_as_ref_deref.rs b/clippy_lints/src/methods/option_as_ref_deref.rs index e6eb64bcbde..3e33f919337 100644 --- a/clippy_lints/src/methods/option_as_ref_deref.rs +++ b/clippy_lints/src/methods/option_as_ref_deref.rs @@ -1,13 +1,13 @@ use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; use clippy_utils::ty::is_type_diagnostic_item; -use clippy_utils::{match_def_path, meets_msrv, msrvs, path_to_local_id, paths, peel_blocks}; +use clippy_utils::{match_def_path, path_to_local_id, paths, peel_blocks}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_middle::ty; -use rustc_semver::RustcVersion; use rustc_span::sym; use super::OPTION_AS_REF_DEREF; @@ -19,9 +19,9 @@ pub(super) fn check( as_ref_recv: &hir::Expr<'_>, map_arg: &hir::Expr<'_>, is_mut: bool, - msrv: Option, + msrv: &Msrv, ) { - if !meets_msrv(msrv, msrvs::OPTION_AS_DEREF) { + if !msrv.meets(msrvs::OPTION_AS_DEREF) { return; } diff --git a/clippy_lints/src/methods/str_splitn.rs b/clippy_lints/src/methods/str_splitn.rs index 1acac59144c..3c01ce1fecd 100644 --- a/clippy_lints/src/methods/str_splitn.rs +++ b/clippy_lints/src/methods/str_splitn.rs @@ -1,9 +1,10 @@ use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_context; use clippy_utils::usage::local_used_after_expr; use clippy_utils::visitors::{for_each_expr_with_closures, Descend}; -use clippy_utils::{is_diag_item_method, match_def_path, meets_msrv, msrvs, path_to_local_id, paths}; +use clippy_utils::{is_diag_item_method, match_def_path, path_to_local_id, paths}; use core::ops::ControlFlow; use if_chain::if_chain; use rustc_errors::Applicability; @@ -12,7 +13,6 @@ use rustc_hir::{ }; use rustc_lint::LateContext; use rustc_middle::ty; -use rustc_semver::RustcVersion; use rustc_span::{sym, Span, Symbol, SyntaxContext}; use super::{MANUAL_SPLIT_ONCE, NEEDLESS_SPLITN}; @@ -24,7 +24,7 @@ pub(super) fn check( self_arg: &Expr<'_>, pat_arg: &Expr<'_>, count: u128, - msrv: Option, + msrv: &Msrv, ) { if count < 2 || !cx.typeck_results().expr_ty_adjusted(self_arg).peel_refs().is_str() { return; @@ -34,7 +34,7 @@ pub(super) fn check( IterUsageKind::Nth(n) => count > n + 1, IterUsageKind::NextTuple => count > 2, }; - let manual = count == 2 && meets_msrv(msrv, msrvs::STR_SPLIT_ONCE); + let manual = count == 2 && msrv.meets(msrvs::STR_SPLIT_ONCE); match parse_iter_usage(cx, expr.span.ctxt(), cx.tcx.hir().parent_iter(expr.hir_id)) { Some(usage) if needless(usage.kind) => lint_needless(cx, method_name, expr, self_arg, pat_arg), diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index 4b4f2f47b1d..21d1df4d0c2 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -1,11 +1,11 @@ use super::implicit_clone::is_clone_like; use super::unnecessary_iter_cloned::{self, is_into_iter}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_opt; use clippy_utils::ty::{get_associated_type, get_iterator_item_ty, implements_trait, is_copy, peel_mid_ty_refs}; use clippy_utils::visitors::find_all_ret_expressions; use clippy_utils::{fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, return_ty}; -use clippy_utils::{meets_msrv, msrvs}; use rustc_errors::Applicability; use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind, ItemKind, LangItem, Node}; use rustc_hir_analysis::check::{FnCtxt, Inherited}; @@ -16,7 +16,6 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; use rustc_middle::ty::EarlyBinder; use rustc_middle::ty::{self, ParamTy, PredicateKind, ProjectionPredicate, TraitPredicate, Ty}; -use rustc_semver::RustcVersion; use rustc_span::{sym, Symbol}; use rustc_trait_selection::traits::{query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause}; use std::cmp::max; @@ -29,7 +28,7 @@ pub fn check<'tcx>( method_name: Symbol, receiver: &'tcx Expr<'_>, args: &'tcx [Expr<'_>], - msrv: Option, + msrv: &Msrv, ) { if_chain! { if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); @@ -200,7 +199,7 @@ fn check_into_iter_call_arg( expr: &Expr<'_>, method_name: Symbol, receiver: &Expr<'_>, - msrv: Option, + msrv: &Msrv, ) -> bool { if_chain! { if let Some(parent) = get_parent_expr(cx, expr); @@ -215,7 +214,7 @@ fn check_into_iter_call_arg( if unnecessary_iter_cloned::check_for_loop_iter(cx, parent, method_name, receiver, true) { return true; } - let cloned_or_copied = if is_copy(cx, item_ty) && meets_msrv(msrv, msrvs::ITERATOR_COPIED) { + let cloned_or_copied = if is_copy(cx, item_ty) && msrv.meets(msrvs::ITERATOR_COPIED) { "copied" } else { "cloned" diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs index 71cc0d0a81c..5bc04bc17fb 100644 --- a/clippy_lints/src/missing_const_for_fn.rs +++ b/clippy_lints/src/missing_const_for_fn.rs @@ -1,9 +1,8 @@ use clippy_utils::diagnostics::span_lint; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::qualify_min_const_fn::is_min_const_fn; use clippy_utils::ty::has_drop; -use clippy_utils::{ - fn_has_unsatisfiable_preds, is_entrypoint_fn, is_from_proc_macro, meets_msrv, msrvs, trait_ref_of_method, -}; +use clippy_utils::{fn_has_unsatisfiable_preds, is_entrypoint_fn, is_from_proc_macro, trait_ref_of_method}; use rustc_hir as hir; use rustc_hir::def_id::CRATE_DEF_ID; use rustc_hir::intravisit::FnKind; @@ -11,7 +10,6 @@ use rustc_hir::{Body, Constness, FnDecl, GenericParamKind, HirId}; use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::Span; @@ -75,12 +73,12 @@ declare_clippy_lint! { impl_lint_pass!(MissingConstForFn => [MISSING_CONST_FOR_FN]); pub struct MissingConstForFn { - msrv: Option, + msrv: Msrv, } impl MissingConstForFn { #[must_use] - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv } } } @@ -95,7 +93,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { span: Span, hir_id: HirId, ) { - if !meets_msrv(self.msrv, msrvs::CONST_IF_MATCH) { + if !self.msrv.meets(msrvs::CONST_IF_MATCH) { return; } @@ -152,7 +150,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { let mir = cx.tcx.optimized_mir(def_id); - if let Err((span, err)) = is_min_const_fn(cx.tcx, mir, self.msrv) { + if let Err((span, err)) = is_min_const_fn(cx.tcx, mir, &self.msrv) { if cx.tcx.is_const_fn_raw(def_id.to_def_id()) { cx.tcx.sess.span_err(span, err.as_ref()); } diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index c6fbb5e805a..0a1b9d173cf 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -1,16 +1,16 @@ use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::higher; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability}; use clippy_utils::sugg::Sugg; -use clippy_utils::{get_parent_expr, in_constant, is_integer_const, meets_msrv, msrvs, path_to_local}; +use clippy_utils::{get_parent_expr, in_constant, is_integer_const, path_to_local}; use if_chain::if_chain; use rustc_ast::ast::RangeLimits; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, HirId}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::{Span, Spanned}; use std::cmp::Ordering; @@ -161,12 +161,12 @@ declare_clippy_lint! { } pub struct Ranges { - msrv: Option, + msrv: Msrv, } impl Ranges { #[must_use] - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv } } } @@ -181,7 +181,7 @@ impl_lint_pass!(Ranges => [ impl<'tcx> LateLintPass<'tcx> for Ranges { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let ExprKind::Binary(ref op, l, r) = expr.kind { - if meets_msrv(self.msrv, msrvs::RANGE_CONTAINS) { + if self.msrv.meets(msrvs::RANGE_CONTAINS) { check_possible_range_contains(cx, op.node, l, r, expr, expr.span); } } diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index 40b03068f6c..61bff4a0e38 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -1,10 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::{meets_msrv, msrvs}; +use clippy_utils::msrvs::{self, Msrv}; use rustc_ast::ast::{Expr, ExprKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; declare_clippy_lint! { @@ -37,12 +36,12 @@ declare_clippy_lint! { } pub struct RedundantFieldNames { - msrv: Option, + msrv: Msrv, } impl RedundantFieldNames { #[must_use] - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv } } } @@ -51,7 +50,7 @@ impl_lint_pass!(RedundantFieldNames => [REDUNDANT_FIELD_NAMES]); impl EarlyLintPass for RedundantFieldNames { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { - if !meets_msrv(self.msrv, msrvs::FIELD_INIT_SHORTHAND) { + if !self.msrv.meets(msrvs::FIELD_INIT_SHORTHAND) { return; } diff --git a/clippy_lints/src/redundant_static_lifetimes.rs b/clippy_lints/src/redundant_static_lifetimes.rs index 60ba62c4a43..3aa2490bc44 100644 --- a/clippy_lints/src/redundant_static_lifetimes.rs +++ b/clippy_lints/src/redundant_static_lifetimes.rs @@ -1,10 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; -use clippy_utils::{meets_msrv, msrvs}; use rustc_ast::ast::{Item, ItemKind, Ty, TyKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; declare_clippy_lint! { @@ -34,12 +33,12 @@ declare_clippy_lint! { } pub struct RedundantStaticLifetimes { - msrv: Option, + msrv: Msrv, } impl RedundantStaticLifetimes { #[must_use] - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv } } } @@ -96,7 +95,7 @@ impl RedundantStaticLifetimes { impl EarlyLintPass for RedundantStaticLifetimes { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - if !meets_msrv(self.msrv, msrvs::STATIC_IN_CONST) { + if !self.msrv.meets(msrvs::STATIC_IN_CONST) { return; } diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index 424a6e9264e..83e651aba8e 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -16,10 +16,10 @@ mod utils; mod wrong_transmute; use clippy_utils::in_constant; +use clippy_utils::msrvs::Msrv; use if_chain::if_chain; use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::symbol::sym; @@ -410,7 +410,7 @@ declare_clippy_lint! { } pub struct Transmute { - msrv: Option, + msrv: Msrv, } impl_lint_pass!(Transmute => [ CROSSPOINTER_TRANSMUTE, @@ -431,7 +431,7 @@ impl_lint_pass!(Transmute => [ ]); impl Transmute { #[must_use] - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv } } } @@ -461,7 +461,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { let linted = wrong_transmute::check(cx, e, from_ty, to_ty) | crosspointer_transmute::check(cx, e, from_ty, to_ty) | transmuting_null::check(cx, e, arg, to_ty) - | transmute_ptr_to_ref::check(cx, e, from_ty, to_ty, arg, path, self.msrv) + | transmute_ptr_to_ref::check(cx, e, from_ty, to_ty, arg, path, &self.msrv) | transmute_int_to_char::check(cx, e, from_ty, to_ty, arg, const_context) | transmute_ref_to_ref::check(cx, e, from_ty, to_ty, arg, const_context) | transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg) diff --git a/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/clippy_lints/src/transmute/transmute_ptr_to_ref.rs index 12d0b866e1c..3dde4eee671 100644 --- a/clippy_lints/src/transmute/transmute_ptr_to_ref.rs +++ b/clippy_lints/src/transmute/transmute_ptr_to_ref.rs @@ -1,12 +1,12 @@ use super::TRANSMUTE_PTR_TO_REF; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::{meets_msrv, msrvs, sugg}; +use clippy_utils::sugg; use rustc_errors::Applicability; use rustc_hir::{self as hir, Expr, GenericArg, Mutability, Path, TyKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty, TypeVisitable}; -use rustc_semver::RustcVersion; /// Checks for `transmute_ptr_to_ref` lint. /// Returns `true` if it's triggered, otherwise returns `false`. @@ -17,7 +17,7 @@ pub(super) fn check<'tcx>( to_ty: Ty<'tcx>, arg: &'tcx Expr<'_>, path: &'tcx Path<'_>, - msrv: Option, + msrv: &Msrv, ) -> bool { match (&from_ty.kind(), &to_ty.kind()) { (ty::RawPtr(from_ptr_ty), ty::Ref(_, to_ref_ty, mutbl)) => { @@ -37,7 +37,7 @@ pub(super) fn check<'tcx>( let sugg = if let Some(ty) = get_explicit_type(path) { let ty_snip = snippet_with_applicability(cx, ty.span, "..", &mut app); - if meets_msrv(msrv, msrvs::POINTER_CAST) { + if msrv.meets(msrvs::POINTER_CAST) { format!("{deref}{}.cast::<{ty_snip}>()", arg.maybe_par()) } else if from_ptr_ty.has_erased_regions() { sugg::make_unop(deref, arg.as_ty(format!("{cast} () as {cast} {ty_snip}"))).to_string() @@ -46,7 +46,7 @@ pub(super) fn check<'tcx>( } } else if from_ptr_ty.ty == *to_ref_ty { if from_ptr_ty.has_erased_regions() { - if meets_msrv(msrv, msrvs::POINTER_CAST) { + if msrv.meets(msrvs::POINTER_CAST) { format!("{deref}{}.cast::<{to_ref_ty}>()", arg.maybe_par()) } else { sugg::make_unop(deref, arg.as_ty(format!("{cast} () as {cast} {to_ref_ty}"))) diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs index b305dae7608..2c2730267db 100644 --- a/clippy_lints/src/unnested_or_patterns.rs +++ b/clippy_lints/src/unnested_or_patterns.rs @@ -2,14 +2,14 @@ use clippy_utils::ast_utils::{eq_field_pat, eq_id, eq_maybe_qself, eq_pat, eq_path}; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::{meets_msrv, msrvs, over}; +use clippy_utils::msrvs::{self, Msrv}; +use clippy_utils::over; use rustc_ast::mut_visit::*; use rustc_ast::ptr::P; use rustc_ast::{self as ast, Mutability, Pat, PatKind, PatKind::*, DUMMY_NODE_ID}; use rustc_ast_pretty::pprust; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::DUMMY_SP; @@ -45,14 +45,13 @@ declare_clippy_lint! { "unnested or-patterns, e.g., `Foo(Bar) | Foo(Baz) instead of `Foo(Bar | Baz)`" } -#[derive(Clone, Copy)] pub struct UnnestedOrPatterns { - msrv: Option, + msrv: Msrv, } impl UnnestedOrPatterns { #[must_use] - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv } } } @@ -61,13 +60,13 @@ impl_lint_pass!(UnnestedOrPatterns => [UNNESTED_OR_PATTERNS]); impl EarlyLintPass for UnnestedOrPatterns { fn check_arm(&mut self, cx: &EarlyContext<'_>, a: &ast::Arm) { - if meets_msrv(self.msrv, msrvs::OR_PATTERNS) { + if self.msrv.meets(msrvs::OR_PATTERNS) { lint_unnested_or_patterns(cx, &a.pat); } } fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { - if meets_msrv(self.msrv, msrvs::OR_PATTERNS) { + if self.msrv.meets(msrvs::OR_PATTERNS) { if let ast::ExprKind::Let(pat, _, _) = &e.kind { lint_unnested_or_patterns(cx, pat); } @@ -75,13 +74,13 @@ impl EarlyLintPass for UnnestedOrPatterns { } fn check_param(&mut self, cx: &EarlyContext<'_>, p: &ast::Param) { - if meets_msrv(self.msrv, msrvs::OR_PATTERNS) { + if self.msrv.meets(msrvs::OR_PATTERNS) { lint_unnested_or_patterns(cx, &p.pat); } } fn check_local(&mut self, cx: &EarlyContext<'_>, l: &ast::Local) { - if meets_msrv(self.msrv, msrvs::OR_PATTERNS) { + if self.msrv.meets(msrvs::OR_PATTERNS) { lint_unnested_or_patterns(cx, &l.pat); } } diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 464ffdc0a2a..06975443d8f 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -1,6 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_from_proc_macro; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::ty::same_type_and_consts; -use clippy_utils::{is_from_proc_macro, meets_msrv, msrvs}; use if_chain::if_chain; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; @@ -14,7 +15,6 @@ use rustc_hir::{ }; use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::{LateContext, LateLintPass}; -use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::Span; @@ -57,13 +57,13 @@ declare_clippy_lint! { #[derive(Default)] pub struct UseSelf { - msrv: Option, + msrv: Msrv, stack: Vec, } impl UseSelf { #[must_use] - pub fn new(msrv: Option) -> Self { + pub fn new(msrv: Msrv) -> Self { Self { msrv, ..Self::default() @@ -199,7 +199,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) { if_chain! { if !hir_ty.span.from_expansion(); - if meets_msrv(self.msrv, msrvs::TYPE_ALIAS_ENUM_VARIANTS); + if self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS); if let Some(&StackItem::Check { impl_id, in_body, @@ -228,7 +228,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { if !expr.span.from_expansion(); - if meets_msrv(self.msrv, msrvs::TYPE_ALIAS_ENUM_VARIANTS); + if self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS); if let Some(&StackItem::Check { impl_id, .. }) = self.stack.last(); if cx.typeck_results().expr_ty(expr) == cx.tcx.type_of(impl_id); then {} else { return; } @@ -248,7 +248,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { fn check_pat(&mut self, cx: &LateContext<'_>, pat: &Pat<'_>) { if_chain! { if !pat.span.from_expansion(); - if meets_msrv(self.msrv, msrvs::TYPE_ALIAS_ENUM_VARIANTS); + if self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS); if let Some(&StackItem::Check { impl_id, .. }) = self.stack.last(); // get the path from the pattern if let PatKind::Path(QPath::Resolved(_, path)) diff --git a/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs b/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs index 1e994e3f2b1..9876a8a765c 100644 --- a/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs +++ b/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs @@ -41,7 +41,7 @@ impl LateLintPass<'_> for MsrvAttrImpl { .type_of(f.did) .walk() .filter(|t| matches!(t.unpack(), GenericArgKind::Type(_))) - .any(|t| match_type(cx, t.expect_ty(), &paths::RUSTC_VERSION)) + .any(|t| match_type(cx, t.expect_ty(), &paths::MSRV)) }); if !items.iter().any(|item| item.ident.name == sym!(enter_lint_attrs)); then { diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index b0063758dce..86ee172cb28 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -105,8 +105,6 @@ use rustc_middle::ty::{ layout::IntegerExt, BorrowKind, ClosureKind, DefIdTree, Ty, TyCtxt, TypeAndMut, TypeVisitable, UpvarCapture, }; use rustc_middle::ty::{FloatTy, IntTy, UintTy}; -use rustc_semver::RustcVersion; -use rustc_session::Session; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::SourceMap; use rustc_span::sym; @@ -118,36 +116,17 @@ use crate::consts::{constant, Constant}; use crate::ty::{can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type, ty_is_fn_once_param}; use crate::visitors::for_each_expr; -pub fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option) -> Option { - if let Ok(version) = RustcVersion::parse(msrv) { - return Some(version); - } else if let Some(sess) = sess { - if let Some(span) = span { - sess.span_err(span, format!("`{msrv}` is not a valid Rust version")); - } - } - None -} - -pub fn meets_msrv(msrv: Option, lint_msrv: RustcVersion) -> bool { - msrv.map_or(true, |msrv| msrv.meets(lint_msrv)) -} - #[macro_export] macro_rules! extract_msrv_attr { ($context:ident) => { fn enter_lint_attrs(&mut self, cx: &rustc_lint::$context<'_>, attrs: &[rustc_ast::ast::Attribute]) { let sess = rustc_lint::LintContext::sess(cx); - match $crate::get_unique_inner_attr(sess, attrs, "msrv") { - Some(msrv_attr) => { - if let Some(msrv) = msrv_attr.value_str() { - self.msrv = $crate::parse_msrv(&msrv.to_string(), Some(sess), Some(msrv_attr.span)); - } else { - sess.span_err(msrv_attr.span, "bad clippy attribute"); - } - }, - _ => (), - } + self.msrv.enter_lint_attrs(sess, attrs); + } + + fn exit_lint_attrs(&mut self, cx: &rustc_lint::$context<'_>, attrs: &[rustc_ast::ast::Attribute]) { + let sess = rustc_lint::LintContext::sess(cx); + self.msrv.exit_lint_attrs(sess, attrs); } }; } diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index 79b19e6fb3e..2c9f75736e5 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -1,4 +1,11 @@ +use std::sync::OnceLock; + +use rustc_ast::Attribute; use rustc_semver::RustcVersion; +use rustc_session::Session; +use rustc_span::Span; + +use crate::attrs::get_unique_inner_attr; macro_rules! msrv_aliases { ($($major:literal,$minor:literal,$patch:literal { @@ -40,3 +47,97 @@ msrv_aliases! { 1,16,0 { STR_REPEAT } 1,55,0 { SEEK_REWIND } } + +fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option) -> Option { + if let Ok(version) = RustcVersion::parse(msrv) { + return Some(version); + } else if let Some(sess) = sess { + if let Some(span) = span { + sess.span_err(span, format!("`{msrv}` is not a valid Rust version")); + } + } + None +} + +/// Tracks the current MSRV from `clippy.toml`, `Cargo.toml` or set via `#[clippy::msrv]` +#[derive(Debug, Clone, Default)] +pub struct Msrv { + stack: Vec, +} + +impl Msrv { + fn new(initial: Option) -> Self { + Self { + stack: Vec::from_iter(initial), + } + } + + fn read_inner(conf_msrv: &Option, sess: &Session) -> Self { + let cargo_msrv = std::env::var("CARGO_PKG_RUST_VERSION") + .ok() + .and_then(|v| parse_msrv(&v, None, None)); + let clippy_msrv = conf_msrv.as_ref().and_then(|s| { + parse_msrv(s, None, None).or_else(|| { + sess.err(format!( + "error reading Clippy's configuration file. `{s}` is not a valid Rust version" + )); + None + }) + }); + + // if both files have an msrv, let's compare them and emit a warning if they differ + if let Some(cargo_msrv) = cargo_msrv + && let Some(clippy_msrv) = clippy_msrv + && clippy_msrv != cargo_msrv + { + sess.warn(format!( + "the MSRV in `clippy.toml` and `Cargo.toml` differ; using `{clippy_msrv}` from `clippy.toml`" + )); + } + + Self::new(clippy_msrv.or(cargo_msrv)) + } + + /// Set the initial MSRV from the Clippy config file or from Cargo due to the `rust-version` + /// field in `Cargo.toml` + /// + /// Returns a `&'static Msrv` as `Copy` types are more easily passed to the + /// `register_{late,early}_pass` callbacks + pub fn read(conf_msrv: &Option, sess: &Session) -> &'static Self { + static PARSED: OnceLock = OnceLock::new(); + + PARSED.get_or_init(|| Self::read_inner(conf_msrv, sess)) + } + + pub fn current(&self) -> Option { + self.stack.last().copied() + } + + pub fn meets(&self, required: RustcVersion) -> bool { + self.current().map_or(true, |version| version.meets(required)) + } + + fn parse_attr(sess: &Session, attrs: &[Attribute]) -> Option { + if let Some(msrv_attr) = get_unique_inner_attr(sess, attrs, "msrv") { + if let Some(msrv) = msrv_attr.value_str() { + return parse_msrv(&msrv.to_string(), Some(sess), Some(msrv_attr.span)); + } + + sess.span_err(msrv_attr.span, "bad clippy attribute"); + } + + None + } + + pub fn enter_lint_attrs(&mut self, sess: &Session, attrs: &[Attribute]) { + if let Some(version) = Self::parse_attr(sess, attrs) { + self.stack.push(version); + } + } + + pub fn exit_lint_attrs(&mut self, sess: &Session, attrs: &[Attribute]) { + if Self::parse_attr(sess, attrs).is_some() { + self.stack.pop(); + } + } +} diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs index 6c09c146082..3cf8cb76651 100644 --- a/clippy_utils/src/paths.rs +++ b/clippy_utils/src/paths.rs @@ -60,6 +60,8 @@ pub const LATE_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "LateLintPass"]; #[cfg(feature = "internal")] pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"]; pub const MEM_SWAP: [&str; 3] = ["core", "mem", "swap"]; +#[cfg(feature = "internal")] +pub const MSRV: [&str; 3] = ["clippy_utils", "msrvs", "Msrv"]; pub const OPEN_OPTIONS: [&str; 3] = ["std", "fs", "OpenOptions"]; pub const OS_STRING_AS_OS_STR: [&str; 5] = ["std", "ffi", "os_str", "OsString", "as_os_str"]; pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"]; @@ -101,8 +103,6 @@ pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "re_bytes", "Regex", "new"]; pub const REGEX_BYTES_SET_NEW: [&str; 5] = ["regex", "re_set", "bytes", "RegexSet", "new"]; pub const REGEX_NEW: [&str; 4] = ["regex", "re_unicode", "Regex", "new"]; pub const REGEX_SET_NEW: [&str; 5] = ["regex", "re_set", "unicode", "RegexSet", "new"]; -#[cfg(feature = "internal")] -pub const RUSTC_VERSION: [&str; 2] = ["rustc_semver", "RustcVersion"]; pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"]; pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"]; pub const SLICE_FROM_RAW_PARTS: [&str; 4] = ["core", "slice", "raw", "from_raw_parts"]; diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index 65722f142aa..0def1245615 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -3,6 +3,7 @@ // of terminologies might not be relevant in the context of Clippy. Note that its behavior might // differ from the time of `rustc` even if the name stays the same. +use crate::msrvs::Msrv; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::mir::{ @@ -18,7 +19,7 @@ use std::borrow::Cow; type McfResult = Result<(), (Span, Cow<'static, str>)>; -pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: Option) -> McfResult { +pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv) -> McfResult { let def_id = body.source.def_id(); let mut current = def_id; loop { @@ -280,7 +281,7 @@ fn check_terminator<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, terminator: &Terminator<'tcx>, - msrv: Option, + msrv: &Msrv, ) -> McfResult { let span = terminator.source_info.span; match &terminator.kind { @@ -364,7 +365,7 @@ fn check_terminator<'tcx>( } } -fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: Option) -> bool { +fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: &Msrv) -> bool { tcx.is_const_fn(def_id) && tcx.lookup_const_stability(def_id).map_or(true, |const_stab| { if let rustc_attr::StabilityLevel::Stable { since, .. } = const_stab.level { @@ -383,15 +384,12 @@ fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: Option) -> bo let since = rustc_span::Symbol::intern(short_version); - crate::meets_msrv( - msrv, - RustcVersion::parse(since.as_str()).unwrap_or_else(|err| { - panic!("`rustc_attr::StabilityLevel::Stable::since` is ill-formatted: `{since}`, {err:?}") - }), - ) + msrv.meets(RustcVersion::parse(since.as_str()).unwrap_or_else(|err| { + panic!("`rustc_attr::StabilityLevel::Stable::since` is ill-formatted: `{since}`, {err:?}") + })) } else { // Unstable const fn with the feature enabled. - msrv.is_none() + msrv.current().is_none() } }) } diff --git a/tests/ui-internal/invalid_msrv_attr_impl.fixed b/tests/ui-internal/invalid_msrv_attr_impl.fixed index 900a8fffd40..08634063a57 100644 --- a/tests/ui-internal/invalid_msrv_attr_impl.fixed +++ b/tests/ui-internal/invalid_msrv_attr_impl.fixed @@ -11,9 +11,9 @@ extern crate rustc_middle; #[macro_use] extern crate rustc_session; use clippy_utils::extract_msrv_attr; +use clippy_utils::msrvs::Msrv; use rustc_hir::Expr; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; -use rustc_semver::RustcVersion; declare_lint! { pub TEST_LINT, @@ -22,7 +22,7 @@ declare_lint! { } struct Pass { - msrv: Option, + msrv: Msrv, } impl_lint_pass!(Pass => [TEST_LINT]); diff --git a/tests/ui-internal/invalid_msrv_attr_impl.rs b/tests/ui-internal/invalid_msrv_attr_impl.rs index 4bc8164db67..f8af77e6d39 100644 --- a/tests/ui-internal/invalid_msrv_attr_impl.rs +++ b/tests/ui-internal/invalid_msrv_attr_impl.rs @@ -11,9 +11,9 @@ extern crate rustc_middle; #[macro_use] extern crate rustc_session; use clippy_utils::extract_msrv_attr; +use clippy_utils::msrvs::Msrv; use rustc_hir::Expr; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; -use rustc_semver::RustcVersion; declare_lint! { pub TEST_LINT, @@ -22,7 +22,7 @@ declare_lint! { } struct Pass { - msrv: Option, + msrv: Msrv, } impl_lint_pass!(Pass => [TEST_LINT]); diff --git a/tests/ui/min_rust_version_attr.rs b/tests/ui/min_rust_version_attr.rs index cd148063bf0..28ab132394b 100644 --- a/tests/ui/min_rust_version_attr.rs +++ b/tests/ui/min_rust_version_attr.rs @@ -27,3 +27,26 @@ fn no_patch_meets() { #![clippy::msrv = "1.43"] let log2_10 = 3.321928094887362; } + +// https://github.com/rust-lang/rust-clippy/issues/6920 +fn scoping() { + mod m { + #![clippy::msrv = "1.42.0"] + } + + // Should warn + let log2_10 = 3.321928094887362; + + mod a { + #![clippy::msrv = "1.42.0"] + + fn should_warn() { + #![clippy::msrv = "1.43.0"] + let log2_10 = 3.321928094887362; + } + + fn should_not_warn() { + let log2_10 = 3.321928094887362; + } + } +} diff --git a/tests/ui/min_rust_version_attr.stderr b/tests/ui/min_rust_version_attr.stderr index 68aa5874819..6174443372f 100644 --- a/tests/ui/min_rust_version_attr.stderr +++ b/tests/ui/min_rust_version_attr.stderr @@ -23,5 +23,21 @@ LL | let log2_10 = 3.321928094887362; | = help: consider using the constant directly -error: aborting due to 3 previous errors +error: approximate value of `f{32, 64}::consts::LOG2_10` found + --> $DIR/min_rust_version_attr.rs:38:19 + | +LL | let log2_10 = 3.321928094887362; + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using the constant directly + +error: approximate value of `f{32, 64}::consts::LOG2_10` found + --> $DIR/min_rust_version_attr.rs:45:27 + | +LL | let log2_10 = 3.321928094887362; + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using the constant directly + +error: aborting due to 5 previous errors -- cgit 1.4.1-3-g733a5 From 461e219d1d4167139a842b290cd1c019ff2d52a2 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Sat, 19 Nov 2022 12:50:02 +0000 Subject: Allow using `clippy::msrv` as an outer attribute --- README.md | 2 +- book/src/configuration.md | 2 +- book/src/development/adding_lints.md | 10 +- clippy_utils/src/attrs.rs | 24 +-- clippy_utils/src/msrvs.rs | 4 +- tests/ui/almost_complete_letter_range.fixed | 5 +- tests/ui/almost_complete_letter_range.rs | 5 +- tests/ui/almost_complete_letter_range.stderr | 26 ++-- tests/ui/cast_abs_to_unsigned.fixed | 7 +- tests/ui/cast_abs_to_unsigned.rs | 7 +- tests/ui/cast_abs_to_unsigned.stderr | 36 ++--- tests/ui/cast_lossless_bool.fixed | 7 +- tests/ui/cast_lossless_bool.rs | 7 +- tests/ui/cast_lossless_bool.stderr | 28 ++-- tests/ui/cfg_attr_rustfmt.fixed | 8 +- tests/ui/cfg_attr_rustfmt.rs | 8 +- tests/ui/cfg_attr_rustfmt.stderr | 2 +- tests/ui/checked_conversions.fixed | 7 +- tests/ui/checked_conversions.rs | 7 +- tests/ui/checked_conversions.stderr | 34 ++--- tests/ui/cloned_instead_of_copied.fixed | 10 +- tests/ui/cloned_instead_of_copied.rs | 10 +- tests/ui/cloned_instead_of_copied.stderr | 16 +- tests/ui/err_expect.fixed | 7 +- tests/ui/err_expect.rs | 7 +- tests/ui/err_expect.stderr | 4 +- tests/ui/filter_map_next_fixable.fixed | 7 +- tests/ui/filter_map_next_fixable.rs | 7 +- tests/ui/filter_map_next_fixable.stderr | 4 +- tests/ui/from_over_into.fixed | 7 +- tests/ui/from_over_into.rs | 7 +- tests/ui/from_over_into.stderr | 10 +- tests/ui/if_then_some_else_none.rs | 5 +- tests/ui/if_then_some_else_none.stderr | 10 +- tests/ui/manual_clamp.rs | 7 +- tests/ui/manual_clamp.stderr | 70 ++++----- tests/ui/manual_is_ascii_check.fixed | 11 +- tests/ui/manual_is_ascii_check.rs | 11 +- tests/ui/manual_is_ascii_check.stderr | 22 +-- tests/ui/manual_rem_euclid.fixed | 13 +- tests/ui/manual_rem_euclid.rs | 13 +- tests/ui/manual_rem_euclid.stderr | 20 +-- tests/ui/manual_retain.fixed | 7 +- tests/ui/manual_retain.rs | 7 +- tests/ui/manual_retain.stderr | 38 ++--- tests/ui/manual_split_once.fixed | 5 +- tests/ui/manual_split_once.rs | 5 +- tests/ui/manual_split_once.stderr | 38 ++--- tests/ui/manual_str_repeat.fixed | 5 +- tests/ui/manual_str_repeat.rs | 5 +- tests/ui/manual_str_repeat.stderr | 20 +-- tests/ui/manual_strip.rs | 7 +- tests/ui/manual_strip.stderr | 32 ++-- tests/ui/map_unwrap_or.rs | 7 +- tests/ui/map_unwrap_or.stderr | 24 +-- tests/ui/match_expr_like_matches_macro.fixed | 7 +- tests/ui/match_expr_like_matches_macro.rs | 7 +- tests/ui/match_expr_like_matches_macro.stderr | 28 ++-- tests/ui/mem_replace.fixed | 7 +- tests/ui/mem_replace.rs | 7 +- tests/ui/mem_replace.stderr | 40 ++--- tests/ui/min_rust_version_attr.rs | 18 ++- tests/ui/min_rust_version_attr.stderr | 12 +- tests/ui/min_rust_version_invalid_attr.stderr | 2 +- tests/ui/missing_const_for_fn/cant_be_const.rs | 4 +- tests/ui/missing_const_for_fn/could_be_const.rs | 10 +- .../ui/missing_const_for_fn/could_be_const.stderr | 24 ++- tests/ui/needless_borrow.fixed | 33 +--- tests/ui/needless_borrow.rs | 33 +--- tests/ui/needless_borrow.stderr | 18 +-- tests/ui/needless_question_mark.fixed | 1 - tests/ui/needless_question_mark.rs | 1 - tests/ui/needless_question_mark.stderr | 28 ++-- tests/ui/needless_splitn.fixed | 3 +- tests/ui/needless_splitn.rs | 3 +- tests/ui/needless_splitn.stderr | 26 ++-- tests/ui/option_as_ref_deref.fixed | 7 +- tests/ui/option_as_ref_deref.rs | 7 +- tests/ui/option_as_ref_deref.stderr | 36 ++--- tests/ui/ptr_as_ptr.fixed | 5 +- tests/ui/ptr_as_ptr.rs | 5 +- tests/ui/ptr_as_ptr.stderr | 16 +- tests/ui/range_contains.fixed | 7 +- tests/ui/range_contains.rs | 7 +- tests/ui/range_contains.stderr | 42 +++--- tests/ui/redundant_field_names.fixed | 7 +- tests/ui/redundant_field_names.rs | 7 +- tests/ui/redundant_field_names.stderr | 16 +- tests/ui/redundant_static_lifetimes.fixed | 7 +- tests/ui/redundant_static_lifetimes.rs | 7 +- tests/ui/redundant_static_lifetimes.stderr | 34 ++--- tests/ui/seek_from_current.fixed | 5 +- tests/ui/seek_from_current.rs | 5 +- tests/ui/seek_from_current.stderr | 2 +- tests/ui/seek_to_start_instead_of_rewind.fixed | 7 +- tests/ui/seek_to_start_instead_of_rewind.rs | 7 +- tests/ui/seek_to_start_instead_of_rewind.stderr | 6 +- tests/ui/transmute_ptr_to_ref.fixed | 5 +- tests/ui/transmute_ptr_to_ref.rs | 5 +- tests/ui/transmute_ptr_to_ref.stderr | 44 +++--- tests/ui/uninlined_format_args.fixed | 5 +- tests/ui/uninlined_format_args.rs | 5 +- tests/ui/uninlined_format_args.stderr | 152 +++++++++---------- tests/ui/unnecessary_to_owned.fixed | 5 +- tests/ui/unnecessary_to_owned.rs | 5 +- tests/ui/unnecessary_to_owned.stderr | 168 ++++++++++----------- tests/ui/unnested_or_patterns.fixed | 8 +- tests/ui/unnested_or_patterns.rs | 8 +- tests/ui/unnested_or_patterns.stderr | 2 +- tests/ui/use_self.fixed | 7 +- tests/ui/use_self.rs | 7 +- tests/ui/use_self.stderr | 84 +++++------ 112 files changed, 799 insertions(+), 979 deletions(-) (limited to 'book/src/development/adding_lints.md') diff --git a/README.md b/README.md index f74de7de42b..1c199d57f51 100644 --- a/README.md +++ b/README.md @@ -224,7 +224,7 @@ in the `Cargo.toml` can be used. rust-version = "1.30" ``` -The MSRV can also be specified as an inner attribute, like below. +The MSRV can also be specified as an attribute, like below. ```rust #![feature(custom_inner_attributes)] diff --git a/book/src/configuration.md b/book/src/configuration.md index 77f1d2e8797..5419eb5c21d 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -72,7 +72,7 @@ minimum supported Rust version (MSRV) in the clippy configuration file. msrv = "1.30.0" ``` -The MSRV can also be specified as an inner attribute, like below. +The MSRV can also be specified as an attribute, like below. ```rust #![feature(custom_inner_attributes)] diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md index 29d0d45dcc9..8b4eee8c9d9 100644 --- a/book/src/development/adding_lints.md +++ b/book/src/development/adding_lints.md @@ -463,7 +463,7 @@ if !self.msrv.meets(msrvs::STR_STRIP_PREFIX) { } ``` -The project's MSRV can also be specified as an inner attribute, which overrides +The project's MSRV can also be specified as an attribute, which overrides the value from `clippy.toml`. This can be accounted for using the `extract_msrv_attr!(LintContext)` macro and passing `LateContext`/`EarlyContext`. @@ -483,19 +483,15 @@ have a case for the version below the MSRV and one with the same contents but for the MSRV version itself. ```rust -#![feature(custom_inner_attributes)] - ... +#[clippy::msrv = "1.44"] fn msrv_1_44() { - #![clippy::msrv = "1.44"] - /* something that would trigger the lint */ } +#[clippy::msrv = "1.45"] fn msrv_1_45() { - #![clippy::msrv = "1.45"] - /* something that would trigger the lint */ } ``` diff --git a/clippy_utils/src/attrs.rs b/clippy_utils/src/attrs.rs index cd8575c90e8..7987a233bdc 100644 --- a/clippy_utils/src/attrs.rs +++ b/clippy_utils/src/attrs.rs @@ -125,19 +125,19 @@ fn parse_attrs(sess: &Session, attrs: &[ast::Attribute], name: &' } } -pub fn get_unique_inner_attr(sess: &Session, attrs: &[ast::Attribute], name: &'static str) -> Option { - let mut unique_attr = None; +pub fn get_unique_attr<'a>( + sess: &'a Session, + attrs: &'a [ast::Attribute], + name: &'static str, +) -> Option<&'a ast::Attribute> { + let mut unique_attr: Option<&ast::Attribute> = None; for attr in get_attr(sess, attrs, name) { - match attr.style { - ast::AttrStyle::Inner if unique_attr.is_none() => unique_attr = Some(attr.clone()), - ast::AttrStyle::Inner => { - sess.struct_span_err(attr.span, &format!("`{name}` is defined multiple times")) - .span_note(unique_attr.as_ref().unwrap().span, "first definition found here") - .emit(); - }, - ast::AttrStyle::Outer => { - sess.span_err(attr.span, format!("`{name}` cannot be an outer attribute")); - }, + if let Some(duplicate) = unique_attr { + sess.struct_span_err(attr.span, &format!("`{name}` is defined multiple times")) + .span_note(duplicate.span, "first definition found here") + .emit(); + } else { + unique_attr = Some(attr); } } unique_attr diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index 2c9f75736e5..12a512f78a6 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -5,7 +5,7 @@ use rustc_semver::RustcVersion; use rustc_session::Session; use rustc_span::Span; -use crate::attrs::get_unique_inner_attr; +use crate::attrs::get_unique_attr; macro_rules! msrv_aliases { ($($major:literal,$minor:literal,$patch:literal { @@ -118,7 +118,7 @@ impl Msrv { } fn parse_attr(sess: &Session, attrs: &[Attribute]) -> Option { - if let Some(msrv_attr) = get_unique_inner_attr(sess, attrs, "msrv") { + if let Some(msrv_attr) = get_unique_attr(sess, attrs, "msrv") { if let Some(msrv) = msrv_attr.value_str() { return parse_msrv(&msrv.to_string(), Some(sess), Some(msrv_attr.span)); } diff --git a/tests/ui/almost_complete_letter_range.fixed b/tests/ui/almost_complete_letter_range.fixed index 079b7c000dc..adcbd4d5134 100644 --- a/tests/ui/almost_complete_letter_range.fixed +++ b/tests/ui/almost_complete_letter_range.fixed @@ -2,7 +2,6 @@ // edition:2018 // aux-build:macro_rules.rs -#![feature(custom_inner_attributes)] #![feature(exclusive_range_pattern)] #![feature(stmt_expr_attributes)] #![warn(clippy::almost_complete_letter_range)] @@ -62,16 +61,16 @@ fn main() { b!(); } +#[clippy::msrv = "1.25"] fn _under_msrv() { - #![clippy::msrv = "1.25"] let _ = match 'a' { 'a'...'z' => 1, _ => 2, }; } +#[clippy::msrv = "1.26"] fn _meets_msrv() { - #![clippy::msrv = "1.26"] let _ = 'a'..='z'; let _ = match 'a' { 'a'..='z' => 1, diff --git a/tests/ui/almost_complete_letter_range.rs b/tests/ui/almost_complete_letter_range.rs index a66900a976e..9979316eca4 100644 --- a/tests/ui/almost_complete_letter_range.rs +++ b/tests/ui/almost_complete_letter_range.rs @@ -2,7 +2,6 @@ // edition:2018 // aux-build:macro_rules.rs -#![feature(custom_inner_attributes)] #![feature(exclusive_range_pattern)] #![feature(stmt_expr_attributes)] #![warn(clippy::almost_complete_letter_range)] @@ -62,16 +61,16 @@ fn main() { b!(); } +#[clippy::msrv = "1.25"] fn _under_msrv() { - #![clippy::msrv = "1.25"] let _ = match 'a' { 'a'..'z' => 1, _ => 2, }; } +#[clippy::msrv = "1.26"] fn _meets_msrv() { - #![clippy::msrv = "1.26"] let _ = 'a'..'z'; let _ = match 'a' { 'a'..'z' => 1, diff --git a/tests/ui/almost_complete_letter_range.stderr b/tests/ui/almost_complete_letter_range.stderr index 3de44c72c1b..9abf6d6c5e7 100644 --- a/tests/ui/almost_complete_letter_range.stderr +++ b/tests/ui/almost_complete_letter_range.stderr @@ -1,5 +1,5 @@ error: almost complete ascii letter range - --> $DIR/almost_complete_letter_range.rs:30:17 + --> $DIR/almost_complete_letter_range.rs:29:17 | LL | let _ = ('a') ..'z'; | ^^^^^^--^^^ @@ -9,7 +9,7 @@ LL | let _ = ('a') ..'z'; = note: `-D clippy::almost-complete-letter-range` implied by `-D warnings` error: almost complete ascii letter range - --> $DIR/almost_complete_letter_range.rs:31:17 + --> $DIR/almost_complete_letter_range.rs:30:17 | LL | let _ = 'A' .. ('Z'); | ^^^^--^^^^^^ @@ -17,7 +17,7 @@ LL | let _ = 'A' .. ('Z'); | help: use an inclusive range: `..=` error: almost complete ascii letter range - --> $DIR/almost_complete_letter_range.rs:37:13 + --> $DIR/almost_complete_letter_range.rs:36:13 | LL | let _ = (b'a')..(b'z'); | ^^^^^^--^^^^^^ @@ -25,7 +25,7 @@ LL | let _ = (b'a')..(b'z'); | help: use an inclusive range: `..=` error: almost complete ascii letter range - --> $DIR/almost_complete_letter_range.rs:38:13 + --> $DIR/almost_complete_letter_range.rs:37:13 | LL | let _ = b'A'..b'Z'; | ^^^^--^^^^ @@ -33,7 +33,7 @@ LL | let _ = b'A'..b'Z'; | help: use an inclusive range: `..=` error: almost complete ascii letter range - --> $DIR/almost_complete_letter_range.rs:43:13 + --> $DIR/almost_complete_letter_range.rs:42:13 | LL | let _ = a!()..'z'; | ^^^^--^^^ @@ -41,7 +41,7 @@ LL | let _ = a!()..'z'; | help: use an inclusive range: `..=` error: almost complete ascii letter range - --> $DIR/almost_complete_letter_range.rs:46:9 + --> $DIR/almost_complete_letter_range.rs:45:9 | LL | b'a'..b'z' if true => 1, | ^^^^--^^^^ @@ -49,7 +49,7 @@ LL | b'a'..b'z' if true => 1, | help: use an inclusive range: `..=` error: almost complete ascii letter range - --> $DIR/almost_complete_letter_range.rs:47:9 + --> $DIR/almost_complete_letter_range.rs:46:9 | LL | b'A'..b'Z' if true => 2, | ^^^^--^^^^ @@ -57,7 +57,7 @@ LL | b'A'..b'Z' if true => 2, | help: use an inclusive range: `..=` error: almost complete ascii letter range - --> $DIR/almost_complete_letter_range.rs:54:9 + --> $DIR/almost_complete_letter_range.rs:53:9 | LL | 'a'..'z' if true => 1, | ^^^--^^^ @@ -65,7 +65,7 @@ LL | 'a'..'z' if true => 1, | help: use an inclusive range: `..=` error: almost complete ascii letter range - --> $DIR/almost_complete_letter_range.rs:55:9 + --> $DIR/almost_complete_letter_range.rs:54:9 | LL | 'A'..'Z' if true => 2, | ^^^--^^^ @@ -73,7 +73,7 @@ LL | 'A'..'Z' if true => 2, | help: use an inclusive range: `..=` error: almost complete ascii letter range - --> $DIR/almost_complete_letter_range.rs:23:17 + --> $DIR/almost_complete_letter_range.rs:22:17 | LL | let _ = 'a'..'z'; | ^^^--^^^ @@ -86,7 +86,7 @@ LL | b!(); = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) error: almost complete ascii letter range - --> $DIR/almost_complete_letter_range.rs:68:9 + --> $DIR/almost_complete_letter_range.rs:67:9 | LL | 'a'..'z' => 1, | ^^^--^^^ @@ -94,7 +94,7 @@ LL | 'a'..'z' => 1, | help: use an inclusive range: `...` error: almost complete ascii letter range - --> $DIR/almost_complete_letter_range.rs:75:13 + --> $DIR/almost_complete_letter_range.rs:74:13 | LL | let _ = 'a'..'z'; | ^^^--^^^ @@ -102,7 +102,7 @@ LL | let _ = 'a'..'z'; | help: use an inclusive range: `..=` error: almost complete ascii letter range - --> $DIR/almost_complete_letter_range.rs:77:9 + --> $DIR/almost_complete_letter_range.rs:76:9 | LL | 'a'..'z' => 1, | ^^^--^^^ diff --git a/tests/ui/cast_abs_to_unsigned.fixed b/tests/ui/cast_abs_to_unsigned.fixed index e6bf944c7a5..8676b562b4f 100644 --- a/tests/ui/cast_abs_to_unsigned.fixed +++ b/tests/ui/cast_abs_to_unsigned.fixed @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![warn(clippy::cast_abs_to_unsigned)] #![allow(clippy::uninlined_format_args, unused)] @@ -33,16 +32,14 @@ fn main() { let _ = (x as i64 - y as i64).unsigned_abs() as u32; } +#[clippy::msrv = "1.50"] fn msrv_1_50() { - #![clippy::msrv = "1.50"] - let x: i32 = 10; assert_eq!(10u32, x.abs() as u32); } +#[clippy::msrv = "1.51"] fn msrv_1_51() { - #![clippy::msrv = "1.51"] - let x: i32 = 10; assert_eq!(10u32, x.unsigned_abs()); } diff --git a/tests/ui/cast_abs_to_unsigned.rs b/tests/ui/cast_abs_to_unsigned.rs index c87320b5209..5775af874f8 100644 --- a/tests/ui/cast_abs_to_unsigned.rs +++ b/tests/ui/cast_abs_to_unsigned.rs @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![warn(clippy::cast_abs_to_unsigned)] #![allow(clippy::uninlined_format_args, unused)] @@ -33,16 +32,14 @@ fn main() { let _ = (x as i64 - y as i64).abs() as u32; } +#[clippy::msrv = "1.50"] fn msrv_1_50() { - #![clippy::msrv = "1.50"] - let x: i32 = 10; assert_eq!(10u32, x.abs() as u32); } +#[clippy::msrv = "1.51"] fn msrv_1_51() { - #![clippy::msrv = "1.51"] - let x: i32 = 10; assert_eq!(10u32, x.abs() as u32); } diff --git a/tests/ui/cast_abs_to_unsigned.stderr b/tests/ui/cast_abs_to_unsigned.stderr index 1b39c554b03..4668554f451 100644 --- a/tests/ui/cast_abs_to_unsigned.stderr +++ b/tests/ui/cast_abs_to_unsigned.stderr @@ -1,5 +1,5 @@ error: casting the result of `i32::abs()` to u32 - --> $DIR/cast_abs_to_unsigned.rs:9:18 + --> $DIR/cast_abs_to_unsigned.rs:8:18 | LL | let y: u32 = x.abs() as u32; | ^^^^^^^^^^^^^^ help: replace with: `x.unsigned_abs()` @@ -7,103 +7,103 @@ LL | let y: u32 = x.abs() as u32; = note: `-D clippy::cast-abs-to-unsigned` implied by `-D warnings` error: casting the result of `i32::abs()` to usize - --> $DIR/cast_abs_to_unsigned.rs:13:20 + --> $DIR/cast_abs_to_unsigned.rs:12:20 | LL | let _: usize = a.abs() as usize; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `i32::abs()` to usize - --> $DIR/cast_abs_to_unsigned.rs:14:20 + --> $DIR/cast_abs_to_unsigned.rs:13:20 | LL | let _: usize = a.abs() as _; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `i32::abs()` to usize - --> $DIR/cast_abs_to_unsigned.rs:15:13 + --> $DIR/cast_abs_to_unsigned.rs:14:13 | LL | let _ = a.abs() as usize; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `i64::abs()` to usize - --> $DIR/cast_abs_to_unsigned.rs:18:13 + --> $DIR/cast_abs_to_unsigned.rs:17:13 | LL | let _ = a.abs() as usize; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `i64::abs()` to u8 - --> $DIR/cast_abs_to_unsigned.rs:19:13 + --> $DIR/cast_abs_to_unsigned.rs:18:13 | LL | let _ = a.abs() as u8; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `i64::abs()` to u16 - --> $DIR/cast_abs_to_unsigned.rs:20:13 + --> $DIR/cast_abs_to_unsigned.rs:19:13 | LL | let _ = a.abs() as u16; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `i64::abs()` to u32 - --> $DIR/cast_abs_to_unsigned.rs:21:13 + --> $DIR/cast_abs_to_unsigned.rs:20:13 | LL | let _ = a.abs() as u32; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `i64::abs()` to u64 - --> $DIR/cast_abs_to_unsigned.rs:22:13 + --> $DIR/cast_abs_to_unsigned.rs:21:13 | LL | let _ = a.abs() as u64; | ^^^^^^^^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `i64::abs()` to u128 - --> $DIR/cast_abs_to_unsigned.rs:23:13 + --> $DIR/cast_abs_to_unsigned.rs:22:13 | LL | let _ = a.abs() as u128; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `isize::abs()` to usize - --> $DIR/cast_abs_to_unsigned.rs:26:13 + --> $DIR/cast_abs_to_unsigned.rs:25:13 | LL | let _ = a.abs() as usize; | ^^^^^^^^^^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `isize::abs()` to u8 - --> $DIR/cast_abs_to_unsigned.rs:27:13 + --> $DIR/cast_abs_to_unsigned.rs:26:13 | LL | let _ = a.abs() as u8; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `isize::abs()` to u16 - --> $DIR/cast_abs_to_unsigned.rs:28:13 + --> $DIR/cast_abs_to_unsigned.rs:27:13 | LL | let _ = a.abs() as u16; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `isize::abs()` to u32 - --> $DIR/cast_abs_to_unsigned.rs:29:13 + --> $DIR/cast_abs_to_unsigned.rs:28:13 | LL | let _ = a.abs() as u32; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `isize::abs()` to u64 - --> $DIR/cast_abs_to_unsigned.rs:30:13 + --> $DIR/cast_abs_to_unsigned.rs:29:13 | LL | let _ = a.abs() as u64; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `isize::abs()` to u128 - --> $DIR/cast_abs_to_unsigned.rs:31:13 + --> $DIR/cast_abs_to_unsigned.rs:30:13 | LL | let _ = a.abs() as u128; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `i64::abs()` to u32 - --> $DIR/cast_abs_to_unsigned.rs:33:13 + --> $DIR/cast_abs_to_unsigned.rs:32:13 | LL | let _ = (x as i64 - y as i64).abs() as u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `(x as i64 - y as i64).unsigned_abs()` error: casting the result of `i32::abs()` to u32 - --> $DIR/cast_abs_to_unsigned.rs:47:23 + --> $DIR/cast_abs_to_unsigned.rs:44:23 | LL | assert_eq!(10u32, x.abs() as u32); | ^^^^^^^^^^^^^^ help: replace with: `x.unsigned_abs()` diff --git a/tests/ui/cast_lossless_bool.fixed b/tests/ui/cast_lossless_bool.fixed index af13b755e31..13b3cf838c9 100644 --- a/tests/ui/cast_lossless_bool.fixed +++ b/tests/ui/cast_lossless_bool.fixed @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![allow(dead_code)] #![warn(clippy::cast_lossless)] @@ -42,14 +41,12 @@ mod cast_lossless_in_impl { } } +#[clippy::msrv = "1.27"] fn msrv_1_27() { - #![clippy::msrv = "1.27"] - let _ = true as u8; } +#[clippy::msrv = "1.28"] fn msrv_1_28() { - #![clippy::msrv = "1.28"] - let _ = u8::from(true); } diff --git a/tests/ui/cast_lossless_bool.rs b/tests/ui/cast_lossless_bool.rs index 3b06af899c6..3eed2135562 100644 --- a/tests/ui/cast_lossless_bool.rs +++ b/tests/ui/cast_lossless_bool.rs @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![allow(dead_code)] #![warn(clippy::cast_lossless)] @@ -42,14 +41,12 @@ mod cast_lossless_in_impl { } } +#[clippy::msrv = "1.27"] fn msrv_1_27() { - #![clippy::msrv = "1.27"] - let _ = true as u8; } +#[clippy::msrv = "1.28"] fn msrv_1_28() { - #![clippy::msrv = "1.28"] - let _ = true as u8; } diff --git a/tests/ui/cast_lossless_bool.stderr b/tests/ui/cast_lossless_bool.stderr index 768b033d10a..ce240b70f89 100644 --- a/tests/ui/cast_lossless_bool.stderr +++ b/tests/ui/cast_lossless_bool.stderr @@ -1,5 +1,5 @@ error: casting `bool` to `u8` is more cleanly stated with `u8::from(_)` - --> $DIR/cast_lossless_bool.rs:9:13 + --> $DIR/cast_lossless_bool.rs:8:13 | LL | let _ = true as u8; | ^^^^^^^^^^ help: try: `u8::from(true)` @@ -7,79 +7,79 @@ LL | let _ = true as u8; = note: `-D clippy::cast-lossless` implied by `-D warnings` error: casting `bool` to `u16` is more cleanly stated with `u16::from(_)` - --> $DIR/cast_lossless_bool.rs:10:13 + --> $DIR/cast_lossless_bool.rs:9:13 | LL | let _ = true as u16; | ^^^^^^^^^^^ help: try: `u16::from(true)` error: casting `bool` to `u32` is more cleanly stated with `u32::from(_)` - --> $DIR/cast_lossless_bool.rs:11:13 + --> $DIR/cast_lossless_bool.rs:10:13 | LL | let _ = true as u32; | ^^^^^^^^^^^ help: try: `u32::from(true)` error: casting `bool` to `u64` is more cleanly stated with `u64::from(_)` - --> $DIR/cast_lossless_bool.rs:12:13 + --> $DIR/cast_lossless_bool.rs:11:13 | LL | let _ = true as u64; | ^^^^^^^^^^^ help: try: `u64::from(true)` error: casting `bool` to `u128` is more cleanly stated with `u128::from(_)` - --> $DIR/cast_lossless_bool.rs:13:13 + --> $DIR/cast_lossless_bool.rs:12:13 | LL | let _ = true as u128; | ^^^^^^^^^^^^ help: try: `u128::from(true)` error: casting `bool` to `usize` is more cleanly stated with `usize::from(_)` - --> $DIR/cast_lossless_bool.rs:14:13 + --> $DIR/cast_lossless_bool.rs:13:13 | LL | let _ = true as usize; | ^^^^^^^^^^^^^ help: try: `usize::from(true)` error: casting `bool` to `i8` is more cleanly stated with `i8::from(_)` - --> $DIR/cast_lossless_bool.rs:16:13 + --> $DIR/cast_lossless_bool.rs:15:13 | LL | let _ = true as i8; | ^^^^^^^^^^ help: try: `i8::from(true)` error: casting `bool` to `i16` is more cleanly stated with `i16::from(_)` - --> $DIR/cast_lossless_bool.rs:17:13 + --> $DIR/cast_lossless_bool.rs:16:13 | LL | let _ = true as i16; | ^^^^^^^^^^^ help: try: `i16::from(true)` error: casting `bool` to `i32` is more cleanly stated with `i32::from(_)` - --> $DIR/cast_lossless_bool.rs:18:13 + --> $DIR/cast_lossless_bool.rs:17:13 | LL | let _ = true as i32; | ^^^^^^^^^^^ help: try: `i32::from(true)` error: casting `bool` to `i64` is more cleanly stated with `i64::from(_)` - --> $DIR/cast_lossless_bool.rs:19:13 + --> $DIR/cast_lossless_bool.rs:18:13 | LL | let _ = true as i64; | ^^^^^^^^^^^ help: try: `i64::from(true)` error: casting `bool` to `i128` is more cleanly stated with `i128::from(_)` - --> $DIR/cast_lossless_bool.rs:20:13 + --> $DIR/cast_lossless_bool.rs:19:13 | LL | let _ = true as i128; | ^^^^^^^^^^^^ help: try: `i128::from(true)` error: casting `bool` to `isize` is more cleanly stated with `isize::from(_)` - --> $DIR/cast_lossless_bool.rs:21:13 + --> $DIR/cast_lossless_bool.rs:20:13 | LL | let _ = true as isize; | ^^^^^^^^^^^^^ help: try: `isize::from(true)` error: casting `bool` to `u16` is more cleanly stated with `u16::from(_)` - --> $DIR/cast_lossless_bool.rs:24:13 + --> $DIR/cast_lossless_bool.rs:23:13 | LL | let _ = (true | false) as u16; | ^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::from(true | false)` error: casting `bool` to `u8` is more cleanly stated with `u8::from(_)` - --> $DIR/cast_lossless_bool.rs:54:13 + --> $DIR/cast_lossless_bool.rs:51:13 | LL | let _ = true as u8; | ^^^^^^^^^^ help: try: `u8::from(true)` diff --git a/tests/ui/cfg_attr_rustfmt.fixed b/tests/ui/cfg_attr_rustfmt.fixed index 8a5645b22ed..b970b1209b6 100644 --- a/tests/ui/cfg_attr_rustfmt.fixed +++ b/tests/ui/cfg_attr_rustfmt.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![feature(stmt_expr_attributes, custom_inner_attributes)] +#![feature(stmt_expr_attributes)] #![allow(unused, clippy::no_effect, clippy::unnecessary_operation)] #![warn(clippy::deprecated_cfg_attr)] @@ -30,16 +30,14 @@ mod foo { pub fn f() {} } +#[clippy::msrv = "1.29"] fn msrv_1_29() { - #![clippy::msrv = "1.29"] - #[cfg_attr(rustfmt, rustfmt::skip)] 1+29; } +#[clippy::msrv = "1.30"] fn msrv_1_30() { - #![clippy::msrv = "1.30"] - #[rustfmt::skip] 1+30; } diff --git a/tests/ui/cfg_attr_rustfmt.rs b/tests/ui/cfg_attr_rustfmt.rs index 2fb140efae7..0a8e6a89d8a 100644 --- a/tests/ui/cfg_attr_rustfmt.rs +++ b/tests/ui/cfg_attr_rustfmt.rs @@ -1,5 +1,5 @@ // run-rustfix -#![feature(stmt_expr_attributes, custom_inner_attributes)] +#![feature(stmt_expr_attributes)] #![allow(unused, clippy::no_effect, clippy::unnecessary_operation)] #![warn(clippy::deprecated_cfg_attr)] @@ -30,16 +30,14 @@ mod foo { pub fn f() {} } +#[clippy::msrv = "1.29"] fn msrv_1_29() { - #![clippy::msrv = "1.29"] - #[cfg_attr(rustfmt, rustfmt::skip)] 1+29; } +#[clippy::msrv = "1.30"] fn msrv_1_30() { - #![clippy::msrv = "1.30"] - #[cfg_attr(rustfmt, rustfmt::skip)] 1+30; } diff --git a/tests/ui/cfg_attr_rustfmt.stderr b/tests/ui/cfg_attr_rustfmt.stderr index 08df7b2b39a..524a2bf7248 100644 --- a/tests/ui/cfg_attr_rustfmt.stderr +++ b/tests/ui/cfg_attr_rustfmt.stderr @@ -13,7 +13,7 @@ LL | #[cfg_attr(rustfmt, rustfmt_skip)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#[rustfmt::skip]` error: `cfg_attr` is deprecated for rustfmt and got replaced by tool attributes - --> $DIR/cfg_attr_rustfmt.rs:43:5 + --> $DIR/cfg_attr_rustfmt.rs:41:5 | LL | #[cfg_attr(rustfmt, rustfmt::skip)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#[rustfmt::skip]` diff --git a/tests/ui/checked_conversions.fixed b/tests/ui/checked_conversions.fixed index f936957cb40..e279ba3147b 100644 --- a/tests/ui/checked_conversions.fixed +++ b/tests/ui/checked_conversions.fixed @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![allow( clippy::cast_lossless, unused, @@ -78,16 +77,14 @@ pub const fn issue_8898(i: u32) -> bool { i <= i32::MAX as u32 } +#[clippy::msrv = "1.33"] fn msrv_1_33() { - #![clippy::msrv = "1.33"] - let value: i64 = 33; let _ = value <= (u32::MAX as i64) && value >= 0; } +#[clippy::msrv = "1.34"] fn msrv_1_34() { - #![clippy::msrv = "1.34"] - let value: i64 = 34; let _ = u32::try_from(value).is_ok(); } diff --git a/tests/ui/checked_conversions.rs b/tests/ui/checked_conversions.rs index 77aec713ff3..9d7a40995c3 100644 --- a/tests/ui/checked_conversions.rs +++ b/tests/ui/checked_conversions.rs @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![allow( clippy::cast_lossless, unused, @@ -78,16 +77,14 @@ pub const fn issue_8898(i: u32) -> bool { i <= i32::MAX as u32 } +#[clippy::msrv = "1.33"] fn msrv_1_33() { - #![clippy::msrv = "1.33"] - let value: i64 = 33; let _ = value <= (u32::MAX as i64) && value >= 0; } +#[clippy::msrv = "1.34"] fn msrv_1_34() { - #![clippy::msrv = "1.34"] - let value: i64 = 34; let _ = value <= (u32::MAX as i64) && value >= 0; } diff --git a/tests/ui/checked_conversions.stderr b/tests/ui/checked_conversions.stderr index b2bf7af8daf..273ead73bda 100644 --- a/tests/ui/checked_conversions.stderr +++ b/tests/ui/checked_conversions.stderr @@ -1,5 +1,5 @@ error: checked cast can be simplified - --> $DIR/checked_conversions.rs:17:13 + --> $DIR/checked_conversions.rs:16:13 | LL | let _ = value <= (u32::max_value() as i64) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u32::try_from(value).is_ok()` @@ -7,97 +7,97 @@ LL | let _ = value <= (u32::max_value() as i64) && value >= 0; = note: `-D clippy::checked-conversions` implied by `-D warnings` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:18:13 + --> $DIR/checked_conversions.rs:17:13 | LL | let _ = value <= (u32::MAX as i64) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u32::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:22:13 + --> $DIR/checked_conversions.rs:21:13 | LL | let _ = value <= i64::from(u16::max_value()) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:23:13 + --> $DIR/checked_conversions.rs:22:13 | LL | let _ = value <= i64::from(u16::MAX) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:27:13 + --> $DIR/checked_conversions.rs:26:13 | LL | let _ = value <= (u8::max_value() as isize) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u8::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:28:13 + --> $DIR/checked_conversions.rs:27:13 | LL | let _ = value <= (u8::MAX as isize) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u8::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:34:13 + --> $DIR/checked_conversions.rs:33:13 | LL | let _ = value <= (i32::max_value() as i64) && value >= (i32::min_value() as i64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:35:13 + --> $DIR/checked_conversions.rs:34:13 | LL | let _ = value <= (i32::MAX as i64) && value >= (i32::MIN as i64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:39:13 + --> $DIR/checked_conversions.rs:38:13 | LL | let _ = value <= i64::from(i16::max_value()) && value >= i64::from(i16::min_value()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i16::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:40:13 + --> $DIR/checked_conversions.rs:39:13 | LL | let _ = value <= i64::from(i16::MAX) && value >= i64::from(i16::MIN); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i16::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:46:13 + --> $DIR/checked_conversions.rs:45:13 | LL | let _ = value <= i32::max_value() as u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:47:13 + --> $DIR/checked_conversions.rs:46:13 | LL | let _ = value <= i32::MAX as u32; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:51:13 + --> $DIR/checked_conversions.rs:50:13 | LL | let _ = value <= isize::max_value() as usize && value as i32 == 5; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `isize::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:52:13 + --> $DIR/checked_conversions.rs:51:13 | LL | let _ = value <= isize::MAX as usize && value as i32 == 5; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `isize::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:56:13 + --> $DIR/checked_conversions.rs:55:13 | LL | let _ = value <= u16::max_value() as u32 && value as i32 == 5; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:57:13 + --> $DIR/checked_conversions.rs:56:13 | LL | let _ = value <= u16::MAX as u32 && value as i32 == 5; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()` error: checked cast can be simplified - --> $DIR/checked_conversions.rs:92:13 + --> $DIR/checked_conversions.rs:89:13 | LL | let _ = value <= (u32::MAX as i64) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u32::try_from(value).is_ok()` diff --git a/tests/ui/cloned_instead_of_copied.fixed b/tests/ui/cloned_instead_of_copied.fixed index 42ed232d100..ecbfc1feedf 100644 --- a/tests/ui/cloned_instead_of_copied.fixed +++ b/tests/ui/cloned_instead_of_copied.fixed @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![warn(clippy::cloned_instead_of_copied)] #![allow(unused)] @@ -17,23 +16,20 @@ fn main() { let _ = Some(&String::new()).cloned(); } +#[clippy::msrv = "1.34"] fn msrv_1_34() { - #![clippy::msrv = "1.34"] - let _ = [1].iter().cloned(); let _ = Some(&1).cloned(); } +#[clippy::msrv = "1.35"] fn msrv_1_35() { - #![clippy::msrv = "1.35"] - let _ = [1].iter().cloned(); let _ = Some(&1).copied(); // Option::copied needs 1.35 } +#[clippy::msrv = "1.36"] fn msrv_1_36() { - #![clippy::msrv = "1.36"] - let _ = [1].iter().copied(); // Iterator::copied needs 1.36 let _ = Some(&1).copied(); } diff --git a/tests/ui/cloned_instead_of_copied.rs b/tests/ui/cloned_instead_of_copied.rs index 471bd9654cc..163dc3dddce 100644 --- a/tests/ui/cloned_instead_of_copied.rs +++ b/tests/ui/cloned_instead_of_copied.rs @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![warn(clippy::cloned_instead_of_copied)] #![allow(unused)] @@ -17,23 +16,20 @@ fn main() { let _ = Some(&String::new()).cloned(); } +#[clippy::msrv = "1.34"] fn msrv_1_34() { - #![clippy::msrv = "1.34"] - let _ = [1].iter().cloned(); let _ = Some(&1).cloned(); } +#[clippy::msrv = "1.35"] fn msrv_1_35() { - #![clippy::msrv = "1.35"] - let _ = [1].iter().cloned(); let _ = Some(&1).cloned(); // Option::copied needs 1.35 } +#[clippy::msrv = "1.36"] fn msrv_1_36() { - #![clippy::msrv = "1.36"] - let _ = [1].iter().cloned(); // Iterator::copied needs 1.36 let _ = Some(&1).cloned(); } diff --git a/tests/ui/cloned_instead_of_copied.stderr b/tests/ui/cloned_instead_of_copied.stderr index 914c9a91e83..e0361acd956 100644 --- a/tests/ui/cloned_instead_of_copied.stderr +++ b/tests/ui/cloned_instead_of_copied.stderr @@ -1,5 +1,5 @@ error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:9:24 + --> $DIR/cloned_instead_of_copied.rs:8:24 | LL | let _ = [1].iter().cloned(); | ^^^^^^ help: try: `copied` @@ -7,43 +7,43 @@ LL | let _ = [1].iter().cloned(); = note: `-D clippy::cloned-instead-of-copied` implied by `-D warnings` error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:10:31 + --> $DIR/cloned_instead_of_copied.rs:9:31 | LL | let _ = vec!["hi"].iter().cloned(); | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:11:22 + --> $DIR/cloned_instead_of_copied.rs:10:22 | LL | let _ = Some(&1).cloned(); | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:12:34 + --> $DIR/cloned_instead_of_copied.rs:11:34 | LL | let _ = Box::new([1].iter()).cloned(); | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:13:32 + --> $DIR/cloned_instead_of_copied.rs:12:32 | LL | let _ = Box::new(Some(&1)).cloned(); | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:31:22 + --> $DIR/cloned_instead_of_copied.rs:28:22 | LL | let _ = Some(&1).cloned(); // Option::copied needs 1.35 | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:37:24 + --> $DIR/cloned_instead_of_copied.rs:33:24 | LL | let _ = [1].iter().cloned(); // Iterator::copied needs 1.36 | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:38:22 + --> $DIR/cloned_instead_of_copied.rs:34:22 | LL | let _ = Some(&1).cloned(); | ^^^^^^ help: try: `copied` diff --git a/tests/ui/err_expect.fixed b/tests/ui/err_expect.fixed index 3bac738acd6..b63cbd8a8e6 100644 --- a/tests/ui/err_expect.fixed +++ b/tests/ui/err_expect.fixed @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![allow(unused)] struct MyTypeNonDebug; @@ -16,16 +15,14 @@ fn main() { test_non_debug.err().expect("Testing non debug type"); } +#[clippy::msrv = "1.16"] fn msrv_1_16() { - #![clippy::msrv = "1.16"] - let x: Result = Ok(16); x.err().expect("16"); } +#[clippy::msrv = "1.17"] fn msrv_1_17() { - #![clippy::msrv = "1.17"] - let x: Result = Ok(17); x.expect_err("17"); } diff --git a/tests/ui/err_expect.rs b/tests/ui/err_expect.rs index 6e7c47d9ad3..c081a745fb4 100644 --- a/tests/ui/err_expect.rs +++ b/tests/ui/err_expect.rs @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![allow(unused)] struct MyTypeNonDebug; @@ -16,16 +15,14 @@ fn main() { test_non_debug.err().expect("Testing non debug type"); } +#[clippy::msrv = "1.16"] fn msrv_1_16() { - #![clippy::msrv = "1.16"] - let x: Result = Ok(16); x.err().expect("16"); } +#[clippy::msrv = "1.17"] fn msrv_1_17() { - #![clippy::msrv = "1.17"] - let x: Result = Ok(17); x.err().expect("17"); } diff --git a/tests/ui/err_expect.stderr b/tests/ui/err_expect.stderr index 91a6cf8de65..82c0754cfb0 100644 --- a/tests/ui/err_expect.stderr +++ b/tests/ui/err_expect.stderr @@ -1,5 +1,5 @@ error: called `.err().expect()` on a `Result` value - --> $DIR/err_expect.rs:13:16 + --> $DIR/err_expect.rs:12:16 | LL | test_debug.err().expect("Testing debug type"); | ^^^^^^^^^^^^ help: try: `expect_err` @@ -7,7 +7,7 @@ LL | test_debug.err().expect("Testing debug type"); = note: `-D clippy::err-expect` implied by `-D warnings` error: called `.err().expect()` on a `Result` value - --> $DIR/err_expect.rs:30:7 + --> $DIR/err_expect.rs:27:7 | LL | x.err().expect("17"); | ^^^^^^^^^^^^ help: try: `expect_err` diff --git a/tests/ui/filter_map_next_fixable.fixed b/tests/ui/filter_map_next_fixable.fixed index 41828ddd7ac..462d46169fc 100644 --- a/tests/ui/filter_map_next_fixable.fixed +++ b/tests/ui/filter_map_next_fixable.fixed @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![warn(clippy::all, clippy::pedantic)] #![allow(unused)] @@ -11,16 +10,14 @@ fn main() { assert_eq!(element, Some(1)); } +#[clippy::msrv = "1.29"] fn msrv_1_29() { - #![clippy::msrv = "1.29"] - let a = ["1", "lol", "3", "NaN", "5"]; let _: Option = a.iter().filter_map(|s| s.parse().ok()).next(); } +#[clippy::msrv = "1.30"] fn msrv_1_30() { - #![clippy::msrv = "1.30"] - let a = ["1", "lol", "3", "NaN", "5"]; let _: Option = a.iter().find_map(|s| s.parse().ok()); } diff --git a/tests/ui/filter_map_next_fixable.rs b/tests/ui/filter_map_next_fixable.rs index be492a81b45..2ea00cf7307 100644 --- a/tests/ui/filter_map_next_fixable.rs +++ b/tests/ui/filter_map_next_fixable.rs @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![warn(clippy::all, clippy::pedantic)] #![allow(unused)] @@ -11,16 +10,14 @@ fn main() { assert_eq!(element, Some(1)); } +#[clippy::msrv = "1.29"] fn msrv_1_29() { - #![clippy::msrv = "1.29"] - let a = ["1", "lol", "3", "NaN", "5"]; let _: Option = a.iter().filter_map(|s| s.parse().ok()).next(); } +#[clippy::msrv = "1.30"] fn msrv_1_30() { - #![clippy::msrv = "1.30"] - let a = ["1", "lol", "3", "NaN", "5"]; let _: Option = a.iter().filter_map(|s| s.parse().ok()).next(); } diff --git a/tests/ui/filter_map_next_fixable.stderr b/tests/ui/filter_map_next_fixable.stderr index e789efeabd5..a9fc6abe88f 100644 --- a/tests/ui/filter_map_next_fixable.stderr +++ b/tests/ui/filter_map_next_fixable.stderr @@ -1,5 +1,5 @@ error: called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find_map(..)` instead - --> $DIR/filter_map_next_fixable.rs:10:32 + --> $DIR/filter_map_next_fixable.rs:9:32 | LL | let element: Option = a.iter().filter_map(|s| s.parse().ok()).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `a.iter().find_map(|s| s.parse().ok())` @@ -7,7 +7,7 @@ LL | let element: Option = a.iter().filter_map(|s| s.parse().ok()).next = note: `-D clippy::filter-map-next` implied by `-D warnings` error: called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find_map(..)` instead - --> $DIR/filter_map_next_fixable.rs:25:26 + --> $DIR/filter_map_next_fixable.rs:22:26 | LL | let _: Option = a.iter().filter_map(|s| s.parse().ok()).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `a.iter().find_map(|s| s.parse().ok())` diff --git a/tests/ui/from_over_into.fixed b/tests/ui/from_over_into.fixed index 1cf49ca45f4..125c9a69cd3 100644 --- a/tests/ui/from_over_into.fixed +++ b/tests/ui/from_over_into.fixed @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![warn(clippy::from_over_into)] #![allow(unused)] @@ -60,9 +59,8 @@ impl From for A { } } +#[clippy::msrv = "1.40"] fn msrv_1_40() { - #![clippy::msrv = "1.40"] - struct FromOverInto(Vec); impl Into> for Vec { @@ -72,9 +70,8 @@ fn msrv_1_40() { } } +#[clippy::msrv = "1.41"] fn msrv_1_41() { - #![clippy::msrv = "1.41"] - struct FromOverInto(Vec); impl From> for FromOverInto { diff --git a/tests/ui/from_over_into.rs b/tests/ui/from_over_into.rs index d30f3c3fc92..5aa127bfabe 100644 --- a/tests/ui/from_over_into.rs +++ b/tests/ui/from_over_into.rs @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![warn(clippy::from_over_into)] #![allow(unused)] @@ -60,9 +59,8 @@ impl From for A { } } +#[clippy::msrv = "1.40"] fn msrv_1_40() { - #![clippy::msrv = "1.40"] - struct FromOverInto(Vec); impl Into> for Vec { @@ -72,9 +70,8 @@ fn msrv_1_40() { } } +#[clippy::msrv = "1.41"] fn msrv_1_41() { - #![clippy::msrv = "1.41"] - struct FromOverInto(Vec); impl Into> for Vec { diff --git a/tests/ui/from_over_into.stderr b/tests/ui/from_over_into.stderr index 9c2a7c04c36..a1764a5ea12 100644 --- a/tests/ui/from_over_into.stderr +++ b/tests/ui/from_over_into.stderr @@ -1,5 +1,5 @@ error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> $DIR/from_over_into.rs:10:1 + --> $DIR/from_over_into.rs:9:1 | LL | impl Into for String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL ~ StringWrapper(val) | error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> $DIR/from_over_into.rs:18:1 + --> $DIR/from_over_into.rs:17:1 | LL | impl Into for String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL ~ SelfType(String::new()) | error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> $DIR/from_over_into.rs:33:1 + --> $DIR/from_over_into.rs:32:1 | LL | impl Into for X { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL ~ let _: X = val; | error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> $DIR/from_over_into.rs:45:1 + --> $DIR/from_over_into.rs:44:1 | LL | impl core::convert::Into for crate::ExplicitPaths { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -59,7 +59,7 @@ LL ~ val.0 | error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> $DIR/from_over_into.rs:80:5 + --> $DIR/from_over_into.rs:77:5 | LL | impl Into> for Vec { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/if_then_some_else_none.rs b/tests/ui/if_then_some_else_none.rs index 3bc3a039524..0e89fdb0dfa 100644 --- a/tests/ui/if_then_some_else_none.rs +++ b/tests/ui/if_then_some_else_none.rs @@ -1,5 +1,4 @@ #![warn(clippy::if_then_some_else_none)] -#![feature(custom_inner_attributes)] fn main() { // Should issue an error. @@ -66,8 +65,8 @@ fn main() { let _ = if foo() { into_some("foo") } else { None }; } +#[clippy::msrv = "1.49"] fn _msrv_1_49() { - #![clippy::msrv = "1.49"] // `bool::then` was stabilized in 1.50. Do not lint this let _ = if foo() { println!("true!"); @@ -77,8 +76,8 @@ fn _msrv_1_49() { }; } +#[clippy::msrv = "1.50"] fn _msrv_1_50() { - #![clippy::msrv = "1.50"] let _ = if foo() { println!("true!"); Some(150) diff --git a/tests/ui/if_then_some_else_none.stderr b/tests/ui/if_then_some_else_none.stderr index 24e0b5947f1..d728a3c31a3 100644 --- a/tests/ui/if_then_some_else_none.stderr +++ b/tests/ui/if_then_some_else_none.stderr @@ -1,5 +1,5 @@ error: this could be simplified with `bool::then` - --> $DIR/if_then_some_else_none.rs:6:13 + --> $DIR/if_then_some_else_none.rs:5:13 | LL | let _ = if foo() { | _____________^ @@ -14,7 +14,7 @@ LL | | }; = note: `-D clippy::if-then-some-else-none` implied by `-D warnings` error: this could be simplified with `bool::then` - --> $DIR/if_then_some_else_none.rs:14:13 + --> $DIR/if_then_some_else_none.rs:13:13 | LL | let _ = if matches!(true, true) { | _____________^ @@ -28,7 +28,7 @@ LL | | }; = help: consider using `bool::then` like: `matches!(true, true).then(|| { /* snippet */ matches!(true, false) })` error: this could be simplified with `bool::then_some` - --> $DIR/if_then_some_else_none.rs:23:28 + --> $DIR/if_then_some_else_none.rs:22:28 | LL | let _ = x.and_then(|o| if o < 32 { Some(o) } else { None }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +36,7 @@ LL | let _ = x.and_then(|o| if o < 32 { Some(o) } else { None }); = help: consider using `bool::then_some` like: `(o < 32).then_some(o)` error: this could be simplified with `bool::then_some` - --> $DIR/if_then_some_else_none.rs:27:13 + --> $DIR/if_then_some_else_none.rs:26:13 | LL | let _ = if !x { Some(0) } else { None }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | let _ = if !x { Some(0) } else { None }; = help: consider using `bool::then_some` like: `(!x).then_some(0)` error: this could be simplified with `bool::then` - --> $DIR/if_then_some_else_none.rs:82:13 + --> $DIR/if_then_some_else_none.rs:81:13 | LL | let _ = if foo() { | _____________^ diff --git a/tests/ui/manual_clamp.rs b/tests/ui/manual_clamp.rs index 331fd29b74e..f7902e6fd53 100644 --- a/tests/ui/manual_clamp.rs +++ b/tests/ui/manual_clamp.rs @@ -1,4 +1,3 @@ -#![feature(custom_inner_attributes)] #![warn(clippy::manual_clamp)] #![allow( unused, @@ -304,9 +303,8 @@ fn cmp_min_max(input: i32) -> i32 { input * 3 } +#[clippy::msrv = "1.49"] fn msrv_1_49() { - #![clippy::msrv = "1.49"] - let (input, min, max) = (0, -1, 2); let _ = if input < min { min @@ -317,9 +315,8 @@ fn msrv_1_49() { }; } +#[clippy::msrv = "1.50"] fn msrv_1_50() { - #![clippy::msrv = "1.50"] - let (input, min, max) = (0, -1, 2); let _ = if input < min { min diff --git a/tests/ui/manual_clamp.stderr b/tests/ui/manual_clamp.stderr index 70abe28091c..988ad1527e8 100644 --- a/tests/ui/manual_clamp.stderr +++ b/tests/ui/manual_clamp.stderr @@ -1,5 +1,5 @@ error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:77:5 + --> $DIR/manual_clamp.rs:76:5 | LL | / if x9 < min { LL | | x9 = min; @@ -13,7 +13,7 @@ LL | | } = note: `-D clippy::manual-clamp` implied by `-D warnings` error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:92:5 + --> $DIR/manual_clamp.rs:91:5 | LL | / if x11 > max { LL | | x11 = max; @@ -26,7 +26,7 @@ LL | | } = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:100:5 + --> $DIR/manual_clamp.rs:99:5 | LL | / if min > x12 { LL | | x12 = min; @@ -39,7 +39,7 @@ LL | | } = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:108:5 + --> $DIR/manual_clamp.rs:107:5 | LL | / if max < x13 { LL | | x13 = max; @@ -52,7 +52,7 @@ LL | | } = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:162:5 + --> $DIR/manual_clamp.rs:161:5 | LL | / if max < x33 { LL | | x33 = max; @@ -65,7 +65,7 @@ LL | | } = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:22:14 + --> $DIR/manual_clamp.rs:21:14 | LL | let x0 = if max < input { | ______________^ @@ -80,7 +80,7 @@ LL | | }; = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:30:14 + --> $DIR/manual_clamp.rs:29:14 | LL | let x1 = if input > max { | ______________^ @@ -95,7 +95,7 @@ LL | | }; = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:38:14 + --> $DIR/manual_clamp.rs:37:14 | LL | let x2 = if input < min { | ______________^ @@ -110,7 +110,7 @@ LL | | }; = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:46:14 + --> $DIR/manual_clamp.rs:45:14 | LL | let x3 = if min > input { | ______________^ @@ -125,7 +125,7 @@ LL | | }; = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:54:14 + --> $DIR/manual_clamp.rs:53:14 | LL | let x4 = input.max(min).min(max); | ^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(min, max)` @@ -133,7 +133,7 @@ LL | let x4 = input.max(min).min(max); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:56:14 + --> $DIR/manual_clamp.rs:55:14 | LL | let x5 = input.min(max).max(min); | ^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(min, max)` @@ -141,7 +141,7 @@ LL | let x5 = input.min(max).max(min); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:58:14 + --> $DIR/manual_clamp.rs:57:14 | LL | let x6 = match input { | ______________^ @@ -154,7 +154,7 @@ LL | | }; = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:64:14 + --> $DIR/manual_clamp.rs:63:14 | LL | let x7 = match input { | ______________^ @@ -167,7 +167,7 @@ LL | | }; = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:70:14 + --> $DIR/manual_clamp.rs:69:14 | LL | let x8 = match input { | ______________^ @@ -180,7 +180,7 @@ LL | | }; = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:84:15 + --> $DIR/manual_clamp.rs:83:15 | LL | let x10 = match input { | _______________^ @@ -193,7 +193,7 @@ LL | | }; = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:115:15 + --> $DIR/manual_clamp.rs:114:15 | LL | let x14 = if input > CONST_MAX { | _______________^ @@ -208,7 +208,7 @@ LL | | }; = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:124:19 + --> $DIR/manual_clamp.rs:123:19 | LL | let x15 = if input > max { | ___________________^ @@ -224,7 +224,7 @@ LL | | }; = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:135:19 + --> $DIR/manual_clamp.rs:134:19 | LL | let x16 = cmp_max(cmp_min(input, CONST_MAX), CONST_MIN); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -232,7 +232,7 @@ LL | let x16 = cmp_max(cmp_min(input, CONST_MAX), CONST_MIN); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:136:19 + --> $DIR/manual_clamp.rs:135:19 | LL | let x17 = cmp_min(cmp_max(input, CONST_MIN), CONST_MAX); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -240,7 +240,7 @@ LL | let x17 = cmp_min(cmp_max(input, CONST_MIN), CONST_MAX); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:137:19 + --> $DIR/manual_clamp.rs:136:19 | LL | let x18 = cmp_max(CONST_MIN, cmp_min(input, CONST_MAX)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -248,7 +248,7 @@ LL | let x18 = cmp_max(CONST_MIN, cmp_min(input, CONST_MAX)); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:138:19 + --> $DIR/manual_clamp.rs:137:19 | LL | let x19 = cmp_min(CONST_MAX, cmp_max(input, CONST_MIN)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -256,7 +256,7 @@ LL | let x19 = cmp_min(CONST_MAX, cmp_max(input, CONST_MIN)); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:139:19 + --> $DIR/manual_clamp.rs:138:19 | LL | let x20 = cmp_max(cmp_min(CONST_MAX, input), CONST_MIN); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -264,7 +264,7 @@ LL | let x20 = cmp_max(cmp_min(CONST_MAX, input), CONST_MIN); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:140:19 + --> $DIR/manual_clamp.rs:139:19 | LL | let x21 = cmp_min(cmp_max(CONST_MIN, input), CONST_MAX); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -272,7 +272,7 @@ LL | let x21 = cmp_min(cmp_max(CONST_MIN, input), CONST_MAX); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:141:19 + --> $DIR/manual_clamp.rs:140:19 | LL | let x22 = cmp_max(CONST_MIN, cmp_min(CONST_MAX, input)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -280,7 +280,7 @@ LL | let x22 = cmp_max(CONST_MIN, cmp_min(CONST_MAX, input)); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:142:19 + --> $DIR/manual_clamp.rs:141:19 | LL | let x23 = cmp_min(CONST_MAX, cmp_max(CONST_MIN, input)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -288,7 +288,7 @@ LL | let x23 = cmp_min(CONST_MAX, cmp_max(CONST_MIN, input)); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:144:19 + --> $DIR/manual_clamp.rs:143:19 | LL | let x24 = f64::max(f64::min(input, CONST_F64_MAX), CONST_F64_MIN); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)` @@ -297,7 +297,7 @@ LL | let x24 = f64::max(f64::min(input, CONST_F64_MAX), CONST_F64_MIN); = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:145:19 + --> $DIR/manual_clamp.rs:144:19 | LL | let x25 = f64::min(f64::max(input, CONST_F64_MIN), CONST_F64_MAX); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)` @@ -306,7 +306,7 @@ LL | let x25 = f64::min(f64::max(input, CONST_F64_MIN), CONST_F64_MAX); = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:146:19 + --> $DIR/manual_clamp.rs:145:19 | LL | let x26 = f64::max(CONST_F64_MIN, f64::min(input, CONST_F64_MAX)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)` @@ -315,7 +315,7 @@ LL | let x26 = f64::max(CONST_F64_MIN, f64::min(input, CONST_F64_MAX)); = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:147:19 + --> $DIR/manual_clamp.rs:146:19 | LL | let x27 = f64::min(CONST_F64_MAX, f64::max(input, CONST_F64_MIN)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)` @@ -324,7 +324,7 @@ LL | let x27 = f64::min(CONST_F64_MAX, f64::max(input, CONST_F64_MIN)); = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:148:19 + --> $DIR/manual_clamp.rs:147:19 | LL | let x28 = f64::max(f64::min(CONST_F64_MAX, input), CONST_F64_MIN); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)` @@ -333,7 +333,7 @@ LL | let x28 = f64::max(f64::min(CONST_F64_MAX, input), CONST_F64_MIN); = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:149:19 + --> $DIR/manual_clamp.rs:148:19 | LL | let x29 = f64::min(f64::max(CONST_F64_MIN, input), CONST_F64_MAX); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)` @@ -342,7 +342,7 @@ LL | let x29 = f64::min(f64::max(CONST_F64_MIN, input), CONST_F64_MAX); = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:150:19 + --> $DIR/manual_clamp.rs:149:19 | LL | let x30 = f64::max(CONST_F64_MIN, f64::min(CONST_F64_MAX, input)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)` @@ -351,7 +351,7 @@ LL | let x30 = f64::max(CONST_F64_MIN, f64::min(CONST_F64_MAX, input)); = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:151:19 + --> $DIR/manual_clamp.rs:150:19 | LL | let x31 = f64::min(CONST_F64_MAX, f64::max(CONST_F64_MIN, input)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)` @@ -360,7 +360,7 @@ LL | let x31 = f64::min(CONST_F64_MAX, f64::max(CONST_F64_MIN, input)); = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:154:5 + --> $DIR/manual_clamp.rs:153:5 | LL | / if x32 < min { LL | | x32 = min; @@ -372,7 +372,7 @@ LL | | } = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> $DIR/manual_clamp.rs:324:13 + --> $DIR/manual_clamp.rs:321:13 | LL | let _ = if input < min { | _____________^ diff --git a/tests/ui/manual_is_ascii_check.fixed b/tests/ui/manual_is_ascii_check.fixed index 765bb785994..231ba83b142 100644 --- a/tests/ui/manual_is_ascii_check.fixed +++ b/tests/ui/manual_is_ascii_check.fixed @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![allow(unused, dead_code)] #![warn(clippy::manual_is_ascii_check)] @@ -18,28 +17,26 @@ fn main() { assert!(matches!('x', 'A'..='Z' | 'a'..='z' | '_')); } +#[clippy::msrv = "1.23"] fn msrv_1_23() { - #![clippy::msrv = "1.23"] - assert!(matches!(b'1', b'0'..=b'9')); assert!(matches!('X', 'A'..='Z')); assert!(matches!('x', 'A'..='Z' | 'a'..='z')); } +#[clippy::msrv = "1.24"] fn msrv_1_24() { - #![clippy::msrv = "1.24"] - assert!(b'1'.is_ascii_digit()); assert!('X'.is_ascii_uppercase()); assert!('x'.is_ascii_alphabetic()); } +#[clippy::msrv = "1.46"] fn msrv_1_46() { - #![clippy::msrv = "1.46"] const FOO: bool = matches!('x', '0'..='9'); } +#[clippy::msrv = "1.47"] fn msrv_1_47() { - #![clippy::msrv = "1.47"] const FOO: bool = 'x'.is_ascii_digit(); } diff --git a/tests/ui/manual_is_ascii_check.rs b/tests/ui/manual_is_ascii_check.rs index be133161041..39ee6151c56 100644 --- a/tests/ui/manual_is_ascii_check.rs +++ b/tests/ui/manual_is_ascii_check.rs @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![allow(unused, dead_code)] #![warn(clippy::manual_is_ascii_check)] @@ -18,28 +17,26 @@ fn main() { assert!(matches!('x', 'A'..='Z' | 'a'..='z' | '_')); } +#[clippy::msrv = "1.23"] fn msrv_1_23() { - #![clippy::msrv = "1.23"] - assert!(matches!(b'1', b'0'..=b'9')); assert!(matches!('X', 'A'..='Z')); assert!(matches!('x', 'A'..='Z' | 'a'..='z')); } +#[clippy::msrv = "1.24"] fn msrv_1_24() { - #![clippy::msrv = "1.24"] - assert!(matches!(b'1', b'0'..=b'9')); assert!(matches!('X', 'A'..='Z')); assert!(matches!('x', 'A'..='Z' | 'a'..='z')); } +#[clippy::msrv = "1.46"] fn msrv_1_46() { - #![clippy::msrv = "1.46"] const FOO: bool = matches!('x', '0'..='9'); } +#[clippy::msrv = "1.47"] fn msrv_1_47() { - #![clippy::msrv = "1.47"] const FOO: bool = matches!('x', '0'..='9'); } diff --git a/tests/ui/manual_is_ascii_check.stderr b/tests/ui/manual_is_ascii_check.stderr index c0a9d4db1a1..397cbe05c82 100644 --- a/tests/ui/manual_is_ascii_check.stderr +++ b/tests/ui/manual_is_ascii_check.stderr @@ -1,5 +1,5 @@ error: manual check for common ascii range - --> $DIR/manual_is_ascii_check.rs:8:13 + --> $DIR/manual_is_ascii_check.rs:7:13 | LL | assert!(matches!('x', 'a'..='z')); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_lowercase()` @@ -7,61 +7,61 @@ LL | assert!(matches!('x', 'a'..='z')); = note: `-D clippy::manual-is-ascii-check` implied by `-D warnings` error: manual check for common ascii range - --> $DIR/manual_is_ascii_check.rs:9:13 + --> $DIR/manual_is_ascii_check.rs:8:13 | LL | assert!(matches!('X', 'A'..='Z')); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'X'.is_ascii_uppercase()` error: manual check for common ascii range - --> $DIR/manual_is_ascii_check.rs:10:13 + --> $DIR/manual_is_ascii_check.rs:9:13 | LL | assert!(matches!(b'x', b'a'..=b'z')); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'x'.is_ascii_lowercase()` error: manual check for common ascii range - --> $DIR/manual_is_ascii_check.rs:11:13 + --> $DIR/manual_is_ascii_check.rs:10:13 | LL | assert!(matches!(b'X', b'A'..=b'Z')); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'X'.is_ascii_uppercase()` error: manual check for common ascii range - --> $DIR/manual_is_ascii_check.rs:14:13 + --> $DIR/manual_is_ascii_check.rs:13:13 | LL | assert!(matches!(num, '0'..='9')); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.is_ascii_digit()` error: manual check for common ascii range - --> $DIR/manual_is_ascii_check.rs:15:13 + --> $DIR/manual_is_ascii_check.rs:14:13 | LL | assert!(matches!(b'1', b'0'..=b'9')); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'1'.is_ascii_digit()` error: manual check for common ascii range - --> $DIR/manual_is_ascii_check.rs:16:13 + --> $DIR/manual_is_ascii_check.rs:15:13 | LL | assert!(matches!('x', 'A'..='Z' | 'a'..='z')); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_alphabetic()` error: manual check for common ascii range - --> $DIR/manual_is_ascii_check.rs:32:13 + --> $DIR/manual_is_ascii_check.rs:29:13 | LL | assert!(matches!(b'1', b'0'..=b'9')); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'1'.is_ascii_digit()` error: manual check for common ascii range - --> $DIR/manual_is_ascii_check.rs:33:13 + --> $DIR/manual_is_ascii_check.rs:30:13 | LL | assert!(matches!('X', 'A'..='Z')); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'X'.is_ascii_uppercase()` error: manual check for common ascii range - --> $DIR/manual_is_ascii_check.rs:34:13 + --> $DIR/manual_is_ascii_check.rs:31:13 | LL | assert!(matches!('x', 'A'..='Z' | 'a'..='z')); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_alphabetic()` error: manual check for common ascii range - --> $DIR/manual_is_ascii_check.rs:44:23 + --> $DIR/manual_is_ascii_check.rs:41:23 | LL | const FOO: bool = matches!('x', '0'..='9'); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_digit()` diff --git a/tests/ui/manual_rem_euclid.fixed b/tests/ui/manual_rem_euclid.fixed index b942fbfe930..4cdc0546a74 100644 --- a/tests/ui/manual_rem_euclid.fixed +++ b/tests/ui/manual_rem_euclid.fixed @@ -1,7 +1,6 @@ // run-rustfix // aux-build:macro_rules.rs -#![feature(custom_inner_attributes)] #![warn(clippy::manual_rem_euclid)] #[macro_use] @@ -55,31 +54,27 @@ pub const fn const_rem_euclid_4(num: i32) -> i32 { num.rem_euclid(4) } +#[clippy::msrv = "1.37"] pub fn msrv_1_37() { - #![clippy::msrv = "1.37"] - let x: i32 = 10; let _: i32 = ((x % 4) + 4) % 4; } +#[clippy::msrv = "1.38"] pub fn msrv_1_38() { - #![clippy::msrv = "1.38"] - let x: i32 = 10; let _: i32 = x.rem_euclid(4); } // For const fns: +#[clippy::msrv = "1.51"] pub const fn msrv_1_51() { - #![clippy::msrv = "1.51"] - let x: i32 = 10; let _: i32 = ((x % 4) + 4) % 4; } +#[clippy::msrv = "1.52"] pub const fn msrv_1_52() { - #![clippy::msrv = "1.52"] - let x: i32 = 10; let _: i32 = x.rem_euclid(4); } diff --git a/tests/ui/manual_rem_euclid.rs b/tests/ui/manual_rem_euclid.rs index 7462d532169..58a9e20f38b 100644 --- a/tests/ui/manual_rem_euclid.rs +++ b/tests/ui/manual_rem_euclid.rs @@ -1,7 +1,6 @@ // run-rustfix // aux-build:macro_rules.rs -#![feature(custom_inner_attributes)] #![warn(clippy::manual_rem_euclid)] #[macro_use] @@ -55,31 +54,27 @@ pub const fn const_rem_euclid_4(num: i32) -> i32 { ((num % 4) + 4) % 4 } +#[clippy::msrv = "1.37"] pub fn msrv_1_37() { - #![clippy::msrv = "1.37"] - let x: i32 = 10; let _: i32 = ((x % 4) + 4) % 4; } +#[clippy::msrv = "1.38"] pub fn msrv_1_38() { - #![clippy::msrv = "1.38"] - let x: i32 = 10; let _: i32 = ((x % 4) + 4) % 4; } // For const fns: +#[clippy::msrv = "1.51"] pub const fn msrv_1_51() { - #![clippy::msrv = "1.51"] - let x: i32 = 10; let _: i32 = ((x % 4) + 4) % 4; } +#[clippy::msrv = "1.52"] pub const fn msrv_1_52() { - #![clippy::msrv = "1.52"] - let x: i32 = 10; let _: i32 = ((x % 4) + 4) % 4; } diff --git a/tests/ui/manual_rem_euclid.stderr b/tests/ui/manual_rem_euclid.stderr index d51bac03b56..e3122a588b6 100644 --- a/tests/ui/manual_rem_euclid.stderr +++ b/tests/ui/manual_rem_euclid.stderr @@ -1,5 +1,5 @@ error: manual `rem_euclid` implementation - --> $DIR/manual_rem_euclid.rs:20:18 + --> $DIR/manual_rem_euclid.rs:19:18 | LL | let _: i32 = ((value % 4) + 4) % 4; | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)` @@ -7,31 +7,31 @@ LL | let _: i32 = ((value % 4) + 4) % 4; = note: `-D clippy::manual-rem-euclid` implied by `-D warnings` error: manual `rem_euclid` implementation - --> $DIR/manual_rem_euclid.rs:21:18 + --> $DIR/manual_rem_euclid.rs:20:18 | LL | let _: i32 = (4 + (value % 4)) % 4; | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)` error: manual `rem_euclid` implementation - --> $DIR/manual_rem_euclid.rs:22:18 + --> $DIR/manual_rem_euclid.rs:21:18 | LL | let _: i32 = (value % 4 + 4) % 4; | ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)` error: manual `rem_euclid` implementation - --> $DIR/manual_rem_euclid.rs:23:18 + --> $DIR/manual_rem_euclid.rs:22:18 | LL | let _: i32 = (4 + value % 4) % 4; | ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)` error: manual `rem_euclid` implementation - --> $DIR/manual_rem_euclid.rs:24:22 + --> $DIR/manual_rem_euclid.rs:23:22 | LL | let _: i32 = 1 + (4 + value % 4) % 4; | ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)` error: manual `rem_euclid` implementation - --> $DIR/manual_rem_euclid.rs:13:22 + --> $DIR/manual_rem_euclid.rs:12:22 | LL | let _: i32 = ((value % 4) + 4) % 4; | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)` @@ -42,25 +42,25 @@ LL | internal_rem_euclid!(); = note: this error originates in the macro `internal_rem_euclid` (in Nightly builds, run with -Z macro-backtrace for more info) error: manual `rem_euclid` implementation - --> $DIR/manual_rem_euclid.rs:50:5 + --> $DIR/manual_rem_euclid.rs:49:5 | LL | ((num % 4) + 4) % 4 | ^^^^^^^^^^^^^^^^^^^ help: consider using: `num.rem_euclid(4)` error: manual `rem_euclid` implementation - --> $DIR/manual_rem_euclid.rs:55:5 + --> $DIR/manual_rem_euclid.rs:54:5 | LL | ((num % 4) + 4) % 4 | ^^^^^^^^^^^^^^^^^^^ help: consider using: `num.rem_euclid(4)` error: manual `rem_euclid` implementation - --> $DIR/manual_rem_euclid.rs:69:18 + --> $DIR/manual_rem_euclid.rs:66:18 | LL | let _: i32 = ((x % 4) + 4) % 4; | ^^^^^^^^^^^^^^^^^ help: consider using: `x.rem_euclid(4)` error: manual `rem_euclid` implementation - --> $DIR/manual_rem_euclid.rs:84:18 + --> $DIR/manual_rem_euclid.rs:79:18 | LL | let _: i32 = ((x % 4) + 4) % 4; | ^^^^^^^^^^^^^^^^^ help: consider using: `x.rem_euclid(4)` diff --git a/tests/ui/manual_retain.fixed b/tests/ui/manual_retain.fixed index fba503a2066..e5ae3cf3e50 100644 --- a/tests/ui/manual_retain.fixed +++ b/tests/ui/manual_retain.fixed @@ -1,5 +1,4 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![warn(clippy::manual_retain)] #![allow(unused)] use std::collections::BTreeMap; @@ -216,8 +215,8 @@ fn vec_deque_retain() { bar = foobar.into_iter().filter(|x| x % 2 == 0).collect(); } +#[clippy::msrv = "1.52"] fn _msrv_153() { - #![clippy::msrv = "1.52"] let mut btree_map: BTreeMap = (0..8).map(|x| (x, x * 10)).collect(); btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); @@ -225,14 +224,14 @@ fn _msrv_153() { btree_set = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect(); } +#[clippy::msrv = "1.25"] fn _msrv_126() { - #![clippy::msrv = "1.25"] let mut s = String::from("foobar"); s = s.chars().filter(|&c| c != 'o').to_owned().collect(); } +#[clippy::msrv = "1.17"] fn _msrv_118() { - #![clippy::msrv = "1.17"] let mut hash_set = HashSet::from([1, 2, 3, 4, 5, 6]); hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect(); let mut hash_map: HashMap = (0..8).map(|x| (x, x * 10)).collect(); diff --git a/tests/ui/manual_retain.rs b/tests/ui/manual_retain.rs index 81a849fe768..1021f15edd1 100644 --- a/tests/ui/manual_retain.rs +++ b/tests/ui/manual_retain.rs @@ -1,5 +1,4 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![warn(clippy::manual_retain)] #![allow(unused)] use std::collections::BTreeMap; @@ -222,8 +221,8 @@ fn vec_deque_retain() { bar = foobar.into_iter().filter(|x| x % 2 == 0).collect(); } +#[clippy::msrv = "1.52"] fn _msrv_153() { - #![clippy::msrv = "1.52"] let mut btree_map: BTreeMap = (0..8).map(|x| (x, x * 10)).collect(); btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); @@ -231,14 +230,14 @@ fn _msrv_153() { btree_set = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect(); } +#[clippy::msrv = "1.25"] fn _msrv_126() { - #![clippy::msrv = "1.25"] let mut s = String::from("foobar"); s = s.chars().filter(|&c| c != 'o').to_owned().collect(); } +#[clippy::msrv = "1.17"] fn _msrv_118() { - #![clippy::msrv = "1.17"] let mut hash_set = HashSet::from([1, 2, 3, 4, 5, 6]); hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect(); let mut hash_map: HashMap = (0..8).map(|x| (x, x * 10)).collect(); diff --git a/tests/ui/manual_retain.stderr b/tests/ui/manual_retain.stderr index ec635919b48..89316ce1d99 100644 --- a/tests/ui/manual_retain.stderr +++ b/tests/ui/manual_retain.stderr @@ -1,5 +1,5 @@ error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:52:5 + --> $DIR/manual_retain.rs:51:5 | LL | btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_map.retain(|k, _| k % 2 == 0)` @@ -7,13 +7,13 @@ LL | btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect() = note: `-D clippy::manual-retain` implied by `-D warnings` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:53:5 + --> $DIR/manual_retain.rs:52:5 | LL | btree_map = btree_map.into_iter().filter(|(_, v)| v % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_map.retain(|_, &mut v| v % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:54:5 + --> $DIR/manual_retain.rs:53:5 | LL | / btree_map = btree_map LL | | .into_iter() @@ -22,37 +22,37 @@ LL | | .collect(); | |__________________^ help: consider calling `.retain()` instead: `btree_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0))` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:76:5 + --> $DIR/manual_retain.rs:75:5 | LL | btree_set = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:77:5 + --> $DIR/manual_retain.rs:76:5 | LL | btree_set = btree_set.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:78:5 + --> $DIR/manual_retain.rs:77:5 | LL | btree_set = btree_set.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:108:5 + --> $DIR/manual_retain.rs:107:5 | LL | hash_map = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_map.retain(|k, _| k % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:109:5 + --> $DIR/manual_retain.rs:108:5 | LL | hash_map = hash_map.into_iter().filter(|(_, v)| v % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_map.retain(|_, &mut v| v % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:110:5 + --> $DIR/manual_retain.rs:109:5 | LL | / hash_map = hash_map LL | | .into_iter() @@ -61,61 +61,61 @@ LL | | .collect(); | |__________________^ help: consider calling `.retain()` instead: `hash_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0))` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:131:5 + --> $DIR/manual_retain.rs:130:5 | LL | hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:132:5 + --> $DIR/manual_retain.rs:131:5 | LL | hash_set = hash_set.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:133:5 + --> $DIR/manual_retain.rs:132:5 | LL | hash_set = hash_set.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:162:5 + --> $DIR/manual_retain.rs:161:5 | LL | s = s.chars().filter(|&c| c != 'o').to_owned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `s.retain(|c| c != 'o')` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:174:5 + --> $DIR/manual_retain.rs:173:5 | LL | vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:175:5 + --> $DIR/manual_retain.rs:174:5 | LL | vec = vec.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:176:5 + --> $DIR/manual_retain.rs:175:5 | LL | vec = vec.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:198:5 + --> $DIR/manual_retain.rs:197:5 | LL | vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:199:5 + --> $DIR/manual_retain.rs:198:5 | LL | vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:200:5 + --> $DIR/manual_retain.rs:199:5 | LL | vec_deque = vec_deque.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)` diff --git a/tests/ui/manual_split_once.fixed b/tests/ui/manual_split_once.fixed index c7ca770434a..50b02019cc2 100644 --- a/tests/ui/manual_split_once.fixed +++ b/tests/ui/manual_split_once.fixed @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![warn(clippy::manual_split_once)] #![allow(unused, clippy::iter_skip_next, clippy::iter_nth_zero)] @@ -127,8 +126,8 @@ fn indirect() -> Option<()> { None } +#[clippy::msrv = "1.51"] fn _msrv_1_51() { - #![clippy::msrv = "1.51"] // `str::split_once` was stabilized in 1.52. Do not lint this let _ = "key=value".splitn(2, '=').nth(1).unwrap(); @@ -137,8 +136,8 @@ fn _msrv_1_51() { let b = iter.next().unwrap(); } +#[clippy::msrv = "1.52"] fn _msrv_1_52() { - #![clippy::msrv = "1.52"] let _ = "key=value".split_once('=').unwrap().1; let (a, b) = "a.b.c".split_once('.').unwrap(); diff --git a/tests/ui/manual_split_once.rs b/tests/ui/manual_split_once.rs index ee2848a251e..e1e8b71a9de 100644 --- a/tests/ui/manual_split_once.rs +++ b/tests/ui/manual_split_once.rs @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![warn(clippy::manual_split_once)] #![allow(unused, clippy::iter_skip_next, clippy::iter_nth_zero)] @@ -127,8 +126,8 @@ fn indirect() -> Option<()> { None } +#[clippy::msrv = "1.51"] fn _msrv_1_51() { - #![clippy::msrv = "1.51"] // `str::split_once` was stabilized in 1.52. Do not lint this let _ = "key=value".splitn(2, '=').nth(1).unwrap(); @@ -137,8 +136,8 @@ fn _msrv_1_51() { let b = iter.next().unwrap(); } +#[clippy::msrv = "1.52"] fn _msrv_1_52() { - #![clippy::msrv = "1.52"] let _ = "key=value".splitn(2, '=').nth(1).unwrap(); let mut iter = "a.b.c".splitn(2, '.'); diff --git a/tests/ui/manual_split_once.stderr b/tests/ui/manual_split_once.stderr index 2696694680a..78da5a16cc5 100644 --- a/tests/ui/manual_split_once.stderr +++ b/tests/ui/manual_split_once.stderr @@ -1,5 +1,5 @@ error: manual implementation of `split_once` - --> $DIR/manual_split_once.rs:14:13 + --> $DIR/manual_split_once.rs:13:13 | LL | let _ = "key=value".splitn(2, '=').nth(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=').unwrap().1` @@ -7,79 +7,79 @@ LL | let _ = "key=value".splitn(2, '=').nth(1).unwrap(); = note: `-D clippy::manual-split-once` implied by `-D warnings` error: manual implementation of `split_once` - --> $DIR/manual_split_once.rs:15:13 + --> $DIR/manual_split_once.rs:14:13 | LL | let _ = "key=value".splitn(2, '=').skip(1).next().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=').unwrap().1` error: manual implementation of `split_once` - --> $DIR/manual_split_once.rs:16:18 + --> $DIR/manual_split_once.rs:15:18 | LL | let (_, _) = "key=value".splitn(2, '=').next_tuple().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=')` error: manual implementation of `split_once` - --> $DIR/manual_split_once.rs:19:13 + --> $DIR/manual_split_once.rs:18:13 | LL | let _ = s.splitn(2, '=').nth(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once('=').unwrap().1` error: manual implementation of `split_once` - --> $DIR/manual_split_once.rs:22:13 + --> $DIR/manual_split_once.rs:21:13 | LL | let _ = s.splitn(2, '=').nth(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once('=').unwrap().1` error: manual implementation of `split_once` - --> $DIR/manual_split_once.rs:25:13 + --> $DIR/manual_split_once.rs:24:13 | LL | let _ = s.splitn(2, '=').skip(1).next().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once('=').unwrap().1` error: manual implementation of `split_once` - --> $DIR/manual_split_once.rs:28:17 + --> $DIR/manual_split_once.rs:27:17 | LL | let _ = s.splitn(2, '=').nth(1)?; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once('=')?.1` error: manual implementation of `split_once` - --> $DIR/manual_split_once.rs:29:17 + --> $DIR/manual_split_once.rs:28:17 | LL | let _ = s.splitn(2, '=').skip(1).next()?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once('=')?.1` error: manual implementation of `rsplit_once` - --> $DIR/manual_split_once.rs:30:17 + --> $DIR/manual_split_once.rs:29:17 | LL | let _ = s.rsplitn(2, '=').nth(1)?; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.rsplit_once('=')?.0` error: manual implementation of `rsplit_once` - --> $DIR/manual_split_once.rs:31:17 + --> $DIR/manual_split_once.rs:30:17 | LL | let _ = s.rsplitn(2, '=').skip(1).next()?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.rsplit_once('=')?.0` error: manual implementation of `rsplit_once` - --> $DIR/manual_split_once.rs:39:13 + --> $DIR/manual_split_once.rs:38:13 | LL | let _ = "key=value".rsplitn(2, '=').nth(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".rsplit_once('=').unwrap().0` error: manual implementation of `rsplit_once` - --> $DIR/manual_split_once.rs:40:18 + --> $DIR/manual_split_once.rs:39:18 | LL | let (_, _) = "key=value".rsplitn(2, '=').next_tuple().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".rsplit_once('=').map(|(x, y)| (y, x))` error: manual implementation of `rsplit_once` - --> $DIR/manual_split_once.rs:41:13 + --> $DIR/manual_split_once.rs:40:13 | LL | let _ = s.rsplitn(2, '=').nth(1); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.rsplit_once('=').map(|x| x.0)` error: manual implementation of `split_once` - --> $DIR/manual_split_once.rs:45:5 + --> $DIR/manual_split_once.rs:44:5 | LL | let mut iter = "a.b.c".splitn(2, '.'); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -104,7 +104,7 @@ LL + | error: manual implementation of `split_once` - --> $DIR/manual_split_once.rs:49:5 + --> $DIR/manual_split_once.rs:48:5 | LL | let mut iter = "a.b.c".splitn(2, '.'); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -129,7 +129,7 @@ LL + | error: manual implementation of `rsplit_once` - --> $DIR/manual_split_once.rs:53:5 + --> $DIR/manual_split_once.rs:52:5 | LL | let mut iter = "a.b.c".rsplitn(2, '.'); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -154,7 +154,7 @@ LL + | error: manual implementation of `rsplit_once` - --> $DIR/manual_split_once.rs:57:5 + --> $DIR/manual_split_once.rs:56:5 | LL | let mut iter = "a.b.c".rsplitn(2, '.'); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -179,13 +179,13 @@ LL + | error: manual implementation of `split_once` - --> $DIR/manual_split_once.rs:142:13 + --> $DIR/manual_split_once.rs:141:13 | LL | let _ = "key=value".splitn(2, '=').nth(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=').unwrap().1` error: manual implementation of `split_once` - --> $DIR/manual_split_once.rs:144:5 + --> $DIR/manual_split_once.rs:143:5 | LL | let mut iter = "a.b.c".splitn(2, '.'); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/manual_str_repeat.fixed b/tests/ui/manual_str_repeat.fixed index 0704ba2f933..3d56f2a0ded 100644 --- a/tests/ui/manual_str_repeat.fixed +++ b/tests/ui/manual_str_repeat.fixed @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![warn(clippy::manual_str_repeat)] use std::borrow::Cow; @@ -54,13 +53,13 @@ fn main() { let _: String = repeat(x).take(count).collect(); } +#[clippy::msrv = "1.15"] fn _msrv_1_15() { - #![clippy::msrv = "1.15"] // `str::repeat` was stabilized in 1.16. Do not lint this let _: String = std::iter::repeat("test").take(10).collect(); } +#[clippy::msrv = "1.16"] fn _msrv_1_16() { - #![clippy::msrv = "1.16"] let _: String = "test".repeat(10); } diff --git a/tests/ui/manual_str_repeat.rs b/tests/ui/manual_str_repeat.rs index f522be439aa..e8240a949db 100644 --- a/tests/ui/manual_str_repeat.rs +++ b/tests/ui/manual_str_repeat.rs @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![warn(clippy::manual_str_repeat)] use std::borrow::Cow; @@ -54,13 +53,13 @@ fn main() { let _: String = repeat(x).take(count).collect(); } +#[clippy::msrv = "1.15"] fn _msrv_1_15() { - #![clippy::msrv = "1.15"] // `str::repeat` was stabilized in 1.16. Do not lint this let _: String = std::iter::repeat("test").take(10).collect(); } +#[clippy::msrv = "1.16"] fn _msrv_1_16() { - #![clippy::msrv = "1.16"] let _: String = std::iter::repeat("test").take(10).collect(); } diff --git a/tests/ui/manual_str_repeat.stderr b/tests/ui/manual_str_repeat.stderr index c6511689716..bdfee7cab26 100644 --- a/tests/ui/manual_str_repeat.stderr +++ b/tests/ui/manual_str_repeat.stderr @@ -1,5 +1,5 @@ error: manual implementation of `str::repeat` using iterators - --> $DIR/manual_str_repeat.rs:10:21 + --> $DIR/manual_str_repeat.rs:9:21 | LL | let _: String = std::iter::repeat("test").take(10).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"test".repeat(10)` @@ -7,55 +7,55 @@ LL | let _: String = std::iter::repeat("test").take(10).collect(); = note: `-D clippy::manual-str-repeat` implied by `-D warnings` error: manual implementation of `str::repeat` using iterators - --> $DIR/manual_str_repeat.rs:11:21 + --> $DIR/manual_str_repeat.rs:10:21 | LL | let _: String = std::iter::repeat('x').take(10).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"x".repeat(10)` error: manual implementation of `str::repeat` using iterators - --> $DIR/manual_str_repeat.rs:12:21 + --> $DIR/manual_str_repeat.rs:11:21 | LL | let _: String = std::iter::repeat('/'').take(10).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"'".repeat(10)` error: manual implementation of `str::repeat` using iterators - --> $DIR/manual_str_repeat.rs:13:21 + --> $DIR/manual_str_repeat.rs:12:21 | LL | let _: String = std::iter::repeat('"').take(10).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"/"".repeat(10)` error: manual implementation of `str::repeat` using iterators - --> $DIR/manual_str_repeat.rs:17:13 + --> $DIR/manual_str_repeat.rs:16:13 | LL | let _ = repeat(x).take(count + 2).collect::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `x.repeat(count + 2)` error: manual implementation of `str::repeat` using iterators - --> $DIR/manual_str_repeat.rs:26:21 + --> $DIR/manual_str_repeat.rs:25:21 | LL | let _: String = repeat(*x).take(count).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(*x).repeat(count)` error: manual implementation of `str::repeat` using iterators - --> $DIR/manual_str_repeat.rs:35:21 + --> $DIR/manual_str_repeat.rs:34:21 | LL | let _: String = repeat(x).take(count).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `x.repeat(count)` error: manual implementation of `str::repeat` using iterators - --> $DIR/manual_str_repeat.rs:47:21 + --> $DIR/manual_str_repeat.rs:46:21 | LL | let _: String = repeat(Cow::Borrowed("test")).take(count).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `Cow::Borrowed("test").repeat(count)` error: manual implementation of `str::repeat` using iterators - --> $DIR/manual_str_repeat.rs:50:21 + --> $DIR/manual_str_repeat.rs:49:21 | LL | let _: String = repeat(x).take(count).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `x.repeat(count)` error: manual implementation of `str::repeat` using iterators - --> $DIR/manual_str_repeat.rs:65:21 + --> $DIR/manual_str_repeat.rs:64:21 | LL | let _: String = std::iter::repeat("test").take(10).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"test".repeat(10)` diff --git a/tests/ui/manual_strip.rs b/tests/ui/manual_strip.rs index 85009d78558..b0b1c262aee 100644 --- a/tests/ui/manual_strip.rs +++ b/tests/ui/manual_strip.rs @@ -1,4 +1,3 @@ -#![feature(custom_inner_attributes)] #![warn(clippy::manual_strip)] fn main() { @@ -66,18 +65,16 @@ fn main() { } } +#[clippy::msrv = "1.44"] fn msrv_1_44() { - #![clippy::msrv = "1.44"] - let s = "abc"; if s.starts_with('a') { s[1..].to_string(); } } +#[clippy::msrv = "1.45"] fn msrv_1_45() { - #![clippy::msrv = "1.45"] - let s = "abc"; if s.starts_with('a') { s[1..].to_string(); diff --git a/tests/ui/manual_strip.stderr b/tests/ui/manual_strip.stderr index ad2a362f3e7..f592e898fc9 100644 --- a/tests/ui/manual_strip.stderr +++ b/tests/ui/manual_strip.stderr @@ -1,11 +1,11 @@ error: stripping a prefix manually - --> $DIR/manual_strip.rs:8:24 + --> $DIR/manual_strip.rs:7:24 | LL | str::to_string(&s["ab".len()..]); | ^^^^^^^^^^^^^^^^ | note: the prefix was tested here - --> $DIR/manual_strip.rs:7:5 + --> $DIR/manual_strip.rs:6:5 | LL | if s.starts_with("ab") { | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -21,13 +21,13 @@ LL ~ .to_string(); | error: stripping a suffix manually - --> $DIR/manual_strip.rs:16:24 + --> $DIR/manual_strip.rs:15:24 | LL | str::to_string(&s[..s.len() - "bc".len()]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the suffix was tested here - --> $DIR/manual_strip.rs:15:5 + --> $DIR/manual_strip.rs:14:5 | LL | if s.ends_with("bc") { | ^^^^^^^^^^^^^^^^^^^^^ @@ -42,13 +42,13 @@ LL ~ .to_string(); | error: stripping a prefix manually - --> $DIR/manual_strip.rs:25:24 + --> $DIR/manual_strip.rs:24:24 | LL | str::to_string(&s[1..]); | ^^^^^^^ | note: the prefix was tested here - --> $DIR/manual_strip.rs:24:5 + --> $DIR/manual_strip.rs:23:5 | LL | if s.starts_with('a') { | ^^^^^^^^^^^^^^^^^^^^^^ @@ -60,13 +60,13 @@ LL ~ .to_string(); | error: stripping a prefix manually - --> $DIR/manual_strip.rs:32:24 + --> $DIR/manual_strip.rs:31:24 | LL | str::to_string(&s[prefix.len()..]); | ^^^^^^^^^^^^^^^^^^ | note: the prefix was tested here - --> $DIR/manual_strip.rs:31:5 + --> $DIR/manual_strip.rs:30:5 | LL | if s.starts_with(prefix) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -77,13 +77,13 @@ LL ~ str::to_string(); | error: stripping a prefix manually - --> $DIR/manual_strip.rs:38:24 + --> $DIR/manual_strip.rs:37:24 | LL | str::to_string(&s[PREFIX.len()..]); | ^^^^^^^^^^^^^^^^^^ | note: the prefix was tested here - --> $DIR/manual_strip.rs:37:5 + --> $DIR/manual_strip.rs:36:5 | LL | if s.starts_with(PREFIX) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -95,13 +95,13 @@ LL ~ str::to_string(); | error: stripping a prefix manually - --> $DIR/manual_strip.rs:45:24 + --> $DIR/manual_strip.rs:44:24 | LL | str::to_string(&TARGET[prefix.len()..]); | ^^^^^^^^^^^^^^^^^^^^^^^ | note: the prefix was tested here - --> $DIR/manual_strip.rs:44:5 + --> $DIR/manual_strip.rs:43:5 | LL | if TARGET.starts_with(prefix) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -112,13 +112,13 @@ LL ~ str::to_string(); | error: stripping a prefix manually - --> $DIR/manual_strip.rs:51:9 + --> $DIR/manual_strip.rs:50:9 | LL | s1[2..].to_uppercase(); | ^^^^^^^ | note: the prefix was tested here - --> $DIR/manual_strip.rs:50:5 + --> $DIR/manual_strip.rs:49:5 | LL | if s1.starts_with("ab") { | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -129,13 +129,13 @@ LL ~ .to_uppercase(); | error: stripping a prefix manually - --> $DIR/manual_strip.rs:83:9 + --> $DIR/manual_strip.rs:80:9 | LL | s[1..].to_string(); | ^^^^^^ | note: the prefix was tested here - --> $DIR/manual_strip.rs:82:5 + --> $DIR/manual_strip.rs:79:5 | LL | if s.starts_with('a') { | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/map_unwrap_or.rs b/tests/ui/map_unwrap_or.rs index 396b22a9abb..32631024ca5 100644 --- a/tests/ui/map_unwrap_or.rs +++ b/tests/ui/map_unwrap_or.rs @@ -1,6 +1,5 @@ // aux-build:option_helpers.rs -#![feature(custom_inner_attributes)] #![warn(clippy::map_unwrap_or)] #![allow(clippy::uninlined_format_args, clippy::unnecessary_lazy_evaluations)] @@ -82,17 +81,15 @@ fn main() { result_methods(); } +#[clippy::msrv = "1.40"] fn msrv_1_40() { - #![clippy::msrv = "1.40"] - let res: Result = Ok(1); let _ = res.map(|x| x + 1).unwrap_or_else(|_e| 0); } +#[clippy::msrv = "1.41"] fn msrv_1_41() { - #![clippy::msrv = "1.41"] - let res: Result = Ok(1); let _ = res.map(|x| x + 1).unwrap_or_else(|_e| 0); diff --git a/tests/ui/map_unwrap_or.stderr b/tests/ui/map_unwrap_or.stderr index d17d24a403e..41781b050fa 100644 --- a/tests/ui/map_unwrap_or.stderr +++ b/tests/ui/map_unwrap_or.stderr @@ -1,5 +1,5 @@ error: called `map().unwrap_or()` on an `Option` value. This can be done more directly by calling `map_or(, )` instead - --> $DIR/map_unwrap_or.rs:18:13 + --> $DIR/map_unwrap_or.rs:17:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -15,7 +15,7 @@ LL + let _ = opt.map_or(0, |x| x + 1); | error: called `map().unwrap_or()` on an `Option` value. This can be done more directly by calling `map_or(, )` instead - --> $DIR/map_unwrap_or.rs:22:13 + --> $DIR/map_unwrap_or.rs:21:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -33,7 +33,7 @@ LL ~ ); | error: called `map().unwrap_or()` on an `Option` value. This can be done more directly by calling `map_or(, )` instead - --> $DIR/map_unwrap_or.rs:26:13 + --> $DIR/map_unwrap_or.rs:25:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -50,7 +50,7 @@ LL ~ }, |x| x + 1); | error: called `map().unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then()` instead - --> $DIR/map_unwrap_or.rs:31:13 + --> $DIR/map_unwrap_or.rs:30:13 | LL | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -62,7 +62,7 @@ LL + let _ = opt.and_then(|x| Some(x + 1)); | error: called `map().unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then()` instead - --> $DIR/map_unwrap_or.rs:33:13 + --> $DIR/map_unwrap_or.rs:32:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -80,7 +80,7 @@ LL ~ ); | error: called `map().unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then()` instead - --> $DIR/map_unwrap_or.rs:37:13 + --> $DIR/map_unwrap_or.rs:36:13 | LL | let _ = opt | _____________^ @@ -95,7 +95,7 @@ LL + .and_then(|x| Some(x + 1)); | error: called `map().unwrap_or()` on an `Option` value. This can be done more directly by calling `map_or(, )` instead - --> $DIR/map_unwrap_or.rs:48:13 + --> $DIR/map_unwrap_or.rs:47:13 | LL | let _ = Some("prefix").map(|p| format!("{}.", p)).unwrap_or(id); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -107,7 +107,7 @@ LL + let _ = Some("prefix").map_or(id, |p| format!("{}.", p)); | error: called `map().unwrap_or_else()` on an `Option` value. This can be done more directly by calling `map_or_else(, )` instead - --> $DIR/map_unwrap_or.rs:52:13 + --> $DIR/map_unwrap_or.rs:51:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -117,7 +117,7 @@ LL | | ).unwrap_or_else(|| 0); | |__________________________^ error: called `map().unwrap_or_else()` on an `Option` value. This can be done more directly by calling `map_or_else(, )` instead - --> $DIR/map_unwrap_or.rs:56:13 + --> $DIR/map_unwrap_or.rs:55:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -127,7 +127,7 @@ LL | | ); | |_________^ error: called `map().unwrap_or_else()` on a `Result` value. This can be done more directly by calling `.map_or_else(, )` instead - --> $DIR/map_unwrap_or.rs:68:13 + --> $DIR/map_unwrap_or.rs:67:13 | LL | let _ = res.map(|x| { | _____________^ @@ -137,7 +137,7 @@ LL | | ).unwrap_or_else(|_e| 0); | |____________________________^ error: called `map().unwrap_or_else()` on a `Result` value. This can be done more directly by calling `.map_or_else(, )` instead - --> $DIR/map_unwrap_or.rs:72:13 + --> $DIR/map_unwrap_or.rs:71:13 | LL | let _ = res.map(|x| x + 1) | _____________^ @@ -147,7 +147,7 @@ LL | | }); | |__________^ error: called `map().unwrap_or_else()` on a `Result` value. This can be done more directly by calling `.map_or_else(, )` instead - --> $DIR/map_unwrap_or.rs:98:13 + --> $DIR/map_unwrap_or.rs:95:13 | LL | let _ = res.map(|x| x + 1).unwrap_or_else(|_e| 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `res.map_or_else(|_e| 0, |x| x + 1)` diff --git a/tests/ui/match_expr_like_matches_macro.fixed b/tests/ui/match_expr_like_matches_macro.fixed index 968f462f8a0..55cd15bd5c3 100644 --- a/tests/ui/match_expr_like_matches_macro.fixed +++ b/tests/ui/match_expr_like_matches_macro.fixed @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![warn(clippy::match_like_matches_macro)] #![allow( unreachable_patterns, @@ -200,17 +199,15 @@ fn main() { }; } +#[clippy::msrv = "1.41"] fn msrv_1_41() { - #![clippy::msrv = "1.41"] - let _y = match Some(5) { Some(0) => true, _ => false, }; } +#[clippy::msrv = "1.42"] fn msrv_1_42() { - #![clippy::msrv = "1.42"] - let _y = matches!(Some(5), Some(0)); } diff --git a/tests/ui/match_expr_like_matches_macro.rs b/tests/ui/match_expr_like_matches_macro.rs index c6b479e27c5..5d645e108e5 100644 --- a/tests/ui/match_expr_like_matches_macro.rs +++ b/tests/ui/match_expr_like_matches_macro.rs @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![warn(clippy::match_like_matches_macro)] #![allow( unreachable_patterns, @@ -241,18 +240,16 @@ fn main() { }; } +#[clippy::msrv = "1.41"] fn msrv_1_41() { - #![clippy::msrv = "1.41"] - let _y = match Some(5) { Some(0) => true, _ => false, }; } +#[clippy::msrv = "1.42"] fn msrv_1_42() { - #![clippy::msrv = "1.42"] - let _y = match Some(5) { Some(0) => true, _ => false, diff --git a/tests/ui/match_expr_like_matches_macro.stderr b/tests/ui/match_expr_like_matches_macro.stderr index a4df8008ac2..46f67ef4900 100644 --- a/tests/ui/match_expr_like_matches_macro.stderr +++ b/tests/ui/match_expr_like_matches_macro.stderr @@ -1,5 +1,5 @@ error: match expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:16:14 + --> $DIR/match_expr_like_matches_macro.rs:15:14 | LL | let _y = match x { | ______________^ @@ -11,7 +11,7 @@ LL | | }; = note: `-D clippy::match-like-matches-macro` implied by `-D warnings` error: match expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:22:14 + --> $DIR/match_expr_like_matches_macro.rs:21:14 | LL | let _w = match x { | ______________^ @@ -21,7 +21,7 @@ LL | | }; | |_____^ help: try this: `matches!(x, Some(_))` error: redundant pattern matching, consider using `is_none()` - --> $DIR/match_expr_like_matches_macro.rs:28:14 + --> $DIR/match_expr_like_matches_macro.rs:27:14 | LL | let _z = match x { | ______________^ @@ -33,7 +33,7 @@ LL | | }; = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` error: match expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:34:15 + --> $DIR/match_expr_like_matches_macro.rs:33:15 | LL | let _zz = match x { | _______________^ @@ -43,13 +43,13 @@ LL | | }; | |_____^ help: try this: `!matches!(x, Some(r) if r == 0)` error: if let .. else expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:40:16 + --> $DIR/match_expr_like_matches_macro.rs:39:16 | LL | let _zzz = if let Some(5) = x { true } else { false }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `matches!(x, Some(5))` error: match expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:64:20 + --> $DIR/match_expr_like_matches_macro.rs:63:20 | LL | let _ans = match x { | ____________________^ @@ -60,7 +60,7 @@ LL | | }; | |_________^ help: try this: `matches!(x, E::A(_) | E::B(_))` error: match expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:74:20 + --> $DIR/match_expr_like_matches_macro.rs:73:20 | LL | let _ans = match x { | ____________________^ @@ -73,7 +73,7 @@ LL | | }; | |_________^ help: try this: `matches!(x, E::A(_) | E::B(_))` error: match expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:84:20 + --> $DIR/match_expr_like_matches_macro.rs:83:20 | LL | let _ans = match x { | ____________________^ @@ -84,7 +84,7 @@ LL | | }; | |_________^ help: try this: `!matches!(x, E::B(_) | E::C)` error: match expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:144:18 + --> $DIR/match_expr_like_matches_macro.rs:143:18 | LL | let _z = match &z { | __________________^ @@ -94,7 +94,7 @@ LL | | }; | |_________^ help: try this: `matches!(z, Some(3))` error: match expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:153:18 + --> $DIR/match_expr_like_matches_macro.rs:152:18 | LL | let _z = match &z { | __________________^ @@ -104,7 +104,7 @@ LL | | }; | |_________^ help: try this: `matches!(&z, Some(3))` error: match expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:170:21 + --> $DIR/match_expr_like_matches_macro.rs:169:21 | LL | let _ = match &z { | _____________________^ @@ -114,7 +114,7 @@ LL | | }; | |_____________^ help: try this: `matches!(&z, AnEnum::X)` error: match expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:184:20 + --> $DIR/match_expr_like_matches_macro.rs:183:20 | LL | let _res = match &val { | ____________________^ @@ -124,7 +124,7 @@ LL | | }; | |_________^ help: try this: `matches!(&val, &Some(ref _a))` error: match expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:196:20 + --> $DIR/match_expr_like_matches_macro.rs:195:20 | LL | let _res = match &val { | ____________________^ @@ -134,7 +134,7 @@ LL | | }; | |_________^ help: try this: `matches!(&val, &Some(ref _a))` error: match expression looks like `matches!` macro - --> $DIR/match_expr_like_matches_macro.rs:256:14 + --> $DIR/match_expr_like_matches_macro.rs:253:14 | LL | let _y = match Some(5) { | ______________^ diff --git a/tests/ui/mem_replace.fixed b/tests/ui/mem_replace.fixed index ae237395b95..874d5584330 100644 --- a/tests/ui/mem_replace.fixed +++ b/tests/ui/mem_replace.fixed @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![allow(unused)] #![warn( clippy::all, @@ -80,16 +79,14 @@ fn main() { dont_lint_primitive(); } +#[clippy::msrv = "1.39"] fn msrv_1_39() { - #![clippy::msrv = "1.39"] - let mut s = String::from("foo"); let _ = std::mem::replace(&mut s, String::default()); } +#[clippy::msrv = "1.40"] fn msrv_1_40() { - #![clippy::msrv = "1.40"] - let mut s = String::from("foo"); let _ = std::mem::take(&mut s); } diff --git a/tests/ui/mem_replace.rs b/tests/ui/mem_replace.rs index 3202e99e0be..f4f3bff5144 100644 --- a/tests/ui/mem_replace.rs +++ b/tests/ui/mem_replace.rs @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![allow(unused)] #![warn( clippy::all, @@ -80,16 +79,14 @@ fn main() { dont_lint_primitive(); } +#[clippy::msrv = "1.39"] fn msrv_1_39() { - #![clippy::msrv = "1.39"] - let mut s = String::from("foo"); let _ = std::mem::replace(&mut s, String::default()); } +#[clippy::msrv = "1.40"] fn msrv_1_40() { - #![clippy::msrv = "1.40"] - let mut s = String::from("foo"); let _ = std::mem::replace(&mut s, String::default()); } diff --git a/tests/ui/mem_replace.stderr b/tests/ui/mem_replace.stderr index dd8a50dab90..caa127f76ee 100644 --- a/tests/ui/mem_replace.stderr +++ b/tests/ui/mem_replace.stderr @@ -1,5 +1,5 @@ error: replacing an `Option` with `None` - --> $DIR/mem_replace.rs:17:13 + --> $DIR/mem_replace.rs:16:13 | LL | let _ = mem::replace(&mut an_option, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()` @@ -7,13 +7,13 @@ LL | let _ = mem::replace(&mut an_option, None); = note: `-D clippy::mem-replace-option-with-none` implied by `-D warnings` error: replacing an `Option` with `None` - --> $DIR/mem_replace.rs:19:13 + --> $DIR/mem_replace.rs:18:13 | LL | let _ = mem::replace(an_option, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:24:13 + --> $DIR/mem_replace.rs:23:13 | LL | let _ = std::mem::replace(&mut s, String::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut s)` @@ -21,103 +21,103 @@ LL | let _ = std::mem::replace(&mut s, String::default()); = note: `-D clippy::mem-replace-with-default` implied by `-D warnings` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:27:13 + --> $DIR/mem_replace.rs:26:13 | LL | let _ = std::mem::replace(s, String::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(s)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:28:13 + --> $DIR/mem_replace.rs:27:13 | LL | let _ = std::mem::replace(s, Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(s)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:31:13 + --> $DIR/mem_replace.rs:30:13 | LL | let _ = std::mem::replace(&mut v, Vec::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:32:13 + --> $DIR/mem_replace.rs:31:13 | LL | let _ = std::mem::replace(&mut v, Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:33:13 + --> $DIR/mem_replace.rs:32:13 | LL | let _ = std::mem::replace(&mut v, Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:34:13 + --> $DIR/mem_replace.rs:33:13 | LL | let _ = std::mem::replace(&mut v, vec![]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:37:13 + --> $DIR/mem_replace.rs:36:13 | LL | let _ = std::mem::replace(&mut hash_map, HashMap::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut hash_map)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:40:13 + --> $DIR/mem_replace.rs:39:13 | LL | let _ = std::mem::replace(&mut btree_map, BTreeMap::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut btree_map)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:43:13 + --> $DIR/mem_replace.rs:42:13 | LL | let _ = std::mem::replace(&mut vd, VecDeque::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut vd)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:46:13 + --> $DIR/mem_replace.rs:45:13 | LL | let _ = std::mem::replace(&mut hash_set, HashSet::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut hash_set)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:49:13 + --> $DIR/mem_replace.rs:48:13 | LL | let _ = std::mem::replace(&mut btree_set, BTreeSet::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut btree_set)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:52:13 + --> $DIR/mem_replace.rs:51:13 | LL | let _ = std::mem::replace(&mut list, LinkedList::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut list)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:55:13 + --> $DIR/mem_replace.rs:54:13 | LL | let _ = std::mem::replace(&mut binary_heap, BinaryHeap::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut binary_heap)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:58:13 + --> $DIR/mem_replace.rs:57:13 | LL | let _ = std::mem::replace(&mut tuple, (vec![], BinaryHeap::new())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut tuple)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:61:13 + --> $DIR/mem_replace.rs:60:13 | LL | let _ = std::mem::replace(&mut refstr, ""); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut refstr)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:64:13 + --> $DIR/mem_replace.rs:63:13 | LL | let _ = std::mem::replace(&mut slice, &[]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut slice)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:94:13 + --> $DIR/mem_replace.rs:91:13 | LL | let _ = std::mem::replace(&mut s, String::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut s)` diff --git a/tests/ui/min_rust_version_attr.rs b/tests/ui/min_rust_version_attr.rs index 28ab132394b..955e7eb7276 100644 --- a/tests/ui/min_rust_version_attr.rs +++ b/tests/ui/min_rust_version_attr.rs @@ -3,27 +3,37 @@ fn main() {} +#[clippy::msrv = "1.42.0"] fn just_under_msrv() { - #![clippy::msrv = "1.42.0"] let log2_10 = 3.321928094887362; } +#[clippy::msrv = "1.43.0"] fn meets_msrv() { - #![clippy::msrv = "1.43.0"] let log2_10 = 3.321928094887362; } +#[clippy::msrv = "1.44.0"] fn just_above_msrv() { - #![clippy::msrv = "1.44.0"] let log2_10 = 3.321928094887362; } +#[clippy::msrv = "1.42"] fn no_patch_under() { - #![clippy::msrv = "1.42"] let log2_10 = 3.321928094887362; } +#[clippy::msrv = "1.43"] fn no_patch_meets() { + let log2_10 = 3.321928094887362; +} + +fn inner_attr_under() { + #![clippy::msrv = "1.42"] + let log2_10 = 3.321928094887362; +} + +fn inner_attr_meets() { #![clippy::msrv = "1.43"] let log2_10 = 3.321928094887362; } diff --git a/tests/ui/min_rust_version_attr.stderr b/tests/ui/min_rust_version_attr.stderr index 6174443372f..7e2135584ef 100644 --- a/tests/ui/min_rust_version_attr.stderr +++ b/tests/ui/min_rust_version_attr.stderr @@ -32,12 +32,20 @@ LL | let log2_10 = 3.321928094887362; = help: consider using the constant directly error: approximate value of `f{32, 64}::consts::LOG2_10` found - --> $DIR/min_rust_version_attr.rs:45:27 + --> $DIR/min_rust_version_attr.rs:48:19 + | +LL | let log2_10 = 3.321928094887362; + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using the constant directly + +error: approximate value of `f{32, 64}::consts::LOG2_10` found + --> $DIR/min_rust_version_attr.rs:55:27 | LL | let log2_10 = 3.321928094887362; | ^^^^^^^^^^^^^^^^^ | = help: consider using the constant directly -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors diff --git a/tests/ui/min_rust_version_invalid_attr.stderr b/tests/ui/min_rust_version_invalid_attr.stderr index 93370a0fa9c..675b7803152 100644 --- a/tests/ui/min_rust_version_invalid_attr.stderr +++ b/tests/ui/min_rust_version_invalid_attr.stderr @@ -4,7 +4,7 @@ error: `invalid.version` is not a valid Rust version LL | #![clippy::msrv = "invalid.version"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `msrv` cannot be an outer attribute +error: `invalid.version` is not a valid Rust version --> $DIR/min_rust_version_invalid_attr.rs:6:1 | LL | #[clippy::msrv = "invalid.version"] diff --git a/tests/ui/missing_const_for_fn/cant_be_const.rs b/tests/ui/missing_const_for_fn/cant_be_const.rs index b950248ef94..75cace18167 100644 --- a/tests/ui/missing_const_for_fn/cant_be_const.rs +++ b/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -7,7 +7,6 @@ #![warn(clippy::missing_const_for_fn)] #![feature(start)] -#![feature(custom_inner_attributes)] extern crate helper; extern crate proc_macro_with_span; @@ -115,9 +114,8 @@ fn unstably_const_fn() { helper::unstably_const_fn() } +#[clippy::msrv = "1.46.0"] mod const_fn_stabilized_after_msrv { - #![clippy::msrv = "1.46.0"] - // Do not lint this because `u8::is_ascii_digit` is stabilized as a const function in 1.47.0. fn const_fn_stabilized_after_msrv(byte: u8) { byte.is_ascii_digit(); diff --git a/tests/ui/missing_const_for_fn/could_be_const.rs b/tests/ui/missing_const_for_fn/could_be_const.rs index b85e8878491..0246c8622ed 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.rs +++ b/tests/ui/missing_const_for_fn/could_be_const.rs @@ -1,6 +1,5 @@ #![warn(clippy::missing_const_for_fn)] #![allow(incomplete_features, clippy::let_and_return)] -#![feature(custom_inner_attributes)] use std::mem::transmute; @@ -68,24 +67,21 @@ mod with_drop { } } +#[clippy::msrv = "1.47.0"] mod const_fn_stabilized_before_msrv { - #![clippy::msrv = "1.47.0"] - // This could be const because `u8::is_ascii_digit` is a stable const function in 1.47. fn const_fn_stabilized_before_msrv(byte: u8) { byte.is_ascii_digit(); } } +#[clippy::msrv = "1.45"] fn msrv_1_45() -> i32 { - #![clippy::msrv = "1.45"] - 45 } +#[clippy::msrv = "1.46"] fn msrv_1_46() -> i32 { - #![clippy::msrv = "1.46"] - 46 } diff --git a/tests/ui/missing_const_for_fn/could_be_const.stderr b/tests/ui/missing_const_for_fn/could_be_const.stderr index f8e221c82f1..955e1ed2634 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.stderr +++ b/tests/ui/missing_const_for_fn/could_be_const.stderr @@ -1,5 +1,5 @@ error: this could be a `const fn` - --> $DIR/could_be_const.rs:13:5 + --> $DIR/could_be_const.rs:12:5 | LL | / pub fn new() -> Self { LL | | Self { guess: 42 } @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::missing-const-for-fn` implied by `-D warnings` error: this could be a `const fn` - --> $DIR/could_be_const.rs:17:5 + --> $DIR/could_be_const.rs:16:5 | LL | / fn const_generic_params<'a, T, const N: usize>(&self, b: &'a [T; N]) -> &'a [T; N] { LL | | b @@ -17,7 +17,7 @@ LL | | } | |_____^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:23:1 + --> $DIR/could_be_const.rs:22:1 | LL | / fn one() -> i32 { LL | | 1 @@ -25,7 +25,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:28:1 + --> $DIR/could_be_const.rs:27:1 | LL | / fn two() -> i32 { LL | | let abc = 2; @@ -34,7 +34,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:34:1 + --> $DIR/could_be_const.rs:33:1 | LL | / fn string() -> String { LL | | String::new() @@ -42,7 +42,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:39:1 + --> $DIR/could_be_const.rs:38:1 | LL | / unsafe fn four() -> i32 { LL | | 4 @@ -50,7 +50,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:44:1 + --> $DIR/could_be_const.rs:43:1 | LL | / fn generic(t: T) -> T { LL | | t @@ -58,7 +58,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:52:1 + --> $DIR/could_be_const.rs:51:1 | LL | / fn generic_arr(t: [T; 1]) -> T { LL | | t[0] @@ -66,7 +66,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:65:9 + --> $DIR/could_be_const.rs:64:9 | LL | / pub fn b(self, a: &A) -> B { LL | | B @@ -74,7 +74,7 @@ LL | | } | |_________^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:75:5 + --> $DIR/could_be_const.rs:73:5 | LL | / fn const_fn_stabilized_before_msrv(byte: u8) { LL | | byte.is_ascii_digit(); @@ -82,11 +82,9 @@ LL | | } | |_____^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:86:1 + --> $DIR/could_be_const.rs:84:1 | LL | / fn msrv_1_46() -> i32 { -LL | | #![clippy::msrv = "1.46"] -LL | | LL | | 46 LL | | } | |_^ diff --git a/tests/ui/needless_borrow.fixed b/tests/ui/needless_borrow.fixed index 85b6b639d55..4cb7f6b687f 100644 --- a/tests/ui/needless_borrow.fixed +++ b/tests/ui/needless_borrow.fixed @@ -1,13 +1,13 @@ // run-rustfix -#![feature(custom_inner_attributes, lint_reasons)] - -#[warn(clippy::all, clippy::needless_borrow)] -#[allow(unused_variables)] -#[allow( +#![feature(lint_reasons)] +#![allow( + unused, clippy::uninlined_format_args, clippy::unnecessary_mut_passed, clippy::unnecessary_to_owned )] +#![warn(clippy::needless_borrow)] + fn main() { let a = 5; let ref_a = &a; @@ -171,14 +171,12 @@ impl<'a> Trait for &'a str {} fn h(_: &dyn Trait) {} -#[allow(dead_code)] fn check_expect_suppression() { let a = 5; #[expect(clippy::needless_borrow)] let _ = x(&&a); } -#[allow(dead_code)] mod issue9160 { pub struct S { f: F, @@ -267,7 +265,6 @@ where } // https://github.com/rust-lang/rust-clippy/pull/9136#pullrequestreview-1037379321 -#[allow(dead_code)] mod copyable_iterator { #[derive(Clone, Copy)] struct Iter; @@ -287,25 +284,20 @@ mod copyable_iterator { } } +#[clippy::msrv = "1.52.0"] mod under_msrv { - #![allow(dead_code)] - #![clippy::msrv = "1.52.0"] - fn foo() { let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap(); } } +#[clippy::msrv = "1.53.0"] mod meets_msrv { - #![allow(dead_code)] - #![clippy::msrv = "1.53.0"] - fn foo() { let _ = std::process::Command::new("ls").args(["-a", "-l"]).status().unwrap(); } } -#[allow(unused)] fn issue9383() { // Should not lint because unions need explicit deref when accessing field use std::mem::ManuallyDrop; @@ -334,7 +326,6 @@ fn issue9383() { } } -#[allow(dead_code)] fn closure_test() { let env = "env".to_owned(); let arg = "arg".to_owned(); @@ -348,7 +339,6 @@ fn closure_test() { f(arg); } -#[allow(dead_code)] mod significant_drop { #[derive(Debug)] struct X; @@ -368,7 +358,6 @@ mod significant_drop { fn debug(_: impl std::fmt::Debug) {} } -#[allow(dead_code)] mod used_exactly_once { fn foo(x: String) { use_x(x); @@ -376,7 +365,6 @@ mod used_exactly_once { fn use_x(_: impl AsRef) {} } -#[allow(dead_code)] mod used_more_than_once { fn foo(x: String) { use_x(&x); @@ -387,7 +375,6 @@ mod used_more_than_once { } // https://github.com/rust-lang/rust-clippy/issues/9111#issuecomment-1277114280 -#[allow(dead_code)] mod issue_9111 { struct A; @@ -409,7 +396,6 @@ mod issue_9111 { } } -#[allow(dead_code)] mod issue_9710 { fn main() { let string = String::new(); @@ -421,7 +407,6 @@ mod issue_9710 { fn f>(_: T) {} } -#[allow(dead_code)] mod issue_9739 { fn foo(_it: impl IntoIterator) {} @@ -434,7 +419,6 @@ mod issue_9739 { } } -#[allow(dead_code)] mod issue_9739_method_variant { struct S; @@ -451,7 +435,6 @@ mod issue_9739_method_variant { } } -#[allow(dead_code)] mod issue_9782 { fn foo>(t: T) { println!("{}", std::mem::size_of::()); @@ -475,7 +458,6 @@ mod issue_9782 { } } -#[allow(dead_code)] mod issue_9782_type_relative_variant { struct S; @@ -493,7 +475,6 @@ mod issue_9782_type_relative_variant { } } -#[allow(dead_code)] mod issue_9782_method_variant { struct S; diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs index 7b97bcf3817..9a01190ed8d 100644 --- a/tests/ui/needless_borrow.rs +++ b/tests/ui/needless_borrow.rs @@ -1,13 +1,13 @@ // run-rustfix -#![feature(custom_inner_attributes, lint_reasons)] - -#[warn(clippy::all, clippy::needless_borrow)] -#[allow(unused_variables)] -#[allow( +#![feature(lint_reasons)] +#![allow( + unused, clippy::uninlined_format_args, clippy::unnecessary_mut_passed, clippy::unnecessary_to_owned )] +#![warn(clippy::needless_borrow)] + fn main() { let a = 5; let ref_a = &a; @@ -171,14 +171,12 @@ impl<'a> Trait for &'a str {} fn h(_: &dyn Trait) {} -#[allow(dead_code)] fn check_expect_suppression() { let a = 5; #[expect(clippy::needless_borrow)] let _ = x(&&a); } -#[allow(dead_code)] mod issue9160 { pub struct S { f: F, @@ -267,7 +265,6 @@ where } // https://github.com/rust-lang/rust-clippy/pull/9136#pullrequestreview-1037379321 -#[allow(dead_code)] mod copyable_iterator { #[derive(Clone, Copy)] struct Iter; @@ -287,25 +284,20 @@ mod copyable_iterator { } } +#[clippy::msrv = "1.52.0"] mod under_msrv { - #![allow(dead_code)] - #![clippy::msrv = "1.52.0"] - fn foo() { let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap(); } } +#[clippy::msrv = "1.53.0"] mod meets_msrv { - #![allow(dead_code)] - #![clippy::msrv = "1.53.0"] - fn foo() { let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap(); } } -#[allow(unused)] fn issue9383() { // Should not lint because unions need explicit deref when accessing field use std::mem::ManuallyDrop; @@ -334,7 +326,6 @@ fn issue9383() { } } -#[allow(dead_code)] fn closure_test() { let env = "env".to_owned(); let arg = "arg".to_owned(); @@ -348,7 +339,6 @@ fn closure_test() { f(arg); } -#[allow(dead_code)] mod significant_drop { #[derive(Debug)] struct X; @@ -368,7 +358,6 @@ mod significant_drop { fn debug(_: impl std::fmt::Debug) {} } -#[allow(dead_code)] mod used_exactly_once { fn foo(x: String) { use_x(&x); @@ -376,7 +365,6 @@ mod used_exactly_once { fn use_x(_: impl AsRef) {} } -#[allow(dead_code)] mod used_more_than_once { fn foo(x: String) { use_x(&x); @@ -387,7 +375,6 @@ mod used_more_than_once { } // https://github.com/rust-lang/rust-clippy/issues/9111#issuecomment-1277114280 -#[allow(dead_code)] mod issue_9111 { struct A; @@ -409,7 +396,6 @@ mod issue_9111 { } } -#[allow(dead_code)] mod issue_9710 { fn main() { let string = String::new(); @@ -421,7 +407,6 @@ mod issue_9710 { fn f>(_: T) {} } -#[allow(dead_code)] mod issue_9739 { fn foo(_it: impl IntoIterator) {} @@ -434,7 +419,6 @@ mod issue_9739 { } } -#[allow(dead_code)] mod issue_9739_method_variant { struct S; @@ -451,7 +435,6 @@ mod issue_9739_method_variant { } } -#[allow(dead_code)] mod issue_9782 { fn foo>(t: T) { println!("{}", std::mem::size_of::()); @@ -475,7 +458,6 @@ mod issue_9782 { } } -#[allow(dead_code)] mod issue_9782_type_relative_variant { struct S; @@ -493,7 +475,6 @@ mod issue_9782_type_relative_variant { } } -#[allow(dead_code)] mod issue_9782_method_variant { struct S; diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr index 485e6b84c86..d26c317124b 100644 --- a/tests/ui/needless_borrow.stderr +++ b/tests/ui/needless_borrow.stderr @@ -163,55 +163,55 @@ LL | let _ = std::fs::write("x", &"".to_string()); | ^^^^^^^^^^^^^^^ help: change this to: `"".to_string()` error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:192:13 + --> $DIR/needless_borrow.rs:190:13 | LL | (&self.f)() | ^^^^^^^^^ help: change this to: `(self.f)` error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:201:13 + --> $DIR/needless_borrow.rs:199:13 | LL | (&mut self.f)() | ^^^^^^^^^^^^^ help: change this to: `(self.f)` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:286:20 + --> $DIR/needless_borrow.rs:283:20 | LL | takes_iter(&mut x) | ^^^^^^ help: change this to: `x` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:304:55 + --> $DIR/needless_borrow.rs:297:55 | LL | let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap(); | ^^^^^^^^^^^^^ help: change this to: `["-a", "-l"]` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:344:37 + --> $DIR/needless_borrow.rs:335:37 | LL | let _ = std::fs::write("x", &arg); | ^^^^ help: change this to: `arg` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:345:37 + --> $DIR/needless_borrow.rs:336:37 | LL | let _ = std::fs::write("x", &loc); | ^^^^ help: change this to: `loc` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:364:15 + --> $DIR/needless_borrow.rs:354:15 | LL | debug(&x); | ^^ help: change this to: `x` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:374:15 + --> $DIR/needless_borrow.rs:363:15 | LL | use_x(&x); | ^^ help: change this to: `x` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:474:13 + --> $DIR/needless_borrow.rs:457:13 | LL | foo(&a); | ^^ help: change this to: `a` diff --git a/tests/ui/needless_question_mark.fixed b/tests/ui/needless_question_mark.fixed index ba9d15e59d0..7eaca571992 100644 --- a/tests/ui/needless_question_mark.fixed +++ b/tests/ui/needless_question_mark.fixed @@ -8,7 +8,6 @@ dead_code, unused_must_use )] -#![feature(custom_inner_attributes)] struct TO { magic: Option, diff --git a/tests/ui/needless_question_mark.rs b/tests/ui/needless_question_mark.rs index 3a6523e8fe8..960bc7b7898 100644 --- a/tests/ui/needless_question_mark.rs +++ b/tests/ui/needless_question_mark.rs @@ -8,7 +8,6 @@ dead_code, unused_must_use )] -#![feature(custom_inner_attributes)] struct TO { magic: Option, diff --git a/tests/ui/needless_question_mark.stderr b/tests/ui/needless_question_mark.stderr index f8308e24e77..d1f89e326c6 100644 --- a/tests/ui/needless_question_mark.stderr +++ b/tests/ui/needless_question_mark.stderr @@ -1,5 +1,5 @@ error: question mark operator is useless here - --> $DIR/needless_question_mark.rs:23:12 + --> $DIR/needless_question_mark.rs:22:12 | LL | return Some(to.magic?); | ^^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `to.magic` @@ -7,67 +7,67 @@ LL | return Some(to.magic?); = note: `-D clippy::needless-question-mark` implied by `-D warnings` error: question mark operator is useless here - --> $DIR/needless_question_mark.rs:31:12 + --> $DIR/needless_question_mark.rs:30:12 | LL | return Some(to.magic?) | ^^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `to.magic` error: question mark operator is useless here - --> $DIR/needless_question_mark.rs:36:5 + --> $DIR/needless_question_mark.rs:35:5 | LL | Some(to.magic?) | ^^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `to.magic` error: question mark operator is useless here - --> $DIR/needless_question_mark.rs:41:21 + --> $DIR/needless_question_mark.rs:40:21 | LL | to.and_then(|t| Some(t.magic?)) | ^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `t.magic` error: question mark operator is useless here - --> $DIR/needless_question_mark.rs:50:9 + --> $DIR/needless_question_mark.rs:49:9 | LL | Some(t.magic?) | ^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `t.magic` error: question mark operator is useless here - --> $DIR/needless_question_mark.rs:55:12 + --> $DIR/needless_question_mark.rs:54:12 | LL | return Ok(tr.magic?); | ^^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `tr.magic` error: question mark operator is useless here - --> $DIR/needless_question_mark.rs:62:12 + --> $DIR/needless_question_mark.rs:61:12 | LL | return Ok(tr.magic?) | ^^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `tr.magic` error: question mark operator is useless here - --> $DIR/needless_question_mark.rs:66:5 + --> $DIR/needless_question_mark.rs:65:5 | LL | Ok(tr.magic?) | ^^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `tr.magic` error: question mark operator is useless here - --> $DIR/needless_question_mark.rs:70:21 + --> $DIR/needless_question_mark.rs:69:21 | LL | tr.and_then(|t| Ok(t.magic?)) | ^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `t.magic` error: question mark operator is useless here - --> $DIR/needless_question_mark.rs:78:9 + --> $DIR/needless_question_mark.rs:77:9 | LL | Ok(t.magic?) | ^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `t.magic` error: question mark operator is useless here - --> $DIR/needless_question_mark.rs:85:16 + --> $DIR/needless_question_mark.rs:84:16 | LL | return Ok(t.magic?); | ^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `t.magic` error: question mark operator is useless here - --> $DIR/needless_question_mark.rs:120:27 + --> $DIR/needless_question_mark.rs:119:27 | LL | || -> Option<_> { Some(Some($expr)?) }() | ^^^^^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `Some($expr)` @@ -78,13 +78,13 @@ LL | let _x = some_and_qmark_in_macro!(x?); = note: this error originates in the macro `some_and_qmark_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: question mark operator is useless here - --> $DIR/needless_question_mark.rs:131:5 + --> $DIR/needless_question_mark.rs:130:5 | LL | Some(to.magic?) | ^^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `to.magic` error: question mark operator is useless here - --> $DIR/needless_question_mark.rs:139:5 + --> $DIR/needless_question_mark.rs:138:5 | LL | Ok(s.magic?) | ^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `s.magic` diff --git a/tests/ui/needless_splitn.fixed b/tests/ui/needless_splitn.fixed index 61f5fc4e679..5496031fefa 100644 --- a/tests/ui/needless_splitn.fixed +++ b/tests/ui/needless_splitn.fixed @@ -1,7 +1,6 @@ // run-rustfix // edition:2018 -#![feature(custom_inner_attributes)] #![warn(clippy::needless_splitn)] #![allow(clippy::iter_skip_next, clippy::iter_nth_zero, clippy::manual_split_once)] @@ -40,8 +39,8 @@ fn _question_mark(s: &str) -> Option<()> { Some(()) } +#[clippy::msrv = "1.51"] fn _test_msrv() { - #![clippy::msrv = "1.51"] // `manual_split_once` MSRV shouldn't apply to `needless_splitn` let _ = "key=value".split('=').nth(0).unwrap(); } diff --git a/tests/ui/needless_splitn.rs b/tests/ui/needless_splitn.rs index 71d9a7077fa..35c2465bae1 100644 --- a/tests/ui/needless_splitn.rs +++ b/tests/ui/needless_splitn.rs @@ -1,7 +1,6 @@ // run-rustfix // edition:2018 -#![feature(custom_inner_attributes)] #![warn(clippy::needless_splitn)] #![allow(clippy::iter_skip_next, clippy::iter_nth_zero, clippy::manual_split_once)] @@ -40,8 +39,8 @@ fn _question_mark(s: &str) -> Option<()> { Some(()) } +#[clippy::msrv = "1.51"] fn _test_msrv() { - #![clippy::msrv = "1.51"] // `manual_split_once` MSRV shouldn't apply to `needless_splitn` let _ = "key=value".splitn(2, '=').nth(0).unwrap(); } diff --git a/tests/ui/needless_splitn.stderr b/tests/ui/needless_splitn.stderr index f112b29e7f2..f607d8e1ab5 100644 --- a/tests/ui/needless_splitn.stderr +++ b/tests/ui/needless_splitn.stderr @@ -1,5 +1,5 @@ error: unnecessary use of `splitn` - --> $DIR/needless_splitn.rs:15:13 + --> $DIR/needless_splitn.rs:14:13 | LL | let _ = str.splitn(2, '=').next(); | ^^^^^^^^^^^^^^^^^^ help: try this: `str.split('=')` @@ -7,73 +7,73 @@ LL | let _ = str.splitn(2, '=').next(); = note: `-D clippy::needless-splitn` implied by `-D warnings` error: unnecessary use of `splitn` - --> $DIR/needless_splitn.rs:16:13 + --> $DIR/needless_splitn.rs:15:13 | LL | let _ = str.splitn(2, '=').nth(0); | ^^^^^^^^^^^^^^^^^^ help: try this: `str.split('=')` error: unnecessary use of `splitn` - --> $DIR/needless_splitn.rs:19:18 + --> $DIR/needless_splitn.rs:18:18 | LL | let (_, _) = str.splitn(3, '=').next_tuple().unwrap(); | ^^^^^^^^^^^^^^^^^^ help: try this: `str.split('=')` error: unnecessary use of `rsplitn` - --> $DIR/needless_splitn.rs:22:13 + --> $DIR/needless_splitn.rs:21:13 | LL | let _ = str.rsplitn(2, '=').next(); | ^^^^^^^^^^^^^^^^^^^ help: try this: `str.rsplit('=')` error: unnecessary use of `rsplitn` - --> $DIR/needless_splitn.rs:23:13 + --> $DIR/needless_splitn.rs:22:13 | LL | let _ = str.rsplitn(2, '=').nth(0); | ^^^^^^^^^^^^^^^^^^^ help: try this: `str.rsplit('=')` error: unnecessary use of `rsplitn` - --> $DIR/needless_splitn.rs:26:18 + --> $DIR/needless_splitn.rs:25:18 | LL | let (_, _) = str.rsplitn(3, '=').next_tuple().unwrap(); | ^^^^^^^^^^^^^^^^^^^ help: try this: `str.rsplit('=')` error: unnecessary use of `splitn` - --> $DIR/needless_splitn.rs:28:13 + --> $DIR/needless_splitn.rs:27:13 | LL | let _ = str.splitn(5, '=').next(); | ^^^^^^^^^^^^^^^^^^ help: try this: `str.split('=')` error: unnecessary use of `splitn` - --> $DIR/needless_splitn.rs:29:13 + --> $DIR/needless_splitn.rs:28:13 | LL | let _ = str.splitn(5, '=').nth(3); | ^^^^^^^^^^^^^^^^^^ help: try this: `str.split('=')` error: unnecessary use of `splitn` - --> $DIR/needless_splitn.rs:35:13 + --> $DIR/needless_splitn.rs:34:13 | LL | let _ = s.splitn(2, '=').next()?; | ^^^^^^^^^^^^^^^^ help: try this: `s.split('=')` error: unnecessary use of `splitn` - --> $DIR/needless_splitn.rs:36:13 + --> $DIR/needless_splitn.rs:35:13 | LL | let _ = s.splitn(2, '=').nth(0)?; | ^^^^^^^^^^^^^^^^ help: try this: `s.split('=')` error: unnecessary use of `rsplitn` - --> $DIR/needless_splitn.rs:37:13 + --> $DIR/needless_splitn.rs:36:13 | LL | let _ = s.rsplitn(2, '=').next()?; | ^^^^^^^^^^^^^^^^^ help: try this: `s.rsplit('=')` error: unnecessary use of `rsplitn` - --> $DIR/needless_splitn.rs:38:13 + --> $DIR/needless_splitn.rs:37:13 | LL | let _ = s.rsplitn(2, '=').nth(0)?; | ^^^^^^^^^^^^^^^^^ help: try this: `s.rsplit('=')` error: unnecessary use of `splitn` - --> $DIR/needless_splitn.rs:46:13 + --> $DIR/needless_splitn.rs:45:13 | LL | let _ = "key=value".splitn(2, '=').nth(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split('=')` diff --git a/tests/ui/option_as_ref_deref.fixed b/tests/ui/option_as_ref_deref.fixed index bc376d0d7fb..d124d133faa 100644 --- a/tests/ui/option_as_ref_deref.fixed +++ b/tests/ui/option_as_ref_deref.fixed @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![allow(unused, clippy::redundant_clone)] #![warn(clippy::option_as_ref_deref)] @@ -44,16 +43,14 @@ fn main() { let _ = opt.as_deref(); } +#[clippy::msrv = "1.39"] fn msrv_1_39() { - #![clippy::msrv = "1.39"] - let opt = Some(String::from("123")); let _ = opt.as_ref().map(String::as_str); } +#[clippy::msrv = "1.40"] fn msrv_1_40() { - #![clippy::msrv = "1.40"] - let opt = Some(String::from("123")); let _ = opt.as_deref(); } diff --git a/tests/ui/option_as_ref_deref.rs b/tests/ui/option_as_ref_deref.rs index ba3a2eedc22..86e354c6716 100644 --- a/tests/ui/option_as_ref_deref.rs +++ b/tests/ui/option_as_ref_deref.rs @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![allow(unused, clippy::redundant_clone)] #![warn(clippy::option_as_ref_deref)] @@ -47,16 +46,14 @@ fn main() { let _ = opt.as_ref().map(std::ops::Deref::deref); } +#[clippy::msrv = "1.39"] fn msrv_1_39() { - #![clippy::msrv = "1.39"] - let opt = Some(String::from("123")); let _ = opt.as_ref().map(String::as_str); } +#[clippy::msrv = "1.40"] fn msrv_1_40() { - #![clippy::msrv = "1.40"] - let opt = Some(String::from("123")); let _ = opt.as_ref().map(String::as_str); } diff --git a/tests/ui/option_as_ref_deref.stderr b/tests/ui/option_as_ref_deref.stderr index 7de8b3b6ba4..e471b56eea8 100644 --- a/tests/ui/option_as_ref_deref.stderr +++ b/tests/ui/option_as_ref_deref.stderr @@ -1,5 +1,5 @@ error: called `.as_ref().map(Deref::deref)` on an Option value. This can be done more directly by calling `opt.clone().as_deref()` instead - --> $DIR/option_as_ref_deref.rs:14:13 + --> $DIR/option_as_ref_deref.rs:13:13 | LL | let _ = opt.clone().as_ref().map(Deref::deref).map(str::len); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.clone().as_deref()` @@ -7,7 +7,7 @@ LL | let _ = opt.clone().as_ref().map(Deref::deref).map(str::len); = note: `-D clippy::option-as-ref-deref` implied by `-D warnings` error: called `.as_ref().map(Deref::deref)` on an Option value. This can be done more directly by calling `opt.clone().as_deref()` instead - --> $DIR/option_as_ref_deref.rs:17:13 + --> $DIR/option_as_ref_deref.rs:16:13 | LL | let _ = opt.clone() | _____________^ @@ -17,97 +17,97 @@ LL | | ) | |_________^ help: try using as_deref instead: `opt.clone().as_deref()` error: called `.as_mut().map(DerefMut::deref_mut)` on an Option value. This can be done more directly by calling `opt.as_deref_mut()` instead - --> $DIR/option_as_ref_deref.rs:23:13 + --> $DIR/option_as_ref_deref.rs:22:13 | LL | let _ = opt.as_mut().map(DerefMut::deref_mut); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()` error: called `.as_ref().map(String::as_str)` on an Option value. This can be done more directly by calling `opt.as_deref()` instead - --> $DIR/option_as_ref_deref.rs:25:13 + --> $DIR/option_as_ref_deref.rs:24:13 | LL | let _ = opt.as_ref().map(String::as_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` error: called `.as_ref().map(|x| x.as_str())` on an Option value. This can be done more directly by calling `opt.as_deref()` instead - --> $DIR/option_as_ref_deref.rs:26:13 + --> $DIR/option_as_ref_deref.rs:25:13 | LL | let _ = opt.as_ref().map(|x| x.as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` error: called `.as_mut().map(String::as_mut_str)` on an Option value. This can be done more directly by calling `opt.as_deref_mut()` instead - --> $DIR/option_as_ref_deref.rs:27:13 + --> $DIR/option_as_ref_deref.rs:26:13 | LL | let _ = opt.as_mut().map(String::as_mut_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()` error: called `.as_mut().map(|x| x.as_mut_str())` on an Option value. This can be done more directly by calling `opt.as_deref_mut()` instead - --> $DIR/option_as_ref_deref.rs:28:13 + --> $DIR/option_as_ref_deref.rs:27:13 | LL | let _ = opt.as_mut().map(|x| x.as_mut_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()` error: called `.as_ref().map(CString::as_c_str)` on an Option value. This can be done more directly by calling `Some(CString::new(vec![]).unwrap()).as_deref()` instead - --> $DIR/option_as_ref_deref.rs:29:13 + --> $DIR/option_as_ref_deref.rs:28:13 | LL | let _ = Some(CString::new(vec![]).unwrap()).as_ref().map(CString::as_c_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(CString::new(vec![]).unwrap()).as_deref()` error: called `.as_ref().map(OsString::as_os_str)` on an Option value. This can be done more directly by calling `Some(OsString::new()).as_deref()` instead - --> $DIR/option_as_ref_deref.rs:30:13 + --> $DIR/option_as_ref_deref.rs:29:13 | LL | let _ = Some(OsString::new()).as_ref().map(OsString::as_os_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(OsString::new()).as_deref()` error: called `.as_ref().map(PathBuf::as_path)` on an Option value. This can be done more directly by calling `Some(PathBuf::new()).as_deref()` instead - --> $DIR/option_as_ref_deref.rs:31:13 + --> $DIR/option_as_ref_deref.rs:30:13 | LL | let _ = Some(PathBuf::new()).as_ref().map(PathBuf::as_path); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(PathBuf::new()).as_deref()` error: called `.as_ref().map(Vec::as_slice)` on an Option value. This can be done more directly by calling `Some(Vec::<()>::new()).as_deref()` instead - --> $DIR/option_as_ref_deref.rs:32:13 + --> $DIR/option_as_ref_deref.rs:31:13 | LL | let _ = Some(Vec::<()>::new()).as_ref().map(Vec::as_slice); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(Vec::<()>::new()).as_deref()` error: called `.as_mut().map(Vec::as_mut_slice)` on an Option value. This can be done more directly by calling `Some(Vec::<()>::new()).as_deref_mut()` instead - --> $DIR/option_as_ref_deref.rs:33:13 + --> $DIR/option_as_ref_deref.rs:32:13 | LL | let _ = Some(Vec::<()>::new()).as_mut().map(Vec::as_mut_slice); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `Some(Vec::<()>::new()).as_deref_mut()` error: called `.as_ref().map(|x| x.deref())` on an Option value. This can be done more directly by calling `opt.as_deref()` instead - --> $DIR/option_as_ref_deref.rs:35:13 + --> $DIR/option_as_ref_deref.rs:34:13 | LL | let _ = opt.as_ref().map(|x| x.deref()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` error: called `.as_mut().map(|x| x.deref_mut())` on an Option value. This can be done more directly by calling `opt.clone().as_deref_mut()` instead - --> $DIR/option_as_ref_deref.rs:36:13 + --> $DIR/option_as_ref_deref.rs:35:13 | LL | let _ = opt.clone().as_mut().map(|x| x.deref_mut()).map(|x| x.len()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.clone().as_deref_mut()` error: called `.as_ref().map(|x| &**x)` on an Option value. This can be done more directly by calling `opt.as_deref()` instead - --> $DIR/option_as_ref_deref.rs:43:13 + --> $DIR/option_as_ref_deref.rs:42:13 | LL | let _ = opt.as_ref().map(|x| &**x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` error: called `.as_mut().map(|x| &mut **x)` on an Option value. This can be done more directly by calling `opt.as_deref_mut()` instead - --> $DIR/option_as_ref_deref.rs:44:13 + --> $DIR/option_as_ref_deref.rs:43:13 | LL | let _ = opt.as_mut().map(|x| &mut **x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()` error: called `.as_ref().map(std::ops::Deref::deref)` on an Option value. This can be done more directly by calling `opt.as_deref()` instead - --> $DIR/option_as_ref_deref.rs:47:13 + --> $DIR/option_as_ref_deref.rs:46:13 | LL | let _ = opt.as_ref().map(std::ops::Deref::deref); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` error: called `.as_ref().map(String::as_str)` on an Option value. This can be done more directly by calling `opt.as_deref()` instead - --> $DIR/option_as_ref_deref.rs:61:13 + --> $DIR/option_as_ref_deref.rs:58:13 | LL | let _ = opt.as_ref().map(String::as_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` diff --git a/tests/ui/ptr_as_ptr.fixed b/tests/ui/ptr_as_ptr.fixed index bea6be66a8e..df36a9b842b 100644 --- a/tests/ui/ptr_as_ptr.fixed +++ b/tests/ui/ptr_as_ptr.fixed @@ -2,7 +2,6 @@ // aux-build:macro_rules.rs #![warn(clippy::ptr_as_ptr)] -#![feature(custom_inner_attributes)] extern crate macro_rules; @@ -45,8 +44,8 @@ fn main() { let _ = macro_rules::ptr_as_ptr_cast!(ptr); } +#[clippy::msrv = "1.37"] fn _msrv_1_37() { - #![clippy::msrv = "1.37"] let ptr: *const u32 = &42_u32; let mut_ptr: *mut u32 = &mut 42_u32; @@ -55,8 +54,8 @@ fn _msrv_1_37() { let _ = mut_ptr as *mut i32; } +#[clippy::msrv = "1.38"] fn _msrv_1_38() { - #![clippy::msrv = "1.38"] let ptr: *const u32 = &42_u32; let mut_ptr: *mut u32 = &mut 42_u32; diff --git a/tests/ui/ptr_as_ptr.rs b/tests/ui/ptr_as_ptr.rs index ca2616b0069..302c66462d9 100644 --- a/tests/ui/ptr_as_ptr.rs +++ b/tests/ui/ptr_as_ptr.rs @@ -2,7 +2,6 @@ // aux-build:macro_rules.rs #![warn(clippy::ptr_as_ptr)] -#![feature(custom_inner_attributes)] extern crate macro_rules; @@ -45,8 +44,8 @@ fn main() { let _ = macro_rules::ptr_as_ptr_cast!(ptr); } +#[clippy::msrv = "1.37"] fn _msrv_1_37() { - #![clippy::msrv = "1.37"] let ptr: *const u32 = &42_u32; let mut_ptr: *mut u32 = &mut 42_u32; @@ -55,8 +54,8 @@ fn _msrv_1_37() { let _ = mut_ptr as *mut i32; } +#[clippy::msrv = "1.38"] fn _msrv_1_38() { - #![clippy::msrv = "1.38"] let ptr: *const u32 = &42_u32; let mut_ptr: *mut u32 = &mut 42_u32; diff --git a/tests/ui/ptr_as_ptr.stderr b/tests/ui/ptr_as_ptr.stderr index c58c55cfd83..a68e1cab6d3 100644 --- a/tests/ui/ptr_as_ptr.stderr +++ b/tests/ui/ptr_as_ptr.stderr @@ -1,5 +1,5 @@ error: `as` casting between raw pointers without changing its mutability - --> $DIR/ptr_as_ptr.rs:19:13 + --> $DIR/ptr_as_ptr.rs:18:13 | LL | let _ = ptr as *const i32; | ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::()` @@ -7,31 +7,31 @@ LL | let _ = ptr as *const i32; = note: `-D clippy::ptr-as-ptr` implied by `-D warnings` error: `as` casting between raw pointers without changing its mutability - --> $DIR/ptr_as_ptr.rs:20:13 + --> $DIR/ptr_as_ptr.rs:19:13 | LL | let _ = mut_ptr as *mut i32; | ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::()` error: `as` casting between raw pointers without changing its mutability - --> $DIR/ptr_as_ptr.rs:25:17 + --> $DIR/ptr_as_ptr.rs:24:17 | LL | let _ = *ptr_ptr as *const i32; | ^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `(*ptr_ptr).cast::()` error: `as` casting between raw pointers without changing its mutability - --> $DIR/ptr_as_ptr.rs:38:25 + --> $DIR/ptr_as_ptr.rs:37:25 | LL | let _: *const i32 = ptr as *const _; | ^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast()` error: `as` casting between raw pointers without changing its mutability - --> $DIR/ptr_as_ptr.rs:39:23 + --> $DIR/ptr_as_ptr.rs:38:23 | LL | let _: *mut i32 = mut_ptr as _; | ^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast()` error: `as` casting between raw pointers without changing its mutability - --> $DIR/ptr_as_ptr.rs:11:9 + --> $DIR/ptr_as_ptr.rs:10:9 | LL | $ptr as *const i32 | ^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `$ptr.cast::()` @@ -42,13 +42,13 @@ LL | let _ = cast_it!(ptr); = note: this error originates in the macro `cast_it` (in Nightly builds, run with -Z macro-backtrace for more info) error: `as` casting between raw pointers without changing its mutability - --> $DIR/ptr_as_ptr.rs:63:13 + --> $DIR/ptr_as_ptr.rs:62:13 | LL | let _ = ptr as *const i32; | ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::()` error: `as` casting between raw pointers without changing its mutability - --> $DIR/ptr_as_ptr.rs:64:13 + --> $DIR/ptr_as_ptr.rs:63:13 | LL | let _ = mut_ptr as *mut i32; | ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::()` diff --git a/tests/ui/range_contains.fixed b/tests/ui/range_contains.fixed index 824f00cb99e..4923731fe45 100644 --- a/tests/ui/range_contains.fixed +++ b/tests/ui/range_contains.fixed @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![warn(clippy::manual_range_contains)] #![allow(unused)] #![allow(clippy::no_effect)] @@ -65,16 +64,14 @@ pub const fn in_range(a: i32) -> bool { 3 <= a && a <= 20 } +#[clippy::msrv = "1.34"] fn msrv_1_34() { - #![clippy::msrv = "1.34"] - let x = 5; x >= 8 && x < 34; } +#[clippy::msrv = "1.35"] fn msrv_1_35() { - #![clippy::msrv = "1.35"] - let x = 5; (8..35).contains(&x); } diff --git a/tests/ui/range_contains.rs b/tests/ui/range_contains.rs index df925eeadfe..d623ccb5da6 100644 --- a/tests/ui/range_contains.rs +++ b/tests/ui/range_contains.rs @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![warn(clippy::manual_range_contains)] #![allow(unused)] #![allow(clippy::no_effect)] @@ -65,16 +64,14 @@ pub const fn in_range(a: i32) -> bool { 3 <= a && a <= 20 } +#[clippy::msrv = "1.34"] fn msrv_1_34() { - #![clippy::msrv = "1.34"] - let x = 5; x >= 8 && x < 34; } +#[clippy::msrv = "1.35"] fn msrv_1_35() { - #![clippy::msrv = "1.35"] - let x = 5; x >= 8 && x < 35; } diff --git a/tests/ui/range_contains.stderr b/tests/ui/range_contains.stderr index 9689e665b05..ea34023a466 100644 --- a/tests/ui/range_contains.stderr +++ b/tests/ui/range_contains.stderr @@ -1,5 +1,5 @@ error: manual `Range::contains` implementation - --> $DIR/range_contains.rs:14:5 + --> $DIR/range_contains.rs:13:5 | LL | x >= 8 && x < 12; | ^^^^^^^^^^^^^^^^ help: use: `(8..12).contains(&x)` @@ -7,121 +7,121 @@ LL | x >= 8 && x < 12; = note: `-D clippy::manual-range-contains` implied by `-D warnings` error: manual `Range::contains` implementation - --> $DIR/range_contains.rs:15:5 + --> $DIR/range_contains.rs:14:5 | LL | x < 42 && x >= 21; | ^^^^^^^^^^^^^^^^^ help: use: `(21..42).contains(&x)` error: manual `Range::contains` implementation - --> $DIR/range_contains.rs:16:5 + --> $DIR/range_contains.rs:15:5 | LL | 100 > x && 1 <= x; | ^^^^^^^^^^^^^^^^^ help: use: `(1..100).contains(&x)` error: manual `RangeInclusive::contains` implementation - --> $DIR/range_contains.rs:19:5 + --> $DIR/range_contains.rs:18:5 | LL | x >= 9 && x <= 99; | ^^^^^^^^^^^^^^^^^ help: use: `(9..=99).contains(&x)` error: manual `RangeInclusive::contains` implementation - --> $DIR/range_contains.rs:20:5 + --> $DIR/range_contains.rs:19:5 | LL | x <= 33 && x >= 1; | ^^^^^^^^^^^^^^^^^ help: use: `(1..=33).contains(&x)` error: manual `RangeInclusive::contains` implementation - --> $DIR/range_contains.rs:21:5 + --> $DIR/range_contains.rs:20:5 | LL | 999 >= x && 1 <= x; | ^^^^^^^^^^^^^^^^^^ help: use: `(1..=999).contains(&x)` error: manual `!Range::contains` implementation - --> $DIR/range_contains.rs:24:5 + --> $DIR/range_contains.rs:23:5 | LL | x < 8 || x >= 12; | ^^^^^^^^^^^^^^^^ help: use: `!(8..12).contains(&x)` error: manual `!Range::contains` implementation - --> $DIR/range_contains.rs:25:5 + --> $DIR/range_contains.rs:24:5 | LL | x >= 42 || x < 21; | ^^^^^^^^^^^^^^^^^ help: use: `!(21..42).contains(&x)` error: manual `!Range::contains` implementation - --> $DIR/range_contains.rs:26:5 + --> $DIR/range_contains.rs:25:5 | LL | 100 <= x || 1 > x; | ^^^^^^^^^^^^^^^^^ help: use: `!(1..100).contains(&x)` error: manual `!RangeInclusive::contains` implementation - --> $DIR/range_contains.rs:29:5 + --> $DIR/range_contains.rs:28:5 | LL | x < 9 || x > 99; | ^^^^^^^^^^^^^^^ help: use: `!(9..=99).contains(&x)` error: manual `!RangeInclusive::contains` implementation - --> $DIR/range_contains.rs:30:5 + --> $DIR/range_contains.rs:29:5 | LL | x > 33 || x < 1; | ^^^^^^^^^^^^^^^ help: use: `!(1..=33).contains(&x)` error: manual `!RangeInclusive::contains` implementation - --> $DIR/range_contains.rs:31:5 + --> $DIR/range_contains.rs:30:5 | LL | 999 < x || 1 > x; | ^^^^^^^^^^^^^^^^ help: use: `!(1..=999).contains(&x)` error: manual `Range::contains` implementation - --> $DIR/range_contains.rs:46:5 + --> $DIR/range_contains.rs:45:5 | LL | y >= 0. && y < 1.; | ^^^^^^^^^^^^^^^^^ help: use: `(0. ..1.).contains(&y)` error: manual `!RangeInclusive::contains` implementation - --> $DIR/range_contains.rs:47:5 + --> $DIR/range_contains.rs:46:5 | LL | y < 0. || y > 1.; | ^^^^^^^^^^^^^^^^ help: use: `!(0. ..=1.).contains(&y)` error: manual `RangeInclusive::contains` implementation - --> $DIR/range_contains.rs:50:5 + --> $DIR/range_contains.rs:49:5 | LL | x >= -10 && x <= 10; | ^^^^^^^^^^^^^^^^^^^ help: use: `(-10..=10).contains(&x)` error: manual `RangeInclusive::contains` implementation - --> $DIR/range_contains.rs:52:5 + --> $DIR/range_contains.rs:51:5 | LL | y >= -3. && y <= 3.; | ^^^^^^^^^^^^^^^^^^^ help: use: `(-3. ..=3.).contains(&y)` error: manual `RangeInclusive::contains` implementation - --> $DIR/range_contains.rs:57:30 + --> $DIR/range_contains.rs:56:30 | LL | (x >= 0) && (x <= 10) && (z >= 0) && (z <= 10); | ^^^^^^^^^^^^^^^^^^^^^ help: use: `(0..=10).contains(&z)` error: manual `RangeInclusive::contains` implementation - --> $DIR/range_contains.rs:57:5 + --> $DIR/range_contains.rs:56:5 | LL | (x >= 0) && (x <= 10) && (z >= 0) && (z <= 10); | ^^^^^^^^^^^^^^^^^^^^^ help: use: `(0..=10).contains(&x)` error: manual `!Range::contains` implementation - --> $DIR/range_contains.rs:58:29 + --> $DIR/range_contains.rs:57:29 | LL | (x < 0) || (x >= 10) || (z < 0) || (z >= 10); | ^^^^^^^^^^^^^^^^^^^^ help: use: `!(0..10).contains(&z)` error: manual `!Range::contains` implementation - --> $DIR/range_contains.rs:58:5 + --> $DIR/range_contains.rs:57:5 | LL | (x < 0) || (x >= 10) || (z < 0) || (z >= 10); | ^^^^^^^^^^^^^^^^^^^^ help: use: `!(0..10).contains(&x)` error: manual `Range::contains` implementation - --> $DIR/range_contains.rs:79:5 + --> $DIR/range_contains.rs:76:5 | LL | x >= 8 && x < 35; | ^^^^^^^^^^^^^^^^ help: use: `(8..35).contains(&x)` diff --git a/tests/ui/redundant_field_names.fixed b/tests/ui/redundant_field_names.fixed index 34ab552cb1d..ec7f8ae923a 100644 --- a/tests/ui/redundant_field_names.fixed +++ b/tests/ui/redundant_field_names.fixed @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![warn(clippy::redundant_field_names)] #![allow(clippy::no_effect, dead_code, unused_variables)] @@ -72,16 +71,14 @@ fn issue_3476() { S { foo: foo:: }; } +#[clippy::msrv = "1.16"] fn msrv_1_16() { - #![clippy::msrv = "1.16"] - let start = 0; let _ = RangeFrom { start: start }; } +#[clippy::msrv = "1.17"] fn msrv_1_17() { - #![clippy::msrv = "1.17"] - let start = 0; let _ = RangeFrom { start }; } diff --git a/tests/ui/redundant_field_names.rs b/tests/ui/redundant_field_names.rs index a051b1f96f0..73122016cf6 100644 --- a/tests/ui/redundant_field_names.rs +++ b/tests/ui/redundant_field_names.rs @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![warn(clippy::redundant_field_names)] #![allow(clippy::no_effect, dead_code, unused_variables)] @@ -72,16 +71,14 @@ fn issue_3476() { S { foo: foo:: }; } +#[clippy::msrv = "1.16"] fn msrv_1_16() { - #![clippy::msrv = "1.16"] - let start = 0; let _ = RangeFrom { start: start }; } +#[clippy::msrv = "1.17"] fn msrv_1_17() { - #![clippy::msrv = "1.17"] - let start = 0; let _ = RangeFrom { start: start }; } diff --git a/tests/ui/redundant_field_names.stderr b/tests/ui/redundant_field_names.stderr index 8b82e062b93..00a72c50cf7 100644 --- a/tests/ui/redundant_field_names.stderr +++ b/tests/ui/redundant_field_names.stderr @@ -1,5 +1,5 @@ error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:36:9 + --> $DIR/redundant_field_names.rs:35:9 | LL | gender: gender, | ^^^^^^^^^^^^^^ help: replace it with: `gender` @@ -7,43 +7,43 @@ LL | gender: gender, = note: `-D clippy::redundant-field-names` implied by `-D warnings` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:37:9 + --> $DIR/redundant_field_names.rs:36:9 | LL | age: age, | ^^^^^^^^ help: replace it with: `age` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:58:25 + --> $DIR/redundant_field_names.rs:57:25 | LL | let _ = RangeFrom { start: start }; | ^^^^^^^^^^^^ help: replace it with: `start` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:59:23 + --> $DIR/redundant_field_names.rs:58:23 | LL | let _ = RangeTo { end: end }; | ^^^^^^^^ help: replace it with: `end` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:60:21 + --> $DIR/redundant_field_names.rs:59:21 | LL | let _ = Range { start: start, end: end }; | ^^^^^^^^^^^^ help: replace it with: `start` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:60:35 + --> $DIR/redundant_field_names.rs:59:35 | LL | let _ = Range { start: start, end: end }; | ^^^^^^^^ help: replace it with: `end` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:62:32 + --> $DIR/redundant_field_names.rs:61:32 | LL | let _ = RangeToInclusive { end: end }; | ^^^^^^^^ help: replace it with: `end` error: redundant field names in struct initialization - --> $DIR/redundant_field_names.rs:86:25 + --> $DIR/redundant_field_names.rs:83:25 | LL | let _ = RangeFrom { start: start }; | ^^^^^^^^^^^^ help: replace it with: `start` diff --git a/tests/ui/redundant_static_lifetimes.fixed b/tests/ui/redundant_static_lifetimes.fixed index 42110dbe81e..4c5846fe837 100644 --- a/tests/ui/redundant_static_lifetimes.fixed +++ b/tests/ui/redundant_static_lifetimes.fixed @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![allow(unused)] #[derive(Debug)] @@ -56,14 +55,12 @@ impl Bar for Foo { const TRAIT_VAR: &'static str = "foo"; } +#[clippy::msrv = "1.16"] fn msrv_1_16() { - #![clippy::msrv = "1.16"] - static V: &'static u8 = &16; } +#[clippy::msrv = "1.17"] fn msrv_1_17() { - #![clippy::msrv = "1.17"] - static V: &u8 = &17; } diff --git a/tests/ui/redundant_static_lifetimes.rs b/tests/ui/redundant_static_lifetimes.rs index bc5200bc862..64a66be1a83 100644 --- a/tests/ui/redundant_static_lifetimes.rs +++ b/tests/ui/redundant_static_lifetimes.rs @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![allow(unused)] #[derive(Debug)] @@ -56,14 +55,12 @@ impl Bar for Foo { const TRAIT_VAR: &'static str = "foo"; } +#[clippy::msrv = "1.16"] fn msrv_1_16() { - #![clippy::msrv = "1.16"] - static V: &'static u8 = &16; } +#[clippy::msrv = "1.17"] fn msrv_1_17() { - #![clippy::msrv = "1.17"] - static V: &'static u8 = &17; } diff --git a/tests/ui/redundant_static_lifetimes.stderr b/tests/ui/redundant_static_lifetimes.stderr index 735113460d2..0938ebf783f 100644 --- a/tests/ui/redundant_static_lifetimes.stderr +++ b/tests/ui/redundant_static_lifetimes.stderr @@ -1,5 +1,5 @@ error: constants have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:9:17 + --> $DIR/redundant_static_lifetimes.rs:8:17 | LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static. | -^^^^^^^---- help: consider removing `'static`: `&str` @@ -7,97 +7,97 @@ LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removin = note: `-D clippy::redundant-static-lifetimes` implied by `-D warnings` error: constants have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:13:21 + --> $DIR/redundant_static_lifetimes.rs:12:21 | LL | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: constants have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:15:32 + --> $DIR/redundant_static_lifetimes.rs:14:32 | LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: constants have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:15:47 + --> $DIR/redundant_static_lifetimes.rs:14:47 | LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: constants have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:17:17 + --> $DIR/redundant_static_lifetimes.rs:16:17 | LL | const VAR_SIX: &'static u8 = &5; | -^^^^^^^--- help: consider removing `'static`: `&u8` error: constants have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:19:20 + --> $DIR/redundant_static_lifetimes.rs:18:20 | LL | const VAR_HEIGHT: &'static Foo = &Foo {}; | -^^^^^^^---- help: consider removing `'static`: `&Foo` error: constants have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:21:19 + --> $DIR/redundant_static_lifetimes.rs:20:19 | LL | const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR Consider removing 'static. | -^^^^^^^----- help: consider removing `'static`: `&[u8]` error: constants have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:23:19 + --> $DIR/redundant_static_lifetimes.rs:22:19 | LL | const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static. | -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)` error: constants have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:25:19 + --> $DIR/redundant_static_lifetimes.rs:24:19 | LL | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. | -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]` error: statics have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:27:25 + --> $DIR/redundant_static_lifetimes.rs:26:25 | LL | static STATIC_VAR_ONE: &'static str = "Test static #1"; // ERROR Consider removing 'static. | -^^^^^^^---- help: consider removing `'static`: `&str` error: statics have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:31:29 + --> $DIR/redundant_static_lifetimes.rs:30:29 | LL | static STATIC_VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: statics have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:33:25 + --> $DIR/redundant_static_lifetimes.rs:32:25 | LL | static STATIC_VAR_SIX: &'static u8 = &5; | -^^^^^^^--- help: consider removing `'static`: `&u8` error: statics have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:35:28 + --> $DIR/redundant_static_lifetimes.rs:34:28 | LL | static STATIC_VAR_HEIGHT: &'static Foo = &Foo {}; | -^^^^^^^---- help: consider removing `'static`: `&Foo` error: statics have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:37:27 + --> $DIR/redundant_static_lifetimes.rs:36:27 | LL | static STATIC_VAR_SLICE: &'static [u8] = b"Test static #3"; // ERROR Consider removing 'static. | -^^^^^^^----- help: consider removing `'static`: `&[u8]` error: statics have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:39:27 + --> $DIR/redundant_static_lifetimes.rs:38:27 | LL | static STATIC_VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static. | -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)` error: statics have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:41:27 + --> $DIR/redundant_static_lifetimes.rs:40:27 | LL | static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. | -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]` error: statics have by default a `'static` lifetime - --> $DIR/redundant_static_lifetimes.rs:68:16 + --> $DIR/redundant_static_lifetimes.rs:65:16 | LL | static V: &'static u8 = &17; | -^^^^^^^--- help: consider removing `'static`: `&u8` diff --git a/tests/ui/seek_from_current.fixed b/tests/ui/seek_from_current.fixed index 4b5303324bc..1309c91b81c 100644 --- a/tests/ui/seek_from_current.fixed +++ b/tests/ui/seek_from_current.fixed @@ -1,12 +1,11 @@ // run-rustfix #![warn(clippy::seek_from_current)] -#![feature(custom_inner_attributes)] use std::fs::File; use std::io::{self, Seek, SeekFrom, Write}; +#[clippy::msrv = "1.50"] fn _msrv_1_50() -> io::Result<()> { - #![clippy::msrv = "1.50"] let mut f = File::create("foo.txt")?; f.write_all(b"Hi!")?; f.seek(SeekFrom::Current(0))?; @@ -14,8 +13,8 @@ fn _msrv_1_50() -> io::Result<()> { Ok(()) } +#[clippy::msrv = "1.51"] fn _msrv_1_51() -> io::Result<()> { - #![clippy::msrv = "1.51"] let mut f = File::create("foo.txt")?; f.write_all(b"Hi!")?; f.stream_position()?; diff --git a/tests/ui/seek_from_current.rs b/tests/ui/seek_from_current.rs index f93639261a1..5d9b1424cf6 100644 --- a/tests/ui/seek_from_current.rs +++ b/tests/ui/seek_from_current.rs @@ -1,12 +1,11 @@ // run-rustfix #![warn(clippy::seek_from_current)] -#![feature(custom_inner_attributes)] use std::fs::File; use std::io::{self, Seek, SeekFrom, Write}; +#[clippy::msrv = "1.50"] fn _msrv_1_50() -> io::Result<()> { - #![clippy::msrv = "1.50"] let mut f = File::create("foo.txt")?; f.write_all(b"Hi!")?; f.seek(SeekFrom::Current(0))?; @@ -14,8 +13,8 @@ fn _msrv_1_50() -> io::Result<()> { Ok(()) } +#[clippy::msrv = "1.51"] fn _msrv_1_51() -> io::Result<()> { - #![clippy::msrv = "1.51"] let mut f = File::create("foo.txt")?; f.write_all(b"Hi!")?; f.seek(SeekFrom::Current(0))?; diff --git a/tests/ui/seek_from_current.stderr b/tests/ui/seek_from_current.stderr index db1125b53cd..c079f361192 100644 --- a/tests/ui/seek_from_current.stderr +++ b/tests/ui/seek_from_current.stderr @@ -1,5 +1,5 @@ error: using `SeekFrom::Current` to start from current position - --> $DIR/seek_from_current.rs:21:5 + --> $DIR/seek_from_current.rs:20:5 | LL | f.seek(SeekFrom::Current(0))?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `f.stream_position()` diff --git a/tests/ui/seek_to_start_instead_of_rewind.fixed b/tests/ui/seek_to_start_instead_of_rewind.fixed index 464b6cdef63..9d0d1124c46 100644 --- a/tests/ui/seek_to_start_instead_of_rewind.fixed +++ b/tests/ui/seek_to_start_instead_of_rewind.fixed @@ -1,6 +1,5 @@ // run-rustfix #![allow(unused)] -#![feature(custom_inner_attributes)] #![warn(clippy::seek_to_start_instead_of_rewind)] use std::fs::OpenOptions; @@ -94,9 +93,8 @@ fn main() { assert_eq!(&buf, hello); } +#[clippy::msrv = "1.54"] fn msrv_1_54() { - #![clippy::msrv = "1.54"] - let mut f = OpenOptions::new() .write(true) .read(true) @@ -115,9 +113,8 @@ fn msrv_1_54() { assert_eq!(&buf, hello); } +#[clippy::msrv = "1.55"] fn msrv_1_55() { - #![clippy::msrv = "1.55"] - let mut f = OpenOptions::new() .write(true) .read(true) diff --git a/tests/ui/seek_to_start_instead_of_rewind.rs b/tests/ui/seek_to_start_instead_of_rewind.rs index 68e09bd7c1f..c5bc57cc3a7 100644 --- a/tests/ui/seek_to_start_instead_of_rewind.rs +++ b/tests/ui/seek_to_start_instead_of_rewind.rs @@ -1,6 +1,5 @@ // run-rustfix #![allow(unused)] -#![feature(custom_inner_attributes)] #![warn(clippy::seek_to_start_instead_of_rewind)] use std::fs::OpenOptions; @@ -94,9 +93,8 @@ fn main() { assert_eq!(&buf, hello); } +#[clippy::msrv = "1.54"] fn msrv_1_54() { - #![clippy::msrv = "1.54"] - let mut f = OpenOptions::new() .write(true) .read(true) @@ -115,9 +113,8 @@ fn msrv_1_54() { assert_eq!(&buf, hello); } +#[clippy::msrv = "1.55"] fn msrv_1_55() { - #![clippy::msrv = "1.55"] - let mut f = OpenOptions::new() .write(true) .read(true) diff --git a/tests/ui/seek_to_start_instead_of_rewind.stderr b/tests/ui/seek_to_start_instead_of_rewind.stderr index de0eec5d909..6cce025359f 100644 --- a/tests/ui/seek_to_start_instead_of_rewind.stderr +++ b/tests/ui/seek_to_start_instead_of_rewind.stderr @@ -1,5 +1,5 @@ error: used `seek` to go to the start of the stream - --> $DIR/seek_to_start_instead_of_rewind.rs:54:7 + --> $DIR/seek_to_start_instead_of_rewind.rs:53:7 | LL | t.seek(SeekFrom::Start(0)); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `rewind()` @@ -7,13 +7,13 @@ LL | t.seek(SeekFrom::Start(0)); = note: `-D clippy::seek-to-start-instead-of-rewind` implied by `-D warnings` error: used `seek` to go to the start of the stream - --> $DIR/seek_to_start_instead_of_rewind.rs:59:7 + --> $DIR/seek_to_start_instead_of_rewind.rs:58:7 | LL | t.seek(SeekFrom::Start(0)); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `rewind()` error: used `seek` to go to the start of the stream - --> $DIR/seek_to_start_instead_of_rewind.rs:131:7 + --> $DIR/seek_to_start_instead_of_rewind.rs:128:7 | LL | f.seek(SeekFrom::Start(0)); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `rewind()` diff --git a/tests/ui/transmute_ptr_to_ref.fixed b/tests/ui/transmute_ptr_to_ref.fixed index e5fe9133f97..074dae5fb28 100644 --- a/tests/ui/transmute_ptr_to_ref.fixed +++ b/tests/ui/transmute_ptr_to_ref.fixed @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![warn(clippy::transmute_ptr_to_ref)] #![allow(clippy::match_single_binding)] @@ -51,8 +50,8 @@ unsafe fn _issue8924<'a, 'b, 'c>(x: *const &'a u32, y: *const &'b u32) -> &'c &' } } +#[clippy::msrv = "1.38"] unsafe fn _meets_msrv<'a, 'b, 'c>(x: *const &'a u32) -> &'c &'b u32 { - #![clippy::msrv = "1.38"] let a = 0u32; let a = &a as *const u32; let _: &u32 = &*a; @@ -63,8 +62,8 @@ unsafe fn _meets_msrv<'a, 'b, 'c>(x: *const &'a u32) -> &'c &'b u32 { } } +#[clippy::msrv = "1.37"] unsafe fn _under_msrv<'a, 'b, 'c>(x: *const &'a u32) -> &'c &'b u32 { - #![clippy::msrv = "1.37"] let a = 0u32; let a = &a as *const u32; let _: &u32 = &*a; diff --git a/tests/ui/transmute_ptr_to_ref.rs b/tests/ui/transmute_ptr_to_ref.rs index fe49cdc324f..2edc122cf47 100644 --- a/tests/ui/transmute_ptr_to_ref.rs +++ b/tests/ui/transmute_ptr_to_ref.rs @@ -1,6 +1,5 @@ // run-rustfix -#![feature(custom_inner_attributes)] #![warn(clippy::transmute_ptr_to_ref)] #![allow(clippy::match_single_binding)] @@ -51,8 +50,8 @@ unsafe fn _issue8924<'a, 'b, 'c>(x: *const &'a u32, y: *const &'b u32) -> &'c &' } } +#[clippy::msrv = "1.38"] unsafe fn _meets_msrv<'a, 'b, 'c>(x: *const &'a u32) -> &'c &'b u32 { - #![clippy::msrv = "1.38"] let a = 0u32; let a = &a as *const u32; let _: &u32 = std::mem::transmute(a); @@ -63,8 +62,8 @@ unsafe fn _meets_msrv<'a, 'b, 'c>(x: *const &'a u32) -> &'c &'b u32 { } } +#[clippy::msrv = "1.37"] unsafe fn _under_msrv<'a, 'b, 'c>(x: *const &'a u32) -> &'c &'b u32 { - #![clippy::msrv = "1.37"] let a = 0u32; let a = &a as *const u32; let _: &u32 = std::mem::transmute(a); diff --git a/tests/ui/transmute_ptr_to_ref.stderr b/tests/ui/transmute_ptr_to_ref.stderr index 10117ee9182..b3e6c09d2d7 100644 --- a/tests/ui/transmute_ptr_to_ref.stderr +++ b/tests/ui/transmute_ptr_to_ref.stderr @@ -1,5 +1,5 @@ error: transmute from a pointer type (`*const T`) to a reference type (`&T`) - --> $DIR/transmute_ptr_to_ref.rs:8:17 + --> $DIR/transmute_ptr_to_ref.rs:7:17 | LL | let _: &T = std::mem::transmute(p); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*p` @@ -7,127 +7,127 @@ LL | let _: &T = std::mem::transmute(p); = note: `-D clippy::transmute-ptr-to-ref` implied by `-D warnings` error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`) - --> $DIR/transmute_ptr_to_ref.rs:11:21 + --> $DIR/transmute_ptr_to_ref.rs:10:21 | LL | let _: &mut T = std::mem::transmute(m); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *m` error: transmute from a pointer type (`*mut T`) to a reference type (`&T`) - --> $DIR/transmute_ptr_to_ref.rs:14:17 + --> $DIR/transmute_ptr_to_ref.rs:13:17 | LL | let _: &T = std::mem::transmute(m); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*m` error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`) - --> $DIR/transmute_ptr_to_ref.rs:17:21 + --> $DIR/transmute_ptr_to_ref.rs:16:21 | LL | let _: &mut T = std::mem::transmute(p as *mut T); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(p as *mut T)` error: transmute from a pointer type (`*const U`) to a reference type (`&T`) - --> $DIR/transmute_ptr_to_ref.rs:20:17 + --> $DIR/transmute_ptr_to_ref.rs:19:17 | LL | let _: &T = std::mem::transmute(o); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(o as *const T)` error: transmute from a pointer type (`*mut U`) to a reference type (`&mut T`) - --> $DIR/transmute_ptr_to_ref.rs:23:21 + --> $DIR/transmute_ptr_to_ref.rs:22:21 | LL | let _: &mut T = std::mem::transmute(om); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(om as *mut T)` error: transmute from a pointer type (`*mut U`) to a reference type (`&T`) - --> $DIR/transmute_ptr_to_ref.rs:26:17 + --> $DIR/transmute_ptr_to_ref.rs:25:17 | LL | let _: &T = std::mem::transmute(om); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(om as *const T)` error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<'_, u8>`) - --> $DIR/transmute_ptr_to_ref.rs:36:32 + --> $DIR/transmute_ptr_to_ref.rs:35:32 | LL | let _: &Foo = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::>()` error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<'_, &u8>`) - --> $DIR/transmute_ptr_to_ref.rs:38:33 + --> $DIR/transmute_ptr_to_ref.rs:37:33 | LL | let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::>()` error: transmute from a pointer type (`*const i32`) to a reference type (`&u8`) - --> $DIR/transmute_ptr_to_ref.rs:42:14 + --> $DIR/transmute_ptr_to_ref.rs:41:14 | LL | unsafe { std::mem::transmute::<_, Bar>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const u8)` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> $DIR/transmute_ptr_to_ref.rs:47:14 + --> $DIR/transmute_ptr_to_ref.rs:46:14 | LL | 0 => std::mem::transmute(x), | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&u32>()` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> $DIR/transmute_ptr_to_ref.rs:48:14 + --> $DIR/transmute_ptr_to_ref.rs:47:14 | LL | 1 => std::mem::transmute(y), | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&u32>()` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> $DIR/transmute_ptr_to_ref.rs:49:14 + --> $DIR/transmute_ptr_to_ref.rs:48:14 | LL | 2 => std::mem::transmute::<_, &&'b u32>(x), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b u32>()` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> $DIR/transmute_ptr_to_ref.rs:50:14 + --> $DIR/transmute_ptr_to_ref.rs:49:14 | LL | _ => std::mem::transmute::<_, &&'b u32>(y), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&'b u32>()` error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) - --> $DIR/transmute_ptr_to_ref.rs:58:19 + --> $DIR/transmute_ptr_to_ref.rs:57:19 | LL | let _: &u32 = std::mem::transmute(a); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a` error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) - --> $DIR/transmute_ptr_to_ref.rs:59:19 + --> $DIR/transmute_ptr_to_ref.rs:58:19 | LL | let _: &u32 = std::mem::transmute::<_, &u32>(a); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a.cast::()` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> $DIR/transmute_ptr_to_ref.rs:61:14 + --> $DIR/transmute_ptr_to_ref.rs:60:14 | LL | 0 => std::mem::transmute(x), | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&u32>()` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> $DIR/transmute_ptr_to_ref.rs:62:14 + --> $DIR/transmute_ptr_to_ref.rs:61:14 | LL | _ => std::mem::transmute::<_, &&'b u32>(x), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b u32>()` error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) - --> $DIR/transmute_ptr_to_ref.rs:70:19 + --> $DIR/transmute_ptr_to_ref.rs:69:19 | LL | let _: &u32 = std::mem::transmute(a); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a` error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) - --> $DIR/transmute_ptr_to_ref.rs:71:19 + --> $DIR/transmute_ptr_to_ref.rs:70:19 | LL | let _: &u32 = std::mem::transmute::<_, &u32>(a); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(a as *const u32)` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> $DIR/transmute_ptr_to_ref.rs:73:14 + --> $DIR/transmute_ptr_to_ref.rs:72:14 | LL | 0 => std::mem::transmute(x), | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &u32)` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> $DIR/transmute_ptr_to_ref.rs:74:14 + --> $DIR/transmute_ptr_to_ref.rs:73:14 | LL | _ => std::mem::transmute::<_, &&'b u32>(x), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &'b u32)` diff --git a/tests/ui/uninlined_format_args.fixed b/tests/ui/uninlined_format_args.fixed index ca56c95c23f..46ec7771114 100644 --- a/tests/ui/uninlined_format_args.fixed +++ b/tests/ui/uninlined_format_args.fixed @@ -1,6 +1,5 @@ // aux-build:proc_macro_with_span.rs // run-rustfix -#![feature(custom_inner_attributes)] #![warn(clippy::uninlined_format_args)] #![allow(named_arguments_used_positionally, unused_imports, unused_macros, unused_variables)] #![allow(clippy::eq_op, clippy::format_in_format_args, clippy::print_literal)] @@ -164,14 +163,14 @@ fn main() { tester(42); } +#[clippy::msrv = "1.57"] fn _under_msrv() { - #![clippy::msrv = "1.57"] let local_i32 = 1; println!("don't expand='{}'", local_i32); } +#[clippy::msrv = "1.58"] fn _meets_msrv() { - #![clippy::msrv = "1.58"] let local_i32 = 1; println!("expand='{local_i32}'"); } diff --git a/tests/ui/uninlined_format_args.rs b/tests/ui/uninlined_format_args.rs index 8e495ebd083..35b3677a896 100644 --- a/tests/ui/uninlined_format_args.rs +++ b/tests/ui/uninlined_format_args.rs @@ -1,6 +1,5 @@ // aux-build:proc_macro_with_span.rs // run-rustfix -#![feature(custom_inner_attributes)] #![warn(clippy::uninlined_format_args)] #![allow(named_arguments_used_positionally, unused_imports, unused_macros, unused_variables)] #![allow(clippy::eq_op, clippy::format_in_format_args, clippy::print_literal)] @@ -169,14 +168,14 @@ fn main() { tester(42); } +#[clippy::msrv = "1.57"] fn _under_msrv() { - #![clippy::msrv = "1.57"] let local_i32 = 1; println!("don't expand='{}'", local_i32); } +#[clippy::msrv = "1.58"] fn _meets_msrv() { - #![clippy::msrv = "1.58"] let local_i32 = 1; println!("expand='{}'", local_i32); } diff --git a/tests/ui/uninlined_format_args.stderr b/tests/ui/uninlined_format_args.stderr index 1182d57ce9b..05ed5b6616c 100644 --- a/tests/ui/uninlined_format_args.stderr +++ b/tests/ui/uninlined_format_args.stderr @@ -1,5 +1,5 @@ error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:41:5 + --> $DIR/uninlined_format_args.rs:40:5 | LL | println!("val='{}'", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -12,7 +12,7 @@ LL + println!("val='{local_i32}'"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:42:5 + --> $DIR/uninlined_format_args.rs:41:5 | LL | println!("val='{ }'", local_i32); // 3 spaces | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL + println!("val='{local_i32}'"); // 3 spaces | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:43:5 + --> $DIR/uninlined_format_args.rs:42:5 | LL | println!("val='{ }'", local_i32); // tab | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +36,7 @@ LL + println!("val='{local_i32}'"); // tab | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:44:5 + --> $DIR/uninlined_format_args.rs:43:5 | LL | println!("val='{ }'", local_i32); // space+tab | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -48,7 +48,7 @@ LL + println!("val='{local_i32}'"); // space+tab | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:45:5 + --> $DIR/uninlined_format_args.rs:44:5 | LL | println!("val='{ }'", local_i32); // tab+space | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL + println!("val='{local_i32}'"); // tab+space | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:46:5 + --> $DIR/uninlined_format_args.rs:45:5 | LL | / println!( LL | | "val='{ @@ -70,7 +70,7 @@ LL | | ); | |_____^ error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:51:5 + --> $DIR/uninlined_format_args.rs:50:5 | LL | println!("{}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -82,7 +82,7 @@ LL + println!("{local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:52:5 + --> $DIR/uninlined_format_args.rs:51:5 | LL | println!("{}", fn_arg); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -94,7 +94,7 @@ LL + println!("{fn_arg}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:53:5 + --> $DIR/uninlined_format_args.rs:52:5 | LL | println!("{:?}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -106,7 +106,7 @@ LL + println!("{local_i32:?}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:54:5 + --> $DIR/uninlined_format_args.rs:53:5 | LL | println!("{:#?}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -118,7 +118,7 @@ LL + println!("{local_i32:#?}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:55:5 + --> $DIR/uninlined_format_args.rs:54:5 | LL | println!("{:4}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -130,7 +130,7 @@ LL + println!("{local_i32:4}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:56:5 + --> $DIR/uninlined_format_args.rs:55:5 | LL | println!("{:04}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -142,7 +142,7 @@ LL + println!("{local_i32:04}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:57:5 + --> $DIR/uninlined_format_args.rs:56:5 | LL | println!("{:<3}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -154,7 +154,7 @@ LL + println!("{local_i32:<3}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:58:5 + --> $DIR/uninlined_format_args.rs:57:5 | LL | println!("{:#010x}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -166,7 +166,7 @@ LL + println!("{local_i32:#010x}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:59:5 + --> $DIR/uninlined_format_args.rs:58:5 | LL | println!("{:.1}", local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -178,7 +178,7 @@ LL + println!("{local_f64:.1}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:60:5 + --> $DIR/uninlined_format_args.rs:59:5 | LL | println!("Hello {} is {:.*}", "x", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -190,7 +190,7 @@ LL + println!("Hello {} is {local_f64:.local_i32$}", "x"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:61:5 + --> $DIR/uninlined_format_args.rs:60:5 | LL | println!("Hello {} is {:.*}", local_i32, 5, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -202,7 +202,7 @@ LL + println!("Hello {local_i32} is {local_f64:.*}", 5); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:62:5 + --> $DIR/uninlined_format_args.rs:61:5 | LL | println!("Hello {} is {2:.*}", local_i32, 5, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -214,7 +214,7 @@ LL + println!("Hello {local_i32} is {local_f64:.*}", 5); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:63:5 + --> $DIR/uninlined_format_args.rs:62:5 | LL | println!("{} {}", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -226,7 +226,7 @@ LL + println!("{local_i32} {local_f64}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:64:5 + --> $DIR/uninlined_format_args.rs:63:5 | LL | println!("{}, {}", local_i32, local_opt.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -238,7 +238,7 @@ LL + println!("{local_i32}, {}", local_opt.unwrap()); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:65:5 + --> $DIR/uninlined_format_args.rs:64:5 | LL | println!("{}", val); | ^^^^^^^^^^^^^^^^^^^ @@ -250,7 +250,7 @@ LL + println!("{val}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:66:5 + --> $DIR/uninlined_format_args.rs:65:5 | LL | println!("{}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -262,7 +262,7 @@ LL + println!("{val}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:68:5 + --> $DIR/uninlined_format_args.rs:67:5 | LL | println!("val='{/t }'", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -274,7 +274,7 @@ LL + println!("val='{local_i32}'"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:69:5 + --> $DIR/uninlined_format_args.rs:68:5 | LL | println!("val='{/n }'", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -286,7 +286,7 @@ LL + println!("val='{local_i32}'"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:70:5 + --> $DIR/uninlined_format_args.rs:69:5 | LL | println!("val='{local_i32}'", local_i32 = local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -298,7 +298,7 @@ LL + println!("val='{local_i32}'"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:71:5 + --> $DIR/uninlined_format_args.rs:70:5 | LL | println!("val='{local_i32}'", local_i32 = fn_arg); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -310,7 +310,7 @@ LL + println!("val='{fn_arg}'"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:72:5 + --> $DIR/uninlined_format_args.rs:71:5 | LL | println!("{0}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -322,7 +322,7 @@ LL + println!("{local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:73:5 + --> $DIR/uninlined_format_args.rs:72:5 | LL | println!("{0:?}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -334,7 +334,7 @@ LL + println!("{local_i32:?}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:74:5 + --> $DIR/uninlined_format_args.rs:73:5 | LL | println!("{0:#?}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -346,7 +346,7 @@ LL + println!("{local_i32:#?}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:75:5 + --> $DIR/uninlined_format_args.rs:74:5 | LL | println!("{0:04}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -358,7 +358,7 @@ LL + println!("{local_i32:04}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:76:5 + --> $DIR/uninlined_format_args.rs:75:5 | LL | println!("{0:<3}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -370,7 +370,7 @@ LL + println!("{local_i32:<3}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:77:5 + --> $DIR/uninlined_format_args.rs:76:5 | LL | println!("{0:#010x}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -382,7 +382,7 @@ LL + println!("{local_i32:#010x}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:78:5 + --> $DIR/uninlined_format_args.rs:77:5 | LL | println!("{0:.1}", local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -394,7 +394,7 @@ LL + println!("{local_f64:.1}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:79:5 + --> $DIR/uninlined_format_args.rs:78:5 | LL | println!("{0} {0}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -406,7 +406,7 @@ LL + println!("{local_i32} {local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:80:5 + --> $DIR/uninlined_format_args.rs:79:5 | LL | println!("{1} {} {0} {}", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -418,7 +418,7 @@ LL + println!("{local_f64} {local_i32} {local_i32} {local_f64}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:81:5 + --> $DIR/uninlined_format_args.rs:80:5 | LL | println!("{0} {1}", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -430,7 +430,7 @@ LL + println!("{local_i32} {local_f64}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:82:5 + --> $DIR/uninlined_format_args.rs:81:5 | LL | println!("{1} {0}", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -442,7 +442,7 @@ LL + println!("{local_f64} {local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:83:5 + --> $DIR/uninlined_format_args.rs:82:5 | LL | println!("{1} {0} {1} {0}", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -454,7 +454,7 @@ LL + println!("{local_f64} {local_i32} {local_f64} {local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:85:5 + --> $DIR/uninlined_format_args.rs:84:5 | LL | println!("{v}", v = local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -466,7 +466,7 @@ LL + println!("{local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:86:5 + --> $DIR/uninlined_format_args.rs:85:5 | LL | println!("{local_i32:0$}", width); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -478,7 +478,7 @@ LL + println!("{local_i32:width$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:87:5 + --> $DIR/uninlined_format_args.rs:86:5 | LL | println!("{local_i32:w$}", w = width); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -490,7 +490,7 @@ LL + println!("{local_i32:width$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:88:5 + --> $DIR/uninlined_format_args.rs:87:5 | LL | println!("{local_i32:.0$}", prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -502,7 +502,7 @@ LL + println!("{local_i32:.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:89:5 + --> $DIR/uninlined_format_args.rs:88:5 | LL | println!("{local_i32:.p$}", p = prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -514,7 +514,7 @@ LL + println!("{local_i32:.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:90:5 + --> $DIR/uninlined_format_args.rs:89:5 | LL | println!("{:0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -526,7 +526,7 @@ LL + println!("{val:val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:91:5 + --> $DIR/uninlined_format_args.rs:90:5 | LL | println!("{0:0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -538,7 +538,7 @@ LL + println!("{val:val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:92:5 + --> $DIR/uninlined_format_args.rs:91:5 | LL | println!("{:0$.0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -550,7 +550,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:93:5 + --> $DIR/uninlined_format_args.rs:92:5 | LL | println!("{0:0$.0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -562,7 +562,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:94:5 + --> $DIR/uninlined_format_args.rs:93:5 | LL | println!("{0:0$.v$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -574,7 +574,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:95:5 + --> $DIR/uninlined_format_args.rs:94:5 | LL | println!("{0:v$.0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -586,7 +586,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:96:5 + --> $DIR/uninlined_format_args.rs:95:5 | LL | println!("{v:0$.0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -598,7 +598,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:97:5 + --> $DIR/uninlined_format_args.rs:96:5 | LL | println!("{v:v$.0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -610,7 +610,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:98:5 + --> $DIR/uninlined_format_args.rs:97:5 | LL | println!("{v:0$.v$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -622,7 +622,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:99:5 + --> $DIR/uninlined_format_args.rs:98:5 | LL | println!("{v:v$.v$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -634,7 +634,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:100:5 + --> $DIR/uninlined_format_args.rs:99:5 | LL | println!("{:0$}", width); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -646,7 +646,7 @@ LL + println!("{width:width$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:101:5 + --> $DIR/uninlined_format_args.rs:100:5 | LL | println!("{:1$}", local_i32, width); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -658,7 +658,7 @@ LL + println!("{local_i32:width$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:102:5 + --> $DIR/uninlined_format_args.rs:101:5 | LL | println!("{:w$}", w = width); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -670,7 +670,7 @@ LL + println!("{width:width$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:103:5 + --> $DIR/uninlined_format_args.rs:102:5 | LL | println!("{:w$}", local_i32, w = width); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -682,7 +682,7 @@ LL + println!("{local_i32:width$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:104:5 + --> $DIR/uninlined_format_args.rs:103:5 | LL | println!("{:.0$}", prec); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -694,7 +694,7 @@ LL + println!("{prec:.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:105:5 + --> $DIR/uninlined_format_args.rs:104:5 | LL | println!("{:.1$}", local_i32, prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -706,7 +706,7 @@ LL + println!("{local_i32:.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:106:5 + --> $DIR/uninlined_format_args.rs:105:5 | LL | println!("{:.p$}", p = prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -718,7 +718,7 @@ LL + println!("{prec:.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:107:5 + --> $DIR/uninlined_format_args.rs:106:5 | LL | println!("{:.p$}", local_i32, p = prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -730,7 +730,7 @@ LL + println!("{local_i32:.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:108:5 + --> $DIR/uninlined_format_args.rs:107:5 | LL | println!("{:0$.1$}", width, prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -742,7 +742,7 @@ LL + println!("{width:width$.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:109:5 + --> $DIR/uninlined_format_args.rs:108:5 | LL | println!("{:0$.w$}", width, w = prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -754,7 +754,7 @@ LL + println!("{width:width$.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:110:5 + --> $DIR/uninlined_format_args.rs:109:5 | LL | println!("{:1$.2$}", local_f64, width, prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -766,7 +766,7 @@ LL + println!("{local_f64:width$.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:111:5 + --> $DIR/uninlined_format_args.rs:110:5 | LL | println!("{:1$.2$} {0} {1} {2}", local_f64, width, prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -778,7 +778,7 @@ LL + println!("{local_f64:width$.prec$} {local_f64} {width} {prec}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:112:5 + --> $DIR/uninlined_format_args.rs:111:5 | LL | / println!( LL | | "{0:1$.2$} {0:2$.1$} {1:0$.2$} {1:2$.0$} {2:0$.1$} {2:1$.0$}", @@ -787,7 +787,7 @@ LL | | ); | |_____^ error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:123:5 + --> $DIR/uninlined_format_args.rs:122:5 | LL | println!("Width = {}, value with width = {:0$}", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -799,7 +799,7 @@ LL + println!("Width = {local_i32}, value with width = {local_f64:local_i32$ | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:124:5 + --> $DIR/uninlined_format_args.rs:123:5 | LL | println!("{:w$.p$}", local_i32, w = width, p = prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -811,7 +811,7 @@ LL + println!("{local_i32:width$.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:125:5 + --> $DIR/uninlined_format_args.rs:124:5 | LL | println!("{:w$.p$}", w = width, p = prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -823,7 +823,7 @@ LL + println!("{width:width$.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:126:20 + --> $DIR/uninlined_format_args.rs:125:20 | LL | println!("{}", format!("{}", local_i32)); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -835,7 +835,7 @@ LL + println!("{}", format!("{local_i32}")); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:144:5 + --> $DIR/uninlined_format_args.rs:143:5 | LL | / println!( LL | | "{}", @@ -845,7 +845,7 @@ LL | | ); | |_____^ error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:149:5 + --> $DIR/uninlined_format_args.rs:148:5 | LL | println!("{}", /* comment with a comma , in it */ val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -857,7 +857,7 @@ LL + println!("{val}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:155:9 + --> $DIR/uninlined_format_args.rs:154:9 | LL | panic!("p1 {}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -869,7 +869,7 @@ LL + panic!("p1 {local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:158:9 + --> $DIR/uninlined_format_args.rs:157:9 | LL | panic!("p2 {0}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -881,7 +881,7 @@ LL + panic!("p2 {local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:161:9 + --> $DIR/uninlined_format_args.rs:160:9 | LL | panic!("p3 {local_i32}", local_i32 = local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -893,7 +893,7 @@ LL + panic!("p3 {local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:181:5 + --> $DIR/uninlined_format_args.rs:180:5 | LL | println!("expand='{}'", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unnecessary_to_owned.fixed b/tests/ui/unnecessary_to_owned.fixed index fadcf7f9c9e..ddeda795f81 100644 --- a/tests/ui/unnecessary_to_owned.fixed +++ b/tests/ui/unnecessary_to_owned.fixed @@ -2,7 +2,6 @@ #![allow(clippy::needless_borrow, clippy::ptr_arg)] #![warn(clippy::unnecessary_to_owned)] -#![feature(custom_inner_attributes)] use std::borrow::Cow; use std::ffi::{CStr, CString, OsStr, OsString}; @@ -215,14 +214,14 @@ fn get_file_path(_file_type: &FileType) -> Result Result $DIR/unnecessary_to_owned.rs:151:64 + --> $DIR/unnecessary_to_owned.rs:150:64 | LL | require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned()); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/unnecessary_to_owned.rs:151:20 + --> $DIR/unnecessary_to_owned.rs:150:20 | LL | require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: `-D clippy::redundant-clone` implied by `-D warnings` error: redundant clone - --> $DIR/unnecessary_to_owned.rs:152:40 + --> $DIR/unnecessary_to_owned.rs:151:40 | LL | require_os_str(&OsString::from("x").to_os_string()); | ^^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/unnecessary_to_owned.rs:152:21 + --> $DIR/unnecessary_to_owned.rs:151:21 | LL | require_os_str(&OsString::from("x").to_os_string()); | ^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/unnecessary_to_owned.rs:153:48 + --> $DIR/unnecessary_to_owned.rs:152:48 | LL | require_path(&std::path::PathBuf::from("x").to_path_buf()); | ^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/unnecessary_to_owned.rs:153:19 + --> $DIR/unnecessary_to_owned.rs:152:19 | LL | require_path(&std::path::PathBuf::from("x").to_path_buf()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/unnecessary_to_owned.rs:154:35 + --> $DIR/unnecessary_to_owned.rs:153:35 | LL | require_str(&String::from("x").to_string()); | ^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/unnecessary_to_owned.rs:154:18 + --> $DIR/unnecessary_to_owned.rs:153:18 | LL | require_str(&String::from("x").to_string()); | ^^^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/unnecessary_to_owned.rs:155:39 + --> $DIR/unnecessary_to_owned.rs:154:39 | LL | require_slice(&[String::from("x")].to_owned()); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/unnecessary_to_owned.rs:155:20 + --> $DIR/unnecessary_to_owned.rs:154:20 | LL | require_slice(&[String::from("x")].to_owned()); | ^^^^^^^^^^^^^^^^^^^ error: unnecessary use of `into_owned` - --> $DIR/unnecessary_to_owned.rs:60:36 + --> $DIR/unnecessary_to_owned.rs:59:36 | LL | require_c_str(&Cow::from(c_str).into_owned()); | ^^^^^^^^^^^^^ help: remove this @@ -68,415 +68,415 @@ LL | require_c_str(&Cow::from(c_str).into_owned()); = note: `-D clippy::unnecessary-to-owned` implied by `-D warnings` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:61:19 + --> $DIR/unnecessary_to_owned.rs:60:19 | LL | require_c_str(&c_str.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `c_str` error: unnecessary use of `to_os_string` - --> $DIR/unnecessary_to_owned.rs:63:20 + --> $DIR/unnecessary_to_owned.rs:62:20 | LL | require_os_str(&os_str.to_os_string()); | ^^^^^^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `into_owned` - --> $DIR/unnecessary_to_owned.rs:64:38 + --> $DIR/unnecessary_to_owned.rs:63:38 | LL | require_os_str(&Cow::from(os_str).into_owned()); | ^^^^^^^^^^^^^ help: remove this error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:65:20 + --> $DIR/unnecessary_to_owned.rs:64:20 | LL | require_os_str(&os_str.to_owned()); | ^^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `to_path_buf` - --> $DIR/unnecessary_to_owned.rs:67:18 + --> $DIR/unnecessary_to_owned.rs:66:18 | LL | require_path(&path.to_path_buf()); | ^^^^^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `into_owned` - --> $DIR/unnecessary_to_owned.rs:68:34 + --> $DIR/unnecessary_to_owned.rs:67:34 | LL | require_path(&Cow::from(path).into_owned()); | ^^^^^^^^^^^^^ help: remove this error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:69:18 + --> $DIR/unnecessary_to_owned.rs:68:18 | LL | require_path(&path.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `to_string` - --> $DIR/unnecessary_to_owned.rs:71:17 + --> $DIR/unnecessary_to_owned.rs:70:17 | LL | require_str(&s.to_string()); | ^^^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `into_owned` - --> $DIR/unnecessary_to_owned.rs:72:30 + --> $DIR/unnecessary_to_owned.rs:71:30 | LL | require_str(&Cow::from(s).into_owned()); | ^^^^^^^^^^^^^ help: remove this error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:73:17 + --> $DIR/unnecessary_to_owned.rs:72:17 | LL | require_str(&s.to_owned()); | ^^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_string` - --> $DIR/unnecessary_to_owned.rs:74:17 + --> $DIR/unnecessary_to_owned.rs:73:17 | LL | require_str(&x_ref.to_string()); | ^^^^^^^^^^^^^^^^^^ help: use: `x_ref.as_ref()` error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned.rs:76:19 + --> $DIR/unnecessary_to_owned.rs:75:19 | LL | require_slice(&slice.to_vec()); | ^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `into_owned` - --> $DIR/unnecessary_to_owned.rs:77:36 + --> $DIR/unnecessary_to_owned.rs:76:36 | LL | require_slice(&Cow::from(slice).into_owned()); | ^^^^^^^^^^^^^ help: remove this error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:78:19 + --> $DIR/unnecessary_to_owned.rs:77:19 | LL | require_slice(&array.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `array.as_ref()` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:79:19 + --> $DIR/unnecessary_to_owned.rs:78:19 | LL | require_slice(&array_ref.to_owned()); | ^^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref.as_ref()` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:80:19 + --> $DIR/unnecessary_to_owned.rs:79:19 | LL | require_slice(&slice.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `into_owned` - --> $DIR/unnecessary_to_owned.rs:83:42 + --> $DIR/unnecessary_to_owned.rs:82:42 | LL | require_x(&Cow::::Owned(x.clone()).into_owned()); | ^^^^^^^^^^^^^ help: remove this error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:86:25 + --> $DIR/unnecessary_to_owned.rs:85:25 | LL | require_deref_c_str(c_str.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `c_str` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:87:26 + --> $DIR/unnecessary_to_owned.rs:86:26 | LL | require_deref_os_str(os_str.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:88:24 + --> $DIR/unnecessary_to_owned.rs:87:24 | LL | require_deref_path(path.to_owned()); | ^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:89:23 + --> $DIR/unnecessary_to_owned.rs:88:23 | LL | require_deref_str(s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:90:25 + --> $DIR/unnecessary_to_owned.rs:89:25 | LL | require_deref_slice(slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:92:30 + --> $DIR/unnecessary_to_owned.rs:91:30 | LL | require_impl_deref_c_str(c_str.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `c_str` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:93:31 + --> $DIR/unnecessary_to_owned.rs:92:31 | LL | require_impl_deref_os_str(os_str.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:94:29 + --> $DIR/unnecessary_to_owned.rs:93:29 | LL | require_impl_deref_path(path.to_owned()); | ^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:95:28 + --> $DIR/unnecessary_to_owned.rs:94:28 | LL | require_impl_deref_str(s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:96:30 + --> $DIR/unnecessary_to_owned.rs:95:30 | LL | require_impl_deref_slice(slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:98:29 + --> $DIR/unnecessary_to_owned.rs:97:29 | LL | require_deref_str_slice(s.to_owned(), slice.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:98:43 + --> $DIR/unnecessary_to_owned.rs:97:43 | LL | require_deref_str_slice(s.to_owned(), slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:99:29 + --> $DIR/unnecessary_to_owned.rs:98:29 | LL | require_deref_slice_str(slice.to_owned(), s.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:99:47 + --> $DIR/unnecessary_to_owned.rs:98:47 | LL | require_deref_slice_str(slice.to_owned(), s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:101:26 + --> $DIR/unnecessary_to_owned.rs:100:26 | LL | require_as_ref_c_str(c_str.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `c_str` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:102:27 + --> $DIR/unnecessary_to_owned.rs:101:27 | LL | require_as_ref_os_str(os_str.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:103:25 + --> $DIR/unnecessary_to_owned.rs:102:25 | LL | require_as_ref_path(path.to_owned()); | ^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:104:24 + --> $DIR/unnecessary_to_owned.rs:103:24 | LL | require_as_ref_str(s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:105:24 + --> $DIR/unnecessary_to_owned.rs:104:24 | LL | require_as_ref_str(x.to_owned()); | ^^^^^^^^^^^^ help: use: `&x` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:106:26 + --> $DIR/unnecessary_to_owned.rs:105:26 | LL | require_as_ref_slice(array.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `array` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:107:26 + --> $DIR/unnecessary_to_owned.rs:106:26 | LL | require_as_ref_slice(array_ref.to_owned()); | ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:108:26 + --> $DIR/unnecessary_to_owned.rs:107:26 | LL | require_as_ref_slice(slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:110:31 + --> $DIR/unnecessary_to_owned.rs:109:31 | LL | require_impl_as_ref_c_str(c_str.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `c_str` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:111:32 + --> $DIR/unnecessary_to_owned.rs:110:32 | LL | require_impl_as_ref_os_str(os_str.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:112:30 + --> $DIR/unnecessary_to_owned.rs:111:30 | LL | require_impl_as_ref_path(path.to_owned()); | ^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:113:29 + --> $DIR/unnecessary_to_owned.rs:112:29 | LL | require_impl_as_ref_str(s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:114:29 + --> $DIR/unnecessary_to_owned.rs:113:29 | LL | require_impl_as_ref_str(x.to_owned()); | ^^^^^^^^^^^^ help: use: `&x` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:115:31 + --> $DIR/unnecessary_to_owned.rs:114:31 | LL | require_impl_as_ref_slice(array.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `array` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:116:31 + --> $DIR/unnecessary_to_owned.rs:115:31 | LL | require_impl_as_ref_slice(array_ref.to_owned()); | ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:117:31 + --> $DIR/unnecessary_to_owned.rs:116:31 | LL | require_impl_as_ref_slice(slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:119:30 + --> $DIR/unnecessary_to_owned.rs:118:30 | LL | require_as_ref_str_slice(s.to_owned(), array.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:119:44 + --> $DIR/unnecessary_to_owned.rs:118:44 | LL | require_as_ref_str_slice(s.to_owned(), array.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `array` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:120:30 + --> $DIR/unnecessary_to_owned.rs:119:30 | LL | require_as_ref_str_slice(s.to_owned(), array_ref.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:120:44 + --> $DIR/unnecessary_to_owned.rs:119:44 | LL | require_as_ref_str_slice(s.to_owned(), array_ref.to_owned()); | ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:121:30 + --> $DIR/unnecessary_to_owned.rs:120:30 | LL | require_as_ref_str_slice(s.to_owned(), slice.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:121:44 + --> $DIR/unnecessary_to_owned.rs:120:44 | LL | require_as_ref_str_slice(s.to_owned(), slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:122:30 + --> $DIR/unnecessary_to_owned.rs:121:30 | LL | require_as_ref_slice_str(array.to_owned(), s.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `array` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:122:48 + --> $DIR/unnecessary_to_owned.rs:121:48 | LL | require_as_ref_slice_str(array.to_owned(), s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:123:30 + --> $DIR/unnecessary_to_owned.rs:122:30 | LL | require_as_ref_slice_str(array_ref.to_owned(), s.to_owned()); | ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:123:52 + --> $DIR/unnecessary_to_owned.rs:122:52 | LL | require_as_ref_slice_str(array_ref.to_owned(), s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:124:30 + --> $DIR/unnecessary_to_owned.rs:123:30 | LL | require_as_ref_slice_str(slice.to_owned(), s.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:124:48 + --> $DIR/unnecessary_to_owned.rs:123:48 | LL | require_as_ref_slice_str(slice.to_owned(), s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_string` - --> $DIR/unnecessary_to_owned.rs:126:20 + --> $DIR/unnecessary_to_owned.rs:125:20 | LL | let _ = x.join(&x_ref.to_string()); | ^^^^^^^^^^^^^^^^^^ help: use: `x_ref` error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned.rs:128:13 + --> $DIR/unnecessary_to_owned.rs:127:13 | LL | let _ = slice.to_vec().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:129:13 + --> $DIR/unnecessary_to_owned.rs:128:13 | LL | let _ = slice.to_owned().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned.rs:130:13 + --> $DIR/unnecessary_to_owned.rs:129:13 | LL | let _ = [std::path::PathBuf::new()][..].to_vec().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:131:13 + --> $DIR/unnecessary_to_owned.rs:130:13 | LL | let _ = [std::path::PathBuf::new()][..].to_owned().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()` error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned.rs:133:13 + --> $DIR/unnecessary_to_owned.rs:132:13 | LL | let _ = IntoIterator::into_iter(slice.to_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:134:13 + --> $DIR/unnecessary_to_owned.rs:133:13 | LL | let _ = IntoIterator::into_iter(slice.to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned.rs:135:13 + --> $DIR/unnecessary_to_owned.rs:134:13 | LL | let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:136:13 + --> $DIR/unnecessary_to_owned.rs:135:13 | LL | let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()` error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned.rs:198:14 + --> $DIR/unnecessary_to_owned.rs:197:14 | LL | for t in file_types.to_vec() { | ^^^^^^^^^^^^^^^^^^^ @@ -492,25 +492,25 @@ LL + let path = match get_file_path(t) { | error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned.rs:221:14 + --> $DIR/unnecessary_to_owned.rs:220:14 | LL | let _ = &["x"][..].to_vec().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `["x"][..].iter().cloned()` error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned.rs:226:14 + --> $DIR/unnecessary_to_owned.rs:225:14 | LL | let _ = &["x"][..].to_vec().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `["x"][..].iter().copied()` error: unnecessary use of `to_string` - --> $DIR/unnecessary_to_owned.rs:273:24 + --> $DIR/unnecessary_to_owned.rs:272:24 | LL | Box::new(build(y.to_string())) | ^^^^^^^^^^^^^ help: use: `y` error: unnecessary use of `to_string` - --> $DIR/unnecessary_to_owned.rs:381:12 + --> $DIR/unnecessary_to_owned.rs:380:12 | LL | id("abc".to_string()) | ^^^^^^^^^^^^^^^^^ help: use: `"abc"` diff --git a/tests/ui/unnested_or_patterns.fixed b/tests/ui/unnested_or_patterns.fixed index 9786c7b1212..0a8e7b34dfa 100644 --- a/tests/ui/unnested_or_patterns.fixed +++ b/tests/ui/unnested_or_patterns.fixed @@ -1,6 +1,6 @@ // run-rustfix -#![feature(box_patterns, custom_inner_attributes)] +#![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] #![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::upper_case_acronyms)] #![allow(unreachable_patterns, irrefutable_let_patterns, unused)] @@ -34,14 +34,12 @@ fn main() { if let S { x: 0, y, .. } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} } +#[clippy::msrv = "1.52"] fn msrv_1_52() { - #![clippy::msrv = "1.52"] - if let [1] | [52] = [0] {} } +#[clippy::msrv = "1.53"] fn msrv_1_53() { - #![clippy::msrv = "1.53"] - if let [1 | 53] = [0] {} } diff --git a/tests/ui/unnested_or_patterns.rs b/tests/ui/unnested_or_patterns.rs index f57322396d4..2c454adfe89 100644 --- a/tests/ui/unnested_or_patterns.rs +++ b/tests/ui/unnested_or_patterns.rs @@ -1,6 +1,6 @@ // run-rustfix -#![feature(box_patterns, custom_inner_attributes)] +#![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] #![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::upper_case_acronyms)] #![allow(unreachable_patterns, irrefutable_let_patterns, unused)] @@ -34,14 +34,12 @@ fn main() { if let S { x: 0, y, .. } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} } +#[clippy::msrv = "1.52"] fn msrv_1_52() { - #![clippy::msrv = "1.52"] - if let [1] | [52] = [0] {} } +#[clippy::msrv = "1.53"] fn msrv_1_53() { - #![clippy::msrv = "1.53"] - if let [1] | [53] = [0] {} } diff --git a/tests/ui/unnested_or_patterns.stderr b/tests/ui/unnested_or_patterns.stderr index fbc12fff0b0..a1f193db555 100644 --- a/tests/ui/unnested_or_patterns.stderr +++ b/tests/ui/unnested_or_patterns.stderr @@ -176,7 +176,7 @@ LL | if let S { x: 0 | 1, y } = (S { x: 0, y: 1 }) {} | ~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:46:12 + --> $DIR/unnested_or_patterns.rs:44:12 | LL | if let [1] | [53] = [0] {} | ^^^^^^^^^^ diff --git a/tests/ui/use_self.fixed b/tests/ui/use_self.fixed index 3b54fe9d5ff..0a6166571eb 100644 --- a/tests/ui/use_self.fixed +++ b/tests/ui/use_self.fixed @@ -1,7 +1,6 @@ // run-rustfix // aux-build:proc_macro_derive.rs -#![feature(custom_inner_attributes)] #![warn(clippy::use_self)] #![allow(dead_code, unreachable_code)] #![allow( @@ -619,9 +618,8 @@ mod issue6902 { } } +#[clippy::msrv = "1.36"] fn msrv_1_36() { - #![clippy::msrv = "1.36"] - enum E { A, } @@ -635,9 +633,8 @@ fn msrv_1_36() { } } +#[clippy::msrv = "1.37"] fn msrv_1_37() { - #![clippy::msrv = "1.37"] - enum E { A, } diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index bf87633cd2d..39c2b431f7f 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -1,7 +1,6 @@ // run-rustfix // aux-build:proc_macro_derive.rs -#![feature(custom_inner_attributes)] #![warn(clippy::use_self)] #![allow(dead_code, unreachable_code)] #![allow( @@ -619,9 +618,8 @@ mod issue6902 { } } +#[clippy::msrv = "1.36"] fn msrv_1_36() { - #![clippy::msrv = "1.36"] - enum E { A, } @@ -635,9 +633,8 @@ fn msrv_1_36() { } } +#[clippy::msrv = "1.37"] fn msrv_1_37() { - #![clippy::msrv = "1.37"] - enum E { A, } diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index 16fb0609242..48364c40c3b 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -1,5 +1,5 @@ error: unnecessary structure name repetition - --> $DIR/use_self.rs:23:21 + --> $DIR/use_self.rs:22:21 | LL | fn new() -> Foo { | ^^^ help: use the applicable keyword: `Self` @@ -7,247 +7,247 @@ LL | fn new() -> Foo { = note: `-D clippy::use-self` implied by `-D warnings` error: unnecessary structure name repetition - --> $DIR/use_self.rs:24:13 + --> $DIR/use_self.rs:23:13 | LL | Foo {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:26:22 + --> $DIR/use_self.rs:25:22 | LL | fn test() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:27:13 + --> $DIR/use_self.rs:26:13 | LL | Foo::new() | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:32:25 + --> $DIR/use_self.rs:31:25 | LL | fn default() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:33:13 + --> $DIR/use_self.rs:32:13 | LL | Foo::new() | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:98:24 + --> $DIR/use_self.rs:97:24 | LL | fn bad(foos: &[Foo]) -> impl Iterator { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:98:55 + --> $DIR/use_self.rs:97:55 | LL | fn bad(foos: &[Foo]) -> impl Iterator { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:113:13 + --> $DIR/use_self.rs:112:13 | LL | TS(0) | ^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:148:29 + --> $DIR/use_self.rs:147:29 | LL | fn bar() -> Bar { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:149:21 + --> $DIR/use_self.rs:148:21 | LL | Bar { foo: Foo {} } | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:160:21 + --> $DIR/use_self.rs:159:21 | LL | fn baz() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:161:13 + --> $DIR/use_self.rs:160:13 | LL | Foo {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:178:21 + --> $DIR/use_self.rs:177:21 | LL | let _ = Enum::B(42); | ^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:179:21 + --> $DIR/use_self.rs:178:21 | LL | let _ = Enum::C { field: true }; | ^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:180:21 + --> $DIR/use_self.rs:179:21 | LL | let _ = Enum::A; | ^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:222:13 + --> $DIR/use_self.rs:221:13 | LL | nested::A::fun_1(); | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:223:13 + --> $DIR/use_self.rs:222:13 | LL | nested::A::A; | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:225:13 + --> $DIR/use_self.rs:224:13 | LL | nested::A {}; | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:244:13 + --> $DIR/use_self.rs:243:13 | LL | TestStruct::from_something() | ^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:258:25 + --> $DIR/use_self.rs:257:25 | LL | async fn g() -> S { | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:259:13 + --> $DIR/use_self.rs:258:13 | LL | S {} | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:263:16 + --> $DIR/use_self.rs:262:16 | LL | &p[S::A..S::B] | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:263:22 + --> $DIR/use_self.rs:262:22 | LL | &p[S::A..S::B] | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:286:29 + --> $DIR/use_self.rs:285:29 | LL | fn foo(value: T) -> Foo { | ^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:287:13 + --> $DIR/use_self.rs:286:13 | LL | Foo:: { value } | ^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:459:13 + --> $DIR/use_self.rs:458:13 | LL | A::new::(submod::B {}) | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:496:13 + --> $DIR/use_self.rs:495:13 | LL | S2::new() | ^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:533:17 + --> $DIR/use_self.rs:532:17 | LL | Foo::Bar => unimplemented!(), | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:534:17 + --> $DIR/use_self.rs:533:17 | LL | Foo::Baz => unimplemented!(), | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:540:20 + --> $DIR/use_self.rs:539:20 | LL | if let Foo::Bar = self { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:564:17 + --> $DIR/use_self.rs:563:17 | LL | Something::Num(n) => *n, | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:565:17 + --> $DIR/use_self.rs:564:17 | LL | Something::TupleNums(n, _m) => *n, | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:566:17 + --> $DIR/use_self.rs:565:17 | LL | Something::StructNums { one, two: _ } => *one, | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:572:17 + --> $DIR/use_self.rs:571:17 | LL | crate::issue8845::Something::Num(n) => *n, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:573:17 + --> $DIR/use_self.rs:572:17 | LL | crate::issue8845::Something::TupleNums(n, _m) => *n, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:574:17 + --> $DIR/use_self.rs:573:17 | LL | crate::issue8845::Something::StructNums { one, two: _ } => *one, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:590:17 + --> $DIR/use_self.rs:589:17 | LL | let Foo(x) = self; | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:595:17 + --> $DIR/use_self.rs:594:17 | LL | let crate::issue8845::Foo(x) = self; | ^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:602:17 + --> $DIR/use_self.rs:601:17 | LL | let Bar { x, .. } = self; | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:607:17 + --> $DIR/use_self.rs:606:17 | LL | let crate::issue8845::Bar { x, .. } = self; | ^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:648:17 + --> $DIR/use_self.rs:645:17 | LL | E::A => {}, | ^ help: use the applicable keyword: `Self` -- cgit 1.4.1-3-g733a5 From 93f602f1cf324e89ec1312583cb033eeb977fa73 Mon Sep 17 00:00:00 2001 From: Maria José Solano Date: Fri, 13 Jan 2023 15:21:49 -0800 Subject: Add missing arguments to cargo lint example --- book/src/development/adding_lints.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'book/src/development/adding_lints.md') diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md index 8b4eee8c9d9..145b393b753 100644 --- a/book/src/development/adding_lints.md +++ b/book/src/development/adding_lints.md @@ -146,7 +146,7 @@ For cargo lints, the process of testing differs in that we are interested in the manifest. If our new lint is named e.g. `foo_categories`, after running `cargo dev -new_lint` we will find by default two new crates, each with its manifest file: +new_lint --name=foo_categories --type=cargo --category=cargo` we will find by default two new crates, each with its manifest file: * `tests/ui-cargo/foo_categories/fail/Cargo.toml`: this file should cause the new lint to raise an error. -- cgit 1.4.1-3-g733a5 From a7db92574cf191444f5bbfdfcb89af5655e280c4 Mon Sep 17 00:00:00 2001 From: Maria José Solano Date: Fri, 13 Jan 2023 18:57:04 -0800 Subject: Split long line --- book/src/development/adding_lints.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'book/src/development/adding_lints.md') diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md index 145b393b753..c6be394bd7d 100644 --- a/book/src/development/adding_lints.md +++ b/book/src/development/adding_lints.md @@ -146,7 +146,8 @@ For cargo lints, the process of testing differs in that we are interested in the manifest. If our new lint is named e.g. `foo_categories`, after running `cargo dev -new_lint --name=foo_categories --type=cargo --category=cargo` we will find by default two new crates, each with its manifest file: +new_lint --name=foo_categories --type=cargo --category=cargo` we will find by +default two new crates, each with its manifest file: * `tests/ui-cargo/foo_categories/fail/Cargo.toml`: this file should cause the new lint to raise an error. -- cgit 1.4.1-3-g733a5 From d950279a039b5a598c87b347ba5d2f151a071a98 Mon Sep 17 00:00:00 2001 From: Tyler Weaver Date: Sat, 14 Jan 2023 07:39:49 -0700 Subject: Document generating lint config docs for adding configuration --- book/src/development/adding_lints.md | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'book/src/development/adding_lints.md') diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md index 8b4eee8c9d9..fd6e1f5aef2 100644 --- a/book/src/development/adding_lints.md +++ b/book/src/development/adding_lints.md @@ -699,6 +699,10 @@ for some users. Adding a configuration is done in the following steps: `clippy.toml` file with the configuration value and a rust file that should be linted by Clippy. The test can otherwise be written as usual. +5. Update [Lint Configuration](../lint_configuration.md) + + Run `cargo collect-metadata` to generate documentation changes for the book. + [`clippy_lints::utils::conf`]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/utils/conf.rs [`clippy_lints` lib file]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/lib.rs [`tests/ui`]: https://github.com/rust-lang/rust-clippy/blob/master/tests/ui -- cgit 1.4.1-3-g733a5